summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbdev/msm/Makefile1
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c30
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h39
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c21
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_rotator.c1092
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_rotator.h100
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_wb.c952
-rw-r--r--include/linux/msm_mdp.h18
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_*/