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; }
/*! 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; }
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; }
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); } } }
/*! 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; }
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))); }
/*! 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 {
/* 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; }
/* * 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); }
/* * 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); }
/* * 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; }
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; }