/* Allocate memory for firmware */ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { void *bank2_virt; dma_addr_t bank2_dma_addr; dev->fw_size = dev->variant->buf_size->fw; if (dev->fw_virt_addr) { mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n"); return -ENOMEM; } dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size, &dev->bank1, GFP_KERNEL); if (!dev->fw_virt_addr) { mfc_err("Allocating bitprocessor buffer failed\n"); return -ENOMEM; } if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) { bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, &bank2_dma_addr, GFP_KERNEL); if (!bank2_virt) { mfc_err("Allocating bank2 base failed\n"); dma_free_coherent(dev->mem_dev_l, dev->fw_size, dev->fw_virt_addr, dev->bank1); dev->fw_virt_addr = NULL; return -ENOMEM; } /* Valid buffers passed to MFC encoder with LAST_FRAME command * should not have address of bank2 - MFC will treat it as a null frame. * To avoid such situation we set bank2 address below the pool address. */ dev->bank2 = bank2_dma_addr - (1 << MFC_BASE_ALIGN_ORDER); dma_free_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER, bank2_virt, bank2_dma_addr); } else { /* In this case bank2 can point to the same address as bank1. * Firmware will always occupy the beginning of this area so it is * impossible having a video frame buffer with zero address. */ dev->bank2 = dev->bank1; } return 0; }
/* Allocate firmware */ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev) { #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) int err; struct cma_info mem_info_f, mem_info_a, mem_info_b; #endif unsigned int base_align; unsigned int firmware_size; void *alloc_ctx; mfc_debug_enter(); if (!dev) { mfc_err("no mfc device to run\n"); return -EINVAL; } base_align = dev->variant->buf_align->mfc_base_align; firmware_size = dev->variant->buf_size->firmware_code; alloc_ctx = dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX]; #if !defined(CONFIG_VIDEOBUF2_ION) if (s5p_mfc_bitproc_buf) { mfc_err("Attempting to allocate firmware when it seems that it is already loaded.\n"); return -ENOMEM; } #else if (s5p_mfc_bitproc_buf) return 0; #endif /* Get memory region information and check if it is correct */ #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) err = cma_info(&mem_info_f, dev->v4l2_dev.dev, MFC_CMA_FW); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "f", mem_info_f.lower_bound, mem_info_f.upper_bound, mem_info_f.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } err = cma_info(&mem_info_a, dev->v4l2_dev.dev, MFC_CMA_BANK1); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "a", mem_info_a.lower_bound, mem_info_a.upper_bound, mem_info_a.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } if (mem_info_f.upper_bound > mem_info_a.lower_bound) { mfc_err("Firmware has to be " "allocated before memory for buffers (bank A).\n"); return -EINVAL; } #endif mfc_debug(2, "Allocating memory for firmware.\n"); #ifdef CONFIG_EXYNOS_CONTENT_PATH_PROTECTION if (dev->num_drm_inst) alloc_ctx = dev->alloc_ctx_fw; #endif s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc_priv(alloc_ctx, firmware_size); if (IS_ERR(s5p_mfc_bitproc_buf)) { s5p_mfc_bitproc_buf = 0; printk(KERN_ERR "Allocating bitprocessor buffer failed\n"); return -ENOMEM; } s5p_mfc_bitproc_phys = s5p_mfc_mem_daddr_priv(s5p_mfc_bitproc_buf); if (s5p_mfc_bitproc_phys & ((1 << base_align) - 1)) { mfc_err("The base memory is not aligned to %dBytes.\n", (1 << base_align)); s5p_mfc_mem_free_priv(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; s5p_mfc_bitproc_buf = 0; return -EIO; } if (!dev->num_drm_inst) { s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr_priv(s5p_mfc_bitproc_buf); mfc_debug(2, "Virtual address for FW: %08lx\n", (long unsigned int)s5p_mfc_bitproc_virt); if (!s5p_mfc_bitproc_virt) { mfc_err("Bitprocessor memory remap failed\n"); s5p_mfc_mem_free_priv(s5p_mfc_bitproc_buf); s5p_mfc_bitproc_phys = 0; s5p_mfc_bitproc_buf = 0; return -EIO; } } dev->port_a = s5p_mfc_bitproc_phys; #if defined(CONFIG_VIDEOBUF2_CMA_PHYS) if (IS_TWOPORT(dev)) { err = cma_info(&mem_info_b, dev->v4l2_dev.dev, MFC_CMA_BANK2); mfc_debug(3, "Area \"%s\" is from %08x to %08x and has size %08x", "b", mem_info_b.lower_bound, mem_info_b.upper_bound, mem_info_b.total_size); if (err) { mfc_err("Couldn't get memory information from CMA.\n"); return -EINVAL; } dev->port_b = mem_info_b.lower_bound; mfc_debug(2, "Port A: %08x Port B: %08x (FW: %08x size: %08x)\n", dev->port_a, dev->port_b, s5p_mfc_bitproc_phys, firmware_size); } else { mfc_debug(2, "Port : %08x (FW: %08x size: %08x)\n", dev->port_a, s5p_mfc_bitproc_phys, firmware_size); } #elif defined(CONFIG_VIDEOBUF2_ION) || defined(CONFIG_VIDEOBUF2_DMA_CMA) dev->port_b = s5p_mfc_bitproc_phys; mfc_debug(2, "Port A: %08x Port B: %08x (FW: %08x size: %08x)\n", dev->port_a, dev->port_b, s5p_mfc_bitproc_phys, firmware_size); #endif mfc_debug_leave(); return 0; }