Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5ebed37 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc_3x: Add new video driver to support CMA buffers"

parents c6784834 5fba8031
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -430,7 +430,12 @@ static int alloc_dma_mem(size_t size, u32 align, u32 flags,
		}

		ion_flags |= ION_FLAG_SECURE | secure_flag;
		if (res->cma_status) {
			heap_mask = ION_HEAP(ION_VIDEO_HEAP_ID);
			ion_flags |= ION_FLAG_CP_CAMERA_ENCODE;
		} else {
			heap_mask = ION_HEAP(ION_SECURE_HEAP_ID);
		}

		if (res->slave_side_cp) {
			heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
+27 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -586,6 +586,32 @@ static int msm_vidc_probe_vidc_device(struct platform_device *pdev)
				"Failed to create link name sysfs for encoder");
		goto err_enc_attr_link_name;
	}
	/* setup the encoder device with cma */
	core->vdev[MSM_VIDC_ENCODER_CMA].vdev.release =
		msm_vidc_release_video_device;
	core->vdev[MSM_VIDC_ENCODER_CMA].vdev.fops = &msm_v4l2_vidc_fops;
	core->vdev[MSM_VIDC_ENCODER_CMA].vdev.ioctl_ops = &msm_v4l2_ioctl_ops;
	core->vdev[MSM_VIDC_ENCODER_CMA].vdev.vfl_dir = VFL_DIR_M2M;
	core->vdev[MSM_VIDC_ENCODER_CMA].type = MSM_VIDC_ENCODER_CMA;
	core->vdev[MSM_VIDC_ENCODER_CMA].vdev.v4l2_dev = &core->v4l2_dev;
	rc = video_register_device(&core->vdev[MSM_VIDC_ENCODER_CMA].vdev,
				VFL_TYPE_GRABBER, nr + 3);
	if (rc) {
		dprintk(VIDC_ERR,
				"Failed to register video cma encoder device");

		goto err_enc_register;
	}

	video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER_CMA].vdev, core);
	dev = &core->vdev[MSM_VIDC_ENCODER_CMA].vdev.dev;
	rc = device_create_file(dev, &dev_attr_link_name);
	if (rc) {
		dprintk(VIDC_ERR,
				"Failed to create link name sysfs for encoder cma");

		goto err_enc_attr_link_name;
	}

	/* finish setting up the 'core' */
	mutex_lock(&vidc_driver->lock);
+72 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include "vidc_hfi_api.h"
#include "msm_vidc_dcvs.h"
#include "msm_vidc_res_parse.h"

#define MAX_EVENTS 30

@@ -1242,6 +1243,9 @@ void *msm_vidc_open(int core_id, int session_type)
	struct msm_vidc_core *core = NULL;
	int rc = 0;
	int i = 0;
	bool reconfig_core = false;
	bool is_cma_enabled = false;
	struct hfi_device *hdev = NULL;

	if (core_id >= MSM_VIDC_CORES_MAX ||
			session_type >= MSM_VIDC_MAX_DEVICES) {
@@ -1256,6 +1260,13 @@ void *msm_vidc_open(int core_id, int session_type)
		goto err_invalid_core;
	}

	if ((session_type == MSM_VIDC_ENCODER_CMA) &&
			!core->resources.cma_exist) {
		dprintk(VIDC_ERR, "Failed cma not enabled\n");

		goto err_invalid_core;

	}
	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
	if (!inst) {
		dprintk(VIDC_ERR, "Failed to allocate memory\n");
@@ -1280,6 +1291,18 @@ void *msm_vidc_open(int core_id, int session_type)

	kref_init(&inst->kref);

	is_cma_enabled = core->resources.cma_status;
	reconfig_core =
		((!is_cma_enabled && session_type == MSM_VIDC_ENCODER_CMA) ||
		(is_cma_enabled && session_type != MSM_VIDC_ENCODER_CMA)) ?
		true : false;

	dprintk(VIDC_DBG, "reconfig_core %d , cma_status %d , session_type %d ",
		reconfig_core, core->resources.cma_status, session_type);

	if (session_type == MSM_VIDC_ENCODER_CMA)
		session_type = MSM_VIDC_ENCODER;

	inst->session_type = session_type;
	inst->state = MSM_VIDC_CORE_UNINIT_DONE;
	inst->core = core;
@@ -1322,6 +1345,50 @@ void *msm_vidc_open(int core_id, int session_type)

	setup_event_queue(inst, &core->vdev[session_type].vdev);

	if (reconfig_core) {
		mutex_lock(&core->lock);
		if (!list_empty(&core->instances)) {
			dprintk(VIDC_ERR,
				"failed due to pending instances in core");

			mutex_unlock(&core->lock);
			goto fail_toggle_cma;
		}
		mutex_unlock(&core->lock);

		rc = msm_comm_try_state(inst, MSM_VIDC_CORE_UNINIT);
		if (rc) {
			dprintk(VIDC_ERR,
				"MSM_VIDC_CORE_UNINIT failed\n");
		}
		cancel_delayed_work(&core->fw_unload_work);

		mutex_lock(&core->lock);
		hdev = core->device;
		rc = call_hfi_op(hdev, core_release,
					hdev->hfi_device_data);
		if (rc) {
			dprintk(VIDC_ERR,
				"Failed to release core, id = %d\n",
				core->id);
			mutex_unlock(&core->lock);
			goto fail_toggle_cma;
		}
		core->state = VIDC_CORE_UNINIT;
		kfree(core->capabilities);
		core->capabilities = NULL;
		msm_vidc_enable_cma(&core->resources, !is_cma_enabled);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s CMA failed\n", is_cma_enabled ?
				"enable":"disable");
			mutex_unlock(&core->lock);
			goto fail_toggle_cma;
		}
		core->resources.cma_status = !is_cma_enabled;
		mutex_unlock(&core->lock);
	}

	mutex_lock(&core->lock);
	list_add_tail(&inst->list, &core->instances);
	mutex_unlock(&core->lock);
