Ejemplo n.º 1
0
static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);

	buf = req->req.buf + req->req.actual;
	prefetchw(buf);

	length = req->req.length - req->req.actual;
	dma_cache_maint(buf, length, DMA_FROM_DEVICE);

	if(length == 0)
		pktcnt = 1;
	else
		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;

	ctrl =  readl(S3C_UDC_OTG_DOEPCTL(ep_num));

	writel(virt_to_phys(buf), S3C_UDC_OTG_DOEPDMA(ep_num));
	writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DOEPTSIZ(ep_num));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DOEPCTL(ep_num));

	DEBUG_OUT_EP("%s: EP%d RX DMA start : DOEPDMA = 0x%x, DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			readl(S3C_UDC_OTG_DOEPDMA(ep_num)),
			readl(S3C_UDC_OTG_DOEPTSIZ(ep_num)),
			readl(S3C_UDC_OTG_DOEPCTL(ep_num)),
			buf, pktcnt, length);
	return 0;

}
Ejemplo n.º 2
0
/*! arc_read_setup_buffer
 */
static void arc_read_setup_buffer(struct pcd_instance *pcd, u8 * buffer_ptr)
{
        struct ep_queue_head    *qh = &udc_controller->ep_qh[0 * 2 + ARC_DIR_OUT];
        int                     timeout;

        dma_cache_maint(qh, sizeof(struct ep_queue_head), DMA_FROM_DEVICE);

        /* C.f 39.16.3.2.1 Setup Phase - Setup Packet Handling (2.3 hardware and later)
         */

        /* 1. Clear ENDPTSETUPSTAT */
        UOG_ENDPTSETUPSTAT |= (1 << 0);                 /* Clear recieve endpoint status */

        do {
                /* 2. set tripwire */
                UOG_USBCMD |= USB_CMD_SUTW;

                /* 3. read setup buffer */
                memcpy(buffer_ptr, (u8 *) qh->setup_buffer, 8);

                /* 4. check tripwire, loop if reset */
        } while (!(UOG_USBCMD & USB_CMD_SUTW));

        /* 5. reset tripwire */
        UOG_USBCMD &= ~USB_CMD_SUTW;

        // XXX This needs to be fixed, should not need to resort to timeout
        timeout = 10000000;
        while ((UOG_ENDPTSETUPSTAT & 1) && --timeout) { continue; }
        if (timeout == 0) printk(KERN_ERR "%s: TIMEOUT\n", __FUNCTION__);
}
static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
		enum dma_data_direction dir)
{
	struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
	dma_addr_t dma_addr;
	int needs_bounce = 0;

	if (device_info)
		DO_STATS ( device_info->map_op_count++ );

	dma_addr = virt_to_dma(dev, ptr);

	if (dev->dma_mask) {
		unsigned long mask = *dev->dma_mask;
		unsigned long limit;

		limit = (mask + 1) & ~mask;
		if (limit && size > limit) {
			dev_err(dev, "DMA mapping too big (requested %#x "
				"mask %#Lx)\n", size, *dev->dma_mask);
			return ~0;
		}

		
		needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
	}

	if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
		struct safe_buffer *buf;

