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 dc5a5a0dc851..09c2dc6c237f 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 #include #include +#include +#include +#include +#include #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 eaf35733b38a..cecdb1411d11 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 c11c4b61d832..50d21a13425a 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) { @@ -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)); 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,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) { 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 #include #include +#include #include "sde_rotator_hwio.h" #include "sde_rotator_base.h" @@ -44,6 +45,8 @@ #define SDEDEV_ERR(dev, fmt, ...) \ dev_err(dev, " " 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__ */