Ejemplo n.º 1
0
static void mdp_set_vsync(unsigned long data)
{
	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)data;
	struct msm_fb_panel_data *pdata = NULL;

	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;

	vsync_mfd = mfd;
	init_timer(&mfd->vsync_resync_timer);

	if ((pdata) && (pdata->set_vsync_notifier == NULL))
		return;

	if ((mfd->panel_info.lcd.vsync_enable) && (mfd->panel_power_on)
	    && (!mfd->vsync_handler_pending)) {
		mfd->vsync_handler_pending = TRUE;
		if (!queue_work(mdp_vsync_wq, &mfd->vsync_resync_worker)) {
			MSM_FB_INFO
			    ("mdp_set_vsync: can't queue_work! -> needs to increase vsync_resync_timer_duration\n");
		}
	} else {
		MSM_FB_DEBUG
		    ("mdp_set_vsync failed!  EN:%d  PWR:%d  PENDING:%d\n",
		     mfd->panel_info.lcd.vsync_enable, mfd->panel_power_on,
		     mfd->vsync_handler_pending);
	}

	mutex_lock(&vsync_timer_lock);
	if (!timer_shutdown_flag) {
		mfd->vsync_resync_timer.function = mdp_set_vsync;
		mfd->vsync_resync_timer.data = data;
		mfd->vsync_resync_timer.expires =
			jiffies + mfd->panel_info.lcd.vsync_notifier_period;
		add_timer(&mfd->vsync_resync_timer);
	}
	mutex_unlock(&vsync_timer_lock);
}
Ejemplo n.º 2
0
void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
{

    DISP_LOCAL_LOG_EMERG("DISP mdp_pipe_kickoff S\n");

    /* complete all the writes before starting */
    wmb();

    /* kick off PPP engine */
    if (term == MDP_PPP_TERM) {
        if (mdp_debug[MDP_PPP_BLOCK])
            jiffies_to_timeval(jiffies, &mdp_ppp_timeval);

        /* let's turn on PPP block */
        mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_ON, FALSE);

        mdp_enable_irq(term);
        INIT_COMPLETION(mdp_ppp_comp);
        mdp_ppp_waiting = TRUE;
        outpdw(MDP_BASE + 0x30, 0x1000);
        wait_for_completion_killable(&mdp_ppp_comp);
        mdp_disable_irq(term);

        if (mdp_debug[MDP_PPP_BLOCK]) {
            struct timeval now;

            jiffies_to_timeval(jiffies, &now);
            mdp_ppp_timeval.tv_usec =
                now.tv_usec - mdp_ppp_timeval.tv_usec;
            MSM_FB_DEBUG("MDP-PPP: %d\n",
                         (int)mdp_ppp_timeval.tv_usec);
        }
    } else if (term == MDP_DMA2_TERM) {
        if (mdp_debug[MDP_DMA2_BLOCK]) {
            MSM_FB_DEBUG("MDP-DMA2: %d\n",
                         (int)mdp_dma2_timeval.tv_usec);
            jiffies_to_timeval(jiffies, &mdp_dma2_timeval);
        }
        /* DMA update timestamp */
        mdp_dma2_last_update_time = ktime_get_real();
        /* let's turn on DMA2 block */
#if 0
        mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
#endif
#ifdef CONFIG_FB_MSM_MDP22
        outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);/* start DMA */
#else
        mdp_lut_enable();

#ifdef CONFIG_FB_MSM_MDP40
        outpdw(MDP_BASE + 0x000c, 0x0);	/* start DMA */
#else
        outpdw(MDP_BASE + 0x0044, 0x0);	/* start DMA */
