Exemplo n.º 1
0
void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
{
	/*---------------------------------------------------------
	// kick off PPP engine
	/---------------------------------------------------------*/
	if (term == MDP_PPP_TERM) {
		if (mdp_debug[MDP_PPP_BLOCK]) {
			jiffies_to_timeval(jiffies, &mdp_ppp_timeval);
		}

		INIT_COMPLETION(mdp_ppp_comp);
		mdp_ppp_waiting = TRUE;

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

		//HWIO_OUT(MDP_DISPLAY0_START, 0x1000);
		outpdw(MDP_BASE + 0x30, 0x1000);
		wait_for_completion_interruptible(&mdp_ppp_comp);

		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_INFO("MDP-PPP: %d\n",
				    (int)mdp_ppp_timeval.tv_usec);
		}
	} else if (term == MDP_DMA2_TERM) {
		if (mdp_debug[MDP_DMA2_BLOCK]) {
			MSM_FB_INFO("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
		// mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_ON,FALSE);
#ifdef CONFIG_FB_MSM_MDP22
		outpdw(MDP_CMD_DEBUG_ACCESS_BASE + 0x0044, 0x0);	// start DMA
#else
		outpdw(MDP_BASE + 0x0044, 0x0);	// start DMA
#endif
	}
	else if (term == MDP_DMA_S_TERM) {
		mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
		outpdw(MDP_BASE + 0x0048, 0x0);	// start DMA
	}
}
Exemplo n.º 2
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;

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

	init_timer(&mfd->vsync_resync_timer);
	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);

	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);
	}
}
static void mipi_s6d6aa0_set_panel(struct mipi_s6d6aa0_data *dsi_data)
{
	dsi_data->panel = dsi_data->pdata->panels[0];
	MSM_FB_INFO("panel: %s\n", dsi_data->panel->name);
	dsi_data->panel_data.panel_info =
		*dsi_data->panel->pctrl->get_panel_info();
}
Exemplo n.º 4
0
void mipi_dsi_set_default_panel(struct mipi_dsi_data *dsi_data)
{
	if (dsi_data->default_panels[0] != NULL)
		dsi_data->panel = dsi_data->default_panels[0];
	else
		dsi_data->panel = dsi_data->panels[0];

	MSM_FB_INFO("default panel: %s\n", dsi_data->panel->name);
	dsi_data->panel_data.panel_info =
		*dsi_data->panel->pctrl->get_panel_info();
	dsi_data->panel_data.panel_info.width =
		dsi_data->panel->width;
	dsi_data->panel_data.panel_info.height =
		dsi_data->panel->height;
}
void mipi_dsi_set_default_panel(struct mipi_dsi_data *dsi_data)
{
	if (dsi_data->default_panels[0] != NULL)
		dsi_data->panel = dsi_data->default_panels[0];
	else
		dsi_data->panel = dsi_data->panels[0];

	MSM_FB_INFO("default panel: %s\n", dsi_data->panel->name);
	dsi_data->panel_data.panel_info =
		*dsi_data->panel->pctrl->get_panel_info();
	dsi_data->panel_data.panel_info.width =
		dsi_data->panel->width;
	dsi_data->panel_data.panel_info.height =
		dsi_data->panel->height;
#ifdef CONFIG_FB_MSM_RECOVER_PANEL
	dsi_data->nvrw_panel_detective = false;
#endif
}
Exemplo n.º 6
0
uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
{
	uint32 elapsed_usec_time;
	uint32 lcd_line;
	ktime_t last_vsync_timetick_local;
	ktime_t curr_time;
	unsigned long flag;

	if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
		return 0;

	spin_lock_irqsave(&mdp_spin_lock, flag);
	last_vsync_timetick_local = mfd->last_vsync_timetick;
	spin_unlock_irqrestore(&mdp_spin_lock, flag);

	curr_time = ktime_get_real();
	elapsed_usec_time =
	    ((curr_time.tv.sec - last_vsync_timetick_local.tv.sec) * 1000000) +
	    ((curr_time.tv.nsec - last_vsync_timetick_local.tv.nsec) / 1000);

	elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;

	/* lcd line calculation referencing to line counter = 0 */
	lcd_line =
	    (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;

	/* lcd line adjusment referencing to the actual line counter at vsync */
	lcd_line =
	    (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
	     lcd_line) % (mfd->total_lcd_lines + 1);

	if (lcd_line > mfd->total_lcd_lines) {
		MSM_FB_INFO
		    ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
	}

	return lcd_line;
}
Exemplo n.º 7
0
uint32 mdp_get_lcd_line_counter(struct msm_fb_data_type *mfd)
{
	uint32 elapsed_usec_time;
	uint32 lcd_line;
	ktime_t last_vsync_timetick_local;
	ktime_t curr_time;
	unsigned long flag;

	if ((!mfd->panel_info.lcd.vsync_enable) || (!vsync_mode))
		return 0;

	spin_lock_irqsave(&mdp_spin_lock, flag);
	last_vsync_timetick_local = mfd->last_vsync_timetick;
	spin_unlock_irqrestore(&mdp_spin_lock, flag);

	curr_time = ktime_get_real();
	elapsed_usec_time = ktime_to_us(ktime_sub(curr_time,
						last_vsync_timetick_local));

	elapsed_usec_time = elapsed_usec_time % mfd->lcd_ref_usec_time;

	/*                                                      */
	lcd_line =
	    (elapsed_usec_time * mfd->total_lcd_lines) / mfd->lcd_ref_usec_time;

	/*                                                                    */
	lcd_line =
	    (mfd->total_lcd_lines - mfd->panel_info.lcd.v_back_porch +
	     lcd_line) % (mfd->total_lcd_lines + 1);

	if (lcd_line > mfd->total_lcd_lines) {
		MSM_FB_INFO
		    ("mdp_get_lcd_line_counter: mdp_lcd_rd_cnt >= mfd->total_lcd_lines error!\n");
	}

	return lcd_line;
}
Exemplo n.º 8
0
static int mddi_probe(struct platform_device *pdev)
{
    struct msm_fb_data_type *mfd;
    struct platform_device *mdp_dev = NULL;
    struct msm_fb_panel_data *pdata = NULL;
    int rc;
    resource_size_t size ;
    u32 clk_rate;

    if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
        mddi_pdata = pdev->dev.platform_data;

        size =  resource_size(&pdev->resource[0]);
        msm_pmdh_base =  ioremap(pdev->resource[0].start, size);

        MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
                    pdev->resource[0].start, (int) msm_pmdh_base);

        if (unlikely(!msm_pmdh_base))
            return -ENOMEM;

        if (mddi_pdata && mddi_pdata->mddi_power_save)
            mddi_pdata->mddi_power_save(1);

        mddi_resource_initialized = 1;
        return 0;
    }

    if (!mddi_resource_initialized)
        return -EPERM;

    mfd = platform_get_drvdata(pdev);

    if (!mfd)
        return -ENODEV;

    if (mfd->key != MFD_KEY)
        return -EINVAL;

    if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
        return -ENOMEM;

    mdp_dev = platform_device_alloc("mdp", pdev->id);
    if (!mdp_dev)
        return -ENOMEM;

    /*
     * link to the latest pdev
     */
    mfd->pdev = mdp_dev;
    mfd->dest = DISPLAY_LCD;

    /*
     * alloc panel device data
     */
    if (platform_device_add_data
            (mdp_dev, pdev->dev.platform_data,
             sizeof(struct msm_fb_panel_data))) {
        printk(KERN_ERR "mddi_probe: platform_device_add_data failed!\n");
        platform_device_put(mdp_dev);
        return -ENOMEM;
    }
    /*
     * data chain
     */
    pdata = mdp_dev->dev.platform_data;
    pdata->on = mddi_on;
    pdata->off = mddi_off;
    pdata->next = pdev;
    pdata->clk_func = pmdh_clk_func;
    /*
     * get/set panel specific fb info
     */
    mfd->panel_info = pdata->panel_info;

    if (mfd->index == 0)
        mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
    else
        mfd->fb_imgType = MDP_RGB_565;

    clk_rate = mfd->panel_info.clk_max;
    if (mddi_pdata &&
            mddi_pdata->mddi_sel_clk &&
            mddi_pdata->mddi_sel_clk(&clk_rate))
        printk(KERN_ERR
               "%s: can't select mddi io clk targate rate = %d\n",
               __func__, clk_rate);

    if (clk_set_max_rate(mddi_clk, clk_rate) < 0)
        printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
    mfd->panel_info.clk_rate = mfd->panel_info.clk_min;

    if (!mddi_client_type)
        mddi_client_type = mfd->panel_info.lcd.rev;
    else if (!mfd->panel_info.lcd.rev)
        printk(KERN_ERR
               "%s: mddi client is trying to revert back to type 1	!!!\n",
               __func__);

    /*
     * set driver data
     */
    platform_set_drvdata(mdp_dev, mfd);
    rc = pm_runtime_set_active(&pdev->dev);
    if (rc < 0)
        printk(KERN_ERR "pm_runtime: fail to set active\n");

    rc = 0;
    pm_runtime_enable(&pdev->dev);
