summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-12-21 07:29:56 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2016-12-21 07:29:56 -0800
commit89936c94ec0d72164b921217952d1bbd79eed9b2 (patch)
treefbc38908317fbd46f81514bee4d78266a2e149b1
parent1c2dbebda1b63d750d6c4c65fa86142051620f7b (diff)
parentcbd1c43d5a8ae87d5f4671f02c4b0a9a27cbd895 (diff)
Merge "msm: sde: secure camera changes for v4l2 rotator"
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_base.c9
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_base.h5
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.c107
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_core.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c57
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h3
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c20
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h1
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c75
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h2
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_util.c143
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_util.h6
-rw-r--r--include/uapi/media/msm_sde_rotator.h6
13 files changed, 376 insertions, 61 deletions
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
index bc153ff8ac2c..5e763f74170e 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -560,6 +560,15 @@ int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
goto probe_done;
}
+ mdata->iclient = msm_ion_client_create(mdata->pdev->name);
+ if (IS_ERR_OR_NULL(mdata->iclient)) {
+ SDEROT_ERR("msm_ion_client_create() return error (%pK)\n",
+ mdata->iclient);
+ mdata->iclient = NULL;
+ rc = -EFAULT;
+ goto probe_done;
+ }
+
*pmdata = mdata;
return 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index 67c6b11329d8..80da9b4cfcb6 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -83,6 +83,7 @@ enum sde_caps_settings {
SDE_CAPS_R1_WB,
SDE_CAPS_R3_WB,
SDE_CAPS_R3_1P5_DOWNSCALE,
+ SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
SDE_CAPS_MAX,
};
@@ -111,6 +112,7 @@ struct sde_smmu_client {
struct sde_module_power mp;
struct reg_bus_client *reg_bus_clt;
bool domain_attached;
+ int domain;
};
struct sde_rot_vbif_debug_bus {
@@ -169,6 +171,9 @@ struct sde_rot_data_type {
u32 regdump_size;
void *sde_rot_hw;
+ int sec_cam_en;
+
+ struct ion_client *iclient;
};
int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index bc827f1eda76..57b4560acdb2 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -25,6 +25,10 @@
#include <linux/msm-bus-board.h>
#include <linux/regulator/consumer.h>
#include <linux/dma-direction.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/rpm-smd.h>
+#include <soc/qcom/secure_buffer.h>
+#include <asm/cacheflush.h>
#include "sde_rotator_base.h"
#include "sde_rotator_core.h"
@@ -37,6 +41,18 @@
#include "sde_rotator_trace.h"
#include "sde_rotator_debug.h"
+
+/* Rotator device id to be used in SCM call */
+#define SDE_ROTATOR_DEVICE 21
+
+/* SCM call function id to be used for switching between secure and non
+ * secure context
+ */
+#define MEM_PROTECT_SD_CTRL_SWITCH 0x18
+
+/* Rotator secure SID */
+#define SDE_ROTATOR_SECURE_SID 0xe01
+
/* waiting for hw time out, 3 vsync for 30fps*/
#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100
@@ -505,6 +521,7 @@ static int sde_rotator_import_buffer(struct sde_layer_buffer *buffer,
planes[i].memory_id = buffer->planes[i].fd;
planes[i].offset = buffer->planes[i].offset;
planes[i].buffer = buffer->planes[i].buffer;
+ planes[i].handle = buffer->planes[i].handle;
}
ret = sde_mdp_data_get_and_validate_size(data, planes,
@@ -513,6 +530,86 @@ static int sde_rotator_import_buffer(struct sde_layer_buffer *buffer,
return ret;
}
+static int sde_rotator_secure_session_ctrl(struct sde_rot_entry *entry)
+{
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+ uint32_t sid_info;
+ struct scm_desc desc;
+ unsigned int resp = 0;
+ int ret = 0;
+
+ if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
+ mdata->sde_caps_map)) {
+ sid_info = SDE_ROTATOR_SECURE_SID;
+ desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
+ desc.args[0] = SDE_ROTATOR_DEVICE;
+ desc.args[1] = SCM_BUFFER_PHYS(&sid_info);
+ desc.args[2] = sizeof(uint32_t);
+
+ if (!mdata->sec_cam_en &&
+ (entry->item.flags & SDE_ROTATION_SECURE_CAMERA)) {
+ /*
+ * Enable secure camera operation
+ * Send SCM call to hypervisor to switch the
+ * secure_vmid to secure context
+ */
+ desc.args[3] = VMID_CP_CAMERA_PREVIEW;
+
+ mdata->sec_cam_en = 1;
+ sde_smmu_secure_ctrl(0);
+
+ dmac_flush_range(&sid_info, &sid_info + 1);
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ MEM_PROTECT_SD_CTRL_SWITCH), &desc);
+ resp = desc.ret[0];
+ if (ret) {
+ SDEROT_ERR("scm_call(1) ret=%d, resp=%x\n",
+ ret, resp);
+ /* failure, attach smmu */
+ mdata->sec_cam_en = 0;
+ sde_smmu_secure_ctrl(1);
+ return -EINVAL;
+ }
+
+ SDEROT_DBG("scm_call(1) ret=%d, resp=%x",
+ ret, resp);
+ SDEROT_EVTLOG(1, entry->item.flags,
+ entry->src_buf.p[0].addr,
+ entry->dst_buf.p[0].addr);
+ } else if (mdata->sec_cam_en && !(entry->item.flags &
+ SDE_ROTATION_SECURE_CAMERA)) {
+ /*
+ * Disable secure camera operation
+ * Send SCM call to hypervisor to switch the
+ * secure_vmid to non-secure context
+ */
+ desc.args[3] = VMID_CP_PIXEL;
+ mdata->sec_cam_en = 0;
+
+ dmac_flush_range(&sid_info, &sid_info + 1);
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ MEM_PROTECT_SD_CTRL_SWITCH), &desc);
+ resp = desc.ret[0];
+
+ SDEROT_DBG("scm_call(0): ret=%d, resp=%x",
+ ret, resp);
+
+ /* force smmu to reattach */
+ sde_smmu_secure_ctrl(1);
+ SDEROT_EVTLOG(0, entry->item.flags,
+ entry->src_buf.p[0].addr,
+ entry->dst_buf.p[0].addr);
+ }
+ } else {
+ return 0;
+ }
+ if (ret)
+ return ret;
+
+ return resp;
+}
+
+
static int sde_rotator_map_and_check_data(struct sde_rot_entry *entry)
{
int ret;
@@ -531,6 +628,13 @@ static int sde_rotator_map_and_check_data(struct sde_rot_entry *entry)
if (IS_ERR_VALUE(ret))
return ret;
+ ret = sde_rotator_secure_session_ctrl(entry);
+ if (ret) {
+ SDEROT_ERR("failed secure session enabling/disabling %d\n",
+ ret);
+ goto end;
+ }
+
/* if error during map, the caller will release the data */
ret = sde_mdp_data_map(&entry->src_buf, true, DMA_TO_DEVICE);
if (ret) {
@@ -642,6 +746,9 @@ static int sde_rotator_import_data(struct sde_rot_mgr *mgr,
if (entry->item.flags & SDE_ROTATION_EXT_DMA_BUF)
flag |= SDE_ROT_EXT_DMA_BUF;
+ if (entry->item.flags & SDE_ROTATION_SECURE_CAMERA)
+ flag |= SDE_SECURE_CAMERA_SESSION;
+
ret = sde_rotator_import_buffer(input, &entry->src_buf, flag,
&mgr->pdev->dev, true);
if (ret) {
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
index e1b326b8eb1c..eca0cbefcab1 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.h
@@ -59,6 +59,9 @@ Rotation request flag
/* use client provided dma buf instead of ion fd */
#define SDE_ROTATION_EXT_DMA_BUF 0x20000
+/* secure camera operation*/
+#define SDE_ROTATION_SECURE_CAMERA 0x40000
+
/**********************************************************************
configuration structures
**********************************************************************/
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 08075ae90507..a3815fac8169 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -90,6 +90,8 @@ static uint32_t sde_rotator_get_flags_from_ctx(struct sde_rotator_ctx *ctx)
ret_flags ^= SDE_ROTATION_FLIP_UD;
if (ctx->secure)
ret_flags |= SDE_ROTATION_SECURE;
+ if (ctx->secure_camera)
+ ret_flags |= SDE_ROTATION_SECURE_CAMERA;
if (ctx->format_out.fmt.pix.field == V4L2_FIELD_INTERLACED &&
ctx->format_cap.fmt.pix.field == V4L2_FIELD_NONE)
ret_flags |= SDE_ROTATION_DEINTERLACE;
@@ -510,28 +512,45 @@ static void *sde_rotator_get_userptr(void *alloc_ctx,
struct sde_rotator_ctx *ctx = alloc_ctx;
struct sde_rotator_device *rot_dev = ctx->rot_dev;
struct sde_rotator_buf_handle *buf;
+ struct ion_client *iclient = rot_dev->mdata->iclient;
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
return ERR_PTR(-ENOMEM);
buf->fd = vaddr;
- buf->secure = ctx->secure;
+ buf->secure = ctx->secure || ctx->secure_camera;
buf->ctx = ctx;
buf->rot_dev = rot_dev;
- buf->buffer = dma_buf_get(buf->fd);
-
- if (IS_ERR_OR_NULL(buf->buffer)) {
- SDEDEV_ERR(rot_dev->dev, "fail get dmabuf fd:%d r:%ld\n",
+ if (ctx->secure_camera) {
+ buf->handle = ion_import_dma_buf(iclient,
+ buf->fd);
+ if (IS_ERR_OR_NULL(buf->handle)) {
+ SDEDEV_ERR(rot_dev->dev,
+ "fail get ion_handler fd:%d r:%ld\n",
buf->fd, PTR_ERR(buf->buffer));
- goto error_dma_buf_get;
+ goto error_buf_get;
+ }
+ SDEDEV_DBG(rot_dev->dev,
+ "get ion_handle s:%d fd:%d buf:%pad\n",
+ buf->ctx->session_id,
+ buf->fd, &buf->handle);
+ } else {
+ buf->buffer = dma_buf_get(buf->fd);
+ if (IS_ERR_OR_NULL(buf->buffer)) {
+ SDEDEV_ERR(rot_dev->dev,
+ "fail get dmabuf fd:%d r:%ld\n",
+ buf->fd, PTR_ERR(buf->buffer));
+ goto error_buf_get;
+ }
+ SDEDEV_DBG(rot_dev->dev,
+ "get dmabuf s:%d fd:%d buf:%pad\n",
+ buf->ctx->session_id,
+ buf->fd, &buf->buffer);
}
- SDEDEV_DBG(rot_dev->dev, "get dmabuf s:%d fd:%d buf:%pad\n",
- buf->ctx->session_id,
- buf->fd, &buf->buffer);
return buf;
-error_dma_buf_get:
+error_buf_get:
kfree(buf);
return ERR_PTR(-ENOMEM);
}
@@ -618,6 +637,9 @@ static int sde_rotator_s_ctrl(struct v4l2_ctrl *ctrl)
ret = sde_rotator_s_ctx_ctrl(ctx, &ctx->secure, ctrl);
break;
+ case V4L2_CID_SDE_ROTATOR_SECURE_CAMERA:
+ ret = sde_rotator_s_ctx_ctrl(ctx, &ctx->secure_camera, ctrl);
+ break;
default:
v4l2_warn(&rot_dev->v4l2_dev, "invalid control %d\n", ctrl->id);
ret = -EINVAL;
@@ -648,6 +670,17 @@ static const struct v4l2_ctrl_config sde_rotator_ctrl_secure = {
.step = 1,
};
+static const struct v4l2_ctrl_config sde_rotator_ctrl_secure_camera = {
+ .ops = &sde_rotator_ctrl_ops,
+ .id = V4L2_CID_SDE_ROTATOR_SECURE_CAMERA,
+ .name = "Secure Camera content",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 0,
+ .min = 0,
+ .max = 1,
+ .step = 1,
+};
+
/*
* sde_rotator_ctx_show - show context state.
*/
@@ -924,6 +957,8 @@ static int sde_rotator_open(struct file *file)
&sde_rotator_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
v4l2_ctrl_new_custom(ctrl_handler,
&sde_rotator_ctrl_secure, NULL);
+ v4l2_ctrl_new_custom(ctrl_handler,
+ &sde_rotator_ctrl_secure_camera, NULL);
if (ctrl_handler->error) {
ret = ctrl_handler->error;
v4l2_ctrl_handler_free(ctrl_handler);
@@ -2010,11 +2045,13 @@ static int sde_rotator_process_buffers(struct sde_rotator_ctx *ctx,
sde_rotator_get_item_from_ctx(ctx, &item);
item.flags |= SDE_ROTATION_EXT_DMA_BUF;
item.input.planes[0].buffer = src_handle->buffer;
+ item.input.planes[0].handle = src_handle->handle;
item.input.planes[0].offset = src_handle->addr;
item.input.planes[0].stride = ctx->format_out.fmt.pix.bytesperline;
item.input.plane_count = 1;
item.input.fence = NULL;
item.output.planes[0].buffer = dst_handle->buffer;
+ item.output.planes[0].handle = dst_handle->handle;
item.output.planes[0].offset = dst_handle->addr;
item.output.planes[0].stride = ctx->format_cap.fmt.pix.bytesperline;
item.output.plane_count = 1;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
index f3c904817296..e6fe1e487755 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.h
@@ -48,6 +48,7 @@ struct sde_rotator_ctx;
* @addr: Address of rotator mmu mapped buffer.
* @secure: Non-secure/secure buffer.
* @buffer: Pointer to dma buf associated with this fd.
+ * @ihandle: ion handle associated with this fd
*/
struct sde_rotator_buf_handle {
int fd;
@@ -57,6 +58,7 @@ struct sde_rotator_buf_handle {
ion_phys_addr_t addr;
int secure;
struct dma_buf *buffer;
+ struct ion_handle *handle;
};
/*
@@ -119,6 +121,7 @@ struct sde_rotator_ctx {
s32 vflip;
s32 rotate;
s32 secure;
+ s32 secure_camera;
atomic_t command_pending;
int abort_pending;
int nbuf_cap;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index ff46a607db0c..79013344b615 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -641,7 +641,8 @@ static void sde_hw_rotator_setup_fetchengine(struct sde_hw_rotator_context *ctx,
((rot->highest_bank & 0x3) << 18));
/* setup source buffer plane security status */
- if (flags & SDE_ROT_FLAG_SECURE_OVERLAY_SESSION) {
+ if (flags & (SDE_ROT_FLAG_SECURE_OVERLAY_SESSION |
+ SDE_ROT_FLAG_SECURE_CAMERA_SESSION)) {
SDE_REGDMA_WRITE(wrptr, ROT_SSPP_SRC_ADDR_SW_STATUS, 0xF);
ctx->is_secure = true;
} else {
@@ -739,7 +740,8 @@ static void sde_hw_rotator_setup_wbengine(struct sde_hw_rotator_context *ctx,
SDE_REGDMA_WRITE(wrptr, ROT_WB_OUT_XY,
cfg->dst_rect->x | (cfg->dst_rect->y << 16));
- if (flags & SDE_ROT_FLAG_SECURE_OVERLAY_SESSION)
+ if (flags & (SDE_ROT_FLAG_SECURE_OVERLAY_SESSION |
+ SDE_ROT_FLAG_SECURE_CAMERA_SESSION))
SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_ADDR_SW_STATUS, 0x1);
else
SDE_REGDMA_WRITE(wrptr, ROT_WB_DST_ADDR_SW_STATUS, 0);
@@ -1131,14 +1133,10 @@ static int sde_hw_rotator_swts_create(struct sde_hw_rotator *rot)
int rc = 0;
struct ion_handle *handle;
struct sde_mdp_img_data *data;
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
u32 bufsize = sizeof(int) * SDE_HW_ROT_REGDMA_TOTAL_CTX * 2;
- rot->iclient = msm_ion_client_create(rot->pdev->name);
- if (IS_ERR_OR_NULL(rot->iclient)) {
- SDEROT_ERR("msm_ion_client_create() return error (%p)\n",
- rot->iclient);
- return -EINVAL;
- }
+ rot->iclient = mdata->iclient;
handle = ion_alloc(rot->iclient, bufsize, SZ_4K,
ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
@@ -1564,6 +1562,9 @@ static int sde_hw_rotator_config(struct sde_rot_hw_resource *hw,
SDE_ROT_FLAG_DEINTERLACE : 0;
flags |= (item->flags & SDE_ROTATION_SECURE) ?
SDE_ROT_FLAG_SECURE_OVERLAY_SESSION : 0;
+ flags |= (item->flags & SDE_ROTATION_SECURE_CAMERA) ?
+ SDE_ROT_FLAG_SECURE_CAMERA_SESSION : 0;
+
sspp_cfg.img_width = item->input.width;
sspp_cfg.img_height = item->input.height;
@@ -1808,13 +1809,14 @@ static int sde_rotator_hw_rev_init(struct sde_hw_rotator *rot)
set_bit(SDE_CAPS_R3_1P5_DOWNSCALE, mdata->sde_caps_map);
}
+ set_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU, mdata->sde_caps_map);
+
mdata->nrt_vbif_dbg_bus = nrt_vbif_dbg_bus_r3;
mdata->nrt_vbif_dbg_bus_size =
ARRAY_SIZE(nrt_vbif_dbg_bus_r3);
mdata->regdump = sde_rot_r3_regdump;
mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
-
SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0);
return 0;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
index 7aecc3cee210..e666f4811c77 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3_internal.h
@@ -28,6 +28,7 @@ struct sde_hw_rotator_context;
#define SDE_ROT_FLAG_SOURCE_ROTATED_90 0x8
#define SDE_ROT_FLAG_ROT_90 0x10
#define SDE_ROT_FLAG_DEINTERLACE 0x20
+#define SDE_ROT_FLAG_SECURE_CAMERA_SESSION 0x40
/**
* General defines
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
index da9845e35fde..49a2cf112b0e 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.c
@@ -51,6 +51,30 @@ static inline bool sde_smmu_is_valid_domain_type(
return true;
}
+static inline bool sde_smmu_is_valid_domain_condition(
+ struct sde_rot_data_type *mdata,
+ int domain_type,
+ bool is_attach)
+{
+ if (is_attach) {
+ if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
+ mdata->sde_caps_map) &&
+ (mdata->sec_cam_en &&
+ domain_type == SDE_IOMMU_DOMAIN_ROT_SECURE))
+ return false;
+ else
+ return true;
+ } else {
+ if (test_bit(SDE_CAPS_SEC_ATTACH_DETACH_SMMU,
+ mdata->sde_caps_map) &&
+ (mdata->sec_cam_en &&
+ domain_type == SDE_IOMMU_DOMAIN_ROT_SECURE))
+ return true;
+ else
+ return false;
+ }
+}
+
struct sde_smmu_client *sde_smmu_get_cb(u32 domain)
{
struct sde_rot_data_type *mdata = sde_rot_get_mdata();
@@ -180,7 +204,7 @@ end:
* And iommu attach is done only once during the initial attach and it is never
* detached as smmu v2 uses a feature called 'retention'.
*/
-static int sde_smmu_attach(struct sde_rot_data_type *mdata)
+int sde_smmu_attach(struct sde_rot_data_type *mdata)
{
struct sde_smmu_client *sde_smmu;
int i, rc = 0;
@@ -199,7 +223,10 @@ static int sde_smmu_attach(struct sde_rot_data_type *mdata)
goto err;
}
- if (!sde_smmu->domain_attached) {
+ if (!sde_smmu->domain_attached &&
+ sde_smmu_is_valid_domain_condition(mdata,
+ i,
+ true)) {
rc = arm_iommu_attach_device(sde_smmu->dev,
sde_smmu->mmu_mapping);
if (rc) {
@@ -239,7 +266,7 @@ err:
* Only disables the clks as it is not required to detach the iommu mapped
* VA range from the device in smmu as explained in the sde_smmu_attach
*/
-static int sde_smmu_detach(struct sde_rot_data_type *mdata)
+int sde_smmu_detach(struct sde_rot_data_type *mdata)
{
struct sde_smmu_client *sde_smmu;
int i;
@@ -249,8 +276,18 @@ static int sde_smmu_detach(struct sde_rot_data_type *mdata)
continue;
sde_smmu = sde_smmu_get_cb(i);
- if (sde_smmu && sde_smmu->dev)
- sde_smmu_enable_power(sde_smmu, false);
+ if (sde_smmu && sde_smmu->dev) {
+ if (sde_smmu->domain_attached &&
+ sde_smmu_is_valid_domain_condition(mdata,
+ i, false)) {
+ arm_iommu_detach_device(sde_smmu->dev);
+ SDEROT_DBG("iommu domain[%i] detached\n", i);
+ sde_smmu->domain_attached = false;
+ }
+ else {
+ sde_smmu_enable_power(sde_smmu, false);
+ }
+ }
}
return 0;
}
@@ -366,6 +403,33 @@ int sde_smmu_ctrl(int enable)
return mdata->iommu_ref_cnt;
}
+int sde_smmu_secure_ctrl(int enable)
+{
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+ int rc = 0;
+
+ mutex_lock(&sde_smmu_ref_cnt_lock);
+ /*
+ * Attach/detach secure context irrespective of ref count,
+ * We come here only when secure camera is disabled
+ */
+ if (enable) {
+ rc = sde_smmu_attach(mdata);
+ if (!rc)
+ mdata->iommu_attached = true;
+ } else {
+ rc = sde_smmu_detach(mdata);
+ /*
+ * keep iommu_attached equal to true,
+ * so that driver does not attemp to attach
+ * while in secure state
+ */
+ }
+
+ mutex_unlock(&sde_smmu_ref_cnt_lock);
+ return rc;
+}
+
/*
* sde_smmu_device_create()
* @dev: sde_mdp device
@@ -475,6 +539,7 @@ int sde_smmu_probe(struct platform_device *pdev)
}
sde_smmu = &mdata->sde_smmu[smmu_domain.domain];
+ sde_smmu->domain = smmu_domain.domain;
mp = &sde_smmu->mp;
memset(mp, 0, sizeof(struct sde_module_power));
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h
index 1adcfb7310f2..4a1c3d323143 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_smmu.h
@@ -45,4 +45,6 @@ int sde_smmu_map_dma_buf(struct dma_buf *dma_buf,
void sde_smmu_unmap_dma_buf(struct sg_table *table, int domain,
int dir, struct dma_buf *dma_buf);
+int sde_smmu_secure_ctrl(int enable);
+
#endif /* SDE_ROTATOR_SMMU_H */
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c
index 60c4c81eddf2..fb7bb37d52d9 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.c
@@ -745,6 +745,13 @@ static int sde_mdp_put_img(struct sde_mdp_img_data *data, bool rotator,
return 0;
}
+static int sde_mdp_is_map_needed(struct sde_mdp_img_data *data)
+{
+ if (data->flags & SDE_SECURE_CAMERA_SESSION)
+ return false;
+ return true;
+}
+
static int sde_mdp_get_img(struct sde_fb_data *img,
struct sde_mdp_img_data *data, struct device *dev,
bool rotator, int dir)
@@ -753,6 +760,8 @@ static int sde_mdp_get_img(struct sde_fb_data *img,
unsigned long *len;
u32 domain;
dma_addr_t *start;
+ struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+ struct ion_client *iclient = mdata->iclient;
start = &data->addr;
len = &data->len;
@@ -766,34 +775,78 @@ static int sde_mdp_get_img(struct sde_fb_data *img,
data->srcp_dma_buf = NULL;
return ret;
}
- domain = sde_smmu_get_domain_type(data->flags, rotator);
-
- SDEROT_DBG("%d domain=%d ihndl=%p\n",
- __LINE__, domain, data->srcp_dma_buf);
- data->srcp_attachment =
- sde_smmu_dma_buf_attach(data->srcp_dma_buf, dev,
- domain);
- if (IS_ERR(data->srcp_attachment)) {
- SDEROT_ERR("%d Failed to attach dma buf\n", __LINE__);
- ret = PTR_ERR(data->srcp_attachment);
- goto err_put;
- }
- SDEROT_DBG("%d attach=%p\n", __LINE__, data->srcp_attachment);
- data->srcp_table =
- dma_buf_map_attachment(data->srcp_attachment, dir);
- if (IS_ERR(data->srcp_table)) {
- SDEROT_ERR("%d Failed to map attachment\n", __LINE__);
- ret = PTR_ERR(data->srcp_table);
- goto err_detach;
- }
+ if (sde_mdp_is_map_needed(data)) {
+ domain = sde_smmu_get_domain_type(data->flags, rotator);
+
+ SDEROT_DBG("%d domain=%d ihndl=%p\n",
+ __LINE__, domain, data->srcp_dma_buf);
+ data->srcp_attachment =
+ sde_smmu_dma_buf_attach(data->srcp_dma_buf, dev,
+ domain);
+ if (IS_ERR(data->srcp_attachment)) {
+ SDEROT_ERR("%d Failed to attach dma buf\n", __LINE__);
+ ret = PTR_ERR(data->srcp_attachment);
+ goto err_put;
+ }
- SDEROT_DBG("%d table=%p\n", __LINE__, data->srcp_table);
- data->addr = 0;
- data->len = 0;
- data->mapped = false;
- data->skip_detach = false;
- /* return early, mapping will be done later */
+ SDEROT_DBG("%d attach=%p\n", __LINE__, data->srcp_attachment);
+ data->srcp_table =
+ dma_buf_map_attachment(data->srcp_attachment, dir);
+ if (IS_ERR(data->srcp_table)) {
+ SDEROT_ERR("%d Failed to map attachment\n", __LINE__);
+ ret = PTR_ERR(data->srcp_table);
+ goto err_detach;
+ }
+
+ SDEROT_DBG("%d table=%p\n", __LINE__, data->srcp_table);
+ data->addr = 0;
+ data->len = 0;
+ data->mapped = false;
+ data->skip_detach = false;
+ /* return early, mapping will be done later */
+ } else {
+ struct ion_handle *ihandle = NULL;
+ struct sg_table *sg_ptr = NULL;
+
+ do {
+ ihandle = img->handle;
+ if (IS_ERR_OR_NULL(ihandle)) {
+ ret = -EINVAL;
+ SDEROT_ERR("invalid ion handle\n");
+ break;
+ }
+
+ sg_ptr = ion_sg_table(iclient, ihandle);
+ if (sg_ptr == NULL) {
+ SDEROT_ERR("ion sg table get failed\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ if (sg_ptr->nents != 1) {
+ SDEROT_ERR("ion buffer mapping failed\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ if (((uint64_t)sg_dma_address(sg_ptr->sgl) >=
+ PHY_ADDR_4G - sg_ptr->sgl->length)) {
+ SDEROT_ERR("ion buffer mapped size invalid\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ data->addr = sg_dma_address(sg_ptr->sgl);
+ data->len = sg_ptr->sgl->length;
+ data->mapped = true;
+ ret = 0;
+ } while (0);
+
+ if (!IS_ERR_OR_NULL(ihandle))
+ ion_free(iclient, ihandle);
+ return ret;
+ }
return 0;
err_detach:
@@ -811,23 +864,39 @@ static int sde_mdp_map_buffer(struct sde_mdp_img_data *data, bool rotator,
{
int ret = -EINVAL;
int domain;
+ struct scatterlist *sg;
+ unsigned int i;
+ struct sg_table *table;
if (data->addr && data->len)
return 0;
if (!IS_ERR_OR_NULL(data->srcp_dma_buf)) {
- domain = sde_smmu_get_domain_type(data->flags,
- rotator);
- ret = sde_smmu_map_dma_buf(data->srcp_dma_buf,
- data->srcp_table, domain,
- &data->addr, &data->len, dir);
- if (IS_ERR_VALUE(ret)) {
- SDEROT_ERR("smmu map dma buf failed: (%d)\n", ret);
- goto err_unmap;
+ if (sde_mdp_is_map_needed(data)) {
+ domain = sde_smmu_get_domain_type(data->flags,
+ rotator);
+ ret = sde_smmu_map_dma_buf(data->srcp_dma_buf,
+ data->srcp_table, domain,
+ &data->addr, &data->len, dir);
+ if (IS_ERR_VALUE(ret)) {
+ SDEROT_ERR("smmu map buf failed:(%d)\n", ret);
+ goto err_unmap;
+ }
+ SDEROT_DBG("map %pad/%lx d:%u f:%x\n",
+ &data->addr,
+ data->len,
+ domain,
+ data->flags);
+ data->mapped = true;
+ } else {
+ data->addr = sg_phys(data->srcp_table->sgl);
+ data->len = 0;
+ table = data->srcp_table;
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ data->len += sg->length;
+ }
+ ret = 0;
}
- SDEROT_DBG("map %pad/%lx d:%u f:%x\n", &data->addr, data->len,
- domain, data->flags);
- data->mapped = true;
}
if (!data->addr) {
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h
index 93074d64bf93..3f94a1570fa2 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_util.h
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/msm_ion.h>
#include "sde_rotator_hwio.h"
#include "sde_rotator_base.h"
@@ -44,6 +45,8 @@
#define SDEDEV_ERR(dev, fmt, ...) \
dev_err(dev, "<SDEROT_ERR> " fmt, ##__VA_ARGS__)
+#define PHY_ADDR_4G (1ULL<<32)
+
struct sde_rect {
u16 x;
u16 y;
@@ -62,12 +65,14 @@ struct sde_rect {
#define SDE_SOURCE_ROTATED_90 0x00100000
#define SDE_SECURE_OVERLAY_SESSION 0x00008000
#define SDE_ROT_EXT_DMA_BUF 0x00010000
+#define SDE_SECURE_CAMERA_SESSION 0x00020000
struct sde_rot_data_type;
struct sde_fb_data {
uint32_t offset;
struct dma_buf *buffer;
+ struct ion_handle *handle;
int memory_id;
int id;
uint32_t flags;
@@ -79,6 +84,7 @@ struct sde_layer_plane {
/* DMA buffer file descriptor information. */
int fd;
struct dma_buf *buffer;
+ struct ion_handle *handle;
/* Pixel offset in the dma buffer. */
uint32_t offset;
diff --git a/include/uapi/media/msm_sde_rotator.h b/include/uapi/media/msm_sde_rotator.h
index 4487edf0c854..3546b0bf1377 100644
--- a/include/uapi/media/msm_sde_rotator.h
+++ b/include/uapi/media/msm_sde_rotator.h
@@ -86,4 +86,10 @@ struct msm_sde_rotator_fence {
/* SDE Rotator private control ID's */
#define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000)
+/*
+ * This control Id indicates this context is associated with the
+ * secure camera.
+ */
+#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000)
+
#endif /* __UAPI_MSM_SDE_ROTATOR_H__ */