#endif
#endif
#ifdef CONFIG_FB_MSM_MDP40
    } else if (term == MDP_DMA_S_TERM) {
        mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
        outpdw(MDP_BASE + 0x0010, 0x0);	/* start DMA */
    } else if (term == MDP_DMA_E_TERM) {
        mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
        outpdw(MDP_BASE + 0x0014, 0x0);	/* start DMA */
    } else if (term == MDP_OVERLAY0_TERM) {
        mdp_pipe_ctrl(MDP_OVERLAY0_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
        mdp_lut_enable();
        outpdw(MDP_BASE + 0x0004, 0);
    } else if (term == MDP_OVERLAY1_TERM) {
        mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
        mdp_lut_enable();
        outpdw(MDP_BASE + 0x0008, 0);
    }
#else
    }
Ejemplo n.º 3
0
static void mdp_dma2_update_lcd(struct msm_fb_data_type *mfd)
{
	MDPIBUF *iBuf = &mfd->ibuf;
#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)\
	|| !defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
	int mddi_dest = FALSE;
	int cmd_mode = FALSE;
#endif
	uint32 outBpp = iBuf->bpp;
	uint32 dma2_cfg_reg;
	uint8 *src;
#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)\
	|| !defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
	uint32 mddi_ld_param;
	uint16 mddi_vdo_packet_reg;
#endif
#ifndef CONFIG_FB_MSM_MDP303
	struct msm_fb_panel_data *pdata =
	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
#endif
	uint32 ystride = mfd->fbi->fix.line_length;
#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)\
	|| !defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
	uint32 mddi_pkt_desc;
#endif

	dma2_cfg_reg = DMA_PACK_ALIGN_LSB |
		    DMA_OUT_SEL_AHB | DMA_IBUF_NONCONTIGUOUS;

#ifdef CONFIG_FB_MSM_MDP22
	dma2_cfg_reg |= DMA_PACK_TIGHT;
#endif

#ifdef CONFIG_FB_MSM_MDP30
	/*
	 * Software workaround:  On 7x25/7x27, the MDP will not
	 * respond if dma_w is 1 pixel.  Set the update width to
	 * 2 pixels and adjust the x offset if needed.
	 */
	if (iBuf->dma_w == 1) {
		iBuf->dma_w = 2;
		if (iBuf->dma_x == (iBuf->ibuf_width - 2))
			iBuf->dma_x--;
	}
#endif

#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)\
	|| !defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
	if (mfd->fb_imgType == MDP_BGR_565)
		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
	else if (mfd->fb_imgType == MDP_RGBA_8888)
		dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
	else
		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;

	if (outBpp == 4) {
		dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
		dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
	}

	if (outBpp == 2)
		dma2_cfg_reg |= DMA_IBUF_FORMAT_RGB565;

	mddi_ld_param = 0;
	mddi_vdo_packet_reg = mfd->panel_info.mddi.vdopkt;

	if ((mfd->panel_info.type == MDDI_PANEL) ||
	    (mfd->panel_info.type == EXT_MDDI_PANEL)) {
		dma2_cfg_reg |= DMA_OUT_SEL_MDDI;
		mddi_dest = TRUE;

		if (mfd->panel_info.type == MDDI_PANEL) {
			mdp_total_vdopkts++;
			if (mfd->panel_info.pdest == DISPLAY_1) {
				dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
				mddi_ld_param = 0;
#ifdef MDDI_HOST_WINDOW_WORKAROUND
				mddi_window_adjust(mfd, iBuf->dma_x,
						   iBuf->dma_w - 1, iBuf->dma_y,
						   iBuf->dma_h - 1);
#endif
			} else {
				dma2_cfg_reg |=
				    DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY;
				mddi_ld_param = 1;
#ifdef MDDI_HOST_WINDOW_WORKAROUND
				mddi_window_adjust(mfd, iBuf->dma_x,
						   iBuf->dma_w - 1, iBuf->dma_y,
						   iBuf->dma_h - 1);
#endif
			}
		} else {
			dma2_cfg_reg |= DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL;
			mddi_ld_param = 2;
		}
#ifdef CONFIG_FB_MSM_MDP303
	} else if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		cmd_mode = TRUE;
		dma2_cfg_reg |= DMA_OUT_SEL_DSI_CMD;
#endif
	} else {
		if (mfd->panel_info.pdest == DISPLAY_1) {
			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_PRIMARY;
			outp32(MDP_EBI2_LCD0, mfd->data_port_phys);
		} else {
			dma2_cfg_reg |= DMA_AHBM_LCD_SEL_SECONDARY;
			outp32(MDP_EBI2_LCD1, mfd->data_port_phys);
		}
	}