@@ -1343,11 +1410,15 @@ void *msm_vidc_open(int core_id, int session_type)
		msm_vidc_debugfs_init_inst(inst, core->debugfs_root);

	return inst;

fail_init:
	mutex_lock(&core->lock);
	list_del(&inst->list);
	mutex_unlock(&core->lock);
fail_toggle_cma:
	mutex_lock(&core->lock);
	v4l2_fh_del(&inst->event_handler);
	v4l2_fh_exit(&inst->event_handler);
	list_del(&inst->list);
	mutex_unlock(&core->lock);
	vb2_queue_release(&inst->bufq[OUTPUT_PORT].vb2_bufq);

+153 −14
Original line number Diff line number Diff line
@@ -20,9 +20,14 @@
#include "msm_vidc_resources.h"
#include "msm_vidc_res_parse.h"
#include "venus_boot.h"
#include <soc/qcom/scm.h>
#include "soc/qcom/secure_buffer.h"
#include <asm/cacheflush.h>
#include <linux/io.h>

#define VENUS_DEVICE_ID 0x0
#define SECURE_SYSCALL_ID 0x18

enum clock_properties {
	CLOCK_PROP_HAS_SCALING = 1 << 0,
};
@@ -1265,12 +1270,63 @@ static int get_secure_vmid(struct context_bank_info *cb)
	return VMID_INVAL;
}

static int msm_vidc_switch_vmid(int vmid, struct context_bank_info *cb)
{
	struct scm_desc desc = {0};
	uint32_t *sid_info = NULL;
	int rc = 0;

	if (!cb) {
		dprintk(VIDC_ERR, "%s: invalid context bank device\n",
			__func__);
		return -EIO;
	}

	sid_info = kzalloc(sizeof(uint32_t) * cb->num_sids, GFP_KERNEL);
	if (!sid_info) {
		dprintk(VIDC_ERR, "%s: memory allocation failred\n",
			__func__);
		return -ENOMEM;
	}

	memcpy(sid_info, &cb->sids, sizeof(uint32_t) * cb->num_sids);
	desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
	desc.args[0] = VENUS_DEVICE_ID;
	desc.args[1] = SCM_BUFFER_PHYS(sid_info);
	desc.args[2] = sizeof(uint32_t) * cb->num_sids;
	desc.args[3] = vmid;

	dmac_flush_range(sid_info, sid_info + 1);
	if (scm_call2(SCM_SIP_FNID(SCM_SVC_MP, SECURE_SYSCALL_ID), &desc)) {
		dprintk(VIDC_ERR, "call to hypervisor failed\n");
		rc = -EINVAL;
	}
	dprintk(VIDC_DBG, "%s switched to 0x%x vmid\n", cb->name, vmid);
	kfree(sid_info);

	return rc;
}

static void msm_vidc_detach_context_banks(
		struct msm_vidc_platform_resources *res)
{
	struct context_bank_info *cb = NULL;

