diff options
| -rw-r--r-- | drivers/video/fbdev/msm/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 30 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.h | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.c | 6 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp.h | 39 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_layer.c | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_overlay.c | 21 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_rotator.c | 1092 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_rotator.h | 100 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdss_mdp_wb.c | 952 | ||||
| -rw-r--r-- | include/linux/msm_mdp.h | 18 |
11 files changed, 38 insertions, 2224 deletions
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index e3f2a5b7843f..b4a901cc159b 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -12,7 +12,6 @@ mdss-mdp-objs += mdss_mdp_pp.o mdss_mdp_pp_debug.o mdss_mdp_pp_cache_config.o mdss-mdp-objs += mdss_mdp_intf_video.o mdss-mdp-objs += mdss_mdp_intf_cmd.o mdss-mdp-objs += mdss_mdp_intf_writeback.o -mdss-mdp-objs += mdss_mdp_rotator.o mdss-mdp-objs += mdss_rotator.o mdss-mdp-objs += mdss_mdp_overlay.o mdss-mdp-objs += mdss_mdp_layer.o diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 858465e6df78..d277db0da189 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -4515,7 +4515,6 @@ int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd, void __user *argp = (void __user *)arg; int ret = -ENOSYS; struct mdp_buf_sync buf_sync; - struct msm_sync_pt_data *sync_pt_data = NULL; unsigned int dsi_mode = 0; struct mdss_panel_data *pdata = NULL; @@ -4557,18 +4556,13 @@ int mdss_fb_do_ioctl(struct fb_info *info, unsigned int cmd, if (ret) goto exit; - if (mfd->mdp.get_sync_fnc) - sync_pt_data = mfd->mdp.get_sync_fnc(mfd, &buf_sync); - if (!sync_pt_data) { - if ((!mfd->op_enable) || (mdss_fb_is_power_off(mfd))) { - ret = -EPERM; - goto exit; - } - sync_pt_data = &mfd->mdp_sync_pt_data; + if ((!mfd->op_enable) || (mdss_fb_is_power_off(mfd))) { + ret = -EPERM; + goto exit; } - ret = mdss_fb_handle_buf_sync_ioctl(sync_pt_data, &buf_sync); - + ret = mdss_fb_handle_buf_sync_ioctl(&mfd->mdp_sync_pt_data, + &buf_sync); if (!ret) ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync)); break; @@ -4623,20 +4617,6 @@ static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd, return mdss_fb_do_ioctl(info, cmd, arg, file); } -struct fb_info *msm_fb_get_writeback_fb(void) -{ - int c = 0; - for (c = 0; c < fbi_list_index; ++c) { - struct msm_fb_data_type *mfd; - mfd = (struct msm_fb_data_type *)fbi_list[c]->par; - if (mfd->panel.type == WRITEBACK_PANEL) - return fbi_list[c]; - } - - return NULL; -} -EXPORT_SYMBOL(msm_fb_get_writeback_fb); - static int mdss_fb_register_extra_panel(struct platform_device *pdev, struct mdss_panel_data *pdata) { diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h index 67d42628597d..af670f607e54 100644 --- a/drivers/video/fbdev/msm/mdss_fb.h +++ b/drivers/video/fbdev/msm/mdss_fb.h @@ -228,8 +228,6 @@ struct msm_mdp_interface { u32 (*fb_stride)(u32 fb_index, u32 xres, int bpp); struct mdss_mdp_format_params *(*get_format_params)(u32 format); int (*splash_init_fnc)(struct msm_fb_data_type *mfd); - struct msm_sync_pt_data *(*get_sync_fnc)(struct msm_fb_data_type *mfd, - const struct mdp_buf_sync *buf_sync); void (*check_dsi_status)(struct work_struct *work, uint32_t interval); int (*configure_panel)(struct msm_fb_data_type *mfd, int mode, int dest_ctrl); diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index b50e29c0e610..84ddef637826 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -54,7 +54,6 @@ #include "mdss_panel.h" #include "mdss_debug.h" #include "mdss_mdp_debug.h" -#include "mdss_mdp_rotator.h" #include "mdss_smmu.h" #include "mdss_mdp_trace.h" @@ -2266,11 +2265,6 @@ static int mdss_mdp_probe(struct platform_device *pdev) pr_err("unable to register bus scaling\n"); goto probe_done; } - rc = mdss_mdp_rot_mgr_init(); - if (rc) { - pr_err("unable to initialize rotation mgr\n"); - goto probe_done; - } rc = mdss_mdp_debug_init(pdev, mdata); if (rc) { diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h index 6b36e2a9bc58..bf3ff960f292 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.h +++ b/drivers/video/fbdev/msm/mdss_mdp.h @@ -1313,6 +1313,37 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata, return true; } +static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format, u32 in_rot90, + u32 bwc) +{ + switch (in_format) { + case MDP_RGB_565: + case MDP_BGR_565: + if (in_rot90) + return MDP_RGB_888; + else + return in_format; + case MDP_RGBA_8888: + if (bwc) + return MDP_BGRA_8888; + else + return in_format; + case MDP_Y_CBCR_H2V2_VENUS: + case MDP_Y_CRCB_H2V2_VENUS: + case MDP_Y_CBCR_H2V2: + if (in_rot90) + return MDP_Y_CRCB_H2V2; + else + return in_format; + case MDP_Y_CB_CR_H2V2: + case MDP_Y_CR_CB_GH2V2: + case MDP_Y_CR_CB_H2V2: + return MDP_Y_CRCB_H2V2; + default: + return in_format; + } +} + irqreturn_t mdss_mdp_isr(int irq, void *ptr); void mdss_mdp_irq_clear(struct mdss_data_type *mdata, u32 intr_type, u32 intf_num); @@ -1594,9 +1625,6 @@ bool mdss_rect_overlap_check(struct mdss_rect *rect1, struct mdss_rect *rect2); void mdss_rect_split(struct mdss_rect *in_roi, struct mdss_rect *l_roi, struct mdss_rect *r_roi, u32 splitpoint); -int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd, - struct mdss_mdp_commit_cb *commit_cb); -int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg); int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id); bool mdss_mdp_mixer_reg_has_pipe(struct mdss_mdp_mixer *mixer, @@ -1616,14 +1644,9 @@ void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl, struct mdss_rect *l_roi, struct mdss_rect *r_roi); void mdss_mdp_mixer_update_pipe_map(struct mdss_mdp_ctl *master_ctl, int mixer_mux); -int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, u32 dst_format); -int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd, - struct mdp_mixer_cfg *mixer_cfg); void mdss_mdp_pipe_calc_pixel_extn(struct mdss_mdp_pipe *pipe); void mdss_mdp_pipe_calc_qseed3_cfg(struct mdss_mdp_pipe *pipe); -int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable); -int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enable); void mdss_mdp_ctl_restore(bool locked); int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl, bool is_recovery); int mdss_mdp_wait_for_xin_halt(u32 xin_id, bool is_vbif_nrt); diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index bc439a92524e..f437109c8382 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -30,7 +30,6 @@ #include "mdss_debug.h" #include "mdss_fb.h" #include "mdss_mdp.h" -#include "mdss_mdp_rotator.h" #include "mdss_mdp_wfd.h" #define CHECK_LAYER_BOUNDS(offset, size, max_size) \ diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c index 57b6af00b8c1..00e540c860c3 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c +++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c @@ -34,7 +34,6 @@ #include "mdss_debug.h" #include "mdss_fb.h" #include "mdss_mdp.h" -#include "mdss_mdp_rotator.h" #include "mdss_smmu.h" #include "mdss_mdp_wfd.h" #include "mdss_dsi_clk.h" @@ -1015,11 +1014,6 @@ static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd, struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); int ret; - if (req->flags & MDSS_MDP_ROT_ONLY) { - ret = mdss_mdp_rotator_setup(mfd, req); - return ret; - } - ret = mutex_lock_interruptible(&mdp5_data->ov_lock); if (ret) return ret; @@ -2123,11 +2117,6 @@ static int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx) if (!mdp5_data || !mdp5_data->ctl) return -ENODEV; - if (ndx & MDSS_MDP_ROT_SESSION_MASK) { - ret = mdss_mdp_rotator_unset(ndx); - return ret; - } - ret = mutex_lock_interruptible(&mdp5_data->ov_lock); if (ret) return ret; @@ -2272,11 +2261,6 @@ static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd, pr_debug("play req id=%x\n", req->id); - if (req->id & MDSS_MDP_ROT_SESSION_MASK) { - ret = mdss_mdp_rotator_play(mfd, req); - return ret; - } - ret = mutex_lock_interruptible(&mdp5_data->ov_lock); if (ret) return ret; @@ -4996,9 +4980,7 @@ ctl_stop: mdp5_data->ctl = NULL; } - if (atomic_dec_return( - &mdp5_data->mdata->active_intf_cnt) == 0) - mdss_mdp_rotator_release_all(); + atomic_dec(&mdp5_data->mdata->active_intf_cnt); if (!mdp5_data->mdata->idle_pc_enabled || (mfd->panel_info->type != MIPI_CMD_PANEL)) { @@ -5404,7 +5386,6 @@ int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd) mdp5_interface->mode_switch = mdss_mode_switch; mdp5_interface->mode_switch_post = mdss_mode_switch_post; mdp5_interface->pre_commit_fnc = mdss_mdp_overlay_precommit; - mdp5_interface->get_sync_fnc = mdss_mdp_rotator_sync_pt_get; mdp5_interface->splash_init_fnc = mdss_mdp_splash_init; mdp5_interface->configure_panel = mdss_mdp_update_panel_info; mdp5_interface->input_event_handler = mdss_mdp_input_event_handler; diff --git a/drivers/video/fbdev/msm/mdss_mdp_rotator.c b/drivers/video/fbdev/msm/mdss_mdp_rotator.c deleted file mode 100644 index d7a9f73966ea..000000000000 --- a/drivers/video/fbdev/msm/mdss_mdp_rotator.c +++ /dev/null @@ -1,1092 +0,0 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include <linux/errno.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/types.h> - -#include <sync.h> -#include <sw_sync.h> - -#include "mdss_mdp.h" -#include "mdss_mdp_rotator.h" -#include "mdss_fb.h" -#include "mdss_debug.h" - -#define MAX_ROTATOR_PIPE_COUNT 2 -#define PIPE_ACQUIRE_TIMEOUT_IN_MS 400 - -#define MAX_ROTATOR_SESSION_ID 0xfffffff - -struct mdss_mdp_rot_pipe { - struct mdss_mdp_pipe *pipe; - struct mdss_mdp_rotator_session *active_session; - struct mdss_mdp_rotator_session *previous_session; - struct completion comp; - bool context_switched; - u32 current_smp_size; - u32 wait_count; -}; - -struct mdss_mdp_rot_session_mgr { - struct list_head queue; - struct mutex session_lock; - int session_id; - int session_count; - - int pipe_count; - struct mutex pipe_lock; - struct mdss_mdp_rot_pipe rot_pipes[MAX_ROTATOR_PIPE_COUNT]; - - struct workqueue_struct *rot_work_queue; -}; - -static struct mdss_mdp_rot_session_mgr *rot_mgr; -static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot); -static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work); -static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot, - struct mdss_mdp_pipe *pipe); -static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot); -static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create( - struct mdss_mdp_rotator_session *rot); - -int mdss_mdp_rot_mgr_init(void) -{ - if (rot_mgr) { - pr_debug("rot manager initialized already\n"); - return 0; - } - - rot_mgr = kzalloc(sizeof(struct mdss_mdp_rot_session_mgr), GFP_KERNEL); - if (!rot_mgr) { - pr_err("fail to allocate rot manager\n"); - return -ENOMEM; - } - - mutex_init(&rot_mgr->session_lock); - mutex_init(&rot_mgr->pipe_lock); - INIT_LIST_HEAD(&rot_mgr->queue); - rot_mgr->rot_work_queue = create_workqueue("rot_commit_workq"); - if (!rot_mgr->rot_work_queue) { - pr_err("fail to create rot commit work queue\n"); - kfree(rot_mgr); - rot_mgr = NULL; - return -ENOMEM; - } - - return 0; -} - -static int mdss_mdp_rot_mgr_pipe_get_count(void) -{ - int count; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return -EINVAL; - } - - mutex_lock(&rot_mgr->pipe_lock); - count = rot_mgr->pipe_count; - mutex_unlock(&rot_mgr->pipe_lock); - - return count; -} - -static int mdss_mdp_rot_mgr_add_pipe(struct mdss_mdp_pipe *pipe) -{ - int i; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return -EINVAL; - } - - mutex_lock(&rot_mgr->pipe_lock); - for (i = 0; i < MAX_ROTATOR_PIPE_COUNT; i++) { - if (!rot_mgr->rot_pipes[i].pipe) - break; - } - if (i >= MAX_ROTATOR_PIPE_COUNT) { - pr_err("max rotation pipe allocated\n"); - mutex_unlock(&rot_mgr->pipe_lock); - return -EINVAL; - } - - rot_mgr->pipe_count++; - rot_mgr->rot_pipes[i].pipe = pipe; - rot_mgr->rot_pipes[i].active_session = NULL; - rot_mgr->rot_pipes[i].previous_session = NULL; - rot_mgr->rot_pipes[i].context_switched = true; - rot_mgr->rot_pipes[i].current_smp_size = 0; - rot_mgr->rot_pipes[i].wait_count = 0; - init_completion(&rot_mgr->rot_pipes[i].comp); - complete(&rot_mgr->rot_pipes[i].comp); - mutex_unlock(&rot_mgr->pipe_lock); - - return 0; -} - -/** - * try to acquire a pipe in the pool, following this strategy: - * first, prefer to look for a free pipe which was used in the previous - * instance, this is to avoid unnecessary pipe context switch. - * second, look for any free pipe available - * third, try to look for a pipe that is in use. To avoid the situation where - * multiple rotation sessions waiting for the same pipe, a wait-count is used - * to keep track of the number of sessions waiting on the pipe, so that we - * can do the load balancing. - */ -static struct mdss_mdp_rot_pipe *mdss_mdp_rot_mgr_acquire_pipe( - struct mdss_mdp_rotator_session *rot) -{ - struct mdss_mdp_rot_pipe *rot_pipe = NULL; - struct mdss_mdp_rot_pipe *free_rot_pipe = NULL; - struct mdss_mdp_rot_pipe *busy_rot_pipe = NULL; - int ret, i; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return NULL; - } - - mutex_lock(&rot_mgr->pipe_lock); - for (i = 0; i < MAX_ROTATOR_PIPE_COUNT; i++) { - rot_pipe = &rot_mgr->rot_pipes[i]; - - if (!rot_pipe->pipe) - continue; - - if (rot_pipe->active_session) { - if (!busy_rot_pipe || - (busy_rot_pipe->wait_count > - rot_pipe->wait_count)) - busy_rot_pipe = rot_pipe; - - continue; - } - - free_rot_pipe = rot_pipe; - - if (rot_pipe->previous_session == rot) - break; - } - - if (free_rot_pipe) { - free_rot_pipe->active_session = rot; - free_rot_pipe->context_switched = - (free_rot_pipe->previous_session != rot); - - rot_pipe = free_rot_pipe; - pr_debug("find a free pipe %p\n", rot_pipe->pipe); - } else { - rot_pipe = busy_rot_pipe; - if (rot_pipe) - pr_debug("find a busy pipe %p\n", rot_pipe->pipe); - } - - if (rot_pipe) - rot_pipe->wait_count++; - - mutex_unlock(&rot_mgr->pipe_lock); - - if (rot_pipe) { - ret = wait_for_completion_timeout(&rot_pipe->comp, - msecs_to_jiffies(PIPE_ACQUIRE_TIMEOUT_IN_MS)); - if (ret <= 0) { - pr_err("wait for pipe error = %d\n", ret); - mutex_lock(&rot_mgr->pipe_lock); - rot_pipe->wait_count--; - mutex_unlock(&rot_mgr->pipe_lock); - rot_pipe = NULL; - } else { - mutex_lock(&rot_mgr->pipe_lock); - rot_pipe->active_session = rot; - rot_pipe->context_switched = - (rot_pipe->previous_session != rot); - mutex_unlock(&rot_mgr->pipe_lock); - } - } - - return rot_pipe; -} - -static void mdss_mdp_rot_mgr_release_pipe(struct mdss_mdp_rot_pipe *pipe) -{ - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return; - } - - mutex_lock(&rot_mgr->pipe_lock); - pipe->previous_session = pipe->active_session; - pipe->active_session = NULL; - pipe->wait_count--; - complete(&pipe->comp); - mutex_unlock(&rot_mgr->pipe_lock); -} - -static int mdss_mdp_rot_mgr_remove_free_pipe(void) -{ - struct mdss_mdp_pipe *pipe; - struct mdss_mdp_mixer *mixer; - struct mdss_mdp_ctl *tmp; - int i; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return -EINVAL; - } - - for (i = 0; i < MAX_ROTATOR_PIPE_COUNT; i++) { - if (!rot_mgr->rot_pipes[i].pipe) - continue; - - if (!rot_mgr->rot_pipes[i].active_session) - break; - } - - if (i >= MAX_ROTATOR_PIPE_COUNT) { - pr_debug("cannot free any unused rotation pipe\n"); - return 0; - } - - pipe = rot_mgr->rot_pipes[i].pipe; - mixer = pipe->mixer_left; - mdss_mdp_pipe_destroy(pipe); - tmp = mdss_mdp_ctl_mixer_switch(mixer->ctl, - MDSS_MDP_WB_CTL_TYPE_BLOCK); - if (tmp) { - mixer = tmp->mixer_left; - mdss_mdp_block_mixer_destroy(mixer); - } - - rot_mgr->rot_pipes[i].pipe = NULL; - rot_mgr->rot_pipes[i].active_session = NULL; - rot_mgr->rot_pipes[i].previous_session = NULL; - rot_mgr->pipe_count--; - - return 0; -} - -static int mdss_mdp_rot_mgr_get_id(u32 *id) -{ - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return -EINVAL; - } - - mutex_lock(&rot_mgr->session_lock); - *id = rot_mgr->session_id | MDSS_MDP_ROT_SESSION_MASK; - rot_mgr->session_id++; - if (rot_mgr->session_id > MAX_ROTATOR_SESSION_ID) { - pr_debug("session id wrap around\n"); - rot_mgr->session_id = 0; - } - mutex_unlock(&rot_mgr->session_lock); - - return 0; -} - -static int mdss_mdp_rot_mgr_add_session(struct mdss_mdp_rotator_session *rot) -{ - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return -EINVAL; - } - - mutex_lock(&rot_mgr->session_lock); - list_add_tail(&rot->head, &rot_mgr->queue); - rot_mgr->session_count++; - mutex_unlock(&rot_mgr->session_lock); - - return 0; -} - -static struct mdss_mdp_rotator_session - *mdss_mdp_rot_mgr_remove_first(void) -{ - struct mdss_mdp_rotator_session *rot; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return NULL; - } - - mutex_lock(&rot_mgr->session_lock); - - rot = list_first_entry_or_null(&rot_mgr->queue, - struct mdss_mdp_rotator_session, head); - - if (rot) { - list_del_init(&rot->head); - rot_mgr->session_count--; - } - mutex_unlock(&rot_mgr->session_lock); - - return rot; -} - -static void mdss_mdp_rot_mgr_del_session(struct mdss_mdp_rotator_session *rot) -{ - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return; - } - - /* if head is empty means that session was already removed */ - if (list_empty(&rot->head)) - return; - - mutex_lock(&rot_mgr->session_lock); - list_del_init(&rot->head); - rot_mgr->session_count--; - - mutex_lock(&rot_mgr->pipe_lock); - if (rot_mgr->session_count < rot_mgr->pipe_count) - mdss_mdp_rot_mgr_remove_free_pipe(); - mutex_unlock(&rot_mgr->pipe_lock); - - mutex_unlock(&rot_mgr->session_lock); -} - - -static struct mdss_mdp_rotator_session - *mdss_mdp_rot_mgr_get_session(u32 session_id) -{ - struct mdss_mdp_rotator_session *rot = NULL; - - if (!rot_mgr) { - pr_err("rot manager not initialized\n"); - return NULL; - } - - mutex_lock(&rot_mgr->session_lock); - - if (!rot_mgr->session_count) { - mutex_unlock(&rot_mgr->session_lock); - return NULL; - } - - list_for_each_entry(rot, &rot_mgr->queue, head) { - if (rot->session_id == session_id) { - mutex_unlock(&rot_mgr->session_lock); - return rot; - } - } - - mutex_unlock(&rot_mgr->session_lock); - return NULL; -} - -static struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void) -{ - struct mdss_mdp_rotator_session *rot; - - rot = kzalloc(sizeof(struct mdss_mdp_rotator_session), GFP_KERNEL); - if (!rot) { - pr_err("error allocating rotator session\n"); - return NULL; - } - - mutex_init(&rot->lock); - INIT_LIST_HEAD(&rot->head); - INIT_LIST_HEAD(&rot->list); - mdss_mdp_rot_mgr_get_id(&rot->session_id); - - return rot; -} - -static void mdss_mdp_rotator_session_free( - struct mdss_mdp_rotator_session *rot) -{ - if (!list_empty(&rot->list)) - list_del(&rot->list); - - if (rot->rot_sync_pt_data) { - struct sync_timeline *obj; - - obj = (struct sync_timeline *) rot->rot_sync_pt_data->timeline; - sync_timeline_destroy(obj); - kfree(rot->rot_sync_pt_data); - } - kfree(rot); -} - - -struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get( - struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync) -{ - struct mdss_mdp_rotator_session *rot; - - rot = mdss_mdp_rot_mgr_get_session(buf_sync->session_id); - if (!rot) - return NULL; - - /** - * check if we can use a singleton sync pt, - * instead of creating one for each rotation. - */ - mutex_lock(&rot->lock); - if (!rot->rot_sync_pt_data) - rot->rot_sync_pt_data = mdss_mdp_rotator_sync_pt_create(rot); - if (rot->rot_sync_pt_data) - rot->use_sync_pt = true; - - mutex_unlock(&rot->lock); - - return rot->rot_sync_pt_data; -} - -static struct mdss_mdp_pipe *mdss_mdp_rotator_pipe_alloc(void) -{ - struct mdss_mdp_mixer *mixer; - struct mdss_mdp_pipe *pipe = NULL; - - mixer = mdss_mdp_block_mixer_alloc(); - if (!mixer) { - pr_debug("wb mixer alloc failed\n"); - return NULL; - } - - pipe = mdss_mdp_pipe_alloc_dma(mixer); - if (!pipe) { - mdss_mdp_block_mixer_destroy(mixer); - pr_debug("dma pipe allocation failed\n"); - return NULL; - } - - pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED; - - return pipe; -} - -static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot, - struct mdss_mdp_pipe *pipe) -{ - if (rot->busy) { - struct mdss_mdp_ctl *ctl = pipe->mixer_left->ctl; - mdss_mdp_display_wait4comp(ctl); - rot->busy = false; - if (ctl->shared_lock) - mutex_unlock(ctl->shared_lock); - } - - return 0; -} - -static int mdss_mdp_rotator_kickoff(struct mdss_mdp_ctl *ctl, - struct mdss_mdp_rotator_session *rot, - struct mdss_mdp_data *dst_data) -{ - int ret; - struct mdss_mdp_writeback_arg wb_args = { - .data = dst_data, - .priv_data = rot, - }; - - rot->busy = true; - ret = mdss_mdp_writeback_display_commit(ctl, &wb_args); - if (ret) { - rot->busy = false; - pr_err("problem with kickoff err=%d\n", ret); - } - - return ret; -} - - -/** - * __mdss_mdp_rotator_to_pipe() - setup pipe according to rotator session params - * @rot: Pointer to rotator session - * @pipe: Pointer to pipe driving structure - * - * After calling this the pipe structure will contain all parameters required - * to use rotator pipe. Note that this function assumes rotator pipe is idle. - */ -static int __mdss_mdp_rotator_to_pipe(struct mdss_mdp_rotator_session *rot, - struct mdss_mdp_rot_pipe *rot_pipe) -{ - struct mdss_mdp_pipe *pipe = NULL; - int ret; - int smp_count; - - pipe = rot_pipe->pipe; - - pipe->flags = rot->flags; - pipe->src_fmt = mdss_mdp_get_format_params(rot->format); - pipe->img_width = rot->img_width; - pipe->img_height = rot->img_height; - pipe->src = rot->src_rect; - pipe->dst = rot->src_rect; - pipe->dst.x = 0; - pipe->dst.y = 0; - pipe->frame_rate = rot->frame_rate; - pipe->params_changed++; - rot->params_changed = 0; - - smp_count = mdss_mdp_smp_calc_num_blocks(pipe); - if (smp_count != rot_pipe->current_smp_size) - mdss_mdp_smp_release(pipe); - - ret = mdss_mdp_smp_reserve(pipe); - if (ret) { - pr_debug("unable to mdss_mdp_smp_reserve rot data\n"); - return ret; - } - - rot_pipe->current_smp_size = smp_count; - return 0; -} - -static int mdss_mdp_rotator_queue_sub(struct mdss_mdp_rotator_session *rot, - struct mdss_mdp_rot_pipe *rot_pipe) -{ - struct mdss_mdp_data *src_data; - struct mdss_mdp_data *dst_data; - struct mdss_mdp_pipe *pipe; - struct mdss_mdp_ctl *orig_ctl, *rot_ctl; - int ret; - - src_data = &rot->src_buf; - dst_data = &rot->dst_buf; - - pipe = rot_pipe->pipe; - - if (!pipe->mixer_left) { - pr_debug("Mixer left is null\n"); - return -EINVAL; - } - - orig_ctl = pipe->mixer_left->ctl; - if (orig_ctl->shared_lock) - mutex_lock(orig_ctl->shared_lock); - - rot_ctl = mdss_mdp_ctl_mixer_switch(orig_ctl, - MDSS_MDP_WB_CTL_TYPE_BLOCK); - if (!rot_ctl) { - ret = -EINVAL; - goto error; - } else { - pipe->mixer_left = rot_ctl->mixer_left; - } - if (rot->params_changed || rot_ctl->mdata->mixer_switched || - rot_pipe->context_switched) { - ret = __mdss_mdp_rotator_to_pipe(rot, rot_pipe); - if (ret) { - pr_err("rotator session=%x to pipe=%d failed %d\n", - rot->session_id, pipe->num, ret); - goto error; - } - } - - ret = mdss_mdp_pipe_queue_data(pipe, src_data); - if (ret) { - pr_err("unable to queue rot data\n"); - goto error; - } - ATRACE_BEGIN("rotator_kickoff"); - ret = mdss_mdp_rotator_kickoff(rot_ctl, rot, dst_data); - ATRACE_END("rotator_kickoff"); - - return ret; -error: - if (orig_ctl->shared_lock) - mutex_unlock(orig_ctl->shared_lock); - return ret; -} - -static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work) -{ - struct mdss_mdp_rotator_session *rot; - int ret; - - rot = container_of(work, struct mdss_mdp_rotator_session, commit_work); - - mutex_lock(&rot->lock); - - ret = mdss_mdp_rotator_queue_helper(rot); - if (ret) - pr_err("rotator queue failed\n"); - - if (rot->rot_sync_pt_data) { - atomic_inc(&rot->rot_sync_pt_data->commit_cnt); - mdss_fb_signal_timeline(rot->rot_sync_pt_data); - } else { - pr_err("rot_sync_pt_data is NULL\n"); - } - - mutex_unlock(&rot->lock); -} - -static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create( - struct mdss_mdp_rotator_session *rot) -{ - struct msm_sync_pt_data *sync_pt_data; - char timeline_name[16]; - - rot->rot_sync_pt_data = kzalloc( - sizeof(struct msm_sync_pt_data), GFP_KERNEL); - sync_pt_data = rot->rot_sync_pt_data; - if (!sync_pt_data) - return NULL; - sync_pt_data->fence_name = "rot-fence"; - sync_pt_data->threshold = 1; - snprintf(timeline_name, sizeof(timeline_name), - "mdss_rot_%d", rot->session_id); - sync_pt_data->timeline = sw_sync_timeline_create(timeline_name); - if (sync_pt_data->timeline == NULL) { - kfree(rot->rot_sync_pt_data); - pr_err("%s: cannot create time line", __func__); - return NULL; - } else { - sync_pt_data->timeline_value = 0; - } - INIT_WORK(&rot->commit_work, - mdss_mdp_rotator_commit_wq_handler); - mutex_init(&sync_pt_data->sync_mutex); - return sync_pt_data; -} - -static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot) -{ - int ret; - struct mdss_mdp_rot_pipe *rot_pipe; - - pr_debug("rotator session=%x start\n", rot->session_id); - - if (rot->use_sync_pt) - mdss_fb_wait_for_fence(rot->rot_sync_pt_data); - - rot_pipe = mdss_mdp_rot_mgr_acquire_pipe(rot); - if (!rot_pipe) { - pr_err("fail to get pipe for session = %d\n", rot->session_id); - return -EINVAL; - } - - ret = mdss_mdp_rotator_queue_sub(rot, rot_pipe); - if (ret) { - pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id); - mdss_mdp_rot_mgr_release_pipe(rot_pipe); - return ret; - } - - mdss_mdp_rotator_busy_wait(rot, rot_pipe->pipe); - - mdss_mdp_rot_mgr_release_pipe(rot_pipe); - - return ret; -} - -static int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot) -{ - int ret = 0; - - if (rot->use_sync_pt) - queue_work(rot_mgr->rot_work_queue, &rot->commit_work); - else - ret = mdss_mdp_rotator_queue_helper(rot); - - pr_debug("rotator session=%x queue done\n", rot->session_id); - - return ret; -} - -static int mdss_mdp_calc_dnsc_factor(struct mdp_overlay *req, - struct mdss_mdp_rotator_session *rot) -{ - int ret = 0; - u16 src_w, src_h, dst_w, dst_h, bit; - src_w = req->src_rect.w; - src_h = req->src_rect.h; - - if (rot->flags & MDP_ROT_90) { - dst_w = req->dst_rect.h; - dst_h = req->dst_rect.w; - } else { - dst_w = req->dst_rect.w; - dst_h = req->dst_rect.h; - } - rot->dnsc_factor_w = 0; - rot->dnsc_factor_h = 0; - - if ((src_w != dst_w) || (src_h != dst_h)) { - if ((src_w % dst_w) || (src_h % dst_h)) { - ret = -EINVAL; - goto dnsc_err; - } - /* - * Validate that the calculated downscale - * factor is valid. Ensure that the factor - * is a number with a single bit enabled, - * no larger than 32 (2^5) as we support - * only power of 2 downscaling up to 32. - */ - rot->dnsc_factor_w = src_w / dst_w; - bit = fls(rot->dnsc_factor_w); - if ((rot->dnsc_factor_w & ~BIT(bit - 1)) || (bit > 5)) { - ret = -EINVAL; - goto dnsc_err; - } - rot->dnsc_factor_h = src_h / dst_h; - bit = fls(rot->dnsc_factor_h); - if ((rot->dnsc_factor_h & ~BIT(bit - 1)) || (bit > 5)) { - ret = -EINVAL; - goto dnsc_err; - } - } - -dnsc_err: - if (ret) { - pr_err("Invalid rotator downscale ratio %dx%d->%dx%d\n", - src_w, src_h, dst_w, dst_h); - rot->dnsc_factor_w = 0; - rot->dnsc_factor_h = 0; - } - return ret; -} - -static int mdss_mdp_rotator_config(struct msm_fb_data_type *mfd, - struct mdss_mdp_rotator_session *rot, - struct mdp_overlay *req, - struct mdss_mdp_format_params *fmt) -{ - struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - u32 bwc_enabled; - - /* keep only flags of interest to rotator */ - rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD | - MDP_SECURE_OVERLAY_SESSION); - - bwc_enabled = req->flags & MDP_BWC_EN; - if (bwc_enabled && !mdp5_data->mdata->has_bwc) { - pr_err("BWC is not supported in MDP version %x\n", - mdp5_data->mdata->mdp_rev); - rot->bwc_mode = 0; - } else { - rot->bwc_mode = bwc_enabled ? 1 : 0; - } - rot->format = fmt->format; - rot->img_width = req->src.width; - rot->img_height = req->src.height; - rot->src_rect.x = req->src_rect.x; - rot->src_rect.y = req->src_rect.y; - rot->src_rect.w = req->src_rect.w; - rot->src_rect.h = req->src_rect.h; - rot->frame_rate = req->frame_rate; - - if (mdp5_data->mdata->has_rot_dwnscale && - mdss_mdp_calc_dnsc_factor(req, rot)) { - pr_err("Error calculating dnsc_factor\n"); - return -EINVAL; - } - - if ((req->flags & MDP_DEINTERLACE) && - (rot->dnsc_factor_w || rot->dnsc_factor_h)) { - pr_err("Downscale not supported with interlaced content\n"); - return -EINVAL; - } - - if (req->flags & MDP_DEINTERLACE) { - rot->flags |= MDP_DEINTERLACE; - rot->src_rect.h /= 2; - rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2); - rot->src_rect.y &= ~1; - } - - rot->dst = rot->src_rect; - - /* - * by default, rotator output should be placed directly on - * output buffer address without any offset. - */ - rot->dst.x = 0; - rot->dst.y = 0; - - if (rot->flags & MDP_ROT_90) - swap(rot->dst.w, rot->dst.h); - - rot->req_data = *req; - - req->src.format = mdss_mdp_get_rotator_dst_format(req->src.format, - req->flags & MDP_ROT_90, req->flags & MDP_BWC_EN); - - rot->params_changed++; - - return 0; -} - -static int mdss_mdp_rotator_create(struct msm_fb_data_type *mfd, - struct mdp_overlay *req, - struct mdss_mdp_format_params *fmt) -{ - struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - struct mdss_mdp_rotator_session *rot; - struct mdss_mdp_pipe *pipe; - int pipe_count; - int ret; - - rot = mdss_mdp_rotator_session_alloc(); - if (!rot) { - pr_err("unable to allocate rotator session\n"); - return -ENOMEM; - } - - mutex_lock(&rot->lock); - - rot->pid = current->tgid; - list_add(&rot->list, &mdp5_data->rot_proc_list); - - req->id = rot->session_id; - - ret = mdss_mdp_rot_mgr_add_session(rot); - if (ret) { - pr_err("fail to add rotation to session mgr\n"); - goto rotator_new_setup_add_err; - } - - ret = mdss_mdp_rotator_config(mfd, rot, req, fmt); - if (ret) { - pr_err("fail to config the rotation object\n"); - goto rotator_new_setup_pipe_alloc_err; - } - - pipe_count = mdss_mdp_rot_mgr_pipe_get_count(); - - if (pipe_count < MAX_ROTATOR_PIPE_COUNT) { - pipe = mdss_mdp_rotator_pipe_alloc(); - if (pipe) { - mdss_mdp_rot_mgr_add_pipe(pipe); - pipe_count++; - } - } - - if (!pipe_count) { - pr_err("no pipe available for the rotation session\n"); - ret = -EBUSY; - goto rotator_new_setup_pipe_alloc_err; - } - - mutex_unlock(&rot->lock); - return 0; - -rotator_new_setup_pipe_alloc_err: - mdss_mdp_rot_mgr_del_session(rot); -rotator_new_setup_add_err: - mutex_unlock(&rot->lock); - mdss_mdp_rotator_session_free(rot); - return ret; -} - -static int mdss_mdp_rotator_config_ex(struct msm_fb_data_type *mfd, - struct mdp_overlay *req, - struct mdss_mdp_format_params *fmt) -{ - struct mdss_mdp_rotator_session *rot; - int ret; - - rot = mdss_mdp_rot_mgr_get_session(req->id); - if (!rot) { - pr_err("rotator session=%x not found\n", req->id); - return -ENODEV; - } - - /* if session hasn't changed, skip reconfiguration */ - if (!memcmp(req, &rot->req_data, sizeof(*req))) { - /* - * as per the IOCTL spec, every successful rotator setup - * needs to return corresponding destination format. - */ - req->src.format = mdss_mdp_get_rotator_dst_format( - req->src.format, req->flags & MDP_ROT_90, - req->flags & MDP_BWC_EN); - - return 0; - } - - flush_work(&rot->commit_work); - - mutex_lock(&rot->lock); - ret = mdss_mdp_rotator_config(mfd, rot, req, fmt); - mutex_unlock(&rot->lock); - return ret; -} - -int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd, - struct mdp_overlay *req) -{ - struct mdss_mdp_format_params *fmt; - int ret = 0; - - fmt = mdss_mdp_get_format_params(req->src.format); - if (!fmt) { - pr_err("invalid rot format %d\n", req->src.format); - return -EINVAL; - } - - ret = mdss_mdp_overlay_req_check(mfd, req, fmt); - if (ret) { - pr_err("rotator failed the overlay request check\n"); - return ret; - } - - if (req->id == MSMFB_NEW_REQUEST) { - ret = mdss_mdp_rotator_create(mfd, req, fmt); - } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) { - ret = mdss_mdp_rotator_config_ex(mfd, req, fmt); - } else { - pr_err("invalid rotator session id=%x\n", req->id); - return -EINVAL; - } - - return ret; -} - -static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot) -{ - pr_debug("finish rot id=%x\n", rot->session_id); - - flush_work(&rot->commit_work); - mdss_mdp_rot_mgr_del_session(rot); - - return 0; -} - -int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot) -{ - int rc; - - rc = mdss_mdp_rotator_finish(rot); - mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE); - mdss_mdp_data_free(&rot->dst_buf, true, DMA_FROM_DEVICE); - mdss_mdp_rotator_session_free(rot); - - return rc; -} - -int mdss_mdp_rotator_release_all(void) -{ - struct mdss_mdp_rotator_session *rot; - if (!rot_mgr) { - pr_debug("rot manager not initialized\n"); - return -EINVAL; - } - - while (true) { - rot = mdss_mdp_rot_mgr_remove_first(); - if (!rot) - break; - - mdss_mdp_rotator_release(rot); - } - - mutex_lock(&rot_mgr->pipe_lock); - if (rot_mgr->session_count < rot_mgr->pipe_count) - mdss_mdp_rot_mgr_remove_free_pipe(); - mutex_unlock(&rot_mgr->pipe_lock); - - return 0; -} - -int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd, - struct msmfb_overlay_data *req) -{ - struct mdss_mdp_rotator_session *rot; - struct mdp_layer_buffer buffer; - int ret; - u32 flgs; - struct mdss_mdp_data src_buf; - - rot = mdss_mdp_rot_mgr_get_session(req->id); - if (!rot) { - pr_err("invalid session id=%x\n", req->id); - return -ENOENT; - } - - memset(&src_buf, 0, sizeof(struct mdss_mdp_data)); - - flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION; - - flush_work(&rot->commit_work); - - mdss_iommu_ctrl(1); - mutex_lock(&rot->lock); - - buffer.width = rot->src_rect.w; - buffer.height = rot->src_rect.h; - buffer.format = rot->format; - ret = mdss_mdp_data_get_and_validate_size(&src_buf, - &req->data, 1, flgs, &mfd->pdev->dev, true, - DMA_TO_DEVICE, &buffer); - if (ret) { - pr_err("src_data pmem error\n"); - goto dst_buf_fail; - } - - ret = mdss_mdp_data_map(&src_buf, true, DMA_TO_DEVICE); - if (ret) { - pr_err("unable to map source buffer\n"); - mdss_mdp_data_free(&src_buf, true, DMA_TO_DEVICE); - goto dst_buf_fail; - } - mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE); - memcpy(&rot->src_buf, &src_buf, sizeof(struct mdss_mdp_data)); - - mdss_mdp_data_free(&rot->dst_buf, true, DMA_FROM_DEVICE); - buffer.width = rot->dst.w; - buffer.height = rot->dst.h; - buffer.format = mdss_mdp_get_rotator_dst_format(rot->format, - rot->flags & MDP_ROT_90, rot->bwc_mode); - - ret = mdss_mdp_data_get_and_validate_size(&rot->dst_buf, - &req->dst_data, 1, flgs, &mfd->pdev->dev, true, - DMA_FROM_DEVICE, &buffer); - if (ret) { - pr_err("dst_data pmem error\n"); - mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE); - goto dst_buf_fail; - } - - ret = mdss_mdp_data_map(&rot->dst_buf, true, DMA_FROM_DEVICE); - if (ret) { - pr_err("unable to map destination buffer\n"); - mdss_mdp_data_free(&rot->dst_buf, true, DMA_FROM_DEVICE); - mdss_mdp_data_free(&rot->src_buf, true, DMA_TO_DEVICE); - goto dst_buf_fail; - } - - ret = mdss_mdp_rotator_queue(rot); - - if (ret) - pr_err("rotator queue error session id=%x\n", req->id); - -dst_buf_fail: - mutex_unlock(&rot->lock); - mdss_iommu_ctrl(0); - return ret; -} - -int mdss_mdp_rotator_unset(int ndx) -{ - struct mdss_mdp_rotator_session *rot; - int ret = 0; - - rot = mdss_mdp_rot_mgr_get_session(ndx); - if (rot) - ret = mdss_mdp_rotator_release(rot); - - return ret; -} diff --git a/drivers/video/fbdev/msm/mdss_mdp_rotator.h b/drivers/video/fbdev/msm/mdss_mdp_rotator.h deleted file mode 100644 index ad1fef9a8d1d..000000000000 --- a/drivers/video/fbdev/msm/mdss_mdp_rotator.h +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#ifndef MDSS_MDP_ROTATOR_H -#define MDSS_MDP_ROTATOR_H - -#include <linux/types.h> - -#include "mdss_mdp.h" - -#define MDSS_MDP_ROT_SESSION_MASK 0x40000000 - -struct mdss_mdp_rotator_session { - u32 session_id; - u32 params_changed; - int pid; - - u32 format; - u32 flags; - - u16 img_width; - u16 img_height; - struct mdss_rect src_rect; - struct mdss_rect dst; - u32 dnsc_factor_w; - u32 dnsc_factor_h; - - u32 bwc_mode; - - struct mutex lock; - u8 busy; - u8 no_wait; - - struct mdss_mdp_data src_buf; - struct mdss_mdp_data dst_buf; - - bool use_sync_pt; - struct list_head head; - struct list_head list; - struct msm_sync_pt_data *rot_sync_pt_data; - struct work_struct commit_work; - - struct mdp_overlay req_data; - - u32 frame_rate; -}; - -static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format, u32 in_rot90, - u32 bwc) -{ - switch (in_format) { - case MDP_RGB_565: - case MDP_BGR_565: - if (in_rot90) - return MDP_RGB_888; - else - return in_format; - case MDP_RGBA_8888: - if (bwc) - return MDP_BGRA_8888; - else - return in_format; - case MDP_Y_CBCR_H2V2_VENUS: - case MDP_Y_CRCB_H2V2_VENUS: - case MDP_Y_CBCR_H2V2: - if (in_rot90) - return MDP_Y_CRCB_H2V2; - else - return in_format; - case MDP_Y_CB_CR_H2V2: - case MDP_Y_CR_CB_GH2V2: - case MDP_Y_CR_CB_H2V2: - return MDP_Y_CRCB_H2V2; - default: - return in_format; - } -} - -int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd, - struct mdp_overlay *req); -int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot); -int mdss_mdp_rotator_release_all(void); -struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get( - struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync); -int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd, - struct msmfb_overlay_data *req); -int mdss_mdp_rotator_unset(int ndx); - -int mdss_mdp_rot_mgr_init(void); - -#endif /* MDSS_MDP_ROTATOR_H */ diff --git a/drivers/video/fbdev/msm/mdss_mdp_wb.c b/drivers/video/fbdev/msm/mdss_mdp_wb.c deleted file mode 100644 index c9b69452d4a7..000000000000 --- a/drivers/video/fbdev/msm/mdss_mdp_wb.c +++ /dev/null @@ -1,952 +0,0 @@ -/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#define pr_fmt(fmt) "%s: " fmt, __func__ - -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/major.h> -#include <linux/module.h> -#include <linux/uaccess.h> -#include <linux/iommu.h> -#include <linux/switch.h> - -#include <linux/qcom_iommu.h> -#include <linux/msm_iommu_domains.h> - -#include "mdss_mdp.h" -#include "mdss_fb.h" -#include "mdss_wb.h" -#include "mdss_smmu.h" - -enum mdss_mdp_wb_state { - WB_OPEN, - WB_START, - WB_STOPING, - WB_STOP -}; - -struct mdss_mdp_wb { - u32 fb_ndx; - struct mutex lock; - struct list_head busy_queue; - struct list_head free_queue; - struct list_head register_queue; - wait_queue_head_t wait_q; - u32 state; - int is_secure; - struct mdss_mdp_pipe *secure_pipe; -}; - -enum mdss_mdp_wb_node_state { - REGISTERED, - IN_FREE_QUEUE, - IN_BUSY_QUEUE, - WITH_CLIENT, - WB_BUFFER_READY, -}; - -struct mdss_mdp_wb_data { - struct list_head registered_entry; - struct list_head active_entry; - struct msmfb_data buf_info; - struct mdss_mdp_data buf_data; - int state; - bool user_alloc; -}; - -static DEFINE_MUTEX(mdss_mdp_wb_buf_lock); -static struct mdss_mdp_wb mdss_mdp_wb_info; - -static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node); - -#ifdef DEBUG_WRITEBACK -/* for debugging: writeback output buffer to allocated memory */ -static inline -struct mdss_mdp_data *mdss_mdp_wb_debug_buffer(struct msm_fb_data_type *mfd) -{ - static struct ion_handle *ihdl; - static void *videomemory; - static ion_phys_addr_t mdss_wb_mem; - static struct mdss_mdp_data mdss_wb_buffer = { .num_planes = 1, }; - int rc; - - if (IS_ERR_OR_NULL(ihdl)) { - struct fb_info *fbi; - size_t img_size; - struct ion_client *iclient = mdss_get_ionclient(); - struct mdss_mdp_img_data *img = mdss_wb_buffer.p; - - fbi = mfd->fbi; - img_size = fbi->var.xres * fbi->var.yres * - fbi->var.bits_per_pixel / 8; - - - ihdl = ion_alloc(iclient, img_size, SZ_4K, - ION_HEAP(ION_SF_HEAP_ID), 0); - if (IS_ERR_OR_NULL(ihdl)) { - pr_err("unable to alloc fbmem from ion (%p)\n", ihdl); - return NULL; - } - - videomemory = ion_map_kernel(iclient, ihdl); - ion_phys(iclient, ihdl, &mdss_wb_mem, &img_size); - - if (is_mdss_iommu_attached()) { - int domain = MDSS_IOMMU_DOMAIN_UNSECURE; - rc = ion_map_iommu(iclient, ihdl, - mdss_smmu_get_domain_id(domain), - 0, SZ_4K, 0, - &img->addr, - (unsigned long *) &img->len, - 0, 0); - } else { - if (MDSS_LPAE_CHECK(mdss_wb_mem)) { - pr_err("Can't use phys mem %pa>4Gb w/o IOMMU\n", - &mdss_wb_mem); - ion_free(iclient, ihdl); - return NULL; - } - - img->addr = mdss_wb_mem; - img->len = img_size; - } - - pr_debug("ihdl=%p virt=%p phys=0x%pa iova=0x%pa size=%u\n", - ihdl, videomemory, &mdss_wb_mem, &img->addr, img_size); - } - return &mdss_wb_buffer; -} -#else -static inline -struct mdss_mdp_data *mdss_mdp_wb_debug_buffer(struct msm_fb_data_type *mfd) -{ - return NULL; -} -#endif - -/* - * mdss_mdp_get_secure() - Queries the secure status of a writeback session - * @mfd: Frame buffer device structure - * @enabled: Pointer to convey if session is secure - * - * This api enables an entity (userspace process, driver module, etc.) to - * query the secure status of a writeback session. The secure status is - * then supplied via a pointer. - */ -int mdss_mdp_wb_get_secure(struct msm_fb_data_type *mfd, uint8_t *enabled) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - if (!wb) - return -EINVAL; - *enabled = wb->is_secure; - return 0; -} - -/* - * mdss_mdp_set_secure() - Updates the secure status of a writeback session - * @mfd: Frame buffer device structure - * @enable: New secure status (1: secure, 0: non-secure) - * - * This api enables an entity to modify the secure status of a writeback - * session. If enable is 1, we allocate a secure pipe so that MDP is - * allowed to write back into the secure buffer. If enable is 0, we - * deallocate the secure pipe (if it was allocated previously). - */ -int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - struct mdss_mdp_pipe *pipe; - struct mdss_mdp_mixer *mixer; - - pr_debug("setting secure=%d\n", enable); - if ((enable != 1) && (enable != 0)) { - pr_err("Invalid enable value = %d\n", enable); - return -EINVAL; - } - - if (!ctl || !ctl->mdata) { - pr_err("%s : ctl is NULL", __func__); - return -EINVAL; - } - - if (!wb) { - pr_err("unable to start, writeback is not initialized\n"); - return -ENODEV; - } - - ctl->is_secure = enable; - wb->is_secure = enable; - - /* newer revisions don't require secure src pipe for secure session */ - if (ctl->mdata->mdp_rev > MDSS_MDP_HW_REV_100) - return 0; - - pipe = wb->secure_pipe; - - if (!enable) { - if (pipe) { - /* unset pipe */ - mdss_mdp_mixer_pipe_unstage(pipe, pipe->mixer_left); - mdss_mdp_pipe_destroy(pipe); - wb->secure_pipe = NULL; - } - return 0; - } - - mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT); - if (!mixer) { - pr_err("Unable to find mixer for wb\n"); - return -ENOENT; - } - - if (!pipe) { - pipe = mdss_mdp_pipe_alloc(mixer, MDSS_MDP_PIPE_TYPE_RGB, - NULL); - if (IS_ERR_OR_NULL(pipe)) - pipe = mdss_mdp_pipe_alloc(mixer, - MDSS_MDP_PIPE_TYPE_VIG, NULL); - if (IS_ERR_OR_NULL(pipe)) { - pr_err("Unable to get pipe to set secure session\n"); - return -ENOMEM; - } - - pipe->src_fmt = mdss_mdp_get_format_params(MDP_RGBA_8888); - - pipe->mfd = mfd; - pipe->mixer_stage = MDSS_MDP_STAGE_BASE; - wb->secure_pipe = pipe; - } - - pipe->img_height = mixer->height; - pipe->img_width = mixer->width; - pipe->src.x = 0; - pipe->src.y = 0; - pipe->src.w = pipe->img_width; - pipe->src.h = pipe->img_height; - pipe->dst = pipe->src; - - pipe->flags = (enable ? MDP_SECURE_OVERLAY_SESSION : 0); - pipe->params_changed++; - - pr_debug("setting secure pipe=%d flags=%x\n", pipe->num, pipe->flags); - - return mdss_mdp_pipe_queue_data(pipe, NULL); -} - -static int mdss_mdp_wb_init(struct msm_fb_data_type *mfd) -{ - struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - int rc = 0; - - mutex_lock(&mdss_mdp_wb_buf_lock); - if (wb == NULL) { - wb = &mdss_mdp_wb_info; - wb->fb_ndx = mfd->index; - mdp5_data->wb = wb; - } else if (mfd->index != wb->fb_ndx) { - pr_err("only one writeback intf supported at a time\n"); - rc = -EMLINK; - goto error; - } else { - pr_debug("writeback already initialized\n"); - } - - pr_debug("init writeback on fb%d\n", wb->fb_ndx); - - mutex_init(&wb->lock); - INIT_LIST_HEAD(&wb->free_queue); - INIT_LIST_HEAD(&wb->busy_queue); - INIT_LIST_HEAD(&wb->register_queue); - wb->state = WB_OPEN; - init_waitqueue_head(&wb->wait_q); - - mdp5_data->wb = wb; -error: - mutex_unlock(&mdss_mdp_wb_buf_lock); - return rc; -} - -static int mdss_mdp_wb_terminate(struct msm_fb_data_type *mfd) -{ - struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - - if (!wb) { - pr_err("unable to terminate, writeback is not initialized\n"); - return -ENODEV; - } - - pr_debug("terminate writeback\n"); - - mutex_lock(&mdss_mdp_wb_buf_lock); - mutex_lock(&wb->lock); - if (!list_empty(&wb->register_queue)) { - struct mdss_mdp_wb_data *node, *temp; - list_for_each_entry_safe(node, temp, &wb->register_queue, - registered_entry) { - mdss_mdp_wb_free_node(node); - list_del(&node->registered_entry); - kfree(node); - } - } - - wb->is_secure = false; - if (wb->secure_pipe) - mdss_mdp_pipe_destroy(wb->secure_pipe); - mutex_unlock(&wb->lock); - if (mdp5_data->ctl) - mdp5_data->ctl->is_secure = false; - mdp5_data->wb = NULL; - mutex_unlock(&mdss_mdp_wb_buf_lock); - - return 0; -} - -static int mdss_mdp_wb_start(struct msm_fb_data_type *mfd) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - - if (!wb) { - pr_err("unable to start, writeback is not initialized\n"); - return -ENODEV; - } - - mutex_lock(&wb->lock); - wb->state = WB_START; - mutex_unlock(&wb->lock); - wake_up(&wb->wait_q); - - return 0; -} - -static int mdss_mdp_wb_stop(struct msm_fb_data_type *mfd) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - - if (!wb) { - pr_err("unable to stop, writeback is not initialized\n"); - return -ENODEV; - } - - mutex_lock(&wb->lock); - wb->state = WB_STOPING; - mutex_unlock(&wb->lock); - wake_up(&wb->wait_q); - - return 0; -} - -static int mdss_mdp_wb_register_node(struct mdss_mdp_wb *wb, - struct mdss_mdp_wb_data *node) -{ - if (!node) { - pr_err("Invalid wb node\n"); - return -EINVAL; - } - node->state = REGISTERED; - list_add_tail(&node->registered_entry, &wb->register_queue); - - return 0; -} - -static struct mdss_mdp_wb_data *get_local_node(struct mdss_mdp_wb *wb, - struct msmfb_data *data) { - struct mdss_mdp_wb_data *node; - struct mdss_mdp_img_data *buf; - int ret; - - if (!data->iova) - return NULL; - - if (!list_empty(&wb->register_queue)) { - list_for_each_entry(node, &wb->register_queue, registered_entry) - if (node->buf_info.iova == data->iova) { - pr_debug("found node iova=%pa addr=%pa\n", - &data->iova, &node->buf_data.p[0].addr); - return node; - } - } - - node = kzalloc(sizeof(struct mdss_mdp_wb_data), GFP_KERNEL); - if (node == NULL) { - pr_err("out of memory\n"); - return NULL; - } - - node->buf_data.num_planes = 1; - node->buf_info = *data; - buf = &node->buf_data.p[0]; - buf->addr = (u32) (data->iova + data->offset); - buf->len = UINT_MAX; /* trusted source */ - if (wb->is_secure) - buf->flags |= MDP_SECURE_OVERLAY_SESSION; - ret = mdss_mdp_wb_register_node(wb, node); - if (IS_ERR_VALUE(ret)) { - pr_err("error registering wb node\n"); - kfree(node); - return NULL; - } - - pr_debug("register node iova=0x%pa addr=0x%pa\n", &data->iova, - &buf->addr); - - return node; -} - -static struct mdss_mdp_wb_data *get_user_node(struct msm_fb_data_type *mfd, - struct msmfb_data *data) -{ - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - struct mdp_layer_buffer buffer; - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - struct mdss_mdp_wb_data *node; - struct mdss_mdp_img_data *buf; - struct mdss_mdp_mixer *mixer; - u32 flags = 0; - int ret; - - if (!list_empty(&wb->register_queue)) { - struct ion_client *iclient = mdss_get_ionclient(); - struct ion_handle *ihdl; - - if (IS_ERR_OR_NULL(iclient)) { - pr_err("unable to get mdss ion client\n"); - return NULL; - } - ihdl = ion_import_dma_buf(iclient, data->memory_id); - if (IS_ERR_OR_NULL(ihdl)) { - pr_err("unable to import fd %d\n", data->memory_id); - return NULL; - } - /* only interested in ptr address, so we can free handle */ - ion_free(iclient, ihdl); - - list_for_each_entry(node, &wb->register_queue, registered_entry) - if ((node->buf_data.p[0].srcp_ihdl == ihdl) && - (node->buf_info.offset == data->offset)) { - pr_debug("found fd=%d hdl=%p off=%x addr=%pa\n", - data->memory_id, ihdl, - data->offset, - &node->buf_data.p[0].addr); - return node; - } - } - - node = kzalloc(sizeof(struct mdss_mdp_wb_data), GFP_KERNEL); - if (node == NULL) { - pr_err("out of memory\n"); - return NULL; - } - - node->user_alloc = true; - if (wb->is_secure) - flags |= MDP_SECURE_OVERLAY_SESSION; - - mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT); - if (!mixer) { - pr_err("Null mixer\n"); - goto register_fail; - } - buffer.width = mixer->width; - buffer.height = mixer->height; - buffer.format = ctl->dst_format; - ret = mdss_mdp_data_get_and_validate_size(&node->buf_data, - data, 1, flags, &mfd->pdev->dev, true, DMA_FROM_DEVICE, - &buffer); - if (IS_ERR_VALUE(ret)) { - pr_err("error getting buffer info\n"); - goto register_fail; - } - - ret = mdss_iommu_ctrl(1); - if (IS_ERR_VALUE(ret)) { - pr_err("IOMMU attach failed\n"); - goto fail_freebuf; - } - - ret = mdss_mdp_data_map(&node->buf_data, true, DMA_FROM_DEVICE); - if (IS_ERR_VALUE(ret)) { - pr_err("error mapping buffer\n"); - mdss_iommu_ctrl(0); - goto fail_freebuf; - } - - mdss_iommu_ctrl(0); - - memcpy(&node->buf_info, data, sizeof(*data)); - - ret = mdss_mdp_wb_register_node(wb, node); - if (IS_ERR_VALUE(ret)) { - pr_err("error registering wb node\n"); - goto fail_freebuf; - } - - buf = &node->buf_data.p[0]; - pr_debug("register node mem_id=%d offset=%u addr=0x%pa len=%lu\n", - data->memory_id, data->offset, &buf->addr, buf->len); - - return node; -fail_freebuf: - mdss_mdp_data_free(&node->buf_data, true, DMA_FROM_DEVICE); -register_fail: - kfree(node); - return NULL; -} - -static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node) -{ - struct mdss_mdp_img_data *buf; - - if (node->user_alloc) { - buf = &node->buf_data.p[0]; - - pr_debug("free user mem_id=%d ihdl=%p, offset=%u addr=0x%pa\n", - node->buf_info.memory_id, - buf->srcp_ihdl, - node->buf_info.offset, - &buf->addr); - - mdss_mdp_data_free(&node->buf_data, true, DMA_FROM_DEVICE); - node->user_alloc = false; - } -} - -static int mdss_mdp_wb_queue(struct msm_fb_data_type *mfd, - struct msmfb_data *data, int local) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - struct mdss_mdp_wb_data *node = NULL; - int ret = 0; - - if (!wb) { - pr_err("unable to queue, writeback is not initialized\n"); - return -ENODEV; - } - - pr_debug("fb%d queue\n", wb->fb_ndx); - - mutex_lock(&wb->lock); - if (local) - node = get_local_node(wb, data); - if (node == NULL) - node = get_user_node(mfd, data); - - if (!node) { - pr_err("memory not registered\n"); - ret = -ENOENT; - } else { - struct mdss_mdp_img_data *buf = &node->buf_data.p[0]; - - switch (node->state) { - case IN_FREE_QUEUE: - pr_err("node 0x%pa was already queueued before\n", - &buf->addr); - ret = -EINVAL; - break; - case IN_BUSY_QUEUE: - pr_err("node 0x%pa still in busy state\n", &buf->addr); - ret = -EBUSY; - break; - case WB_BUFFER_READY: - pr_debug("node 0x%pa re-queueded without dequeue\n", - &buf->addr); - list_del(&node->active_entry); - case WITH_CLIENT: - case REGISTERED: - list_add_tail(&node->active_entry, &wb->free_queue); - node->state = IN_FREE_QUEUE; - break; - default: - pr_err("Invalid node 0x%pa state %d\n", - &buf->addr, node->state); - ret = -EINVAL; - break; - } - } - mutex_unlock(&wb->lock); - - return ret; -} - -static int is_buffer_ready(struct mdss_mdp_wb *wb) -{ - int rc; - mutex_lock(&wb->lock); - rc = !list_empty(&wb->busy_queue) || (wb->state == WB_STOPING); - mutex_unlock(&wb->lock); - - return rc; -} - -static int mdss_mdp_wb_dequeue(struct msm_fb_data_type *mfd, - struct msmfb_data *data) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - struct mdss_mdp_wb_data *node = NULL; - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - int ret; - - if (!wb) { - pr_err("unable to dequeue, writeback is not initialized\n"); - return -ENODEV; - } - - if (!ctl) { - pr_err("unable to dequeue, ctl is not initialized\n"); - return -ENODEV; - } - - ret = wait_event_interruptible(wb->wait_q, is_buffer_ready(wb)); - if (ret) { - pr_err("failed to get dequeued buffer\n"); - return -ENOBUFS; - } - - mutex_lock(&wb->lock); - if (wb->state == WB_STOPING) { - pr_debug("wfd stopped\n"); - mdss_mdp_display_wait4comp(ctl); - wb->state = WB_STOP; - ret = -ENOBUFS; - } else if (!list_empty(&wb->busy_queue)) { - struct mdss_mdp_img_data *buf; - node = list_first_entry(&wb->busy_queue, - struct mdss_mdp_wb_data, - active_entry); - list_del(&node->active_entry); - node->state = WITH_CLIENT; - memcpy(data, &node->buf_info, sizeof(*data)); - - buf = &node->buf_data.p[0]; - pr_debug("found node addr=%pa len=%lu\n", &buf->addr, buf->len); - } else { - pr_debug("node is NULL, wait for next\n"); - ret = -ENOBUFS; - } - mutex_unlock(&wb->lock); - return ret; -} - -int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd, - struct mdss_mdp_commit_cb *commit_cb) -{ - struct mdss_mdp_wb *wb = mfd_to_wb(mfd); - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - struct mdss_mdp_wb_data *node = NULL; - int ret = 0; - struct mdss_mdp_writeback_arg wb_args; - - if (!ctl) { - pr_err("no ctl attached to fb=%d devicet\n", mfd->index); - return -ENODEV; - } - - if (!mdss_mdp_ctl_is_power_on(ctl)) - return 0; - - memset(&wb_args, 0, sizeof(wb_args)); - - mutex_lock(&mdss_mdp_wb_buf_lock); - if (wb) { - mutex_lock(&wb->lock); - /* in case of reinit of control path need to reset secure */ - if (ctl->play_cnt == 0) - mdss_mdp_wb_set_secure(ctl->mfd, wb->is_secure); - if (!list_empty(&wb->free_queue) && wb->state != WB_STOPING && - wb->state != WB_STOP) { - node = list_first_entry(&wb->free_queue, - struct mdss_mdp_wb_data, - active_entry); - list_del(&node->active_entry); - node->state = IN_BUSY_QUEUE; - wb_args.data = &node->buf_data; - } else { - pr_debug("unable to get buf wb state=%d\n", wb->state); - } - mutex_unlock(&wb->lock); - } - - if (wb_args.data == NULL) - wb_args.data = mdss_mdp_wb_debug_buffer(ctl->mfd); - - if (wb_args.data == NULL) { - pr_err("unable to get writeback buf ctl=%d\n", ctl->num); - /* drop buffer but don't return error */ - ret = 0; - mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_DONE); - goto kickoff_fail; - } - - ret = mdss_mdp_writeback_display_commit(ctl, &wb_args); - if (ret) { - pr_err("error on commit ctl=%d\n", ctl->num); - goto kickoff_fail; - } - - if (commit_cb) - commit_cb->commit_cb_fnc( - MDP_COMMIT_STAGE_SETUP_DONE, - commit_cb->data); - - mdss_mdp_display_wait4comp(ctl); - - if (commit_cb) - commit_cb->commit_cb_fnc(MDP_COMMIT_STAGE_READY_FOR_KICKOFF, - commit_cb->data); - - if (wb && node) { - mutex_lock(&wb->lock); - list_add_tail(&node->active_entry, &wb->busy_queue); - node->state = WB_BUFFER_READY; - mutex_unlock(&wb->lock); - wake_up(&wb->wait_q); - } - -kickoff_fail: - mutex_unlock(&mdss_mdp_wb_buf_lock); - return ret; -} - -int mdss_mdp_wb_set_mirr_hint(struct msm_fb_data_type *mfd, int hint) -{ - struct mdss_panel_data *pdata = NULL; - struct mdss_wb_ctrl *wb_ctrl = NULL; - - if (!mfd) { - pr_err("No panel data!\n"); - return -EINVAL; - } - - pdata = mfd->pdev->dev.platform_data; - wb_ctrl = container_of(pdata, struct mdss_wb_ctrl, pdata); - - switch (hint) { - case MDP_WRITEBACK_MIRROR_ON: - case MDP_WRITEBACK_MIRROR_PAUSE: - case MDP_WRITEBACK_MIRROR_RESUME: - case MDP_WRITEBACK_MIRROR_OFF: - pr_info("wfd state switched to %d\n", hint); - switch_set_state(&wb_ctrl->sdev, hint); - return 0; - default: - return -EINVAL; - } -} - -int mdss_mdp_wb_get_format(struct msm_fb_data_type *mfd, - struct mdp_mixer_cfg *mixer_cfg) -{ - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - - if (!ctl) { - pr_err("No panel data!\n"); - return -EINVAL; - } else { - mixer_cfg->writeback_format = ctl->dst_format; - } - - return 0; -} - -int mdss_mdp_wb_set_format(struct msm_fb_data_type *mfd, u32 dst_format) -{ - struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd); - - if (!ctl) { - pr_err("No panel data!\n"); - return -EINVAL; - } else if (dst_format >= MDP_IMGTYPE_LIMIT2) { - pr_err("Invalid dst format=%u\n", dst_format); - return -EINVAL; - } else { - ctl->dst_format = dst_format; - } - - pr_debug("wfd format %d\n", ctl->dst_format); - return 0; -} - -int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, - void *arg) -{ - struct msmfb_data data; - int ret = -ENOSYS, hint = 0; - - switch (cmd) { - case MSMFB_WRITEBACK_INIT: - ret = mdss_mdp_wb_init(mfd); - break; - case MSMFB_WRITEBACK_START: - ret = mdss_mdp_wb_start(mfd); - break; - case MSMFB_WRITEBACK_STOP: - ret = mdss_mdp_wb_stop(mfd); - break; - case MSMFB_WRITEBACK_QUEUE_BUFFER: - if (!copy_from_user(&data, arg, sizeof(data))) { - ret = mdss_mdp_wb_queue(mfd, &data, false); - ret = copy_to_user(arg, &data, sizeof(data)); - } else { - pr_err("wb queue buf failed on copy_from_user\n"); - ret = -EFAULT; - } - break; - case MSMFB_WRITEBACK_DEQUEUE_BUFFER: - if (!copy_from_user(&data, arg, sizeof(data))) { - ret = mdss_mdp_wb_dequeue(mfd, &data); - ret = copy_to_user(arg, &data, sizeof(data)); - } else { - pr_err("wb dequeue buf failed on copy_from_user\n"); - ret = -EFAULT; - } - break; - case MSMFB_WRITEBACK_TERMINATE: - ret = mdss_mdp_wb_terminate(mfd); - break; - case MSMFB_WRITEBACK_SET_MIRRORING_HINT: - if (!copy_from_user(&hint, arg, sizeof(hint))) { - ret = mdss_mdp_wb_set_mirr_hint(mfd, hint); - } else { - pr_err("set mirroring hint failed on copy_from_user\n"); - ret = -EFAULT; - } - break; - } - - return ret; -} - -int msm_fb_writeback_start(struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_start(mfd); -} -EXPORT_SYMBOL(msm_fb_writeback_start); - -int msm_fb_writeback_queue_buffer(struct fb_info *info, - struct msmfb_data *data) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_queue(mfd, data, true); -} -EXPORT_SYMBOL(msm_fb_writeback_queue_buffer); - -int msm_fb_writeback_dequeue_buffer(struct fb_info *info, - struct msmfb_data *data) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_dequeue(mfd, data); -} -EXPORT_SYMBOL(msm_fb_writeback_dequeue_buffer); - -int msm_fb_writeback_stop(struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_stop(mfd); -} -EXPORT_SYMBOL(msm_fb_writeback_stop); - -int msm_fb_writeback_init(struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_init(mfd); -} -EXPORT_SYMBOL(msm_fb_writeback_init); - -int msm_fb_writeback_terminate(struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_terminate(mfd); -} -EXPORT_SYMBOL(msm_fb_writeback_terminate); - -int msm_fb_get_iommu_domain(struct fb_info *info, int domain) -{ - int mdss_domain; - switch (domain) { - case MDP_IOMMU_DOMAIN_CP: - mdss_domain = MDSS_IOMMU_DOMAIN_SECURE; - break; - case MDP_IOMMU_DOMAIN_NS: - mdss_domain = MDSS_IOMMU_DOMAIN_UNSECURE; - break; - default: - pr_err("Invalid mdp iommu domain (%d)\n", domain); - return -EINVAL; - } - return mdss_smmu_get_domain_id(mdss_domain); -} -EXPORT_SYMBOL(msm_fb_get_iommu_domain); - -int msm_fb_writeback_set_secure(struct fb_info *info, int enable) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *) info->par; - - if (!mfd) - return -ENODEV; - - return mdss_mdp_wb_set_secure(mfd, enable); -} -EXPORT_SYMBOL(msm_fb_writeback_set_secure); - -/** - * msm_fb_writeback_iommu_ref() - Add/Remove vote on MDSS IOMMU being attached. - * @enable - true adds vote on MDSS IOMMU, false removes the vote. - * - * Call to vote on MDSS IOMMU being enabled. To ensure buffers are properly - * mapped to IOMMU context bank. - */ -int msm_fb_writeback_iommu_ref(struct fb_info *info, int enable) -{ - int ret; - - if (enable) { - ret = mdss_iommu_ctrl(1); - if (IS_ERR_VALUE(ret)) { - pr_err("IOMMU attach failed\n"); - return ret; - } - } else { - mdss_iommu_ctrl(0); - } - - return 0; -} -EXPORT_SYMBOL(msm_fb_writeback_iommu_ref); diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h index 1eb2e93e65a2..22e64f4272b9 100644 --- a/include/linux/msm_mdp.h +++ b/include/linux/msm_mdp.h @@ -1,7 +1,7 @@ /* include/linux/msm_mdp.h * * Copyright (C) 2007 Google Incorporated - * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014,2016 The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -17,20 +17,4 @@ #include <uapi/linux/msm_mdp.h> -int msm_fb_get_iommu_domain(struct fb_info *info, int domain); -/* get the framebuffer physical address information */ -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); -int msm_fb_writeback_queue_buffer(struct fb_info *info, - struct msmfb_data *data); -int msm_fb_writeback_dequeue_buffer(struct fb_info *info, - struct msmfb_data *data); -int msm_fb_writeback_stop(struct fb_info *info); -int msm_fb_writeback_terminate(struct fb_info *info); -int msm_fb_writeback_set_secure(struct fb_info *info, int enable); -int msm_fb_writeback_iommu_ref(struct fb_info *info, int enable); - #endif /*_MSM_MDP_H_*/ |
