Пример #1
0
/*
 * init and exit
 */
static int __init imapx200_decode_init(void)
{
	/* call probe */
	if(platform_driver_register(&imapx200_decode_driver))
	{
		decode_error("Fail to register platform driver for IMAPX200 Decode Driver\n");
		decode_debug("IMAPX200 Decode Driver init failed\n");
		return -EPERM;
	}

	decode_debug("IMAPX200 Hantro 9170 Decode Driver init OK\n");

	return IMAPX200_DECODE_RET_OK;
}
Пример #2
0
static void __exit imapx200_decode_exit(void)
{
	/* call remove */
	platform_driver_unregister(&imapx200_decode_driver);

	decode_debug("IMAPX200 Decode Driver exit OK\n");
}
Пример #3
0
/*
 * File operations, this system call should be called before
 * any interrupt occurs. You can call fcntl system call to set 
 * driver node file property in order to get asynchronization
 * signal.
 */
static int imapx200_decode_fasync(int fd, struct file *file, int mode)
{
	decode_param_t *dev;
	struct fasync_struct **async_queue;

	dev = &decode_param;
	async_queue = NULL;

	/* select whitch interrupt this instance will sign up for */
	if((unsigned int *)(file->private_data) == &(decode_param.dec_instance))
	{
		decode_debug("IMAPX200 Decode dec fasync called\n");
		async_queue = &(decode_param.async_queue_dec);
	}
	else if((unsigned int *)(file->private_data) == &(decode_param.pp_instance))
	{
		decode_debug("IMAPX200 Decode pp fasync called\n");
		async_queue = &(decode_param.async_queue_pp);
	}
	else
		decode_error("IMAPX200 Decode wrong fasync called\n");

	return fasync_helper(fd, file, mode, async_queue);
}
Пример #4
0
/*
 * open system call just mark file private data as a decode 
 * instance by default, and you can change it by a ioctl call
 */
static int imapx200_decode_open(struct inode *inode, struct file *file)
{
	mutex_lock(&decode_lock);
	if(decode_open_count == 0)
	{
#if defined(CONFIG_IMAP_MMPOOL_MANAGEMENT)	/* 2010/10/21 */
		power_on_mpool_in_memalloc();
#endif	/* CONFIG_IMAP_MMPOOL_MANAGEMENT */
		decode_enable_hw_power();
	}
	decode_open_count++;
	mutex_unlock(&decode_lock);

	/* dec instance by default, you can change it by ioctl pp instance */
	file->private_data = &(decode_param.dec_instance);

	decode_debug("IMAPX200 Decode open OK\n");

	return IMAPX200_DECODE_RET_OK;
}
Пример #5
0
/*
 * fasync system call be called here
 */
static int imapx200_decode_release(struct inode *inode, struct file *file)
{
#ifdef CONFIG_IMAP_DECODE_SIGNAL_MODE
	/* reset decode driver node file property */
	if(file->f_flags & FASYNC)
		imapx200_decode_fasync(-1, file, 0);
#endif	/* CONFIG_IMAP_DECODE_SIGNAL_MODE */

	mutex_lock(&decode_lock);
	decode_open_count--;
	if(decode_open_count == 0)
	{
		decode_disable_hw_power();
#if defined(CONFIG_IMAP_MMPOOL_MANAGEMENT)	/* 2010/10/21 */
		power_off_mpool_in_memalloc();
#endif	/* CONFIG_IMAP_MMPOOL_MANAGEMENT */
	}
	mutex_unlock(&decode_lock);

	decode_debug("IMAPX200 Decode release OK\n");

	return IMAPX200_DECODE_RET_OK;
}
Пример #6
0
/* tbc_decode:
 * 	If ptr is NULL then this uses in place decoding, 
 *	otherwise fills out the structure pointered to.
 *	When not using in place decoding the structure should be
 *	initialised with zeros.  tlp elements will be decoded if 
 *	tbc->tlp is not NULL.
 */
