msm: sde: secure camera changes for v4l2 rotator

Add support for secure camera buffer handling in SDE rotator.
This change adds detaching the secure context when the buffer
with the secure camera flag is signaled and attaches the secure
context when going back to normal non securer-camera usecases.

Change-Id: Iaff45907e78775975fa3035404dcfd9b27e6e816
Signed-off-by: Abhijit Kulkarni <kabhijit@codeaurora.org>
This commit is contained in:
Abhijit Kulkarni 2016-09-26 22:32:10 -07:00
parent 368fecd7df
commit cbd1c43d5a
13 changed files with 376 additions and 61 deletions

View file

@ -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;

View file

@ -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,

View file

@ -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) {

View file

@ -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
**********************************************************************/

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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) {
@ -240,7 +267,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;
@ -250,8 +277,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;
}
@ -367,6 +404,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
@ -476,6 +540,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));

View file

@ -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 */

View file

@ -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,35 +775,79 @@ 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;
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 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;
}
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 */
return 0;
err_detach:
dma_buf_detach(data->srcp_dma_buf, data->srcp_attachment);
@ -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) {

View file

@ -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;

View file

@ -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__ */