#ifndef CONFIG_MSM_BUS_SCALING
    mfd->ebi1_clk = clk_get(NULL, "ebi1_mddi_clk");
    if (IS_ERR(mfd->ebi1_clk))
        return PTR_ERR(mfd->ebi1_clk);
    clk_set_rate(mfd->ebi1_clk, 65000000);
#endif
    /*
     * register in mdp driver
     */
    rc = platform_device_add(mdp_dev);
    if (rc)
        goto mddi_probe_err;

    pdev_list[pdev_list_cnt++] = pdev;

#ifdef CONFIG_HAS_EARLYSUSPEND
    mfd->mddi_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
    mfd->mddi_early_suspend.suspend = mddi_early_suspend;
    mfd->mddi_early_suspend.resume = mddi_early_resume;
    register_early_suspend(&mfd->mddi_early_suspend);
#endif

    return 0;

mddi_probe_err:
    platform_device_put(mdp_dev);
    return rc;
}
Exemplo n.º 9
0
static int mddi_ext_probe(struct platform_device *pdev)
{
	struct msm_fb_data_type *mfd;
	struct platform_device *mdp_dev = NULL;
	struct msm_fb_panel_data *pdata = NULL;
	int rc;
	resource_size_t size ;
	u32 clk_rate;

	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
		mddi_ext_pdata = pdev->dev.platform_data;

		size =  resource_size(&pdev->resource[0]);
		msm_emdh_base = ioremap(pdev->resource[0].start, size);

		MSM_FB_INFO("external mddi base address = 0x%x\n",
				pdev->resource[0].start);

		if (unlikely(!msm_emdh_base))
			return -ENOMEM;

		mddi_ext_resource_initialized = 1;
		return 0;
	}

	if (!mddi_ext_resource_initialized)
		return -EPERM;

	mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
		return -ENOMEM;

	mdp_dev = platform_device_alloc("mdp", pdev->id);
	if (!mdp_dev)
		return -ENOMEM;

	
	mfd->pdev = mdp_dev;
	mfd->dest = DISPLAY_EXT_MDDI;

	
	if (platform_device_add_data
	    (mdp_dev, pdev->dev.platform_data,
	     sizeof(struct msm_fb_panel_data))) {
		printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
		platform_device_put(mdp_dev);
		return -ENOMEM;
	}
	
	pdata = mdp_dev->dev.platform_data;
	pdata->on = mddi_ext_on;
	pdata->off = mddi_ext_off;
	pdata->next = pdev;

	
	mfd->panel_info = pdata->panel_info;
	mfd->fb_imgType = MDP_RGB_565;

	clk_rate = mfd->panel_info.clk_max;
	if (mddi_ext_pdata &&
	    mddi_ext_pdata->mddi_sel_clk &&
	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
			printk(KERN_ERR
			  "%s: can't select mddi io clk targate rate = %d\n",
			  __func__, clk_rate);

	if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;

	
	platform_set_drvdata(mdp_dev, mfd);

	
	rc = platform_device_add(mdp_dev);
	if (rc)
		goto mddi_ext_probe_err;

	pdev_list[pdev_list_cnt++] = pdev;

#ifdef CONFIG_HAS_EARLYSUSPEND
	mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
	mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
	mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
	register_early_suspend(&mfd->mddi_ext_early_suspend);
#endif

	return 0;

mddi_ext_probe_err:
	platform_device_put(mdp_dev);
	return rc;
}
Exemplo n.º 10
0
void mdp_config_vsync(struct msm_fb_data_type *mfd)
{
	/* vsync on primary lcd only for now */
	if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
	    || (!vsync_mode)) {
		goto err_handle;
	}

	vsync_clk_status = 0;
	if (mfd->panel_info.lcd.vsync_enable) {
		mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
		    mfd->panel_info.lcd.v_front_porch +
		    mfd->panel_info.lcd.v_pulse_width;
		mfd->total_lcd_lines =
		    mfd->panel_info.yres + mfd->total_porch_lines;
		mfd->lcd_ref_usec_time =
		    100000000 / mfd->panel_info.lcd.refx100;
		mfd->vsync_handler_pending = FALSE;
		mfd->last_vsync_timetick.tv.sec = 0;
		mfd->last_vsync_timetick.tv.nsec = 0;

#ifdef MDP_HW_VSYNC
		if (mdp_vsync_clk == NULL)
			mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");

		if (IS_ERR(mdp_vsync_clk)) {
			printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
			mfd->use_mdp_vsync = 0;
		} else
			mfd->use_mdp_vsync = 1;

		if (mfd->use_mdp_vsync) {
			uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
			uint32 mdp_vsync_clk_speed_hz;

			mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);

			if (mdp_vsync_clk_speed_hz == 0) {
				mfd->use_mdp_vsync = 0;
			} else {
				/*
				 * Do this calculation in 2 steps for
				 * rounding uint32 properly.
				 */
				vsync_cnt_cfg_dem =
				    (mfd->panel_info.lcd.refx100 *
				     mfd->total_lcd_lines) / 100;
				vsync_cnt_cfg =
				    (mdp_vsync_clk_speed_hz) /
				    vsync_cnt_cfg_dem;

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

				mdp_set_sync_cfg_0(mfd, vsync_cnt_cfg);


#ifdef CONFIG_FB_MSM_MDP40
				if (mdp_hw_revision < MDP4_REVISION_V2_1)
					mdp_set_sync_cfg_1(mfd, vsync_cnt_cfg);
#endif

				/*
				 * load the last line + 1 to be in the
				 * safety zone
				 */
				vsync_load_cnt = mfd->panel_info.yres;

				/* line counter init value at the next pulse */
				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_INIT_VAL,
							vsync_load_cnt);
#ifdef CONFIG_FB_MSM_MDP40
				if (mdp_hw_revision < MDP4_REVISION_V2_1) {
					MDP_OUTP(MDP_BASE +
					MDP_SEC_VSYNC_INIT_VAL, vsync_load_cnt);
				}
#endif

				/*
				 * external vsync source pulse width and
				 * polarity flip
				 */
				MDP_OUTP(MDP_BASE + MDP_PRIM_VSYNC_OUT_CTRL,
							BIT(0));
#ifdef CONFIG_FB_MSM_MDP40
				if (mdp_hw_revision < MDP4_REVISION_V2_1) {
					MDP_OUTP(MDP_BASE +
					MDP_SEC_VSYNC_OUT_CTRL, BIT(0));
					MDP_OUTP(MDP_BASE +
						MDP_VSYNC_SEL, 0x20);
				}
#endif

				/* threshold */
#ifdef CONFIG_MACH_ACER_A4
				MDP_OUTP(MDP_BASE + MDP_SYNC_THRESH_0, (vsync_above_th << 16) | (vsync_start_th));
				MDP_OUTP(MDP_BASE + MDP_SYNC_THRESH_1, (vsync_above_th << 16) | (vsync_start_th));
#else
				MDP_OUTP(MDP_BASE + 0x200,
					 (vsync_above_th << 16) |
					 (vsync_start_th));
#endif

				mdp_hw_vsync_clk_disable(mfd);
				/* MDP cmd block disable */
				mdp_pipe_ctrl(MDP_CMD_BLOCK,
					      MDP_BLOCK_POWER_OFF, FALSE);
			}
		}