#else
	dma2_cfg_reg |= DMA_PACK_PATTERN_BGR;
	dma2_cfg_reg |= DMA_IBUF_C3ALPHA_EN;
	dma2_cfg_reg |= DMA_IBUF_FORMAT_xRGB8888_OR_ARGB8888;
	dma2_cfg_reg |= DMA_OUT_SEL_DSI_CMD;
#endif

	src = (uint8 *) iBuf->buf;
	/* starting input address */
	src += iBuf->dma_x * outBpp + iBuf->dma_y * ystride;

	mdp_curr_dma2_update_width = iBuf->dma_w;
	mdp_curr_dma2_update_height = iBuf->dma_h;

	/* MDP cmd block enable */
	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);

#ifdef CONFIG_FB_MSM_MDP22
	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0184,
			(iBuf->dma_h << 16 | iBuf->dma_w));
	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0188, src);
	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x018C, ystride);
#else
#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)
	if (cmd_mode)
		MDP_OUTP(MDP_BASE + 0x90004,
			(mfd->panel_info.yres << 16 | mfd->panel_info.xres));
	else
		MDP_OUTP(MDP_BASE + 0x90004, (iBuf->dma_h << 16 | iBuf->dma_w));
#else
	MDP_OUTP(MDP_BASE + 0x90004,
		(mfd->panel_info.yres << 16 | mfd->panel_info.xres));
#endif

	MDP_OUTP(MDP_BASE + 0x90008, src);
	MDP_OUTP(MDP_BASE + 0x9000c, ystride);
#endif

#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)\
	|| !defined(CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888)
	if (mfd->panel_info.bpp == 18) {
		mddi_pkt_desc = MDDI_VDO_PACKET_DESC;
		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
	} else if (mfd->panel_info.bpp == 24) {
		mddi_pkt_desc = MDDI_VDO_PACKET_DESC_24;
		dma2_cfg_reg |= DMA_DSTC0G_8BITS |      /* 888 24BPP */
			DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
	} else {
		mddi_pkt_desc = MDDI_VDO_PACKET_DESC_16;
		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
	}
#else
	dma2_cfg_reg |= DMA_DSTC0G_8BITS |      /* 888 24BPP */
		DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
#endif

#ifndef CONFIG_FB_MSM_MDP303

	if (mddi_dest) {
#ifdef CONFIG_FB_MSM_MDP22
		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0194,
			 (iBuf->dma_y << 16) | iBuf->dma_x);
		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0, mddi_ld_param);
		MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4,
			 (mddi_pkt_desc << 16) | mddi_vdo_packet_reg);
#else
		MDP_OUTP(MDP_BASE + 0x90010, (iBuf->dma_y << 16) | iBuf->dma_x);
		MDP_OUTP(MDP_BASE + 0x00090, mddi_ld_param);
		MDP_OUTP(MDP_BASE + 0x00094,
			 (mddi_pkt_desc << 16) | mddi_vdo_packet_reg);
#endif
	} else {
		/* setting EBI2 LCDC write window */
		pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
				iBuf->dma_h);
	}
#else
#if !defined(CONFIG_FB_MSM_MIPI_ORISE_CMD_FWVGA_PT)
	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
#else
	{
		/* dma_p = 0, dma_s = 1 */
		 MDP_OUTP(MDP_BASE + 0xF1000, 0x10);
		 /* enable dsi trigger on dma_p */
		 MDP_OUTP(MDP_BASE + 0xF1004, 0x01);
#endif
	}