int tbc_decode (BYTE *data, unsigned int length, tbc_t **ptr)
{
	tenc_element_t 	element;
	tbc_t 		*tbc;
	int		in_place;
	int		ret;

	if (*ptr != NULL) {
		tbc		= *ptr;
		in_place 	= 0;
	} else {
		tbc		= (tbc_t *) data;
		in_place	= 1;
	}	

	/* Decode the required elements */
	if ((ret = load_uint (&data, &length, "endU", &(tbc->endian))) < 0)
		return ret;
	if ((ret = load_uint (&data, &length, "ws U", &(tbc->ws))) < 0)
		return ret;
	if ((ret = load_uint (&data, &length, "vs U", &(tbc->vs))) < 0)
		return ret;

	if ((ret = tenc_walk_to_element (data, &length, "bc B", &element)) < 0)
		return ret;
	
	tbc->bytecode_len	= element.length;
	tbc->bytecode		= element.data.bytes;
	data			= element.next;

	/* Decode optional elements */
	if (in_place) {
		tbc->tlp	= NULL;
		tbc->symbols	= NULL;
		tbc->ffi	= NULL;
		tbc->debug	= NULL;
	} else {
		if (tbc->tlp != NULL) {
			tbc->tlp->fmt 		= NULL;
			tbc->tlp->symbol 	= NULL;
		}
	}

	/* Copy pointer */
	*ptr 		= tbc;

	while (length > 0) {
		if (tenc_decode_element (data, &length, &element) < 0)
			return 0; /* ignore errors */

		if (ids_match (element.id, "tlpL")) {
			tbc->tlp = decode_tlp (data, tbc->tlp, &element); 
		} else if (in_place && ids_match (element.id, "ffiL")) {
			tbc->ffi = decode_ffi (data, &element);
		} else if (in_place && ids_match (element.id, "stbL")) {
			tbc->symbols = decode_symbols (&element);
		} else if (in_place && ids_match (element.id, "dbgL")) {
			tbc->debug = decode_debug (data, &element);
		}

		data = element.next;
	}

	return 0;
}
Пример #7
0
/*
 * platform operation relate functions
 */
static int imapx200_decode_probe(struct platform_device *pdev)
{
	int		ret;
	unsigned int	size;
	struct resource	*res;

	/* get decode hardware clock and enable it */
	imap_vdec_clock = NULL;
	imap_vdec_clock = clk_get(&pdev->dev, "vdec");
	if(imap_vdec_clock == NULL)
	{
		decode_error("Fail to get decode hardware source\n");
		return IMAPX200_DECODE_RET_ERROR;
	}
	clk_enable(imap_vdec_clock);

	/* 
	 * 9170 decode ic is supposed that powered on when using, but uboot powers on 
	 * it for some usage, so i have to power down it here to ensure that when system
	 * boot, decode ic is not costing elec
	 */
	decode_disable_hw_power();

	/* initualize open count */
	decode_open_count = 0;

	/* initualize instances just for mark */
	decode_param.dec_instance	= 0;
	decode_param.pp_instance	= 0;

#ifdef CONFIG_IMAP_DECODE_POLL_MODE
	/* initualize wait queue */
	init_waitqueue_head(&wait_decode);
#endif	/* CONFIG_IMAP_DECODE_POLL_MODE */

#ifdef CONFIG_IMAP_DECODE_SIGNAL_MODE
	/* initualize async queue */
	decode_param.async_queue_dec	= NULL;
	decode_param.async_queue_pp	= NULL;
#endif	/* CONFIG_IMAP_DECODE_SIGNAL_MODE */

	/* get register base address */
	res = NULL;
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if(res == NULL)
	{
		decode_error("Fail to get IMAPX200 Decode resource\n");
		return -ENOENT;
	}

	/* request memory region for registers */
	size = res->end - res->start + 1;
	decode_param.reg_reserved_size = size;
	decode_param.resource_mem = NULL;
	decode_param.resource_mem = request_mem_region(res->start, size, pdev->name);
	if(decode_param.resource_mem == NULL)
	{
		decode_error("Fail to get IMAPX200 Decode register memory region\n");
		return -ENOENT;
	}
	decode_param.reg_base_phys_addr = res->start;

	decode_param.reg_base_virt_addr = NULL;
	/*
	 * ATTENTON: memory map for registers should always be nocache method
	 * cuz we don't want register data to be cached 
	 */
	decode_param.reg_base_virt_addr = ioremap_nocache(res->start, size);
	if(decode_param.reg_base_virt_addr == NULL)
	{
		decode_error("Fail to ioremap IMAPX200 Decode register base address\n");
		return -EINVAL;
	}

	/* get and config irq */
	res = NULL;
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if(res == NULL)
	{
		decode_error("Fail to get IMAPX200 Decode irq resource\n");
		return -ENOENT;
	}
	
	if(res->start != IRQ_VDEC)
	{
		decode_error("Get wrong irq number for IMAPX200 Decode\n");
		return -ENOENT;
	}

	/*
	 * decoder and pp shared one irq line, so we must register irq in share mode
	 */
	ret = -1;
	ret = request_irq(res->start, imapx200_decode_irq_handle, IRQF_DISABLED, \
			pdev->name, (void *)(&decode_param));
	if(ret)
	{
		decode_error("Fail to request irq for IMAPX200 Decode device\n");
		return ret;
	}

	/* register char device driver */
	ret = -1;
	ret = decode_driver_register();
	if(ret)
	{
		decode_error("Fail to register char device for IMAPX200 Decode\n");
		return ret;
	}

	/* reset hardware */
	reset_hw_reg_decode();

	mutex_init(&decode_lock);

	decode_debug("IMAPX200 Decode Driver probe OK\n");

	return IMAPX200_DECODE_RET_OK;
}
Пример #8
0
/* 
 * This irq handle function should never be reexecute at the same
 * time. Pp and decode share the same interrupt signal thread, in 
 * pp external mode, a finished interruption refer to be a pp irq, 
 * but in pp pipeline mode(decode pipeline with decode), recieved 
 * irq refers to be a decode interruption.
 * In this driver, we use System V signal asynchronization thread
 * communication. So you should set System V in you kernel make 
 * menuconfig.
 * ATTENTION: if your application runs in multi-thread mode, be 
 * aware that if you set your application getting this signal
 * as process mode, the signal will be send to your application's
 * main thread, and signal will never be processed twice. So in 
 * this case you won't get anything in your derived thread.
 */