#else
		mfd->use_mdp_vsync = 0;
		hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
			     HRTIMER_MODE_REL);
		mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
		mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
#endif

#ifdef CONFIG_FB_MSM_MDDI
		mfd->channel_irq = 0;
		if (mfd->panel_info.lcd.hw_vsync_mode) {
			u32 vsync_gpio = mfd->vsync_gpio;
			u32 ret;

			if (vsync_gpio == -1) {
				MSM_FB_INFO("vsync_gpio not defined!\n");
				goto err_handle;
			}

			ret = gpio_tlmm_config(GPIO_CFG
					(vsync_gpio,
					(mfd->use_mdp_vsync) ? 1 : 0,
					GPIO_CFG_INPUT,
					GPIO_CFG_PULL_DOWN,
					GPIO_CFG_2MA),
					GPIO_CFG_ENABLE);
			if (ret)
				goto err_handle;

			/*
			 * if use_mdp_vsync, then no interrupt need since
			 * mdp_vsync is feed directly to mdp to reset the
			 * write pointer counter. therefore no irq_handler
			 * need to reset write pointer counter.
			 */
			if (!mfd->use_mdp_vsync) {
				mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
				if (request_irq
				    (mfd->channel_irq,
				     &mdp_hw_vsync_handler_proxy,
				     IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
				     (void *)mfd)) {
					MSM_FB_INFO
					("irq=%d failed! vsync_gpio=%d\n",
						mfd->channel_irq,
						vsync_gpio);
					goto err_handle;
				}
			}
		}
#endif
		mdp_hw_vsync_clk_enable(mfd);
		mdp_set_vsync((unsigned long)mfd);
	}

	return;

err_handle:
	if (mfd->vsync_width_boundary)
		vfree(mfd->vsync_width_boundary);
	mfd->panel_info.lcd.vsync_enable = FALSE;
	printk(KERN_ERR "%s: failed!\n", __func__);
}
Exemplo n.º 11
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);
	}
}
Exemplo n.º 12
0
void mdp_config_vsync(struct platform_device *pdev,
	struct msm_fb_data_type *mfd)
{
	/* vsync on primary lcd only for now */
	if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
	    || (!vsync_mode)) {
		goto err_handle;
	}

	vsync_clk_status = 0;
	if (mfd->panel_info.lcd.vsync_enable) {
		mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
		    mfd->panel_info.lcd.v_front_porch +
		    mfd->panel_info.lcd.v_pulse_width;
		mfd->total_lcd_lines =
		    mfd->panel_info.yres + mfd->total_porch_lines;
		mfd->lcd_ref_usec_time =
		    100000000 / mfd->panel_info.lcd.refx100;
		mfd->vsync_handler_pending = FALSE;

		mfd->last_vsync_timetick.tv64 = 0;

#ifdef MDP_HW_VSYNC
		if (mdp_vsync_clk == NULL)
			mdp_vsync_clk = clk_get(&pdev->dev, "vsync_clk");

		if (IS_ERR(mdp_vsync_clk)) {
			printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
			mfd->use_mdp_vsync = 0;
		} else
			mfd->use_mdp_vsync = 1;

		if (mfd->use_mdp_vsync) {
			uint32 vsync_cnt_cfg_dem;
			uint32 mdp_vsync_clk_speed_hz;

			mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);

			if (mdp_vsync_clk_speed_hz == 0) {
				mfd->use_mdp_vsync = 0;
			} else {
				/*
				 * Do this calculation in 2 steps for
				 * rounding uint32 properly.
				 */
				vsync_cnt_cfg_dem =
				    (mfd->panel_info.lcd.refx100 *
				     mfd->total_lcd_lines) / 100;
				vsync_cnt_cfg =
				    (mdp_vsync_clk_speed_hz) /
				    vsync_cnt_cfg_dem;
				mdp_vsync_cfg_regs(mfd, TRUE);
			}
		}
#else
		mfd->use_mdp_vsync = 0;
		hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
			     HRTIMER_MODE_REL);
		mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
		mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
#endif