#endif

	/* dma2 config register */
#ifdef MDP_HW_VSYNC
	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);

	if ((mfd->use_mdp_vsync) &&
	    (mfd->ibuf.vsync_enable) && (mfd->panel_info.lcd.vsync_enable)) {
		uint32 start_y;

		if (vsync_start_y_adjust <= iBuf->dma_y)
			start_y = iBuf->dma_y - vsync_start_y_adjust;
		else
			start_y =
			    (mfd->total_lcd_lines - 1) - (vsync_start_y_adjust -
							  iBuf->dma_y);

		/*
		 * MDP VSYNC clock must be On by now so, we don't have to
		 * re-enable it
		 */
		MDP_OUTP(MDP_BASE + 0x210, start_y);
		MDP_OUTP(MDP_BASE + 0x20c, 1);	/* enable prim vsync */
	} else {
		MDP_OUTP(MDP_BASE + 0x20c, 0);	/* disable prim vsync */
	}
#else
#ifdef CONFIG_FB_MSM_MDP22
	MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0180, dma2_cfg_reg);
#else
	MDP_OUTP(MDP_BASE + 0x90000, dma2_cfg_reg);
#endif
#endif /* MDP_HW_VSYNC */

	/* MDP cmd block disable */
	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}

static ktime_t vt = { 0 };
int mdp_usec_diff_threshold = 100;
int mdp_expected_usec_wait;

enum hrtimer_restart mdp_dma2_vsync_hrtimer_handler(struct hrtimer *ht)
{
	struct msm_fb_data_type *mfd = NULL;

	mfd = container_of(ht, struct msm_fb_data_type, dma_hrtimer);

	mdp_pipe_kickoff(MDP_DMA2_TERM, mfd);

	if (msm_fb_debug_enabled) {
		ktime_t t;
		int usec_diff;
		int actual_wait;

		t = ktime_get_real();

		actual_wait = ktime_to_us(ktime_sub(t, vt));
		usec_diff = actual_wait - mdp_expected_usec_wait;

		if ((mdp_usec_diff_threshold < usec_diff) || (usec_diff < 0))
			MSM_FB_DEBUG
			    ("HRT Diff = %d usec Exp=%d usec  Act=%d usec\n",
			     usec_diff, mdp_expected_usec_wait, actual_wait);
	}

	return HRTIMER_NORESTART;
}


#ifdef CONFIG_FB_MSM_MDP303
static int busy_wait_cnt;

