linux/drivers/staging/msm/mdp4_overlay_mddi.c
<<
>>
Prefs
   1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
   2 *
   3 * This program is free software; you can redistribute it and/or modify
   4 * it under the terms of the GNU General Public License version 2 and
   5 * only version 2 as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 *
  12 * You should have received a copy of the GNU General Public License
  13 * along with this program; if not, write to the Free Software
  14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15 * 02110-1301, USA.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/kernel.h>
  20#include <linux/sched.h>
  21#include <linux/time.h>
  22#include <linux/init.h>
  23#include <linux/interrupt.h>
  24#include <linux/hrtimer.h>
  25#include <linux/delay.h>
  26#include <mach/hardware.h>
  27#include <linux/io.h>
  28
  29#include <asm/system.h>
  30#include <asm/mach-types.h>
  31#include <linux/semaphore.h>
  32#include <linux/spinlock.h>
  33
  34#include <linux/fb.h>
  35
  36#include "mdp.h"
  37#include "msm_fb.h"
  38#include "mdp4.h"
  39
  40static struct mdp4_overlay_pipe *mddi_pipe;
  41static struct mdp4_overlay_pipe *pending_pipe;
  42static struct msm_fb_data_type *mddi_mfd;
  43
  44#define WHOLESCREEN
  45
  46void mdp4_overlay_update_lcd(struct msm_fb_data_type *mfd)
  47{
  48        MDPIBUF *iBuf = &mfd->ibuf;
  49        uint8 *src;
  50        int bpp, ptype;
  51        uint32 format;
  52        uint32 mddi_ld_param;
  53        uint16 mddi_vdo_packet_reg;
  54        struct mdp4_overlay_pipe *pipe;
  55
  56        if (mfd->key != MFD_KEY)
  57                return;
  58
  59        mddi_mfd = mfd;         /* keep it */
  60
  61        bpp = iBuf->bpp;
  62
  63        if (bpp == 2)
  64                format = MDP_RGB_565;
  65        else if (bpp == 3)
  66                format = MDP_RGB_888;
  67        else
  68                format = MDP_ARGB_8888;
  69
  70        /* MDP cmd block enable */
  71        mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
  72
  73        if (mddi_pipe == NULL) {
  74                ptype = mdp4_overlay_format2type(format);
  75                pipe = mdp4_overlay_pipe_alloc();
  76                pipe->pipe_type = ptype;
  77                /* use RGB1 pipe */
  78                pipe->pipe_num  = OVERLAY_PIPE_RGB1;
  79                pipe->mixer_num  = MDP4_MIXER0;
  80                pipe->src_format = format;
  81                mdp4_overlay_format2pipe(pipe);
  82
  83                mddi_pipe = pipe; /* keep it */
  84
  85                mddi_ld_param = 0;
  86                mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;
  87
  88                if (mfd->panel_info.type == MDDI_PANEL) {
  89                        if (mfd->panel_info.pdest == DISPLAY_1)
  90                                mddi_ld_param = 0;
  91                        else
  92                                mddi_ld_param = 1;
  93                } else {
  94                        mddi_ld_param = 2;
  95                }
  96
  97                MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
  98                MDP_OUTP(MDP_BASE + 0x00094,
  99                         (MDDI_VDO_PACKET_DESC << 16) | mddi_vdo_packet_reg);
 100        } else {
 101                pipe = mddi_pipe;
 102        }
 103
 104
 105        src = (uint8 *) iBuf->buf;
 106
 107#ifdef WHOLESCREEN
 108        {
 109                struct fb_info *fbi;
 110
 111                fbi = mfd->fbi;
 112                pipe->src_height = fbi->var.yres;
 113                pipe->src_width = fbi->var.xres;
 114                pipe->src_h = fbi->var.yres;
 115                pipe->src_w = fbi->var.xres;
 116                pipe->src_y = 0;
 117                pipe->src_x = 0;
 118                pipe->dst_h = fbi->var.yres;
 119                pipe->dst_w = fbi->var.xres;
 120                pipe->dst_y = 0;
 121                pipe->dst_x = 0;
 122                pipe->srcp0_addr = (uint32)src;
 123                pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
 124        }
 125
 126#else
 127        if (mdp4_overlay_active(MDP4_MIXER0)) {
 128                struct fb_info *fbi;
 129
 130                fbi = mfd->fbi;
 131                pipe->src_height = fbi->var.yres;
 132                pipe->src_width = fbi->var.xres;
 133                pipe->src_h = fbi->var.yres;
 134                pipe->src_w = fbi->var.xres;
 135                pipe->src_y = 0;
 136                pipe->src_x = 0;
 137                pipe->dst_h = fbi->var.yres;
 138                pipe->dst_w = fbi->var.xres;
 139                pipe->dst_y = 0;
 140                pipe->dst_x = 0;
 141                pipe->srcp0_addr = (uint32) src;
 142                pipe->srcp0_ystride = fbi->var.xres_virtual * bpp;
 143        } else {
 144                /* starting input address */
 145                src += (iBuf->dma_x + iBuf->dma_y * iBuf->ibuf_width) * bpp;
 146
 147                pipe->src_height = iBuf->dma_h;
 148                pipe->src_width = iBuf->dma_w;
 149                pipe->src_h = iBuf->dma_h;
 150                pipe->src_w = iBuf->dma_w;
 151                pipe->src_y = 0;
 152                pipe->src_x = 0;
 153                pipe->dst_h = iBuf->dma_h;
 154                pipe->dst_w = iBuf->dma_w;
 155                pipe->dst_y = iBuf->dma_y;
 156                pipe->dst_x = iBuf->dma_x;
 157                pipe->srcp0_addr = (uint32) src;
 158                pipe->srcp0_ystride = iBuf->ibuf_width * bpp;
 159        }
 160#endif
 161
 162        pipe->mixer_stage  = MDP4_MIXER_STAGE_BASE;
 163
 164        mdp4_overlay_rgb_setup(pipe);
 165
 166        mdp4_mixer_stage_up(pipe);
 167
 168        mdp4_overlayproc_cfg(pipe);
 169
 170        mdp4_overlay_dmap_xy(pipe);
 171
 172        mdp4_overlay_dmap_cfg(mfd, 0);
 173
 174        /* MDP cmd block disable */
 175        mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 176
 177}
 178
 179/*
 180 * mdp4_overlay0_done_mddi: called from isr
 181 */
 182void mdp4_overlay0_done_mddi()
 183{
 184        if (pending_pipe)
 185                complete(&pending_pipe->comp);
 186}
 187
 188void mdp4_mddi_overlay_restore(void)
 189{
 190        /* mutex holded by caller */
 191        mdp4_overlay_update_lcd(mddi_mfd);
 192        mdp4_mddi_overlay_kickoff(mddi_mfd, mddi_pipe);
 193}
 194
 195void mdp4_mddi_overlay_kickoff(struct msm_fb_data_type *mfd,
 196                                struct mdp4_overlay_pipe *pipe)
 197{
 198#ifdef MDP4_NONBLOCKING
 199        unsigned long flag;
 200
 201        spin_lock_irqsave(&mdp_spin_lock, flag);
 202        if (mfd->dma->busy == TRUE) {
 203                INIT_COMPLETION(pipe->comp);
 204                pending_pipe = pipe;
 205        }
 206        spin_unlock_irqrestore(&mdp_spin_lock, flag);
 207
 208        if (pending_pipe != NULL) {
 209                /* wait until DMA finishes the current job */
 210                wait_for_completion_killable(&pipe->comp);
 211                pending_pipe = NULL;
 212        }
 213        down(&mfd->sem);
 214        mdp_enable_irq(MDP_OVERLAY0_TERM);
 215        mfd->dma->busy = TRUE;
 216        /* start OVERLAY pipe */
 217        mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
 218        up(&mfd->sem);
 219#else
 220        down(&mfd->sem);
 221        mdp_enable_irq(MDP_OVERLAY0_TERM);
 222        mfd->dma->busy = TRUE;
 223        INIT_COMPLETION(pipe->comp);
 224        pending_pipe = pipe;
 225
 226        /* start OVERLAY pipe */
 227        mdp_pipe_kickoff(MDP_OVERLAY0_TERM, mfd);
 228        up(&mfd->sem);
 229
 230        /* wait until DMA finishes the current job */
 231        wait_for_completion_killable(&pipe->comp);
 232        mdp_disable_irq(MDP_OVERLAY0_TERM);
 233#endif
 234
 235}
 236
 237void mdp4_mddi_overlay(struct msm_fb_data_type *mfd)
 238{
 239        mutex_lock(&mfd->dma->ov_mutex);
 240
 241        if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
 242                mdp4_overlay_update_lcd(mfd);
 243
 244                mdp4_mddi_overlay_kickoff(mfd, mddi_pipe);
 245
 246        /* signal if pan function is waiting for the update completion */
 247                if (mfd->pan_waiting) {
 248                        mfd->pan_waiting = FALSE;
 249                        complete(&mfd->pan_comp);
 250                }
 251        }
 252
 253        mutex_unlock(&mfd->dma->ov_mutex);
 254}
 255