/* arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
 *
 * Verificion code for aDSP VDEC packets from userspace.
 *
 * Copyright (C) 2008 Google, Inc.
 * Copyright (c) 2008-2010, 2012 The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/io.h>

#include <mach/qdsp5/qdsp5vdeccmdi.h>
#include "adsp.h"
#include <mach/debug_mm.h>

#define MAX_FLUSH_SIZE 160

static inline void *high_low_short_to_ptr(unsigned short high,
					  unsigned short low)
{
	return (void *)((((unsigned long)high) << 16) | ((unsigned long)low));
}

static inline void ptr_to_high_low_short(void *ptr, unsigned short *high,
					 unsigned short *low)
{
	*high = (unsigned short)((((unsigned long)ptr) >> 16) & 0xffff);
	*low = (unsigned short)((unsigned long)ptr & 0xffff);
}

static int pmem_fixup_high_low(unsigned short *high,
				unsigned short *low,
				unsigned short size_high,
				unsigned short size_low,
				struct msm_adsp_module *module,
				unsigned long *addr, unsigned long *size,
				struct file **filp, unsigned long *offset)
{
	void *phys_addr;
	unsigned long phys_size;
	unsigned long kvaddr;

	phys_addr = high_low_short_to_ptr(*high, *low);
	phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
	MM_DBG("virt %x %x\n", (unsigned int)phys_addr,
			(unsigned int)phys_size);
	if (phys_addr) {
		if (adsp_ion_fixup_kvaddr(module, &phys_addr,
			 &kvaddr, phys_size, filp, offset)) {
			MM_ERR("ah%x al%x sh%x sl%x addr %x size %x\n",
					*high, *low, size_high,
					size_low, (unsigned int)phys_addr,
					(unsigned int)phys_size);
			return -EINVAL;
		}
	}
	ptr_to_high_low_short(phys_addr, high, low);
	MM_DBG("phys %x %x\n", (unsigned int)phys_addr,
			(unsigned int)phys_size);
	if (addr)
		*addr = kvaddr;
	if (size)
		*size = phys_size;
	return 0;
}

static int verify_vdec_pkt_cmd(struct msm_adsp_module *module,
			       void *cmd_data, size_t cmd_size)
{
	void *phys_addr;
	unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
	viddec_cmd_subframe_pkt *pkt;
	unsigned long subframe_pkt_addr;
	unsigned long subframe_pkt_size;
	unsigned short *frame_header_pkt;
	int i, num_addr, col_addr = 0, skip;
	int start_pos = 0, xdim_pos = 1, ydim_pos = 2;
	unsigned short *frame_buffer_high, *frame_buffer_low;
	unsigned long frame_buffer_size;
	unsigned short frame_buffer_size_high, frame_buffer_size_low;
	struct file *filp = NULL;
	unsigned long offset = 0;
	unsigned long Codec_Id = 0;

	MM_DBG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id,
					(unsigned int)cmd_data);
	if (cmd_id != VIDDEC_CMD_SUBFRAME_PKT) {
		MM_INFO("adsp_video: unknown video packet %u\n", cmd_id);
		return 0;
	}
	if (cmd_size < sizeof(viddec_cmd_subframe_pkt))
		return -1;

	pkt = (viddec_cmd_subframe_pkt *)cmd_data;
	phys_addr = high_low_short_to_ptr(pkt->subframe_packet_high,
				pkt->subframe_packet_low);

	if (pmem_fixup_high_low(&(pkt->subframe_packet_high),
				&(pkt->subframe_packet_low),
				pkt->subframe_packet_size_high,
				pkt->subframe_packet_size_low,
				module,
				&subframe_pkt_addr,
				&subframe_pkt_size,
				&filp, &offset))
		return -1;
	Codec_Id = pkt->codec_selection_word;
	/*Invalidate cache before accessing the cached pmem buffer*/
	if (adsp_ion_do_cache_op(module, phys_addr, (void *)subframe_pkt_addr,
		subframe_pkt_size*2, offset, ION_IOC_INV_CACHES)){
		MM_ERR("Cache operation failed for" \
			" phys addr high %x addr low %x\n",
			pkt->subframe_packet_high, pkt->subframe_packet_low);
		return -EINVAL;
	}
	/* deref those ptrs and check if they are a frame header packet */
	frame_header_pkt = (unsigned short *)subframe_pkt_addr;
	switch (frame_header_pkt[0]) {
	case 0xB201: /* h.264 vld in dsp */
	   if (Codec_Id == 0x8) {
		num_addr = 16;
		skip = 0;
		start_pos = 5;
	   } else {
	       num_addr = 16;
	       skip = 0;
	       start_pos = 6;
	       col_addr = 17;
	   }
		break;
	case 0x8201: /* h.264 vld in arm */
		num_addr = 16;
		skip = 0;
		start_pos = 6;
		break;
	case 0x4D01: /* mpeg-4 and h.263 vld in arm */
		num_addr = 3;
		skip = 0;
		start_pos = 5;
		break;
	case 0x9201: /*For Real Decoder*/
		num_addr = 2;
		skip = 0;
		start_pos = 5;
		break;
	case 0xBD01: /* mpeg-4 and h.263 vld in dsp */
		num_addr = 3;
		skip = 0;
		start_pos = 6;
		if (((frame_header_pkt[5] & 0x000c) >> 2) == 0x2) /* B-frame */
			start_pos = 8;
		break;
	case 0x0001: /* wmv */
		num_addr = 2;
		skip = 0;
		start_pos = 5;
		break;
	case 0xC201: /*WMV main profile*/
		 num_addr = 3;
		 skip = 0;
		 start_pos = 6;
		 break;
	case 0xDD01: /* VP6 */
		num_addr = 3;
		skip = 0;
		start_pos = 10;
		break;
	case 0xFD01: /* VP8 */
		num_addr = 3;
		skip = 0;
		start_pos = 24;
		break;
	default:
		return 0;
	}

	frame_buffer_high = &frame_header_pkt[start_pos];
	frame_buffer_low = &frame_header_pkt[start_pos + 1];
	frame_buffer_size = (frame_header_pkt[xdim_pos] *
			     frame_header_pkt[ydim_pos] * 3) / 2;
	ptr_to_high_low_short((void *)frame_buffer_size,
			      &frame_buffer_size_high,
			      &frame_buffer_size_low);
	for (i = 0; i < num_addr; i++) {
		if (frame_buffer_high && frame_buffer_low) {
			if (pmem_fixup_high_low(frame_buffer_high,
						frame_buffer_low,
						frame_buffer_size_high,
						frame_buffer_size_low,
						module,
						NULL, NULL, NULL, NULL))
				return -EINVAL;
	   }
		frame_buffer_high += 2;
		frame_buffer_low += 2;
	}
	/* Patch the output buffer. */
	frame_buffer_high += 2*skip;
	frame_buffer_low += 2*skip;
	if (frame_buffer_high && frame_buffer_low) {
		if (pmem_fixup_high_low(frame_buffer_high,
					frame_buffer_low,
					frame_buffer_size_high,
					frame_buffer_size_low,
					module,
					NULL, NULL, NULL, NULL))
			return -EINVAL;
	}
	if (col_addr) {
		frame_buffer_high += 2;
		frame_buffer_low += 2;
		/* Patch the Co-located buffers.*/
		frame_buffer_size =  (72 * frame_header_pkt[xdim_pos] *
					frame_header_pkt[ydim_pos]) >> 16;
		ptr_to_high_low_short((void *)frame_buffer_size,
					&frame_buffer_size_high,
					&frame_buffer_size_low);
		for (i = 0; i < col_addr; i++) {
			if (frame_buffer_high && frame_buffer_low) {
				if (pmem_fixup_high_low(frame_buffer_high,
						frame_buffer_low,
						frame_buffer_size_high,
						frame_buffer_size_low,
						module,
						NULL, NULL, NULL, NULL))
					return -EINVAL;
			}
			frame_buffer_high += 2;
			frame_buffer_low += 2;
		}
	}
	/*Flush the cached mem subframe packet before sending to DSP*/
	if (adsp_ion_do_cache_op(module,  phys_addr, (void *)subframe_pkt_addr,
		MAX_FLUSH_SIZE, offset, ION_IOC_CLEAN_CACHES)){
		MM_ERR("Cache operation failed for" \
			" phys addr high %x addr low %x\n",
			pkt->subframe_packet_high, pkt->subframe_packet_low);
		return -EINVAL;
	}
	return 0;
}

int adsp_video_verify_cmd(struct msm_adsp_module *module,
			 unsigned int queue_id, void *cmd_data,
			 size_t cmd_size)
{
	switch (queue_id) {
	case QDSP_mpuVDecPktQueue:
		return verify_vdec_pkt_cmd(module, cmd_data, cmd_size);
	default:
		MM_INFO("unknown video queue %u\n", queue_id);
		return 0;
	}
}