#ifdef CONFIG_FB_MSM_MDDI
		mfd->channel_irq = 0;
		if (mfd->panel_info.lcd.hw_vsync_mode) {
			u32 vsync_gpio = mfd->vsync_gpio;
			u32 ret;

			if (vsync_gpio == -1) {
				MSM_FB_INFO("vsync_gpio not defined!\n");
				goto err_handle;
			}

			ret = gpio_tlmm_config(GPIO_CFG
					(vsync_gpio,
					(mfd->use_mdp_vsync) ? 1 : 0,
					GPIO_CFG_INPUT,
					GPIO_CFG_PULL_DOWN,
					GPIO_CFG_2MA),
					GPIO_CFG_ENABLE);
			if (ret)
				goto err_handle;

			/*
			 * if use_mdp_vsync, then no interrupt need since
			 * mdp_vsync is feed directly to mdp to reset the
			 * write pointer counter. therefore no irq_handler
			 * need to reset write pointer counter.
			 */
			if (!mfd->use_mdp_vsync) {
				mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
				if (request_irq
				    (mfd->channel_irq,
				     &mdp_hw_vsync_handler_proxy,
				     IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
				     (void *)mfd)) {
					MSM_FB_INFO
					("irq=%d failed! vsync_gpio=%d\n",
						mfd->channel_irq,
						vsync_gpio);
					goto err_handle;
				}
			}
		}
#endif
		mdp_hw_vsync_clk_enable(mfd);
		mdp_set_vsync((unsigned long)mfd);
	}

	return;

