linux/drivers/staging/dream/qdsp5/adsp_video_verify_cmd.c
<<
>>
Prefs
   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
 164