Commit | Line | Data |
---|---|---|
b9164398 NQ |
1 | /* |
2 | * drivers/amlogic/amports/vmpeg12.c | |
3 | * | |
4 | * Copyright (C) 2015 Amlogic, Inc. All rights reserved. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
e0614bf7 | 16 | */ |
b9164398 NQ |
17 | |
18 | #include <linux/kernel.h> | |
19 | #include <linux/types.h> | |
20 | #include <linux/errno.h> | |
21 | #include <linux/interrupt.h> | |
22 | #include <linux/timer.h> | |
23 | #include <linux/kfifo.h> | |
24 | #include <linux/platform_device.h> | |
25 | #include <linux/amlogic/media/frame_sync/ptsserv.h> | |
26 | #include <linux/amlogic/media/utils/amstream.h> | |
27 | #include <linux/amlogic/media/canvas/canvas.h> | |
28 | #include <linux/module.h> | |
29 | #include <linux/amlogic/media/vfm/vframe.h> | |
30 | #include <linux/amlogic/media/vfm/vframe_provider.h> | |
31 | #include <linux/amlogic/media/vfm/vframe_receiver.h> | |
32 | #include <linux/amlogic/cpu_version.h> | |
33 | #include <linux/amlogic/media/codec_mm/codec_mm.h> | |
34 | #include <linux/dma-mapping.h> | |
a6c89e96 | 35 | #include <linux/slab.h> |
b9164398 NQ |
36 | #include <linux/amlogic/media/utils/vdec_reg.h> |
37 | #include "vmpeg12.h" | |
38 | #include <linux/amlogic/media/registers/register.h> | |
39 | #include "../../../stream_input/amports/amports_priv.h" | |
fe96802b NQ |
40 | #include "../utils/decoder_mmu_box.h" |
41 | #include "../utils/decoder_bmmu_box.h" | |
a6c89e96 | 42 | #include <linux/uaccess.h> |
fe96802b | 43 | #include <linux/amlogic/media/codec_mm/configs.h> |
668e656d | 44 | #include <linux/amlogic/tee.h> |
b9164398 | 45 | |
a093654a TG |
46 | #include <trace/events/meson_atrace.h> |
47 | ||
48 | ||
b9164398 NQ |
49 | #ifdef CONFIG_AM_VDEC_MPEG12_LOG |
50 | #define AMLOG | |
51 | #define LOG_LEVEL_VAR amlog_level_vmpeg | |
52 | #define LOG_MASK_VAR amlog_mask_vmpeg | |
53 | #define LOG_LEVEL_ERROR 0 | |
54 | #define LOG_LEVEL_INFO 1 | |
55 | #define LOG_LEVEL_DESC "0:ERROR, 1:INFO" | |
56 | #endif | |
57 | #include <linux/amlogic/media/utils/amlog.h> | |
58 | MODULE_AMLOG(LOG_LEVEL_ERROR, 0, LOG_LEVEL_DESC, LOG_DEFAULT_MASK_DESC); | |
59 | ||
60 | #include "../utils/amvdec.h" | |
61 | #include "../utils/vdec.h" | |
6fff1c64 | 62 | #include "../utils/firmware.h" |
63e810c0 | 63 | #include "../../../common/chips/decoder_cpu_ver_info.h" |
b9164398 NQ |
64 | |
65 | #define DRIVER_NAME "amvdec_mpeg12" | |
66 | #define MODULE_NAME "amvdec_mpeg12" | |
67 | ||
68 | /* protocol registers */ | |
69 | #define MREG_SEQ_INFO AV_SCRATCH_4 | |
70 | #define MREG_PIC_INFO AV_SCRATCH_5 | |
71 | #define MREG_PIC_WIDTH AV_SCRATCH_6 | |
72 | #define MREG_PIC_HEIGHT AV_SCRATCH_7 | |
73 | #define MREG_BUFFERIN AV_SCRATCH_8 | |
74 | #define MREG_BUFFEROUT AV_SCRATCH_9 | |
75 | ||
76 | #define MREG_CMD AV_SCRATCH_A | |
77 | #define MREG_CO_MV_START AV_SCRATCH_B | |
78 | #define MREG_ERROR_COUNT AV_SCRATCH_C | |
79 | #define MREG_FRAME_OFFSET AV_SCRATCH_D | |
80 | #define MREG_WAIT_BUFFER AV_SCRATCH_E | |
81 | #define MREG_FATAL_ERROR AV_SCRATCH_F | |
a6c89e96 | 82 | #define MREG_FORCE_I_RDY AV_SCRATCH_G |
b9164398 NQ |
83 | |
84 | #define PICINFO_ERROR 0x80000000 | |
85 | #define PICINFO_TYPE_MASK 0x00030000 | |
86 | #define PICINFO_TYPE_I 0x00000000 | |
87 | #define PICINFO_TYPE_P 0x00010000 | |
88 | #define PICINFO_TYPE_B 0x00020000 | |
89 | ||
90 | #define PICINFO_PROG 0x8000 | |
91 | #define PICINFO_RPT_FIRST 0x4000 | |
92 | #define PICINFO_TOP_FIRST 0x2000 | |
93 | #define PICINFO_FRAME 0x1000 | |
94 | ||
95 | #define SEQINFO_EXT_AVAILABLE 0x80000000 | |
96 | #define SEQINFO_PROG 0x00010000 | |
fe96802b | 97 | #define CCBUF_SIZE (5*1024) |
b9164398 NQ |
98 | |
99 | #define VF_POOL_SIZE 32 | |
100 | #define DECODE_BUFFER_NUM_MAX 8 | |
101 | #define PUT_INTERVAL (HZ/100) | |
fe96802b NQ |
102 | #define WORKSPACE_SIZE (2*SZ_64K) |
103 | #define MAX_BMMU_BUFFER_NUM (DECODE_BUFFER_NUM_MAX + 1) | |
104 | ||
b9164398 NQ |
105 | |
106 | #define INCPTR(p) ptr_atomic_wrap_inc(&p) | |
107 | ||
108 | #define DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE 0x0002 | |
109 | #define DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE 0x0004 | |
110 | #define DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE 0x0008 | |
111 | #define DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE 0x0010 | |
112 | #define DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE 0x0020 | |
113 | #define DEC_CONTROL_INTERNAL_MASK 0x0fff | |
114 | #define DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE 0x1000 | |
115 | ||
116 | #define INTERLACE_SEQ_ALWAYS | |
117 | ||
118 | #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */ | |
119 | #define NV21 | |
120 | #endif | |
fe96802b | 121 | |
b9164398 NQ |
122 | |
123 | enum { | |
124 | FRAME_REPEAT_TOP, | |
125 | FRAME_REPEAT_BOT, | |
126 | FRAME_REPEAT_NONE | |
127 | }; | |
128 | ||
129 | static struct vframe_s *vmpeg_vf_peek(void *); | |
130 | static struct vframe_s *vmpeg_vf_get(void *); | |
131 | static void vmpeg_vf_put(struct vframe_s *, void *); | |
132 | static int vmpeg_vf_states(struct vframe_states *states, void *); | |
133 | static int vmpeg_event_cb(int type, void *data, void *private_data); | |
134 | ||
fe96802b | 135 | static int vmpeg12_prot_init(void); |
b9164398 NQ |
136 | static void vmpeg12_local_init(void); |
137 | ||
138 | static const char vmpeg12_dec_id[] = "vmpeg12-dev"; | |
139 | #define PROVIDER_NAME "decoder.mpeg12" | |
140 | static const struct vframe_operations_s vmpeg_vf_provider = { | |
141 | .peek = vmpeg_vf_peek, | |
142 | .get = vmpeg_vf_get, | |
143 | .put = vmpeg_vf_put, | |
144 | .event_cb = vmpeg_event_cb, | |
145 | .vf_states = vmpeg_vf_states, | |
146 | }; | |
fe96802b | 147 | static void *mm_blk_handle; |
b9164398 NQ |
148 | static struct vframe_provider_s vmpeg_vf_prov; |
149 | ||
150 | static DECLARE_KFIFO(newframe_q, struct vframe_s *, VF_POOL_SIZE); | |
151 | static DECLARE_KFIFO(display_q, struct vframe_s *, VF_POOL_SIZE); | |
152 | static DECLARE_KFIFO(recycle_q, struct vframe_s *, VF_POOL_SIZE); | |
153 | ||
154 | static const u32 frame_rate_tab[16] = { | |
fe96802b NQ |
155 | 96000 / 30, 96000000 / 23976, 96000 / 24, 96000 / 25, |
156 | 9600000 / 2997, 96000 / 30, 96000 / 50, 9600000 / 5994, | |
b9164398 NQ |
157 | 96000 / 60, |
158 | /* > 8 reserved, use 24 */ | |
159 | 96000 / 24, 96000 / 24, 96000 / 24, 96000 / 24, | |
160 | 96000 / 24, 96000 / 24, 96000 / 24 | |
161 | }; | |
162 | ||
163 | static struct vframe_s vfpool[VF_POOL_SIZE]; | |
164 | static struct vframe_s vfpool2[VF_POOL_SIZE]; | |
165 | static int cur_pool_idx; | |
166 | static s32 vfbuf_use[DECODE_BUFFER_NUM_MAX]; | |
167 | static u32 dec_control; | |
168 | static u32 frame_width, frame_height, frame_dur, frame_prog; | |
169 | static u32 saved_resolution; | |
170 | static struct timer_list recycle_timer; | |
171 | static u32 stat; | |
fe96802b NQ |
172 | static u32 buf_size = 32 * 1024 * 1024; |
173 | static u32 ccbuf_phyAddress; | |
b9164398 NQ |
174 | static void *ccbuf_phyAddress_virt; |
175 | static int ccbuf_phyAddress_is_remaped_nocache; | |
fe96802b NQ |
176 | static u32 lastpts; |
177 | static u32 fr_hint_status; | |
a6c89e96 | 178 | static u32 last_offset; |
fe96802b | 179 | |
b9164398 NQ |
180 | |
181 | static DEFINE_SPINLOCK(lock); | |
182 | ||
183 | static u32 frame_rpt_state; | |
184 | ||
185 | static struct dec_sysinfo vmpeg12_amstream_dec_info; | |
fe96802b | 186 | static struct vdec_info *gvs; |
a6c89e96 | 187 | static struct vdec_s *vdec; |
b9164398 NQ |
188 | |
189 | /* for error handling */ | |
190 | static s32 frame_force_skip_flag; | |
191 | static s32 error_frame_skip_level; | |
192 | static s32 wait_buffer_counter; | |
193 | static u32 first_i_frame_ready; | |
a6c89e96 | 194 | static u32 force_first_i_ready; |
b9164398 | 195 | |
fe96802b NQ |
196 | static struct work_struct userdata_push_work; |
197 | static struct work_struct notify_work; | |
198 | static struct work_struct reset_work; | |
a994f6d6 | 199 | static struct work_struct set_clk_work; |
d481db31 | 200 | static bool is_reset; |
fe96802b | 201 | |
4522fc84 PY |
202 | static DEFINE_MUTEX(userdata_mutex); |
203 | ||
204 | static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len); | |
205 | ||
a6c89e96 NQ |
206 | struct mpeg12_userdata_recored_t { |
207 | struct userdata_meta_info_t meta_info; | |
208 | u32 rec_start; | |
209 | u32 rec_len; | |
210 | }; | |
211 | ||
212 | #define USERDATA_FIFO_NUM 256 | |
213 | ||
214 | struct mpeg12_userdata_info_t { | |
215 | struct mpeg12_userdata_recored_t records[USERDATA_FIFO_NUM]; | |
216 | u8 *data_buf; | |
217 | u8 *data_buf_end; | |
218 | u32 buf_len; | |
219 | u32 read_index; | |
220 | u32 write_index; | |
221 | u32 last_wp; | |
222 | }; | |
223 | ||
224 | static struct mpeg12_userdata_info_t *p_userdata_mgr; | |
225 | ||
226 | ||
b9164398 NQ |
227 | static inline int pool_index(struct vframe_s *vf) |
228 | { | |
229 | if ((vf >= &vfpool[0]) && (vf <= &vfpool[VF_POOL_SIZE - 1])) | |
230 | return 0; | |
231 | else if ((vf >= &vfpool2[0]) && (vf <= &vfpool2[VF_POOL_SIZE - 1])) | |
232 | return 1; | |
233 | else | |
234 | return -1; | |
235 | } | |
236 | ||
237 | static inline u32 index2canvas(u32 index) | |
238 | { | |
239 | const u32 canvas_tab[8] = { | |
240 | #ifdef NV21 | |
241 | 0x010100, 0x030302, 0x050504, 0x070706, | |
242 | 0x090908, 0x0b0b0a, 0x0d0d0c, 0x0f0f0e | |
243 | #else | |
244 | 0x020100, 0x050403, 0x080706, 0x0b0a09, | |
245 | 0x0e0d0c, 0x11100f, 0x141312, 0x171615 | |
246 | #endif | |
247 | }; | |
248 | ||
249 | return canvas_tab[index]; | |
250 | } | |
251 | ||
252 | static void set_frame_info(struct vframe_s *vf) | |
253 | { | |
e0614bf7 | 254 | unsigned int ar_bits; |
b9164398 NQ |
255 | u32 temp; |
256 | ||
257 | #ifdef CONFIG_AM_VDEC_MPEG12_LOG | |
258 | bool first = (frame_width == 0) && (frame_height == 0); | |
259 | #endif | |
260 | temp = READ_VREG(MREG_PIC_WIDTH); | |
261 | if (temp > 1920) | |
262 | vf->width = frame_width = 1920; | |
263 | else | |
264 | vf->width = frame_width = temp; | |
265 | ||
266 | temp = READ_VREG(MREG_PIC_HEIGHT); | |
267 | if (temp > 1088) | |
268 | vf->height = frame_height = 1088; | |
269 | else | |
270 | vf->height = frame_height = temp; | |
271 | ||
272 | vf->flag = 0; | |
273 | ||
274 | if (frame_dur > 0) | |
275 | vf->duration = frame_dur; | |
276 | else { | |
fe96802b NQ |
277 | int index = (READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf; |
278 | vf->duration = frame_dur = frame_rate_tab[index]; | |
279 | schedule_work(¬ify_work); | |
b9164398 NQ |
280 | } |
281 | ||
fe96802b NQ |
282 | gvs->frame_dur = vf->duration; |
283 | ||
b9164398 NQ |
284 | ar_bits = READ_VREG(MREG_SEQ_INFO) & 0xf; |
285 | ||
286 | if (ar_bits == 0x2) | |
287 | vf->ratio_control = 0xc0 << DISP_RATIO_ASPECT_RATIO_BIT; | |
288 | ||
289 | else if (ar_bits == 0x3) | |
290 | vf->ratio_control = 0x90 << DISP_RATIO_ASPECT_RATIO_BIT; | |
291 | ||
292 | else if (ar_bits == 0x4) | |
293 | vf->ratio_control = 0x74 << DISP_RATIO_ASPECT_RATIO_BIT; | |
294 | ||
295 | else | |
296 | vf->ratio_control = 0; | |
297 | ||
298 | amlog_level_if(first, LOG_LEVEL_INFO, | |
299 | "mpeg2dec: w(%d), h(%d), dur(%d), dur-ES(%d)\n", | |
300 | frame_width, frame_height, frame_dur, | |
301 | frame_rate_tab[(READ_VREG(MREG_SEQ_INFO) >> 4) & 0xf]); | |
302 | } | |
303 | ||
304 | static bool error_skip(u32 info, struct vframe_s *vf) | |
305 | { | |
306 | if (error_frame_skip_level) { | |
307 | /* skip error frame */ | |
308 | if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) { | |
309 | if ((info & PICINFO_ERROR) == 0) { | |
310 | if ((info & PICINFO_TYPE_MASK) == | |
311 | PICINFO_TYPE_I) | |
312 | frame_force_skip_flag = 0; | |
313 | } else { | |
314 | if (error_frame_skip_level >= 2) | |
315 | frame_force_skip_flag = 1; | |
316 | } | |
317 | if ((info & PICINFO_ERROR) || (frame_force_skip_flag)) | |
318 | return true; | |
319 | } | |
320 | } | |
321 | ||
322 | return false; | |
323 | } | |
324 | ||
a6c89e96 NQ |
325 | |
326 | static void aml_swap_data(uint8_t *user_data, int ud_size) | |
327 | { | |
328 | int swap_blocks, i, j, k, m; | |
329 | unsigned char c_temp; | |
330 | ||
331 | /* swap byte order */ | |
332 | swap_blocks = ud_size / 8; | |
333 | for (i = 0; i < swap_blocks; i++) { | |
334 | j = i * 8; | |
335 | k = j + 7; | |
336 | for (m = 0; m < 4; m++) { | |
337 | c_temp = user_data[j]; | |
338 | user_data[j++] = user_data[k]; | |
339 | user_data[k--] = c_temp; | |
340 | } | |
341 | } | |
342 | } | |
343 | ||
344 | /* | |
345 | #define DUMP_USER_DATA | |
346 | */ | |
347 | #ifdef DUMP_USER_DATA | |
348 | static int last_wp; | |
349 | #define DUMP_USER_DATA_HEX | |
350 | ||
351 | ||
352 | #ifdef DUMP_USER_DATA_HEX | |
353 | static void print_data(unsigned char *pdata, | |
354 | int len, | |
355 | unsigned int flag, | |
356 | unsigned int duration, | |
357 | unsigned int vpts, | |
358 | unsigned int vpts_valid, | |
bbee6a9b NQ |
359 | int rec_id, |
360 | u32 reference) | |
a6c89e96 NQ |
361 | { |
362 | int nLeft; | |
363 | ||
364 | nLeft = len; | |
365 | ||
bbee6a9b | 366 | pr_info("%d len:%d, flag:0x%x, dur:%d, vpts:0x%x, valid:%d, refer:%d\n", |
a6c89e96 | 367 | rec_id, len, flag, |
bbee6a9b NQ |
368 | duration, vpts, vpts_valid, |
369 | reference); | |
a6c89e96 NQ |
370 | while (nLeft >= 16) { |
371 | pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", | |
372 | pdata[0], pdata[1], pdata[2], pdata[3], | |
373 | pdata[4], pdata[5], pdata[6], pdata[7], | |
374 | pdata[8], pdata[9], pdata[10], pdata[11], | |
375 | pdata[12], pdata[13], pdata[14], pdata[15]); | |
376 | nLeft -= 16; | |
377 | pdata += 16; | |
378 | } | |
379 | ||
380 | ||
381 | while (nLeft > 0) { | |
382 | pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n", | |
383 | pdata[0], pdata[1], pdata[2], pdata[3], | |
384 | pdata[4], pdata[5], pdata[6], pdata[7]); | |
385 | nLeft -= 8; | |
386 | pdata += 8; | |
387 | } | |
388 | } | |
389 | #endif | |
390 | ||
391 | ||
bbee6a9b NQ |
392 | #define DEBUG_CC_DUMP_ASCII |
393 | ||
394 | #ifdef DEBUG_CC_DUMP_ASCII | |
395 | static int vbi_to_ascii(int c) | |
396 | { | |
397 | if (c < 0) | |
398 | return '?'; | |
399 | ||
400 | c &= 0x7F; | |
401 | ||
402 | if (c < 0x20 || c >= 0x7F) | |
403 | return '.'; | |
404 | ||
405 | return c; | |
406 | } | |
407 | ||
408 | static void dump_cc_ascii(const uint8_t *buf, int poc) | |
409 | { | |
410 | int cc_flag; | |
411 | int cc_count; | |
412 | int i; | |
413 | int szAscii[32]; | |
414 | int index = 0; | |
415 | ||
416 | cc_flag = buf[1] & 0x40; | |
417 | if (!cc_flag) { | |
418 | pr_info("### cc_flag is invalid\n"); | |
419 | return; | |
420 | } | |
421 | cc_count = buf[1] & 0x1f; | |
422 | ||
423 | for (i = 0; i < cc_count; ++i) { | |
424 | unsigned int b0; | |
425 | unsigned int cc_valid; | |
426 | unsigned int cc_type; | |
427 | unsigned char cc_data1; | |
428 | unsigned char cc_data2; | |
429 | ||
430 | b0 = buf[3 + i * 3]; | |
431 | cc_valid = b0 & 4; | |
432 | cc_type = b0 & 3; | |
433 | cc_data1 = buf[4 + i * 3]; | |
434 | cc_data2 = buf[5 + i * 3]; | |
435 | ||
436 | ||
437 | if (cc_type == 0) { | |
438 | /* NTSC pair, Line 21 */ | |
439 | szAscii[index++] = vbi_to_ascii(cc_data1); | |
440 | szAscii[index++] = vbi_to_ascii(cc_data2); | |
441 | if ((!cc_valid) || (i >= 3)) | |
442 | break; | |
443 | } | |
444 | } | |
445 | switch (index) { | |
446 | case 8: | |
447 | pr_info("push poc:%d : %c %c %c %c %c %c %c %c\n", | |
448 | poc, | |
449 | szAscii[0], szAscii[1], szAscii[2], szAscii[3], | |
450 | szAscii[4], szAscii[5], szAscii[6], szAscii[7]); | |
451 | break; | |
452 | case 7: | |
453 | pr_info("push poc:%d : %c %c %c %c %c %c %c\n", | |
454 | poc, | |
455 | szAscii[0], szAscii[1], szAscii[2], szAscii[3], | |
456 | szAscii[4], szAscii[5], szAscii[6]); | |
457 | break; | |
458 | case 6: | |
459 | pr_info("push poc:%d : %c %c %c %c %c %c\n", poc, | |
460 | szAscii[0], szAscii[1], szAscii[2], szAscii[3], | |
461 | szAscii[4], szAscii[5]); | |
462 | break; | |
463 | case 5: | |
464 | pr_info("push poc:%d : %c %c %c %c %c\n", poc, | |
465 | szAscii[0], szAscii[1], szAscii[2], szAscii[3], | |
466 | szAscii[4]); | |
467 | break; | |
468 | case 4: | |
469 | pr_info("push poc:%d : %c %c %c %c\n", poc, | |
470 | szAscii[0], szAscii[1], szAscii[2], szAscii[3]); | |
471 | break; | |
472 | case 3: | |
473 | pr_info("push poc:%d : %c %c %c\n", poc, | |
474 | szAscii[0], szAscii[1], szAscii[2]); | |
475 | break; | |
476 | case 2: | |
477 | pr_info("push poc:%d : %c %c\n", poc, | |
478 | szAscii[0], szAscii[1]); | |
479 | break; | |
480 | case 1: | |
481 | pr_info("push poc:%d : %c\n", poc, szAscii[0]); | |
482 | break; | |
483 | default: | |
484 | pr_info("push poc:%d and no CC data: index = %d\n", | |
485 | poc, index); | |
486 | break; | |
487 | } | |
488 | } | |
489 | #endif | |
490 | ||
491 | ||
492 | static int is_atsc(u8 *pdata) | |
493 | { | |
494 | if ((pdata[0] == 0x47) && | |
495 | (pdata[1] == 0x41) && | |
496 | (pdata[2] == 0x39) && | |
497 | (pdata[3] == 0x34)) | |
498 | return 1; | |
499 | else | |
500 | return 0; | |
501 | } | |
502 | /* | |
503 | #define DUMP_HEAD_INFO_DATA | |
504 | */ | |
a6c89e96 NQ |
505 | static void dump_data(u8 *pdata, |
506 | unsigned int user_data_length, | |
507 | unsigned int flag, | |
508 | unsigned int duration, | |
509 | unsigned int vpts, | |
510 | unsigned int vpts_valid, | |
bbee6a9b NQ |
511 | int rec_id, |
512 | u32 reference) | |
a6c89e96 NQ |
513 | { |
514 | unsigned char szBuf[256]; | |
515 | ||
516 | ||
517 | memset(szBuf, 0, 256); | |
518 | memcpy(szBuf, pdata, user_data_length); | |
519 | ||
520 | aml_swap_data(szBuf, user_data_length); | |
521 | #ifdef DUMP_USER_DATA_HEX | |
522 | print_data(szBuf, | |
523 | user_data_length, | |
524 | flag, | |
525 | duration, | |
526 | vpts, | |
527 | vpts_valid, | |
bbee6a9b NQ |
528 | rec_id, |
529 | reference); | |
a6c89e96 NQ |
530 | #endif |
531 | ||
532 | #ifdef DEBUG_CC_DUMP_ASCII | |
bbee6a9b NQ |
533 | #ifdef DUMP_HEAD_INFO_DATA |
534 | if (is_atsc(szBuf+8)) | |
535 | dump_cc_ascii(szBuf+8+4, reference); | |
536 | #else | |
537 | if (is_atsc(szBuf)) | |
538 | dump_cc_ascii(szBuf+4, reference); | |
539 | #endif | |
a6c89e96 NQ |
540 | #endif |
541 | } | |
542 | ||
543 | ||
a6c89e96 | 544 | |
a6c89e96 NQ |
545 | |
546 | #define MAX_USER_DATA_SIZE 1572864 | |
547 | static void *user_data_buf; | |
548 | static unsigned char *pbuf_start; | |
549 | static int total_len; | |
550 | static int bskip; | |
551 | static int n_userdata_id; | |
552 | ||
553 | static void reset_user_data_buf(void) | |
554 | { | |
555 | total_len = 0; | |
556 | pbuf_start = user_data_buf; | |
557 | bskip = 0; | |
558 | n_userdata_id = 0; | |
559 | } | |
560 | ||
bbee6a9b NQ |
561 | static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta, |
562 | u32 reference) | |
a6c89e96 NQ |
563 | { |
564 | u32 *pLen; | |
565 | int info_cnt; | |
566 | u8 *pbuf_end; | |
567 | ||
568 | if (!user_data_buf) | |
569 | return; | |
570 | ||
571 | if (bskip) { | |
572 | pr_info("over size, skip\n"); | |
573 | return; | |
574 | } | |
575 | info_cnt = 0; | |
576 | pLen = (u32 *)pbuf_start; | |
577 | ||
578 | *pLen = len; | |
579 | pbuf_start += sizeof(u32); | |
580 | info_cnt++; | |
581 | pLen++; | |
582 | ||
583 | *pLen = pmeta->duration; | |
584 | pbuf_start += sizeof(u32); | |
585 | info_cnt++; | |
586 | pLen++; | |
587 | ||
588 | *pLen = pmeta->flags; | |
589 | pbuf_start += sizeof(u32); | |
590 | info_cnt++; | |
591 | pLen++; | |
592 | ||
593 | *pLen = pmeta->vpts; | |
594 | pbuf_start += sizeof(u32); | |
595 | info_cnt++; | |
596 | pLen++; | |
597 | ||
598 | *pLen = pmeta->vpts_valid; | |
599 | pbuf_start += sizeof(u32); | |
600 | info_cnt++; | |
601 | pLen++; | |
602 | ||
603 | ||
604 | *pLen = n_userdata_id; | |
605 | pbuf_start += sizeof(u32); | |
606 | info_cnt++; | |
607 | pLen++; | |
608 | ||
bbee6a9b NQ |
609 | *pLen = reference; |
610 | pbuf_start += sizeof(u32); | |
611 | info_cnt++; | |
612 | pLen++; | |
613 | ||
a6c89e96 NQ |
614 | |
615 | ||
616 | pbuf_end = (u8 *)ccbuf_phyAddress_virt + CCBUF_SIZE; | |
617 | if (pdata + len > pbuf_end) { | |
618 | int first_section_len; | |
619 | ||
620 | first_section_len = pbuf_end - pdata; | |
621 | memcpy(pbuf_start, pdata, first_section_len); | |
622 | pdata = (u8 *)ccbuf_phyAddress_virt; | |
623 | pbuf_start += first_section_len; | |
624 | memcpy(pbuf_start, pdata, len - first_section_len); | |
625 | pbuf_start += len - first_section_len; | |
626 | } else { | |
627 | memcpy(pbuf_start, pdata, len); | |
628 | pbuf_start += len; | |
629 | } | |
630 | ||
631 | total_len += len + info_cnt * sizeof(u32); | |
632 | if (total_len >= MAX_USER_DATA_SIZE-4096) | |
633 | bskip = 1; | |
634 | } | |
635 | ||
bbee6a9b NQ |
636 | static void dump_userdata_info(void *puser_data, |
637 | int len, | |
638 | struct userdata_meta_info_t *pmeta, | |
639 | u32 reference) | |
640 | { | |
641 | u8 *pstart; | |
642 | ||
643 | pstart = (u8 *)puser_data; | |
644 | ||
645 | #ifdef DUMP_HEAD_INFO_DATA | |
646 | push_to_buf(pstart, len, pmeta, reference); | |
647 | #else | |
648 | push_to_buf(pstart+8, len - 8, pmeta, reference); | |
649 | #endif | |
650 | } | |
651 | ||
a6c89e96 NQ |
652 | static void show_user_data_buf(void) |
653 | { | |
654 | u8 *pbuf; | |
655 | int len; | |
656 | unsigned int flag; | |
657 | unsigned int duration; | |
658 | unsigned int vpts; | |
659 | unsigned int vpts_valid; | |
660 | int rec_id; | |
bbee6a9b | 661 | u32 reference; |
a6c89e96 NQ |
662 | |
663 | pr_info("show user data buf\n"); | |
664 | pbuf = user_data_buf; | |
665 | ||
666 | while (pbuf < pbuf_start) { | |
667 | u32 *pLen; | |
668 | ||
669 | pLen = (u32 *)pbuf; | |
670 | ||
671 | len = *pLen; | |
672 | pLen++; | |
673 | pbuf += sizeof(u32); | |
674 | ||
675 | duration = *pLen; | |
676 | pLen++; | |
677 | pbuf += sizeof(u32); | |
678 | ||
679 | flag = *pLen; | |
680 | pLen++; | |
681 | pbuf += sizeof(u32); | |
682 | ||
683 | vpts = *pLen; | |
684 | pLen++; | |
685 | pbuf += sizeof(u32); | |
686 | ||
687 | vpts_valid = *pLen; | |
688 | pLen++; | |
689 | pbuf += sizeof(u32); | |
690 | ||
691 | rec_id = *pLen; | |
692 | pLen++; | |
693 | pbuf += sizeof(u32); | |
694 | ||
bbee6a9b NQ |
695 | reference = *pLen; |
696 | pLen++; | |
697 | pbuf += sizeof(u32); | |
698 | ||
699 | ||
700 | dump_data(pbuf, len, flag, duration, | |
701 | vpts, vpts_valid, rec_id, reference); | |
a6c89e96 | 702 | pbuf += len; |
bbee6a9b | 703 | msleep(30); |
a6c89e96 NQ |
704 | } |
705 | } | |
706 | #endif | |
707 | ||
bbee6a9b NQ |
708 | static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, |
709 | int wp, | |
710 | u32 reference); | |
a6c89e96 NQ |
711 | /* |
712 | #define PRINT_HEAD_INFO | |
713 | */ | |
fe96802b NQ |
714 | static void userdata_push_do_work(struct work_struct *work) |
715 | { | |
716 | u32 reg; | |
a6c89e96 NQ |
717 | u32 offset, pts; |
718 | u64 pts_us64 = 0; | |
719 | u8 *pdata; | |
720 | u8 head_info[8]; | |
721 | struct userdata_meta_info_t meta_info; | |
722 | u32 wp; | |
723 | u32 index; | |
724 | u32 picture_struct; | |
725 | u32 reference; | |
726 | u32 picture_type; | |
727 | u32 temp; | |
728 | #ifdef PRINT_HEAD_INFO | |
729 | u8 *ptype_str; | |
730 | #endif | |
731 | memset(&meta_info, 0, sizeof(meta_info)); | |
fe96802b | 732 | |
a6c89e96 | 733 | meta_info.duration = frame_dur; |
fe96802b | 734 | |
a6c89e96 NQ |
735 | reg = READ_VREG(AV_SCRATCH_M); |
736 | meta_info.flags = ((reg >> 30) << 1); | |
737 | meta_info.flags |= (VFORMAT_MPEG12 << 3); | |
738 | /* check top_field_first flag */ | |
739 | if ((reg >> 28) & 0x1) { | |
740 | meta_info.flags |= (1 << 10); | |
741 | meta_info.flags |= (((reg >> 29) & 0x1) << 11); | |
742 | } | |
743 | ||
744 | offset = READ_VREG(AV_SCRATCH_N); | |
745 | if (offset != last_offset) { | |
746 | meta_info.flags |= 1; | |
747 | last_offset = offset; | |
748 | } | |
749 | ||
750 | if (pts_pickout_offset_us64 | |
751 | (PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) { | |
752 | pr_info("pick out pts failed by offset = 0x%x\n", offset); | |
753 | pts = -1; | |
754 | meta_info.vpts_valid = 0; | |
755 | } else | |
756 | meta_info.vpts_valid = 1; | |
757 | meta_info.vpts = pts; | |
fe96802b NQ |
758 | |
759 | if (!ccbuf_phyAddress_is_remaped_nocache && | |
760 | ccbuf_phyAddress && | |
761 | ccbuf_phyAddress_virt) { | |
762 | codec_mm_dma_flush( | |
763 | ccbuf_phyAddress_virt, | |
764 | CCBUF_SIZE, | |
765 | DMA_FROM_DEVICE); | |
766 | } | |
a6c89e96 | 767 | |
4522fc84 | 768 | mutex_lock(&userdata_mutex); |
a35da9f0 | 769 | if (p_userdata_mgr && ccbuf_phyAddress_virt) { |
bbee6a9b NQ |
770 | int new_wp; |
771 | ||
772 | new_wp = reg & 0xffff; | |
773 | if (new_wp < p_userdata_mgr->last_wp) | |
774 | pdata = (u8 *)ccbuf_phyAddress_virt; | |
775 | else | |
776 | pdata = (u8 *)ccbuf_phyAddress_virt + | |
777 | p_userdata_mgr->last_wp; | |
a6c89e96 NQ |
778 | memcpy(head_info, pdata, 8); |
779 | } else | |
780 | memset(head_info, 0, 8); | |
4522fc84 | 781 | mutex_unlock(&userdata_mutex); |
a6c89e96 NQ |
782 | aml_swap_data(head_info, 8); |
783 | ||
784 | wp = (head_info[0] << 8 | head_info[1]); | |
785 | index = (head_info[2] << 8 | head_info[3]); | |
786 | ||
787 | picture_struct = (head_info[6] << 8 | head_info[7]); | |
788 | temp = (head_info[4] << 8 | head_info[5]); | |
789 | reference = temp & 0x3FF; | |
790 | picture_type = (temp >> 10) & 0x7; | |
791 | ||
792 | #if 0 | |
bbee6a9b | 793 | pr_info("index = %d, wp = %d, ref = %d, type = %d, struct = 0x%x, vpts:0x%x\n", |
a6c89e96 | 794 | index, wp, reference, |
bbee6a9b | 795 | picture_type, picture_struct, meta_info.vpts); |
a6c89e96 NQ |
796 | #endif |
797 | switch (picture_type) { | |
798 | case 1: | |
799 | /* pr_info("I type, pos:%d\n", | |
800 | (meta_info.flags>>1)&0x3); */ | |
801 | meta_info.flags |= (1<<7); | |
802 | #ifdef PRINT_HEAD_INFO | |
803 | ptype_str = " I"; | |
804 | #endif | |
805 | break; | |
806 | case 2: | |
807 | /* pr_info("P type, pos:%d\n", | |
808 | (meta_info.flags>>1)&0x3); */ | |
809 | meta_info.flags |= (2<<7); | |
810 | #ifdef PRINT_HEAD_INFO | |
811 | ptype_str = " P"; | |
812 | #endif | |
813 | break; | |
814 | case 3: | |
815 | /* pr_info("B type, pos:%d\n", | |
816 | (meta_info.flags>>1)&0x3); */ | |
817 | meta_info.flags |= (3<<7); | |
818 | #ifdef PRINT_HEAD_INFO | |
819 | ptype_str = " B"; | |
820 | #endif | |
821 | break; | |
822 | case 4: | |
823 | /* pr_info("D type, pos:%d\n", | |
824 | (meta_info.flags>>1)&0x3); */ | |
825 | meta_info.flags |= (4<<7); | |
826 | #ifdef PRINT_HEAD_INFO | |
827 | ptype_str = " D"; | |
828 | #endif | |
829 | break; | |
830 | default: | |
831 | /* pr_info("Unknown type:0x%x, pos:%d\n", | |
832 | pheader->picture_coding_type, | |
833 | (meta_info.flags>>1)&0x3); */ | |
834 | #ifdef PRINT_HEAD_INFO | |
835 | ptype_str = " U"; | |
836 | #endif | |
837 | break; | |
838 | } | |
839 | #ifdef PRINT_HEAD_INFO | |
bbee6a9b | 840 | pr_info("ref:%d, type:%s, ext:%d, offset:0x%x, first:%d, id:%d\n", |
a6c89e96 NQ |
841 | reference, ptype_str, |
842 | (reg >> 30), offset, | |
bbee6a9b NQ |
843 | (reg >> 28)&0x3, |
844 | n_userdata_id); | |
a6c89e96 | 845 | #endif |
bbee6a9b | 846 | vmpeg12_add_userdata(meta_info, reg & 0xffff, reference); |
a6c89e96 NQ |
847 | |
848 | WRITE_VREG(AV_SCRATCH_M, 0); | |
fe96802b NQ |
849 | } |
850 | ||
851 | static void vmpeg12_notify_work(struct work_struct *work) | |
852 | { | |
853 | pr_info("frame duration changed %d\n", frame_dur); | |
854 | if (fr_hint_status == VDEC_NEED_HINT) { | |
855 | vf_notify_receiver(PROVIDER_NAME, | |
856 | VFRAME_EVENT_PROVIDER_FR_HINT, | |
857 | (void *)((unsigned long)frame_dur)); | |
858 | fr_hint_status = VDEC_HINTED; | |
859 | } | |
860 | return; | |
861 | } | |
b9164398 NQ |
862 | static irqreturn_t vmpeg12_isr(int irq, void *dev_id) |
863 | { | |
864 | u32 reg, info, seqinfo, offset, pts, pts_valid = 0; | |
865 | struct vframe_s *vf; | |
866 | u64 pts_us64 = 0; | |
a8f62ee0 | 867 | u32 frame_size; |
b9164398 NQ |
868 | |
869 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
870 | ||
871 | reg = READ_VREG(MREG_BUFFEROUT); | |
872 | ||
a6c89e96 | 873 | if (reg) { |
b9164398 NQ |
874 | info = READ_VREG(MREG_PIC_INFO); |
875 | offset = READ_VREG(MREG_FRAME_OFFSET); | |
fe96802b | 876 | seqinfo = READ_VREG(MREG_SEQ_INFO); |
b9164398 NQ |
877 | |
878 | if ((first_i_frame_ready == 0) && | |
879 | ((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) && | |
880 | ((info & PICINFO_ERROR) == 0)) | |
881 | first_i_frame_ready = 1; | |
882 | ||
883 | if ((pts_lookup_offset_us64 | |
a8f62ee0 RZ |
884 | (PTS_TYPE_VIDEO, offset, &pts, |
885 | &frame_size, 0, &pts_us64) == 0) | |
b9164398 NQ |
886 | && (((info & PICINFO_TYPE_MASK) == PICINFO_TYPE_I) |
887 | || ((info & PICINFO_TYPE_MASK) == | |
888 | PICINFO_TYPE_P))) | |
889 | pts_valid = 1; | |
890 | ||
fe96802b NQ |
891 | if (pts_valid && lastpts == pts) |
892 | pts_valid = 0; | |
893 | if (pts_valid) | |
894 | lastpts = pts; | |
b9164398 NQ |
895 | /*if (frame_prog == 0) */ |
896 | { | |
897 | frame_prog = info & PICINFO_PROG; | |
fe96802b NQ |
898 | if ((seqinfo & SEQINFO_EXT_AVAILABLE) |
899 | && (!(seqinfo & SEQINFO_PROG))) | |
900 | frame_prog = 0; | |
b9164398 NQ |
901 | } |
902 | ||
903 | if ((dec_control & | |
904 | DEC_CONTROL_FLAG_FORCE_2500_720_576_INTERLACE) | |
905 | && (frame_width == 720 || frame_width == 480) | |
906 | && (frame_height == 576) | |
907 | && (frame_dur == 3840)) | |
908 | frame_prog = 0; | |
909 | else if ((dec_control & | |
910 | DEC_CONTROL_FLAG_FORCE_3000_704_480_INTERLACE) | |
911 | && (frame_width == 704) && (frame_height == 480) | |
912 | && (frame_dur == 3200)) | |
913 | frame_prog = 0; | |
914 | else if ((dec_control & | |
915 | DEC_CONTROL_FLAG_FORCE_2500_704_576_INTERLACE) | |
916 | && (frame_width == 704) && (frame_height == 576) | |
917 | && (frame_dur == 3840)) | |
918 | frame_prog = 0; | |
919 | else if ((dec_control & | |
920 | DEC_CONTROL_FLAG_FORCE_2500_544_576_INTERLACE) | |
921 | && (frame_width == 544) && (frame_height == 576) | |
922 | && (frame_dur == 3840)) | |
923 | frame_prog = 0; | |
924 | else if ((dec_control & | |
925 | DEC_CONTROL_FLAG_FORCE_2500_480_576_INTERLACE) | |
926 | && (frame_width == 480) && (frame_height == 576) | |
927 | && (frame_dur == 3840)) | |
928 | frame_prog = 0; | |
929 | else if (dec_control & DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE) | |
930 | frame_prog = 0; | |
931 | if (frame_prog & PICINFO_PROG) { | |
932 | u32 index = ((reg & 0xf) - 1) & 7; | |
933 | ||
934 | seqinfo = READ_VREG(MREG_SEQ_INFO); | |
935 | ||
936 | if (kfifo_get(&newframe_q, &vf) == 0) { | |
937 | pr_info | |
938 | ("fatal error, no available buffer slot."); | |
939 | return IRQ_HANDLED; | |
940 | } | |
941 | ||
942 | set_frame_info(vf); | |
b57a24af PY |
943 | /*pr_info("video signal type:0x%x\n", |
944 | READ_VREG(AV_SCRATCH_H));*/ | |
945 | vf->signal_type = READ_VREG(AV_SCRATCH_H); | |
b9164398 NQ |
946 | vf->index = index; |
947 | #ifdef NV21 | |
948 | vf->type = | |
949 | VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD | | |
950 | VIDTYPE_VIU_NV21; | |
951 | #else | |
952 | vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD; | |
953 | #endif | |
954 | if ((seqinfo & SEQINFO_EXT_AVAILABLE) | |
955 | && (seqinfo & SEQINFO_PROG)) { | |
956 | if (info & PICINFO_RPT_FIRST) { | |
957 | if (info & PICINFO_TOP_FIRST) { | |
958 | vf->duration = | |
959 | vf->duration * 3; | |
960 | /* repeat three times */ | |
961 | } else { | |
962 | vf->duration = | |
963 | vf->duration * 2; | |
964 | /* repeat two times */ | |
965 | } | |
966 | } | |
967 | vf->duration_pulldown = 0; | |
968 | /* no pull down */ | |
969 | ||
970 | } else { | |
971 | vf->duration_pulldown = | |
972 | (info & PICINFO_RPT_FIRST) ? | |
973 | vf->duration >> 1 : 0; | |
974 | } | |
975 | ||
fe96802b NQ |
976 | /*count info*/ |
977 | vdec_count_info(gvs, info & PICINFO_ERROR, offset); | |
978 | ||
b9164398 NQ |
979 | vf->duration += vf->duration_pulldown; |
980 | vf->canvas0Addr = vf->canvas1Addr = | |
981 | index2canvas(index); | |
982 | vf->orientation = 0; | |
983 | vf->pts = (pts_valid) ? pts : 0; | |
984 | vf->pts_us64 = (pts_valid) ? pts_us64 : 0; | |
985 | vf->type_original = vf->type; | |
986 | ||
987 | vfbuf_use[index] = 1; | |
988 | ||
989 | if ((error_skip(info, vf)) || | |
990 | ((first_i_frame_ready == 0) | |
991 | && ((PICINFO_TYPE_MASK & info) != | |
992 | PICINFO_TYPE_I))) { | |
fe96802b | 993 | gvs->drop_frame_count++; |
b9164398 NQ |
994 | kfifo_put(&recycle_q, |
995 | (const struct vframe_s *)vf); | |
996 | } else { | |
fe96802b NQ |
997 | vf->mem_handle = |
998 | decoder_bmmu_box_get_mem_handle( | |
999 | mm_blk_handle, | |
1000 | index); | |
b9164398 NQ |
1001 | kfifo_put(&display_q, |
1002 | (const struct vframe_s *)vf); | |
a093654a | 1003 | ATRACE_COUNTER(MODULE_NAME, vf->pts); |
b9164398 NQ |
1004 | vf_notify_receiver(PROVIDER_NAME, |
1005 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
1006 | NULL); | |
1007 | } | |
1008 | ||
1009 | } else { | |
1010 | u32 index = ((reg & 0xf) - 1) & 7; | |
1011 | int first_field_type = (info & PICINFO_TOP_FIRST) ? | |
1012 | VIDTYPE_INTERLACE_TOP : | |
1013 | VIDTYPE_INTERLACE_BOTTOM; | |
1014 | ||
1015 | #ifdef INTERLACE_SEQ_ALWAYS | |
1016 | /* once an interlaced sequence exist, | |
e0614bf7 ZZ |
1017 | *always force interlaced type |
1018 | */ | |
b9164398 NQ |
1019 | /* to make DI easy. */ |
1020 | dec_control |= DEC_CONTROL_FLAG_FORCE_SEQ_INTERLACE; | |
1021 | #endif | |
fe96802b | 1022 | #if 0 |
b9164398 NQ |
1023 | if (info & PICINFO_FRAME) { |
1024 | frame_rpt_state = | |
1025 | (info & PICINFO_TOP_FIRST) ? | |
1026 | FRAME_REPEAT_TOP : FRAME_REPEAT_BOT; | |
1027 | } else { | |
1028 | if (frame_rpt_state == FRAME_REPEAT_TOP) { | |
1029 | first_field_type = | |
1030 | VIDTYPE_INTERLACE_TOP; | |
1031 | } else if (frame_rpt_state == | |
1032 | FRAME_REPEAT_BOT) { | |
1033 | first_field_type = | |
1034 | VIDTYPE_INTERLACE_BOTTOM; | |
1035 | } | |
1036 | frame_rpt_state = FRAME_REPEAT_NONE; | |
1037 | } | |
fe96802b NQ |
1038 | #else |
1039 | frame_rpt_state = FRAME_REPEAT_NONE; | |
1040 | #endif | |
b9164398 NQ |
1041 | if (kfifo_get(&newframe_q, &vf) == 0) { |
1042 | pr_info | |
1043 | ("fatal error, no available buffer slot."); | |
1044 | return IRQ_HANDLED; | |
1045 | } | |
fe96802b NQ |
1046 | if (info & PICINFO_RPT_FIRST) |
1047 | vfbuf_use[index] = 3; | |
1048 | else | |
1049 | vfbuf_use[index] = 2; | |
b9164398 NQ |
1050 | |
1051 | set_frame_info(vf); | |
1052 | vf->signal_type = 0; | |
1053 | vf->index = index; | |
1054 | vf->type = | |
1055 | (first_field_type == VIDTYPE_INTERLACE_TOP) ? | |
1056 | VIDTYPE_INTERLACE_TOP : | |
1057 | VIDTYPE_INTERLACE_BOTTOM; | |
1058 | #ifdef NV21 | |
1059 | vf->type |= VIDTYPE_VIU_NV21; | |
1060 | #endif | |
d481db31 NQ |
1061 | if (info & PICINFO_RPT_FIRST) |
1062 | vf->duration /= 3; | |
1063 | else | |
1064 | vf->duration >>= 1; | |
b9164398 NQ |
1065 | vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? |
1066 | vf->duration >> 1 : 0; | |
1067 | vf->duration += vf->duration_pulldown; | |
1068 | vf->orientation = 0; | |
1069 | vf->canvas0Addr = vf->canvas1Addr = | |
1070 | index2canvas(index); | |
1071 | vf->pts = (pts_valid) ? pts : 0; | |
1072 | vf->pts_us64 = (pts_valid) ? pts_us64 : 0; | |
1073 | vf->type_original = vf->type; | |
1074 | ||
1075 | if ((error_skip(info, vf)) || | |
1076 | ((first_i_frame_ready == 0) | |
1077 | && ((PICINFO_TYPE_MASK & info) != | |
1078 | PICINFO_TYPE_I))) { | |
fe96802b | 1079 | gvs->drop_frame_count++; |
b9164398 NQ |
1080 | kfifo_put(&recycle_q, |
1081 | (const struct vframe_s *)vf); | |
1082 | } else { | |
fe96802b NQ |
1083 | vf->mem_handle = |
1084 | decoder_bmmu_box_get_mem_handle( | |
1085 | mm_blk_handle, | |
1086 | index); | |
b9164398 NQ |
1087 | kfifo_put(&display_q, |
1088 | (const struct vframe_s *)vf); | |
a093654a | 1089 | ATRACE_COUNTER(MODULE_NAME, vf->pts); |
b9164398 NQ |
1090 | vf_notify_receiver(PROVIDER_NAME, |
1091 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
1092 | NULL); | |
1093 | } | |
1094 | ||
1095 | if (kfifo_get(&newframe_q, &vf) == 0) { | |
1096 | pr_info | |
1097 | ("fatal error, no available buffer slot."); | |
1098 | return IRQ_HANDLED; | |
1099 | } | |
1100 | ||
1101 | set_frame_info(vf); | |
1102 | vf->signal_type = 0; | |
1103 | vf->index = index; | |
1104 | vf->type = (first_field_type == | |
1105 | VIDTYPE_INTERLACE_TOP) ? | |
1106 | VIDTYPE_INTERLACE_BOTTOM : | |
1107 | VIDTYPE_INTERLACE_TOP; | |
1108 | #ifdef NV21 | |
1109 | vf->type |= VIDTYPE_VIU_NV21; | |
1110 | #endif | |
d481db31 NQ |
1111 | if (info & PICINFO_RPT_FIRST) |
1112 | vf->duration /= 3; | |
1113 | else | |
1114 | vf->duration >>= 1; | |
b9164398 NQ |
1115 | vf->duration_pulldown = (info & PICINFO_RPT_FIRST) ? |
1116 | vf->duration >> 1 : 0; | |
1117 | vf->duration += vf->duration_pulldown; | |
1118 | vf->orientation = 0; | |
1119 | vf->canvas0Addr = vf->canvas1Addr = | |
1120 | index2canvas(index); | |
1121 | vf->pts = 0; | |
1122 | vf->pts_us64 = 0; | |
1123 | vf->type_original = vf->type; | |
1124 | ||
fe96802b NQ |
1125 | /*count info*/ |
1126 | vdec_count_info(gvs, info & PICINFO_ERROR, offset); | |
1127 | ||
b9164398 NQ |
1128 | if ((error_skip(info, vf)) || |
1129 | ((first_i_frame_ready == 0) | |
1130 | && ((PICINFO_TYPE_MASK & info) != | |
1131 | PICINFO_TYPE_I))) { | |
fe96802b | 1132 | gvs->drop_frame_count++; |
b9164398 NQ |
1133 | kfifo_put(&recycle_q, |
1134 | (const struct vframe_s *)vf); | |
1135 | } else { | |
fe96802b NQ |
1136 | vf->mem_handle = |
1137 | decoder_bmmu_box_get_mem_handle( | |
1138 | mm_blk_handle, | |
1139 | index); | |
b9164398 NQ |
1140 | kfifo_put(&display_q, |
1141 | (const struct vframe_s *)vf); | |
a093654a | 1142 | ATRACE_COUNTER(MODULE_NAME, vf->pts); |
b9164398 NQ |
1143 | vf_notify_receiver(PROVIDER_NAME, |
1144 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
1145 | NULL); | |
1146 | } | |
b9164398 | 1147 | |
fe96802b NQ |
1148 | if (info & PICINFO_RPT_FIRST) { |
1149 | if (kfifo_get(&newframe_q, &vf) == 0) { | |
1150 | pr_info("error, no available buffer slot."); | |
1151 | return IRQ_HANDLED; | |
1152 | } | |
1153 | ||
1154 | set_frame_info(vf); | |
1155 | ||
1156 | vf->index = index; | |
1157 | vf->type = (first_field_type == | |
1158 | VIDTYPE_INTERLACE_TOP) ? | |
1159 | VIDTYPE_INTERLACE_TOP : | |
1160 | VIDTYPE_INTERLACE_BOTTOM; | |
1161 | #ifdef NV21 | |
1162 | vf->type |= VIDTYPE_VIU_NV21; | |
1163 | #endif | |
d481db31 | 1164 | vf->duration /= 3; |
fe96802b NQ |
1165 | vf->duration_pulldown = |
1166 | (info & PICINFO_RPT_FIRST) ? | |
1167 | vf->duration >> 1 : 0; | |
1168 | vf->duration += vf->duration_pulldown; | |
1169 | vf->orientation = 0; | |
1170 | vf->canvas0Addr = vf->canvas1Addr = | |
1171 | index2canvas(index); | |
1172 | vf->pts = 0; | |
1173 | vf->pts_us64 = 0; | |
1174 | if ((error_skip(info, vf)) || | |
1175 | ((first_i_frame_ready == 0) | |
1176 | && ((PICINFO_TYPE_MASK & info) | |
1177 | != PICINFO_TYPE_I))) { | |
1178 | kfifo_put(&recycle_q, | |
1179 | (const struct vframe_s *)vf); | |
1180 | } else { | |
1181 | kfifo_put(&display_q, | |
1182 | (const struct vframe_s *)vf); | |
a093654a | 1183 | ATRACE_COUNTER(MODULE_NAME, vf->pts); |
fe96802b NQ |
1184 | vf_notify_receiver(PROVIDER_NAME, |
1185 | VFRAME_EVENT_PROVIDER_VFRAME_READY, | |
1186 | NULL); | |
1187 | } | |
1188 | } | |
1189 | } | |
b9164398 NQ |
1190 | WRITE_VREG(MREG_BUFFEROUT, 0); |
1191 | } | |
1192 | ||
a6c89e96 NQ |
1193 | reg = READ_VREG(AV_SCRATCH_M); |
1194 | if (reg & (1<<16)) | |
1195 | schedule_work(&userdata_push_work); | |
1196 | ||
b9164398 NQ |
1197 | return IRQ_HANDLED; |
1198 | } | |
1199 | ||
1200 | static struct vframe_s *vmpeg_vf_peek(void *op_arg) | |
1201 | { | |
1202 | struct vframe_s *vf; | |
1203 | ||
1204 | if (kfifo_peek(&display_q, &vf)) | |
1205 | return vf; | |
1206 | ||
1207 | return NULL; | |
1208 | } | |
1209 | ||
1210 | static struct vframe_s *vmpeg_vf_get(void *op_arg) | |
1211 | { | |
1212 | struct vframe_s *vf; | |
1213 | ||
1214 | if (kfifo_get(&display_q, &vf)) | |
1215 | return vf; | |
1216 | ||
1217 | return NULL; | |
1218 | } | |
1219 | ||
1220 | static void vmpeg_vf_put(struct vframe_s *vf, void *op_arg) | |
1221 | { | |
1222 | if (pool_index(vf) == cur_pool_idx) | |
1223 | kfifo_put(&recycle_q, (const struct vframe_s *)vf); | |
1224 | } | |
1225 | ||
1226 | static int vmpeg_event_cb(int type, void *data, void *private_data) | |
1227 | { | |
1228 | if (type & VFRAME_EVENT_RECEIVER_RESET) { | |
1229 | unsigned long flags; | |
e0614bf7 | 1230 | |
b9164398 NQ |
1231 | amvdec_stop(); |
1232 | #ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1233 | vf_light_unreg_provider(&vmpeg_vf_prov); | |
1234 | #endif | |
1235 | spin_lock_irqsave(&lock, flags); | |
1236 | vmpeg12_local_init(); | |
1237 | vmpeg12_prot_init(); | |
1238 | spin_unlock_irqrestore(&lock, flags); | |
1239 | #ifndef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1240 | vf_reg_provider(&vmpeg_vf_prov); | |
1241 | #endif | |
1242 | amvdec_start(); | |
1243 | } | |
1244 | return 0; | |
1245 | } | |
1246 | ||
1247 | static int vmpeg_vf_states(struct vframe_states *states, void *op_arg) | |
1248 | { | |
1249 | unsigned long flags; | |
e0614bf7 | 1250 | |
b9164398 NQ |
1251 | spin_lock_irqsave(&lock, flags); |
1252 | ||
1253 | states->vf_pool_size = VF_POOL_SIZE; | |
1254 | states->buf_free_num = kfifo_len(&newframe_q); | |
1255 | states->buf_avail_num = kfifo_len(&display_q); | |
1256 | states->buf_recycle_num = kfifo_len(&recycle_q); | |
1257 | ||
1258 | spin_unlock_irqrestore(&lock, flags); | |
1259 | ||
1260 | return 0; | |
1261 | } | |
1262 | ||
1263 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1264 | static void vmpeg12_ppmgr_reset(void) | |
1265 | { | |
1266 | vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_RESET, NULL); | |
1267 | ||
1268 | vmpeg12_local_init(); | |
1269 | ||
1270 | pr_info("vmpeg12dec: vf_ppmgr_reset\n"); | |
1271 | } | |
1272 | #endif | |
1273 | ||
a6c89e96 | 1274 | static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit); |
9cc3c918 | 1275 | static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec); |
a6c89e96 | 1276 | |
fe96802b NQ |
1277 | static void reset_do_work(struct work_struct *work) |
1278 | { | |
1279 | amvdec_stop(); | |
1280 | ||
1281 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1282 | vmpeg12_ppmgr_reset(); | |
1283 | #else | |
1284 | vf_light_unreg_provider(&vmpeg_vf_prov); | |
1285 | vmpeg12_local_init(); | |
1286 | vf_reg_provider(&vmpeg_vf_prov); | |
1287 | #endif | |
1288 | vmpeg12_prot_init(); | |
4522fc84 | 1289 | vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); |
a6c89e96 NQ |
1290 | vmpeg12_reset_userdata_fifo(vdec, 1); |
1291 | #ifdef DUMP_USER_DATA | |
1292 | last_wp = 0; | |
1293 | #endif | |
6fa7657f | 1294 | |
a6c89e96 | 1295 | amvdec_start(); |
6fa7657f | 1296 | } |
1297 | ||
a994f6d6 | 1298 | static void vmpeg12_set_clk(struct work_struct *work) |
1299 | { | |
1300 | if (frame_dur > 0 && saved_resolution != | |
1301 | frame_width * frame_height * (96000 / frame_dur)) { | |
1302 | int fps = 96000 / frame_dur; | |
1303 | ||
1304 | saved_resolution = frame_width * frame_height * fps; | |
1305 | vdec_source_changed(VFORMAT_MPEG12, | |
1306 | frame_width, frame_height, fps); | |
1307 | } | |
1308 | } | |
1309 | ||
1310 | ||
b9164398 NQ |
1311 | static void vmpeg_put_timer_func(unsigned long arg) |
1312 | { | |
1313 | struct timer_list *timer = (struct timer_list *)arg; | |
1314 | int fatal_reset = 0; | |
1315 | ||
1316 | enum receviver_start_e state = RECEIVER_INACTIVE; | |
e0614bf7 | 1317 | |
b9164398 NQ |
1318 | if (vf_get_receiver(PROVIDER_NAME)) { |
1319 | state = vf_notify_receiver(PROVIDER_NAME, | |
1320 | VFRAME_EVENT_PROVIDER_QUREY_STATE, NULL); | |
1321 | if ((state == RECEIVER_STATE_NULL) | |
1322 | || (state == RECEIVER_STATE_NONE)) { | |
1323 | /* receiver has no event_cb or | |
e0614bf7 ZZ |
1324 | *receiver's event_cb does not process this event |
1325 | */ | |
b9164398 NQ |
1326 | state = RECEIVER_INACTIVE; |
1327 | } | |
1328 | } else | |
1329 | state = RECEIVER_INACTIVE; | |
1330 | ||
1331 | if (READ_VREG(MREG_FATAL_ERROR) == 1) | |
1332 | fatal_reset = 1; | |
1333 | ||
1334 | if ((READ_VREG(MREG_WAIT_BUFFER) != 0) && | |
1335 | (kfifo_is_empty(&recycle_q)) && | |
1336 | (kfifo_is_empty(&display_q)) && (state == RECEIVER_INACTIVE)) { | |
1337 | if (++wait_buffer_counter > 4) | |
1338 | fatal_reset = 1; | |
1339 | ||
1340 | } else | |
1341 | wait_buffer_counter = 0; | |
1342 | ||
1343 | if (fatal_reset && (kfifo_is_empty(&display_q))) { | |
1344 | pr_info("$$$$decoder is waiting for buffer or fatal reset.\n"); | |
fe96802b | 1345 | schedule_work(&reset_work); |
b9164398 NQ |
1346 | } |
1347 | ||
1348 | while (!kfifo_is_empty(&recycle_q) && (READ_VREG(MREG_BUFFERIN) == 0)) { | |
1349 | struct vframe_s *vf; | |
e0614bf7 | 1350 | |
b9164398 NQ |
1351 | if (kfifo_get(&recycle_q, &vf)) { |
1352 | if ((vf->index < DECODE_BUFFER_NUM_MAX) && | |
1353 | (--vfbuf_use[vf->index] == 0)) { | |
1354 | WRITE_VREG(MREG_BUFFERIN, vf->index + 1); | |
1355 | vf->index = DECODE_BUFFER_NUM_MAX; | |
1356 | } | |
1357 | ||
1358 | if (pool_index(vf) == cur_pool_idx) { | |
1359 | kfifo_put(&newframe_q, | |
1360 | (const struct vframe_s *)vf); | |
1361 | } | |
1362 | } | |
1363 | } | |
1364 | ||
a994f6d6 | 1365 | schedule_work(&set_clk_work); |
b9164398 NQ |
1366 | |
1367 | timer->expires = jiffies + PUT_INTERVAL; | |
1368 | ||
1369 | add_timer(timer); | |
1370 | } | |
1371 | ||
fe96802b | 1372 | int vmpeg12_dec_status(struct vdec_s *vdec, struct vdec_info *vstatus) |
b9164398 | 1373 | { |
70809fec NQ |
1374 | if (!(stat & STAT_VDEC_RUN)) |
1375 | return -1; | |
1376 | ||
fe96802b NQ |
1377 | vstatus->frame_width = frame_width; |
1378 | vstatus->frame_height = frame_height; | |
b9164398 | 1379 | if (frame_dur != 0) |
fe96802b | 1380 | vstatus->frame_rate = 96000 / frame_dur; |
b9164398 | 1381 | else |
fe96802b | 1382 | vstatus->frame_rate = -1; |
b9164398 NQ |
1383 | vstatus->error_count = READ_VREG(AV_SCRATCH_C); |
1384 | vstatus->status = stat; | |
fe96802b NQ |
1385 | vstatus->bit_rate = gvs->bit_rate; |
1386 | vstatus->frame_dur = frame_dur; | |
1387 | vstatus->frame_data = gvs->frame_data; | |
1388 | vstatus->total_data = gvs->total_data; | |
1389 | vstatus->frame_count = gvs->frame_count; | |
1390 | vstatus->error_frame_count = gvs->error_frame_count; | |
1391 | vstatus->drop_frame_count = gvs->drop_frame_count; | |
1392 | vstatus->total_data = gvs->total_data; | |
1393 | vstatus->samp_cnt = gvs->samp_cnt; | |
1394 | vstatus->offset = gvs->offset; | |
1395 | snprintf(vstatus->vdec_name, sizeof(vstatus->vdec_name), | |
1396 | "%s", DRIVER_NAME); | |
1397 | ||
1398 | return 0; | |
1399 | } | |
b9164398 | 1400 | |
d481db31 NQ |
1401 | int vmpeg12_set_isreset(struct vdec_s *vdec, int isreset) |
1402 | { | |
1403 | is_reset = isreset; | |
1404 | return 0; | |
1405 | } | |
1406 | ||
a6c89e96 NQ |
1407 | |
1408 | ||
4522fc84 PY |
1409 | |
1410 | static void vmpeg12_create_userdata_manager(u8 *userdata_buf, int buf_len) | |
a6c89e96 | 1411 | { |
bbee6a9b NQ |
1412 | mutex_lock(&userdata_mutex); |
1413 | ||
a6c89e96 NQ |
1414 | p_userdata_mgr = (struct mpeg12_userdata_info_t *) |
1415 | vmalloc(sizeof(struct mpeg12_userdata_info_t)); | |
1416 | if (p_userdata_mgr) { | |
1417 | memset(p_userdata_mgr, 0, | |
1418 | sizeof(struct mpeg12_userdata_info_t)); | |
1419 | p_userdata_mgr->data_buf = userdata_buf; | |
1420 | p_userdata_mgr->buf_len = buf_len; | |
1421 | p_userdata_mgr->data_buf_end = userdata_buf + buf_len; | |
1422 | } | |
bbee6a9b | 1423 | mutex_unlock(&userdata_mutex); |
a6c89e96 NQ |
1424 | } |
1425 | ||
4522fc84 | 1426 | static void vmpeg12_destroy_userdata_manager(void) |
a6c89e96 | 1427 | { |
bbee6a9b NQ |
1428 | mutex_lock(&userdata_mutex); |
1429 | ||
a6c89e96 NQ |
1430 | if (p_userdata_mgr) { |
1431 | vfree(p_userdata_mgr); | |
1432 | p_userdata_mgr = NULL; | |
1433 | } | |
bbee6a9b | 1434 | mutex_unlock(&userdata_mutex); |
a6c89e96 NQ |
1435 | } |
1436 | ||
bbee6a9b NQ |
1437 | static void vmpeg12_add_userdata(struct userdata_meta_info_t meta_info, |
1438 | int wp, | |
1439 | u32 reference) | |
a6c89e96 NQ |
1440 | { |
1441 | struct mpeg12_userdata_recored_t *p_userdata_rec; | |
1442 | int data_length; | |
1443 | ||
1444 | mutex_lock(&userdata_mutex); | |
1445 | ||
1446 | if (p_userdata_mgr) { | |
1447 | if (wp > p_userdata_mgr->last_wp) | |
1448 | data_length = wp - p_userdata_mgr->last_wp; | |
1449 | else { | |
1450 | p_userdata_mgr->last_wp = 0; | |
1451 | data_length = wp - p_userdata_mgr->last_wp; | |
1452 | } | |
1453 | ||
1454 | if (data_length & 0x7) | |
1455 | data_length = (((data_length + 8) >> 3) << 3); | |
1456 | /* | |
1457 | pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n", | |
1458 | p_userdata_mgr->read_index, | |
1459 | p_userdata_mgr->write_index, | |
1460 | data_length, | |
1461 | p_userdata_mgr->last_wp, | |
1462 | wp, | |
1463 | n_userdata_id); | |
1464 | */ | |
1465 | p_userdata_rec = p_userdata_mgr->records | |
1466 | + p_userdata_mgr->write_index; | |
1467 | p_userdata_rec->meta_info = meta_info; | |
1468 | p_userdata_rec->rec_start = p_userdata_mgr->last_wp; | |
1469 | p_userdata_rec->rec_len = data_length; | |
1470 | p_userdata_mgr->last_wp = wp; | |
1471 | ||
1472 | #ifdef DUMP_USER_DATA | |
1473 | dump_userdata_info(p_userdata_mgr->data_buf | |
1474 | + p_userdata_rec->rec_start, | |
1475 | data_length, | |
bbee6a9b NQ |
1476 | &meta_info, |
1477 | reference); | |
a6c89e96 NQ |
1478 | n_userdata_id++; |
1479 | #endif | |
1480 | ||
1481 | p_userdata_mgr->write_index++; | |
1482 | if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM) | |
1483 | p_userdata_mgr->write_index = 0; | |
1484 | } | |
1485 | mutex_unlock(&userdata_mutex); | |
1486 | ||
1487 | vdec_wakeup_userdata_poll(vdec); | |
1488 | } | |
1489 | ||
1490 | ||
1491 | static int vmpeg12_user_data_read(struct vdec_s *vdec, | |
1492 | struct userdata_param_t *puserdata_para) | |
1493 | { | |
1494 | int rec_ri, rec_wi; | |
1495 | int rec_len; | |
1496 | u8 *rec_data_start; | |
1497 | u8 *pdest_buf; | |
1498 | struct mpeg12_userdata_recored_t *p_userdata_rec; | |
a6c89e96 NQ |
1499 | u32 data_size; |
1500 | u32 res; | |
1501 | int copy_ok = 1; | |
1502 | ||
9cc3c918 RZ |
1503 | pdest_buf = puserdata_para->pbuf_addr; |
1504 | ||
a6c89e96 NQ |
1505 | mutex_lock(&userdata_mutex); |
1506 | ||
1507 | if (!p_userdata_mgr) { | |
1508 | mutex_unlock(&userdata_mutex); | |
1509 | return 0; | |
1510 | } | |
1511 | /* | |
1512 | pr_info("ri = %d, wi = %d\n", | |
1513 | p_userdata_mgr->read_index, | |
1514 | p_userdata_mgr->write_index); | |
1515 | */ | |
1516 | rec_ri = p_userdata_mgr->read_index; | |
1517 | rec_wi = p_userdata_mgr->write_index; | |
1518 | ||
1519 | if (rec_ri == rec_wi) { | |
1520 | mutex_unlock(&userdata_mutex); | |
1521 | return 0; | |
1522 | } | |
1523 | ||
1524 | p_userdata_rec = p_userdata_mgr->records + rec_ri; | |
1525 | ||
1526 | rec_len = p_userdata_rec->rec_len; | |
1527 | rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf; | |
1528 | /* | |
1529 | pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n", | |
1530 | p_userdata_rec->rec_len, | |
1531 | p_userdata_rec->rec_start, | |
1532 | puserdata_para->buf_len); | |
1533 | */ | |
1534 | if (rec_len <= puserdata_para->buf_len) { | |
1535 | /* dvb user data buffer is enought to copy the whole recored. */ | |
1536 | data_size = rec_len; | |
1537 | if (rec_data_start + data_size | |
1538 | > p_userdata_mgr->data_buf_end) { | |
1539 | int first_section_len; | |
1540 | ||
1541 | first_section_len = p_userdata_mgr->buf_len | |
1542 | - p_userdata_rec->rec_start; | |
1543 | res = (u32)copy_to_user((void *)pdest_buf, | |
1544 | (void *)rec_data_start, | |
1545 | first_section_len); | |
1546 | if (res) { | |
1547 | pr_info("p1 read not end res=%d, request=%d\n", | |
1548 | res, first_section_len); | |
1549 | copy_ok = 0; | |
1550 | ||
1551 | p_userdata_rec->rec_len -= | |
1552 | first_section_len - res; | |
1553 | p_userdata_rec->rec_start += | |
1554 | first_section_len - res; | |
1555 | puserdata_para->data_size = | |
1556 | first_section_len - res; | |
1557 | } else { | |
1558 | res = (u32)copy_to_user( | |
1559 | (void *)(pdest_buf+first_section_len), | |
1560 | (void *)p_userdata_mgr->data_buf, | |
1561 | data_size - first_section_len); | |
1562 | if (res) { | |
1563 | pr_info("p2 read not end res=%d, request=%d\n", | |
1564 | res, data_size); | |
1565 | copy_ok = 0; | |
1566 | } | |
1567 | p_userdata_rec->rec_len -= data_size - res; | |
1568 | p_userdata_rec->rec_start = | |
1569 | data_size - first_section_len - res; | |
1570 | puserdata_para->data_size = data_size - res; | |
1571 | } | |
1572 | } else { | |
1573 | res = (u32)copy_to_user((void *)pdest_buf, | |
1574 | (void *)rec_data_start, | |
1575 | data_size); | |
1576 | if (res) { | |
1577 | pr_info("p3 read not end res=%d, request=%d\n", | |
1578 | res, data_size); | |
1579 | copy_ok = 0; | |
1580 | } | |
1581 | p_userdata_rec->rec_len -= data_size - res; | |
1582 | p_userdata_rec->rec_start += data_size - res; | |
1583 | puserdata_para->data_size = data_size - res; | |
1584 | } | |
1585 | ||
1586 | if (copy_ok) { | |
1587 | p_userdata_mgr->read_index++; | |
1588 | if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM) | |
1589 | p_userdata_mgr->read_index = 0; | |
1590 | } | |
1591 | } else { | |
1592 | /* dvb user data buffer is not enought | |
1593 | to copy the whole recored. */ | |
1594 | data_size = puserdata_para->buf_len; | |
1595 | if (rec_data_start + data_size | |
1596 | > p_userdata_mgr->data_buf_end) { | |
1597 | int first_section_len; | |
1598 | ||
1599 | first_section_len = p_userdata_mgr->buf_len | |
1600 | - p_userdata_rec->rec_start; | |
1601 | res = (u32)copy_to_user((void *)pdest_buf, | |
1602 | (void *)rec_data_start, | |
1603 | first_section_len); | |
1604 | if (res) { | |
1605 | pr_info("p4 read not end res=%d, request=%d\n", | |
1606 | res, first_section_len); | |
1607 | copy_ok = 0; | |
1608 | p_userdata_rec->rec_len -= | |
1609 | first_section_len - res; | |
1610 | p_userdata_rec->rec_start += | |
1611 | first_section_len - res; | |
1612 | puserdata_para->data_size = | |
1613 | first_section_len - res; | |
1614 | } else { | |
1615 | /* first secton copy is ok*/ | |
1616 | res = (u32)copy_to_user( | |
1617 | (void *)(pdest_buf+first_section_len), | |
1618 | (void *)p_userdata_mgr->data_buf, | |
1619 | data_size - first_section_len); | |
1620 | if (res) { | |
1621 | pr_info("p5 read not end res=%d, request=%d\n", | |
1622 | res, | |
1623 | data_size - first_section_len); | |
1624 | copy_ok = 0; | |
1625 | } | |
1626 | ||
1627 | p_userdata_rec->rec_len -= data_size - res; | |
1628 | p_userdata_rec->rec_start = | |
1629 | data_size - first_section_len - res; | |
1630 | puserdata_para->data_size = data_size - res; | |
1631 | } | |
1632 | } else { | |
1633 | res = (u32)copy_to_user((void *)pdest_buf, | |
1634 | (void *)rec_data_start, | |
1635 | data_size); | |
1636 | if (res) { | |
1637 | pr_info("p6 read not end res=%d, request=%d\n", | |
1638 | res, data_size); | |
1639 | copy_ok = 0; | |
1640 | } | |
1641 | ||
1642 | p_userdata_rec->rec_len -= data_size - res; | |
1643 | p_userdata_rec->rec_start += data_size - res; | |
1644 | puserdata_para->data_size = data_size - res; | |
1645 | } | |
1646 | ||
1647 | if (copy_ok) { | |
1648 | p_userdata_mgr->read_index++; | |
1649 | if (p_userdata_mgr->read_index | |
1650 | >= USERDATA_FIFO_NUM) | |
1651 | p_userdata_mgr->read_index = 0; | |
1652 | } | |
1653 | ||
1654 | } | |
4522fc84 PY |
1655 | |
1656 | puserdata_para->meta_info = p_userdata_rec->meta_info; | |
a6c89e96 NQ |
1657 | |
1658 | if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index) | |
1659 | puserdata_para->meta_info.records_in_que = | |
1660 | p_userdata_mgr->write_index - | |
1661 | p_userdata_mgr->read_index; | |
1662 | else | |
1663 | puserdata_para->meta_info.records_in_que = | |
1664 | p_userdata_mgr->write_index + | |
1665 | USERDATA_FIFO_NUM - | |
1666 | p_userdata_mgr->read_index; | |
1667 | puserdata_para->version = (0<<24|0<<16|0<<8|1); | |
1668 | ||
1669 | mutex_unlock(&userdata_mutex); | |
1670 | ||
1671 | return 1; | |
1672 | } | |
1673 | ||
1674 | static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit) | |
1675 | { | |
1676 | mutex_lock(&userdata_mutex); | |
1677 | ||
1678 | if (p_userdata_mgr) { | |
1679 | pr_info("vmpeg12_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n", | |
1680 | bInit, p_userdata_mgr->read_index, | |
1681 | p_userdata_mgr->write_index); | |
1682 | p_userdata_mgr->read_index = 0; | |
1683 | p_userdata_mgr->write_index = 0; | |
1684 | ||
1685 | if (bInit) | |
1686 | p_userdata_mgr->last_wp = 0; | |
1687 | } | |
1688 | ||
1689 | mutex_unlock(&userdata_mutex); | |
1690 | } | |
1691 | ||
9cc3c918 | 1692 | static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec) |
b78f4cd9 | 1693 | { |
9cc3c918 | 1694 | amstream_wakeup_userdata_poll(vdec); |
b78f4cd9 PY |
1695 | } |
1696 | ||
fe96802b NQ |
1697 | static int vmpeg12_vdec_info_init(void) |
1698 | { | |
1699 | gvs = kzalloc(sizeof(struct vdec_info), GFP_KERNEL); | |
1700 | if (NULL == gvs) { | |
1701 | pr_info("the struct of vdec status malloc failed.\n"); | |
1702 | return -ENOMEM; | |
1703 | } | |
b9164398 NQ |
1704 | return 0; |
1705 | } | |
1706 | ||
1707 | /****************************************/ | |
fe96802b | 1708 | static int vmpeg12_canvas_init(void) |
b9164398 | 1709 | { |
fe96802b | 1710 | int i, ret; |
b9164398 NQ |
1711 | u32 canvas_width, canvas_height; |
1712 | u32 decbuf_size, decbuf_y_size, decbuf_uv_size; | |
fe96802b | 1713 | static unsigned long buf_start; |
b9164398 NQ |
1714 | |
1715 | if (buf_size <= 0x00400000) { | |
1716 | /* SD only */ | |
1717 | canvas_width = 768; | |
1718 | canvas_height = 576; | |
1719 | decbuf_y_size = 0x80000; | |
1720 | decbuf_uv_size = 0x20000; | |
1721 | decbuf_size = 0x100000; | |
1722 | } else { | |
1723 | /* HD & SD */ | |
1724 | canvas_width = 1920; | |
1725 | canvas_height = 1088; | |
1726 | decbuf_y_size = 0x200000; | |
1727 | decbuf_uv_size = 0x80000; | |
1728 | decbuf_size = 0x300000; | |
1729 | } | |
1730 | ||
b9164398 | 1731 | |
fe96802b NQ |
1732 | for (i = 0; i < MAX_BMMU_BUFFER_NUM; i++) { |
1733 | ||
1734 | if (i == (MAX_BMMU_BUFFER_NUM - 1)) /* workspace mem */ | |
1735 | decbuf_size = WORKSPACE_SIZE; | |
1736 | ||
1737 | ret = decoder_bmmu_box_alloc_buf_phy(mm_blk_handle, i, | |
1738 | decbuf_size, DRIVER_NAME, &buf_start); | |
1739 | if (ret < 0) | |
1740 | return ret; | |
1741 | ||
1742 | if (i == (MAX_BMMU_BUFFER_NUM - 1)) { | |
1743 | ||
1744 | WRITE_VREG(MREG_CO_MV_START, (buf_start + CCBUF_SIZE)); | |
1745 | if (!ccbuf_phyAddress) { | |
1746 | ccbuf_phyAddress | |
1747 | = (u32)buf_start; | |
1748 | ||
1749 | ccbuf_phyAddress_virt | |
7d2e7e17 NQ |
1750 | = codec_mm_phys_to_virt( |
1751 | ccbuf_phyAddress); | |
fe96802b NQ |
1752 | if (!ccbuf_phyAddress_virt) { |
1753 | ccbuf_phyAddress_virt | |
7d2e7e17 NQ |
1754 | = codec_mm_vmap( |
1755 | ccbuf_phyAddress, | |
1756 | CCBUF_SIZE); | |
fe96802b NQ |
1757 | ccbuf_phyAddress_is_remaped_nocache = 1; |
1758 | } | |
1759 | } | |
b9164398 | 1760 | |
b9164398 NQ |
1761 | } else { |
1762 | #ifdef NV21 | |
1763 | canvas_config(2 * i + 0, | |
fe96802b | 1764 | buf_start, |
b9164398 NQ |
1765 | canvas_width, canvas_height, |
1766 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); | |
1767 | canvas_config(2 * i + 1, | |
fe96802b | 1768 | buf_start + |
b9164398 NQ |
1769 | decbuf_y_size, canvas_width, |
1770 | canvas_height / 2, CANVAS_ADDR_NOWRAP, | |
1771 | CANVAS_BLKMODE_32X32); | |
1772 | #else | |
1773 | canvas_config(3 * i + 0, | |
fe96802b | 1774 | buf_start, |
b9164398 NQ |
1775 | canvas_width, canvas_height, |
1776 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); | |
1777 | canvas_config(3 * i + 1, | |
fe96802b | 1778 | buf_start + |
b9164398 NQ |
1779 | decbuf_y_size, canvas_width / 2, |
1780 | canvas_height / 2, CANVAS_ADDR_NOWRAP, | |
1781 | CANVAS_BLKMODE_32X32); | |
1782 | canvas_config(3 * i + 2, | |
fe96802b | 1783 | buf_start + |
b9164398 NQ |
1784 | decbuf_y_size + decbuf_uv_size, |
1785 | canvas_width / 2, canvas_height / 2, | |
1786 | CANVAS_ADDR_NOWRAP, CANVAS_BLKMODE_32X32); | |
1787 | #endif | |
1788 | } | |
1789 | } | |
1790 | ||
fe96802b | 1791 | return 0; |
b9164398 NQ |
1792 | } |
1793 | ||
fe96802b | 1794 | static int vmpeg12_prot_init(void) |
b9164398 | 1795 | { |
fe96802b | 1796 | int ret; |
63e810c0 | 1797 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) { |
b9164398 NQ |
1798 | int save_reg = READ_VREG(POWER_CTL_VLD); |
1799 | ||
1800 | WRITE_VREG(DOS_SW_RESET0, (1 << 7) | (1 << 6) | (1 << 4)); | |
1801 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1802 | ||
63e810c0 | 1803 | if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) { |
b9164398 NQ |
1804 | |
1805 | READ_VREG(DOS_SW_RESET0); | |
1806 | READ_VREG(DOS_SW_RESET0); | |
1807 | READ_VREG(DOS_SW_RESET0); | |
1808 | ||
1809 | WRITE_VREG(DOS_SW_RESET0, (1<<7) | (1<<6) | (1<<4)); | |
1810 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1811 | ||
1812 | WRITE_VREG(DOS_SW_RESET0, (1<<9) | (1<<8)); | |
1813 | WRITE_VREG(DOS_SW_RESET0, 0); | |
1814 | ||
1815 | READ_VREG(DOS_SW_RESET0); | |
1816 | READ_VREG(DOS_SW_RESET0); | |
1817 | READ_VREG(DOS_SW_RESET0); | |
1818 | ||
1819 | WRITE_VREG(MDEC_SW_RESET, (1 << 7)); | |
1820 | WRITE_VREG(MDEC_SW_RESET, 0); | |
1821 | } | |
1822 | ||
1823 | WRITE_VREG(POWER_CTL_VLD, save_reg); | |
1824 | ||
1825 | } else | |
fe96802b | 1826 | WRITE_RESET_REG(RESET0_REGISTER, RESET_IQIDCT | RESET_MC); |
b9164398 | 1827 | |
fe96802b | 1828 | ret = vmpeg12_canvas_init(); |
b9164398 NQ |
1829 | |
1830 | #ifdef NV21 | |
1831 | WRITE_VREG(AV_SCRATCH_0, 0x010100); | |
1832 | WRITE_VREG(AV_SCRATCH_1, 0x030302); | |
1833 | WRITE_VREG(AV_SCRATCH_2, 0x050504); | |
1834 | WRITE_VREG(AV_SCRATCH_3, 0x070706); | |
1835 | WRITE_VREG(AV_SCRATCH_4, 0x090908); | |
1836 | WRITE_VREG(AV_SCRATCH_5, 0x0b0b0a); | |
1837 | WRITE_VREG(AV_SCRATCH_6, 0x0d0d0c); | |
1838 | WRITE_VREG(AV_SCRATCH_7, 0x0f0f0e); | |
1839 | #else | |
1840 | WRITE_VREG(AV_SCRATCH_0, 0x020100); | |
1841 | WRITE_VREG(AV_SCRATCH_1, 0x050403); | |
1842 | WRITE_VREG(AV_SCRATCH_2, 0x080706); | |
1843 | WRITE_VREG(AV_SCRATCH_3, 0x0b0a09); | |
1844 | WRITE_VREG(AV_SCRATCH_4, 0x0e0d0c); | |
1845 | WRITE_VREG(AV_SCRATCH_5, 0x11100f); | |
1846 | WRITE_VREG(AV_SCRATCH_6, 0x141312); | |
1847 | WRITE_VREG(AV_SCRATCH_7, 0x171615); | |
1848 | #endif | |
1849 | ||
1850 | /* set to mpeg1 default */ | |
1851 | WRITE_VREG(MPEG1_2_REG, 0); | |
1852 | /* disable PSCALE for hardware sharing */ | |
1853 | WRITE_VREG(PSCALE_CTRL, 0); | |
1854 | /* for Mpeg1 default value */ | |
1855 | WRITE_VREG(PIC_HEAD_INFO, 0x380); | |
1856 | /* disable mpeg4 */ | |
1857 | WRITE_VREG(M4_CONTROL_REG, 0); | |
1858 | /* clear mailbox interrupt */ | |
1859 | WRITE_VREG(ASSIST_MBOX1_CLR_REG, 1); | |
1860 | /* clear buffer IN/OUT registers */ | |
1861 | WRITE_VREG(MREG_BUFFERIN, 0); | |
1862 | WRITE_VREG(MREG_BUFFEROUT, 0); | |
1863 | /* set reference width and height */ | |
1864 | if ((frame_width != 0) && (frame_height != 0)) | |
1865 | WRITE_VREG(MREG_CMD, (frame_width << 16) | frame_height); | |
1866 | else | |
1867 | WRITE_VREG(MREG_CMD, 0); | |
a6c89e96 | 1868 | WRITE_VREG(MREG_FORCE_I_RDY, (force_first_i_ready & 0x01)); |
b9164398 NQ |
1869 | /* clear error count */ |
1870 | WRITE_VREG(MREG_ERROR_COUNT, 0); | |
1871 | WRITE_VREG(MREG_FATAL_ERROR, 0); | |
1872 | /* clear wait buffer status */ | |
1873 | WRITE_VREG(MREG_WAIT_BUFFER, 0); | |
1874 | #ifdef NV21 | |
1875 | SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 17); | |
1876 | #endif | |
fe96802b | 1877 | return ret; |
b9164398 NQ |
1878 | } |
1879 | ||
1880 | static void vmpeg12_local_init(void) | |
1881 | { | |
1882 | int i; | |
1883 | ||
1884 | INIT_KFIFO(display_q); | |
1885 | INIT_KFIFO(recycle_q); | |
1886 | INIT_KFIFO(newframe_q); | |
1887 | ||
1888 | cur_pool_idx ^= 1; | |
1889 | ||
1890 | for (i = 0; i < VF_POOL_SIZE; i++) { | |
1891 | const struct vframe_s *vf; | |
e0614bf7 | 1892 | |
b9164398 NQ |
1893 | if (cur_pool_idx == 0) { |
1894 | vf = &vfpool[i]; | |
1895 | vfpool[i].index = DECODE_BUFFER_NUM_MAX; | |
1896 | } else { | |
1897 | vf = &vfpool2[i]; | |
1898 | vfpool2[i].index = DECODE_BUFFER_NUM_MAX; | |
1899 | } | |
1900 | kfifo_put(&newframe_q, (const struct vframe_s *)vf); | |
1901 | } | |
1902 | ||
1903 | for (i = 0; i < DECODE_BUFFER_NUM_MAX; i++) | |
1904 | vfbuf_use[i] = 0; | |
fe96802b | 1905 | if (mm_blk_handle) { |
4522fc84 PY |
1906 | mutex_lock(&userdata_mutex); |
1907 | if (p_userdata_mgr) { | |
1908 | vfree(p_userdata_mgr); | |
1909 | p_userdata_mgr = NULL; | |
1910 | } | |
1911 | if (ccbuf_phyAddress_is_remaped_nocache) | |
7d2e7e17 | 1912 | codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); |
4522fc84 PY |
1913 | ccbuf_phyAddress_virt = NULL; |
1914 | ccbuf_phyAddress = 0; | |
1915 | ccbuf_phyAddress_is_remaped_nocache = 0; | |
fe96802b NQ |
1916 | decoder_bmmu_box_free(mm_blk_handle); |
1917 | mm_blk_handle = NULL; | |
4522fc84 | 1918 | mutex_unlock(&userdata_mutex); |
fe96802b NQ |
1919 | } |
1920 | ||
1921 | mm_blk_handle = decoder_bmmu_box_alloc_box( | |
1922 | DRIVER_NAME, | |
1923 | 0, | |
1924 | MAX_BMMU_BUFFER_NUM, | |
1925 | 4 + PAGE_SHIFT, | |
1926 | CODEC_MM_FLAGS_CMA_CLEAR | | |
1927 | CODEC_MM_FLAGS_FOR_VDECODER); | |
1928 | ||
b9164398 NQ |
1929 | |
1930 | frame_width = frame_height = frame_dur = frame_prog = 0; | |
1931 | frame_force_skip_flag = 0; | |
1932 | wait_buffer_counter = 0; | |
a6c89e96 | 1933 | first_i_frame_ready = force_first_i_ready; |
b9164398 NQ |
1934 | saved_resolution = 0; |
1935 | dec_control &= DEC_CONTROL_INTERNAL_MASK; | |
1936 | } | |
1937 | ||
1938 | static s32 vmpeg12_init(void) | |
1939 | { | |
1940 | int ret = -1, size = -1; | |
1941 | char *buf = vmalloc(0x1000 * 16); | |
e0614bf7 | 1942 | |
b9164398 NQ |
1943 | if (IS_ERR_OR_NULL(buf)) |
1944 | return -ENOMEM; | |
1945 | ||
1946 | init_timer(&recycle_timer); | |
1947 | ||
1948 | stat |= STAT_TIMER_INIT; | |
1949 | ||
1950 | vmpeg12_local_init(); | |
1951 | ||
1952 | amvdec_enable(); | |
1953 | ||
1954 | size = get_firmware_data(VIDEO_DEC_MPEG12, buf); | |
1955 | if (size < 0) { | |
1956 | pr_err("get firmware fail."); | |
1957 | vfree(buf); | |
1958 | return -1; | |
1959 | } | |
1960 | ||
d91b51fb | 1961 | ret = amvdec_loadmc_ex(VFORMAT_MPEG12, "mpeg12", buf); |
668e656d | 1962 | if (ret < 0) { |
b9164398 NQ |
1963 | amvdec_disable(); |
1964 | vfree(buf); | |
668e656d NQ |
1965 | pr_err("MPEG12: the %s fw loading failed, err: %x\n", |
1966 | tee_enabled() ? "TEE" : "local", ret); | |
b9164398 NQ |
1967 | return -EBUSY; |
1968 | } | |
1969 | ||
1970 | vfree(buf); | |
1971 | ||
1972 | stat |= STAT_MC_LOAD; | |
1973 | ||
1974 | /* enable AMRISC side protocol */ | |
1975 | vmpeg12_prot_init(); | |
1976 | ||
1977 | ret = vdec_request_irq(VDEC_IRQ_1, vmpeg12_isr, | |
1978 | "vmpeg12-irq", (void *)vmpeg12_dec_id); | |
1979 | ||
1980 | if (ret) { | |
1981 | amvdec_disable(); | |
1982 | amlog_level(LOG_LEVEL_ERROR, "vmpeg12 irq register error.\n"); | |
1983 | return -ENOENT; | |
1984 | } | |
1985 | ||
1986 | stat |= STAT_ISR_REG; | |
1987 | #ifdef CONFIG_AMLOGIC_POST_PROCESS_MANAGER | |
1988 | vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, | |
1989 | NULL); | |
1990 | vf_reg_provider(&vmpeg_vf_prov); | |
1991 | vf_notify_receiver(PROVIDER_NAME, VFRAME_EVENT_PROVIDER_START, NULL); | |
1992 | #else | |
1993 | vf_provider_init(&vmpeg_vf_prov, PROVIDER_NAME, &vmpeg_vf_provider, | |
1994 | NULL); | |
1995 | vf_reg_provider(&vmpeg_vf_prov); | |
1996 | #endif | |
fe96802b | 1997 | if (vmpeg12_amstream_dec_info.rate != 0) { |
6d2907a6 | 1998 | if (!is_reset) { |
d481db31 NQ |
1999 | vf_notify_receiver(PROVIDER_NAME, |
2000 | VFRAME_EVENT_PROVIDER_FR_HINT, | |
2001 | (void *) | |
2002 | ((unsigned long) | |
2003 | vmpeg12_amstream_dec_info.rate)); | |
6d2907a6 LC |
2004 | fr_hint_status = VDEC_HINTED; |
2005 | } | |
fe96802b NQ |
2006 | } else |
2007 | fr_hint_status = VDEC_NEED_HINT; | |
b9164398 NQ |
2008 | |
2009 | stat |= STAT_VF_HOOK; | |
2010 | ||
2011 | recycle_timer.data = (ulong)&recycle_timer; | |
2012 | recycle_timer.function = vmpeg_put_timer_func; | |
2013 | recycle_timer.expires = jiffies + PUT_INTERVAL; | |
2014 | ||
2015 | add_timer(&recycle_timer); | |
2016 | ||
2017 | stat |= STAT_TIMER_ARM; | |
2018 | ||
2019 | amvdec_start(); | |
2020 | ||
2021 | stat |= STAT_VDEC_RUN; | |
2022 | ||
2023 | return 0; | |
2024 | } | |
2025 | ||
a6c89e96 NQ |
2026 | #ifdef DUMP_USER_DATA |
2027 | static int amvdec_mpeg12_init_userdata_dump(void) | |
2028 | { | |
2029 | user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL); | |
2030 | if (user_data_buf) | |
2031 | return 1; | |
2032 | else | |
2033 | return 0; | |
2034 | } | |
2035 | #endif | |
2036 | ||
b9164398 NQ |
2037 | static int amvdec_mpeg12_probe(struct platform_device *pdev) |
2038 | { | |
2039 | struct vdec_s *pdata = *(struct vdec_s **)pdev->dev.platform_data; | |
2040 | ||
2041 | amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe start.\n"); | |
2042 | ||
2043 | if (pdata == NULL) { | |
2044 | amlog_level(LOG_LEVEL_ERROR, | |
2045 | "amvdec_mpeg12 platform data undefined.\n"); | |
2046 | return -EFAULT; | |
2047 | } | |
2048 | ||
2049 | if (pdata->sys_info) | |
2050 | vmpeg12_amstream_dec_info = *pdata->sys_info; | |
2051 | ||
b9164398 | 2052 | pdata->dec_status = vmpeg12_dec_status; |
d481db31 | 2053 | pdata->set_isreset = vmpeg12_set_isreset; |
a6c89e96 NQ |
2054 | |
2055 | pdata->user_data_read = vmpeg12_user_data_read; | |
2056 | pdata->reset_userdata_fifo = vmpeg12_reset_userdata_fifo; | |
b78f4cd9 | 2057 | pdata->wakeup_userdata_poll = vmpeg12_wakeup_userdata_poll; |
d481db31 | 2058 | is_reset = 0; |
b9164398 | 2059 | |
fe96802b NQ |
2060 | vmpeg12_vdec_info_init(); |
2061 | ||
a674e3cd | 2062 | INIT_WORK(&set_clk_work, vmpeg12_set_clk); |
b9164398 NQ |
2063 | if (vmpeg12_init() < 0) { |
2064 | amlog_level(LOG_LEVEL_ERROR, "amvdec_mpeg12 init failed.\n"); | |
fe96802b NQ |
2065 | kfree(gvs); |
2066 | gvs = NULL; | |
9b670a2d | 2067 | pdata->dec_status = NULL; |
b9164398 NQ |
2068 | return -ENODEV; |
2069 | } | |
a6c89e96 NQ |
2070 | vdec = pdata; |
2071 | #ifdef DUMP_USER_DATA | |
2072 | amvdec_mpeg12_init_userdata_dump(); | |
2073 | #endif | |
4522fc84 | 2074 | vmpeg12_create_userdata_manager(ccbuf_phyAddress_virt, CCBUF_SIZE); |
a6c89e96 | 2075 | |
fe96802b NQ |
2076 | INIT_WORK(&userdata_push_work, userdata_push_do_work); |
2077 | INIT_WORK(¬ify_work, vmpeg12_notify_work); | |
2078 | INIT_WORK(&reset_work, reset_do_work); | |
a674e3cd | 2079 | |
a6c89e96 NQ |
2080 | |
2081 | last_offset = 0xFFFFFFFF; | |
2082 | #ifdef DUMP_USER_DATA | |
2083 | last_wp = 0; | |
2084 | reset_user_data_buf(); | |
2085 | #endif | |
b9164398 NQ |
2086 | |
2087 | amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 probe end.\n"); | |
2088 | ||
2089 | return 0; | |
2090 | } | |
2091 | ||
2092 | static int amvdec_mpeg12_remove(struct platform_device *pdev) | |
2093 | { | |
fe96802b NQ |
2094 | cancel_work_sync(&userdata_push_work); |
2095 | cancel_work_sync(¬ify_work); | |
2096 | cancel_work_sync(&reset_work); | |
a994f6d6 | 2097 | cancel_work_sync(&set_clk_work); |
fe96802b | 2098 | |
b9164398 NQ |
2099 | if (stat & STAT_VDEC_RUN) { |
2100 | amvdec_stop(); | |
2101 | stat &= ~STAT_VDEC_RUN; | |
2102 | } | |
2103 | ||
2104 | if (stat & STAT_ISR_REG) { | |
2105 | vdec_free_irq(VDEC_IRQ_1, (void *)vmpeg12_dec_id); | |
2106 | stat &= ~STAT_ISR_REG; | |
2107 | } | |
2108 | ||
2109 | if (stat & STAT_TIMER_ARM) { | |
2110 | del_timer_sync(&recycle_timer); | |
2111 | stat &= ~STAT_TIMER_ARM; | |
2112 | } | |
2113 | ||
2114 | if (stat & STAT_VF_HOOK) { | |
6d2907a6 | 2115 | if (fr_hint_status == VDEC_HINTED) |
fe96802b NQ |
2116 | vf_notify_receiver(PROVIDER_NAME, |
2117 | VFRAME_EVENT_PROVIDER_FR_END_HINT, NULL); | |
2118 | fr_hint_status = VDEC_NO_NEED_HINT; | |
b9164398 NQ |
2119 | |
2120 | vf_unreg_provider(&vmpeg_vf_prov); | |
2121 | stat &= ~STAT_VF_HOOK; | |
2122 | } | |
2123 | ||
2124 | amvdec_disable(); | |
2125 | if (ccbuf_phyAddress_is_remaped_nocache) | |
7d2e7e17 | 2126 | codec_mm_unmap_phyaddr(ccbuf_phyAddress_virt); |
b9164398 NQ |
2127 | |
2128 | ccbuf_phyAddress_virt = NULL; | |
2129 | ccbuf_phyAddress = 0; | |
2130 | ccbuf_phyAddress_is_remaped_nocache = 0; | |
a6c89e96 | 2131 | vmpeg12_destroy_userdata_manager(); |
fe96802b NQ |
2132 | |
2133 | if (mm_blk_handle) { | |
2134 | decoder_bmmu_box_free(mm_blk_handle); | |
2135 | mm_blk_handle = NULL; | |
2136 | } | |
b9164398 NQ |
2137 | amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 remove.\n"); |
2138 | ||
fe96802b NQ |
2139 | kfree(gvs); |
2140 | gvs = NULL; | |
a6c89e96 NQ |
2141 | vdec = NULL; |
2142 | ||
2143 | #ifdef DUMP_USER_DATA | |
2144 | if (user_data_buf) { | |
2145 | show_user_data_buf(); | |
2146 | kfree(user_data_buf); | |
2147 | user_data_buf = NULL; | |
2148 | } | |
2149 | #endif | |
fe96802b | 2150 | |
b9164398 NQ |
2151 | return 0; |
2152 | } | |
2153 | ||
2154 | /****************************************/ | |
2155 | ||
2156 | static struct platform_driver amvdec_mpeg12_driver = { | |
2157 | .probe = amvdec_mpeg12_probe, | |
2158 | .remove = amvdec_mpeg12_remove, | |
2159 | #ifdef CONFIG_PM | |
2160 | .suspend = amvdec_suspend, | |
2161 | .resume = amvdec_resume, | |
2162 | #endif | |
2163 | .driver = { | |
2164 | .name = DRIVER_NAME, | |
2165 | } | |
2166 | }; | |
2167 | ||
2168 | static struct codec_profile_t amvdec_mpeg12_profile = { | |
2169 | .name = "mpeg12", | |
2170 | .profile = "" | |
2171 | }; | |
2172 | ||
fe96802b NQ |
2173 | |
2174 | static struct mconfig mpeg12_configs[] = { | |
2175 | MC_PU32("stat", &stat), | |
2176 | MC_PU32("dec_control", &dec_control), | |
2177 | MC_PU32("error_frame_skip_level", &error_frame_skip_level), | |
2178 | }; | |
2179 | static struct mconfig_node mpeg12_node; | |
2180 | ||
2181 | ||
b9164398 NQ |
2182 | static int __init amvdec_mpeg12_driver_init_module(void) |
2183 | { | |
2184 | amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module init\n"); | |
2185 | ||
2186 | if (platform_driver_register(&amvdec_mpeg12_driver)) { | |
2187 | amlog_level(LOG_LEVEL_ERROR, | |
2188 | "failed to register amvdec_mpeg12 driver\n"); | |
2189 | return -ENODEV; | |
2190 | } | |
2191 | vcodec_profile_register(&amvdec_mpeg12_profile); | |
fe96802b NQ |
2192 | INIT_REG_NODE_CONFIGS("media.decoder", &mpeg12_node, |
2193 | "mpeg12", mpeg12_configs, CONFIG_FOR_RW); | |
b9164398 NQ |
2194 | return 0; |
2195 | } | |
2196 | ||
2197 | static void __exit amvdec_mpeg12_driver_remove_module(void) | |
2198 | { | |
2199 | amlog_level(LOG_LEVEL_INFO, "amvdec_mpeg12 module remove.\n"); | |
2200 | ||
2201 | platform_driver_unregister(&amvdec_mpeg12_driver); | |
2202 | } | |
2203 | ||
2204 | /****************************************/ | |
b9164398 NQ |
2205 | module_param(dec_control, uint, 0664); |
2206 | MODULE_PARM_DESC(dec_control, "\n amvmpeg12 decoder control\n"); | |
2207 | module_param(error_frame_skip_level, uint, 0664); | |
2208 | MODULE_PARM_DESC(error_frame_skip_level, | |
2209 | "\n amvdec_mpeg12 error_frame_skip_level\n"); | |
a6c89e96 | 2210 | module_param(force_first_i_ready, uint, 0664); |
a674e3cd | 2211 | MODULE_PARM_DESC(force_first_i_ready, "\n amvmpeg12 force_first_i_ready\n"); |
b9164398 NQ |
2212 | |
2213 | module_init(amvdec_mpeg12_driver_init_module); | |
2214 | module_exit(amvdec_mpeg12_driver_remove_module); | |
2215 | ||
2216 | MODULE_DESCRIPTION("AMLOGIC MPEG1/2 Video Decoder Driver"); | |
2217 | MODULE_LICENSE("GPL"); | |
2218 | MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>"); |