rk312x: vpu select vdpu clk by default
[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 #define BIT_VCODEC_CLK_SEL      (1<<10)\r
729         if (cpu_is_rk312x())\r
730                 writel_relaxed(readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_CON1) |\r
731                         BIT_VCODEC_CLK_SEL | (BIT_VCODEC_CLK_SEL << 16),\r
732                         RK_GRF_VIRT + RK312X_GRF_SOC_CON1);\r
733 \r
734 \r
735         udelay(10);\r
736         wake_lock(&pservice->wake_lock);\r
737 \r
738 #if defined(CONFIG_VCODEC_MMU)\r
739         if (pservice->mmu_dev)\r
740                 rockchip_iovmm_activate(pservice->dev);\r
741 #endif    \r
742 }\r
743 \r
744 static inline bool reg_check_rmvb_wmv(vpu_reg *reg)\r
745 {\r
746         unsigned long type = (reg->reg[3] & 0xF0000000) >> 28;\r
747         return ((type == 8) || (type == 4));\r
748 }\r
749 \r
750 static inline bool reg_check_interlace(vpu_reg *reg)\r
751 {\r
752         unsigned long type = (reg->reg[3] & (1 << 23));\r
753         return (type > 0);\r
754 }\r
755 \r
756 static inline enum VPU_DEC_FMT reg_check_fmt(vpu_reg *reg)\r
757 {\r
758         enum VPU_DEC_FMT type = (enum VPU_DEC_FMT)((reg->reg[3] & 0xF0000000) >> 28);\r
759         return type;\r
760 }\r
761 \r
762 static inline int reg_probe_width(vpu_reg *reg)\r
763 {\r
764         int width_in_mb = reg->reg[4] >> 23;\r
765         return width_in_mb * 16;\r
766 }\r
767 \r
768 #if defined(CONFIG_VCODEC_MMU)\r
769 static int vcodec_bufid_to_iova(struct vpu_service_info *pservice, u8 *tbl,\r
770                                 int size, vpu_reg *reg,\r
771                                 struct extra_info_for_iommu *ext_inf)\r
772 {\r
773         int i;\r
774         int usr_fd = 0;\r
775         int offset = 0;\r
776 \r
777         if (tbl == NULL || size <= 0) {\r
778                 dev_err(pservice->dev, "input arguments invalidate\n");\r
779                 return -1;\r
780         }\r
781 \r
782         vpu_service_power_on(pservice);\r
783 \r
784         for (i = 0; i < size; i++) {\r
785                 usr_fd = reg->reg[tbl[i]] & 0x3FF;\r
786 \r
787                 if (tbl[i] == 41 && pservice->hw_info->hw_id != HEVC_ID &&\r
788                     (reg->type == VPU_DEC || reg->type == VPU_DEC_PP))\r
789                         /* special for vpu dec num 41 regitster */\r
790                         offset = reg->reg[tbl[i]] >> 10 << 4;\r
791                 else\r
792                         offset = reg->reg[tbl[i]] >> 10;\r
793 \r
794                 if (usr_fd != 0) {\r
795                         struct ion_handle *hdl;\r
796                         int ret;\r
797                         struct vcodec_mem_region *mem_region;\r
798 \r
799                         hdl = ion_import_dma_buf(pservice->ion_client, usr_fd);\r
800                         if (IS_ERR(hdl)) {\r
801                                 dev_err(pservice->dev, "import dma-buf from fd %d failed, reg[%d]\n", usr_fd, tbl[i]);\r
802                                 return PTR_ERR(hdl);\r
803                         }\r
804 \r
805                         mem_region = kzalloc(sizeof(struct vcodec_mem_region), GFP_KERNEL);\r
806 \r
807                         if (mem_region == NULL) {\r
808                                 dev_err(pservice->dev, "allocate memory for iommu memory region failed\n");\r
809                                 ion_free(pservice->ion_client, hdl);\r
810                                 return -1;\r
811                         }\r
812 \r
813                         mem_region->hdl = hdl;\r
814 \r
815                         vcodec_enter_mode(pservice->dev_id);\r
816                         ret = ion_map_iommu(pservice->dev, pservice->ion_client, mem_region->hdl, &mem_region->iova, &mem_region->len);\r
817                         vcodec_exit_mode();\r
818                         if (ret < 0) {\r
819                                 dev_err(pservice->dev, "ion map iommu failed\n");\r
820                                 kfree(mem_region);\r
821                                 ion_free(pservice->ion_client, hdl);\r
822                                 return ret;\r
823                         }\r
824                         reg->reg[tbl[i]] = mem_region->iova + offset;\r
825                         INIT_LIST_HEAD(&mem_region->reg_lnk);\r
826                         list_add_tail(&mem_region->reg_lnk, &reg->mem_region_list);\r
827                 }\r
828         }\r
829 \r
830         if (ext_inf != NULL && ext_inf->magic == EXTRA_INFO_MAGIC) {\r
831                 for (i=0; i<ext_inf->cnt; i++) {\r
832                         pr_info("reg[%d] + offset %d\n", ext_inf->elem[i].index, ext_inf->elem[i].offset);\r
833                         reg->reg[ext_inf->elem[i].index] += ext_inf->elem[i].offset;\r
834                 }\r
835         }\r
836 \r
837         return 0;\r
838 }\r
839 \r
840 static int vcodec_reg_address_translate(struct vpu_service_info *pservice,\r
841                                         vpu_reg *reg,\r
842                                         struct extra_info_for_iommu *ext_inf)\r
843 {\r
844         VPU_HW_ID hw_id;\r
845         u8 *tbl;\r
846         int size = 0;\r
847 \r
848         hw_id = pservice->hw_info->hw_id;\r
849 \r
850         if (hw_id == HEVC_ID) {\r
851                 tbl = addr_tbl_hevc_dec;\r
852                 size = sizeof(addr_tbl_hevc_dec);\r
853         } else {\r
854                 if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
855                         switch (reg_check_fmt(reg)) {\r
856                         case VPU_DEC_FMT_H264:\r
857                                 {\r
858                                         tbl = addr_tbl_vpu_h264dec;\r
859                                         size = sizeof(addr_tbl_vpu_h264dec);\r
860                                         break;\r
861                                 }\r
862                         case VPU_DEC_FMT_VP8:\r
863                         case VPU_DEC_FMT_VP7:\r
864                                 {\r
865                                         tbl = addr_tbl_vpu_vp8dec;\r
866                                         size = sizeof(addr_tbl_vpu_vp8dec);\r
867                                         break;\r
868                                 }\r
869 \r
870                         case VPU_DEC_FMT_VP6:\r
871                                 {\r
872                                         tbl = addr_tbl_vpu_vp6dec;\r
873                                         size = sizeof(addr_tbl_vpu_vp6dec);\r
874                                         break;\r
875                                 }\r
876                         case VPU_DEC_FMT_VC1:\r
877                                 {\r
878                                         tbl = addr_tbl_vpu_vc1dec;\r
879                                         size = sizeof(addr_tbl_vpu_vc1dec);\r
880                                         break;\r
881                                 }\r
882 \r
883                         case VPU_DEC_FMT_JPEG:\r
884                                 {\r
885                                         tbl = addr_tbl_vpu_jpegdec;\r
886                                         size = sizeof(addr_tbl_vpu_jpegdec);\r
887                                         break;\r
888                                 }\r
889                         default:\r
890                                 tbl = addr_tbl_vpu_defaultdec;\r
891                                 size = sizeof(addr_tbl_vpu_defaultdec);\r
892                                 break;\r
893                         }\r
894                 } else if (reg->type == VPU_ENC) {\r
895                         tbl = addr_tbl_vpu_enc;\r
896                         size = sizeof(addr_tbl_vpu_enc);\r
897                 }\r
898         }\r
899 \r
900         if (size != 0) {\r
901                 return vcodec_bufid_to_iova(pservice, tbl, size, reg, ext_inf);\r
902         } else {\r
903                 return -1;\r
904         }\r
905 }\r
906 #endif\r
907 \r
908 static vpu_reg *reg_init(struct vpu_service_info *pservice, vpu_session *session, void __user *src, unsigned long size)\r
909 {\r
910         int extra_size = 0;\r
911         struct extra_info_for_iommu extra_info;\r
912         vpu_reg *reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
913         if (NULL == reg) {\r
914                 pr_err("error: kmalloc fail in reg_init\n");\r
915                 return NULL;\r
916         }\r
917 \r
918         if (size > pservice->reg_size) {\r
919                 /*printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
920                 size = pservice->reg_size;*/\r
921                 extra_size = size - pservice->reg_size;\r
922                 size = pservice->reg_size;\r
923         }\r
924         reg->session = session;\r
925         reg->type = session->type;\r
926         reg->size = size;\r
927         reg->freq = VPU_FREQ_DEFAULT;\r
928         reg->reg = (unsigned long *)&reg[1];\r
929         INIT_LIST_HEAD(&reg->session_link);\r
930         INIT_LIST_HEAD(&reg->status_link);\r
931 \r
932 #if defined(CONFIG_VCODEC_MMU)\r
933         if (pservice->mmu_dev)\r
934                 INIT_LIST_HEAD(&reg->mem_region_list);\r
935 #endif\r
936 \r
937         if (copy_from_user(&reg->reg[0], (void __user *)src, 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 (copy_from_user(&extra_info, (u8 *)src + size, extra_size)) {\r
944                 pr_err("error: copy_from_user failed in reg_init\n");\r
945                 kfree(reg);\r
946                 return NULL;\r
947         }\r
948 \r
949 #if defined(CONFIG_VCODEC_MMU)\r
950         if (pservice->mmu_dev && 0 > vcodec_reg_address_translate(pservice, reg, &extra_info)) {\r
951                 pr_err("error: translate reg address failed\n");\r
952                 kfree(reg);\r
953                 return NULL;\r
954         }\r
955 #endif\r
956 \r
957         mutex_lock(&pservice->lock);\r
958         list_add_tail(&reg->status_link, &pservice->waiting);\r
959         list_add_tail(&reg->session_link, &session->waiting);\r
960         mutex_unlock(&pservice->lock);\r
961 \r
962         if (pservice->auto_freq) {\r
963                 if (!soc_is_rk2928g()) {\r
964                         if (reg->type == VPU_DEC || reg->type == VPU_DEC_PP) {\r
965                                 if (reg_check_rmvb_wmv(reg)) {\r
966                                         reg->freq = VPU_FREQ_200M;\r
967                                 } else if (reg_check_fmt(reg) == VPU_DEC_FMT_H264) {\r
968                                         if (reg_probe_width(reg) > 3200) {\r
969                                                 // raise frequency for 4k avc.\r
970                                                 reg->freq = VPU_FREQ_500M;\r
971                                         }\r
972                                 } else {\r
973                                         if (reg_check_interlace(reg)) {\r
974                                                 reg->freq = VPU_FREQ_400M;\r
975                                         }\r
976                                 }\r
977                         }\r
978                         if (reg->type == VPU_PP) {\r
979                                 reg->freq = VPU_FREQ_400M;\r
980                         }\r
981                 }\r
982         }\r
983 \r
984         return reg;\r
985 }\r
986 \r
987 static void reg_deinit(struct vpu_service_info *pservice, vpu_reg *reg)\r
988 {\r
989 #if defined(CONFIG_VCODEC_MMU)\r
990         struct vcodec_mem_region *mem_region = NULL, *n;\r
991 #endif\r
992 \r
993         list_del_init(&reg->session_link);\r
994         list_del_init(&reg->status_link);\r
995         if (reg == pservice->reg_codec)\r
996                 pservice->reg_codec = NULL;\r
997         if (reg == pservice->reg_pproc)\r
998                 pservice->reg_pproc = NULL;\r
999 \r
1000 #if defined(CONFIG_VCODEC_MMU)\r
1001         // release memory region attach to this registers table.\r
1002         if (pservice->mmu_dev) {\r
1003                 list_for_each_entry_safe(mem_region, n, &reg->mem_region_list, reg_lnk) {\r
1004                         /* do not unmap iommu manually,\r
1005                            unmap will proccess when memory release */\r
1006                         /*vcodec_enter_mode(pservice->dev_id);\r
1007                         ion_unmap_iommu(pservice->dev,\r
1008                                         pservice->ion_client,\r
1009                                         mem_region->hdl);\r
1010                         vcodec_exit_mode();*/\r
1011                         ion_free(pservice->ion_client, mem_region->hdl);\r
1012                         list_del_init(&mem_region->reg_lnk);\r
1013                         kfree(mem_region);\r
1014                 }\r
1015         }\r
1016 #endif\r
1017 \r
1018         kfree(reg);\r
1019 }\r
1020 \r
1021 static void reg_from_wait_to_run(struct vpu_service_info *pservice, vpu_reg *reg)\r
1022 {\r
1023         list_del_init(&reg->status_link);\r
1024         list_add_tail(&reg->status_link, &pservice->running);\r
1025 \r
1026         list_del_init(&reg->session_link);\r
1027         list_add_tail(&reg->session_link, &reg->session->running);\r
1028 }\r
1029 \r
1030 static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)\r
1031 {\r
1032         int i;\r
1033         u32 *dst = (u32 *)&reg->reg[0];\r
1034 \r
1035         for (i = 0; i < count; i++)\r
1036                 *dst++ = *src++;\r
1037 }\r
1038 \r
1039 static void reg_from_run_to_done(struct vpu_service_info *pservice, vpu_reg *reg)\r
1040 {\r
1041         int irq_reg = -1;\r
1042         list_del_init(&reg->status_link);\r
1043         list_add_tail(&reg->status_link, &pservice->done);\r
1044 \r
1045         list_del_init(&reg->session_link);\r
1046         list_add_tail(&reg->session_link, &reg->session->done);\r
1047 \r
1048         vcodec_enter_mode(pservice->dev_id);\r
1049         switch (reg->type) {\r
1050         case VPU_ENC : {\r
1051                 pservice->reg_codec = NULL;\r
1052                 reg_copy_from_hw(reg, pservice->enc_dev.hwregs, pservice->hw_info->enc_reg_num);\r
1053                 irq_reg = ENC_INTERRUPT_REGISTER;\r
1054                 break;\r
1055         }\r
1056         case VPU_DEC : {\r
1057                 int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
1058                 pservice->reg_codec = NULL;\r
1059                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs, reg_len);\r
1060                 irq_reg = DEC_INTERRUPT_REGISTER;\r
1061                 break;\r
1062         }\r
1063         case VPU_PP : {\r
1064                 pservice->reg_pproc = NULL;\r
1065                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);\r
1066                 pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
1067                 break;\r
1068         }\r
1069         case VPU_DEC_PP : {\r
1070                 pservice->reg_codec = NULL;\r
1071                 pservice->reg_pproc = NULL;\r
1072                 reg_copy_from_hw(reg, pservice->dec_dev.hwregs, REG_NUM_9190_DEC_PP);\r
1073                 pservice->dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;\r
1074                 break;\r
1075         }\r
1076         default : {\r
1077                 pr_err("error: copy reg from hw with unknown type %d\n", reg->type);\r
1078                 break;\r
1079         }\r
1080         }\r
1081         vcodec_exit_mode();\r
1082 \r
1083         if (irq_reg != -1) {\r
1084                 reg->reg[irq_reg] = pservice->irq_status;\r
1085         }\r
1086 \r
1087         atomic_sub(1, &reg->session->task_running);\r
1088         atomic_sub(1, &pservice->total_running);\r
1089         wake_up(&reg->session->wait);\r
1090 }\r
1091 \r
1092 static void vpu_service_set_freq(struct vpu_service_info *pservice, vpu_reg *reg)\r
1093 {\r
1094         VPU_FREQ curr = atomic_read(&pservice->freq_status);\r
1095         if (curr == reg->freq) {\r
1096                 return ;\r
1097         }\r
1098         atomic_set(&pservice->freq_status, reg->freq);\r
1099         switch (reg->freq) {\r
1100         case VPU_FREQ_200M : {\r
1101                 clk_set_rate(pservice->aclk_vcodec, 200*MHZ);\r
1102                 //printk("default: 200M\n");\r
1103         } break;\r
1104         case VPU_FREQ_266M : {\r
1105                 clk_set_rate(pservice->aclk_vcodec, 266*MHZ);\r
1106                 //printk("default: 266M\n");\r
1107         } break;\r
1108         case VPU_FREQ_300M : {\r
1109                 clk_set_rate(pservice->aclk_vcodec, 300*MHZ);\r
1110                 //printk("default: 300M\n");\r
1111         } break;\r
1112         case VPU_FREQ_400M : {\r
1113                 clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
1114                 //printk("default: 400M\n");\r
1115         } break;\r
1116         case VPU_FREQ_500M : {\r
1117                 clk_set_rate(pservice->aclk_vcodec, 500*MHZ);\r
1118         } break;\r
1119         case VPU_FREQ_600M : {\r
1120                 clk_set_rate(pservice->aclk_vcodec, 600*MHZ);\r
1121         } break;\r
1122         default : {\r
1123                 if (soc_is_rk2928g()) {\r
1124                         clk_set_rate(pservice->aclk_vcodec, 400*MHZ);\r
1125                 } else {\r
1126                         clk_set_rate(pservice->aclk_vcodec, 300*MHZ);\r
1127                 }\r
1128                 //printk("default: 300M\n");\r
1129         } break;\r
1130         }\r
1131 }\r
1132 \r
1133 #if HEVC_SIM_ENABLE\r
1134 static void simulate_start(struct vpu_service_info *pservice);\r
1135 #endif\r
1136 static void reg_copy_to_hw(struct vpu_service_info *pservice, vpu_reg *reg)\r
1137 {\r
1138         int i;\r
1139         u32 *src = (u32 *)&reg->reg[0];\r
1140         atomic_add(1, &pservice->total_running);\r
1141         atomic_add(1, &reg->session->task_running);\r
1142         if (pservice->auto_freq) {\r
1143                 vpu_service_set_freq(pservice, reg);\r
1144         }\r
1145 \r
1146         vcodec_enter_mode(pservice->dev_id);\r
1147 \r
1148         switch (reg->type) {\r
1149         case VPU_ENC : {\r
1150                 int enc_count = pservice->hw_info->enc_reg_num;\r
1151                 u32 *dst = (u32 *)pservice->enc_dev.hwregs;\r
1152 \r
1153                 pservice->reg_codec = reg;\r
1154 \r
1155                 dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC] & 0x6;\r
1156 \r
1157                 for (i = 0; i < VPU_REG_EN_ENC; i++)\r
1158                         dst[i] = src[i];\r
1159 \r
1160                 for (i = VPU_REG_EN_ENC + 1; i < enc_count; i++)\r
1161                         dst[i] = src[i];\r
1162 \r
1163                 dsb();\r
1164 \r
1165                 dst[VPU_REG_ENC_GATE] = src[VPU_REG_ENC_GATE] | VPU_REG_ENC_GATE_BIT;\r
1166                 dst[VPU_REG_EN_ENC]   = src[VPU_REG_EN_ENC];\r
1167 \r
1168 #if VPU_SERVICE_SHOW_TIME\r
1169                 do_gettimeofday(&enc_start);\r
1170 #endif\r
1171 \r
1172         } break;\r
1173         case VPU_DEC : {\r
1174                 u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
1175 \r
1176                 pservice->reg_codec = reg;\r
1177 \r
1178                 if (pservice->hw_info->hw_id != HEVC_ID) {\r
1179                         for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)\r
1180                                 dst[i] = src[i];\r
1181                 } else {\r
1182                         for (i = REG_NUM_HEVC_DEC - 1; i > VPU_REG_EN_DEC; i--) {\r
1183                                 dst[i] = src[i];\r
1184                         }\r
1185                 }\r
1186 \r
1187                 dsb();\r
1188 \r
1189                 if (pservice->hw_info->hw_id != HEVC_ID) {\r
1190                         dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;\r
1191                         dst[VPU_REG_EN_DEC]   = src[VPU_REG_EN_DEC];\r
1192                 } else {\r
1193                         dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];\r
1194                 }\r
1195 \r
1196                 dsb();\r
1197                 dmb();\r
1198 \r
1199 #if VPU_SERVICE_SHOW_TIME\r
1200                 do_gettimeofday(&dec_start);\r
1201 #endif\r
1202 \r
1203         } break;\r
1204         case VPU_PP : {\r
1205                 u32 *dst = (u32 *)pservice->dec_dev.hwregs + PP_INTERRUPT_REGISTER;\r
1206                 pservice->reg_pproc = reg;\r
1207 \r
1208                 dst[VPU_REG_PP_GATE] = src[VPU_REG_PP_GATE] | VPU_REG_PP_GATE_BIT;\r
1209 \r
1210                 for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_9190_PP; i++)\r
1211                         dst[i] = src[i];\r
1212 \r
1213                 dsb();\r
1214 \r
1215                 dst[VPU_REG_EN_PP] = src[VPU_REG_EN_PP];\r
1216 \r
1217 #if VPU_SERVICE_SHOW_TIME\r
1218                 do_gettimeofday(&pp_start);\r
1219 #endif\r
1220 \r
1221         } break;\r
1222         case VPU_DEC_PP : {\r
1223                 u32 *dst = (u32 *)pservice->dec_dev.hwregs;\r
1224                 pservice->reg_codec = reg;\r
1225                 pservice->reg_pproc = reg;\r
1226 \r
1227                 for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_9190_DEC_PP; i++)\r
1228                         dst[i] = src[i];\r
1229 \r
1230                 dst[VPU_REG_EN_DEC_PP]   = src[VPU_REG_EN_DEC_PP] | 0x2;\r
1231                 dsb();\r
1232 \r
1233                 dst[VPU_REG_DEC_PP_GATE] = src[VPU_REG_DEC_PP_GATE] | VPU_REG_PP_GATE_BIT;\r
1234                 dst[VPU_REG_DEC_GATE]    = src[VPU_REG_DEC_GATE]    | VPU_REG_DEC_GATE_BIT;\r
1235                 dst[VPU_REG_EN_DEC]      = src[VPU_REG_EN_DEC];\r
1236 \r
1237 #if VPU_SERVICE_SHOW_TIME\r
1238                 do_gettimeofday(&dec_start);\r
1239 #endif\r
1240 \r
1241         } break;\r
1242         default : {\r
1243                 pr_err("error: unsupport session type %d", reg->type);\r
1244                 atomic_sub(1, &pservice->total_running);\r
1245                 atomic_sub(1, &reg->session->task_running);\r
1246                 break;\r
1247         }\r
1248         }\r
1249 \r
1250         vcodec_exit_mode();\r
1251 \r
1252 #if HEVC_SIM_ENABLE\r
1253         if (pservice->hw_info->hw_id == HEVC_ID) {\r
1254                 simulate_start(pservice);\r
1255         }\r
1256 #endif\r
1257 }\r
1258 \r
1259 static void try_set_reg(struct vpu_service_info *pservice)\r
1260 {\r
1261         // first get reg from reg list\r
1262         if (!list_empty(&pservice->waiting)) {\r
1263                 int can_set = 0;\r
1264                 vpu_reg *reg = list_entry(pservice->waiting.next, vpu_reg, status_link);\r
1265 \r
1266                 vpu_service_power_on(pservice);\r
1267 \r
1268                 switch (reg->type) {\r
1269                 case VPU_ENC : {\r
1270                         if ((NULL == pservice->reg_codec) &&  (NULL == pservice->reg_pproc))\r
1271                                 can_set = 1;\r
1272                 } break;\r
1273                 case VPU_DEC : {\r
1274                         if (NULL == pservice->reg_codec)\r
1275                                 can_set = 1;\r
1276                         if (pservice->auto_freq && (NULL != pservice->reg_pproc)) {\r
1277                                 can_set = 0;\r
1278                         }\r
1279                 } break;\r
1280                 case VPU_PP : {\r
1281                         if (NULL == pservice->reg_codec) {\r
1282                                 if (NULL == pservice->reg_pproc)\r
1283                                         can_set = 1;\r
1284                         } else {\r
1285                                 if ((VPU_DEC == pservice->reg_codec->type) && (NULL == pservice->reg_pproc))\r
1286                                         can_set = 1;\r
1287                                 // can not charge frequency when vpu is working\r
1288                                 if (pservice->auto_freq) {\r
1289                                         can_set = 0;\r
1290                                 }\r
1291                         }\r
1292                 } break;\r
1293                 case VPU_DEC_PP : {\r
1294                         if ((NULL == pservice->reg_codec) && (NULL == pservice->reg_pproc))\r
1295                                 can_set = 1;\r
1296                         } break;\r
1297                 default : {\r
1298                         printk("undefined reg type %d\n", reg->type);\r
1299                 } break;\r
1300                 }\r
1301                 if (can_set) {\r
1302                         reg_from_wait_to_run(pservice, reg);\r
1303                         reg_copy_to_hw(pservice, reg);\r
1304                 }\r
1305         }\r
1306 }\r
1307 \r
1308 static int return_reg(struct vpu_service_info *pservice, vpu_reg *reg, u32 __user *dst)\r
1309 {\r
1310         int ret = 0;\r
1311         switch (reg->type) {\r
1312         case VPU_ENC : {\r
1313                 if (copy_to_user(dst, &reg->reg[0], pservice->hw_info->enc_io_size))\r
1314                         ret = -EFAULT;\r
1315                 break;\r
1316         }\r
1317         case VPU_DEC : {\r
1318                 int reg_len = pservice->hw_info->hw_id == HEVC_ID ? REG_NUM_HEVC_DEC : REG_NUM_9190_DEC;\r
1319                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(reg_len)))\r
1320                         ret = -EFAULT;\r
1321                 break;\r
1322         }\r
1323         case VPU_PP : {\r
1324                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_PP)))\r
1325                         ret = -EFAULT;\r
1326                 break;\r
1327         }\r
1328         case VPU_DEC_PP : {\r
1329                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_DEC_PP)))\r
1330                         ret = -EFAULT;\r
1331                 break;\r
1332         }\r
1333         default : {\r
1334                 ret = -EFAULT;\r
1335                 pr_err("error: copy reg to user with unknown type %d\n", reg->type);\r
1336                 break;\r
1337         }\r
1338         }\r
1339         reg_deinit(pservice, reg);\r
1340         return ret;\r
1341 }\r
1342 \r
1343 static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)\r
1344 {\r
1345     struct vpu_service_info *pservice = container_of(filp->f_dentry->d_inode->i_cdev, struct vpu_service_info, cdev);\r
1346         vpu_session *session = (vpu_session *)filp->private_data;\r
1347         if (NULL == session) {\r
1348                 return -EINVAL;\r
1349         }\r
1350 \r
1351         switch (cmd) {\r
1352         case VPU_IOC_SET_CLIENT_TYPE : {\r
1353                 session->type = (VPU_CLIENT_TYPE)arg;\r
1354                 break;\r
1355         }\r
1356         case VPU_IOC_GET_HW_FUSE_STATUS : {\r
1357                 vpu_request req;\r
1358                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1359                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_from_user failed\n");\r
1360                         return -EFAULT;\r
1361                 } else {\r
1362                         if (VPU_ENC != session->type) {\r
1363                                 if (copy_to_user((void __user *)req.req, &pservice->dec_config, sizeof(VPUHwDecConfig_t))) {\r
1364                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);\r
1365                                         return -EFAULT;\r
1366                                 }\r
1367                         } else {\r
1368                                 if (copy_to_user((void __user *)req.req, &pservice->enc_config, sizeof(VPUHwEncConfig_t))) {\r
1369                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);\r
1370                                         return -EFAULT;\r
1371                                 }\r
1372                         }\r
1373                 }\r
1374 \r
1375                 break;\r
1376         }\r
1377         case VPU_IOC_SET_REG : {\r
1378                 vpu_request req;\r
1379                 vpu_reg *reg;\r
1380                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1381                         pr_err("error: VPU_IOC_SET_REG copy_from_user failed\n");\r
1382                         return -EFAULT;\r
1383                 }\r
1384                 reg = reg_init(pservice, session, (void __user *)req.req, req.size);\r
1385                 if (NULL == reg) {\r
1386                         return -EFAULT;\r
1387                 } else {\r
1388                         mutex_lock(&pservice->lock);\r
1389                         try_set_reg(pservice);\r
1390                         mutex_unlock(&pservice->lock);\r
1391                 }\r
1392 \r
1393                 break;\r
1394         }\r
1395         case VPU_IOC_GET_REG : {\r
1396                 vpu_request req;\r
1397                 vpu_reg *reg;\r
1398                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {\r
1399                         pr_err("error: VPU_IOC_GET_REG copy_from_user failed\n");\r
1400                         return -EFAULT;\r
1401                 } else {\r
1402                         int ret = wait_event_timeout(session->wait, !list_empty(&session->done), VPU_TIMEOUT_DELAY);\r
1403                         if (!list_empty(&session->done)) {\r
1404                                 if (ret < 0) {\r
1405                                         pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session->pid, ret);\r
1406                                 }\r
1407                                 ret = 0;\r
1408                         } else {\r
1409                                 if (unlikely(ret < 0)) {\r
1410                                         pr_err("error: pid %d wait task ret %d\n", session->pid, ret);\r
1411                                 } else if (0 == ret) {\r
1412                                         pr_err("error: pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));\r
1413                                         ret = -ETIMEDOUT;\r
1414                                 }\r
1415                         }\r
1416                         if (ret < 0) {\r
1417                                 int task_running = atomic_read(&session->task_running);\r
1418                                 mutex_lock(&pservice->lock);\r
1419                                 vpu_service_dump(pservice);\r
1420                                 if (task_running) {\r
1421                                         atomic_set(&session->task_running, 0);\r
1422                                         atomic_sub(task_running, &pservice->total_running);\r
1423                                         printk("%d task is running but not return, reset hardware...", task_running);\r
1424                                         vpu_reset(pservice);\r
1425                                         printk("done\n");\r
1426                                 }\r
1427                                 vpu_service_session_clear(pservice, session);\r
1428                                 mutex_unlock(&pservice->lock);\r
1429                                 return ret;\r
1430                         }\r
1431                 }\r
1432                 mutex_lock(&pservice->lock);\r
1433                 reg = list_entry(session->done.next, vpu_reg, session_link);\r
1434                 return_reg(pservice, reg, (u32 __user *)req.req);\r
1435                 mutex_unlock(&pservice->lock);\r
1436                 break;\r
1437         }\r
1438         case VPU_IOC_PROBE_IOMMU_STATUS: {\r
1439                 int iommu_enable = 0;\r
1440 \r
1441 #if defined(CONFIG_VCODEC_MMU)\r
1442                 iommu_enable = pservice->mmu_dev ? 1 : 0;\r
1443 #endif\r
1444 \r
1445                 if (copy_to_user((void __user *)arg, &iommu_enable, sizeof(int))) {\r
1446                         pr_err("error: VPU_IOC_PROBE_IOMMU_STATUS copy_to_user failed\n");\r
1447                         return -EFAULT;\r
1448                 }\r
1449                 break;\r
1450         }\r
1451         default : {\r
1452                 pr_err("error: unknow vpu service ioctl cmd %x\n", cmd);\r
1453                 break;\r
1454         }\r
1455         }\r
1456 \r
1457         return 0;\r
1458 }\r
1459 \r
1460 static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)\r
1461 {\r
1462         int ret = -EINVAL, i = 0;\r
1463         volatile u32 *tmp = (volatile u32 *)ioremap_nocache(hw_addr, 0x4);\r
1464         u32 enc_id = *tmp;\r
1465 \r
1466 #if HEVC_SIM_ENABLE\r
1467         /// temporary, hevc driver test.\r
1468         if (strncmp(dev_name(p->dev), "hevc_service", strlen("hevc_service")) == 0) {\r
1469                 p->hw_info = &vpu_hw_set[2];\r
1470                 return 0;\r
1471         }\r
1472 #endif\r
1473         enc_id = (enc_id >> 16) & 0xFFFF;\r
1474         pr_info("checking hw id %x\n", enc_id);\r
1475         p->hw_info = NULL;\r
1476         for (i = 0; i < ARRAY_SIZE(vpu_hw_set); i++) {\r
1477                 if (enc_id == vpu_hw_set[i].hw_id) {\r
1478                         p->hw_info = &vpu_hw_set[i];\r
1479                         ret = 0;\r
1480                         break;\r
1481                 }\r
1482         }\r
1483         iounmap((void *)tmp);\r
1484         return ret;\r
1485 }\r
1486 \r
1487 static int vpu_service_open(struct inode *inode, struct file *filp)\r
1488 {\r
1489         struct vpu_service_info *pservice = container_of(inode->i_cdev, struct vpu_service_info, cdev);\r
1490         vpu_session *session = (vpu_session *)kmalloc(sizeof(vpu_session), GFP_KERNEL);\r
1491         if (NULL == session) {\r
1492                 pr_err("error: unable to allocate memory for vpu_session.");\r
1493                 return -ENOMEM;\r
1494         }\r
1495 \r
1496         session->type   = VPU_TYPE_BUTT;\r
1497         session->pid    = current->pid;\r
1498         INIT_LIST_HEAD(&session->waiting);\r
1499         INIT_LIST_HEAD(&session->running);\r
1500         INIT_LIST_HEAD(&session->done);\r
1501         INIT_LIST_HEAD(&session->list_session);\r
1502         init_waitqueue_head(&session->wait);\r
1503         atomic_set(&session->task_running, 0);\r
1504         mutex_lock(&pservice->lock);\r
1505         list_add_tail(&session->list_session, &pservice->session);\r
1506         filp->private_data = (void *)session;\r
1507         mutex_unlock(&pservice->lock);\r
1508 \r
1509         pr_debug("dev opened\n");\r
1510         return nonseekable_open(inode, filp);\r
1511 }\r
1512 \r
1513 static int vpu_service_release(struct inode *inode, struct file *filp)\r
1514 {\r
1515         struct vpu_service_info *pservice = container_of(inode->i_cdev, struct vpu_service_info, cdev);\r
1516         int task_running;\r
1517         vpu_session *session = (vpu_session *)filp->private_data;\r
1518         if (NULL == session)\r
1519                 return -EINVAL;\r
1520 \r
1521         task_running = atomic_read(&session->task_running);\r
1522         if (task_running) {\r
1523                 pr_err("error: vpu_service session %d still has %d task running when closing\n", session->pid, task_running);\r
1524                 msleep(50);\r
1525         }\r
1526         wake_up(&session->wait);\r
1527 \r
1528         mutex_lock(&pservice->lock);\r
1529         /* remove this filp from the asynchronusly notified filp's */\r
1530         list_del_init(&session->list_session);\r
1531         vpu_service_session_clear(pservice, session);\r
1532         kfree(session);\r
1533         filp->private_data = NULL;\r
1534         mutex_unlock(&pservice->lock);\r
1535 \r
1536         pr_debug("dev closed\n");\r
1537         return 0;\r
1538 }\r
1539 \r
1540 static const struct file_operations vpu_service_fops = {\r
1541         .unlocked_ioctl = vpu_service_ioctl,\r
1542         .open           = vpu_service_open,\r
1543         .release        = vpu_service_release,\r
1544         //.fasync       = vpu_service_fasync,\r
1545 };\r
1546 \r
1547 static irqreturn_t vdpu_irq(int irq, void *dev_id);\r
1548 static irqreturn_t vdpu_isr(int irq, void *dev_id);\r
1549 static irqreturn_t vepu_irq(int irq, void *dev_id);\r
1550 static irqreturn_t vepu_isr(int irq, void *dev_id);\r
1551 static void get_hw_info(struct vpu_service_info *pservice);\r
1552 \r
1553 #if HEVC_SIM_ENABLE\r
1554 static void simulate_work(struct work_struct *work_s)\r
1555 {\r
1556         struct delayed_work *dlwork = container_of(work_s, struct delayed_work, work);\r
1557         struct vpu_service_info *pservice = container_of(dlwork, struct vpu_service_info, simulate_work);\r
1558         vpu_device *dev = &pservice->dec_dev;\r
1559 \r
1560         if (!list_empty(&pservice->running)) {\r
1561                 atomic_add(1, &dev->irq_count_codec);\r
1562                 vdpu_isr(0, (void*)pservice);\r
1563         } else {\r
1564                 //simulate_start(pservice);\r
1565                 pr_err("empty running queue\n");\r
1566         }\r
1567 }\r
1568 \r
1569 static void simulate_init(struct vpu_service_info *pservice)\r
1570 {\r
1571         INIT_DELAYED_WORK(&pservice->simulate_work, simulate_work);\r
1572 }\r
1573 \r
1574 static void simulate_start(struct vpu_service_info *pservice)\r
1575 {\r
1576         cancel_delayed_work_sync(&pservice->power_off_work);\r
1577         queue_delayed_work(system_nrt_wq, &pservice->simulate_work, VPU_SIMULATE_DELAY);\r
1578 }\r
1579 #endif\r
1580 \r
1581 #ifdef CONFIG_VCODEC_MMU\r
1582 static struct device *rockchip_get_sysmmu_device_by_compatible(const char *compt)\r
1583 {\r
1584         struct device_node *dn = NULL;\r
1585         struct platform_device *pd = NULL;\r
1586         struct device *ret = NULL ;\r
1587 \r
1588         dn = of_find_compatible_node(NULL,NULL,compt);\r
1589         if(!dn) {\r
1590                 printk("can't find device node %s \r\n",compt);\r
1591                 return NULL;\r
1592         }\r
1593         \r
1594         pd = of_find_device_by_node(dn);\r
1595         if(!pd) {       \r
1596                 printk("can't find platform device in device node %s \r\n",compt);\r
1597                 return  NULL;\r
1598         }\r
1599         ret = &pd->dev;\r
1600         \r
1601         return ret;\r
1602 \r
1603 }\r
1604 #ifdef CONFIG_IOMMU_API\r
1605 static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
1606 {\r
1607         dev->archdata.iommu = iommu;\r
1608 }\r
1609 #else\r
1610 static inline void platform_set_sysmmu(struct device *iommu, struct device *dev)\r
1611 {\r
1612 }\r
1613 #endif\r
1614 #endif\r
1615 \r
1616 #if HEVC_TEST_ENABLE\r
1617 static int hevc_test_case0(vpu_service_info *pservice);\r
1618 #endif\r
1619 #if defined(CONFIG_ION_ROCKCHIP)\r
1620 extern struct ion_client *rockchip_ion_client_create(const char * name);\r
1621 #endif\r
1622 static int vcodec_probe(struct platform_device *pdev)\r
1623 {\r
1624         int ret = 0;\r
1625         struct resource *res = NULL;\r
1626         struct device *dev = &pdev->dev;\r
1627         void __iomem *regs = NULL;\r
1628         struct device_node *np = pdev->dev.of_node;\r
1629         struct vpu_service_info *pservice = devm_kzalloc(dev, sizeof(struct vpu_service_info), GFP_KERNEL);\r
1630         char *prop = (char*)dev_name(dev);\r
1631 #if defined(CONFIG_VCODEC_MMU)\r
1632         u32 iommu_en = 0;\r
1633         char mmu_dev_dts_name[40];\r
1634         of_property_read_u32(np, "iommu_enabled", &iommu_en);\r
1635 #endif\r
1636 \r
1637         pr_info("probe device %s\n", dev_name(dev));\r
1638 \r
1639         of_property_read_string(np, "name", (const char**)&prop);\r
1640         dev_set_name(dev, prop);\r
1641 \r
1642         if (strcmp(dev_name(dev), "hevc_service") == 0) {\r
1643                 pservice->dev_id = VCODEC_DEVICE_ID_HEVC;\r
1644         } else if (strcmp(dev_name(dev), "vpu_service") == 0) {\r
1645                 pservice->dev_id = VCODEC_DEVICE_ID_VPU;\r
1646         } else {\r
1647                 dev_err(dev, "Unknown device %s to probe\n", dev_name(dev));\r
1648                 return -1;\r
1649         }\r
1650 \r
1651         mutex_init(&g_mode_mutex);\r
1652         vcodec_enter_mode(pservice->dev_id);\r
1653 \r
1654         wake_lock_init(&pservice->wake_lock, WAKE_LOCK_SUSPEND, "vpu");\r
1655         INIT_LIST_HEAD(&pservice->waiting);\r
1656         INIT_LIST_HEAD(&pservice->running);\r
1657         INIT_LIST_HEAD(&pservice->done);\r
1658         INIT_LIST_HEAD(&pservice->session);\r
1659         mutex_init(&pservice->lock);\r
1660         pservice->reg_codec     = NULL;\r
1661         pservice->reg_pproc     = NULL;\r
1662         atomic_set(&pservice->total_running, 0);\r
1663         pservice->enabled = false;\r
1664 #if defined(CONFIG_VCODEC_MMU)\r
1665         pservice->mmu_dev = NULL;\r
1666 #endif\r
1667         pservice->dev = dev;\r
1668 \r
1669         if (0 > vpu_get_clk(pservice))\r
1670                 goto err;\r
1671 \r
1672         INIT_DELAYED_WORK(&pservice->power_off_work, vpu_power_off_work);\r
1673 \r
1674         vpu_service_power_on(pservice);\r
1675 \r
1676         mdelay(1);\r
1677 \r
1678         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1679 \r
1680         res->flags &= ~IORESOURCE_CACHEABLE;\r
1681 \r
1682         regs = devm_ioremap_resource(pservice->dev, res);\r
1683         if (IS_ERR(regs)) {\r
1684                 ret = PTR_ERR(regs);\r
1685                 goto err;\r
1686         }\r
1687 \r
1688         {\r
1689                 u32 offset = res->start;\r
1690                 if (cpu_is_rk3036()) {\r
1691                         if (pservice->dev_id == VCODEC_DEVICE_ID_VPU)\r
1692                                 offset += 0x400;\r
1693                 }\r
1694                 ret = vpu_service_check_hw(pservice, offset);\r
1695                 if (ret < 0) {\r
1696                         pr_err("error: hw info check faild\n");\r
1697                         goto err;\r
1698                 }\r
1699         }\r
1700 \r
1701         /// define regs address.\r
1702         pservice->dec_dev.iobaseaddr = res->start + pservice->hw_info->dec_offset;\r
1703         pservice->dec_dev.iosize     = pservice->hw_info->dec_io_size;\r
1704 \r
1705         pservice->dec_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->dec_offset);\r
1706 \r
1707         pservice->reg_size   = pservice->dec_dev.iosize;\r
1708 \r
1709         if (pservice->hw_info->hw_id != HEVC_ID && !cpu_is_rk3036()) {\r
1710                 pservice->enc_dev.iobaseaddr = res->start + pservice->hw_info->enc_offset;\r
1711                 pservice->enc_dev.iosize     = pservice->hw_info->enc_io_size;\r
1712 \r
1713                 pservice->reg_size = pservice->reg_size > pservice->enc_dev.iosize ? pservice->reg_size : pservice->enc_dev.iosize;\r
1714 \r
1715                 pservice->enc_dev.hwregs = (volatile u32 *)((u8 *)regs + pservice->hw_info->enc_offset);\r
1716 \r
1717                 pservice->irq_enc = platform_get_irq_byname(pdev, "irq_enc");\r
1718                 if (pservice->irq_enc < 0) {\r
1719                         dev_err(pservice->dev, "cannot find IRQ encoder\n");\r
1720                         ret = -ENXIO;\r
1721                         goto err;\r
1722                 }\r
1723 \r
1724                 ret = devm_request_threaded_irq(pservice->dev, pservice->irq_enc, vepu_irq, vepu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
1725                 if (ret) {\r
1726                         dev_err(pservice->dev, "error: can't request vepu irq %d\n", pservice->irq_enc);\r
1727                         goto err;\r
1728                 }\r
1729         }\r
1730 \r
1731         pservice->irq_dec = platform_get_irq_byname(pdev, "irq_dec");\r
1732         if (pservice->irq_dec < 0) {\r
1733                 dev_err(pservice->dev, "cannot find IRQ decoder\n");\r
1734                 ret = -ENXIO;\r
1735                 goto err;\r
1736         }\r
1737 \r
1738         /* get the IRQ line */\r
1739         ret = devm_request_threaded_irq(pservice->dev, pservice->irq_dec, vdpu_irq, vdpu_isr, 0, dev_name(pservice->dev), (void *)pservice);\r
1740         if (ret) {\r
1741                 dev_err(pservice->dev, "error: can't request vdpu irq %d\n", pservice->irq_dec);\r
1742                 goto err;\r
1743         }\r
1744 \r
1745         atomic_set(&pservice->dec_dev.irq_count_codec, 0);\r
1746         atomic_set(&pservice->dec_dev.irq_count_pp, 0);\r
1747         atomic_set(&pservice->enc_dev.irq_count_codec, 0);\r
1748         atomic_set(&pservice->enc_dev.irq_count_pp, 0);\r
1749 \r
1750         /// create device\r
1751         ret = alloc_chrdev_region(&pservice->dev_t, 0, 1, dev_name(dev));\r
1752         if (ret) {\r
1753                 dev_err(dev, "alloc dev_t failed\n");\r
1754                 goto err;\r
1755         }\r
1756 \r
1757         cdev_init(&pservice->cdev, &vpu_service_fops);\r
1758 \r
1759         pservice->cdev.owner = THIS_MODULE;\r
1760         pservice->cdev.ops = &vpu_service_fops;\r
1761 \r
1762         ret = cdev_add(&pservice->cdev, pservice->dev_t, 1);\r
1763 \r
1764         if (ret) {\r
1765                 dev_err(dev, "add dev_t failed\n");\r
1766                 goto err;\r
1767         }\r
1768 \r
1769         pservice->cls = class_create(THIS_MODULE, dev_name(dev));\r
1770 \r
1771         if (IS_ERR(pservice->cls)) {\r
1772                 ret = PTR_ERR(pservice->cls);\r
1773                 dev_err(dev, "class_create err:%d\n", ret);\r
1774                 goto err;\r
1775         }\r
1776 \r
1777         pservice->child_dev = device_create(pservice->cls, dev, pservice->dev_t, NULL, dev_name(dev));\r
1778 \r
1779         platform_set_drvdata(pdev, pservice);\r
1780 \r
1781         get_hw_info(pservice);\r
1782 \r
1783 \r
1784 #ifdef CONFIG_DEBUG_FS\r
1785         pservice->debugfs_dir = vcodec_debugfs_create_device_dir((char*)dev_name(dev), parent);\r
1786         if (pservice->debugfs_dir == NULL)\r
1787                 pr_err("create debugfs dir %s failed\n", dev_name(dev));\r
1788 \r
1789         pservice->debugfs_file_regs =\r
1790                 debugfs_create_file("regs", 0664,\r
1791                                     pservice->debugfs_dir, pservice,\r
1792                                     &debug_vcodec_fops);\r
1793 #endif\r
1794 \r
1795 #if defined(CONFIG_VCODEC_MMU)\r
1796         if (iommu_en) {\r
1797                 pservice->ion_client = rockchip_ion_client_create("vpu");\r
1798                 if (IS_ERR(pservice->ion_client)) {\r
1799                         dev_err(&pdev->dev, "failed to create ion client for vcodec");\r
1800                         return PTR_ERR(pservice->ion_client);\r
1801                 } else {\r
1802                         dev_info(&pdev->dev, "vcodec ion client create success!\n");\r
1803                 }\r
1804 \r
1805                 if (pservice->hw_info->hw_id == HEVC_ID)\r
1806                         sprintf(mmu_dev_dts_name, HEVC_IOMMU_COMPATIBLE_NAME);\r
1807                 else\r
1808                         sprintf(mmu_dev_dts_name, VPU_IOMMU_COMPATIBLE_NAME);\r
1809 \r
1810                 pservice->mmu_dev = rockchip_get_sysmmu_device_by_compatible(mmu_dev_dts_name);\r
1811 \r
1812                 if (pservice->mmu_dev) {\r
1813                         platform_set_sysmmu(pservice->mmu_dev, pservice->dev);\r
1814                         rockchip_iovmm_activate(pservice->dev);\r
1815                 }\r
1816         }\r
1817 #endif\r
1818 \r
1819         vpu_service_power_off(pservice);\r
1820         vcodec_exit_mode();\r
1821 \r
1822         pr_info("init success\n");\r
1823 \r
1824 #if HEVC_SIM_ENABLE\r
1825         if (pservice->hw_info->hw_id == HEVC_ID)\r
1826                 simulate_init(pservice);\r
1827 #endif\r
1828 \r
1829 #if HEVC_TEST_ENABLE\r
1830         hevc_test_case0(pservice);\r
1831 #endif\r
1832 \r
1833         return 0;\r
1834 \r
1835 err:\r
1836         pr_info("init failed\n");\r
1837         vpu_service_power_off(pservice);\r
1838         vpu_put_clk(pservice);\r
1839         wake_lock_destroy(&pservice->wake_lock);\r
1840 \r
1841         if (res)\r
1842                 devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
1843         if (pservice->irq_enc > 0)\r
1844                 free_irq(pservice->irq_enc, (void *)pservice);\r
1845         if (pservice->irq_dec > 0)\r
1846                 free_irq(pservice->irq_dec, (void *)pservice);\r
1847 \r
1848         if (pservice->child_dev) {\r
1849                 device_destroy(pservice->cls, pservice->dev_t);\r
1850                 cdev_del(&pservice->cdev);\r
1851                 unregister_chrdev_region(pservice->dev_t, 1);\r
1852         }\r
1853 \r
1854         if (pservice->cls)\r
1855                 class_destroy(pservice->cls);\r
1856 \r
1857         return ret;\r
1858 }\r
1859 \r
1860 static int vcodec_remove(struct platform_device *pdev)\r
1861 {\r
1862         struct vpu_service_info *pservice = platform_get_drvdata(pdev);\r
1863         struct resource *res;\r
1864 \r
1865         device_destroy(pservice->cls, pservice->dev_t);\r
1866         class_destroy(pservice->cls);\r
1867         cdev_del(&pservice->cdev);\r
1868         unregister_chrdev_region(pservice->dev_t, 1);\r
1869 \r
1870         free_irq(pservice->irq_enc, (void *)&pservice->enc_dev);\r
1871         free_irq(pservice->irq_dec, (void *)&pservice->dec_dev);\r
1872         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);\r
1873         devm_release_mem_region(&pdev->dev, res->start, resource_size(res));\r
1874         vpu_put_clk(pservice);\r
1875         wake_lock_destroy(&pservice->wake_lock);\r
1876 \r
1877 #ifdef CONFIG_DEBUG_FS\r
1878         debugfs_remove(pservice->debugfs_file_regs);\r
1879         debugfs_remove(pservice->debugfs_dir);\r
1880 #endif\r
1881 \r
1882         return 0;\r
1883 }\r
1884 \r
1885 #if defined(CONFIG_OF)\r
1886 static const struct of_device_id vcodec_service_dt_ids[] = {\r
1887         {.compatible = "vpu_service",},\r
1888         {.compatible = "rockchip,hevc_service",},\r
1889         {},\r
1890 };\r
1891 #endif\r
1892 \r
1893 static struct platform_driver vcodec_driver = {\r
1894         .probe = vcodec_probe,\r
1895         .remove = vcodec_remove,\r
1896         .driver = {\r
1897                 .name = "vcodec",\r
1898                 .owner = THIS_MODULE,\r
1899 #if defined(CONFIG_OF)\r
1900                 .of_match_table = of_match_ptr(vcodec_service_dt_ids),\r
1901 #endif\r
1902         },\r
1903 };\r
1904 \r
1905 static void get_hw_info(struct vpu_service_info *pservice)\r
1906 {\r
1907         VPUHwDecConfig_t *dec = &pservice->dec_config;\r
1908         VPUHwEncConfig_t *enc = &pservice->enc_config;\r
1909 \r
1910         if (pservice->dev_id == VCODEC_DEVICE_ID_VPU) {\r
1911                 u32 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG0];\r
1912                 u32 asicID      = pservice->dec_dev.hwregs[0];\r
1913 \r
1914                 dec->h264Support    = (configReg >> DWL_H264_E) & 0x3U;\r
1915                 dec->jpegSupport    = (configReg >> DWL_JPEG_E) & 0x01U;\r
1916                 if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))\r
1917                         dec->jpegSupport = JPEG_PROGRESSIVE;\r
1918                 dec->mpeg4Support   = (configReg >> DWL_MPEG4_E) & 0x3U;\r
1919                 dec->vc1Support     = (configReg >> DWL_VC1_E) & 0x3U;\r
1920                 dec->mpeg2Support   = (configReg >> DWL_MPEG2_E) & 0x01U;\r
1921                 dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;\r
1922                 dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;\r
1923                 dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;\r
1924 \r
1925                 if (soc_is_rk3190() || soc_is_rk3288())\r
1926                         dec->maxDecPicWidth = 4096;\r
1927                 else if (cpu_is_rk3036() || cpu_is_rk312x())\r
1928                         dec->maxDecPicWidth = 1920;\r
1929                 else\r
1930                         dec->maxDecPicWidth = configReg & 0x07FFU;\r
1931 \r
1932                 /* 2nd Config register */\r
1933                 configReg   = pservice->dec_dev.hwregs[VPU_DEC_HWCFG1];\r
1934                 if (dec->refBufSupport) {\r
1935                         if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)\r
1936                                 dec->refBufSupport |= 2;\r
1937                         if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)\r
1938                                 dec->refBufSupport |= 4;\r
1939                 }\r
1940                 dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;\r
1941                 dec->vp7Support     = (configReg >> DWL_VP7_E) & 0x01U;\r
1942                 dec->vp8Support     = (configReg >> DWL_VP8_E) & 0x01U;\r
1943                 dec->avsSupport     = (configReg >> DWL_AVS_E) & 0x01U;\r
1944 \r
1945                 /* JPEG xtensions */\r
1946                 if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U))\r
1947                         dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;\r
1948                 else\r
1949                         dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;\r
1950 \r
1951                 if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) )\r
1952                         dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;\r
1953                 else\r
1954                         dec->rvSupport = RV_NOT_SUPPORTED;\r
1955                 dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;\r
1956 \r
1957                 if (dec->refBufSupport && (asicID >> 16) == 0x6731U )\r
1958                         dec->refBufSupport |= 8; /* enable HW support for offset */\r
1959 \r
1960                 /// invalidate fuse register value in rk319x vpu and following.\r
1961                 if (!soc_is_rk3190() && !soc_is_rk3288() && !cpu_is_rk3036() && !cpu_is_rk312x()) {\r
1962                         VPUHwFuseStatus_t hwFuseSts;\r
1963                         /* Decoder fuse configuration */\r
1964                         u32 fuseReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
1965 \r
1966                         hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;\r
1967                         hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;\r
1968                         hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;\r
1969                         hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;\r
1970                         hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;\r
1971                         hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;\r
1972                         hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;\r
1973                         hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;\r
1974                         hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;\r
1975                         hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;\r
1976                         hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;\r
1977                         hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;\r
1978                         hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;\r
1979                         hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;\r
1980 \r
1981                         /* check max. decoder output width */\r
1982 \r
1983                         if (fuseReg & 0x8000U)\r
1984                                 hwFuseSts.maxDecPicWidthFuse = 1920;\r
1985                         else if (fuseReg & 0x4000U)\r
1986                                 hwFuseSts.maxDecPicWidthFuse = 1280;\r
1987                         else if (fuseReg & 0x2000U)\r
1988                                 hwFuseSts.maxDecPicWidthFuse = 720;\r
1989                         else if (fuseReg & 0x1000U)\r
1990                                 hwFuseSts.maxDecPicWidthFuse = 352;\r
1991                         else    /* remove warning */\r
1992                                 hwFuseSts.maxDecPicWidthFuse = 352;\r
1993 \r
1994                         hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;\r
1995 \r
1996                         /* Pp configuration */\r
1997                         configReg = pservice->dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];\r
1998 \r
1999                         if ((configReg >> DWL_PP_E) & 0x01U) {\r
2000                                 dec->ppSupport = 1;\r
2001                                 dec->maxPpOutPicWidth = configReg & 0x07FFU;\r
2002                                 /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */\r
2003                                 dec->ppConfig = configReg;\r
2004                         } else {\r
2005                                 dec->ppSupport = 0;\r
2006                                 dec->maxPpOutPicWidth = 0;\r
2007                                 dec->ppConfig = 0;\r
2008                         }\r
2009 \r
2010                         /* check the HW versio */\r
2011                         if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {\r
2012                                 /* Pp configuration */\r
2013                                 configReg = pservice->dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];\r
2014                                 if ((configReg >> DWL_PP_E) & 0x01U) {\r
2015                                         /* Pp fuse configuration */\r
2016                                         u32 fuseRegPp = pservice->dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];\r
2017 \r
2018                                         if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {\r
2019                                                 hwFuseSts.ppSupportFuse = 1;\r
2020                                                 /* check max. pp output width */\r
2021                                                 if (fuseRegPp & 0x8000U)\r
2022                                                         hwFuseSts.maxPpOutPicWidthFuse = 1920;\r
2023                                                 else if (fuseRegPp & 0x4000U)\r
2024                                                         hwFuseSts.maxPpOutPicWidthFuse = 1280;\r
2025                                                 else if (fuseRegPp & 0x2000U)\r
2026                                                         hwFuseSts.maxPpOutPicWidthFuse = 720;\r
2027                                                 else if (fuseRegPp & 0x1000U)\r
2028                                                         hwFuseSts.maxPpOutPicWidthFuse = 352;\r
2029                                                 else\r
2030                                                         hwFuseSts.maxPpOutPicWidthFuse = 352;\r
2031                                                 hwFuseSts.ppConfigFuse = fuseRegPp;\r
2032                                         } else {\r
2033                                                 hwFuseSts.ppSupportFuse = 0;\r
2034                                                 hwFuseSts.maxPpOutPicWidthFuse = 0;\r
2035                                                 hwFuseSts.ppConfigFuse = 0;\r
2036                                         }\r
2037                                 } else {\r
2038                                         hwFuseSts.ppSupportFuse = 0;\r
2039                                         hwFuseSts.maxPpOutPicWidthFuse = 0;\r
2040                                         hwFuseSts.ppConfigFuse = 0;\r
2041                                 }\r
2042 \r
2043                                 if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)\r
2044                                         dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;\r
2045                                 if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)\r
2046                                         dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;\r
2047                                 if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;\r
2048                                 if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;\r
2049                                 if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;\r
2050                                 if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;\r
2051                                 if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)\r
2052                                         dec->jpegSupport = JPEG_BASELINE;\r
2053                                 if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;\r
2054                                 if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;\r
2055                                 if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;\r
2056                                 if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;\r
2057                                 if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;\r
2058                                 if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;\r
2059 \r
2060                                 /* check the pp config vs fuse status */\r
2061                                 if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {\r
2062                                         u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);\r
2063                                         u32 alphaBlend  = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);\r
2064                                         u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);\r
2065                                         u32 alphaBlendFuse  = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);\r
2066 \r
2067                                         if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;\r
2068                                         if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;\r
2069                                 }\r
2070                                 if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;\r
2071                                 if (!hwFuseSts.refBufSupportFuse)   dec->refBufSupport = REF_BUF_NOT_SUPPORTED;\r
2072                                 if (!hwFuseSts.rvSupportFuse)       dec->rvSupport = RV_NOT_SUPPORTED;\r
2073                                 if (!hwFuseSts.avsSupportFuse)      dec->avsSupport = AVS_NOT_SUPPORTED;\r
2074                                 if (!hwFuseSts.mvcSupportFuse)      dec->mvcSupport = MVC_NOT_SUPPORTED;\r
2075                         }\r
2076                 }\r
2077 \r
2078                 if (!cpu_is_rk3036()) {\r
2079                         configReg = pservice->enc_dev.hwregs[63];\r
2080                         enc->maxEncodedWidth = configReg & ((1 << 11) - 1);\r
2081                         enc->h264Enabled = (configReg >> 27) & 1;\r
2082                         enc->mpeg4Enabled = (configReg >> 26) & 1;\r
2083                         enc->jpegEnabled = (configReg >> 25) & 1;\r
2084                         enc->vsEnabled = (configReg >> 24) & 1;\r
2085                         enc->rgbEnabled = (configReg >> 28) & 1;\r
2086                         /*enc->busType = (configReg >> 20) & 15;\r
2087                         enc->synthesisLanguage = (configReg >> 16) & 15;\r
2088                         enc->busWidth = (configReg >> 12) & 15;*/\r
2089                         enc->reg_size = pservice->reg_size;\r
2090                         enc->reserv[0] = enc->reserv[1] = 0;\r
2091                 }\r
2092 \r
2093                 pservice->auto_freq = soc_is_rk2928g() || soc_is_rk2928l() || soc_is_rk2926() || soc_is_rk3288();\r
2094                 if (pservice->auto_freq) {\r
2095                         pr_info("vpu_service set to auto frequency mode\n");\r
2096                         atomic_set(&pservice->freq_status, VPU_FREQ_BUT);\r
2097                 }\r
2098 \r
2099                 pservice->bug_dec_addr = cpu_is_rk30xx();\r
2100         } else {\r
2101                 if (cpu_is_rk3036()  || cpu_is_rk312x())\r
2102                         dec->maxDecPicWidth = 1920;\r
2103                 else\r
2104                         dec->maxDecPicWidth = 4096;\r
2105                 /* disable frequency switch in hevc.*/\r
2106                 pservice->auto_freq = false;\r
2107         }\r
2108 }\r
2109 \r
2110 static irqreturn_t vdpu_irq(int irq, void *dev_id)\r
2111 {\r
2112         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2113         vpu_device *dev = &pservice->dec_dev;\r
2114         u32 raw_status;\r
2115         u32 irq_status;\r
2116 \r
2117         vcodec_enter_mode_nolock(pservice->dev_id, &pservice->reserved_mode);\r
2118 \r
2119         irq_status = raw_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2120 \r
2121         pr_debug("dec_irq\n");\r
2122 \r
2123         if (irq_status & DEC_INTERRUPT_BIT) {\r
2124                 pr_debug("dec_isr dec %x\n", irq_status);\r
2125                 if ((irq_status & 0x40001) == 0x40001)\r
2126                 {\r
2127                         do {\r
2128                                 irq_status = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2129                         } while ((irq_status & 0x40001) == 0x40001);\r
2130                 }\r
2131 \r
2132                 /* clear dec IRQ */\r
2133                 if (pservice->hw_info->hw_id != HEVC_ID)\r
2134                         writel(irq_status & (~DEC_INTERRUPT_BIT|DEC_BUFFER_EMPTY_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2135                 else\r
2136                         writel(0, dev->hwregs + DEC_INTERRUPT_REGISTER);\r
2137                 atomic_add(1, &dev->irq_count_codec);\r
2138         }\r
2139 \r
2140         if (pservice->hw_info->hw_id != HEVC_ID) {\r
2141                 irq_status = readl(dev->hwregs + PP_INTERRUPT_REGISTER);\r
2142                 if (irq_status & PP_INTERRUPT_BIT) {\r
2143                         pr_debug("vdpu_isr pp  %x\n", irq_status);\r
2144                         /* clear pp IRQ */\r
2145                         writel(irq_status & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);\r
2146                         atomic_add(1, &dev->irq_count_pp);\r
2147                 }\r
2148         }\r
2149 \r
2150         pservice->irq_status = raw_status;\r
2151 \r
2152         vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
2153 \r
2154         return IRQ_WAKE_THREAD;\r
2155 }\r
2156 \r
2157 static irqreturn_t vdpu_isr(int irq, void *dev_id)\r
2158 {\r
2159         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2160         vpu_device *dev = &pservice->dec_dev;\r
2161 \r
2162         mutex_lock(&pservice->lock);\r
2163         if (atomic_read(&dev->irq_count_codec)) {\r
2164 #if VPU_SERVICE_SHOW_TIME\r
2165                 do_gettimeofday(&dec_end);\r
2166                 pr_info("dec task: %ld ms\n",\r
2167                         (dec_end.tv_sec  - dec_start.tv_sec)  * 1000 +\r
2168                         (dec_end.tv_usec - dec_start.tv_usec) / 1000);\r
2169 #endif\r
2170                 atomic_sub(1, &dev->irq_count_codec);\r
2171                 if (NULL == pservice->reg_codec) {\r
2172                         pr_err("error: dec isr with no task waiting\n");\r
2173                 } else {\r
2174                         reg_from_run_to_done(pservice, pservice->reg_codec);\r
2175                 }\r
2176         }\r
2177 \r
2178         if (atomic_read(&dev->irq_count_pp)) {\r
2179 \r
2180 #if VPU_SERVICE_SHOW_TIME\r
2181                 do_gettimeofday(&pp_end);\r
2182                 printk("pp  task: %ld ms\n",\r
2183                         (pp_end.tv_sec  - pp_start.tv_sec)  * 1000 +\r
2184                         (pp_end.tv_usec - pp_start.tv_usec) / 1000);\r
2185 #endif\r
2186 \r
2187                 atomic_sub(1, &dev->irq_count_pp);\r
2188                 if (NULL == pservice->reg_pproc) {\r
2189                         pr_err("error: pp isr with no task waiting\n");\r
2190                 } else {\r
2191                         reg_from_run_to_done(pservice, pservice->reg_pproc);\r
2192                 }\r
2193         }\r
2194         try_set_reg(pservice);\r
2195         mutex_unlock(&pservice->lock);\r
2196         return IRQ_HANDLED;\r
2197 }\r
2198 \r
2199 static irqreturn_t vepu_irq(int irq, void *dev_id)\r
2200 {\r
2201         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2202         vpu_device *dev = &pservice->enc_dev;\r
2203         u32 irq_status;\r
2204 \r
2205         vcodec_enter_mode_nolock(pservice->dev_id,  &pservice->reserved_mode);\r
2206         irq_status= readl(dev->hwregs + ENC_INTERRUPT_REGISTER);\r
2207 \r
2208         pr_debug("vepu_irq irq status %x\n", irq_status);\r
2209 \r
2210 #if VPU_SERVICE_SHOW_TIME\r
2211         do_gettimeofday(&enc_end);\r
2212         pr_info("enc task: %ld ms\n",\r
2213                 (enc_end.tv_sec  - enc_start.tv_sec)  * 1000 +\r
2214                 (enc_end.tv_usec - enc_start.tv_usec) / 1000);\r
2215 #endif\r
2216         if (likely(irq_status & ENC_INTERRUPT_BIT)) {\r
2217                 /* clear enc IRQ */\r
2218                 writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);\r
2219                 atomic_add(1, &dev->irq_count_codec);\r
2220         }\r
2221 \r
2222         pservice->irq_status = irq_status;\r
2223 \r
2224         vcodec_exit_mode_nolock(pservice->dev_id, pservice->reserved_mode);\r
2225 \r
2226         return IRQ_WAKE_THREAD;\r
2227 }\r
2228 \r
2229 static irqreturn_t vepu_isr(int irq, void *dev_id)\r
2230 {\r
2231         struct vpu_service_info *pservice = (struct vpu_service_info*)dev_id;\r
2232         vpu_device *dev = &pservice->enc_dev;\r
2233 \r
2234         mutex_lock(&pservice->lock);\r
2235         if (atomic_read(&dev->irq_count_codec)) {\r
2236                 atomic_sub(1, &dev->irq_count_codec);\r
2237                 if (NULL == pservice->reg_codec) {\r
2238                         pr_err("error: enc isr with no task waiting\n");\r
2239                 } else {\r
2240                         reg_from_run_to_done(pservice, pservice->reg_codec);\r
2241                 }\r
2242         }\r
2243         try_set_reg(pservice);\r
2244         mutex_unlock(&pservice->lock);\r
2245         return IRQ_HANDLED;\r
2246 }\r
2247 \r
2248 static int __init vcodec_service_init(void)\r
2249 {\r
2250         int ret;\r
2251 \r
2252         if ((ret = platform_driver_register(&vcodec_driver)) != 0) {\r
2253                 pr_err("Platform device register failed (%d).\n", ret);\r
2254                 return ret;\r
2255         }\r
2256 \r
2257 #ifdef CONFIG_DEBUG_FS\r
2258         vcodec_debugfs_init();\r
2259 #endif\r
2260 \r
2261         return ret;\r
2262 }\r
2263 \r
2264 static void __exit vcodec_service_exit(void)\r
2265 {\r
2266 #ifdef CONFIG_DEBUG_FS\r
2267         vcodec_debugfs_exit();\r
2268 #endif\r
2269 \r
2270         platform_driver_unregister(&vcodec_driver);\r
2271 }\r
2272 \r
2273 module_init(vcodec_service_init);\r
2274 module_exit(vcodec_service_exit);\r
2275 \r
2276 #ifdef CONFIG_DEBUG_FS\r
2277 #include <linux/seq_file.h>\r
2278 \r
2279 static int vcodec_debugfs_init()\r
2280 {\r
2281         parent = debugfs_create_dir("vcodec", NULL);\r
2282         if (!parent)\r
2283                 return -1;\r
2284 \r
2285         return 0;\r
2286 }\r
2287 \r
2288 static void vcodec_debugfs_exit()\r
2289 {\r
2290         debugfs_remove(parent);\r
2291 }\r
2292 \r
2293 static struct dentry* vcodec_debugfs_create_device_dir(char *dirname, struct dentry *parent)\r
2294 {\r
2295         return debugfs_create_dir(dirname, parent);\r
2296 }\r
2297 \r
2298 static int debug_vcodec_show(struct seq_file *s, void *unused)\r
2299 {\r
2300         struct vpu_service_info *pservice = s->private;\r
2301         unsigned int i, n;\r
2302         vpu_reg *reg, *reg_tmp;\r
2303         vpu_session *session, *session_tmp;\r
2304 \r
2305         mutex_lock(&pservice->lock);\r
2306         vpu_service_power_on(pservice);\r
2307         if (pservice->hw_info->hw_id != HEVC_ID) {\r
2308                 seq_printf(s, "\nENC Registers:\n");\r
2309                 n = pservice->enc_dev.iosize >> 2;\r
2310                 for (i = 0; i < n; i++) {\r
2311                         seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->enc_dev.hwregs + i));\r
2312                 }\r
2313         }\r
2314         seq_printf(s, "\nDEC Registers:\n");\r
2315         n = pservice->dec_dev.iosize >> 2;\r
2316         for (i = 0; i < n; i++)\r
2317                 seq_printf(s, "\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
2318 \r
2319         seq_printf(s, "\nvpu service status:\n");\r
2320         list_for_each_entry_safe(session, session_tmp, &pservice->session, list_session) {\r
2321                 seq_printf(s, "session pid %d type %d:\n", session->pid, session->type);\r
2322                 /*seq_printf(s, "waiting reg set %d\n");*/\r
2323                 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {\r
2324                         seq_printf(s, "waiting register set\n");\r
2325                 }\r
2326                 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {\r
2327                         seq_printf(s, "running register set\n");\r
2328                 }\r
2329                 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {\r
2330                         seq_printf(s, "done    register set\n");\r
2331                 }\r
2332         }\r
2333         mutex_unlock(&pservice->lock);\r
2334 \r
2335         return 0;\r
2336 }\r
2337 \r
2338 static int debug_vcodec_open(struct inode *inode, struct file *file)\r
2339 {\r
2340         return single_open(file, debug_vcodec_show, inode->i_private);\r
2341 }\r
2342 \r
2343 #endif\r
2344 \r
2345 #if HEVC_TEST_ENABLE & defined(CONFIG_ION_ROCKCHIP)\r
2346 #include "hevc_test_inc/pps_00.h"\r
2347 #include "hevc_test_inc/register_00.h"\r
2348 #include "hevc_test_inc/rps_00.h"\r
2349 #include "hevc_test_inc/scaling_list_00.h"\r
2350 #include "hevc_test_inc/stream_00.h"\r
2351 \r
2352 #include "hevc_test_inc/pps_01.h"\r
2353 #include "hevc_test_inc/register_01.h"\r
2354 #include "hevc_test_inc/rps_01.h"\r
2355 #include "hevc_test_inc/scaling_list_01.h"\r
2356 #include "hevc_test_inc/stream_01.h"\r
2357 \r
2358 #include "hevc_test_inc/cabac.h"\r
2359 \r
2360 extern struct ion_client *rockchip_ion_client_create(const char * name);\r
2361 \r
2362 static struct ion_client *ion_client = NULL;\r
2363 u8* get_align_ptr(u8* tbl, int len, u32 *phy)\r
2364 {\r
2365         int size = (len+15) & (~15);\r
2366         struct ion_handle *handle;\r
2367         u8 *ptr;// = (u8*)kzalloc(size, GFP_KERNEL);\r
2368 \r
2369         if (ion_client == NULL)\r
2370                 ion_client = rockchip_ion_client_create("vcodec");\r
2371 \r
2372         handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
2373 \r
2374         ptr = ion_map_kernel(ion_client, handle);\r
2375 \r
2376         ion_phys(ion_client, handle, phy, &size);\r
2377 \r
2378         memcpy(ptr, tbl, len);\r
2379 \r
2380         return ptr;\r
2381 }\r
2382 \r
2383 u8* get_align_ptr_no_copy(int len, u32 *phy)\r
2384 {\r
2385         int size = (len+15) & (~15);\r
2386         struct ion_handle *handle;\r
2387         u8 *ptr;\r
2388 \r
2389         if (ion_client == NULL)\r
2390                 ion_client = rockchip_ion_client_create("vcodec");\r
2391 \r
2392         handle = ion_alloc(ion_client, (size_t)len, 16, ION_HEAP(ION_CMA_HEAP_ID), 0);\r
2393 \r
2394         ptr = ion_map_kernel(ion_client, handle);\r
2395 \r
2396         ion_phys(ion_client, handle, phy, &size);\r
2397 \r
2398         return ptr;\r
2399 }\r
2400 \r
2401 #define TEST_CNT    2\r
2402 static int hevc_test_case0(vpu_service_info *pservice)\r
2403 {\r
2404         vpu_session session;\r
2405         vpu_reg *reg;\r
2406         unsigned long size = 272;//sizeof(register_00); // registers array length\r
2407         int testidx = 0;\r
2408         int ret = 0;\r
2409 \r
2410         u8 *pps_tbl[TEST_CNT];\r
2411         u8 *register_tbl[TEST_CNT];\r
2412         u8 *rps_tbl[TEST_CNT];\r
2413         u8 *scaling_list_tbl[TEST_CNT];\r
2414         u8 *stream_tbl[TEST_CNT];\r
2415 \r
2416         int stream_size[2];\r
2417         int pps_size[2];\r
2418         int rps_size[2];\r
2419         int scl_size[2];\r
2420         int cabac_size[2];\r
2421 \r
2422         u32 phy_pps;\r
2423         u32 phy_rps;\r
2424         u32 phy_scl;\r
2425         u32 phy_str;\r
2426         u32 phy_yuv;\r
2427         u32 phy_ref;\r
2428         u32 phy_cabac;\r
2429 \r
2430         volatile u8 *stream_buf;\r
2431         volatile u8 *pps_buf;\r
2432         volatile u8 *rps_buf;\r
2433         volatile u8 *scl_buf;\r
2434         volatile u8 *yuv_buf;\r
2435         volatile u8 *cabac_buf;\r
2436         volatile u8 *ref_buf;\r
2437 \r
2438         u8 *pps;\r
2439         u8 *yuv[2];\r
2440         int i;\r
2441 \r
2442         pps_tbl[0] = pps_00;\r
2443         pps_tbl[1] = pps_01;\r
2444 \r
2445         register_tbl[0] = register_00;\r
2446         register_tbl[1] = register_01;\r
2447 \r
2448         rps_tbl[0] = rps_00;\r
2449         rps_tbl[1] = rps_01;\r
2450 \r
2451         scaling_list_tbl[0] = scaling_list_00;\r
2452         scaling_list_tbl[1] = scaling_list_01;\r
2453 \r
2454         stream_tbl[0] = stream_00;\r
2455         stream_tbl[1] = stream_01;\r
2456 \r
2457         stream_size[0] = sizeof(stream_00);\r
2458         stream_size[1] = sizeof(stream_01);\r
2459 \r
2460         pps_size[0] = sizeof(pps_00);\r
2461         pps_size[1] = sizeof(pps_01);\r
2462 \r
2463         rps_size[0] = sizeof(rps_00);\r
2464         rps_size[1] = sizeof(rps_01);\r
2465 \r
2466         scl_size[0] = sizeof(scaling_list_00);\r
2467         scl_size[1] = sizeof(scaling_list_01);\r
2468 \r
2469         cabac_size[0] = sizeof(Cabac_table);\r
2470         cabac_size[1] = sizeof(Cabac_table);\r
2471 \r
2472         /* create session */\r
2473         session.pid = current->pid;\r
2474         session.type = VPU_DEC;\r
2475         INIT_LIST_HEAD(&session.waiting);\r
2476         INIT_LIST_HEAD(&session.running);\r
2477         INIT_LIST_HEAD(&session.done);\r
2478         INIT_LIST_HEAD(&session.list_session);\r
2479         init_waitqueue_head(&session.wait);\r
2480         atomic_set(&session.task_running, 0);\r
2481         list_add_tail(&session.list_session, &pservice->session);\r
2482 \r
2483         yuv[0] = get_align_ptr_no_copy(256*256*2, &phy_yuv);\r
2484         yuv[1] = get_align_ptr_no_copy(256*256*2, &phy_ref);\r
2485 \r
2486         while (testidx < TEST_CNT) {\r
2487                 /* create registers */\r
2488                 reg = kmalloc(sizeof(vpu_reg)+pservice->reg_size, GFP_KERNEL);\r
2489                 if (NULL == reg) {\r
2490                         pr_err("error: kmalloc fail in reg_init\n");\r
2491                         return -1;\r
2492                 }\r
2493 \r
2494                 if (size > pservice->reg_size) {\r
2495                         printk("warning: vpu reg size %lu is larger than hw reg size %lu\n", size, pservice->reg_size);\r
2496                         size = pservice->reg_size;\r
2497                 }\r
2498                 reg->session = &session;\r
2499                 reg->type = session.type;\r
2500                 reg->size = size;\r
2501                 reg->freq = VPU_FREQ_DEFAULT;\r
2502                 reg->reg = (unsigned long *)&reg[1];\r
2503                 INIT_LIST_HEAD(&reg->session_link);\r
2504                 INIT_LIST_HEAD(&reg->status_link);\r
2505 \r
2506                 /* TODO: stuff registers */\r
2507                 memcpy(&reg->reg[0], register_tbl[testidx], /*sizeof(register_00)*/ 176);\r
2508 \r
2509                 stream_buf = get_align_ptr(stream_tbl[testidx], stream_size[testidx], &phy_str);\r
2510                 pps_buf = get_align_ptr(pps_tbl[0], pps_size[0], &phy_pps);\r
2511                 rps_buf = get_align_ptr(rps_tbl[testidx], rps_size[testidx], &phy_rps);\r
2512                 scl_buf = get_align_ptr(scaling_list_tbl[testidx], scl_size[testidx], &phy_scl);\r
2513                 cabac_buf = get_align_ptr(Cabac_table, cabac_size[testidx], &phy_cabac);\r
2514 \r
2515                 pps = pps_buf;\r
2516 \r
2517                 /* TODO: replace reigster address */\r
2518                 for (i=0; i<64; i++) {\r
2519                         u32 scaling_offset;\r
2520                         u32 tmp;\r
2521 \r
2522                         scaling_offset = (u32)pps[i*80+74];\r
2523                         scaling_offset += (u32)pps[i*80+75] << 8;\r
2524                         scaling_offset += (u32)pps[i*80+76] << 16;\r
2525                         scaling_offset += (u32)pps[i*80+77] << 24;\r
2526 \r
2527                         tmp = phy_scl + scaling_offset;\r
2528 \r
2529                         pps[i*80+74] = tmp & 0xff;\r
2530                         pps[i*80+75] = (tmp >> 8) & 0xff;\r
2531                         pps[i*80+76] = (tmp >> 16) & 0xff;\r
2532                         pps[i*80+77] = (tmp >> 24) & 0xff;\r
2533                 }\r
2534 \r
2535                 printk("%s %d, phy stream %08x, phy pps %08x, phy rps %08x\n",\r
2536                         __func__, __LINE__, phy_str, phy_pps, phy_rps);\r
2537 \r
2538                 reg->reg[1] = 0x21;\r
2539                 reg->reg[4] = phy_str;\r
2540                 reg->reg[5] = ((stream_size[testidx]+15)&(~15))+64;\r
2541                 reg->reg[6] = phy_cabac;\r
2542                 reg->reg[7] = testidx?phy_ref:phy_yuv;\r
2543                 reg->reg[42] = phy_pps;\r
2544                 reg->reg[43] = phy_rps;\r
2545                 for (i = 10; i <= 24; i++)\r
2546                         reg->reg[i] = phy_yuv;\r
2547 \r
2548                 mutex_lock(&pservice->lock);\r
2549                 list_add_tail(&reg->status_link, &pservice->waiting);\r
2550                 list_add_tail(&reg->session_link, &session.waiting);\r
2551                 mutex_unlock(&pservice->lock);\r
2552 \r
2553                 printk("%s %d %p\n", __func__, __LINE__, pservice);\r
2554 \r
2555                 /* stuff hardware */\r
2556                 try_set_reg(pservice);\r
2557 \r
2558                 /* wait for result */\r
2559                 ret = wait_event_timeout(session.wait, !list_empty(&session.done), VPU_TIMEOUT_DELAY);\r
2560                 if (!list_empty(&session.done)) {\r
2561                         if (ret < 0)\r
2562                                 pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session.pid, ret);\r
2563                         ret = 0;\r
2564                 } else {\r
2565                         if (unlikely(ret < 0)) {\r
2566                                 pr_err("error: pid %d wait task ret %d\n", session.pid, ret);\r
2567                         } else if (0 == ret) {\r
2568                                 pr_err("error: pid %d wait %d task done timeout\n", session.pid, atomic_read(&session.task_running));\r
2569                                 ret = -ETIMEDOUT;\r
2570                         }\r
2571                 }\r
2572                 if (ret < 0) {\r
2573                         int task_running = atomic_read(&session.task_running);\r
2574                         int n;\r
2575                         mutex_lock(&pservice->lock);\r
2576                         vpu_service_dump(pservice);\r
2577                         if (task_running) {\r
2578                                 atomic_set(&session.task_running, 0);\r
2579                                 atomic_sub(task_running, &pservice->total_running);\r
2580                                 printk("%d task is running but not return, reset hardware...", task_running);\r
2581                                 vpu_reset(pservice);\r
2582                                 printk("done\n");\r
2583                         }\r
2584                         vpu_service_session_clear(pservice, &session);\r
2585                         mutex_unlock(&pservice->lock);\r
2586 \r
2587                         printk("\nDEC Registers:\n");\r
2588                         n = pservice->dec_dev.iosize >> 2;\r
2589                         for (i=0; i<n; i++)\r
2590                                 printk("\tswreg%d = %08X\n", i, readl(pservice->dec_dev.hwregs + i));\r
2591 \r
2592                         pr_err("test index %d failed\n", testidx);\r
2593                         break;\r
2594                 } else {\r
2595                         pr_info("test index %d success\n", testidx);\r
2596 \r
2597                         vpu_reg *reg = list_entry(session.done.next, vpu_reg, session_link);\r
2598 \r
2599                         for (i=0; i<68; i++) {\r
2600                                 if (i % 4 == 0)\r
2601                                         printk("%02d: ", i);\r
2602                                 printk("%08x ", reg->reg[i]);\r
2603                                 if ((i+1) % 4 == 0)\r
2604                                         printk("\n");\r
2605                         }\r
2606 \r
2607                         testidx++;\r
2608                 }\r
2609 \r
2610                 reg_deinit(pservice, reg);\r
2611         }\r
2612 \r
2613         return 0;\r
2614 }\r
2615 \r
2616 #endif\r
2617 \r