		buf = alloc_safe_buffer(device_info, ptr, size, dir);
		if (buf == 0) {
			dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
			       __func__, ptr);
			return 0;
		}

		dev_dbg(dev,
			"%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
			__func__, buf->ptr, virt_to_dma(dev, buf->ptr),
			buf->safe, buf->safe_dma_addr);

		if ((dir == DMA_TO_DEVICE) ||
		    (dir == DMA_BIDIRECTIONAL)) {
			dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
				__func__, ptr, buf->safe, size);
			memcpy(buf->safe, ptr, size);
		}
		ptr = buf->safe;

		dma_addr = buf->safe_dma_addr;
	} else {
		
		dma_cache_maint(ptr, size, dir);
	}

	return dma_addr;
}
Ejemplo n.º 4
0
static int setdma_tx(struct s3c_ep *ep, struct s3c_request *req)
{
	u32 *buf, ctrl = 0;
	u32 length, pktcnt;
	u32 ep_num = ep_index(ep);

	buf = req->req.buf + req->req.actual;
	prefetch(buf);
	length = req->req.length - req->req.actual;

	if(ep_num == EP0_CON) {
		length = min(length, (u32)ep_maxpacket(ep));
	}

	req->req.actual += length;
	dma_cache_maint(buf, length, DMA_TO_DEVICE);

	if (length == 0)
		pktcnt = 1;
	else
		pktcnt = (length - 1)/(ep->ep.maxpacket) + 1;
	

/* Remove Flush the endpoint's Tx FIFO code : LSI Patch*/	
#if 0 
	/* Flush the endpoint's Tx FIFO */
        writel(ep_num<<6, S3C_UDC_OTG_GRSTCTL);
        writel((ep_num<<6)|0x20, S3C_UDC_OTG_GRSTCTL);
        while(readl(S3C_UDC_OTG_GRSTCTL) & 0x20);
#endif

	/* Write the FIFO number to be used for this endpoint */
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	ctrl &= ~DEPCTL_TXFNUM_MASK;;
	ctrl |= (ep_num << DEPCTL_TXFNUM_BIT);
	writel(ctrl , S3C_UDC_OTG_DIEPCTL(ep_num));


	writel(virt_to_phys(buf), S3C_UDC_OTG_DIEPDMA(ep_num));
	writel((pktcnt<<19)|(length<<0), S3C_UDC_OTG_DIEPTSIZ(ep_num));
	ctrl = readl(S3C_UDC_OTG_DIEPCTL(ep_num));
	writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, S3C_UDC_OTG_DIEPCTL(ep_num));

	ctrl = readl(S3C_UDC_OTG_DIEPCTL(EP0_CON));
	ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT))|(ep_num<<DEPCTL_NEXT_EP_BIT);
	writel(ctrl, S3C_UDC_OTG_DIEPCTL(EP0_CON));

	DEBUG_IN_EP("%s:EP%d TX DMA start : DIEPDMA0 = 0x%x, DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n"
			"\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n",
			__func__, ep_num,
			readl(S3C_UDC_OTG_DIEPDMA(ep_num)),
			readl(S3C_UDC_OTG_DIEPTSIZ(ep_num)),
			readl(S3C_UDC_OTG_DIEPCTL(ep_num)),
			buf, pktcnt, length);

	return length;
}
Ejemplo n.º 5
0
static void complete_rx(struct s3c_udc *dev, u8 ep_num)
{
	struct s3c_ep *ep = &dev->ep[ep_num];
	struct s3c_request *req = NULL;
	u32 ep_tsr = 0, xfer_size = 0, xfer_length, is_short = 0;

	if (list_empty(&ep->queue)) {
		DEBUG_OUT_EP("%s: RX DMA done : NULL REQ on OUT EP-%d\n",
					__func__, ep_num);
		return;

	}

	req = list_entry(ep->queue.next, struct s3c_request, queue);

	ep_tsr = readl(S3C_UDC_OTG_DOEPTSIZ(ep_num));

	if (ep_num == EP0_CON)
		xfer_size = (ep_tsr & 0x7f);

	else
		xfer_size = (ep_tsr & 0x7fff);
	
	dma_cache_maint(req->req.buf, req->req.length, DMA_FROM_DEVICE);
	xfer_length = req->req.length - xfer_size;
	req->req.actual += min(xfer_length, req->req.length - req->req.actual);
	is_short = (xfer_length < ep->ep.maxpacket);

	DEBUG_OUT_EP("%s: RX DMA done : ep = %d, rx bytes = %d/%d, "
		     "is_short = %d, DOEPTSIZ = 0x%x, remained bytes = %d\n",
			__func__, ep_num, req->req.actual, req->req.length,
			is_short, ep_tsr, xfer_size);

	if (is_short || req->req.actual == xfer_length) {
		if(ep_num == EP0_CON && dev->ep0state == DATA_STATE_RECV) {
			DEBUG_OUT_EP("	=> Send ZLP\n");
			dev->ep0state = WAIT_FOR_SETUP;
			s3c_udc_ep0_zlp();

		} else {
			done(ep, req, 0);

			if(!list_empty(&ep->queue)) {
				req = list_entry(ep->queue.next, struct s3c_request, queue);
				DEBUG_OUT_EP("%s: Next Rx request start...\n", __func__);
				if (ep_num == EP0_CON && dev->ep0state == WAIT_FOR_SETUP)
					setdma_rx(ep, req, 1);
				else
					setdma_rx(ep, req, 0);
			}
		}
	}
Ejemplo n.º 6
0
/*! arc_read_rcv_buffer
 *
 * Recover number of bytes DMA'd to receive buffer, sync.
 */
int arc_read_rcv_buffer (struct pcd_instance *pcd, struct usbd_endpoint_instance *endpoint)
{
        struct arc_private_struct *privdata = endpoint->privdata;
        struct ep_td_struct     *curr_td = privdata->cur_dtd;
        struct ep_queue_head    *qh = privdata->cur_dqh;
        struct usbd_urb         *rx_urb = endpoint->rcv_urb;

        /* sync qh and td structures, note that urb-buffer was invalidated in arc_add_buffer_to_dtd() */
        dma_cache_maint(qh, sizeof(struct ep_queue_head), DMA_FROM_DEVICE);
        dma_cache_maint(curr_td, sizeof(struct ep_td_struct), DMA_FROM_DEVICE);

        if (rx_urb) {
                int length = rx_urb->buffer_length -
                        ((le32_to_cpu(curr_td->size_ioc_sts) & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS);

                if (TRACE_VERBOSE) TRACE_MSG4(pcd->TAG, "buffer_length: %d alloc_length: %d Len: %d (%x)" ,
                                rx_urb->buffer_length, rx_urb->alloc_length, length,
                                le32_to_cpu(curr_td->size_ioc_sts));
                return length;
        }
        TRACE_MSG1(pcd->TAG, "NO RCV URB (%x)" , le32_to_cpu(curr_td->size_ioc_sts));
        return 0;
}
Ejemplo n.º 7
0
static void omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
                                         unsigned int u32_count, int is_write)
{
	const int block_size = 16;
	unsigned int block_count, len;
	int dma_ch;
	unsigned long fifo_reg, timeout, jiffies_before, jiffies_spent;
	static unsigned long max_jiffies = 0;

	dma_ch = omap_nand_dma_ch;
	block_count = u32_count * 4 / block_size;
	nand_write_reg(NND_STATUS, 0x0f);
	nand_write_reg(NND_FIFOCTRL, (block_size << 24) | block_count);
	fifo_reg = NAND_BASE + NND_FIFO;
	if (is_write) {
		omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_TIPB,
					 OMAP_DMA_AMODE_CONSTANT, fifo_reg,
					 0, 0);
		omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_EMIFF,
					OMAP_DMA_AMODE_POST_INC,
					virt_to_phys(addr),
					0, 0);
//		omap_set_dma_src_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_4);
		/* Set POSTWRITE bit */
		nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 16));
	} else {
		omap_set_dma_src_params(dma_ch, OMAP_DMA_PORT_TIPB,
					OMAP_DMA_AMODE_CONSTANT, fifo_reg,
					0, 0);
		omap_set_dma_dest_params(dma_ch, OMAP_DMA_PORT_EMIFF,
					 OMAP_DMA_AMODE_POST_INC,
					 virt_to_phys(addr),
					 0, 0);
//		omap_set_dma_dest_burst_mode(dma_ch, OMAP_DMA_DATA_BURST_8);
		/* Set PREFETCH bit */
		nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) | (1 << 17));
	}
	omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, block_size / 4,
				     block_count, OMAP_DMA_SYNC_FRAME,
				     0, 0);
	init_completion(&omap_nand_dma_comp);

	len = u32_count << 2;
	dma_cache_maint(addr, len, DMA_TO_DEVICE);
	omap_start_dma(dma_ch);
	jiffies_before = jiffies;
	timeout = wait_for_completion_timeout(&omap_nand_dma_comp,
					      msecs_to_jiffies(1000));
	jiffies_spent = (unsigned long)((long)jiffies - (long)jiffies_before);
	if (jiffies_spent > max_jiffies)
		max_jiffies = jiffies_spent;

	if (timeout == 0) {
		printk(KERN_WARNING "omap-hw-nand: DMA timeout after %u ms, max. seen latency %u ms\n",
		       jiffies_to_msecs(jiffies_spent),
		       jiffies_to_msecs(max_jiffies));
	}
	if (!is_write)
		dma_cache_maint(addr, len, DMA_FROM_DEVICE);

	nand_write_reg(NND_CTRL, nand_read_reg(NND_CTRL) & ~((1 << 16) | (1 << 17)));
}
Ejemplo n.º 8
0
/*! arc_add_buffer_to_dtd
 *
 * C.f. 39.16.5.3 - case 1: Link list is empty
 */