void	mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
{
	unsigned long flag;
	int need_wait = 0;

#ifdef DSI_CLK_CTRL
	mod_timer(&dsi_clock_timer, jiffies + HZ); /* one second */
#endif

	spin_lock_irqsave(&mdp_spin_lock, flag);
#ifdef DSI_CLK_CTRL

	spin_lock_bh(&dsi_clk_lock);
	if (mipi_dsi_clk_on == 0)
		mipi_dsi_turn_on_clks();
	spin_unlock_bh(&dsi_clk_lock);
#endif

	if (mfd->dma->busy == TRUE) {
		if (busy_wait_cnt == 0)
			INIT_COMPLETION(mfd->dma->comp);
		busy_wait_cnt++;
		need_wait++;
	}
	spin_unlock_irqrestore(&mdp_spin_lock, flag);

	if (need_wait) {
		/* wait until DMA finishes the current job */
/* FIH-SW-MM-VH-DISPLAY-JB01*[ */
		if (!wait_for_completion_timeout(&mfd->dma->comp, 1*HZ)) {
			printk(KERN_ALERT "[DISPLAY] %s: Wait DMA finish timeout!\n", __func__);
			mfd->dma->busy= FALSE;
			mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
			complete(&mfd->dma->comp);
		}
/* FIH-SW-MM-VH-DISPLAY-JB01*] */
	}
}
Ejemplo n.º 4
0
void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
		   boolean isr)
{
	boolean mdp_all_blocks_off = TRUE;
	int i;
	unsigned long flag;

	spin_lock_irqsave(&mdp_spin_lock, flag);
	if (MDP_BLOCK_POWER_ON == state) {
		mdp_block_power_cnt[block]++;

		if (MDP_DMA2_BLOCK == block)
			mdp_in_processing = TRUE;
	} else {
		mdp_block_power_cnt[block]--;

		if (mdp_block_power_cnt[block] < 0) {
			//////////////////////////////////////////////////////////////////
			// Master has to serve a request to power off MDP always
			// It also has a timer to power off.
			// So, in case of timer expires first and DMA2 finishes later,
			// master has to power off two times
			//
			// There shouldn't be multiple power-off request for other blocks
			//////////////////////////////////////////////////////////////////
			if (block != MDP_MASTER_BLOCK) {
				MSM_FB_INFO
				    ("mdp_block_power_cnt[block=%d] multiple power-off request\n",
				     block);
			}
			mdp_block_power_cnt[block] = 0;
		}

		if (MDP_DMA2_BLOCK == block)
			mdp_in_processing = FALSE;
	}
	spin_unlock_irqrestore(&mdp_spin_lock, flag);

	/////////////////////////////////////////////////////////////////
	// If it's in isr, we send our request to workqueue.
	// Otherwise, processing happens in the current context
	/////////////////////////////////////////////////////////////////
	if (isr) {
		////////////////////////////////////////////////////
		//checking all blocks power state
		////////////////////////////////////////////////////
		for (i = 0; i < MDP_MAX_BLOCK; i++) {
			if (mdp_block_power_cnt[i] > 0)
				mdp_all_blocks_off = FALSE;
		}
		////////////////////////////////////////////////////

		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
			//send workqueue to turn off mdp power
			queue_delayed_work(mdp_pipe_ctrl_wq,
					   &mdp_pipe_ctrl_worker,
					   mdp_timer_duration);
		}
	} else {
		down(&mdp_pipe_ctrl_mutex);
		////////////////////////////////////////////////////
		//checking all blocks power state
		////////////////////////////////////////////////////
		for (i = 0; i < MDP_MAX_BLOCK; i++) {
			if (mdp_block_power_cnt[i] > 0)
				mdp_all_blocks_off = FALSE;
		}
		////////////////////////////////////////////////////

		//find out whether a delayable work item is currently pending
		if (delayed_work_pending(&mdp_pipe_ctrl_worker)) {
			// try to cancel the current work ***
			// if it fails to stop (which means del_timer can't delete it
			// from the list, it's about to expire and run), we have to
			// let it run.  queue_delayed_work won't accept the next job
			// which is same as queue_delayed_work(mdp_timer_duration = 0)

			cancel_delayed_work(&mdp_pipe_ctrl_worker);
		}

		if ((mdp_all_blocks_off) && (mdp_current_clk_on)) {
			if (block == MDP_MASTER_BLOCK) {
				mdp_current_clk_on = FALSE;
				// turn off MDP clk
				if (mdp_clk != NULL) {
					clk_disable(mdp_clk);
					disable_irq(INT_MDP);
					MSM_FB_DEBUG("MDP CLK OFF\n");
				}

			} else {
				//send workqueue to turn off mdp power
				queue_delayed_work(mdp_pipe_ctrl_wq,
						   &mdp_pipe_ctrl_worker,
						   mdp_timer_duration);
			}
		} else if ((!mdp_all_blocks_off) && (!mdp_current_clk_on)) {
			mdp_current_clk_on = TRUE;
			// turn on MDP clk
			if (mdp_clk != NULL) {
				enable_irq(INT_MDP);
				clk_enable(mdp_clk);
				MSM_FB_DEBUG("MDP CLK ON\n");
			}
		}
		up(&mdp_pipe_ctrl_mutex);
	}
}