diff options
Diffstat (limited to 'drivers/staging/msm/mdp_ppp_dq.c')
-rw-r--r-- | drivers/staging/msm/mdp_ppp_dq.c | 347 |
1 files changed, 0 insertions, 347 deletions
diff --git a/drivers/staging/msm/mdp_ppp_dq.c b/drivers/staging/msm/mdp_ppp_dq.c deleted file mode 100644 index 3a687c7a569..00000000000 --- a/drivers/staging/msm/mdp_ppp_dq.c +++ /dev/null @@ -1,347 +0,0 @@ -/* Copyright (c) 2009-2010, Code Aurora Forum. 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include "mdp.h" - -static boolean mdp_ppp_intr_flag = FALSE; -static boolean mdp_ppp_busy_flag = FALSE; - -/* Queue to keep track of the completed jobs for cleaning */ -static LIST_HEAD(mdp_ppp_djob_clnrq); -static DEFINE_SPINLOCK(mdp_ppp_djob_clnrq_lock); - -/* Worker to cleanup Display Jobs */ -static struct workqueue_struct *mdp_ppp_djob_clnr; - -/* Display Queue (DQ) for MDP PPP Block */ -static LIST_HEAD(mdp_ppp_dq); -static DEFINE_SPINLOCK(mdp_ppp_dq_lock); - -/* Current Display Job for MDP PPP */ -static struct mdp_ppp_djob *curr_djob; - -/* Track ret code for the last opeartion */ -static int mdp_ppp_ret_code; - -inline int mdp_ppp_get_ret_code(void) -{ - return mdp_ppp_ret_code; -} - -/* Push <Reg, Val> pair into DQ (if available) to later - * program the MDP PPP Block */ -inline void mdp_ppp_outdw(uint32_t addr, uint32_t data) -{ - if (curr_djob) { - - /* get the last node of the list. */ - struct mdp_ppp_roi_cmd_set *node = - list_entry(curr_djob->roi_cmd_list.prev, - struct mdp_ppp_roi_cmd_set, node); - - /* If a node is already full, create a new one and add it to - * the list (roi_cmd_list). - */ - if (node->ncmds == MDP_PPP_ROI_NODE_SIZE) { - node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), - GFP_KERNEL); - if (!node) { - printk(KERN_ERR - "MDP_PPP: not enough memory.\n"); - mdp_ppp_ret_code = -EINVAL; - return; - } - - /* no ROI commands initially */ - node->ncmds = 0; - - /* add one node to roi_cmd_list. */ - list_add_tail(&node->node, &curr_djob->roi_cmd_list); - } - - /* register ROI commands */ - node->cmd[node->ncmds].reg = addr; - node->cmd[node->ncmds].val = data; - node->ncmds++; - } else - /* program MDP PPP block now */ - outpdw((addr), (data)); -} - -/* Initialize DQ */ -inline void mdp_ppp_dq_init(void) -{ - mdp_ppp_djob_clnr = create_singlethread_workqueue("MDPDJobClnrThrd"); -} - -/* Release resources of a job (DJob). */ -static void mdp_ppp_del_djob(struct mdp_ppp_djob *job) -{ - struct mdp_ppp_roi_cmd_set *node, *tmp; - - /* release mem */ - mdp_ppp_put_img(job->p_src_file, job->p_dst_file); - - /* release roi_cmd_list */ - list_for_each_entry_safe(node, tmp, &job->roi_cmd_list, node) { - list_del(&node->node); - kfree(node); - } - - /* release job struct */ - kfree(job); -} - -/* Worker thread to reclaim resources once a display job is done */ -static void mdp_ppp_djob_cleaner(struct work_struct *work) -{ - struct mdp_ppp_djob *job; - - MDP_PPP_DEBUG_MSG("mdp ppp display job cleaner started \n"); - - /* cleanup display job */ - job = container_of(work, struct mdp_ppp_djob, cleaner.work); - if (likely(work && job)) - mdp_ppp_del_djob(job); -} - -/* Create a new Display Job (DJob) */ -inline struct mdp_ppp_djob *mdp_ppp_new_djob(void) -{ - struct mdp_ppp_djob *job; - struct mdp_ppp_roi_cmd_set *node; - - /* create a new djob */ - job = kmalloc(sizeof(struct mdp_ppp_djob), GFP_KERNEL); - if (!job) - return NULL; - - /* add the first node to curr_djob->roi_cmd_list */ - node = kmalloc(sizeof(struct mdp_ppp_roi_cmd_set), GFP_KERNEL); - if (!node) { - kfree(job); - return NULL; - } - - /* make this current djob container to keep track of the curr djob not - * used in the async path i.e. no sync needed - * - * Should not contain any references from the past djob - */ - BUG_ON(curr_djob); - curr_djob = job; - INIT_LIST_HEAD(&curr_djob->roi_cmd_list); - - /* no ROI commands initially */ - node->ncmds = 0; - INIT_LIST_HEAD(&node->node); - list_add_tail(&node->node, &curr_djob->roi_cmd_list); - - /* register this djob with the djob cleaner - * initializes 'work' data struct - */ - INIT_DELAYED_WORK(&curr_djob->cleaner, mdp_ppp_djob_cleaner); - INIT_LIST_HEAD(&curr_djob->entry); - - curr_djob->p_src_file = 0; - curr_djob->p_dst_file = 0; - - return job; -} - -/* Undo the effect of mdp_ppp_new_djob() */ -inline void mdp_ppp_clear_curr_djob(void) -{ - if (likely(curr_djob)) { - mdp_ppp_del_djob(curr_djob); - curr_djob = NULL; - } -} - -/* Cleanup dirty djobs */ -static void mdp_ppp_flush_dirty_djobs(void *cond) -{ - unsigned long flags; - struct mdp_ppp_djob *job; - - /* Flush the jobs from the djob clnr queue */ - while (cond && test_bit(0, (unsigned long *)cond)) { - - /* Until we are done with the cleanup queue */ - spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); - if (list_empty(&mdp_ppp_djob_clnrq)) { - spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); - break; - } - - MDP_PPP_DEBUG_MSG("flushing djobs ... loop \n"); - - /* Retrieve the job that needs to be cleaned */ - job = list_entry(mdp_ppp_djob_clnrq.next, - struct mdp_ppp_djob, entry); - list_del_init(&job->entry); - spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); - - /* Keep mem state coherent */ - msm_fb_ensure_mem_coherency_after_dma(job->info, &job->req, 1); - - /* Schedule jobs for cleanup - * A separate worker thread does this */ - queue_delayed_work(mdp_ppp_djob_clnr, &job->cleaner, - mdp_timer_duration); - } -} - -/* If MDP PPP engine is busy, wait until it is available again */ -void mdp_ppp_wait(void) -{ - unsigned long flags; - int cond = 1; - - /* keep flushing dirty djobs as long as MDP PPP engine is busy */ - mdp_ppp_flush_dirty_djobs(&mdp_ppp_busy_flag); - - /* block if MDP PPP engine is still busy */ - spin_lock_irqsave(&mdp_ppp_dq_lock, flags); - if (test_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) { - - /* prepare for the wakeup event */ - test_and_set_bit(0, (unsigned long *)&mdp_ppp_waiting); - INIT_COMPLETION(mdp_ppp_comp); - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); - - /* block uninterruptibly until available */ - MDP_PPP_DEBUG_MSG("waiting for mdp... \n"); - wait_for_completion_killable(&mdp_ppp_comp); - - /* if MDP PPP engine is still free, - * disable INT_MDP if enabled - */ - spin_lock_irqsave(&mdp_ppp_dq_lock, flags); - if (!test_bit(0, (unsigned long *)&mdp_ppp_busy_flag) && - test_and_clear_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) - mdp_disable_irq(MDP_PPP_TERM); - } - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); - - /* flush remaining dirty djobs, if any */ - mdp_ppp_flush_dirty_djobs(&cond); -} - -/* Program MDP PPP block to process this ROI */ -static void mdp_ppp_process_roi(struct list_head *roi_cmd_list) -{ - - /* program PPP engine with registered ROI commands */ - struct mdp_ppp_roi_cmd_set *node; - list_for_each_entry(node, roi_cmd_list, node) { - int i = 0; - for (; i < node->ncmds; i++) { - MDP_PPP_DEBUG_MSG("%d: reg: 0x%x val: 0x%x \n", - i, node->cmd[i].reg, node->cmd[i].val); - outpdw(node->cmd[i].reg, node->cmd[i].val); - } - } - - /* kickoff MDP PPP engine */ - MDP_PPP_DEBUG_MSG("kicking off mdp \n"); - outpdw(MDP_BASE + 0x30, 0x1000); -} - -/* Submit this display job to MDP PPP engine */ -static void mdp_ppp_dispatch_djob(struct mdp_ppp_djob *job) -{ - /* enable INT_MDP if disabled */ - if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_intr_flag)) - mdp_enable_irq(MDP_PPP_TERM); - - /* turn on PPP and CMD blocks */ - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - - /* process this ROI */ - mdp_ppp_process_roi(&job->roi_cmd_list); -} - -/* Enqueue this display job to be cleaned up later in "mdp_ppp_djob_done" */ -static inline void mdp_ppp_enqueue_djob(struct mdp_ppp_djob *job) -{ - unsigned long flags; - - spin_lock_irqsave(&mdp_ppp_dq_lock, flags); - list_add_tail(&job->entry, &mdp_ppp_dq); - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); -} - -/* First enqueue display job for cleanup and dispatch immediately - * if MDP PPP engine is free */ -void mdp_ppp_process_curr_djob(void) -{ - /* enqueue djob */ - mdp_ppp_enqueue_djob(curr_djob); - - /* dispatch now if MDP PPP engine is free */ - if (!test_and_set_bit(0, (unsigned long *)&mdp_ppp_busy_flag)) - mdp_ppp_dispatch_djob(curr_djob); - - /* done with the current djob */ - curr_djob = NULL; -} - -/* Called from mdp_isr - cleanup finished job and start with next - * if available else set MDP PPP engine free */ -void mdp_ppp_djob_done(void) -{ - struct mdp_ppp_djob *curr, *next; - unsigned long flags; - - /* dequeue current */ - spin_lock_irqsave(&mdp_ppp_dq_lock, flags); - curr = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, entry); - list_del_init(&curr->entry); - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); - - /* cleanup current - enqueue in the djob clnr queue */ - spin_lock_irqsave(&mdp_ppp_djob_clnrq_lock, flags); - list_add_tail(&curr->entry, &mdp_ppp_djob_clnrq); - spin_unlock_irqrestore(&mdp_ppp_djob_clnrq_lock, flags); - - /* grab next pending */ - spin_lock_irqsave(&mdp_ppp_dq_lock, flags); - if (!list_empty(&mdp_ppp_dq)) { - next = list_entry(mdp_ppp_dq.next, struct mdp_ppp_djob, - entry); - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); - - /* process next in the queue */ - mdp_ppp_process_roi(&next->roi_cmd_list); - } else { - /* no pending display job */ - spin_unlock_irqrestore(&mdp_ppp_dq_lock, flags); - - /* turn off PPP and CMD blocks - "in_isr" is TRUE */ - mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, TRUE); - - /* notify if waiting */ - if (test_and_clear_bit(0, (unsigned long *)&mdp_ppp_waiting)) - complete(&mdp_ppp_comp); - - /* set free */ - test_and_clear_bit(0, (unsigned long *)&mdp_ppp_busy_flag); - } -} |