static void arc_add_buffer_to_dtd (struct pcd_instance *pcd, struct usbd_endpoint_instance *endpoint,
                int dir, int len, int offset)
{
        struct otg_instance     *otg = pcd->otg;
        struct usbd_urb         *urb = endpoint->active_urb;
        struct arc_private_struct *privdata = endpoint->privdata;

        u8                      hs = pcd->bus->high_speed;
        u8                      physicalEndpoint = endpoint->physicalEndpoint[hs];
        u8                      bEndpointAddress = endpoint->bEndpointAddress[hs];
        u8                      epnum = bEndpointAddress & 0x3f;
        u16                     wMaxPacketSize = endpoint->wMaxPacketSize[hs];
        struct ep_queue_head    *dQH = &udc_controller->ep_qh[2 * epnum + dir];
        struct ep_td_struct     *dtd = &(udc_controller->ep_dtd[2 * epnum + dir]);

        u32                     mask = 0;
        int                     timeout1 = 0;
        int                     timeout2 = 0;

        u32                     endptstat = -1;
        u32                     endptprime = -1;
        u32                     endptcomplete = -1;

        TRACE_MSG6(pcd->TAG, "[%2d] USBCMD: %08x ENDPTPRIME: %08x COMPLETE: %08x STATUS: %08x %s",
                        2*epnum+dir, UOG_USBCMD, UOG_ENDPTPRIME, UOG_ENDPTCOMPLETE,
                        (u32)dQH->size_ioc_int_sts, (dir == ARC_DIR_OUT) ? "OUT" : "IN");

        if (urb && urb->buffer) {

                TRACE_MSG4(pcd->TAG, "buffer: %x length: %d alloc: %d dir: %d ",
                                urb->buffer, urb->actual_length, urb->buffer_length, dir);

                /* flush cache for IN */
                if ((dir == ARC_DIR_IN) && urb->actual_length)
                        dma_cache_maint(urb->buffer, urb->actual_length, DMA_TO_DEVICE);

                /* invalidate cache for OUT */
                else if ((dir == ARC_DIR_OUT) && urb->buffer_length)
                        dma_cache_maint(urb->buffer, urb->alloc_length, DMA_FROM_DEVICE);
        }

        /* Set size and interrupt on each dtd, Clear reserved field,
         * set pointers and flush from cache, and save in cur_dqh for dtd_releases()
         */
        memset(dtd, 0, sizeof(struct ep_td_struct));
        dtd->size_ioc_sts = cpu_to_le32(((len << DTD_LENGTH_BIT_POS) | DTD_IOC | DTD_STATUS_ACTIVE));
        dtd->size_ioc_sts &= cpu_to_le32(~DTD_RESERVED_FIELDS);
        dtd->buff_ptr0 = cpu_to_le32(endpoint->active_urb ?  (u32) (virt_to_phys (endpoint->active_urb->buffer + offset)) : 0);
        dtd->next_td_ptr = cpu_to_le32(DTD_NEXT_TERMINATE);
        dtd->next_td_virt = NULL;
        dma_cache_maint(dtd, sizeof(struct ep_td_struct), DMA_TO_DEVICE);
        privdata->cur_dqh = dQH;

        /* Case 1 - Step 1 - Write dQH next pointer and dQH terminate bit to 0 as single DWord */
        dQH->next_dtd_ptr = cpu_to_le32( virt_to_phys((void *)dtd) & EP_QUEUE_HEAD_NEXT_POINTER_MASK);

        /* Case 1 - Step 2 - Clear active and halt bit */
        dQH->size_ioc_int_sts &= le32_to_cpu(~(EP_QUEUE_HEAD_STATUS_ACTIVE | EP_QUEUE_HEAD_STATUS_HALT));

        dma_cache_maint(dQH, sizeof(struct ep_queue_head), DMA_TO_DEVICE);

        /* Case 1 - Step 3 - Prime endpoint by writing ENDPTPRIME */
        mask = (dir == ARC_DIR_OUT) ?  (1 << epnum) : (1 << (epnum + 16));

        /* Verify that endpoint PRIME is not set, wait if necessary. */
        for (timeout1 = 0; (UOG_ENDPTPRIME & mask) && (timeout1 ++ < 100); udelay(1));

        /* ep0 needs extra tests */
        UNLESS(epnum) {
                /* C.f. 39.16.3.2.2 Data Phase */
                UOG_ENDPTPRIME |= mask;
                for (timeout2 = 0; timeout2++ < 100; ) {
                        endptprime = UOG_ENDPTPRIME;    // order may be important
                        endptstat = UOG_ENDPTSTAT;      // we check stat after prime
                        BREAK_IF(endptstat & mask);
                        BREAK_UNLESS(endptprime & mask);
                }
                if (!(endptstat & mask) && !(endptprime & mask)) {
                        TRACE_MSG2(pcd->TAG, "[%2d] ENDPTSETUPSTAT: %04x PREMATURE FAILUURE", 2*epnum+dir, UOG_ENDPTSETUPSTAT);
                }
                TRACE_MSG6(pcd->TAG, "[%2d] ENDPTPRIME %08x ENPTSTAT: %08x mask: %08x timeout: %d:%d SET",
                                2*epnum+dir, UOG_ENDPTPRIME, UOG_ENDPTSTAT, mask, timeout1, timeout2);;
        }
        /* epn general case */
        else {
Ejemplo n.º 9
0
/* Input arguments for S3C_MFC_IOCTL_MFC_SET_CONFIG */
int s3c_mfc_set_config_params(s3c_mfc_inst_context_t *mfc_inst, s3c_mfc_args_t *args)		
{   __D("\n");
	int             ret, size;
	unsigned int    param_change_enable = 0, param_change_val;
	unsigned char	*start;
	unsigned int	offset;
	
	switch (args->set_config.in_config_param) {
	case S3C_MFC_SET_CONFIG_DEC_ROTATE:
#if (S3C_MFC_ROTATE_ENABLE == 1)
		args->set_config.out_config_value_old[0]
			= s3c_mfc_inst_set_post_rotate(mfc_inst, args->set_config.in_config_value[0]);
#else
		mfc_err("S3C_MFC_IOCTL_MFC_SET_CONFIG with S3C_MFC_SET_CONFIG_DEC_ROTATE is not supported\n");
		mfc_err("please check if S3C_MFC_ROTATE_ENABLE is defined as 1 in MfcConfig.h file\n");
#endif
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_H263_PARAM:
		args->set_config.out_config_value_old[0] = mfc_inst->h263_annex;
		mfc_inst->h263_annex = args->set_config.in_config_value[0];
		mfc_debug("parameter = 0x%x\n", mfc_inst->h263_annex);
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_SLICE_MODE:
		if (mfc_inst->enc_num_slices) {
			args->set_config.out_config_value_old[0] = 1;
			args->set_config.out_config_value_old[1] = mfc_inst->enc_num_slices;
		} else {
			args->set_config.out_config_value_old[0] = 0;
			args->set_config.out_config_value_old[1] = 0;
		}

		if (args->set_config.in_config_value[0])
			mfc_inst->enc_num_slices = args->set_config.in_config_value[1];
		else
			mfc_inst->enc_num_slices = 0;

		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CONFIG_ENC_PARAM_CHANGE:

		switch (args->set_config.in_config_value[0]) {
		case S3C_ENC_PARAM_GOP_NUM:
			param_change_enable = (1 << 0);
			break;

		case S3C_ENC_PARAM_INTRA_QP:
			param_change_enable = (1 << 1);
			break;

		case S3C_ENC_PARAM_BITRATE:
			param_change_enable = (1 << 2);
			break;

		case S3C_ENC_PARAM_F_RATE:
			param_change_enable = (1 << 3);
			break;

		case S3C_ENC_PARAM_INTRA_REF:
			param_change_enable = (1 << 4);
			break;

		case S3C_ENC_PARAM_SLICE_MODE:
			param_change_enable = (1 << 5);
			break;

		default:
			break;
		}

		param_change_val  = args->set_config.in_config_value[1];
		ret = s3c_mfc_inst_enc_param_change(mfc_inst, param_change_enable, param_change_val);

		break;

	case S3C_MFC_SET_CONFIG_ENC_CUR_PIC_OPT:

		switch (args->set_config.in_config_value[0]) {
		case S3C_ENC_PIC_OPT_IDR:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 1);
			break;

		case S3C_ENC_PIC_OPT_SKIP:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 0);
			break;

		case S3C_ENC_PIC_OPT_RECOVERY:
			mfc_inst->enc_pic_option ^= (args->set_config.in_config_value[1] << 24);
			break;

		default:
			break;
		}

		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_CLEAN:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_TO_DEVICE);
		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_clean_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		outer_clean_range((unsigned long)start, (unsigned long)end);
		*/
		
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_INVALIDATE:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_FROM_DEVICE);

		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_inv_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end = start + args->set_config.in_config_value[1];
		outer_inv_range((unsigned long)start, (unsigned long)end);
		*/
		ret = S3C_MFC_INST_RET_OK;
		break;

	case S3C_MFC_SET_CACHE_CLEAN_INVALIDATE:
		/* 
		 * in_config_value[0] : start address in user layer 
		 * in_config_value[1] : offset 
		 * in_config_value[2] : start address of stream buffer in user layer
		 */
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = mfc_inst->stream_buffer + offset;
		size = args->set_config.in_config_value[1];
		dma_cache_maint(start, size, DMA_BIDIRECTIONAL);

		/*
		offset = args->set_config.in_config_value[0] - args->set_config.in_config_value[2];
		start = (unsigned int)mfc_inst->stream_buffer + offset;
		end   = start + args->set_config.in_config_value[1];
		dmac_flush_range((void *)start, (void *)end);

		start = (unsigned int)mfc_inst->phys_addr_stream_buffer + offset;
		end = start + args->set_config.in_config_value[1];
		outer_flush_range((unsigned long)start, (unsigned long)end);
		*/
		ret = S3C_MFC_INST_RET_OK;
		break;