	list_for_each_entry(cb, &res->context_banks, list) {
		arm_iommu_detach_device(cb->dev);
		if (cb->mapping)
			arm_iommu_release_mapping(cb->mapping);
	}
}

static int msm_vidc_setup_context_bank(struct context_bank_info *cb,
		struct device *dev)
		struct device *dev, int cma_enable)
{
	int rc = 0;
	int secure_vmid = VMID_INVAL;
	struct bus_type *bus;
	u32 start_addr = 0, pool_size = 0;
	int s1_bypass = 1;

	if (!dev || !cb) {
		dprintk(VIDC_ERR,
@@ -1286,8 +1342,15 @@ static int msm_vidc_setup_context_bank(struct context_bank_info *cb,
		goto remove_cb;
	}

	cb->mapping = arm_iommu_create_mapping(bus, cb->addr_range.start,
					cb->addr_range.size);
	if (cma_enable) {
		start_addr = cb->cma.addr_range.start;
		pool_size = cb->cma.addr_range.size;
	} else {
		start_addr = cb->addr_range.start;
		pool_size = cb->addr_range.size;
	}

	cb->mapping = arm_iommu_create_mapping(bus, start_addr, pool_size);
	if (IS_ERR_OR_NULL(cb->mapping)) {
		dprintk(VIDC_ERR, "%s - failed to create mapping\n", __func__);
		rc = PTR_ERR(cb->mapping) ?: -ENODEV;
@@ -1296,16 +1359,30 @@ static int msm_vidc_setup_context_bank(struct context_bank_info *cb,

	if (cb->is_secure) {
		secure_vmid = get_secure_vmid(cb);
		if (cma_enable && cb->cma.s1_bypass)
			secure_vmid = VMID_CP_CAMERA_ENCODE;
		rc = iommu_domain_set_attr(cb->mapping->domain,
				DOMAIN_ATTR_SECURE_VMID, &secure_vmid);
		if (rc) {
			dprintk(VIDC_ERR,
					"%s - programming secure vmid failed: %s %d\n",
				"%s - programming secure vmid failed: %s 0x%x\n",
				__func__, dev_name(dev), rc);
			goto release_mapping;
		}
	}

	if (cma_enable && cb->cma.s1_bypass) {
		s1_bypass = cb->cma.s1_bypass;
		rc = iommu_domain_set_attr(cb->mapping->domain,
			DOMAIN_ATTR_S1_BYPASS, &s1_bypass);
		if (rc) {
			dprintk(VIDC_ERR,
				"%s S1 bypass failed rc %d ", __func__, rc);

			goto release_mapping;
		}
	}

	rc = arm_iommu_attach_device(cb->dev, cb->mapping);
	if (rc) {
		dprintk(VIDC_ERR, "%s - Couldn't arm_iommu_attach_device\n",
@@ -1324,11 +1401,12 @@ static int msm_vidc_setup_context_bank(struct context_bank_info *cb,
	dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
	dma_set_seg_boundary(dev, (unsigned long)DMA_BIT_MASK(64));

	dprintk(VIDC_DBG, "Attached %s and created mapping\n", dev_name(dev));
	dprintk(VIDC_DBG, "Attached %s and created mapping cma status %d\n",
			dev_name(dev), cma_enable);
	dprintk(VIDC_DBG,
		"Context bank name:%s, buffer_type: %#x, is_secure: %d, address range start: %#x, size: %#x, dev: %pK, mapping: %pK",
		cb->name, cb->buffer_type, cb->is_secure, cb->addr_range.start,
		cb->addr_range.size, cb->dev, cb->mapping);
		cb->name, cb->buffer_type, cb->is_secure, start_addr,
		pool_size, cb->dev, cb->mapping);

	return rc;

@@ -1426,6 +1504,7 @@ static int msm_vidc_populate_context_bank(struct device *dev,
	int rc = 0;
	struct context_bank_info *cb = NULL;
	struct device_node *np = NULL;
	unsigned int i = 0, j = 0, count = 0;

	if (!dev || !core) {
		dprintk(VIDC_ERR, "%s - invalid inputs\n", __func__);
@@ -1448,8 +1527,21 @@ static int msm_vidc_populate_context_bank(struct device *dev,
			"Failed to read cb label from device tree\n");
		rc = 0;
	}

	dprintk(VIDC_DBG, "%s: context bank has name %s\n", __func__, cb->name);
	of_get_property(np, "iommus", &count);
	memset(&cb->sids, -1, sizeof(cb->sids));
	count /= 4;
	for (i = 1, j = 0 ; i < count; i = i+2, j++) {
		rc = of_property_read_u32_index(dev->of_node,
			"iommus", i, &cb->sids[j]);
		if (rc < 0)
			dprintk(VIDC_ERR, "can't fetch SID\n");

		dprintk(VIDC_DBG,
			"%s sid[%d]:0x%x\n",  cb->name, j, cb->sids[j]);
	}
	cb->num_sids = j;

	rc = of_property_read_u32_array(np, "virtual-addr-pool",
			(u32 *)&cb->addr_range, 2);
	if (rc) {
@@ -1459,6 +1551,13 @@ static int msm_vidc_populate_context_bank(struct device *dev,
		goto err_setup_cb;
	}

	rc = of_property_read_u32_array(np, "cma-addr-pool",
			(u32 *)&cb->cma.addr_range, 2);

	cb->cma.s1_bypass = of_property_read_bool(np, "qcom,cma-s1-bypass");
	if (cb->cma.s1_bypass && !rc)
		core->resources.cma_exist = true;

	cb->is_secure = of_property_read_bool(np, "qcom,secure-context-bank");
	dprintk(VIDC_DBG, "context bank %s : secure = %d\n",
			cb->name, cb->is_secure);
@@ -1471,11 +1570,12 @@ static int msm_vidc_populate_context_bank(struct device *dev,
		goto err_setup_cb;
	}
	dprintk(VIDC_DBG,
		"context bank %s address start = %x address size = %x buffer_type = %x\n",
		cb->name, cb->addr_range.start,
		cb->addr_range.size, cb->buffer_type);
		"context bank %s address start = %x size = %x cma address start = %x size = %x s1 bypass = %d buffer_type = %x\n",
		cb->name, cb->addr_range.start, cb->addr_range.size,
		cb->cma.addr_range.start, cb->cma.addr_range.size,
		cb->cma.s1_bypass, cb->buffer_type);

	rc = msm_vidc_setup_context_bank(cb, dev);
	rc = msm_vidc_setup_context_bank(cb, dev, false);
	if (rc) {
		dprintk(VIDC_ERR, "Cannot setup context bank %d\n", rc);
		goto err_setup_cb;
@@ -1572,7 +1672,7 @@ static int msm_vidc_populate_legacy_context_bank(
			goto err_setup_cb;
		}

		rc = msm_vidc_setup_context_bank(cb, cb->dev);
		rc = msm_vidc_setup_context_bank(cb, cb->dev, false);
		if (rc) {
			dprintk(VIDC_ERR, "Cannot setup context bank %d\n", rc);
			goto err_setup_cb;
@@ -1659,3 +1759,42 @@ int read_bus_resources_from_dt(struct platform_device *pdev)

	return msm_vidc_populate_bus(&pdev->dev, &core->resources);
}

int msm_vidc_enable_cma(struct msm_vidc_platform_resources *res, bool enable)
{
	int rc;
	int secure_vmid = VMID_INVAL;
	struct context_bank_info *cb = NULL;

	dprintk(VIDC_DBG, "%s: In enable status %d\n", __func__, enable);

	msm_vidc_detach_context_banks(res);
	list_for_each_entry(cb, &res->context_banks, list) {
		if (cb->is_secure && cb->cma.s1_bypass) {
			if (enable) {
				rc = msm_vidc_switch_vmid(VMID_CP_CAMERA_ENCODE,
						cb);
				if (rc) {
					dprintk(VIDC_ERR,
						"failed SID switching\n");
					goto detach_cb;
				}
			} else {
				secure_vmid = get_secure_vmid(cb);
				rc = msm_vidc_switch_vmid(secure_vmid, cb);
				if (rc)
					goto detach_cb;
			}
		}
		rc = msm_vidc_setup_context_bank(cb, cb->dev, enable);
		if (rc)
			goto detach_cb;
	}

	return rc;

detach_cb:
	dprintk(VIDC_DBG, "%s: - failed %d\n", __func__, enable);
	msm_vidc_detach_context_banks(res);
	return rc;
}
+1 −0
Original line number Diff line number Diff line
@@ -31,4 +31,5 @@ int msm_vidc_load_u32_table(struct platform_device *pdev,
		struct device_node *of_node, char *table_name, int struct_size,
		u32 **table, u32 *num_elements);

int msm_vidc_enable_cma(struct msm_vidc_platform_resources *res, bool enable);
#endif
Loading