]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/dream/qdsp5/adsp_video_verify_cmd.c
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel...
[net-next-2.6.git] / drivers / staging / dream / qdsp5 / adsp_video_verify_cmd.c
CommitLineData
caff4cae
IM
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
34static 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
40static 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
47static 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
75static 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
150int 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