upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / staging / dream / qdsp5 / adsp_video_verify_cmd.c
1 /* arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
2  *
3  * Verificion code for aDSP VDEC packets from userspace.
4  *
5  * Copyright (c) 2008 QUALCOMM Incorporated
6  * Copyright (C) 2008 Google, Inc.
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  */
18 #include <linux/io.h>
19
20 #define ADSP_DEBUG_MSGS 0
21 #if ADSP_DEBUG_MSGS
22 #define DLOG(fmt,args...) \
23         do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
24              ##args); } \
25         while (0)
26 #else
27 #define DLOG(x...) do {} while (0)
28 #endif
29
30
31 #include <mach/qdsp5/qdsp5vdeccmdi.h>
32 #include "adsp.h"
33
34 static inline void *high_low_short_to_ptr(unsigned short high,
35                                           unsigned short low)
36 {
37         return (void *)((((unsigned long)high) << 16) | ((unsigned long)low));
38 }
39
40 static inline void ptr_to_high_low_short(void *ptr, unsigned short *high,
41                                          unsigned short *low)
42 {
43         *high = (unsigned short)((((unsigned long)ptr) >> 16) & 0xffff);
44         *low = (unsigned short)((unsigned long)ptr & 0xffff);
45 }
46
47 static int pmem_fixup_high_low(unsigned short *high,
48                                 unsigned short *low,
49                                 unsigned short size_high,
50                                 unsigned short size_low,
51                                 struct msm_adsp_module *module,
52                                 unsigned long *addr, unsigned long *size)
53 {
54         void *phys_addr;
55         unsigned long phys_size;
56         unsigned long kvaddr;
57
58         phys_addr = high_low_short_to_ptr(*high, *low);
59         phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
60         DLOG("virt %x %x\n", phys_addr, phys_size);
61         if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size)) {
62                 DLOG("ah%x al%x sh%x sl%x addr %x size %x\n",
63                         *high, *low, size_high, size_low, phys_addr, phys_size);
64                 return -1;
65         }
66         ptr_to_high_low_short(phys_addr, high, low);
67         DLOG("phys %x %x\n", phys_addr, phys_size);
68         if (addr)
69                 *addr = kvaddr;
70         if (size)
71                 *size = phys_size;
72         return 0;
73 }
74
75 static int verify_vdec_pkt_cmd(struct msm_adsp_module *module,
76                                void *cmd_data, size_t cmd_size)
77 {
78         unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
79         viddec_cmd_subframe_pkt *pkt;
80         unsigned long subframe_pkt_addr;
81         unsigned long subframe_pkt_size;
82         viddec_cmd_frame_header_packet *frame_header_pkt;
83         int i, num_addr, skip;
84         unsigned short *frame_buffer_high, *frame_buffer_low;
85         unsigned long frame_buffer_size;
86         unsigned short frame_buffer_size_high, frame_buffer_size_low;
87
88         DLOG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id, cmd_data);
89         if (cmd_id != VIDDEC_CMD_SUBFRAME_PKT) {
90                 printk(KERN_INFO "adsp_video: unknown video packet %u\n",
91                         cmd_id);
92                 return 0;
93         }
94         if (cmd_size < sizeof(viddec_cmd_subframe_pkt))
95                 return -1;
96
97         pkt = (viddec_cmd_subframe_pkt *)cmd_data;
98
99         if (pmem_fixup_high_low(&(pkt->subframe_packet_high),
100                                 &(pkt->subframe_packet_low),
101                                 pkt->subframe_packet_size_high,
102                                 pkt->subframe_packet_size_low,
103                                 module,
104                                 &subframe_pkt_addr,
105                                 &subframe_pkt_size))
106                 return -1;
107
108         /* deref those ptrs and check if they are a frame header packet */
109         frame_header_pkt = (viddec_cmd_frame_header_packet *)subframe_pkt_addr;
110
111         switch (frame_header_pkt->packet_id) {
112         case 0xB201: /* h.264 */
113                 num_addr = skip = 8;
114                 break;
115         case 0x4D01: /* mpeg-4 and h.263 */
116                 num_addr = 3;
117                 skip = 0;
118                 break;
119         default:
120                 return 0;
121         }
122
123         frame_buffer_high = &frame_header_pkt->frame_buffer_0_high;
124         frame_buffer_low = &frame_header_pkt->frame_buffer_0_low;
125         frame_buffer_size = (frame_header_pkt->x_dimension *
126                              frame_header_pkt->y_dimension * 3) / 2;
127         ptr_to_high_low_short((void *)frame_buffer_size,
128                               &frame_buffer_size_high,
129                               &frame_buffer_size_low);
130         for (i = 0; i < num_addr; i++) {
131                 if (pmem_fixup_high_low(frame_buffer_high, frame_buffer_low,
132                                         frame_buffer_size_high,
133                                         frame_buffer_size_low,
134                                         module,
135                                         NULL, NULL))
136                         return -1;
137                 frame_buffer_high += 2;
138                 frame_buffer_low += 2;
139         }
140         /* Patch the output buffer. */
141         frame_buffer_high += 2*skip;
142         frame_buffer_low += 2*skip;
143         if (pmem_fixup_high_low(frame_buffer_high, frame_buffer_low,
144                                 frame_buffer_size_high,
145                                 frame_buffer_size_low, module, NULL, NULL))
146                 return -1;
147         return 0;
148 }
149
150 int adsp_video_verify_cmd(struct msm_adsp_module *module,
151                          unsigned int queue_id, void *cmd_data,
152                          size_t cmd_size)
153 {
154         switch (queue_id) {
155         case QDSP_mpuVDecPktQueue:
156                 DLOG("\n");
157                 return verify_vdec_pkt_cmd(module, cmd_data, cmd_size);
158         default:
159                 printk(KERN_INFO "unknown video queue %u\n", queue_id);
160                 return 0;
161         }
162 }
163