Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <linux/init.h> |
2 | #include <linux/module.h> | |
3 | #include <linux/kernel.h> | |
4 | #include <linux/types.h> | |
5 | #include <linux/device.h> | |
6 | #include <linux/kdev_t.h> | |
7 | #include <linux/fs.h> | |
8 | #include <linux/cdev.h> | |
9 | #include <linux/platform_device.h> | |
10 | #include <linux/dma-mapping.h> | |
11 | #include <linux/mm_types.h> | |
12 | #include <linux/mm.h> | |
13 | #include <linux/jiffies.h> | |
14 | #include <linux/sched.h> | |
15 | #include <linux/cpumask.h> | |
16 | #include <asm/uaccess.h> | |
17 | #include <asm/page.h> | |
18 | #include <linux/vmalloc.h> | |
19 | #include <linux/interrupt.h> | |
20 | #include <mach/irqs.h> | |
21 | #include <linux/wait.h> | |
22 | #include <linux/proc_fs.h> | |
23 | #include <linux/semaphore.h> | |
24 | #include <mach/dma.h> | |
25 | #include <linux/delay.h> | |
26 | #include <linux/earlysuspend.h> | |
27 | #include "mach/sync_write.h" | |
28 | #include "mach/mt_reg_base.h" | |
29 | #include "mach/mt_clkmgr.h" | |
30 | #ifdef CONFIG_MTK_HIBERNATION | |
31 | #include "mach/mtk_hibernate_dpm.h" | |
32 | #endif | |
33 | ||
34 | #include "videocodec_kernel_driver.h" | |
35 | ||
36 | #include <asm/cacheflush.h> | |
37 | #include <asm/io.h> | |
38 | #include <asm/sizes.h> | |
39 | #include "val_types_private.h" | |
40 | #include "hal_types_private.h" | |
41 | #include "val_api_private.h" | |
42 | #include "val_log.h" | |
43 | #include "drv_api.h" | |
44 | ||
45 | #define VDO_HW_WRITE(ptr,data) mt65xx_reg_sync_writel(data,ptr) | |
46 | #define VDO_HW_READ(ptr) (*((volatile unsigned int * const)(ptr))) | |
47 | ||
48 | #define VCODEC_DEVNAME "Vcodec" | |
49 | #define MT8127_VCODEC_DEV_MAJOR_NUMBER 160 //189 | |
50 | //#define VDEC_USE_L2C | |
51 | ||
52 | static dev_t vcodec_devno = MKDEV(MT8127_VCODEC_DEV_MAJOR_NUMBER,0); | |
53 | static struct cdev *vcodec_cdev; | |
54 | static struct class *vcodec_class = NULL; | |
55 | static struct device *vcodec_device = NULL; | |
56 | ||
57 | static DEFINE_MUTEX(IsOpenedLock); | |
58 | static DEFINE_MUTEX(PWRLock); | |
59 | static DEFINE_MUTEX(VdecHWLock); | |
60 | static DEFINE_MUTEX(VencHWLock); | |
61 | static DEFINE_MUTEX(EncEMILock); | |
62 | static DEFINE_MUTEX(L2CLock); | |
63 | static DEFINE_MUTEX(DecEMILock); | |
64 | static DEFINE_MUTEX(DriverOpenCountLock); | |
65 | static DEFINE_MUTEX(DecHWLockEventTimeoutLock); | |
66 | static DEFINE_MUTEX(EncHWLockEventTimeoutLock); | |
67 | static DEFINE_MUTEX(VdecPWRLock); | |
68 | static DEFINE_MUTEX(VencPWRLock); | |
69 | ||
70 | static DEFINE_SPINLOCK(DecIsrLock); | |
71 | static DEFINE_SPINLOCK(EncIsrLock); | |
72 | static DEFINE_SPINLOCK(LockDecHWCountLock); | |
73 | static DEFINE_SPINLOCK(LockEncHWCountLock); | |
74 | static DEFINE_SPINLOCK(DecISRCountLock); | |
75 | static DEFINE_SPINLOCK(EncISRCountLock); | |
76 | ||
77 | ||
78 | static VAL_EVENT_T DecHWLockEvent; //mutex : HWLockEventTimeoutLock | |
79 | static VAL_EVENT_T EncHWLockEvent; //mutex : HWLockEventTimeoutLock | |
80 | static VAL_EVENT_T DecIsrEvent; //mutex : HWLockEventTimeoutLock | |
81 | static VAL_EVENT_T EncIsrEvent; //mutex : HWLockEventTimeoutLock | |
82 | static int MT8127Driver_Open_Count; //mutex : DriverOpenCountLock | |
83 | static VAL_UINT32_T gu4PWRCounter = 0; //mutex : PWRLock | |
84 | static VAL_UINT32_T gu4EncEMICounter = 0; //mutex : EncEMILock | |
85 | static VAL_UINT32_T gu4DecEMICounter = 0; //mutex : DecEMILock | |
86 | static VAL_UINT32_T gu4L2CCounter = 0; //mutex : L2CLock | |
87 | static VAL_BOOL_T bIsOpened = VAL_FALSE; //mutex : IsOpenedLock | |
88 | static VAL_UINT32_T gu4HwVencIrqStatus = 0; //hardware VENC IRQ status (VP8/H264) | |
89 | ||
90 | static VAL_UINT32_T gu4VdecPWRCounter = 0; //mutex : VdecPWRLock | |
91 | static VAL_UINT32_T gu4VencPWRCounter = 0; //mutex : VencPWRLock | |
92 | ||
93 | ||
94 | static VAL_UINT32_T gu4VdecLockThreadId = 0; | |
95 | ||
96 | //#define MT8127_VCODEC_DEBUG | |
97 | #ifdef MT8127_VCODEC_DEBUG | |
98 | #undef VCODEC_DEBUG | |
99 | #define VCODEC_DEBUG MFV_LOGE | |
100 | #undef MFV_LOGD | |
101 | #define MFV_LOGD MFV_LOGE | |
102 | #else | |
103 | #define VCODEC_DEBUG(...) | |
104 | #undef MFV_LOGD | |
105 | //#define MFV_LOGD MFV_LOGE | |
106 | #define MFV_LOGD(...) | |
107 | #endif | |
108 | ||
109 | // VENC physical base address | |
110 | #undef VENC_BASE | |
111 | #define VENC_BASE 0x15009000 | |
112 | #define VENC_REGION 0x1000 | |
113 | #define VENC_IRQ_STATUS_addr VENC_BASE + 0x05C | |
114 | #define VENC_IRQ_ACK_addr VENC_BASE + 0x060 | |
115 | #define VENC_MP4_IRQ_ACK_addr VENC_BASE + 0x678 | |
116 | #define VENC_MP4_IRQ_STATUS_addr VENC_BASE + 0x67C | |
117 | #define VENC_ZERO_COEF_COUNT_addr VENC_BASE + 0x688 | |
118 | #define VENC_BYTE_COUNT_addr VENC_BASE + 0x680 | |
119 | #define VENC_MP4_IRQ_ENABLE_addr VENC_BASE + 0x668 | |
120 | #define VENC_SW_PAUSE VENC_BASE + 0x0AC | |
121 | #define VENC_SW_HRST_N VENC_BASE + 0x0A8 | |
122 | ||
123 | #define VENC_MP4_STATUS_addr VENC_BASE + 0x664 | |
124 | #define VENC_MP4_MVQP_STATUS_addr VENC_BASE + 0x6E4 | |
125 | ||
126 | #define VENC_IRQ_STATUS_SPS 0x1 | |
127 | #define VENC_IRQ_STATUS_PPS 0x2 | |
128 | #define VENC_IRQ_STATUS_FRM 0x4 | |
129 | #define VENC_IRQ_STATUS_DRAM 0x8 | |
130 | #define VENC_IRQ_STATUS_PAUSE 0x10 | |
131 | #define VENC_IRQ_STATUS_SWITCH 0x20 | |
132 | ||
133 | //#define VENC_PWR_FPGA | |
134 | // Cheng-Jung 20120621 VENC power physical base address (FPGA only, should use API) [ | |
135 | #ifdef VENC_PWR_FPGA | |
136 | #define CLK_CFG_0_addr 0x10000140 | |
137 | #define CLK_CFG_4_addr 0x10000150 | |
138 | #define VENC_PWR_addr 0x10006230 | |
139 | #define VENCSYS_CG_SET_addr 0x15000004 | |
140 | ||
141 | #define PWR_ONS_1_D 3 | |
142 | #define PWR_CKD_1_D 4 | |
143 | #define PWR_ONN_1_D 2 | |
144 | #define PWR_ISO_1_D 1 | |
145 | #define PWR_RST_0_D 0 | |
146 | ||
147 | #define PWR_ON_SEQ_0 ((0x1 << PWR_ONS_1_D) | (0x1 << PWR_CKD_1_D) | (0x1 << PWR_ONN_1_D) | (0x1 << PWR_ISO_1_D) | (0x0 << PWR_RST_0_D)) | |
148 | #define PWR_ON_SEQ_1 ((0x1 << PWR_ONS_1_D) | (0x0 << PWR_CKD_1_D) | (0x1 << PWR_ONN_1_D) | (0x1 << PWR_ISO_1_D) | (0x0 << PWR_RST_0_D)) | |
149 | #define PWR_ON_SEQ_2 ((0x1 << PWR_ONS_1_D) | (0x0 << PWR_CKD_1_D) | (0x1 << PWR_ONN_1_D) | (0x0 << PWR_ISO_1_D) | (0x0 << PWR_RST_0_D)) | |
150 | #define PWR_ON_SEQ_3 ((0x1 << PWR_ONS_1_D) | (0x0 << PWR_CKD_1_D) | (0x1 << PWR_ONN_1_D) | (0x0 << PWR_ISO_1_D) | (0x1 << PWR_RST_0_D)) | |
151 | // ] | |
152 | #endif | |
153 | ||
154 | // VDEC virtual base address | |
155 | #define VDEC_BASE_PHY 0x16000000 | |
156 | #define VDEC_REGION 0x29000 | |
157 | #define VDEC_MISC_BASE VDEC_BASE + 0x0000 | |
158 | #define VDEC_VLD_BASE VDEC_BASE + 0x1000 | |
159 | ||
160 | #define HW_BASE 0x7FFF000 | |
161 | #define HW_REGION 0x2000 | |
162 | ||
163 | #define INFO_BASE_1 0x08000000 | |
164 | #define INFO_REGION_1 0x1000 | |
165 | #define INFO_BASE_2 0x10000000 | |
166 | #define INFO_REGION_2 0x1000 | |
167 | #define INFO_BASE_3 0x10004000 | |
168 | #define INFO_REGION_3 0x1000 | |
169 | ||
170 | int KVA_VENC_IRQ_ACK_ADDR; | |
171 | int KVA_VENC_IRQ_STATUS_ADDR; | |
172 | int KVA_VENC_SW_PAUSE, KVA_VENC_SW_HRST_N; | |
173 | #ifdef VENC_PWR_FPGA | |
174 | // Cheng-Jung 20120621 VENC power physical base address (FPGA only, should use API) [ | |
175 | int KVA_VENC_CLK_CFG_0_ADDR, KVA_VENC_CLK_CFG_4_ADDR, KVA_VENC_PWR_ADDR, KVA_VENCSYS_CG_SET_ADDR; | |
176 | // ] | |
177 | #endif | |
178 | ||
179 | extern unsigned int pmem_user_v2p_video(unsigned int va); | |
180 | #ifdef VDEC_USE_L2C | |
181 | extern int config_L2(int size); | |
182 | #endif | |
183 | ||
184 | void vdec_power_on(void) | |
185 | { | |
186 | mutex_lock(&VdecPWRLock); | |
187 | gu4VdecPWRCounter++; | |
188 | mutex_unlock(&VdecPWRLock); | |
189 | ||
190 | // Central power on | |
191 | enable_clock(MT_CG_DISP0_SMI_COMMON, "VDEC"); | |
192 | enable_clock(MT_CG_VDEC0_VDEC, "VDEC"); | |
193 | enable_clock(MT_CG_VDEC1_LARB, "VDEC"); | |
194 | #ifdef VDEC_USE_L2C | |
195 | enable_clock(MT_CG_INFRA_L2C_SRAM, "VDEC"); | |
196 | #endif | |
197 | if (0x111 != VDO_HW_READ(VDEC_GCON_BASE)) | |
198 | { | |
199 | MFV_LOGE("[MFV][ERROR] Failed to turn VDEC clock on! VDEC_CG = 0x%08x, VDEC_LARB_CG = 0x%08x", VDO_HW_READ(VDEC_GCON_BASE), VDO_HW_READ(VDEC_GCON_BASE + 0x0008)); | |
200 | } | |
201 | } | |
202 | ||
203 | void vdec_power_off(void) | |
204 | { | |
205 | mutex_lock(&VdecPWRLock); | |
206 | if (gu4VdecPWRCounter == 0) | |
207 | { | |
208 | } | |
209 | else | |
210 | { | |
211 | gu4VdecPWRCounter--; | |
212 | // Central power off | |
213 | disable_clock(MT_CG_VDEC0_VDEC, "VDEC"); | |
214 | disable_clock(MT_CG_VDEC1_LARB, "VDEC"); | |
215 | disable_clock(MT_CG_DISP0_SMI_COMMON, "VDEC"); | |
216 | #ifdef VDEC_USE_L2C | |
217 | disable_clock(MT_CG_INFRA_L2C_SRAM, "VDEC"); | |
218 | #endif | |
219 | } | |
220 | mutex_unlock(&VdecPWRLock); | |
221 | } | |
222 | ||
223 | void venc_power_on(void) | |
224 | { | |
225 | mutex_lock(&VencPWRLock); | |
226 | gu4VencPWRCounter++; | |
227 | mutex_unlock(&VencPWRLock); | |
228 | ||
229 | MFV_LOGD("venc_power_on +\n"); | |
230 | #ifdef VENC_PWR_FPGA | |
231 | // Cheng-Jung 20120621 VENC power physical base address (FPGA only, should use API) [ | |
232 | //VDO_HW_WRITE(KVA_VENC_CLK_CFG_0_ADDR, ((VDO_HW_READ(KVA_VENC_CLK_CFG_0_ADDR) & 0xfffffff8) | 0x00000001)); | |
233 | //VDO_HW_WRITE(KVA_VENC_CLK_CFG_0_ADDR, ((VDO_HW_READ(KVA_VENC_CLK_CFG_0_ADDR) & 0xfffff8ff) | 0x00000100)); | |
234 | //VDO_HW_WRITE(KVA_VENC_CLK_CFG_4_ADDR, ((VDO_HW_READ(KVA_VENC_CLK_CFG_4_ADDR) & 0xffff00ff) | 0x00000600)); | |
235 | ||
236 | // MTCMOS on | |
237 | VDO_HW_WRITE(KVA_VENC_PWR_ADDR, ((VDO_HW_READ(KVA_VENC_PWR_ADDR) & 0xffffffc0) | PWR_ON_SEQ_0)); | |
238 | VDO_HW_WRITE(KVA_VENC_PWR_ADDR, ((VDO_HW_READ(KVA_VENC_PWR_ADDR) & 0xffffffc0) | PWR_ON_SEQ_1)); | |
239 | VDO_HW_WRITE(KVA_VENC_PWR_ADDR, ((VDO_HW_READ(KVA_VENC_PWR_ADDR) & 0xffffffc0) | PWR_ON_SEQ_2)); | |
240 | VDO_HW_WRITE(KVA_VENC_PWR_ADDR, ((VDO_HW_READ(KVA_VENC_PWR_ADDR) & 0xffffffc0) | PWR_ON_SEQ_3)); | |
241 | ||
242 | // CG (clock gate) on | |
243 | VDO_HW_WRITE(KVA_VENCSYS_CG_SET_ADDR, 0x00000001); | |
244 | // ] | |
245 | #else | |
246 | enable_clock(MT_CG_DISP0_SMI_COMMON, "VENC"); | |
247 | enable_clock(MT_CG_IMAGE_VENC_JPENC, "VENC"); | |
248 | enable_clock(MT_CG_IMAGE_LARB2_SMI, "VENC"); | |
249 | #endif | |
250 | ||
251 | MFV_LOGD("venc_power_on -\n"); | |
252 | } | |
253 | ||
254 | void venc_power_off(void) | |
255 | { | |
256 | mutex_lock(&VencPWRLock); | |
257 | if (gu4VencPWRCounter == 0) | |
258 | { | |
259 | } | |
260 | else | |
261 | { | |
262 | gu4VencPWRCounter--; | |
263 | MFV_LOGD("venc_power_off +\n"); | |
264 | disable_clock(MT_CG_IMAGE_VENC_JPENC, "VENC"); | |
265 | disable_clock(MT_CG_IMAGE_LARB2_SMI, "VENC"); | |
266 | disable_clock(MT_CG_DISP0_SMI_COMMON, "VENC"); | |
267 | MFV_LOGD("venc_power_off -\n"); | |
268 | } | |
269 | mutex_unlock(&VencPWRLock); | |
270 | } | |
271 | ||
272 | void dec_isr(void) | |
273 | { | |
274 | VAL_RESULT_T eValRet; | |
275 | unsigned long ulFlags, ulFlagsISR, ulFlagsLockHW; | |
276 | ||
277 | VAL_UINT32_T u4TempDecISRCount = 0; | |
278 | VAL_UINT32_T u4TempLockDecHWCount = 0; | |
279 | VAL_UINT32_T u4CgStatus = 0; | |
280 | VAL_UINT32_T u4DecDoneStatus = 0; | |
281 | ||
282 | u4CgStatus = VDO_HW_READ(0xF6000000); | |
283 | if ((u4CgStatus & 0x10) != 0) | |
284 | { | |
285 | MFV_LOGE("[MFV][ERROR] DEC ISR, VDEC active is not 0x0 (0x%08x)", u4CgStatus); | |
286 | return; | |
287 | } | |
288 | ||
289 | u4DecDoneStatus = VDO_HW_READ(0xF60200A4); | |
290 | if ((u4DecDoneStatus & (0x1 << 16)) != 0x10000) | |
291 | { | |
292 | MFV_LOGE("[MFV][ERROR] DEC ISR, Decode done status is not 0x1 (0x%08x)", u4DecDoneStatus); | |
293 | return; | |
294 | } | |
295 | ||
296 | ||
297 | spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); | |
298 | gu4DecISRCount++; | |
299 | u4TempDecISRCount = gu4DecISRCount; | |
300 | spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); | |
301 | ||
302 | spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); | |
303 | u4TempLockDecHWCount = gu4LockDecHWCount; | |
304 | spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); | |
305 | ||
306 | if (u4TempDecISRCount != u4TempLockDecHWCount) | |
307 | { | |
308 | //MFV_LOGE("[INFO] Dec ISRCount: 0x%x, LockHWCount:0x%x\n", u4TempDecISRCount, u4TempLockDecHWCount); | |
309 | } | |
310 | ||
311 | // Clear interrupt | |
312 | VDO_HW_WRITE(VDEC_MISC_BASE+41*4, VDO_HW_READ(VDEC_MISC_BASE + 41*4) | 0x11); | |
313 | VDO_HW_WRITE(VDEC_MISC_BASE+41*4, VDO_HW_READ(VDEC_MISC_BASE + 41*4) & ~0x10); | |
314 | ||
315 | ||
316 | spin_lock_irqsave(&DecIsrLock, ulFlags); | |
317 | eValRet = eVideoSetEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); | |
318 | if(VAL_RESULT_NO_ERROR != eValRet) | |
319 | { | |
320 | MFV_LOGE("[MFV][ERROR] ISR set DecIsrEvent error\n"); | |
321 | } | |
322 | spin_unlock_irqrestore(&DecIsrLock, ulFlags); | |
323 | ||
324 | return; | |
325 | } | |
326 | ||
327 | ||
328 | void enc_isr(void) | |
329 | { | |
330 | VAL_RESULT_T eValRet; | |
331 | unsigned long ulFlagsISR, ulFlagsLockHW; | |
332 | ||
333 | ||
334 | VAL_UINT32_T u4TempEncISRCount = 0; | |
335 | VAL_UINT32_T u4TempLockEncHWCount = 0; | |
336 | //---------------------- | |
337 | ||
338 | spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); | |
339 | gu4EncISRCount++; | |
340 | u4TempEncISRCount = gu4EncISRCount; | |
341 | spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); | |
342 | ||
343 | spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); | |
344 | u4TempLockEncHWCount = gu4LockEncHWCount; | |
345 | spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); | |
346 | ||
347 | if (u4TempEncISRCount != u4TempLockEncHWCount) | |
348 | { | |
349 | //MFV_LOGE("[INFO] Enc ISRCount: 0x%x, LockHWCount:0x%x\n", u4TempEncISRCount, u4TempLockEncHWCount); | |
350 | } | |
351 | ||
352 | if (grVcodecEncHWLock.pvHandle == 0) | |
353 | { | |
354 | MFV_LOGE("[ERROR] NO one Lock Enc HW, please check!!\n"); | |
355 | ||
356 | // Clear all status | |
357 | //VDO_HW_WRITE(KVA_VENC_MP4_IRQ_ACK_ADDR, 1); | |
358 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PAUSE); | |
359 | //VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM_VP8); | |
360 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SWITCH); | |
361 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM); | |
362 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SPS); | |
363 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PPS); | |
364 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_FRM); | |
365 | return; | |
366 | } | |
367 | ||
368 | if (grVcodecEncHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) // hardwire | |
369 | { | |
370 | gu4HwVencIrqStatus = VDO_HW_READ(KVA_VENC_IRQ_STATUS_ADDR); | |
371 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_PAUSE) | |
372 | { | |
373 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PAUSE); | |
374 | } | |
375 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_SWITCH) | |
376 | { | |
377 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SWITCH); | |
378 | } | |
379 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_DRAM) | |
380 | { | |
381 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_DRAM); | |
382 | } | |
383 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_SPS) | |
384 | { | |
385 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_SPS); | |
386 | } | |
387 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_PPS) | |
388 | { | |
389 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_PPS); | |
390 | } | |
391 | if (gu4HwVencIrqStatus & VENC_IRQ_STATUS_FRM) | |
392 | { | |
393 | VDO_HW_WRITE(KVA_VENC_IRQ_ACK_ADDR, VENC_IRQ_STATUS_FRM); | |
394 | } | |
395 | } | |
396 | else | |
397 | { | |
398 | MFV_LOGE("Invalid lock holder driver type = %d\n", grVcodecEncHWLock.eDriverType); | |
399 | } | |
400 | ||
401 | eValRet = eVideoSetEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
402 | if(VAL_RESULT_NO_ERROR != eValRet) | |
403 | { | |
404 | MFV_LOGE("[MFV][ERROR] ISR set EncIsrEvent error\n"); | |
405 | } | |
406 | } | |
407 | ||
408 | static irqreturn_t video_intr_dlr(int irq, void *dev_id) | |
409 | { | |
410 | dec_isr(); | |
411 | return IRQ_HANDLED; | |
412 | } | |
413 | ||
414 | static irqreturn_t video_intr_dlr2(int irq, void *dev_id) | |
415 | { | |
416 | enc_isr(); | |
417 | return IRQ_HANDLED; | |
418 | } | |
419 | ||
420 | ||
421 | static long vcodec_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |
422 | { | |
423 | VAL_INT32_T ret; | |
424 | VAL_UINT8_T *user_data_addr; | |
425 | VAL_RESULT_T eValRet; | |
426 | VAL_UINT32_T ulFlags, ulFlagsLockHW; | |
427 | VAL_HW_LOCK_T rHWLock; | |
428 | VAL_BOOL_T bLockedHW = VAL_FALSE; | |
429 | VAL_UINT32_T FirstUseDecHW = 0; | |
430 | VAL_UINT32_T FirstUseEncHW = 0; | |
431 | VAL_TIME_T rCurTime; | |
432 | VAL_UINT32_T u4TimeInterval; | |
433 | VAL_ISR_T val_isr; | |
434 | VAL_VCODEC_CORE_LOADING_T rTempCoreLoading; | |
435 | VAL_VCODEC_CPU_OPP_LIMIT_T rCpuOppLimit; | |
436 | VAL_INT32_T temp_nr_cpu_ids; | |
437 | VAL_POWER_T rPowerParam; | |
438 | #if 0 | |
439 | VCODEC_DRV_CMD_QUEUE_T rDrvCmdQueue; | |
440 | P_VCODEC_DRV_CMD_T cmd_queue = VAL_NULL; | |
441 | VAL_UINT32_T u4Size, uValue, nCount; | |
442 | #endif | |
443 | ||
444 | switch(cmd) { | |
445 | case VCODEC_SET_THREAD_ID: | |
446 | MFV_LOGE("[MT8127] VCODEC_SET_THREAD_ID [EMPTY] + tid = %d\n", current->pid); | |
447 | ||
448 | MFV_LOGE("[MT8127] VCODEC_SET_THREAD_ID [EMPTY] - tid = %d\n", current->pid); | |
449 | break; | |
450 | ||
451 | case VCODEC_ALLOC_NON_CACHE_BUFFER: | |
452 | MFV_LOGE("[MT8127][M4U]! VCODEC_ALLOC_NON_CACHE_BUFFER [EMPTY] + tid = %d\n", current->pid); | |
453 | ||
454 | MFV_LOGE("[MT8127][M4U]! VCODEC_ALLOC_NON_CACHE_BUFFER [EMPTY] - tid = %d\n", current->pid); | |
455 | break; | |
456 | ||
457 | case VCODEC_FREE_NON_CACHE_BUFFER: | |
458 | MFV_LOGE("[MT8127][M4U]! VCODEC_FREE_NON_CACHE_BUFFER [EMPTY] + tid = %d\n", current->pid); | |
459 | ||
460 | MFV_LOGE("[MT8127][M4U]! VCODEC_FREE_NON_CACHE_BUFFER [EMPTY] - tid = %d\n", current->pid); | |
461 | break; | |
462 | ||
463 | case VCODEC_INC_DEC_EMI_USER: | |
464 | MFV_LOGD("[MT8127] VCODEC_INC_DEC_EMI_USER + tid = %d\n", current->pid); | |
465 | ||
466 | mutex_lock(&DecEMILock); | |
467 | gu4DecEMICounter++; | |
468 | MFV_LOGE("DEC_EMI_USER = %d\n", gu4DecEMICounter); | |
469 | user_data_addr = (VAL_UINT8_T *)arg; | |
470 | ret = copy_to_user(user_data_addr, &gu4DecEMICounter, sizeof(VAL_UINT32_T)); | |
471 | if (ret) | |
472 | { | |
473 | MFV_LOGE("[ERROR] VCODEC_INC_DEC_EMI_USER, copy_to_user failed: %d\n", ret); | |
474 | mutex_unlock(&DecEMILock); | |
475 | return -EFAULT; | |
476 | } | |
477 | mutex_unlock(&DecEMILock); | |
478 | ||
479 | MFV_LOGD("[MT8127] VCODEC_INC_DEC_EMI_USER - tid = %d\n", current->pid); | |
480 | break; | |
481 | ||
482 | case VCODEC_DEC_DEC_EMI_USER: | |
483 | MFV_LOGD("[MT8127] VCODEC_DEC_DEC_EMI_USER + tid = %d\n", current->pid); | |
484 | ||
485 | mutex_lock(&DecEMILock); | |
486 | gu4DecEMICounter--; | |
487 | MFV_LOGE("DEC_EMI_USER = %d\n", gu4DecEMICounter); | |
488 | user_data_addr = (VAL_UINT8_T *)arg; | |
489 | ret = copy_to_user(user_data_addr, &gu4DecEMICounter, sizeof(VAL_UINT32_T)); | |
490 | if (ret) | |
491 | { | |
492 | MFV_LOGE("[ERROR] VCODEC_DEC_DEC_EMI_USER, copy_to_user failed: %d\n", ret); | |
493 | mutex_unlock(&DecEMILock); | |
494 | return -EFAULT; | |
495 | } | |
496 | mutex_unlock(&DecEMILock); | |
497 | ||
498 | MFV_LOGD("[MT8127] VCODEC_DEC_DEC_EMI_USER - tid = %d\n", current->pid); | |
499 | break; | |
500 | ||
501 | case VCODEC_INC_ENC_EMI_USER: | |
502 | MFV_LOGD("[MT8127] VCODEC_INC_ENC_EMI_USER + tid = %d\n", current->pid); | |
503 | ||
504 | mutex_lock(&EncEMILock); | |
505 | gu4EncEMICounter++; | |
506 | MFV_LOGE("ENC_EMI_USER = %d\n", gu4EncEMICounter); | |
507 | user_data_addr = (VAL_UINT8_T *)arg; | |
508 | ret = copy_to_user(user_data_addr, &gu4EncEMICounter, sizeof(VAL_UINT32_T)); | |
509 | if (ret) { | |
510 | MFV_LOGE("[ERROR] VCODEC_INC_ENC_EMI_USER, copy_to_user failed: %d\n", ret); | |
511 | mutex_unlock(&EncEMILock); | |
512 | return -EFAULT; | |
513 | } | |
514 | mutex_unlock(&EncEMILock); | |
515 | ||
516 | MFV_LOGD("[MT8127] VCODEC_INC_ENC_EMI_USER - tid = %d\n", current->pid); | |
517 | break; | |
518 | ||
519 | case VCODEC_DEC_ENC_EMI_USER: | |
520 | MFV_LOGD("[MT8127] VCODEC_DEC_ENC_EMI_USER + tid = %d\n", current->pid); | |
521 | ||
522 | mutex_lock(&EncEMILock); | |
523 | gu4EncEMICounter--; | |
524 | MFV_LOGE("ENC_EMI_USER = %d\n", gu4EncEMICounter); | |
525 | user_data_addr = (VAL_UINT8_T *)arg; | |
526 | ret = copy_to_user(user_data_addr, &gu4EncEMICounter, sizeof(VAL_UINT32_T)); | |
527 | if (ret) { | |
528 | MFV_LOGE("[ERROR] VCODEC_DEC_ENC_EMI_USER, copy_to_user failed: %d\n", ret); | |
529 | mutex_unlock(&EncEMILock); | |
530 | return -EFAULT; | |
531 | } | |
532 | mutex_unlock(&EncEMILock); | |
533 | ||
534 | MFV_LOGD("[MT8127] VCODEC_DEC_ENC_EMI_USER - tid = %d\n", current->pid); | |
535 | break; | |
536 | ||
537 | case VCODEC_LOCKHW: | |
538 | MFV_LOGD("[MT8127] VCODEC_LOCKHW + tid = %d\n", current->pid); | |
539 | user_data_addr = (VAL_UINT8_T *)arg; | |
540 | ret = copy_from_user(&rHWLock, user_data_addr, sizeof(VAL_HW_LOCK_T)); | |
541 | if (ret) { | |
542 | MFV_LOGE("[ERROR] VCODEC_LOCKHW, copy_from_user failed: %d\n", ret); | |
543 | return -EFAULT; | |
544 | } | |
545 | ||
546 | MFV_LOGD("LOCKHW eDriverType = %d\n", rHWLock.eDriverType); | |
547 | eValRet = VAL_RESULT_INVALID_ISR; | |
548 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || | |
549 | rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || | |
550 | rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_DEC) | |
551 | { | |
552 | while (bLockedHW == VAL_FALSE) | |
553 | { | |
554 | mutex_lock(&DecHWLockEventTimeoutLock); | |
555 | if (DecHWLockEvent.u4TimeoutMs == 1) { | |
556 | MFV_LOGE("[NOT ERROR][VCODEC_LOCKHW] First Use Dec HW!!\n"); | |
557 | FirstUseDecHW = 1; | |
558 | } | |
559 | else { | |
560 | FirstUseDecHW = 0; | |
561 | } | |
562 | mutex_unlock(&DecHWLockEventTimeoutLock); | |
563 | if (FirstUseDecHW == 1) | |
564 | { | |
565 | eValRet = eVideoWaitEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); | |
566 | } | |
567 | mutex_lock(&DecHWLockEventTimeoutLock); | |
568 | if (DecHWLockEvent.u4TimeoutMs != 1000) | |
569 | { | |
570 | DecHWLockEvent.u4TimeoutMs = 1000; | |
571 | FirstUseDecHW = 1; | |
572 | } | |
573 | else | |
574 | { | |
575 | FirstUseDecHW = 0; | |
576 | } | |
577 | mutex_unlock(&DecHWLockEventTimeoutLock); | |
578 | ||
579 | mutex_lock(&VdecHWLock); | |
580 | // one process try to lock twice | |
581 | if (grVcodecDecHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle)) { | |
582 | MFV_LOGE("[WARNING] one decoder instance try to lock twice, may cause lock HW timeout!! instance = 0x%x, CurrentTID = %d\n", | |
583 | grVcodecDecHWLock.pvHandle, current->pid); | |
584 | } | |
585 | mutex_unlock(&VdecHWLock); | |
586 | ||
587 | if (FirstUseDecHW == 0) { | |
588 | MFV_LOGD("Not first time use HW, timeout = %d\n", DecHWLockEvent.u4TimeoutMs); | |
589 | eValRet = eVideoWaitEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); | |
590 | } | |
591 | ||
592 | if (VAL_RESULT_INVALID_ISR == eValRet) { | |
593 | MFV_LOGE("[ERROR][VCODEC_LOCKHW] DecHWLockEvent TimeOut, CurrentTID = %d\n", current->pid); | |
594 | if (FirstUseDecHW != 1) { | |
595 | mutex_lock(&VdecHWLock); | |
596 | if (grVcodecDecHWLock.pvHandle == 0) { | |
597 | MFV_LOGE("[WARNING] maybe mediaserver restart before, please check!!\n"); | |
598 | } | |
599 | else { | |
600 | MFV_LOGE("[WARNING] someone use HW, and check timeout value!!\n"); | |
601 | } | |
602 | mutex_unlock(&VdecHWLock); | |
603 | } | |
604 | } | |
605 | else if (VAL_RESULT_RESTARTSYS == eValRet) | |
606 | { | |
607 | MFV_LOGE("[WARNING] VAL_RESULT_RESTARTSYS return when HWLock!!\n"); | |
608 | return -ERESTARTSYS; | |
609 | } | |
610 | ||
611 | mutex_lock(&VdecHWLock); | |
612 | if (grVcodecDecHWLock.pvHandle == 0) // No one holds dec hw lock now | |
613 | { | |
614 | gu4VdecLockThreadId = current->pid; | |
615 | grVcodecDecHWLock.pvHandle = (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle); | |
616 | grVcodecDecHWLock.eDriverType = rHWLock.eDriverType; | |
617 | eVideoGetTimeOfDay(&grVcodecDecHWLock.rLockedTime, sizeof(VAL_TIME_T)); | |
618 | ||
619 | MFV_LOGD("No process use dec HW, so current process can use HW\n"); | |
620 | MFV_LOGD("LockInstance = 0x%x CurrentTID = %d, rLockedTime(s, us) = %d, %d\n", | |
621 | grVcodecDecHWLock.pvHandle, current->pid, grVcodecDecHWLock.rLockedTime.u4Sec, grVcodecDecHWLock.rLockedTime.u4uSec); | |
622 | ||
623 | bLockedHW = VAL_TRUE; | |
624 | if (VAL_RESULT_INVALID_ISR == eValRet && FirstUseDecHW != 1) { | |
625 | MFV_LOGE("[WARNING] reset power/irq when HWLock!!\n"); | |
626 | vdec_power_off(); | |
627 | disable_irq(MT_VDEC_IRQ_ID); | |
628 | } | |
629 | vdec_power_on(); | |
630 | enable_irq(MT_VDEC_IRQ_ID); | |
631 | } | |
632 | else // Another one holding dec hw now | |
633 | { | |
634 | MFV_LOGE("[NOT ERROR][VCODEC_LOCKHW] E\n"); | |
635 | eVideoGetTimeOfDay(&rCurTime, sizeof(VAL_TIME_T)); | |
636 | u4TimeInterval = (((((rCurTime.u4Sec - grVcodecDecHWLock.rLockedTime.u4Sec) * 1000000) + rCurTime.u4uSec) | |
637 | - grVcodecDecHWLock.rLockedTime.u4uSec) / 1000); | |
638 | ||
639 | MFV_LOGD("someone use dec HW, and check timeout value\n"); | |
640 | MFV_LOGD("Instance = 0x%x CurrentTID = %d, TimeInterval(ms) = %d, TimeOutValue(ms)) = %d\n", | |
641 | grVcodecDecHWLock.pvHandle, current->pid, u4TimeInterval, rHWLock.u4TimeoutMs); | |
642 | ||
643 | MFV_LOGD("Instance = 0x%x, CurrentTID = %d, rLockedTime(s, us) = %d, %d, rCurTime(s, us) = %d, %d\n", | |
644 | grVcodecDecHWLock.pvHandle, current->pid, | |
645 | grVcodecDecHWLock.rLockedTime.u4Sec, grVcodecDecHWLock.rLockedTime.u4uSec, | |
646 | rCurTime.u4Sec, rCurTime.u4uSec | |
647 | ); | |
648 | ||
649 | // 2012/12/16. Cheng-Jung Never steal hardware lock | |
650 | if (0) | |
651 | //if (u4TimeInterval >= rHWLock.u4TimeoutMs) | |
652 | { | |
653 | grVcodecDecHWLock.pvHandle = (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle); | |
654 | grVcodecDecHWLock.eDriverType = rHWLock.eDriverType; | |
655 | eVideoGetTimeOfDay(&grVcodecDecHWLock.rLockedTime, sizeof(VAL_TIME_T)); | |
656 | bLockedHW = VAL_TRUE; | |
657 | vdec_power_on(); | |
658 | // TODO: Error handling, VDEC break, reset? | |
659 | } | |
660 | } | |
661 | mutex_unlock(&VdecHWLock); | |
662 | spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); | |
663 | gu4LockDecHWCount++; | |
664 | spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); | |
665 | } | |
666 | } | |
667 | else if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || | |
668 | rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) | |
669 | { | |
670 | VAL_UINT32_T u4VencLockTimeOutCount = 0; | |
671 | while (bLockedHW == VAL_FALSE) | |
672 | { | |
673 | // Early break for JPEG VENC | |
674 | if (rHWLock.u4TimeoutMs == 0) | |
675 | { | |
676 | if (grVcodecEncHWLock.pvHandle != 0) | |
677 | { | |
678 | break; | |
679 | } | |
680 | } | |
681 | ||
682 | // Wait to acquire Enc HW lock | |
683 | mutex_lock(&EncHWLockEventTimeoutLock); | |
684 | if (EncHWLockEvent.u4TimeoutMs == 1) { | |
685 | MFV_LOGE("[NOT ERROR][VCODEC_LOCKHW] First Use Enc HW %d!!\n", rHWLock.eDriverType); | |
686 | FirstUseEncHW = 1; | |
687 | } | |
688 | else { | |
689 | FirstUseEncHW = 0; | |
690 | } | |
691 | MFV_LOGD("[VCODEC_LOCKHW] ENC Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
692 | mutex_unlock(&EncHWLockEventTimeoutLock); | |
693 | if (FirstUseEncHW == 1) | |
694 | { | |
695 | eValRet = eVideoWaitEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); | |
696 | MFV_LOGD("[VCODEC_LOCKHW] [%d] Use Enc HW, wait event 1, ret[%d]!!\n", rHWLock.eDriverType,eValRet); | |
697 | } | |
698 | //MFV_LOGD("[VCODEC_LOCKHW] ENC Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
699 | ||
700 | mutex_lock(&EncHWLockEventTimeoutLock); | |
701 | //MFV_LOGD("[VCODEC_LOCKHW] ENC Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
702 | ||
703 | if (EncHWLockEvent.u4TimeoutMs == 1) | |
704 | { | |
705 | EncHWLockEvent.u4TimeoutMs = 1000; | |
706 | FirstUseEncHW = 1; | |
707 | } | |
708 | else | |
709 | { | |
710 | FirstUseEncHW = 0; | |
711 | if (rHWLock.u4TimeoutMs == 0) | |
712 | { | |
713 | EncHWLockEvent.u4TimeoutMs = 0; // No wait | |
714 | } | |
715 | else | |
716 | { | |
717 | EncHWLockEvent.u4TimeoutMs = 1000; // Wait indefinitely | |
718 | } | |
719 | } | |
720 | //MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
721 | ||
722 | mutex_unlock(&EncHWLockEventTimeoutLock); | |
723 | //MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
724 | ||
725 | mutex_lock(&VencHWLock); | |
726 | // one process try to lock twice | |
727 | if (grVcodecEncHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle)) { | |
728 | MFV_LOGE("[WARNING] [VCODEC_LOCKHW] one encoder instance try to lock twice, may cause lock HW timeout!! instance = 0x%x, CurrentTID = %d, type:%d\n", | |
729 | grVcodecEncHWLock.pvHandle, current->pid, rHWLock.eDriverType); | |
730 | } | |
731 | //MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
732 | ||
733 | mutex_unlock(&VencHWLock); | |
734 | //MFV_LOGD("[VCODEC_LOCKHW] First[%d] Use Enc HW %d,line %d!!\n", FirstUseEncHW,rHWLock.eDriverType,__LINE__); | |
735 | ||
736 | if (FirstUseEncHW == 0) { | |
737 | eValRet = eVideoWaitEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); | |
738 | MFV_LOGD("[VCODEC_LOCKHW] [%d] Use Enc HW, wait[%d] event 2, ret[%d]!!\n", rHWLock.eDriverType, EncHWLockEvent.u4TimeoutMs, eValRet); | |
739 | } | |
740 | MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
741 | ||
742 | if (VAL_RESULT_INVALID_ISR == eValRet) { | |
743 | MFV_LOGE("[ERROR][VCODEC_LOCKHW] First[%d] TimeOut, CurrentTID = %d,line %d\n", FirstUseEncHW, current->pid, __LINE__); | |
744 | if (FirstUseEncHW != 1) { | |
745 | mutex_lock(&VencHWLock); | |
746 | if (grVcodecEncHWLock.pvHandle == 0) { | |
747 | MFV_LOGE("[WARNING] VCODEC_LOCKHW maybe mediaserver restart before, please check!!\n"); | |
748 | } | |
749 | else { | |
750 | MFV_LOGE("[WARNING] VCODEC_LOCKHW someone use HW, and check timeout value!! %d\n", u4VencLockTimeOutCount); | |
751 | ++u4VencLockTimeOutCount; | |
752 | if (u4VencLockTimeOutCount > 30) | |
753 | { | |
754 | MFV_LOGE("VCODEC_LOCKHW - ID %d fail, someone locked HW time out more than 30 times %x, %x, %x, type:%d\n", current->pid, grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), rHWLock.pvHandle, rHWLock.eDriverType); | |
755 | mutex_unlock(&VencHWLock); | |
756 | return -EFAULT; | |
757 | } | |
758 | ||
759 | if (rHWLock.u4TimeoutMs == 0) | |
760 | { | |
761 | MFV_LOGE("VCODEC_LOCKHW - ID %d fail, someone locked HW already %x, %x, %x, type:%d\n", current->pid, grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), rHWLock.pvHandle, rHWLock.eDriverType); | |
762 | mutex_unlock(&VencHWLock); | |
763 | return -EFAULT; | |
764 | } | |
765 | } | |
766 | mutex_unlock(&VencHWLock); | |
767 | } | |
768 | } | |
769 | else if (VAL_RESULT_RESTARTSYS == eValRet) | |
770 | { | |
771 | MFV_LOGD("[ERROR][VCODEC_LOCKHW] VAL_RESULT_RESTARTSYS Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
772 | return -ERESTARTSYS; | |
773 | } | |
774 | //MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
775 | ||
776 | mutex_lock(&VencHWLock); | |
777 | MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
778 | ||
779 | if (grVcodecEncHWLock.pvHandle == 0) //No process use HW, so current process can use HW | |
780 | { | |
781 | //MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Use Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
782 | ||
783 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || | |
784 | rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) | |
785 | { | |
786 | grVcodecEncHWLock.pvHandle = (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle); | |
787 | MFV_LOGD("[VCODEC_LOCKHW] No process use HW, so current process can use HW, handle = 0x%x\n", grVcodecEncHWLock.pvHandle); | |
788 | grVcodecEncHWLock.eDriverType = rHWLock.eDriverType; | |
789 | eVideoGetTimeOfDay(&grVcodecEncHWLock.rLockedTime, sizeof(VAL_TIME_T)); | |
790 | ||
791 | MFV_LOGD("VCODEC_LOCKHW No process use HW, so current process can use HW\n"); | |
792 | MFV_LOGD("VCODEC_LOCKHW LockInstance = 0x%x CurrentTID = %d, rLockedTime(s, us) = %d, %d\n", | |
793 | grVcodecEncHWLock.pvHandle, current->pid, grVcodecEncHWLock.rLockedTime.u4Sec, grVcodecEncHWLock.rLockedTime.u4uSec); | |
794 | ||
795 | bLockedHW = VAL_TRUE; | |
796 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
797 | { | |
798 | venc_power_on(); | |
799 | } | |
800 | #ifdef MTK_SEC_VIDEO_PATH_SUPPORT | |
801 | MFV_LOGD("[VCODEC_LOCKHW] rHWLock.bSecureInst 0x%x\n", rHWLock.bSecureInst); | |
802 | if (rHWLock.bSecureInst == VAL_FALSE) | |
803 | { | |
804 | MFV_LOGE("[VCODEC_LOCKHW] Request IR by type 0x%x\n", rHWLock.eDriverType); | |
805 | if (request_irq(MT_VENC_IRQ_ID , (irq_handler_t)video_intr_dlr2, IRQF_TRIGGER_LOW, VCODEC_DEVNAME, NULL) < 0) | |
806 | { | |
807 | MFV_LOGE("[VCODEC_LOCKHW] ENC [MFV_DEBUG][ERROR] error to request enc irq\n"); | |
808 | } | |
809 | else | |
810 | { | |
811 | MFV_LOGD("[VCODEC_LOCKHW] ENC [MFV_DEBUG] success to request enc irq\n"); | |
812 | } | |
813 | //enable_irq(MT_VDEC_IRQ_ID); | |
814 | } | |
815 | #else | |
816 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
817 | { | |
818 | venc_power_on(); | |
819 | enable_irq(MT_VENC_IRQ_ID); | |
820 | } | |
821 | #endif | |
822 | } | |
823 | MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
824 | ||
825 | } | |
826 | else //someone use HW, and check timeout value | |
827 | { | |
828 | MFV_LOGD("[VCODEC_LOCKHW] LOCK hW Enc HW %d,line %d!!\n", rHWLock.eDriverType,__LINE__); | |
829 | ||
830 | if (rHWLock.u4TimeoutMs == 0) | |
831 | { | |
832 | bLockedHW = VAL_FALSE; | |
833 | mutex_unlock(&VencHWLock); | |
834 | break; | |
835 | } | |
836 | ||
837 | eVideoGetTimeOfDay(&rCurTime, sizeof(VAL_TIME_T)); | |
838 | u4TimeInterval = (((((rCurTime.u4Sec - grVcodecEncHWLock.rLockedTime.u4Sec) * 1000000) + rCurTime.u4uSec) | |
839 | - grVcodecEncHWLock.rLockedTime.u4uSec) / 1000); | |
840 | ||
841 | MFV_LOGD("VCODEC_LOCKHW someone use enc HW, and check timeout value\n"); | |
842 | MFV_LOGD("VCODEC_LOCKHW LockInstance = 0x%x, CurrentInstance = 0x%x, CurrentTID = %d, TimeInterval(ms) = %d, TimeOutValue(ms)) = %d\n", | |
843 | grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), current->pid, u4TimeInterval, rHWLock.u4TimeoutMs); | |
844 | ||
845 | MFV_LOGD("VCODEC_LOCKHW LockInstance = 0x%x, CurrentInstance = 0x%x, CurrentTID = %d, rLockedTime(s, us) = %d, %d, rCurTime(s, us) = %d, %d\n", | |
846 | grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), current->pid, | |
847 | grVcodecEncHWLock.rLockedTime.u4Sec, grVcodecEncHWLock.rLockedTime.u4uSec, | |
848 | rCurTime.u4Sec, rCurTime.u4uSec | |
849 | ); | |
850 | ||
851 | // 2013/04/10. Cheng-Jung Never steal hardware lock | |
852 | if (0) | |
853 | //if (u4TimeInterval >= rHWLock.u4TimeoutMs) | |
854 | { | |
855 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || | |
856 | rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) | |
857 | { | |
858 | grVcodecEncHWLock.pvHandle = (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle); | |
859 | grVcodecEncHWLock.eDriverType = rHWLock.eDriverType; | |
860 | eVideoGetTimeOfDay(&grVcodecEncHWLock.rLockedTime, sizeof(VAL_TIME_T)); | |
861 | ||
862 | MFV_LOGD(" VCODEC_LOCKHW LockInstance = 0x%x, CurrentTID = %d, rLockedTime(s, us) = %d, %d\n", | |
863 | grVcodecEncHWLock.pvHandle, current->pid, grVcodecEncHWLock.rLockedTime.u4Sec, grVcodecEncHWLock.rLockedTime.u4uSec); | |
864 | ||
865 | bLockedHW = VAL_TRUE; | |
866 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
867 | { | |
868 | venc_power_on(); | |
869 | } | |
870 | } | |
871 | } | |
872 | } | |
873 | ||
874 | if (VAL_TRUE == bLockedHW) | |
875 | { | |
876 | MFV_LOGE(" VCODEC_LOCKHW Lock ok grVcodecEncHWLock.pvHandle = 0x%x, va:%x, type:%d", grVcodecEncHWLock.pvHandle, (unsigned int)rHWLock.pvHandle, rHWLock.eDriverType); | |
877 | } | |
878 | mutex_unlock(&VencHWLock); | |
879 | } | |
880 | ||
881 | if (VAL_FALSE == bLockedHW) | |
882 | { | |
883 | MFV_LOGE("VCODEC_LOCKHW - ID %d fail, someone locked HW already , %x, %x, %x, type:%d\n", current->pid, grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), rHWLock.pvHandle, rHWLock.eDriverType); | |
884 | return -EFAULT; | |
885 | } | |
886 | ||
887 | spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); | |
888 | gu4LockEncHWCount++; | |
889 | spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); | |
890 | ||
891 | MFV_LOGD("VCODEC_LOCKHW get locked - ObjId =%d\n", current->pid); | |
892 | ||
893 | MFV_LOGD("VCODEC_LOCKHW - tid = %d\n", current->pid); | |
894 | } | |
895 | else | |
896 | { | |
897 | MFV_LOGE("[WARNING] VCODEC_LOCKHW Unknown instance\n"); | |
898 | return -EFAULT; | |
899 | } | |
900 | MFV_LOGD("VCODEC_LOCKHW - tid = %d\n", current->pid); | |
901 | break; | |
902 | ||
903 | case VCODEC_UNLOCKHW: | |
904 | MFV_LOGD("VCODEC_UNLOCKHW + tid = %d\n", current->pid); | |
905 | user_data_addr = (VAL_UINT8_T *)arg; | |
906 | ret = copy_from_user(&rHWLock, user_data_addr, sizeof(VAL_HW_LOCK_T)); | |
907 | if (ret) { | |
908 | MFV_LOGE("[ERROR] VCODEC_UNLOCKHW, copy_from_user failed: %d\n", ret); | |
909 | return -EFAULT; | |
910 | } | |
911 | ||
912 | MFV_LOGD("VCODEC_UNLOCKHW eDriverType = %d\n", rHWLock.eDriverType); | |
913 | eValRet = VAL_RESULT_INVALID_ISR; | |
914 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || | |
915 | rHWLock.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || | |
916 | rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_DEC) | |
917 | { | |
918 | mutex_lock(&VdecHWLock); | |
919 | if (grVcodecDecHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle)) // Current owner give up hw lock | |
920 | { | |
921 | grVcodecDecHWLock.pvHandle = 0; | |
922 | grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
923 | disable_irq(MT_VDEC_IRQ_ID); | |
924 | // TODO: check if turning power off is ok | |
925 | vdec_power_off(); | |
926 | } | |
927 | else // Not current owner | |
928 | { | |
929 | MFV_LOGD(" [ERROR] VCODEC_UNLOCKHW Not owner trying to unlock dec hardware 0x%x\n", pmem_user_v2p_video((unsigned int)rHWLock.pvHandle)); | |
930 | mutex_unlock(&VdecHWLock); | |
931 | return -EFAULT; | |
932 | } | |
933 | mutex_unlock(&VdecHWLock); | |
934 | eValRet = eVideoSetEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); | |
935 | } | |
936 | else if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC || | |
937 | rHWLock.eDriverType == VAL_DRIVER_TYPE_JPEG_ENC) | |
938 | { | |
939 | mutex_lock(&VencHWLock); | |
940 | if (grVcodecEncHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)rHWLock.pvHandle)) // Current owner give up hw lock | |
941 | { | |
942 | MFV_LOGD("VCODEC_UNLOCKHW match handle\n"); | |
943 | grVcodecEncHWLock.pvHandle = 0; | |
944 | grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
945 | #ifdef MTK_SEC_VIDEO_PATH_SUPPORT | |
946 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
947 | { | |
948 | if (rHWLock.bSecureInst == VAL_FALSE) | |
949 | { | |
950 | free_irq(MT_VENC_IRQ_ID , NULL); | |
951 | } | |
952 | venc_power_off(); | |
953 | } | |
954 | #else | |
955 | if (rHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
956 | { | |
957 | disable_irq(MT_VENC_IRQ_ID); | |
958 | // turn venc power off | |
959 | venc_power_off(); | |
960 | } | |
961 | #endif | |
962 | } | |
963 | else // Not current owner | |
964 | { | |
965 | // [TODO] error handling | |
966 | MFV_LOGE("[ERROR] VCODEC_UNLOCKHW Not owner trying to unlock enc hardware 0x%x, pa:%x, va:%x type:%d\n", grVcodecEncHWLock.pvHandle, pmem_user_v2p_video((unsigned int)rHWLock.pvHandle), (unsigned int)rHWLock.pvHandle, rHWLock.eDriverType); | |
967 | mutex_unlock(&VencHWLock); | |
968 | return -EFAULT; | |
969 | } | |
970 | mutex_unlock(&VencHWLock); | |
971 | ||
972 | eValRet = eVideoSetEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); | |
973 | MFV_LOGE("VCODEC_UNLOCKHW ENC Set event ret %d\n", eValRet); | |
974 | } | |
975 | else | |
976 | { | |
977 | MFV_LOGE("[WARNING] VCODEC_UNLOCKHW Unknown instance\n"); | |
978 | return -EFAULT; | |
979 | } | |
980 | MFV_LOGD("VCODEC_UNLOCKHW - tid = %d\n", current->pid); | |
981 | break; | |
982 | ||
983 | case VCODEC_INC_PWR_USER: | |
984 | MFV_LOGD("[MT8127] VCODEC_INC_PWR_USER + tid = %d\n", current->pid); | |
985 | user_data_addr = (VAL_UINT8_T *)arg; | |
986 | ret = copy_from_user(&rPowerParam, user_data_addr, sizeof(VAL_POWER_T)); | |
987 | if (ret) { | |
988 | MFV_LOGE("[ERROR] VCODEC_INC_PWR_USER, copy_from_user failed: %d\n", ret); | |
989 | return -EFAULT; | |
990 | } | |
991 | MFV_LOGD("INC_PWR_USER eDriverType = %d\n", rPowerParam.eDriverType); | |
992 | mutex_lock(&L2CLock); | |
993 | if (rPowerParam.eDriverType == VAL_DRIVER_TYPE_H264_DEC || | |
994 | rPowerParam.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || | |
995 | rPowerParam.eDriverType == VAL_DRIVER_TYPE_MP4_DEC) | |
996 | { | |
997 | gu4L2CCounter++; | |
998 | MFV_LOGD("INC_PWR_USER L2C counter = %d\n", gu4L2CCounter); | |
999 | } | |
1000 | #ifdef VDEC_USE_L2C | |
1001 | if (1 == gu4L2CCounter) | |
1002 | { | |
1003 | if (config_L2(SZ_256K)) | |
1004 | { | |
1005 | MFV_LOGE("[MFV][ERROR] Switch L2C size to 256K failed\n"); | |
1006 | mutex_unlock(&L2CLock); | |
1007 | return -EFAULT; | |
1008 | } | |
1009 | else | |
1010 | { | |
1011 | MFV_LOGD("[MFV][ERROR] Switch L2C size to 256K successful\n"); | |
1012 | } | |
1013 | } | |
1014 | #endif | |
1015 | mutex_unlock(&L2CLock); | |
1016 | ||
1017 | MFV_LOGD("[MT8127] VCODEC_INC_PWR_USER - tid = %d\n", current->pid); | |
1018 | break; | |
1019 | ||
1020 | case VCODEC_DEC_PWR_USER: | |
1021 | MFV_LOGD("[MT8127] VCODEC_DEC_PWR_USER + tid = %d\n", current->pid); | |
1022 | user_data_addr = (VAL_UINT8_T *)arg; | |
1023 | ret = copy_from_user(&rPowerParam, user_data_addr, sizeof(VAL_POWER_T)); | |
1024 | if (ret) { | |
1025 | MFV_LOGE("[ERROR] VCODEC_DEC_PWR_USER, copy_from_user failed: %d\n", ret); | |
1026 | return -EFAULT; | |
1027 | } | |
1028 | MFV_LOGD("DEC_PWR_USER eDriverType = %d\n", rPowerParam.eDriverType); | |
1029 | ||
1030 | mutex_lock(&L2CLock); | |
1031 | if (rPowerParam.eDriverType == VAL_DRIVER_TYPE_H264_DEC || | |
1032 | rPowerParam.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || | |
1033 | rPowerParam.eDriverType == VAL_DRIVER_TYPE_MP4_DEC) | |
1034 | { | |
1035 | gu4L2CCounter--; | |
1036 | MFV_LOGD("DEC_PWR_USER L2C counter = %d\n", gu4L2CCounter); | |
1037 | } | |
1038 | #ifdef VDEC_USE_L2C | |
1039 | if (0 == gu4L2CCounter) | |
1040 | { | |
1041 | if (config_L2(SZ_512K)) | |
1042 | { | |
1043 | MFV_LOGE("[MFV][ERROR] Switch L2C size to 512K failed\n"); | |
1044 | mutex_unlock(&L2CLock); | |
1045 | return -EFAULT; | |
1046 | } | |
1047 | else | |
1048 | { | |
1049 | MFV_LOGD("[MFV][ERROR] Switch L2C size to 512K successful\n"); | |
1050 | } | |
1051 | } | |
1052 | #endif | |
1053 | mutex_unlock(&L2CLock); | |
1054 | MFV_LOGD("[MT8127] VCODEC_DEC_PWR_USER - tid = %d\n", current->pid); | |
1055 | break; | |
1056 | ||
1057 | case VCODEC_WAITISR: | |
1058 | ||
1059 | MFV_LOGD("[MT8127] VCODEC_WAITISR + tid = %d\n", current->pid); | |
1060 | user_data_addr = (VAL_UINT8_T *)arg; | |
1061 | ret = copy_from_user(&val_isr, user_data_addr, sizeof(VAL_ISR_T)); | |
1062 | if (ret) { | |
1063 | MFV_LOGE("[ERROR] VCODEC_WAITISR, copy_from_user failed: %d\n", ret); | |
1064 | return -EFAULT; | |
1065 | } | |
1066 | ||
1067 | if (val_isr.eDriverType == VAL_DRIVER_TYPE_MP4_DEC || | |
1068 | val_isr.eDriverType == VAL_DRIVER_TYPE_HEVC_DEC || | |
1069 | val_isr.eDriverType == VAL_DRIVER_TYPE_H264_DEC) | |
1070 | { | |
1071 | mutex_lock(&VdecHWLock); | |
1072 | if (grVcodecDecHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)val_isr.pvHandle)) | |
1073 | { | |
1074 | bLockedHW = VAL_TRUE; | |
1075 | } | |
1076 | else | |
1077 | { | |
1078 | } | |
1079 | mutex_unlock(&VdecHWLock); | |
1080 | ||
1081 | if (bLockedHW == VAL_FALSE) | |
1082 | { | |
1083 | MFV_LOGE("[ERROR] DO NOT have HWLock, so return fail\n"); | |
1084 | break; | |
1085 | } | |
1086 | ||
1087 | spin_lock_irqsave(&DecIsrLock, ulFlags); | |
1088 | DecIsrEvent.u4TimeoutMs = val_isr.u4TimeoutMs; | |
1089 | spin_unlock_irqrestore(&DecIsrLock, ulFlags); | |
1090 | ||
1091 | eValRet = eVideoWaitEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); | |
1092 | if(VAL_RESULT_INVALID_ISR == eValRet) | |
1093 | { | |
1094 | return -2; | |
1095 | } | |
1096 | else if (VAL_RESULT_RESTARTSYS == eValRet) | |
1097 | { | |
1098 | MFV_LOGE("[WARNING] VAL_RESULT_RESTARTSYS return when WAITISR!!\n"); | |
1099 | return -ERESTARTSYS; | |
1100 | } | |
1101 | } | |
1102 | else if (val_isr.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
1103 | { | |
1104 | mutex_lock(&VencHWLock); | |
1105 | if (grVcodecEncHWLock.pvHandle == (VAL_VOID_T*)pmem_user_v2p_video((unsigned int)val_isr.pvHandle)) | |
1106 | { | |
1107 | bLockedHW = VAL_TRUE; | |
1108 | } | |
1109 | else | |
1110 | { | |
1111 | } | |
1112 | mutex_unlock(&VencHWLock); | |
1113 | ||
1114 | if (bLockedHW == VAL_FALSE) | |
1115 | { | |
1116 | MFV_LOGE("[ERROR] DO NOT have enc HWLock, so return fail pa:%x, va:%x\n", pmem_user_v2p_video((unsigned int)val_isr.pvHandle), val_isr.pvHandle); | |
1117 | break; | |
1118 | } | |
1119 | ||
1120 | spin_lock_irqsave(&EncIsrLock, ulFlags); | |
1121 | EncIsrEvent.u4TimeoutMs = val_isr.u4TimeoutMs; | |
1122 | spin_unlock_irqrestore(&EncIsrLock, ulFlags); | |
1123 | ||
1124 | eValRet = eVideoWaitEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
1125 | if(VAL_RESULT_INVALID_ISR == eValRet) | |
1126 | { | |
1127 | return -2; | |
1128 | } | |
1129 | else if (VAL_RESULT_RESTARTSYS == eValRet) | |
1130 | { | |
1131 | MFV_LOGE("[WARNING] VAL_RESULT_RESTARTSYS return when WAITISR!!\n"); | |
1132 | return -ERESTARTSYS; | |
1133 | } | |
1134 | ||
1135 | if (val_isr.u4IrqStatusNum > 0) | |
1136 | { | |
1137 | val_isr.u4IrqStatus[0] = gu4HwVencIrqStatus; | |
1138 | ret = copy_to_user(user_data_addr, &val_isr, sizeof(VAL_ISR_T)); | |
1139 | if (ret) { | |
1140 | MFV_LOGE("[ERROR] VCODEC_WAITISR, copy_to_user failed: %d\n", ret); | |
1141 | return -EFAULT; | |
1142 | } | |
1143 | } | |
1144 | } | |
1145 | else | |
1146 | { | |
1147 | MFV_LOGE("[WARNING] VCODEC_WAITISR Unknown instance\n"); | |
1148 | return -EFAULT; | |
1149 | } | |
1150 | MFV_LOGD("[MT8127] VCODEC_WAITISR - tid = %d\n", current->pid); | |
1151 | break; | |
1152 | ||
1153 | case VCODEC_INITHWLOCK: | |
1154 | { | |
1155 | MFV_LOGE("[MT8127] VCODEC_INITHWLOCK [EMPTY] + - tid = %d\n", current->pid); | |
1156 | ||
1157 | MFV_LOGE("[MT8127] VCODEC_INITHWLOCK [EMPTY] - - tid = %d\n", current->pid); | |
1158 | } | |
1159 | break; | |
1160 | ||
1161 | case VCODEC_DEINITHWLOCK: | |
1162 | { | |
1163 | MFV_LOGE("[MT8127] VCODEC_DEINITHWLOCK [EMPTY] + - tid = %d\n", current->pid); | |
1164 | ||
1165 | MFV_LOGE("[MT8127] VCODEC_DEINITHWLOCK [EMPTY] - - tid = %d\n", current->pid); | |
1166 | } | |
1167 | break; | |
1168 | ||
1169 | case VCODEC_GET_CPU_LOADING_INFO: | |
1170 | { | |
1171 | VAL_UINT8_T *user_data_addr, cpu_id; | |
4b9e9796 | 1172 | VAL_VCODEC_CPU_LOADING_INFO_T _temp = {0}; |
6fa3eb70 S |
1173 | |
1174 | MFV_LOGD("[MT8127] VCODEC_GET_CPU_LOADING_INFO +\n"); | |
1175 | user_data_addr = (VAL_UINT8_T *)arg; | |
1176 | // TODO: | |
1177 | #if 1 // Morris Yang update for multi-core | |
1178 | //MFV_LOGE("[MT8127] VCODEC_GET_CPU_LOADING_INFO num_possible_cpus(%d)\n", num_possible_cpus()); | |
1179 | for (cpu_id = 0 ; cpu_id < num_possible_cpus() ; cpu_id++) { | |
1180 | _temp._cpu_idle_time += mt_get_cpu_idle(cpu_id); | |
1181 | _temp._thread_cpu_time += mt_get_thread_cputime(cpu_id); | |
1182 | } | |
1183 | //spin_lock_irqsave(&OalHWContextLock, ulFlags); | |
1184 | //_temp._inst_count = getCurInstanceCount(); | |
1185 | //spin_unlock_irqrestore(&OalHWContextLock, ulFlags); | |
1186 | _temp._sched_clock = mt_sched_clock(); | |
1187 | #endif | |
1188 | ret = copy_to_user(user_data_addr, &_temp, sizeof(VAL_VCODEC_CPU_LOADING_INFO_T)); | |
1189 | if (ret) { | |
1190 | MFV_LOGE("[ERROR] VCODEC_GET_CPU_LOADING_INFO, copy_to_user failed: %d\n", ret); | |
1191 | return -EFAULT; | |
1192 | } | |
1193 | ||
1194 | MFV_LOGD("[MT8127] VCODEC_GET_CPU_LOADING_INFO -\n"); | |
1195 | break; | |
1196 | } | |
1197 | ||
1198 | case VCODEC_GET_CORE_LOADING: | |
1199 | { | |
1200 | MFV_LOGD("[MT8127] VCODEC_GET_CORE_LOADING + - tid = %d\n", current->pid); | |
1201 | ||
1202 | user_data_addr = (VAL_UINT8_T *)arg; | |
1203 | ret = copy_from_user(&rTempCoreLoading, user_data_addr, sizeof(VAL_VCODEC_CORE_LOADING_T)); | |
1204 | if (ret) | |
1205 | { | |
1206 | MFV_LOGE("[ERROR] VCODEC_GET_CORE_LOADING, copy_from_user failed: %d\n", ret); | |
1207 | return -EFAULT; | |
1208 | } | |
1209 | rTempCoreLoading.Loading = get_cpu_load(rTempCoreLoading.CPUid); | |
1210 | ret = copy_to_user(user_data_addr, &rTempCoreLoading, sizeof(VAL_VCODEC_CORE_LOADING_T)); | |
1211 | if (ret) { | |
1212 | MFV_LOGE("[ERROR] VCODEC_GET_CORE_LOADING, copy_to_user failed: %d\n", ret); | |
1213 | return -EFAULT; | |
1214 | } | |
1215 | ||
1216 | MFV_LOGD("[MT8127] VCODEC_GET_CORE_LOADING - - tid = %d\n", current->pid); | |
1217 | break; | |
1218 | } | |
1219 | ||
1220 | case VCODEC_GET_CORE_NUMBER: | |
1221 | { | |
1222 | MFV_LOGD("[MT8127] VCODEC_GET_CORE_NUMBER + - tid = %d\n", current->pid); | |
1223 | ||
1224 | user_data_addr = (VAL_UINT8_T *)arg; | |
1225 | temp_nr_cpu_ids = nr_cpu_ids; | |
1226 | ret = copy_to_user(user_data_addr, &temp_nr_cpu_ids, sizeof(int)); | |
1227 | if (ret) { | |
1228 | MFV_LOGE("[ERROR] VCODEC_GET_CORE_NUMBER, copy_to_user failed: %d\n", ret); | |
1229 | return -EFAULT; | |
1230 | } | |
1231 | MFV_LOGD("[MT8127] VCODEC_GET_CORE_NUMBER - - tid = %d\n", current->pid); | |
1232 | break; | |
1233 | } | |
1234 | case VCODEC_SET_CPU_OPP_LIMIT: | |
1235 | MFV_LOGE("[MT8127] VCODEC_SET_CPU_OPP_LIMIT [EMPTY] + - tid = %d\n", current->pid); | |
1236 | user_data_addr = (VAL_UINT8_T *)arg; | |
1237 | ret = copy_from_user(&rCpuOppLimit, user_data_addr, sizeof(VAL_VCODEC_CPU_OPP_LIMIT_T)); | |
1238 | if (ret) { | |
1239 | MFV_LOGE("[ERROR] VCODEC_SET_CPU_OPP_LIMIT, copy_from_user failed: %d\n", ret); | |
1240 | return -EFAULT; | |
1241 | } | |
1242 | MFV_LOGE("+VCODEC_SET_CPU_OPP_LIMIT (%d, %d, %d), tid = %d\n", rCpuOppLimit.limited_freq, rCpuOppLimit.limited_cpu, rCpuOppLimit.enable, current->pid); | |
1243 | // TODO: Check if cpu_opp_limit is available | |
1244 | //ret = cpu_opp_limit(EVENT_VIDEO, rCpuOppLimit.limited_freq, rCpuOppLimit.limited_cpu, rCpuOppLimit.enable); // 0: PASS, other: FAIL | |
1245 | if (ret) { | |
1246 | MFV_LOGE("[ERROR] cpu_opp_limit failed: %d\n", ret); | |
1247 | return -EFAULT; | |
1248 | } | |
1249 | MFV_LOGE("-VCODEC_SET_CPU_OPP_LIMIT tid = %d, ret = %d\n", current->pid, ret); | |
1250 | MFV_LOGE("[MT8127] VCODEC_SET_CPU_OPP_LIMIT [EMPTY] - - tid = %d\n", current->pid); | |
1251 | break; | |
1252 | case VCODEC_MB: | |
1253 | mb(); | |
1254 | break; | |
1255 | #if 0 | |
1256 | case MFV_SET_CMD_CMD: | |
1257 | MFV_LOGD("[MFV] MFV_SET_CMD_CMD\n"); | |
1258 | MFV_LOGD("[MFV] Arg = %x\n",arg); | |
1259 | user_data_addr = (VAL_UINT8_T *)arg; | |
1260 | ret = copy_from_user(&rDrvCmdQueue, user_data_addr, sizeof(VCODEC_DRV_CMD_QUEUE_T)); | |
1261 | MFV_LOGD("[MFV] CmdNum = %d\n",rDrvCmdQueue.CmdNum); | |
1262 | u4Size = (rDrvCmdQueue.CmdNum)*sizeof(VCODEC_DRV_CMD_T); | |
1263 | ||
1264 | cmd_queue = (P_VCODEC_DRV_CMD_T)kmalloc(u4Size,GFP_ATOMIC); | |
1265 | if (cmd_queue != VAL_NULL && rDrvCmdQueue.pCmd != VAL_NULL) { | |
1266 | ret = copy_from_user(cmd_queue, rDrvCmdQueue.pCmd, u4Size); | |
1267 | while (cmd_queue->type != END_CMD) { | |
1268 | switch (cmd_queue->type) | |
1269 | { | |
1270 | case ENABLE_HW_CMD: | |
1271 | break; | |
1272 | case DISABLE_HW_CMD: | |
1273 | break; | |
1274 | case WRITE_REG_CMD: | |
1275 | VDO_HW_WRITE(cmd_queue->address + cmd_queue->offset, cmd_queue->value); | |
1276 | break; | |
1277 | case READ_REG_CMD: | |
1278 | uValue = VDO_HW_READ(cmd_queue->address + cmd_queue->offset); | |
1279 | copy_to_user((void *)cmd_queue->value, &uValue, sizeof(VAL_UINT32_T)); | |
1280 | break; | |
1281 | case WRITE_SYSRAM_CMD: | |
1282 | VDO_HW_WRITE(cmd_queue->address + cmd_queue->offset, cmd_queue->value); | |
1283 | break; | |
1284 | case READ_SYSRAM_CMD: | |
1285 | uValue = VDO_HW_READ(cmd_queue->address + cmd_queue->offset); | |
1286 | copy_to_user((void *)cmd_queue->value, &uValue, sizeof(VAL_UINT32_T)); | |
1287 | break; | |
1288 | case MASTER_WRITE_CMD: | |
1289 | uValue = VDO_HW_READ(cmd_queue->address + cmd_queue->offset); | |
1290 | VDO_HW_WRITE(cmd_queue->address + cmd_queue->offset, cmd_queue->value | (uValue & cmd_queue->mask)); | |
1291 | break; | |
1292 | case SETUP_ISR_CMD: | |
1293 | break; | |
1294 | case WAIT_ISR_CMD: | |
1295 | MFV_LOGD("HAL_CMD_SET_CMD_QUEUE: WAIT_ISR_CMD+\n"); | |
1296 | ||
1297 | MFV_LOGD("HAL_CMD_SET_CMD_QUEUE: WAIT_ISR_CMD-\n"); | |
1298 | break; | |
1299 | case TIMEOUT_CMD: | |
1300 | break; | |
1301 | case WRITE_SYSRAM_RANGE_CMD: | |
1302 | break; | |
1303 | case READ_SYSRAM_RANGE_CMD: | |
1304 | break; | |
1305 | case POLL_REG_STATUS_CMD: | |
1306 | uValue = VDO_HW_READ(cmd_queue->address + cmd_queue->offset); | |
1307 | nCount = 0; | |
1308 | while ((uValue & cmd_queue->mask) != 0) { | |
1309 | nCount++; | |
1310 | if (nCount > 1000) { | |
1311 | break; | |
1312 | } | |
1313 | uValue = VDO_HW_READ(cmd_queue->address + cmd_queue->offset); | |
1314 | } | |
1315 | break; | |
1316 | default: | |
1317 | break; | |
1318 | } | |
1319 | cmd_queue++; | |
1320 | } | |
1321 | ||
1322 | } | |
1323 | break; | |
1324 | #endif | |
1325 | default: | |
1326 | MFV_LOGE("========[ERROR] vcodec_ioctl default case======== %u\n", cmd); | |
1327 | break; | |
1328 | } | |
1329 | return 0xFF; | |
1330 | } | |
1331 | ||
1332 | static int vcodec_open(struct inode *inode, struct file *file) | |
1333 | { | |
1334 | MFV_LOGD("[VCODEC_DEBUG] vcodec_open\n"); | |
1335 | ||
1336 | mutex_lock(&DriverOpenCountLock); | |
1337 | MT8127Driver_Open_Count++; | |
1338 | ||
1339 | MFV_LOGE("vcodec_open pid = %d, MT8127Driver_Open_Count %d\n", current->pid, MT8127Driver_Open_Count); | |
1340 | mutex_unlock(&DriverOpenCountLock); | |
1341 | ||
1342 | ||
1343 | // TODO: Check upper limit of concurrent users? | |
1344 | ||
1345 | return 0; | |
1346 | } | |
1347 | ||
1348 | static int venc_hw_reset(int type) | |
1349 | { | |
1350 | VAL_UINT32_T uValue; | |
1351 | VAL_RESULT_T eValRet; | |
1352 | MFV_LOGE("Start VENC HW Reset"); | |
1353 | ||
1354 | ////clear irq event | |
1355 | //EncIsrEvent.u4TimeoutMs = 1; | |
1356 | //eValRet = eVideoWaitEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
1357 | //MFV_LOGE("ret %d", eValRet); | |
1358 | //if type == 0//Soft Reset | |
1359 | //step 1 | |
1360 | VDO_HW_WRITE(KVA_VENC_SW_PAUSE, 1); | |
1361 | //step 2 | |
1362 | //EncIsrEvent.u4TimeoutMs = 10000; | |
1363 | EncIsrEvent.u4TimeoutMs = 2; | |
1364 | eValRet = eVideoWaitEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
1365 | if(VAL_RESULT_INVALID_ISR == eValRet || gu4HwVencIrqStatus != VENC_IRQ_STATUS_PAUSE)//timeout or don't get pasue | |
1366 | {//step 3 | |
1367 | uValue = VDO_HW_READ(KVA_VENC_IRQ_STATUS_ADDR); | |
1368 | if (gu4HwVencIrqStatus != VENC_IRQ_STATUS_PAUSE) | |
1369 | { | |
1370 | udelay(200); | |
1371 | } | |
1372 | MFV_LOGE("irq_status 0x%x", uValue); | |
1373 | VDO_HW_WRITE(KVA_VENC_SW_PAUSE, 0); | |
1374 | VDO_HW_WRITE(KVA_VENC_SW_HRST_N, 0); | |
1375 | uValue = VDO_HW_READ(KVA_VENC_SW_HRST_N); | |
1376 | MFV_LOGE("3 HRST = %d, isr = 0x%x", uValue, gu4HwVencIrqStatus); | |
1377 | } | |
1378 | else | |
1379 | {//step 4 | |
1380 | VDO_HW_WRITE(KVA_VENC_SW_HRST_N, 0); | |
1381 | uValue = gu4HwVencIrqStatus; | |
1382 | VDO_HW_WRITE(KVA_VENC_SW_PAUSE, 0); | |
1383 | MFV_LOGE("4 HRST = %d, isr = 0x%x", uValue, gu4HwVencIrqStatus); | |
1384 | } | |
1385 | ||
1386 | VDO_HW_WRITE(KVA_VENC_SW_HRST_N, 1); | |
1387 | uValue = VDO_HW_READ(KVA_VENC_SW_HRST_N); | |
1388 | MFV_LOGE("HRST = %d", uValue); | |
1389 | ||
1390 | return 1; | |
1391 | } | |
1392 | ||
1393 | static int vcodec_flush(struct file *file, fl_owner_t id) | |
1394 | { | |
1395 | MFV_LOGD("[VCODEC_DEBUG] vcodec_flush, curr_tid =%d\n", current->pid); | |
1396 | MFV_LOGE("vcodec_flush pid = %d, MT8127Driver_Open_Count %d\n", current->pid, MT8127Driver_Open_Count); | |
1397 | ||
1398 | return 0; | |
1399 | } | |
1400 | ||
1401 | static int vcodec_release(struct inode *inode, struct file *file) | |
1402 | { | |
1403 | unsigned long ulFlagsLockHW, ulFlagsISR; | |
1404 | ||
1405 | //dump_stack(); | |
1406 | MFV_LOGD("[VCODEC_DEBUG] vcodec_release, curr_tid =%d\n", current->pid); | |
1407 | mutex_lock(&DriverOpenCountLock); | |
1408 | MFV_LOGE("vcodec_release pid = %d, MT8127Driver_Open_Count %d\n", current->pid, MT8127Driver_Open_Count); | |
1409 | ||
1410 | MT8127Driver_Open_Count--; | |
1411 | ||
1412 | if (MT8127Driver_Open_Count == 0) { | |
1413 | ||
1414 | mutex_lock(&VdecHWLock); | |
1415 | if (grVcodecEncHWLock.eDriverType == VAL_DRIVER_TYPE_H264_ENC) | |
1416 | { | |
1417 | venc_hw_reset(0); | |
1418 | disable_irq(MT_VENC_IRQ_ID); | |
1419 | venc_power_off(); | |
1420 | MFV_LOGE("Clean venc lock\n"); | |
1421 | } | |
1422 | mutex_unlock(&VdecHWLock); | |
1423 | ||
1424 | mutex_lock(&VdecHWLock); | |
1425 | gu4VdecLockThreadId = 0; | |
1426 | grVcodecDecHWLock.pvHandle = 0; | |
1427 | grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
1428 | grVcodecDecHWLock.rLockedTime.u4Sec = 0; | |
1429 | grVcodecDecHWLock.rLockedTime.u4uSec = 0; | |
1430 | mutex_unlock(&VdecHWLock); | |
1431 | ||
1432 | mutex_lock(&VencHWLock); | |
1433 | grVcodecEncHWLock.pvHandle = 0; | |
1434 | grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
1435 | grVcodecEncHWLock.rLockedTime.u4Sec = 0; | |
1436 | grVcodecEncHWLock.rLockedTime.u4uSec = 0; | |
1437 | mutex_unlock(&VencHWLock); | |
1438 | ||
1439 | mutex_lock(&DecEMILock); | |
1440 | gu4DecEMICounter = 0; | |
1441 | mutex_unlock(&DecEMILock); | |
1442 | ||
1443 | mutex_lock(&EncEMILock); | |
1444 | gu4EncEMICounter = 0; | |
1445 | mutex_unlock(&EncEMILock); | |
1446 | ||
1447 | mutex_lock(&PWRLock); | |
1448 | gu4PWRCounter = 0; | |
1449 | mutex_unlock(&PWRLock); | |
1450 | ||
1451 | mutex_lock(&L2CLock); | |
1452 | #ifdef VDEC_USE_L2C | |
1453 | if (gu4L2CCounter != 0) | |
1454 | { | |
1455 | MFV_LOGE("vcodec_flush pid = %d, L2 user = %d, force restore L2 settings\n", current->pid, gu4L2CCounter); | |
1456 | if (config_L2(SZ_512K)) | |
1457 | { | |
1458 | MFV_LOGE("restore L2 settings failed\n"); | |
1459 | } | |
1460 | } | |
1461 | #endif | |
1462 | gu4L2CCounter = 0; | |
1463 | mutex_unlock(&L2CLock); | |
1464 | ||
1465 | spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); | |
1466 | gu4LockDecHWCount = 0; | |
1467 | spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); | |
1468 | ||
1469 | spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); | |
1470 | gu4LockEncHWCount = 0; | |
1471 | spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); | |
1472 | ||
1473 | spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); | |
1474 | gu4DecISRCount = 0; | |
1475 | spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); | |
1476 | ||
1477 | spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); | |
1478 | gu4EncISRCount = 0; | |
1479 | spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); | |
1480 | } | |
1481 | mutex_unlock(&DriverOpenCountLock); | |
1482 | ||
1483 | return 0; | |
1484 | } | |
1485 | ||
1486 | void vcodec_vma_open(struct vm_area_struct *vma) | |
1487 | { | |
1488 | MFV_LOGD("vcodec VMA open, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT); | |
1489 | } | |
1490 | ||
1491 | void vcodec_vma_close(struct vm_area_struct *vma) | |
1492 | { | |
1493 | MFV_LOGD("vcodec VMA close, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT); | |
1494 | } | |
1495 | ||
1496 | static struct vm_operations_struct vcodec_remap_vm_ops = { | |
1497 | .open = vcodec_vma_open, | |
1498 | .close = vcodec_vma_close, | |
1499 | }; | |
1500 | ||
1501 | static int vcodec_mmap(struct file* file, struct vm_area_struct* vma) | |
1502 | { | |
1503 | long length; | |
1504 | unsigned int pfn; | |
1505 | ||
1506 | length = vma->vm_end - vma->vm_start; | |
1507 | pfn = vma->vm_pgoff<<PAGE_SHIFT; | |
1508 | ||
1509 | if(((length > VENC_REGION) || (pfn < VENC_BASE) || (pfn > VENC_BASE+VENC_REGION)) && | |
1510 | ((length > VDEC_REGION) || (pfn < VDEC_BASE_PHY) || (pfn > VDEC_BASE_PHY+VDEC_REGION)) && | |
1511 | ((length > HW_REGION) || (pfn < HW_BASE) || (pfn > HW_BASE+HW_REGION)) && | |
1512 | ((length > INFO_REGION_1) || (pfn < INFO_BASE_1) || (pfn > INFO_BASE_1+INFO_REGION_1)) && | |
1513 | ((length > INFO_REGION_2) || (pfn < INFO_BASE_2) || (pfn > INFO_BASE_2+INFO_REGION_2)) && | |
1514 | ((length > INFO_REGION_3) || (pfn < INFO_BASE_3) || (pfn > INFO_BASE_3+INFO_REGION_3)) | |
1515 | ) | |
1516 | { | |
1517 | MFV_LOGE("[ERROR] mmap region error: Length(0x%x), pfn(0x%x)\n", length, pfn); | |
1518 | return -EAGAIN; | |
1519 | } | |
1520 | ||
1521 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | |
1522 | MFV_LOGE("[mmap] vma->start 0x%x, vma->end 0x%x, vma->pgoff 0x%x\n", | |
1523 | (unsigned int)vma->vm_start, (unsigned int)vma->vm_end, (unsigned int)vma->vm_pgoff); | |
1524 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, | |
1525 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) { | |
1526 | return -EAGAIN; | |
1527 | } | |
1528 | ||
1529 | vma->vm_ops = &vcodec_remap_vm_ops; | |
1530 | vcodec_vma_open(vma); | |
1531 | ||
1532 | return 0; | |
1533 | } | |
1534 | ||
1535 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
1536 | static void vcodec_early_suspend(struct early_suspend *h) | |
1537 | { | |
1538 | mutex_lock(&PWRLock); | |
1539 | MFV_LOGE("vcodec_early_suspend, tid = %d, PWR_USER = %d\n", current->pid, gu4PWRCounter); | |
1540 | mutex_unlock(&PWRLock); | |
1541 | /* | |
1542 | if (gu4PWRCounter != 0) | |
1543 | { | |
1544 | MFV_LOGE("[MT6589_VCodec_early_suspend] Someone Use HW, Disable Power!\n"); | |
1545 | disable_clock(MT65XX_PDN_MM_VBUF, "Video_VBUF"); | |
1546 | disable_clock(MT_CG_VDEC0_VDE, "VideoDec"); | |
1547 | disable_clock(MT_CG_VENC_VEN, "VideoEnc"); | |
1548 | disable_clock(MT65XX_PDN_MM_GDC_SHARE_MACRO, "VideoEnc"); | |
1549 | } | |
1550 | */ | |
1551 | MFV_LOGD("vcodec_early_suspend - tid = %d\n", current->pid); | |
1552 | } | |
1553 | ||
1554 | static void vcodec_late_resume(struct early_suspend *h) | |
1555 | { | |
1556 | mutex_lock(&PWRLock); | |
1557 | MFV_LOGE("vcodec_late_resume, tid = %d, PWR_USER = %d\n", current->pid, gu4PWRCounter); | |
1558 | mutex_unlock(&PWRLock); | |
1559 | /* | |
1560 | if (gu4PWRCounter != 0) | |
1561 | { | |
1562 | MFV_LOGE("[vcodec_late_resume] Someone Use HW, Enable Power!\n"); | |
1563 | enable_clock(MT65XX_PDN_MM_VBUF, "Video_VBUF"); | |
1564 | enable_clock(MT_CG_VDEC0_VDE, "VideoDec"); | |
1565 | enable_clock(MT_CG_VENC_VEN, "VideoEnc"); | |
1566 | enable_clock(MT65XX_PDN_MM_GDC_SHARE_MACRO, "VideoEnc"); | |
1567 | } | |
1568 | */ | |
1569 | MFV_LOGD("vcodec_late_resume - tid = %d\n", current->pid); | |
1570 | } | |
1571 | ||
1572 | static struct early_suspend vcodec_early_suspend_handler = | |
1573 | { | |
1574 | .level = (EARLY_SUSPEND_LEVEL_DISABLE_FB - 1), | |
1575 | .suspend = vcodec_early_suspend, | |
1576 | .resume = vcodec_late_resume, | |
1577 | }; | |
1578 | #endif | |
1579 | ||
1580 | static struct file_operations vcodec_fops = { | |
1581 | .owner = THIS_MODULE, | |
1582 | .unlocked_ioctl = vcodec_unlocked_ioctl, | |
1583 | .open = vcodec_open, | |
1584 | .flush = vcodec_flush, | |
1585 | .release = vcodec_release, | |
1586 | .mmap = vcodec_mmap, | |
1587 | }; | |
1588 | ||
1589 | static int vcodec_probe(struct platform_device *dev) | |
1590 | { | |
1591 | int ret; | |
1592 | MFV_LOGD("+vcodec_probe\n"); | |
1593 | ||
1594 | mutex_lock(&DecEMILock); | |
1595 | gu4DecEMICounter = 0; | |
1596 | mutex_unlock(&DecEMILock); | |
1597 | ||
1598 | mutex_lock(&EncEMILock); | |
1599 | gu4EncEMICounter = 0; | |
1600 | mutex_unlock(&EncEMILock); | |
1601 | ||
1602 | mutex_lock(&PWRLock); | |
1603 | gu4PWRCounter = 0; | |
1604 | mutex_unlock(&PWRLock); | |
1605 | ||
1606 | mutex_lock(&L2CLock); | |
1607 | gu4L2CCounter = 0; | |
1608 | mutex_unlock(&L2CLock); | |
1609 | ||
1610 | ret = register_chrdev_region(vcodec_devno, 1, VCODEC_DEVNAME); | |
1611 | if (ret) { | |
1612 | MFV_LOGE("[VCODEC_DEBUG][ERROR] Can't Get Major number for VCodec Device\n"); | |
1613 | } | |
1614 | ||
1615 | vcodec_cdev = cdev_alloc(); | |
1616 | vcodec_cdev->owner = THIS_MODULE; | |
1617 | vcodec_cdev->ops = &vcodec_fops; | |
1618 | ||
1619 | ret = cdev_add(vcodec_cdev, vcodec_devno, 1); | |
1620 | if (ret) { | |
1621 | MFV_LOGE("[VCODEC_DEBUG][ERROR] Can't add Vcodec Device\n"); | |
1622 | } | |
1623 | ||
1624 | vcodec_class = class_create(THIS_MODULE, VCODEC_DEVNAME); | |
1625 | if (IS_ERR(vcodec_class)) { | |
1626 | ret = PTR_ERR(vcodec_class); | |
1627 | MFV_LOGE("Unable to create class, err = %d", ret); | |
1628 | return ret; | |
1629 | } | |
1630 | ||
1631 | vcodec_device = device_create(vcodec_class, NULL, vcodec_devno, NULL, VCODEC_DEVNAME); | |
1632 | ||
1633 | if (request_irq(MT_VDEC_IRQ_ID , (irq_handler_t)video_intr_dlr, IRQF_TRIGGER_LOW, VCODEC_DEVNAME, NULL) < 0) | |
1634 | { | |
1635 | MFV_LOGD("[VCODEC_DEBUG][ERROR] error to request dec irq\n"); | |
1636 | } | |
1637 | else | |
1638 | { | |
1639 | MFV_LOGD("[VCODEC_DEBUG] success to request dec irq\n"); | |
1640 | } | |
1641 | #ifdef MTK_SEC_VIDEO_PATH_SUPPORT | |
1642 | MFV_LOGD("[VCODEC_DEBUG] CONFIG_SEC_VIDEO_PATH_SUPPORT not request enc irq\n"); | |
1643 | #else | |
1644 | if (request_irq(MT_VENC_IRQ_ID , (irq_handler_t)video_intr_dlr2, IRQF_TRIGGER_LOW, VCODEC_DEVNAME, NULL) < 0) | |
1645 | { | |
1646 | MFV_LOGE("[VCODEC_DEBUG][ERROR] error to request enc irq\n"); | |
1647 | } | |
1648 | else | |
1649 | { | |
1650 | MFV_LOGD("[VCODEC_DEBUG] success to request enc irq\n"); | |
1651 | } | |
1652 | #endif | |
1653 | ||
1654 | disable_irq(MT_VDEC_IRQ_ID); | |
1655 | #ifdef MTK_SEC_VIDEO_PATH_SUPPORT | |
1656 | #else | |
1657 | disable_irq(MT_VENC_IRQ_ID); | |
1658 | #endif | |
1659 | ||
1660 | MFV_LOGD("[VCODEC_DEBUG] vcodec_probe Done\n"); | |
1661 | ||
1662 | return 0; | |
1663 | } | |
1664 | ||
1665 | #ifdef CONFIG_MTK_HIBERNATION | |
1666 | extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); | |
1667 | extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); | |
1668 | static int vcodec_pm_restore_noirq(struct device *device) | |
1669 | { | |
1670 | // vdec : IRQF_TRIGGER_LOW | |
1671 | mt_irq_set_sens(MT_VDEC_IRQ_ID, MT_LEVEL_SENSITIVE); | |
1672 | mt_irq_set_polarity(MT_VDEC_IRQ_ID, MT_POLARITY_LOW); | |
1673 | // venc: IRQF_TRIGGER_LOW | |
1674 | mt_irq_set_sens(MT_VENC_IRQ_ID, MT_LEVEL_SENSITIVE); | |
1675 | mt_irq_set_polarity(MT_VENC_IRQ_ID, MT_POLARITY_LOW); | |
1676 | ||
1677 | return 0; | |
1678 | } | |
1679 | #endif | |
1680 | ||
1681 | static int __init vcodec_driver_init(void) | |
1682 | { | |
1683 | VAL_RESULT_T eValHWLockRet; | |
1684 | unsigned long ulFlags, ulFlagsLockHW, ulFlagsISR; | |
1685 | ||
1686 | MFV_LOGD("+vcodec_init !!\n"); | |
1687 | ||
1688 | mutex_lock(&DriverOpenCountLock); | |
1689 | MT8127Driver_Open_Count = 0; | |
1690 | mutex_unlock(&DriverOpenCountLock); | |
1691 | ||
1692 | KVA_VENC_IRQ_STATUS_ADDR = (int)ioremap(VENC_IRQ_STATUS_addr, 4); | |
1693 | KVA_VENC_IRQ_ACK_ADDR = (int)ioremap(VENC_IRQ_ACK_addr, 4); | |
1694 | KVA_VENC_SW_PAUSE = (int)ioremap(VENC_SW_PAUSE, 4); | |
1695 | KVA_VENC_SW_HRST_N = (int)ioremap(VENC_SW_HRST_N, 4); | |
1696 | #ifdef VENC_PWR_FPGA | |
1697 | KVA_VENC_CLK_CFG_0_ADDR = (int)ioremap(CLK_CFG_0_addr, 4); | |
1698 | KVA_VENC_CLK_CFG_4_ADDR = (int)ioremap(CLK_CFG_4_addr, 4); | |
1699 | KVA_VENC_PWR_ADDR = (int)ioremap(VENC_PWR_addr, 4); | |
1700 | KVA_VENCSYS_CG_SET_ADDR = (int)ioremap(VENCSYS_CG_SET_addr, 4); | |
1701 | #endif | |
1702 | ||
1703 | spin_lock_irqsave(&LockDecHWCountLock, ulFlagsLockHW); | |
1704 | gu4LockDecHWCount = 0; | |
1705 | spin_unlock_irqrestore(&LockDecHWCountLock, ulFlagsLockHW); | |
1706 | ||
1707 | spin_lock_irqsave(&LockEncHWCountLock, ulFlagsLockHW); | |
1708 | gu4LockEncHWCount = 0; | |
1709 | spin_unlock_irqrestore(&LockEncHWCountLock, ulFlagsLockHW); | |
1710 | ||
1711 | spin_lock_irqsave(&DecISRCountLock, ulFlagsISR); | |
1712 | gu4DecISRCount = 0; | |
1713 | spin_unlock_irqrestore(&DecISRCountLock, ulFlagsISR); | |
1714 | ||
1715 | spin_lock_irqsave(&EncISRCountLock, ulFlagsISR); | |
1716 | gu4EncISRCount = 0; | |
1717 | spin_unlock_irqrestore(&EncISRCountLock, ulFlagsISR); | |
1718 | ||
1719 | mutex_lock(&IsOpenedLock); | |
1720 | if (VAL_FALSE == bIsOpened) { | |
1721 | bIsOpened = VAL_TRUE; | |
1722 | vcodec_probe(NULL); | |
1723 | } | |
1724 | mutex_unlock(&IsOpenedLock); | |
1725 | ||
1726 | mutex_lock(&VdecHWLock); | |
1727 | gu4VdecLockThreadId = 0; | |
1728 | grVcodecDecHWLock.pvHandle = 0; | |
1729 | grVcodecDecHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
1730 | grVcodecDecHWLock.rLockedTime.u4Sec = 0; | |
1731 | grVcodecDecHWLock.rLockedTime.u4uSec = 0; | |
1732 | mutex_unlock(&VdecHWLock); | |
1733 | ||
1734 | mutex_lock(&VencHWLock); | |
1735 | grVcodecEncHWLock.pvHandle = 0; | |
1736 | grVcodecEncHWLock.eDriverType = VAL_DRIVER_TYPE_NONE; | |
1737 | grVcodecEncHWLock.rLockedTime.u4Sec = 0; | |
1738 | grVcodecEncHWLock.rLockedTime.u4uSec = 0; | |
1739 | mutex_unlock(&VencHWLock); | |
1740 | ||
1741 | //MT8127_HWLockEvent part | |
1742 | mutex_lock(&DecHWLockEventTimeoutLock); | |
1743 | DecHWLockEvent.pvHandle = "DECHWLOCK_EVENT"; | |
1744 | DecHWLockEvent.u4HandleSize = sizeof("DECHWLOCK_EVENT")+1; | |
1745 | DecHWLockEvent.u4TimeoutMs = 1; | |
1746 | mutex_unlock(&DecHWLockEventTimeoutLock); | |
1747 | eValHWLockRet = eVideoCreateEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); | |
1748 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1749 | MFV_LOGE("[MFV][ERROR] create dec hwlock event error\n"); | |
1750 | } | |
1751 | ||
1752 | mutex_lock(&EncHWLockEventTimeoutLock); | |
1753 | EncHWLockEvent.pvHandle = "ENCHWLOCK_EVENT"; | |
1754 | EncHWLockEvent.u4HandleSize = sizeof("ENCHWLOCK_EVENT")+1; | |
1755 | EncHWLockEvent.u4TimeoutMs = 1; | |
1756 | mutex_unlock(&EncHWLockEventTimeoutLock); | |
1757 | eValHWLockRet = eVideoCreateEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); | |
1758 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1759 | MFV_LOGE("[MFV][ERROR] create enc hwlock event error\n"); | |
1760 | } | |
1761 | ||
1762 | //MT8127_IsrEvent part | |
1763 | spin_lock_irqsave(&DecIsrLock, ulFlags); | |
1764 | DecIsrEvent.pvHandle = "DECISR_EVENT"; | |
1765 | DecIsrEvent.u4HandleSize = sizeof("DECISR_EVENT")+1; | |
1766 | DecIsrEvent.u4TimeoutMs = 1; | |
1767 | spin_unlock_irqrestore(&DecIsrLock, ulFlags); | |
1768 | eValHWLockRet = eVideoCreateEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); | |
1769 | if(VAL_RESULT_NO_ERROR != eValHWLockRet) | |
1770 | { | |
1771 | MFV_LOGE("[MFV][ERROR] create dec isr event error\n"); | |
1772 | } | |
1773 | ||
1774 | spin_lock_irqsave(&EncIsrLock, ulFlags); | |
1775 | EncIsrEvent.pvHandle = "ENCISR_EVENT"; | |
1776 | EncIsrEvent.u4HandleSize = sizeof("ENCISR_EVENT")+1; | |
1777 | EncIsrEvent.u4TimeoutMs = 1; | |
1778 | spin_unlock_irqrestore(&EncIsrLock, ulFlags); | |
1779 | eValHWLockRet = eVideoCreateEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
1780 | if(VAL_RESULT_NO_ERROR != eValHWLockRet) | |
1781 | { | |
1782 | MFV_LOGE("[MFV][ERROR] create enc isr event error\n"); | |
1783 | } | |
1784 | ||
1785 | MFV_LOGD("[VCODEC_DEBUG] vcodec_driver_init Done\n"); | |
1786 | ||
1787 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
1788 | register_early_suspend(&vcodec_early_suspend_handler); | |
1789 | #endif | |
1790 | ||
1791 | #ifdef CONFIG_MTK_HIBERNATION | |
1792 | register_swsusp_restore_noirq_func(ID_M_VCODEC, vcodec_pm_restore_noirq, NULL); | |
1793 | #endif | |
1794 | ||
1795 | return 0; | |
1796 | } | |
1797 | ||
1798 | static void __exit vcodec_driver_exit(void) | |
1799 | { | |
1800 | VAL_RESULT_T eValHWLockRet; | |
1801 | ||
1802 | MFV_LOGD("[VCODEC_DEBUG] mflexvideo_driver_exit\n"); | |
1803 | ||
1804 | mutex_lock(&IsOpenedLock); | |
1805 | if (VAL_TRUE == bIsOpened) { | |
1806 | bIsOpened = VAL_FALSE; | |
1807 | } | |
1808 | mutex_unlock(&IsOpenedLock); | |
1809 | ||
1810 | cdev_del(vcodec_cdev); | |
1811 | unregister_chrdev_region(vcodec_devno, 1); | |
1812 | ||
1813 | // [TODO] iounmap the following? | |
1814 | iounmap((void*)KVA_VENC_IRQ_STATUS_ADDR); | |
1815 | iounmap((void*)KVA_VENC_IRQ_ACK_ADDR); | |
1816 | iounmap((void*)KVA_VENC_SW_PAUSE); | |
1817 | iounmap((void*)KVA_VENC_SW_HRST_N); | |
1818 | #ifdef VENC_PWR_FPGA | |
1819 | iounmap((void*)KVA_VENC_CLK_CFG_0_ADDR); | |
1820 | iounmap((void*)KVA_VENC_CLK_CFG_4_ADDR); | |
1821 | iounmap((void*)KVA_VENC_PWR_ADDR); | |
1822 | iounmap((void*)KVA_VENCSYS_CG_SET_ADDR); | |
1823 | #endif | |
1824 | ||
1825 | // [TODO] free IRQ here | |
1826 | free_irq(MT_VENC_IRQ_ID, NULL); | |
1827 | free_irq(MT_VDEC_IRQ_ID, NULL); | |
1828 | ||
1829 | ||
1830 | //MT6589_HWLockEvent part | |
1831 | eValHWLockRet = eVideoCloseEvent(&DecHWLockEvent, sizeof(VAL_EVENT_T)); | |
1832 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1833 | MFV_LOGE("[MFV][ERROR] close dec hwlock event error\n"); | |
1834 | } | |
1835 | ||
1836 | eValHWLockRet = eVideoCloseEvent(&EncHWLockEvent, sizeof(VAL_EVENT_T)); | |
1837 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1838 | MFV_LOGE("[MFV][ERROR] close enc hwlock event error\n"); | |
1839 | } | |
1840 | ||
1841 | //MT6589_IsrEvent part | |
1842 | eValHWLockRet = eVideoCloseEvent(&DecIsrEvent, sizeof(VAL_EVENT_T)); | |
1843 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1844 | MFV_LOGE("[MFV][ERROR] close dec isr event error\n"); | |
1845 | } | |
1846 | ||
1847 | eValHWLockRet = eVideoCloseEvent(&EncIsrEvent, sizeof(VAL_EVENT_T)); | |
1848 | if (VAL_RESULT_NO_ERROR != eValHWLockRet) { | |
1849 | MFV_LOGE("[MFV][ERROR] close enc isr event error\n"); | |
1850 | } | |
1851 | ||
1852 | ||
1853 | ||
1854 | #ifdef CONFIG_HAS_EARLYSUSPEND | |
1855 | unregister_early_suspend(&vcodec_early_suspend_handler); | |
1856 | #endif | |
1857 | ||
1858 | #ifdef CONFIG_MTK_HIBERNATION | |
1859 | unregister_swsusp_restore_noirq_func(ID_M_VCODEC); | |
1860 | #endif | |
1861 | } | |
1862 | ||
1863 | module_init(vcodec_driver_init); | |
1864 | module_exit(vcodec_driver_exit); | |
1865 | MODULE_AUTHOR("Legis, Lu <legis.lu@mediatek.com>"); | |
1866 | MODULE_DESCRIPTION("MT8127 Vcodec Driver"); | |
1867 | MODULE_LICENSE("GPL"); |