msm_fb: display: Add IOMMU support to MDP and rotator driver
Add IOMMU support to MDP and rotator driver for operating with
virtual addresses instead of physical addresses
Change-Id: Ia5afcf33220e0e75e92948649c2bd4d7ef32917d
Signed-off-by: Ravishangar Kalyanam <rkalya@codeaurora.org>
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 3d9c9d1..59013e3 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -33,6 +33,8 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#endif
+#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
#define DRIVER_NAME "msm_rotator"
@@ -146,6 +148,33 @@
CLK_SUSPEND,
};
+int msm_rotator_iommu_map_buf(int mem_id, unsigned char src,
+ unsigned long *start, unsigned long *len,
+ struct ion_handle **pihdl)
+{
+ if (!msm_rotator_dev->client)
+ return -EINVAL;
+
+ *pihdl = ion_import_fd(msm_rotator_dev->client, mem_id);
+ if (IS_ERR_OR_NULL(*pihdl)) {
+ pr_err("ion_import_fd() failed\n");
+ return PTR_ERR(*pihdl);
+ }
+ pr_debug("%s(): ion_hdl %p, ion_buf %p\n", __func__, *pihdl,
+ ion_share(msm_rotator_dev->client, *pihdl));
+
+ if (ion_map_iommu(msm_rotator_dev->client,
+ *pihdl, ROTATOR_DOMAIN, GEN_POOL,
+ SZ_4K, 0, start, len, 0, ION_IOMMU_UNMAP_DELAYED)) {
+ pr_err("ion_map_iommu() failed\n");
+ return -EINVAL;
+ }
+
+ pr_debug("%s(): mem_id %d, start 0x%lx, len 0x%lx\n",
+ __func__, mem_id, *start, *len);
+ return 0;
+}
+
int msm_rotator_imem_allocate(int requestor)
{
int rc = 0;
@@ -748,9 +777,9 @@
return 0;
}
-static int get_img(struct msmfb_data *fbd, unsigned long *start,
- unsigned long *len, struct file **p_file, int *p_need,
- struct ion_handle **p_ihdl)
+static int get_img(struct msmfb_data *fbd, unsigned char src,
+ unsigned long *start, unsigned long *len, struct file **p_file,
+ int *p_need, struct ion_handle **p_ihdl)
{
int ret = 0;
#ifdef CONFIG_FB
@@ -766,19 +795,25 @@
#ifdef CONFIG_FB
if (fbd->flags & MDP_MEMORY_ID_TYPE_FB) {
file = fget_light(fbd->memory_id, &put_needed);
- if (file == NULL)
+ if (file == NULL) {
+ pr_err("fget_light returned NULL\n");
return -EINVAL;
+ }
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
- if (get_fb_phys_info(start, len, fb_num))
+ if (get_fb_phys_info(start, len, fb_num,
+ ROTATOR_SUBSYSTEM_ID)) {
+ pr_err("get_fb_phys_info() failed\n");
ret = -1;
- else {
+ } else {
*p_file = file;
*p_need = put_needed;
}
- } else
+ } else {
+ pr_err("invalid FB_MAJOR failed\n");
ret = -1;
+ }
if (ret)
fput_light(file, put_needed);
return ret;
@@ -786,15 +821,8 @@
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- *p_ihdl = ion_import_fd(msm_rotator_dev->client,
- fbd->memory_id);
- if (IS_ERR_OR_NULL(*p_ihdl))
- return PTR_ERR(*p_ihdl);
- if (!ion_phys(msm_rotator_dev->client, *p_ihdl, start,
- (size_t *) len))
- return 0;
- else
- return -ENOMEM;
+ return msm_rotator_iommu_map_buf(fbd->memory_id, src, start,
+ len, p_ihdl);
#endif
#ifdef CONFIG_ANDROID_PMEM
if (!get_pmem_file(fbd->memory_id, start, &vstart, len, p_file))
@@ -812,8 +840,13 @@
put_pmem_file(p_file);
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- if (!IS_ERR_OR_NULL(p_ihdl))
+ if (!IS_ERR_OR_NULL(p_ihdl)) {
+ pr_debug("%s(): p_ihdl %p\n", __func__, p_ihdl);
+ ion_unmap_iommu(msm_rotator_dev->client,
+ p_ihdl, ROTATOR_DOMAIN, GEN_POOL);
+
ion_free(msm_rotator_dev->client, p_ihdl);
+ }
#endif
}
static int msm_rotator_do_rotate(unsigned long arg)
@@ -878,17 +911,18 @@
goto do_rotate_unlock_mutex;
}
-
- rc = get_img(&info.src, (unsigned long *)&in_paddr,
- (unsigned long *)&src_len, &srcp0_file, &ps0_need, &srcp0_ihdl);
+ rc = get_img(&info.src, 1, (unsigned long *)&in_paddr,
+ (unsigned long *)&src_len, &srcp0_file, &ps0_need,
+ &srcp0_ihdl);
if (rc) {
pr_err("%s: in get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src.memory_id);
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.dst, (unsigned long *)&out_paddr,
- (unsigned long *)&dst_len, &dstp0_file, &p_need, &dstp0_ihdl);
+ rc = get_img(&info.dst, 0, (unsigned long *)&out_paddr,
+ (unsigned long *)&dst_len, &dstp0_file, &p_need,
+ &dstp0_ihdl);
if (rc) {
pr_err("%s: out get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst.memory_id);
@@ -916,7 +950,7 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.src_chroma,
+ rc = get_img(&info.src_chroma, 1,
(unsigned long *)&in_chroma_paddr,
(unsigned long *)&src_len, &srcp1_file, &p_need,
&srcp1_ihdl);
@@ -926,7 +960,7 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(&info.dst_chroma,
+ rc = get_img(&info.dst_chroma, 0,
(unsigned long *)&out_chroma_paddr,
(unsigned long *)&dst_len, &dstp1_file, &p_need,
&dstp1_ihdl);
@@ -1514,7 +1548,8 @@
clk_disable(msm_rotator_dev->imem_clk);
#endif
if (ver != pdata->hardware_version_number)
- pr_info("%s: invalid HW version\n", DRIVER_NAME);
+ pr_info("%s: invalid HW version ver 0x%x\n",
+ DRIVER_NAME, ver);
msm_rotator_dev->irq = platform_get_irq(pdev, 0);
if (msm_rotator_dev->irq < 0) {
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 6fbeca2..9d8c205 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -246,6 +246,12 @@
int32_t dirty;
};
+struct mdp4_iommu_pipe_info {
+ struct ion_handle *ihdl[MDP4_MAX_PLANE];
+ struct ion_handle *prev_ihdl[MDP4_MAX_PLANE];
+ u8 mark_unmap;
+};
+
struct mdp4_overlay_pipe {
uint32 pipe_used;
uint32 pipe_type; /* rgb, video/graphic */
@@ -445,6 +451,7 @@
{
return 0;
}
+
static inline void mdp4_dma_e_done_dtv(void)
{
/* empty */
@@ -739,4 +746,5 @@
void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
int mdp4_igc_lut_config(struct mdp_igc_lut_data *cfg);
+void mdp4_iommu_unmap(struct mdp4_overlay_pipe *pipe);
#endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index cb7a3b5..46e683a 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -21,6 +21,7 @@
#include <linux/hrtimer.h>
#include <linux/clk.h>
#include <mach/hardware.h>
+#include <mach/iommu_domains.h>
#include <linux/io.h>
#include <linux/debugfs.h>
#include <linux/fb.h>
@@ -96,6 +97,104 @@
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
static int new_perf_level;
+static struct ion_client *display_iclient;
+static struct mdp4_iommu_pipe_info mdp_iommu[MDP4_MIXER_MAX][OVERLAY_PIPE_RGB3];
+
+int mdp4_overlay_iommu_map_buf(int mem_id,
+ struct mdp4_overlay_pipe *pipe, unsigned int plane,
+ unsigned long *start, unsigned long *len,
+ struct ion_handle **srcp_ihdl)
+{
+ struct mdp4_iommu_pipe_info *iom_pipe_info;
+
+ if (!display_iclient)
+ return -EINVAL;
+
+ *srcp_ihdl = ion_import_fd(display_iclient, mem_id);
+ if (IS_ERR_OR_NULL(*srcp_ihdl)) {
+ pr_err("ion_import_fd() failed\n");
+ return PTR_ERR(*srcp_ihdl);
+ }
+ pr_debug("%s(): ion_hdl %p, ion_buf %p\n", __func__, *srcp_ihdl,
+ ion_share(display_iclient, *srcp_ihdl));
+ pr_debug("mixer %u, pipe %u, plane %u\n", pipe->mixer_num,
+ pipe->pipe_ndx, plane);
+ if (ion_map_iommu(display_iclient, *srcp_ihdl,
+ DISPLAY_DOMAIN, GEN_POOL, SZ_4K, 0, start,
+ len, 0, ION_IOMMU_UNMAP_DELAYED)) {
+ ion_free(display_iclient, *srcp_ihdl);
+ pr_err("ion_map_iommu() failed\n");
+ return -EINVAL;
+ }
+
+ iom_pipe_info = &mdp_iommu[pipe->mixer_num][pipe->pipe_ndx - 1];
+ if (!iom_pipe_info->ihdl[plane]) {
+ iom_pipe_info->ihdl[plane] = *srcp_ihdl;
+ } else {
+ if (iom_pipe_info->prev_ihdl[plane]) {
+ ion_unmap_iommu(display_iclient,
+ iom_pipe_info->prev_ihdl[plane],
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(display_iclient,
+ iom_pipe_info->prev_ihdl[plane]);
+ pr_debug("Previous: mixer %u, pipe %u, plane %u, "
+ "prev_ihdl %p\n", pipe->mixer_num,
+ pipe->pipe_ndx, plane,
+ iom_pipe_info->prev_ihdl[plane]);
+ }
+
+ iom_pipe_info->prev_ihdl[plane] = iom_pipe_info->ihdl[plane];
+ iom_pipe_info->ihdl[plane] = *srcp_ihdl;
+ }
+ pr_debug("mem_id %d, start 0x%lx, len 0x%lx\n",
+ mem_id, *start, *len);
+ return 0;
+}
+
+void mdp4_iommu_unmap(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_iommu_pipe_info *iom_pipe_info;
+ unsigned char i, j;
+
+ if (!display_iclient)
+ return;
+
+ for (j = 0; j < OVERLAY_PIPE_RGB3; j++) {
+ iom_pipe_info = &mdp_iommu[pipe->mixer_num][j];
+ for (i = 0; i < MDP4_MAX_PLANE; i++) {
+ if (iom_pipe_info->prev_ihdl[i]) {
+ pr_debug("%s(): mixer %u, pipe %u, plane %u, "
+ "prev_ihdl %p\n", __func__,
+ pipe->mixer_num, j + 1, i,
+ iom_pipe_info->prev_ihdl[i]);
+ ion_unmap_iommu(display_iclient,
+ iom_pipe_info->prev_ihdl[i],
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(display_iclient,
+ iom_pipe_info->prev_ihdl[i]);
+ iom_pipe_info->prev_ihdl[i] = NULL;
+ }
+
+ if (iom_pipe_info->mark_unmap) {
+ if (iom_pipe_info->ihdl[i]) {
+ if (pipe->mixer_num == MDP4_MIXER1)
+ mdp4_overlay_dtv_wait4vsync();
+ pr_debug("%s(): mixer %u, pipe %u, plane %u, "
+ "ihdl %p\n", __func__,
+ pipe->mixer_num, j + 1, i,
+ iom_pipe_info->ihdl[i]);
+ ion_unmap_iommu(display_iclient,
+ iom_pipe_info->ihdl[i],
+ DISPLAY_DOMAIN, GEN_POOL);
+ ion_free(display_iclient,
+ iom_pipe_info->ihdl[i]);
+ iom_pipe_info->ihdl[i] = NULL;
+ }
+ }
+ }
+ iom_pipe_info->mark_unmap = 0;
+ }
+}
/* static array with index 0 for unset status and 1 for set status */
static bool overlay_status[MDP4_OVERLAY_TYPE_MAX];
@@ -1657,6 +1756,7 @@
void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe)
{
uint32 ptype, num, ndx, mixer;
+ struct mdp4_iommu_pipe_info *iom_pipe_info;
pr_debug("%s: pipe=%x ndx=%d\n", __func__, (int)pipe, pipe->pipe_ndx);
@@ -1664,6 +1764,8 @@
num = pipe->pipe_num;
ndx = pipe->pipe_ndx;
mixer = pipe->mixer_num;
+ iom_pipe_info = &mdp_iommu[pipe->mixer_num][pipe->pipe_ndx - 1];
+ iom_pipe_info->mark_unmap = 1;
memset(pipe, 0, sizeof(*pipe));
@@ -1751,6 +1853,7 @@
struct msm_fb_data_type *mfd)
{
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_iommu_pipe_info *iom_pipe_info;
int ret, ptype;
if (mfd == NULL) {
@@ -1864,6 +1967,15 @@
return -ENOMEM;
}
+ if (!display_iclient && !IS_ERR_OR_NULL(mfd->iclient)) {
+ display_iclient = mfd->iclient;
+ pr_debug("%s(): display_iclient %p\n", __func__,
+ display_iclient);
+ }
+
+ iom_pipe_info = &mdp_iommu[pipe->mixer_num][pipe->pipe_ndx - 1];
+ iom_pipe_info->mark_unmap = 0;
+
pipe->src_format = req->src.format;
ret = mdp4_overlay_format2pipe(pipe);
@@ -1927,12 +2039,10 @@
}
static int get_img(struct msmfb_data *img, struct fb_info *info,
+ struct mdp4_overlay_pipe *pipe, unsigned int plane,
unsigned long *start, unsigned long *len, struct file **srcp_file,
int *p_need, struct ion_handle **srcp_ihdl)
{
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
-#endif
struct file *file;
int put_needed, ret = 0, fb_num;
#ifdef CONFIG_ANDROID_PMEM
@@ -1953,9 +2063,10 @@
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
- if (get_fb_phys_info(start, len, fb_num))
+ if (get_fb_phys_info(start, len, fb_num,
+ DISPLAY_SUBSYSTEM_ID)) {
ret = -1;
- else {
+ } else {
*srcp_file = file;
*p_need = put_needed;
}
@@ -1967,13 +2078,8 @@
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- *srcp_ihdl = ion_import_fd(mfd->iclient, img->memory_id);
- if (IS_ERR_OR_NULL(*srcp_ihdl))
- return PTR_ERR(*srcp_ihdl);
- if (!ion_phys(mfd->iclient, *srcp_ihdl, start, (size_t *) len))
- return 0;
- else
- return -EINVAL;
+ return mdp4_overlay_iommu_map_buf(img->memory_id, pipe, plane,
+ start, len, srcp_ihdl);
#endif
#ifdef CONFIG_ANDROID_PMEM
if (!get_pmem_file(img->memory_id, start, &vstart,
@@ -2301,7 +2407,7 @@
((req->src_rect.w > req->dst_rect.w) &&
(req->src_rect.h > req->dst_rect.h)));
if (test) {
- pr_warn("%s: No sharpening while downscaling.\n",
+ pr_debug("%s: No sharpening while downscaling.\n",
__func__);
pipe->flags &= ~MDP_SHARPENING;
}
@@ -2524,6 +2630,7 @@
mdp4_overlay1_update_blt_mode(mfd);
mdp4_overlay_dtv_wait_for_ov(mfd, pipe);
+ mdp4_iommu_unmap(pipe);
mutex_unlock(&mfd->dma->ov_mutex);
return 0;
@@ -2560,7 +2667,8 @@
return -EINTR;
img = &req->data;
- get_img(img, info, &start, &len, &srcp0_file, &ps0_need, &srcp0_ihdl);
+ get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
+ &ps0_need, &srcp0_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: pmem Error\n", __func__);
@@ -2578,7 +2686,7 @@
if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, &start, &len, &srcp1_file,
+ get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
&p_need, &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
@@ -2610,7 +2718,7 @@
} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, &start, &len, &srcp1_file,
+ get_img(img, info, pipe, 1, &start, &len, &srcp1_file,
&p_need, &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
@@ -2621,7 +2729,7 @@
pipe->srcp1_addr = start + img->offset;
img = &req->plane2_data;
- get_img(img, info, &start, &len, &srcp2_file,
+ get_img(img, info, pipe, 2, &start, &len, &srcp2_file,
&p_need, &srcp2_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
@@ -2672,7 +2780,7 @@
mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
} else {
if (pipe->flags & MDP_SHARPENING) {
- pr_warn(
+ pr_debug(
"%s: Sharpening/Smoothing not supported on RGB pipe\n",
__func__);
pipe->flags &= ~MDP_SHARPENING;
@@ -2742,7 +2850,8 @@
/* write out DPP HSIC registers */
if (pipe->flags & MDP_DPP_HSIC)
mdp4_hsic_update(pipe);
-
+ if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
+ mdp4_iommu_unmap(pipe);
mdp4_stat.overlay_play[pipe->mixer_num]++;
mutex_unlock(&mfd->dma->ov_mutex);
end:
@@ -2757,14 +2866,5 @@
/* only source may use frame buffer */
if (img->flags & MDP_MEMORY_ID_TYPE_FB)
fput_light(srcp0_file, ps0_need);
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- else if (!IS_ERR_OR_NULL(srcp0_ihdl))
- ion_free(mfd->iclient, srcp0_ihdl);
-
- if (!IS_ERR_OR_NULL(srcp1_ihdl))
- ion_free(mfd->iclient, srcp1_ihdl);
- if (!IS_ERR_OR_NULL(srcp2_ihdl))
- ion_free(mfd->iclient, srcp2_ihdl);
-#endif
return ret;
}
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 35d5769..f8200a8 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -37,6 +37,7 @@
int mdp4_atv_on(struct platform_device *pdev)
{
uint8 *buf;
+ unsigned int buf_offset;
int bpp, ptype;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
@@ -57,7 +58,7 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
if (atv_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -96,7 +97,15 @@
pipe->src_w = fbi->var.xres;
pipe->src_y = 0;
pipe->src_x = 0;
- pipe->srcp0_addr = (uint32) buf;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
pipe->srcp0_ystride = fbi->fix.line_length;
mdp4_overlay_dmae_xy(pipe); /* dma_e */
@@ -129,8 +138,10 @@
msleep(100);
/* dis-engage rgb2 from mixer1 */
- if (atv_pipe)
+ if (atv_pipe) {
mdp4_mixer_stage_down(atv_pipe);
+ mdp4_iommu_unmap(atv_pipe);
+ }
return ret;
}
@@ -147,6 +158,7 @@
{
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
+ unsigned int buf_offset;
int bpp;
unsigned long flag;
struct mdp4_overlay_pipe *pipe;
@@ -157,12 +169,19 @@
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
mutex_lock(&mfd->dma->ov_mutex);
pipe = atv_pipe;
- pipe->srcp0_addr = (uint32) buf;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
mdp4_overlay_rgb_setup(pipe);
mdp4_mixer_stage_up(pipe);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 18753fb..299763f 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -654,8 +654,10 @@
void mdp_dsi_cmd_overlay_suspend(void)
{
/* dis-engage rgb0 from mixer0 */
- if (dsi_pipe)
+ if (dsi_pipe) {
mdp4_mixer_stage_down(dsi_pipe);
+ mdp4_iommu_unmap(dsi_pipe);
+ }
}
void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd)
@@ -671,7 +673,7 @@
mdp4_overlay_update_dsi_cmd(mfd);
mdp4_dsi_cmd_kickoff_ui(mfd, dsi_pipe);
-
+ mdp4_iommu_unmap(dsi_pipe);
/* signal if pan function is waiting for the update completion */
if (mfd->pan_waiting) {
mfd->pan_waiting = FALSE;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index ea2f331..e729a55 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -99,6 +99,7 @@
int hsync_start_x;
int hsync_end_x;
uint8 *buf;
+ unsigned int buf_offset;
int bpp, ptype;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
@@ -121,7 +122,7 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
if (dsi_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -175,10 +176,18 @@
pipe->src_w = fbi->var.xres;
pipe->src_y = 0;
pipe->src_x = 0;
- pipe->srcp0_addr = (uint32) buf;
pipe->srcp0_ystride = fbi->fix.line_length;
pipe->bpp = bpp;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
pipe->dst_h = fbi->var.yres;
pipe->dst_w = fbi->var.xres;
@@ -294,8 +303,10 @@
ret = panel_next_off(pdev);
/* dis-engage rgb0 from mixer0 */
- if (dsi_pipe)
+ if (dsi_pipe) {
mdp4_mixer_stage_down(dsi_pipe);
+ mdp4_iommu_unmap(dsi_pipe);
+ }
return ret;
}
@@ -306,6 +317,7 @@
{
struct fb_info *fbi;
struct mdp4_overlay_pipe *pipe;
+ unsigned int buf_offset;
int bpp;
uint8 *buf = NULL;
@@ -327,7 +339,7 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
if (pipe->is_3d) {
pipe->src_height = pipe->src_height_3d;
@@ -353,7 +365,15 @@
pipe->src_x = 0;
pipe->dst_y = 0;
pipe->dst_x = 0;
- pipe->srcp0_addr = (uint32)buf;
+
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
mdp4_overlay_rgb_setup(pipe);
@@ -669,6 +689,7 @@
{
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
+ unsigned int buf_offset;
int bpp;
struct mdp4_overlay_pipe *pipe;
@@ -678,16 +699,26 @@
/* no need to power on cmd block since it's dsi video mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
mutex_lock(&mfd->dma->ov_mutex);
pipe = dsi_pipe;
- pipe->srcp0_addr = (uint32) buf;
+
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
mdp4_overlay_rgb_setup(pipe);
mdp4_mixer_stage_up(pipe);
mdp4_overlay_reg_flush(pipe, 0);
mdp4_overlay_dsi_video_start();
mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
+ mdp4_iommu_unmap(pipe);
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index db1234f..2dd7436 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -268,6 +268,7 @@
mdp4_overlay_dtv_wait4vsync();
mdp4_dtv_stop(mfd);
mdp4_overlay_pipe_free(dtv_pipe);
+ mdp4_iommu_unmap(dtv_pipe);
dtv_pipe = NULL;
}
mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
@@ -660,5 +661,6 @@
mdp4_overlay_reg_flush(pipe, 0);
mdp4_overlay_dtv_start();
mdp4_overlay_dtv_ov_done_push(mfd, pipe);
+ mdp4_iommu_unmap(pipe);
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 5d7a473..d9716bd 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -79,6 +79,7 @@
int hsync_start_x;
int hsync_end_x;
uint8 *buf;
+ unsigned int buf_offset;
int bpp, ptype;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
@@ -108,7 +109,7 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
if (lcdc_pipe == NULL) {
ptype = mdp4_overlay_format2type(mfd->fb_imgType);
@@ -141,7 +142,15 @@
pipe->src_w = fbi->var.xres;
pipe->src_y = 0;
pipe->src_x = 0;
- pipe->srcp0_addr = (uint32) buf;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
+
pipe->srcp0_ystride = fbi->fix.line_length;
pipe->bpp = bpp;
@@ -271,8 +280,10 @@
msleep(16);
/* dis-engage rgb0 from mixer0 */
- if (lcdc_pipe)
+ if (lcdc_pipe) {
mdp4_mixer_stage_down(lcdc_pipe);
+ mdp4_iommu_unmap(lcdc_pipe);
+ }
#ifdef CONFIG_MSM_BUS_SCALING
mdp_bus_scale_update_request(0);
@@ -559,6 +570,7 @@
{
struct fb_info *fbi = mfd->fbi;
uint8 *buf;
+ unsigned int buf_offset;
int bpp;
struct mdp4_overlay_pipe *pipe;
@@ -568,16 +580,24 @@
/* no need to power on cmd block since it's lcdc mode */
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += calc_fb_offset(mfd, fbi, bpp);
+ buf_offset = calc_fb_offset(mfd, fbi, bpp);
mutex_lock(&mfd->dma->ov_mutex);
pipe = lcdc_pipe;
- pipe->srcp0_addr = (uint32) buf;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
mdp4_overlay_rgb_setup(pipe);
mdp4_mixer_stage_up(pipe);
mdp4_overlay_reg_flush(pipe, 0);
mdp4_overlay_lcdc_start();
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
+ mdp4_iommu_unmap(pipe);
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index d8e7998..f92fb43 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -141,6 +141,7 @@
{
struct fb_info *fbi;
uint8 *buf;
+ unsigned int buf_offset;
struct mdp4_overlay_pipe *pipe;
int bpp;
@@ -156,7 +157,7 @@
bpp = fbi->var.bits_per_pixel / 8;
buf = (uint8 *) fbi->fix.smem_start;
- buf += fbi->var.xoffset * bpp +
+ buf_offset = fbi->var.xoffset * bpp +
fbi->var.yoffset * fbi->fix.line_length;
/* MDP cmd block enable */
@@ -173,8 +174,15 @@
pipe->src_x = 0;
pipe->dst_y = 0;
pipe->dst_x = 0;
- pipe->srcp0_addr = (uint32)buf;
+ if (mfd->map_buffer) {
+ pipe->srcp0_addr = (unsigned int)mfd->map_buffer->iova[0] + \
+ buf_offset;
+ pr_debug("start 0x%lx srcp0_addr 0x%x\n", mfd->
+ map_buffer->iova[0], pipe->srcp0_addr);
+ } else {
+ pipe->srcp0_addr = (uint32)(buf + buf_offset);
+ }
mdp4_mixer_stage_up(pipe);
@@ -349,6 +357,7 @@
pr_debug("%s: in writeback pan display 0x%x\n", __func__,
(unsigned int)writeback_pipe->blt_addr);
mdp4_writeback_kickoff_ui(mfd, writeback_pipe);
+ mdp4_iommu_unmap(writeback_pipe);
/* signal if pan function is waiting for the
* update completion */
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index dc0756e..9b8f60f 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -28,6 +28,7 @@
#include <asm/system.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
+#include <mach/iommu_domains.h>
#include "mdp.h"
#include "msm_fb.h"
#include "mdp4.h"
@@ -2539,7 +2540,7 @@
{
struct mdp_buf_type *buf;
ion_phys_addr_t addr;
- u32 len;
+ unsigned long len;
if (mix_num == MDP4_MIXER0)
buf = mfd->ov0_wb_buf;
@@ -2560,10 +2561,10 @@
buf->ihdl = ion_alloc(mfd->iclient, buf->size, SZ_4K,
mfd->mem_hid);
if (!IS_ERR_OR_NULL(buf->ihdl)) {
- if (ion_phys(mfd->iclient, buf->ihdl,
- &addr, &len)) {
- pr_err("%s:%d: ion_phys map failed\n",
- __func__, __LINE__);
+ if (ion_map_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_DOMAIN, GEN_POOL, SZ_4K, 0, &addr,
+ &len, 0, 0)) {
+ pr_err("ion_map_iommu() failed\n");
return -ENOMEM;
}
} else {
@@ -2598,6 +2599,8 @@
if (!IS_ERR_OR_NULL(mfd->iclient)) {
if (!IS_ERR_OR_NULL(buf->ihdl)) {
+ ion_unmap_iommu(mfd->iclient, buf->ihdl,
+ DISPLAY_DOMAIN, GEN_POOL);
ion_free(mfd->iclient, buf->ihdl);
pr_debug("%s:%d free writeback imem\n", __func__,
__LINE__);
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index ab5abf5..32856ef 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -529,7 +529,10 @@
down(&mfd->sem);
iBuf = &mfd->ibuf;
- iBuf->buf = (uint8 *) info->fix.smem_start;
+ if (mfd->map_buffer)
+ iBuf->buf = (uint8 *)mfd->map_buffer->iova[0];
+ else
+ iBuf->buf = (uint8 *) info->fix.smem_start;
iBuf->buf += calc_fb_offset(mfd, fbi, bpp);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index bc0a65c..f8cc926 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -82,6 +82,8 @@
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
+static struct ion_client *iclient;
+
u32 msm_fb_debug_enabled;
/* Setting msm_fb_msg_level to 8 prints out ALL messages */
u32 msm_fb_msg_level = 7;
@@ -343,6 +345,13 @@
MSM_FB_DEBUG("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n",
(int)fbram_phys, (int)fbram);
+ iclient = msm_ion_client_create(-1, pdev->name);
+ if (IS_ERR_OR_NULL(iclient)) {
+ pr_err("msm_ion_client_create() return"
+ " error, val %p\n", iclient);
+ iclient = NULL;
+ }
+
msm_fb_resource_initialized = 1;
return 0;
}
@@ -1018,6 +1027,9 @@
int *id;
int fbram_offset;
int remainder, remainder_mode2;
+ static int subsys_id[2] = {MSM_SUBSYSTEM_DISPLAY,
+ MSM_SUBSYSTEM_ROTATOR};
+ unsigned int flags = MSM_SUBSYSTEM_MAP_IOVA;
/*
* fb info initialization
@@ -1264,6 +1276,16 @@
fbi->screen_base = fbram;
fbi->fix.smem_start = (unsigned long)fbram_phys;
+ mfd->map_buffer = msm_subsystem_map_buffer(
+ fbi->fix.smem_start, fbi->fix.smem_len,
+ flags, subsys_id, 2);
+ if (mfd->map_buffer) {
+ pr_debug("%s(): buf 0x%lx, mfd->map_buffer->iova[0] 0x%lx\n"
+ "mfd->map_buffer->iova[1] 0x%lx", __func__,
+ fbi->fix.smem_start, mfd->map_buffer->iova[0],
+ mfd->map_buffer->iova[1]);
+ }
+
memset(fbi->screen_base, 0x0, fix->smem_len);
mfd->op_enable = TRUE;
@@ -3495,11 +3517,7 @@
mfd->fb_page = fb_num;
mfd->index = fbi_list_index;
mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
-#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- mfd->iclient = msm_ion_client_create(-1, pdev->name);
-#else
- mfd->iclient = NULL;
-#endif
+ mfd->iclient = iclient;
/* link to the latest pdev */
mfd->pdev = this_dev;
@@ -3522,19 +3540,32 @@
}
EXPORT_SYMBOL(msm_fb_add_device);
-int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num)
+int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num,
+ int subsys_id)
{
struct fb_info *info;
+ struct msm_fb_data_type *mfd;
- if (fb_num > MAX_FBI_LIST)
+ if (fb_num > MAX_FBI_LIST ||
+ (subsys_id != DISPLAY_SUBSYSTEM_ID &&
+ subsys_id != ROTATOR_SUBSYSTEM_ID)) {
+ pr_err("%s(): Invalid parameters\n", __func__);
return -1;
+ }
info = fbi_list[fb_num];
- if (!info)
+ if (!info) {
+ pr_err("%s(): info is NULL\n", __func__);
return -1;
+ }
- *start = info->fix.smem_start;
+ mfd = (struct msm_fb_data_type *)info->par;
+ if (mfd->map_buffer)
+ *start = mfd->map_buffer->iova[subsys_id];
+ else
+ *start = info->fix.smem_start;
*len = info->fix.smem_len;
+
return 0;
}
EXPORT_SYMBOL(get_fb_phys_info);
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 79d9140..44d5018 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -23,6 +23,7 @@
#include "linux/proc_fs.h"
#include <mach/hardware.h>
+#include <mach/msm_subsystem_map.h>
#include <linux/io.h>
#include <mach/board.h>
@@ -171,6 +172,7 @@
struct list_head writeback_register_queue;
wait_queue_head_t wait_q;
struct ion_client *iclient;
+ struct msm_mapped_buffer *map_buffer;
struct mdp_buf_type *ov0_wb_buf;
struct mdp_buf_type *ov1_wb_buf;
u32 ov_start;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 6442faa..56e8438 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -445,11 +445,16 @@
struct mdp_mixer_info info[MAX_PIPE_PER_MIXER];
};
+enum {
+ DISPLAY_SUBSYSTEM_ID,
+ ROTATOR_SUBSYSTEM_ID,
+};
#ifdef __KERNEL__
/* get the framebuffer physical address information */
-int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num);
+int get_fb_phys_info(unsigned long *start, unsigned long *len, int fb_num,
+ int subsys_id);
struct fb_info *msm_fb_get_writeback_fb(void);
int msm_fb_writeback_init(struct fb_info *info);
int msm_fb_writeback_start(struct fb_info *info);