#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))
	case S3C_MFC_SET_PADDING_SIZE:
		mfc_debug("padding size = %d\n", 		\
			args->set_config.in_config_value[0]);
		mfc_inst->padding_size = args->set_config.in_config_value[0];
		ret = S3C_MFC_INST_RET_OK;
		break;
#endif

	default:
		ret = -1;
	}

	/* Output arguments for S3C_MFC_IOCTL_MFC_SET_CONFIG */
	args->set_config.ret_code = ret;

	return S3C_MFC_INST_RET_OK;
}
Ejemplo n.º 10
0
/*
 *  Node 2 Buffer DMA callback
 */
void ipc_dma_node2buf_callback(int lch, u16 ch_status, void *data)
{
	int ret, i;
	struct USB_IPC_API_PARAMS *ipc_ch;
	IPC_DATA_HEADER *header;

	DEBUG("%s\n", __func__);

	ipc_ch = ipc_memcpy_node2buf.ipc_ch;
	/* Set DONE bit. If all node buffer are copied to URB buffer */
	ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
		comand |= NODE_DESCRIPTOR_DONE_BIT;

	ipc_memcpy_node2buf.buf_phy +=
		ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
			length;
	ipc_memcpy_node2buf.total_size +=
		ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
			length;
	ipc_ch->write_ptr.total_num +=
		ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
			length;

	if (ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
	    comand & NODE_DESCRIPTOR_LAST_BIT)
		ipc_memcpy_node2buf.frame_index++;

	header = (IPC_DATA_HEADER *) ipc_ch->write_ptr.temp_buff;

	if ((ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.node_index].
	     comand & NODE_DESCRIPTOR_END_BIT) ||
	    (ipc_memcpy_node2buf.node_index >=
	     ipc_memcpy_node2buf.ipc_ch->max_node_num) ||
	    ipc_memcpy_node2buf.frame_index >= header->nb_frame) {
		omap_stop_dma(ipc_memcpy_node2buf.dma_ch);

		dma_cache_maint((void *) ipc_ch->write_ptr.temp_buff,
				ipc_ch->max_temp_buff_size,
				DMA_FROM_DEVICE);

		/* change to big endian */
		header = (IPC_DATA_HEADER *) ipc_ch->write_ptr.temp_buff;
		DEBUG("DMA copy ok:header->version=%x header->nb_frame=%d"
		      "total_size=%d total_num=%d\n",
			header->version, header->nb_frame,
			ipc_memcpy_node2buf.total_size,
			ipc_ch->write_ptr.total_num);
		usb_ipc_exchange_endian16(&(header->version));
		if (header->nb_frame > 0) {
			for (i = 0; i < header->nb_frame; i++)
				usb_ipc_exchange_endian16(&(header->
							     frames[i].
								length));
			usb_ipc_exchange_endian16(&(header->nb_frame));
#if defined(USE_IPC_FRAME_HEADER_CHECKSUM)
			if (header->options == 1) {
				/*TODO: calculate checksum here */
				usb_ipc_exchange_endian16(&(header->
								checksum));
			}
#endif
		}
		/* change to big endian end */

		ipc_ch->write_ptr.end_flag = 1;
		dma_cache_maint((const void *) ipc_ch->write_ptr.temp_buff,
				sizeof(IPC_DATA_HEADER_INDEX) +
					(sizeof(IPC_FRAME_DESCRIPTOR) *
						(header->nb_frame)),
				DMA_TO_DEVICE);
		if (!ipc_ch->usb_ifs)
			return;
		LOG_IPC_ACTIVITY(aIpcW, iIpcW, 0x4);
		ret = ipc_ch->usb_ifs->usb_write(
				(unsigned char *) ipc_ch->write_ptr.temp_buff,
				ipc_memcpy_node2buf.
				total_size);
		if (ret != 0)
			ipc_ch->write_flag = 0;

		return;
	}

	ipc_memcpy_node2buf.node_index++;

	dma_cache_maint(ipc_memcpy_node2buf.
			node_ptr[ipc_memcpy_node2buf.node_index].data_ptr,
		ipc_memcpy_node2buf.node_ptr[ipc_memcpy_node2buf.
			node_index].length,
		DMA_TO_DEVICE);

	DEBUG("Continue DMA:buf_phy=%lx total_size=%d node_index=%d\n",
		ipc_memcpy_node2buf.buf_phy, ipc_memcpy_node2buf.total_size,
		ipc_memcpy_node2buf.node_index);
	LOG_IPC_ACTIVITY(aIpcW, iIpcW, 0x3);
	OMAP_DMA_MEM2MEM_START(ipc_memcpy_node2buf.dma_ch,
		NODE_BUF_PHYS_ADDR(ipc_memcpy_node2buf.
			node_ptr[ipc_memcpy_node2buf.node_index].data_ptr),
		ipc_memcpy_node2buf.buf_phy,
		ipc_memcpy_node2buf.
			node_ptr[ipc_memcpy_node2buf.node_index].
				length);
}
Ejemplo n.º 11
0
/*
 *  Buffer 2 Node DMA callback
 */