static irqreturn_t imapx200_decode_irq_handle(int irq, void *dev_id)
{
	unsigned int handled;
	unsigned int irq_status_dec;
	unsigned int irq_status_pp;
	decode_param_t *dev;
	
	handled = 0;
	dev = (decode_param_t *)dev_id;

	/* interrupt status register read */
	irq_status_dec = readl(dev->reg_base_virt_addr + IMAPX200_DECODE_IRQ_STAT_DEC * 4);
	irq_status_pp = readl(dev->reg_base_virt_addr + IMAPX200_DECODE_IRQ_STAT_PP * 4);

	/* this structure is to enable irq in irq */
	if((irq_status_dec & IMAPX200_DECODE_IRQ_BIT_DEC) || (irq_status_pp & IMAPX200_DECODE_IRQ_BIT_PP))
	{
		if(irq_status_dec & IMAPX200_DECODE_IRQ_BIT_DEC)
		{
#ifdef CONFIG_IMAP_DEC_HW_PERFORMANCE
			do_gettimeofday(&(dev->end_time));
#endif
			/* clear irq */
			writel(irq_status_dec & (~IMAPX200_DECODE_IRQ_BIT_DEC), \
					dev->reg_base_virt_addr + IMAPX200_DECODE_IRQ_STAT_DEC * 4);

#ifdef CONFIG_IMAP_DECODE_SIGNAL_MODE
			/* fasync kill for decode instances to send signal */
			if(dev->async_queue_dec != NULL)
				kill_fasync(&(dev->async_queue_dec), SIGIO, POLL_IN);
			else
				decode_alert("IMAPX200 Decode dec received w/o anybody waiting for it\n");
#endif	/* CONFIG_IMAP_DECODE_SIGNAL_MODE */

#ifdef CONFIG_IMAP_DECODE_POLL_MODE
			dec_poll_mark = 1;
			wake_up(&wait_decode);
#endif	/* CONFIG_IMAP_DECODE_POLL_MODE */

			decode_debug("IMAPX200 Decode get dec irq\n");
		}

		/* In pp pipeline mode, only one decode interrupt will be set */
		if(irq_status_pp & IMAPX200_DECODE_IRQ_BIT_PP)
		{
#ifdef CONFIG_IMAP_DEC_HW_PERFORMANCE
			do_gettimeofday(&(dev->end_time));
#endif
			/* clear irq */
			writel(irq_status_dec & (~IMAPX200_DECODE_IRQ_BIT_PP), \
					dev->reg_base_virt_addr + IMAPX200_DECODE_IRQ_STAT_PP * 4);

#ifdef CONFIG_IMAP_DECODE_SIGNAL_MODE
			/* fasync kill for pp instance */
			if(dev->async_queue_pp != NULL)
				kill_fasync(&dev->async_queue_pp, SIGIO, POLL_IN);
			else
				decode_alert("IMAPX200 Decode pp received w/o anybody waiting for it\n");
#endif	/* CONFIG_IMAP_DECODE_SIGNAL_MODE */

#ifdef CONFIG_IMAP_DECODE_POLL_MODE
			pp_poll_mark = 1;
			wake_up(&wait_decode);
#endif	/* CONFIG_IMAP_DECODE_POLL_MODE */

			 decode_debug("IMAPX200 Decode get pp irq\n");
		}
		
		handled = 1;
	}
	else
		decode_debug("IMAPX200 Decode Driver get an unknown irq\n");

	return IRQ_RETVAL(handled);
}