err_handle:
	if (mfd->vsync_width_boundary)
		vfree(mfd->vsync_width_boundary);
	mfd->panel_info.lcd.vsync_enable = FALSE;
	printk(KERN_ERR "%s: failed!\n", __func__);
}
Exemplo n.º 13
0
static int mipi_dsi_on(struct platform_device *pdev)
{
	int ret = 0;
	u32 clk_rate;
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct fb_var_screeninfo *var;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
	u32 ystride, bpp, data;
	u32 dummy_xres, dummy_yres;
	int target_type = 0;

	mfd = platform_get_drvdata(pdev);
	fbi = mfd->fbi;
	var = &fbi->var;
	pinfo = &mfd->panel_info;

	MSM_FB_INFO("%s: %d\n",__func__,__LINE__);
	if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
		mipi_dsi_pdata->dsi_power_save(1);

	cont_splash_clk_ctrl(0);
	mipi_dsi_prepare_clocks();

	local_bh_disable();
	mipi_dsi_ahb_ctrl(1);
	local_bh_enable();

	clk_rate = mfd->fbi->var.pixclock;
	clk_rate = min(clk_rate, mfd->panel_info.clk_max);

	mipi_dsi_phy_ctrl(1);

	if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
		target_type = mipi_dsi_pdata->target_type;

	mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);

	local_bh_disable();
	mipi_dsi_clk_enable();
	local_bh_enable();

	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
	MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);

	hbp = var->left_margin;
	hfp = var->right_margin;
	vbp = var->upper_margin;
	vfp = var->lower_margin;
	hspw = var->hsync_len;
	vspw = var->vsync_len;
	width = mfd->panel_info.xres;
	height = mfd->panel_info.yres;

	mipi  = &mfd->panel_info.mipi;
	if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
		dummy_xres = mfd->panel_info.lcdc.xres_pad;
		dummy_yres = mfd->panel_info.lcdc.yres_pad;

		if (mdp_rev >= MDP_REV_41) {
			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hspw + hbp + width + dummy_xres) << 16 |
				(hspw + hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vspw + vbp + height + dummy_yres) << 16 |
				(vspw + vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vspw + vbp + height + dummy_yres +
					vfp - 1) << 16 | (hspw + hbp +
					width + dummy_xres + hfp - 1));
		} else {
			/* DSI_LAN_SWAP_CTRL */
			MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);

			MIPI_OUTP(MIPI_DSI_BASE + 0x20,
				((hbp + width + dummy_xres) << 16 | (hbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x24,
				((vbp + height + dummy_yres) << 16 | (vbp)));
			MIPI_OUTP(MIPI_DSI_BASE + 0x28,
				(vbp + height + dummy_yres + vfp) << 16 |
					(hbp + width + dummy_xres + hfp));
		}

		MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
		MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
		MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));

	} else {		/* command mode */
		if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
			bpp = 3;
		else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
			bpp = 2;
		else
			bpp = 3;	/* Default format set to RGB888 */

		ystride = width * bpp + 1;

		/* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
		data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
		MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);

		/* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
		data = height << 16 | width;
		MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
		MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
	}

	mipi_dsi_host_init(mipi);

	if (mipi->force_clk_lane_hs) {
		u32 tmp;

		tmp = MIPI_INP(MIPI_DSI_BASE + 0xA8);
		tmp |= (1<<28);
		MIPI_OUTP(MIPI_DSI_BASE + 0xA8, tmp);
		wmb();
	}

	if (mdp_rev >= MDP_REV_41)
		mutex_lock(&mfd->dma->ov_mutex);
	else
		down(&mfd->dma->mutex);

	ret = panel_next_on(pdev);

	mipi_dsi_op_mode_config(mipi->mode);

	if (mfd->panel_info.type == MIPI_CMD_PANEL) {
		if (pinfo->lcd.vsync_enable) {
			if (pinfo->lcd.hw_vsync_mode && vsync_gpio >= 0) {
				if (mdp_rev >= MDP_REV_41) {
					if (gpio_request(vsync_gpio,
						"MDP_VSYNC") == 0)
						gpio_direction_input(
							vsync_gpio);
					else
						pr_err("%s: unable to \
							request gpio=%d\n",
							__func__, vsync_gpio);
				} else if (mdp_rev == MDP_REV_303) {
					if (!tlmm_settings && gpio_request(
						vsync_gpio, "MDP_VSYNC") == 0) {
						ret = gpio_tlmm_config(
							GPIO_CFG(
							vsync_gpio, 1,
							GPIO_CFG_INPUT,
							GPIO_CFG_PULL_DOWN,
							GPIO_CFG_2MA),
							GPIO_CFG_ENABLE);

						if (ret) {
							pr_err(
							"%s: unable to config \
							tlmm = %d\n",
							__func__, vsync_gpio);
						}
						tlmm_settings = TRUE;

						gpio_direction_input(
							vsync_gpio);
					} else {
						if (!tlmm_settings) {
							pr_err(
							"%s: unable to request \
							gpio=%d\n",
							__func__, vsync_gpio);
						}
					}
				}
Exemplo n.º 14
0
static int mipi_dsi_probe(struct platform_device *pdev)
{
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct msm_panel_info *pinfo;
	struct mipi_panel_info *mipi;
	struct platform_device *mdp_dev = NULL;
	struct msm_fb_panel_data *pdata = NULL;
	int rc;
	uint8 lanes = 0, bpp;
	uint32 h_period, v_period, dsi_pclk_rate;

	resource_size_t size ;

	if ((pdev->id == 1) && (pdev->num_resources >= 0)) {
		mipi_dsi_pdata = pdev->dev.platform_data;

		size =  resource_size(&pdev->resource[0]);
		mipi_dsi_base =  ioremap(pdev->resource[0].start, size);

		MSM_FB_INFO("mipi_dsi base phy_addr = 0x%x virt = 0x%x\n",
				pdev->resource[0].start, (int) mipi_dsi_base);

		if (!mipi_dsi_base)
			return -ENOMEM;

		if (mdp_rev >= MDP_REV_41) {
			mmss_sfpb_base =  ioremap(MMSS_SFPB_BASE_PHY, 0x100);
			MSM_FB_INFO("mmss_sfpb  base phy_addr = 0x%x,"
				"virt = 0x%x\n", MMSS_SFPB_BASE_PHY,
				(int) mmss_sfpb_base);

			if (!mmss_sfpb_base)
				return -ENOMEM;
		}

		dsi_irq = platform_get_irq(pdev, 0);
		if (dsi_irq < 0) {
			pr_err("mipi_dsi: can not get mdp irq\n");
			return -ENOMEM;
		}

		rc = request_irq(dsi_irq, mipi_dsi_isr, IRQF_DISABLED,
						"MIPI_DSI", 0);
		if (rc) {
			pr_err("mipi_dsi_host request_irq() failed!\n");
			return rc;
		}

		disable_irq(dsi_irq);

		if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata &&
			mipi_dsi_pdata->target_type == 1) {
			/* Target type is 1 for device with (De)serializer
			 * 0x4f00000 is the base for TV Encoder.
			 * Unused Offset 0x1000 is used for
			 * (de)serializer on emulation platform
			 */
			periph_base = ioremap(MMSS_SERDES_BASE_PHY, 0x100);

			if (periph_base) {
				pr_debug("periph_base %p\n", periph_base);
				writel(0x4, periph_base + 0x28);
				writel(0xc, periph_base + 0x28);
			} else {
				pr_err("periph_base is NULL\n");
				free_irq(dsi_irq, 0);
				return -ENOMEM;
			}
		}

		if (mipi_dsi_pdata) {
			vsync_gpio = mipi_dsi_pdata->vsync_gpio;
			pr_debug("%s: vsync_gpio=%d\n", __func__, vsync_gpio);

			if (mdp_rev == MDP_REV_303 &&
				mipi_dsi_pdata->dsi_client_reset) {
				if (mipi_dsi_pdata->dsi_client_reset())
					pr_err("%s: DSI Client Reset failed!\n",
						__func__);
				else
					pr_debug("%s: DSI Client Reset success\n",
						__func__);
			}
		}

		mipi_dsi_resource_initialized = 1;

		return 0;
	}

	mipi_dsi_clk_init(&pdev->dev);

	if (!mipi_dsi_resource_initialized)
		return -EPERM;

	mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
		return -ENOMEM;


	mdp_dev = platform_device_alloc("mdp", pdev->id);
	if (!mdp_dev)
		return -ENOMEM;

	/*
	 * link to the latest pdev
	 */
	mfd->pdev = mdp_dev;
	mfd->dest = DISPLAY_LCD;

	/*
	 * alloc panel device data
	 */
	if (platform_device_add_data
	    (mdp_dev, pdev->dev.platform_data,
	     sizeof(struct msm_fb_panel_data))) {
		pr_err("mipi_dsi_probe: platform_device_add_data failed!\n");
		platform_device_put(mdp_dev);
		return -ENOMEM;
	}
	/*
	 * data chain
	 */
	pdata = mdp_dev->dev.platform_data;
	pdata->on = mipi_dsi_on;
	pdata->off = mipi_dsi_off;
	pdata->next = pdev;

	/*
	 * get/set panel specific fb info
	 */
	mfd->panel_info = pdata->panel_info;
	pinfo = &mfd->panel_info;

	if (mdp_rev == MDP_REV_303 &&
		mipi_dsi_pdata->get_lane_config) {
		if (mipi_dsi_pdata->get_lane_config() != 2) {
			pr_info("Changing to DSI Single Mode Configuration\n");
#ifdef CONFIG_FB_MSM_MDP303
			update_lane_config(pinfo);
#endif
		}
	}

	if (mfd->index == 0)
		mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
	else
		mfd->fb_imgType = MDP_RGB_565;

	fbi = mfd->fbi;
	fbi->var.pixclock = mfd->panel_info.clk_rate;
	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
	fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
	fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
	fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;

	h_period = ((mfd->panel_info.lcdc.h_pulse_width)
			+ (mfd->panel_info.lcdc.h_back_porch)
			+ (mfd->panel_info.xres)
			+ (mfd->panel_info.lcdc.h_front_porch));

	v_period = ((mfd->panel_info.lcdc.v_pulse_width)
			+ (mfd->panel_info.lcdc.v_back_porch)
			+ (mfd->panel_info.yres)
			+ (mfd->panel_info.lcdc.v_front_porch));

	mipi  = &mfd->panel_info.mipi;

	if (mipi->data_lane3)
		lanes += 1;
	if (mipi->data_lane2)
		lanes += 1;
	if (mipi->data_lane1)
		lanes += 1;
	if (mipi->data_lane0)
		lanes += 1;

	if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
	    || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
	    || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
		bpp = 3;
	else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
		 || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
		bpp = 2;
	else
		bpp = 3;		/* Default format set to RGB888 */

	if (mfd->panel_info.type == MIPI_VIDEO_PANEL &&
		!mfd->panel_info.clk_rate) {
		h_period += mfd->panel_info.mipi.xres_pad;
		v_period += mfd->panel_info.mipi.yres_pad;

		if (lanes > 0) {
			mfd->panel_info.clk_rate =
			((h_period * v_period * (mipi->frame_rate) * bpp * 8)
			   / lanes);
		} else {
			pr_err("%s: forcing mipi_dsi lanes to 1\n", __func__);
			mfd->panel_info.clk_rate =
				(h_period * v_period
					 * (mipi->frame_rate) * bpp * 8);
		}
	}
	pll_divider_config.clk_rate = mfd->panel_info.clk_rate;

	rc = mipi_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
	if (rc)
		goto mipi_dsi_probe_err;

	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
		dsi_pclk_rate = 35000000;
	mipi->dsi_pclk_rate = dsi_pclk_rate;

	/*
	 * set driver data
	 */
	platform_set_drvdata(mdp_dev, mfd);

	/*
	 * register in mdp driver
	 */
	rc = platform_device_add(mdp_dev);
	if (rc)
		goto mipi_dsi_probe_err;

	pdev_list[pdev_list_cnt++] = pdev;

return 0;