void ipc_dma_buf2node_callback(int lch, u16 ch_status, void *data)
{
	int size;
	HW_CTRL_IPC_WRITE_STATUS_T ipc_status;
	struct USB_IPC_API_PARAMS *ipc_ch;

	DEBUG("%s\n", __func__);

	ipc_ch = ipc_memcpy_buf2node.ipc_ch;
	/* Set DONE bit. If all node buffer are copied to URB buffer,
	 * finished
	 */
	ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].comand |=
		NODE_DESCRIPTOR_DONE_BIT;
	ipc_memcpy_buf2node.buf_phy +=
		ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].
			length;
	ipc_memcpy_buf2node.header->frames[ipc_memcpy_buf2node.
					   frame_index].length -=
		ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].
			length;
	if (ipc_memcpy_buf2node.header->
	    frames[ipc_memcpy_buf2node.frame_index].length == 0) {
		ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].
			comand |= NODE_DESCRIPTOR_LAST_BIT;
		ipc_memcpy_buf2node.frame_index++;
	}

	dma_cache_maint(ipc_ch->read_ptr.
			node_ptr[ipc_memcpy_buf2node.node_index].data_ptr,
		ipc_ch->read_ptr.node_ptr
			[ipc_memcpy_buf2node.node_index].length,
		DMA_FROM_DEVICE);

	ipc_memcpy_buf2node.total_size +=
		ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].
			length;

	ipc_memcpy_buf2node.node_index++;
	if ((ipc_memcpy_buf2node.node_index >=
	     ipc_memcpy_buf2node.ipc_ch->read_ptr.node_num) ||
	    (ipc_memcpy_buf2node.frame_index >=
	     ipc_memcpy_buf2node.header->nb_frame)) {
		omap_stop_dma(ipc_memcpy_buf2node.dma_ch);

		ipc_ch->read_ptr.node_ptr
			[ipc_memcpy_buf2node.node_index-1].comand |=
		    NODE_DESCRIPTOR_END_BIT;

		DEBUG("DMA copy ok:header->version=%x header->nb_frame=%d\n",
			ipc_memcpy_buf2node.header->version,
			ipc_memcpy_buf2node.header->nb_frame);
		DEBUG("buf_phy=%lx total_size=%d node_index=%d "
		      "frame_index=%d\n",
			ipc_memcpy_buf2node.buf_phy,
			ipc_memcpy_buf2node.total_size,
			ipc_memcpy_buf2node.node_index,
			ipc_memcpy_buf2node.frame_index);

		/* clear flag to indicate API read function call is done */
		ipc_memcpy_buf2node.ipc_ch->read_flag = 0;

		/* read callback, ... */
		if (ipc_memcpy_buf2node.ipc_ch->cfg.read_callback != NULL) {
			ipc_status.nb_bytes = ipc_memcpy_buf2node.total_size;
			ipc_status.channel = &ipc_memcpy_buf2node.ipc_ch->ch;
			LOG_IPC_ACTIVITY(aIpcR, iIpcR, 0x16);
			ipc_memcpy_buf2node.ipc_ch->cfg.
				read_callback(&ipc_status);
		} else {
			LOG_IPC_ACTIVITY(aIpcR, iIpcR, 0x1E);
			SEM_UNLOCK(&ipc_memcpy_buf2node.ipc_ch->read_ptr.
				read_mutex);
		}
		return;
	}

	/* set DMA parameters, then start DMA transfer */
	size = ipc_memcpy_buf2node.header->frames
			[ipc_memcpy_buf2node.frame_index].length;
	if (size >
	    ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].
	    length) {
		size = ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.
				node_index].length;
	}
	ipc_ch->read_ptr.node_ptr[ipc_memcpy_buf2node.node_index].length =
	    size;

	DEBUG("Continue DMA:buf_phy=%lx total_size=%d"
	      "node_index=%d frame_index=%d\n",
		ipc_memcpy_buf2node.buf_phy, ipc_memcpy_buf2node.total_size,
		ipc_memcpy_buf2node.node_index,
		ipc_memcpy_buf2node.frame_index);
	LOG_IPC_ACTIVITY(aIpcR, iIpcR, 0x15);
	/* set DMA parameters, then start DMA transfer */
	OMAP_DMA_MEM2MEM_START(ipc_memcpy_buf2node.dma_ch,
		ipc_memcpy_buf2node.buf_phy,
		NODE_BUF_PHYS_ADDR(ipc_ch->read_ptr.
			node_ptr[ipc_memcpy_buf2node.node_index].data_ptr),
		size);
}
Ejemplo n.º 12
0
/*
 *  Node 2 Buffer DMA transfer
 */
