Example #1
0
/* Allocate temporary buffers for decoding */
int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
{
    void *desc_virt;
    struct s5p_mfc_dev *dev = ctx->dev;

    ctx->desc_buf = vb2_dma_contig_memops.alloc(
                        dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
    if (IS_ERR_VALUE((int)ctx->desc_buf)) {
        ctx->desc_buf = NULL;
        mfc_err("Allocating DESC buffer failed\n");
        return -ENOMEM;
    }
    ctx->desc_phys = s5p_mfc_mem_cookie(
                         dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
    BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
    desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
    if (desc_virt == NULL) {
        vb2_dma_contig_memops.put(ctx->desc_buf);
        ctx->desc_phys = 0;
        ctx->desc_buf = NULL;
        mfc_err("Remapping DESC buffer failed\n");
        return -ENOMEM;
    }
    memset(desc_virt, 0, DESC_BUF_SIZE);
    wmb();
    return 0;
}
int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
{
	struct s5p_mfc_dev *dev = ctx->dev;
	void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];

	ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
							SHARED_BUF_SIZE);
	if (IS_ERR(ctx->shm_alloc)) {
		mfc_err("failed to allocate shared memory\n");
		return PTR_ERR(ctx->shm_alloc);
	}
	/*                                                  */
	ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
								- dev->bank1;
	BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
	ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
	if (!ctx->shm) {
		vb2_dma_contig_memops.put(ctx->shm_alloc);
		ctx->shm_ofs = 0;
		ctx->shm_alloc = NULL;
		mfc_err("failed to virt addr of shared memory\n");
		return -ENOMEM;
	}
	memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
	wmb();
	return 0;
}
/* Allocate firmware */
int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
{
#if defined(CONFIG_S5P_MFC_VB2_CMA)
	int err;
	struct cma_info mem_info_f, mem_info_a, mem_info_b;
#endif
	unsigned int base_align = dev->variant->buf_align->mfc_base_align;
	unsigned int firmware_size = dev->variant->buf_size->firmware_code;

	mfc_debug_enter();

#if !defined(CONFIG_S5P_MFC_VB2_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_S5P_MFC_VB2_CMA)
	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;
	}
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc(
		dev->alloc_ctx[MFC_CMA_FW_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_cookie(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}
	dev->port_a = s5p_mfc_bitproc_phys;

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	if (HAS_PORTNUM(dev) && 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_S5P_MFC_VB2_SDVMM)
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc(
		dev->alloc_ctx[MFC_CMA_FW_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_cookie(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	dev->port_a = s5p_mfc_bitproc_phys;
	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);
#elif defined(CONFIG_S5P_MFC_VB2_ION)
	mfc_debug(2, "Allocating memory for firmware.\n");
	s5p_mfc_bitproc_buf = s5p_mfc_mem_alloc(
		dev->alloc_ctx[MFC_CMA_FW_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_cookie(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	s5p_mfc_bitproc_virt = s5p_mfc_mem_vaddr(
		dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX], 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_put(dev->alloc_ctx[MFC_CMA_FW_ALLOC_CTX],
							s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		return -EIO;
	}

	dev->port_a = s5p_mfc_bitproc_phys;
	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;
}
int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
{
	struct firmware *fw_blob;
	size_t bank2_base_phys;
	void *b_base;
	int err;

	mfc_debug_enter();
	err = request_firmware((const struct firmware **)&fw_blob,
				     "s5p-mfc.fw", dev->v4l2_dev.dev);
	if (err != 0) {
		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
		return -EINVAL;
	}
	dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
	if (s5p_mfc_bitproc_buf) {
		mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
		release_firmware(fw_blob);
		return -ENOMEM;
	}
	s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
	if (IS_ERR(s5p_mfc_bitproc_buf)) {
		s5p_mfc_bitproc_buf = 0;
		mfc_err("Allocating bitprocessor buffer failed\n");
		release_firmware(fw_blob);
		return -ENOMEM;
	}
	s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
	if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
		mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		release_firmware(fw_blob);
		return -EIO;
	}
	s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
	if (!s5p_mfc_bitproc_virt) {
		mfc_err("Bitprocessor memory remap failed\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		release_firmware(fw_blob);
		return -EIO;
	}
	dev->bank1 = s5p_mfc_bitproc_phys;
	b_base = vb2_dma_contig_memops.alloc(
		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
	if (IS_ERR(b_base)) {
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		mfc_err("Allocating bank2 base failed\n");
	release_firmware(fw_blob);
		return -ENOMEM;
	}
	bank2_base_phys = s5p_mfc_mem_cookie(
		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
	vb2_dma_contig_memops.put(b_base);
	if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
		mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
		s5p_mfc_bitproc_phys = 0;
		s5p_mfc_bitproc_buf = 0;
		release_firmware(fw_blob);
		return -EIO;
	}
	dev->bank2 = bank2_base_phys;
	memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
	wmb();
	release_firmware(fw_blob);
	mfc_debug_leave();
	return 0;
}