mipi_dsi_probe_err:
	platform_device_put(mdp_dev);
	return rc;
}
Exemplo n.º 15
0
void mdp_config_vsync(struct msm_fb_data_type *mfd)
{
	// vsync on primary lcd only for now
	if ((mfd->dest != DISPLAY_LCD) || (mfd->panel_info.pdest != DISPLAY_1)
	    || (!vsync_mode)) {
		goto err_handle;
	}

	if (mfd->panel_info.lcd.vsync_enable) {
		mfd->total_porch_lines = mfd->panel_info.lcd.v_back_porch +
		    mfd->panel_info.lcd.v_front_porch +
		    mfd->panel_info.lcd.v_pulse_width;
		mfd->total_lcd_lines =
		    mfd->panel_info.yres + mfd->total_porch_lines;
		mfd->lcd_ref_usec_time =
		    100000000 / mfd->panel_info.lcd.refx100;
		mfd->vsync_handler_pending = FALSE;
		mfd->last_vsync_timetick.tv.sec = 0;
		mfd->last_vsync_timetick.tv.nsec = 0;

#ifdef MDP_HW_VSYNC
		if (mdp_vsync_clk == NULL)
			mdp_vsync_clk = clk_get(NULL, "mdp_vsync_clk");

		if (IS_ERR(mdp_vsync_clk)) {
			printk(KERN_ERR "error: can't get mdp_vsync_clk!\n");
			mfd->use_mdp_vsync = 0;
		} else
			mfd->use_mdp_vsync = 1;

		if (mfd->use_mdp_vsync) {
			uint32 vsync_cnt_cfg, vsync_cnt_cfg_dem;
			uint32 mdp_vsync_clk_speed_hz;

			mdp_vsync_clk_speed_hz = clk_get_rate(mdp_vsync_clk);

			if (mdp_vsync_clk_speed_hz == 0) {
				mfd->use_mdp_vsync = 0;
			} else {
				// Do this calculation in 2 steps for rounding uint32 properly.
				vsync_cnt_cfg_dem =
				    (mfd->panel_info.lcd.refx100 *
				     mfd->total_lcd_lines) / 100;
				vsync_cnt_cfg =
				    (mdp_vsync_clk_speed_hz) /
				    vsync_cnt_cfg_dem;

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

				MDP_OUTP(MDP_BASE + 0x300,
					 ((mfd->total_lcd_lines -
					   1) << MDP_SYNCFG_HGT_LOC) | (mfd->
									panel_info.
									lcd.
									hw_vsync_mode
									?
									MDP_SYNCFG_VSYNC_EXT_EN
									: 0) |
					 MDP_SYNCFG_VSYNC_INT_EN |
					 vsync_cnt_cfg);

				// load the last line + 1 to be in the safety zone
				vsync_load_cnt = mfd->panel_info.yres;

				// line counter init value at the next pulse
				MDP_OUTP(MDP_BASE + 0x328, vsync_load_cnt);

				// external vsync source pulse width and polarity flip
				MDP_OUTP(MDP_BASE + 0x318, BIT(30) | BIT(0));

				// threshold
				MDP_OUTP(MDP_BASE + 0x200,
					 (vsync_above_th << 16) |
					 (vsync_start_th));

				mdp_hw_vsync_clk_disable(mfd);
				// MDP cmd block disable
				mdp_pipe_ctrl(MDP_CMD_BLOCK,
					      MDP_BLOCK_POWER_OFF, FALSE);
			}
		}
#else
		mfd->use_mdp_vsync = 0;
		hrtimer_init(&mfd->dma_hrtimer, CLOCK_MONOTONIC,
			     HRTIMER_MODE_REL);
		mfd->dma_hrtimer.function = mdp_dma2_vsync_hrtimer_handler;
		mfd->vsync_width_boundary = vmalloc(mfd->panel_info.xres * 4);
#endif

		mfd->channel_irq = 0;
		if (mfd->panel_info.lcd.hw_vsync_mode) {
			u32 vsync_gpio = mfd->vsync_gpio;
			u32 ret;

			if (vsync_gpio == -1) {
				MSM_FB_INFO("vsync_gpio not defined!\n");
				goto err_handle;
			}

			ret = gpio_tlmm_config(GPIO_CFG
					(vsync_gpio,
					(mfd->use_mdp_vsync) ? 1 : 0,
					GPIO_INPUT,
					GPIO_PULL_DOWN,
					GPIO_2MA),
					GPIO_ENABLE);
			if (ret)
				goto err_handle;

			if (!mfd->use_mdp_vsync) {
				mfd->channel_irq = MSM_GPIO_TO_INT(vsync_gpio);
				if (request_irq
				    (mfd->channel_irq,
				     &mdp_hw_vsync_handler_proxy,
				     IRQF_TRIGGER_FALLING, "VSYNC_GPIO",
				     (void *)mfd)) {
					MSM_FB_INFO
					("irq=%d failed! vsync_gpio=%d\n",
						mfd->channel_irq,
						vsync_gpio);
					goto err_handle;
				}
			}
		}

		mdp_set_vsync((unsigned long)mfd);
	}

	return;

err_handle:
	if (mfd->vsync_width_boundary)
		vfree(mfd->vsync_width_boundary);
	mfd->panel_info.lcd.vsync_enable = FALSE;
	printk(KERN_ERR "%s: failed!\n", __func__);
}
Exemplo n.º 16
0
static int mdp_probe(struct platform_device *pdev)
{
	struct platform_device *msm_fb_dev = NULL;
	struct msm_fb_data_type *mfd;
	struct msm_fb_panel_data *pdata = NULL;
	int rc;
	unsigned long flag;
        resource_size_t  size ;

	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
		mdp_pdata = pdev->dev.platform_data;

		size =  resource_size(&pdev->resource[0]);
		msm_mdp_base = ioremap(pdev->resource[0].start, size);

		MSM_FB_INFO("MDP HW Base Address = 0x%x\n",
				(int)pdev->resource[0].start);

		if (unlikely(!msm_mdp_base))
			return -ENOMEM;

		mdp_resource_initialized = 1;
		return 0;
	}

	if (!mdp_resource_initialized)
		return -EPERM;

	mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
		return -ENOMEM;

	msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
	if (!msm_fb_dev)
		return -ENOMEM;

	/////////////////////////////////////////
	// link to the latest pdev
	/////////////////////////////////////////
	mfd->pdev = msm_fb_dev;

	/////////////////////////////////////////
	// add panel data
	/////////////////////////////////////////
	if (platform_device_add_data
	    (msm_fb_dev, pdev->dev.platform_data,
	     sizeof(struct msm_fb_panel_data))) {
		printk(KERN_ERR "mdp_probe: platform_device_add_data failed!\n");
		rc = -ENOMEM;
		goto mdp_probe_err;
	}
	/////////////////////////////////////////
	// data chain
	/////////////////////////////////////////
	pdata = msm_fb_dev->dev.platform_data;
	pdata->on = mdp_on;
	pdata->off = mdp_off;
	pdata->next = pdev;

	switch (mfd->panel.type) {
	case EXT_MDDI_PANEL:
	case MDDI_PANEL:
	case EBI2_PANEL:
		INIT_WORK(&mfd->dma_update_worker,
			  mdp_lcd_update_workqueue_handler);
		INIT_WORK(&mfd->vsync_resync_worker,
			  mdp_vsync_resync_workqueue_handler);
		mfd->hw_refresh = FALSE;

		if (mfd->panel.type == EXT_MDDI_PANEL)
			mfd->refresh_timer_duration = (66 * HZ / 1000);	// 15 fps -> 66 msec
		else
			mfd->refresh_timer_duration = (42 * HZ / 1000);	// 24 fps -> 42 msec

#ifdef CONFIG_FB_MSM_MDP22
		mfd->dma_fnc = mdp_dma2_update;
		mfd->dma = &dma2_data;
#else
		if (mfd->panel_info.pdest == DISPLAY_1) {
			mfd->dma_fnc = mdp_dma2_update;
			mfd->dma = &dma2_data;
		} else {
			mfd->dma_fnc = mdp_dma_s_update;
			mfd->dma = &dma_s_data;
		}
#endif
		if (mdp_pdata)
			mfd->vsync_gpio = mdp_pdata->gpio;
		else
			mfd->vsync_gpio = -1;

		mdp_config_vsync(mfd);
		break;

	case LCDC_PANEL:
		pdata->on = mdp_lcdc_on;
		pdata->off = mdp_lcdc_off;
		mfd->hw_refresh = TRUE;
		mfd->cursor_update = mdp_hw_cursor_update;
		mfd->dma_fnc = mdp_lcdc_update;
		mfd->dma = &dma2_data;

		spin_lock_irqsave(&mdp_spin_lock, flag);
		mdp_intr_mask &= ~MDP_DMA_P_DONE;
		outp32(MDP_INTR_ENABLE, mdp_intr_mask);
		spin_unlock_irqrestore(&mdp_spin_lock, flag);
		break;

	case TV_PANEL:
		pdata->on = mdp_dma3_on;
		pdata->off = mdp_dma3_off;
		mfd->hw_refresh = TRUE;
		mfd->dma_fnc = mdp_dma3_update;
		mfd->dma = &dma3_data;
		break;

	default:
		printk(KERN_ERR "mdp_probe: unknown device type!\n");
		rc = -ENODEV;
		goto mdp_probe_err;
	}

	/////////////////////////////////////////
	// set driver data
	/////////////////////////////////////////
	platform_set_drvdata(msm_fb_dev, mfd);

	rc = platform_device_add(msm_fb_dev);
	if (rc) {
		goto mdp_probe_err;
	}

	pdev_list[pdev_list_cnt++] = pdev;
	return 0;

      mdp_probe_err:
	platform_device_put(msm_fb_dev);
	return rc;
}
Exemplo n.º 17
0
static int mddi_ext_probe(struct platform_device *pdev)
{
	struct msm_fb_data_type *mfd;
	struct platform_device *mdp_dev = NULL;
	struct msm_fb_panel_data *pdata = NULL;
	int rc;
	resource_size_t size ;
	u32 clk_rate;

	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
		mddi_ext_pdata = pdev->dev.platform_data;
		mddi_ext_clk = clk_get(&pdev->dev, "core_clk");
		if (IS_ERR(mddi_ext_clk)) {
			pr_err("can't find emdh_clk\n");
			return PTR_ERR(mddi_ext_clk);
		}
		clk_prepare_enable(mddi_ext_clk);

		mddi_ext_pclk = clk_get(&pdev->dev, "iface_clk");
		if (IS_ERR(mddi_ext_pclk))
			mddi_ext_pclk = NULL;
		else
			clk_prepare_enable(mddi_ext_pclk);

		size =  resource_size(&pdev->resource[0]);
		msm_emdh_base = ioremap(pdev->resource[0].start, size);

		MSM_FB_INFO("external mddi base address = 0x%x\n",
				pdev->resource[0].start);

		if (unlikely(!msm_emdh_base))
			return -ENOMEM;

		mddi_ext_resource_initialized = 1;
		return 0;
	}

	if (!mddi_ext_resource_initialized)
		return -EPERM;

	mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
		return -ENOMEM;

	mdp_dev = platform_device_alloc("mdp", pdev->id);
	if (!mdp_dev)
		return -ENOMEM;

	/*
	 * link to the latest pdev
	 */
	mfd->pdev = mdp_dev;
	mfd->dest = DISPLAY_EXT_MDDI;

	/*
	 * alloc panel device data
	 */
	if (platform_device_add_data
	    (mdp_dev, pdev->dev.platform_data,
	     sizeof(struct msm_fb_panel_data))) {
		printk(KERN_ERR "mddi_ext_probe: platform_device_add_data failed!\n");
		platform_device_put(mdp_dev);
		return -ENOMEM;
	}
	/*
	 * data chain
	 */
	pdata = mdp_dev->dev.platform_data;
	pdata->on = mddi_ext_on;
	pdata->off = mddi_ext_off;
	pdata->next = pdev;

	/*
	 * get/set panel specific fb info
	 */
	mfd->panel_info = pdata->panel_info;
	mfd->fb_imgType = MDP_RGB_565;

	clk_rate = mfd->panel_info.clk_max;
	if (mddi_ext_pdata &&
	    mddi_ext_pdata->mddi_sel_clk &&
	    mddi_ext_pdata->mddi_sel_clk(&clk_rate))
			printk(KERN_ERR
			  "%s: can't select mddi io clk targate rate = %d\n",
			  __func__, clk_rate);

	if (clk_set_max_rate(mddi_ext_clk, clk_rate) < 0)
		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;

	/*
	 * set driver data
	 */
	platform_set_drvdata(mdp_dev, mfd);
	rc = pm_runtime_set_active(&pdev->dev);
	if (rc < 0)
		printk(KERN_ERR "pm_runtime: fail to set active\n");

	rc = 0;
	pm_runtime_enable(&pdev->dev);
	/*
	 * register in mdp driver
	 */
	rc = platform_device_add(mdp_dev);
	if (rc)
		goto mddi_ext_probe_err;

	pdev_list[pdev_list_cnt++] = pdev;

