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