int ipc_dma_memcpy_node2buf(struct USB_IPC_API_PARAMS *ipc_ch,
			    HW_CTRL_IPC_DATA_NODE_DESCRIPTOR_T *ctrl_ptr)
{
	int ret, i;
	int frame_size, frame_index, len;
	IPC_DATA_HEADER *header;

	DEBUG("%s\n", __func__);

	if (ipc_memcpy_node2buf.dma_ch == -1) {	/* error: using memcpy */
		/* copy data into write URB buffer */
		frame_size = 0;
		frame_index = 0;
		header = (IPC_DATA_HEADER *) ipc_ch->write_ptr.temp_buff;
		len = sizeof(IPC_DATA_HEADER_INDEX) +
			((header->nb_frame) * sizeof(IPC_FRAME_DESCRIPTOR));
		for (i = 0; i < ipc_ch->max_node_num; i++) {
			if ((len + ctrl_ptr[i].length) >
			    ipc_ch->max_temp_buff_size) {
				break;
			}
			memcpy((void *) &ipc_ch->write_ptr.temp_buff[len],
			       ctrl_ptr[i].data_ptr, ctrl_ptr[i].length);
			frame_size += ctrl_ptr[i].length;
			len += ctrl_ptr[i].length;
			ctrl_ptr[i].comand |= NODE_DESCRIPTOR_DONE_BIT;
			ipc_ch->write_ptr.total_num += ctrl_ptr[i].length;
			if (ctrl_ptr[i].comand & NODE_DESCRIPTOR_LAST_BIT) {
				header->frames[frame_index].length = frame_size;
				frame_index++;
				frame_size = 0;
			}
			if (ctrl_ptr[i].comand & NODE_DESCRIPTOR_END_BIT)
				break;
		}
		header->nb_frame = frame_index;
		/* change to little endian */
		usb_ipc_exchange_endian16(&(header->version));
		if (header->nb_frame > 0) {
			for (i = 0; i < header->nb_frame; i++)
				usb_ipc_exchange_endian16(&(header->
						frames[i].length));
			usb_ipc_exchange_endian16(&(header->nb_frame));
		}
		/* change to little endian end */
		ipc_ch->write_ptr.end_flag = 1;
		if (!ipc_ch->usb_ifs)
			return 0;
		ret = ipc_ch->usb_ifs->usb_write((unsigned char *)ipc_ch->
					write_ptr.temp_buff, len);
		if (ret != 0)
			ipc_ch->write_flag = 0;

		return 0;
	}

	/* generate header */
	header = (IPC_DATA_HEADER *)ipc_ch->write_ptr.temp_buff;
	frame_size = 0;
	frame_index = 0;
	len = sizeof(IPC_DATA_HEADER_INDEX) +
		((header->nb_frame) * sizeof(IPC_FRAME_DESCRIPTOR));
	for (i = 0; i < ipc_ch->max_node_num; i++) {
		if (((len + ctrl_ptr[i].length) >
		     ipc_ch->max_temp_buff_size) ||
		    (ctrl_ptr[i].length <= 0) ||
		    (ctrl_ptr[i].length > MAX_FRAME_SIZE)) {
			break;
		}
		frame_size += ctrl_ptr[i].length;
		len += ctrl_ptr[i].length;
		if (ctrl_ptr[i].comand & NODE_DESCRIPTOR_LAST_BIT) {
			header->frames[frame_index].length = frame_size;
			DEBUG("header->frames[%d]=%d\n", frame_index,
			      frame_size);
			frame_index++;
			frame_size = 0;
		}
		if (ctrl_ptr[i].comand & NODE_DESCRIPTOR_END_BIT)
			break;
	}
	header->nb_frame = frame_index;
	if (frame_index == 0) {
		omap_free_dma(ipc_memcpy_node2buf.dma_ch);
		usb_ipc_exchange_endian16(&(header->version));
		ipc_ch->write_ptr.end_flag = 1;
		return -1;
	}
	DEBUG("header->version=%x header->nb_frame=%d"
	      "write_ptr.temp_buff_phy_addr=%x\n",
	      header->version, header->nb_frame,
	      ipc_ch->write_ptr.temp_buff_phy_addr);

	ipc_memcpy_node2buf.ipc_ch = ipc_ch;
	ipc_memcpy_node2buf.node_index = 0;
	ipc_memcpy_node2buf.frame_index = 0;
	ipc_memcpy_node2buf.node_ptr = ctrl_ptr;
	ipc_memcpy_node2buf.total_size = sizeof(IPC_DATA_HEADER_INDEX) +
		(sizeof(IPC_FRAME_DESCRIPTOR) * (header->nb_frame));
	ipc_memcpy_node2buf.buf_phy = ipc_ch->write_ptr.temp_buff_phy_addr +
		(sizeof(IPC_DATA_HEADER_INDEX) +
			(sizeof(IPC_FRAME_DESCRIPTOR) * (header->nb_frame)));

	DEBUG("Start DMA:buf_phy=%lx total_size=%d node_index=%d\n",
		ipc_memcpy_node2buf.buf_phy,
		ipc_memcpy_node2buf.total_size,
		ipc_memcpy_node2buf.node_index);

	dma_cache_maint((void *) ipc_ch->write_ptr.temp_buff,
			sizeof(IPC_DATA_HEADER_INDEX) +
			  (sizeof(IPC_FRAME_DESCRIPTOR) * (header->nb_frame)),
			DMA_TO_DEVICE);
	dma_cache_maint(ipc_memcpy_node2buf.
			node_ptr[ipc_memcpy_node2buf.node_index].data_ptr,
		ipc_memcpy_node2buf.node_ptr
			[ipc_memcpy_node2buf.node_index].length,
			DMA_TO_DEVICE);

	LOG_IPC_ACTIVITY(aIpcW, iIpcW, 0x2);
	/* set DMA parameters, then start DMA transfer */
	OMAP_DMA_MEM2MEM_START(ipc_memcpy_node2buf.dma_ch,
			       NODE_BUF_PHYS_ADDR(ipc_memcpy_node2buf.
					node_ptr[ipc_memcpy_node2buf.
						node_index].data_ptr),
			       ipc_memcpy_node2buf.buf_phy,
			       ipc_memcpy_node2buf.
				node_ptr[ipc_memcpy_node2buf.node_index].
					length);
	return 0;
}
Ejemplo n.º 13
0
static int s3c_mfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret = 0;
	int buf_size;
	int nStrmLen, nHdrLen;
	int out;
	int yuv_size;
	int size;
	
	void		*temp;
	unsigned int	vir_mv_addr;
	unsigned int	vir_mb_type_addr;
	unsigned int	tmp;
	unsigned int	in_usr_data, yuv_buffer, run_index, out_buf_size, databuf_vaddr, offset;
	unsigned int	yuv_buff_cnt, databuf_paddr;
	unsigned char	*OutBuf	= NULL;
	unsigned char	*start, *end;
	
	s3c_mfc_inst_context_t	*pMfcInst;
	s3c_mfc_handle_t		*handle;
	s3c_mfc_codec_mode_t	codec_mode = 0;
	s3c_mfc_args_t		args;
	s3c_mfc_enc_info_t		enc_info;

	/* 
	 * Parameter Check
	 */
	handle = (s3c_mfc_handle_t *)file->private_data;
	if (handle->mfc_inst == NULL) {
		return -EFAULT;
	}

	pMfcInst = handle->mfc_inst;

	switch (cmd) {
	case S3C_MFC_IOCTL_MFC_MPEG4_ENC_INIT:
	case S3C_MFC_IOCTL_MFC_H264_ENC_INIT:
	case S3C_MFC_IOCTL_MFC_H263_ENC_INIT:
		mutex_lock(s3c_mfc_mutex);

		mfc_debug("cmd = %d\n", cmd);

		out = copy_from_user(&args.enc_init, (s3c_mfc_enc_init_arg_t *)arg, 
						sizeof(s3c_mfc_enc_init_arg_t));

		if ( cmd == S3C_MFC_IOCTL_MFC_MPEG4_ENC_INIT )
			codec_mode = MP4_ENC;
		else if ( cmd == S3C_MFC_IOCTL_MFC_H264_ENC_INIT )
			codec_mode = AVC_ENC;
		else if ( cmd == S3C_MFC_IOCTL_MFC_H263_ENC_INIT )
			codec_mode = H263_ENC;

		/* 
		 * Initialize MFC Instance
		 */
		enc_info.width			= args.enc_init.in_width;
		enc_info.height			= args.enc_init.in_height;
		enc_info.bitrate		= args.enc_init.in_bitrate;
		enc_info.gop_number		= args.enc_init.in_gopNum;
		enc_info.frame_rate_residual	= args.enc_init.in_frameRateRes;
		enc_info.frame_rate_division	= args.enc_init.in_frameRateDiv;

		/*
		enc_info.intraqp	= args.enc_init.in_intraqp;
		enc_info.qpmax		= args.enc_init.in_qpmax;
		enc_info.gamma		= args.enc_init.in_gamma;
		*/

		ret = s3c_mfc_instance_init_enc(pMfcInst, codec_mode, &enc_info);

		args.enc_init.ret_code = ret;
		out = copy_to_user((s3c_mfc_enc_init_arg_t *)arg, &args.enc_init, 
						sizeof(s3c_mfc_enc_init_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_MPEG4_ENC_EXE:
	case S3C_MFC_IOCTL_MFC_H264_ENC_EXE:
	case S3C_MFC_IOCTL_MFC_H263_ENC_EXE:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.enc_exe, (s3c_mfc_enc_exe_arg_t *)arg, 
							sizeof(s3c_mfc_enc_exe_arg_t));

		tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;

		start = pMfcInst->yuv_buffer;
		size = tmp * pMfcInst->yuv_buffer_count; 
		dma_cache_maint(start, size, DMA_TO_DEVICE);

		/* 
		 * Encode MFC Instance
		 */
		ret = s3c_mfc_inst_enc(pMfcInst, &nStrmLen, &nHdrLen);

		start = pMfcInst->stream_buffer;
		size = pMfcInst->stream_buffer_size;
		dma_cache_maint(start, size, DMA_FROM_DEVICE);

		args.enc_exe.ret_code	= ret;
		if (ret == S3C_MFC_INST_RET_OK) {
			args.enc_exe.out_encoded_size = nStrmLen;
			args.enc_exe.out_header_size  = nHdrLen;
		}
		out = copy_to_user((s3c_mfc_enc_exe_arg_t *)arg, &args.enc_exe, 
						sizeof(s3c_mfc_enc_exe_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_MPEG4_DEC_INIT:
	case S3C_MFC_IOCTL_MFC_H264_DEC_INIT:
	case S3C_MFC_IOCTL_MFC_H263_DEC_INIT:
	case S3C_MFC_IOCTL_MFC_VC1_DEC_INIT:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.dec_init, (s3c_mfc_dec_init_arg_t *)arg, 
							sizeof(s3c_mfc_dec_init_arg_t));

		if ( cmd == S3C_MFC_IOCTL_MFC_MPEG4_DEC_INIT )
			codec_mode = MP4_DEC;
		else if ( cmd == S3C_MFC_IOCTL_MFC_H264_DEC_INIT )
			codec_mode = AVC_DEC;
		else if ( cmd == S3C_MFC_IOCTL_MFC_H263_DEC_INIT)
			codec_mode = H263_DEC;
		else {
			codec_mode = VC1_DEC;
		}

		start = pMfcInst->stream_buffer;
		size = pMfcInst->stream_buffer_size;
		dma_cache_maint(start, size, DMA_TO_DEVICE);

		/* 
		 * Initialize MFC Instance
		 */
		ret = s3c_mfc_inst_init_dec(pMfcInst, codec_mode, 
						args.dec_init.in_strmSize);

		args.dec_init.ret_code	= ret;
		if (ret == S3C_MFC_INST_RET_OK) {
			args.dec_init.out_width	     = pMfcInst->width;
			args.dec_init.out_height     = pMfcInst->height;
			args.dec_init.out_buf_width  = pMfcInst->buf_width;
			args.dec_init.out_buf_height = pMfcInst->buf_height;
		}
		out = copy_to_user((s3c_mfc_dec_init_arg_t *)arg, &args.dec_init, 
							sizeof(s3c_mfc_dec_init_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_MPEG4_DEC_EXE:
	case S3C_MFC_IOCTL_MFC_H264_DEC_EXE:
	case S3C_MFC_IOCTL_MFC_H263_DEC_EXE:
	case S3C_MFC_IOCTL_MFC_VC1_DEC_EXE:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.dec_exe, (s3c_mfc_dec_exe_arg_t *)arg, 
							sizeof(s3c_mfc_dec_exe_arg_t));

		tmp = (pMfcInst->width * pMfcInst->height * 3) >> 1;

		start = pMfcInst->stream_buffer;
		size = pMfcInst->stream_buffer_size;
		dma_cache_maint(start, size, DMA_TO_DEVICE);

		ret = s3c_mfc_inst_dec(pMfcInst, args.dec_exe.in_strmSize);

		start = pMfcInst->yuv_buffer;
		size = tmp * pMfcInst->yuv_buffer_count;
		dma_cache_maint(start, size, DMA_FROM_DEVICE);	

		args.dec_exe.ret_code = ret;
		out = copy_to_user((s3c_mfc_dec_exe_arg_t *)arg, &args.dec_exe,
						 sizeof(s3c_mfc_dec_exe_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_GET_LINE_BUF_ADDR:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.get_buf_addr, 
			(s3c_mfc_get_buf_addr_arg_t *)arg, sizeof(s3c_mfc_get_buf_addr_arg_t));

		ret = s3c_mfc_inst_get_line_buff(pMfcInst, &OutBuf, &buf_size);

		args.get_buf_addr.out_buf_size	= buf_size;
		args.get_buf_addr.out_buf_addr	= args.get_buf_addr.in_usr_data + (OutBuf - s3c_mfc_get_databuf_virt_addr());
		args.get_buf_addr.ret_code	= ret;

		out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, 
			&args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_GET_YUV_BUF_ADDR:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.get_buf_addr, 
			(s3c_mfc_get_buf_addr_arg_t *)arg, 
			sizeof(s3c_mfc_get_buf_addr_arg_t));

		if (pMfcInst->yuv_buffer == NULL) {
			mfc_err("mfc frame buffer is not internally allocated yet\n");
			mutex_unlock(s3c_mfc_mutex);
			return -EFAULT;
		}

		/* FRAM_BUF address is calculated differently for Encoder and Decoder. */
		switch (pMfcInst->codec_mode) {
		case MP4_DEC:
		case AVC_DEC:
		case VC1_DEC:
		case H263_DEC:
			/* Decoder case */
			yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
			args.get_buf_addr.out_buf_size = yuv_size;

			in_usr_data = (unsigned int)args.get_buf_addr.in_usr_data;
			yuv_buffer = (unsigned int)pMfcInst->yuv_buffer;
			run_index = pMfcInst->run_index;
			out_buf_size = args.get_buf_addr.out_buf_size;
			databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr();
			offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr;
			
#if (S3C_MFC_ROTATE_ENABLE == 1)
			if ((pMfcInst->codec_mode != VC1_DEC) && 
				(pMfcInst->post_rotation_mode & 0x0010)) {
				yuv_buff_cnt = pMfcInst->yuv_buffer_count;
				offset = yuv_buffer + yuv_buff_cnt * out_buf_size - databuf_vaddr;
			}
#endif
			args.get_buf_addr.out_buf_addr = in_usr_data + offset;
			break;

		case MP4_ENC:
		case AVC_ENC:
		case H263_ENC:
			/* Encoder case */
			yuv_size = (pMfcInst->width * pMfcInst->height * 3) >> 1;
			in_usr_data = args.get_buf_addr.in_usr_data;
			run_index = pMfcInst->run_index;
			yuv_buffer = (unsigned int)pMfcInst->yuv_buffer;
			databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr();
			offset = run_index * yuv_size + (yuv_buffer - databuf_vaddr);
			
			args.get_buf_addr.out_buf_addr = in_usr_data + offset;			
			break;
		} /* end of switch (codec_mode) */

		args.get_buf_addr.ret_code = S3C_MFC_INST_RET_OK;
		out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, &args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_GET_PHY_FRAM_BUF_ADDR:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args.get_buf_addr, 
			(s3c_mfc_get_buf_addr_arg_t *)arg, 
			sizeof(s3c_mfc_get_buf_addr_arg_t));

		yuv_size = (pMfcInst->buf_width * pMfcInst->buf_height * 3) >> 1;
		args.get_buf_addr.out_buf_size = yuv_size;
		yuv_buffer = (unsigned int)pMfcInst->yuv_buffer;
		run_index = pMfcInst->run_index;
		out_buf_size = args.get_buf_addr.out_buf_size;
		databuf_vaddr = (unsigned int)s3c_mfc_get_databuf_virt_addr();
		databuf_paddr = (unsigned int)S3C_MFC_BASEADDR_DATA_BUF;
		offset = yuv_buffer + run_index * out_buf_size - databuf_vaddr;		
		
#if (S3C_MFC_ROTATE_ENABLE == 1)
		if ((pMfcInst->codec_mode != VC1_DEC) && (pMfcInst->post_rotation_mode & 0x0010)) {
			yuv_buff_cnt = pMfcInst->yuv_buffer_count;
			offset = yuv_buffer + yuv_buff_cnt * out_buf_size - databuf_vaddr;
		}
#endif
		args.get_buf_addr.out_buf_addr = databuf_paddr + offset;
		args.get_buf_addr.ret_code = S3C_MFC_INST_RET_OK;

		out = copy_to_user((s3c_mfc_get_buf_addr_arg_t *)arg, 
			&args.get_buf_addr, sizeof(s3c_mfc_get_buf_addr_arg_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_GET_MPEG4_ASP_PARAM:
#if (defined(DIVX_ENABLE) && (DIVX_ENABLE == 1))

		out = copy_from_user(&args.mpeg4_asp_param, (s3c_mfc_get_mpeg4asp_arg_t *)arg, \
							sizeof(s3c_mfc_get_mpeg4asp_arg_t));

		ret = S3C_MFC_INST_RET_OK;
		args.mpeg4_asp_param.ret_code = S3C_MFC_INST_RET_OK;
		args.mpeg4_asp_param.mp4asp_vop_time_res = pMfcInst->RET_DEC_SEQ_INIT_BAK_MP4ASP_VOP_TIME_RES;
		args.mpeg4_asp_param.byte_consumed = pMfcInst->RET_DEC_PIC_RUN_BAK_BYTE_CONSUMED;
		args.mpeg4_asp_param.mp4asp_fcode = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_FCODE;
		args.mpeg4_asp_param.mp4asp_time_base_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_TIME_BASE_LAST;
		args.mpeg4_asp_param.mp4asp_nonb_time_last = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_NONB_TIME_LAST;
		args.mpeg4_asp_param.mp4asp_trd = pMfcInst->RET_DEC_PIC_RUN_BAK_MP4ASP_MP4ASP_TRD;

		args.mpeg4_asp_param.mv_addr = (args.mpeg4_asp_param.in_usr_mapped_addr + S3C_MFC_STREAM_BUF_SIZE) 	\
							+ (pMfcInst->mv_mbyte_addr - pMfcInst->phys_addr_yuv_buffer);
		args.mpeg4_asp_param.mb_type_addr = args.mpeg4_asp_param.mv_addr + S3C_MFC_MAX_MV_SIZE;	
		args.mpeg4_asp_param.mv_size = S3C_MFC_MAX_MV_SIZE;
		args.mpeg4_asp_param.mb_type_size = S3C_MFC_MAX_MBYTE_SIZE;

		vir_mv_addr = (unsigned int)((pMfcInst->stream_buffer + S3C_MFC_STREAM_BUF_SIZE) + \
					(pMfcInst->mv_mbyte_addr - pMfcInst->phys_addr_yuv_buffer));
		vir_mb_type_addr = vir_mv_addr + S3C_MFC_MAX_MV_SIZE;

		out = copy_to_user((s3c_mfc_get_mpeg4asp_arg_t *)arg, &args.mpeg4_asp_param, \
							sizeof(s3c_mfc_get_mpeg4asp_arg_t));
#endif	
		break;

	case S3C_MFC_IOCTL_MFC_GET_CONFIG:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args, (s3c_mfc_args_t *)arg, sizeof(s3c_mfc_args_t));

		ret = s3c_mfc_get_config_params(pMfcInst, &args);

		out = copy_to_user((s3c_mfc_args_t *)arg, &args, sizeof(s3c_mfc_args_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_MFC_SET_CONFIG:
		mutex_lock(s3c_mfc_mutex);

		out = copy_from_user(&args, (s3c_mfc_args_t *)arg, sizeof(s3c_mfc_args_t));

		ret = s3c_mfc_set_config_params(pMfcInst, &args);

		out = copy_to_user((s3c_mfc_args_t *)arg, &args, sizeof(s3c_mfc_args_t));

		mutex_unlock(s3c_mfc_mutex);
		break;

	case S3C_MFC_IOCTL_VIRT_TO_PHYS:
		temp = __virt_to_phys((void *)arg);
		return (int)temp;
		break;

	default:
		mutex_lock(s3c_mfc_mutex);
		mfc_debug("requested ioctl command is not defined (ioctl cmd = 0x%x)\n", cmd);
		mutex_unlock(s3c_mfc_mutex);
		return -ENOIOCTLCMD;
	}

	switch (ret) {
	case S3C_MFC_INST_RET_OK:
		return 0;
	default:
		return -EPERM;
	}
	return -EPERM;
}