#ifdef CONFIG_HAS_EARLYSUSPEND
	mfd->mddi_ext_early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
	mfd->mddi_ext_early_suspend.suspend = mddi_ext_early_suspend;
	mfd->mddi_ext_early_suspend.resume = mddi_ext_early_resume;
	register_early_suspend(&mfd->mddi_ext_early_suspend);
#endif

	return 0;

mddi_ext_probe_err:
	platform_device_put(mdp_dev);
	return rc;
}
Exemplo n.º 18
0
static int mipi_dsi_probe(struct platform_device *pdev)
{
	struct msm_fb_data_type *mfd;
	struct fb_info *fbi;
	struct platform_device *mdp_dev = NULL;
	struct msm_fb_panel_data *pdata = NULL;
	int rc;
	resource_size_t size ;

	if ((pdev->id == 0) && (pdev->num_resources >= 0)) {
		mipi_dsi_pdata = pdev->dev.platform_data;

		size =  resource_size(&pdev->resource[0]);
		mipi_dsi_base =  ioremap(pdev->resource[0].start, size);

		MSM_FB_INFO("mipi_dsi base phy_addr = 0x%x virt = 0x%x\n",
				pdev->resource[0].start, (int) mipi_dsi_base);

		if (!mipi_dsi_base)
			return -ENOMEM;

		mmss_cc_base =  ioremap(MMSS_CC_BASE_PHY, 0x200);
		MSM_FB_INFO("mmss_cc base phy_addr = 0x%x virt = 0x%x\n",
				MMSS_CC_BASE_PHY, (int) mmss_cc_base);

		if (!mmss_cc_base)
			return -ENOMEM;

		mmss_sfpb_base =  ioremap(MMSS_SFPB_BASE_PHY, 0x100);
		MSM_FB_INFO("mmss_sfpb  base phy_addr = 0x%x virt = 0x%x\n",
				MMSS_SFPB_BASE_PHY, (int) mmss_sfpb_base);

		if (!mmss_cc_base)
			return -ENOMEM;

		rc = request_irq(DSI_IRQ, mipi_dsi_isr, IRQF_DISABLED,
						"MIPI_DSI", 0);
		if (rc) {
			printk(KERN_ERR "mipi_dsi_host request_irq() failed!\n");
			return rc;
		}

		disable_irq(DSI_IRQ);

		mipi_dsi_calibration();

		if (mipi_dsi_mxo_selected())
			dsi_cc_data |= BIT(8);	/* use MXO for DSI PLL clkref */
		else
			dsi_cc_data &= ~BIT(8);	/* use PXO */

		mipi_dsi_resource_initialized = 1;

		return 0;
	}

	if (!mipi_dsi_resource_initialized)
		return -EPERM;

	mfd = platform_get_drvdata(pdev);

	if (!mfd)
		return -ENODEV;

	if (mfd->key != MFD_KEY)
		return -EINVAL;

	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
		return -ENOMEM;


	mdp_dev = platform_device_alloc("mdp", pdev->id);
	if (!mdp_dev)
		return -ENOMEM;

	/*
	 * link to the latest pdev
	 */
	mfd->pdev = mdp_dev;
	mfd->dest = DISPLAY_LCD;

	/*
	 * alloc panel device data
	 */
	if (platform_device_add_data
	    (mdp_dev, pdev->dev.platform_data,
	     sizeof(struct msm_fb_panel_data))) {
		printk(KERN_ERR "mipi_dsi_probe: platform_device_add_data failed!\n");
		platform_device_put(mdp_dev);
		return -ENOMEM;
	}
	/*
	 * data chain
	 */
	pdata = mdp_dev->dev.platform_data;
	pdata->on = mipi_dsi_on;
	pdata->off = mipi_dsi_off;
	pdata->next = pdev;

	/*
	 * get/set panel specific fb info
	 */
	mfd->panel_info = pdata->panel_info;

	if (mfd->index == 0)
		mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
	else
		mfd->fb_imgType = MDP_RGB_565;

	fbi = mfd->fbi;
	fbi->var.pixclock = mfd->panel_info.clk_rate;
	fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
	fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
	fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
	fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
	fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
	fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;

#ifdef DSI_CLK
	clk_rate = mfd->panel_info.clk_max;
	if (clk_set_max_rate(mipi_dsi_clk, clk_rate) < 0)
		printk(KERN_ERR "%s: clk_set_max_rate failed\n", __func__);
	mfd->panel_info.clk_rate = mfd->panel_info.clk_min;
#endif

	/*
	 * set driver data
	 */
	platform_set_drvdata(mdp_dev, mfd);

	/*
	 * register in mdp driver
	 */
	rc = platform_device_add(mdp_dev);
	if (rc)
		goto mipi_dsi_probe_err;

	pdev_list[pdev_list_cnt++] = pdev;

	mfd->pm_qos_req = pm_qos_add_request(PM_QOS_SYSTEM_BUS_FREQ,
					       PM_QOS_DEFAULT_VALUE);
	if (!mfd->pm_qos_req)
		goto mipi_dsi_probe_err;

	return 0;

mipi_dsi_probe_err:
	platform_device_put(mdp_dev);
	return rc;
}
Exemplo n.º 19
0
void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
{
    /* 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_INFO("MDP-PPP: %d\n",
                        (int)mdp_ppp_timeval.tv_usec);
        }
    } else if (term == MDP_DMA2_TERM) {
        if (mdp_debug[MDP_DMA2_BLOCK]) {
            MSM_FB_INFO("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
    }
static int __init mipi_cmd_sony_wvga_pt_init(void)
{
	int ret;

	if (msm_fb_detect_client("mipi_cmd_sony_wvga"))
		return 0;
	MSM_FB_INFO("[DISP] panel: mipi_cmd_sony_wvga\n");

	pinfo.xres = 480;
	pinfo.yres = 800;
	pinfo.type = MIPI_CMD_PANEL;
	pinfo.pdest = DISPLAY_1;
	pinfo.wait_cycle = 0;
	pinfo.bpp = 24;
	pinfo.lcdc.h_back_porch = 2;
	pinfo.lcdc.h_front_porch = 2;
	pinfo.lcdc.h_pulse_width = 2;
	pinfo.lcdc.v_back_porch = 2;
	pinfo.lcdc.v_front_porch = 2;
	pinfo.lcdc.v_pulse_width = 2;
	pinfo.lcdc.border_clr = 0;	/* blk */
	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
	pinfo.lcdc.hsync_skew = 0;
	pinfo.lcd.v_back_porch = 2;
	pinfo.lcd.v_front_porch = 2;
	pinfo.lcd.v_pulse_width = 2;
	pinfo.bl_max = 255;
	pinfo.bl_min = 1;
	pinfo.fb_num = 2;
	pinfo.clk_rate = 499000000;
	pinfo.lcd.vsync_enable = TRUE;
	pinfo.lcd.hw_vsync_mode = TRUE;
	pinfo.lcd.refx100 = 6500; /* adjust refx100 to prevent tearing */

	pinfo.mipi.mode = DSI_CMD_MODE;
	pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
	pinfo.mipi.vc = 0;
	pinfo.mipi.rgb_swap = DSI_RGB_SWAP_RGB;
	pinfo.mipi.data_lane0 = TRUE;

	pinfo.mipi.t_clk_post = 0x20;
	pinfo.mipi.t_clk_pre = 0x2c;
	pinfo.mipi.stream = 0;	/* dma_p */
	pinfo.mipi.mdp_trigger = DSI_CMD_TRIGGER_SW;
	pinfo.mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
	pinfo.mipi.te_sel = 1; /* TE from vsycn gpio */
	pinfo.mipi.interleave_max = 1;
	pinfo.mipi.insert_dcs_cmd = TRUE;
	pinfo.mipi.wr_mem_continue = 0x3c;
	pinfo.mipi.wr_mem_start = 0x2c;
	pinfo.mipi.dsi_phy_db = &dsi_cmd_mode_phy_db;
	pinfo.mipi.tx_eot_append = 0x01;
	pinfo.mipi.rx_eot_ignore = 0;
	pinfo.mipi.dlane_swap = 0x01;

	ret = mipi_sony_device_register(&pinfo, MIPI_DSI_PRIM,
						MIPI_DSI_PANEL_WVGA_PT);
	if (ret)
		pr_err("%s: failed to register device!\n", __func__);

	return ret;
}