Beispiel #1
0
void mdp3_dump_dma(void *data)
{
	struct mdp3_dma *dma = (struct mdp3_dma *)data;
	u32 isr, mask;

	mdp3_clk_prepare();
	mdp3_clk_enable(1, 0);

	isr = MDP3_REG_READ(MDP3_REG_INTR_STATUS);
	mask = MDP3_REG_READ(MDP3_REG_INTR_ENABLE);
	MDSS_TIMEOUT_LOG("-------- MDP3 INTERRUPT DATA ---------\n");
	MDSS_TIMEOUT_LOG("MDP3_REG_INTR_STATUS: 0x%08X\n", isr);
	MDSS_TIMEOUT_LOG("MDP3_REG_INTR_ENABLE: 0x%08X\n", mask);
	MDSS_TIMEOUT_LOG("global irqs disabled: %d\n", irqs_disabled());
	MDSS_TIMEOUT_LOG("------ MDP3 INTERRUPT DATA DONE ------\n");

	if (dma) {
		MDSS_TIMEOUT_LOG("-------- MDP3 DMA DATA ---------\n");
		MDSS_TIMEOUT_LOG("vsync_cnt=%u\n", dma->vsync_cnt);
		MDSS_TIMEOUT_LOG("------ MDP3 DMA DATA DONE ------\n");
	}

	mdp3_clk_enable(0, 0);
	mdp3_clk_unprepare();
}
Beispiel #2
0
static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status)
{
	int rc = 0;
	if (status) {

		mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE,
				MDP3_CLIENT_DMA_P);
		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
				MDP3_CLIENT_DMA_P);

		rc = mdp3_clk_prepare();
		if (rc) {
			pr_err("mdp3 clk prepare fail\n");
			return rc;
		}

		rc = mdp3_clk_enable(1, 1);
		if (rc) {
			pr_err("mdp3 clk enable fail\n");
			mdp3_clk_unprepare();
			return rc;
		}
	} else {
		rc = mdp3_clk_enable(0, 1);
		if (rc)
			pr_err("mdp3 clk disable fail\n");
		else
			mdp3_clk_unprepare();
	}
	return rc;
}
Beispiel #3
0
static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
	struct fb_info *fbi = mfd->fbi;
	struct fb_fix_screeninfo *fix;
	int format;

	fix = &fbi->fix;
	format = mdp3_ctrl_get_source_format(mfd->fb_imgType);
	mutex_lock(&mdp3_session->lock);

	if (mdp3_session->overlay.id == ndx && ndx == 1) {
		struct mdp3_dma *dma = mdp3_session->dma;
		dma->source_config.format = format;
		dma->source_config.stride = fix->line_length;
		dma->output_config.pack_pattern =
			mdp3_ctrl_get_pack_pattern(mfd->fb_imgType);
		mdp3_clk_enable(1, 0);
		mdp3_session->dma->dma_config_source(dma);
		mdp3_clk_enable(0, 0);
		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
		mdp3_bufq_deinit(&mdp3_session->bufq_in);
	} else {
		rc = -EINVAL;
	}

	mutex_unlock(&mdp3_session->lock);

	return rc;
}
Beispiel #4
0
static int mdp3_histogram_stop(struct mdp3_session_data *session,
					u32 block)
{
	int ret;
	pr_debug("mdp3_histogram_stop\n");

	if (!session->dma->histo_op || block != MDP_BLOCK_DMA_P) {
		pr_err("mdp3_histogram_stop not supported\n");
		return -EINVAL;
	}

	mutex_lock(&session->histo_lock);

	if (!session->histo_status) {
		ret = 0;
		goto histogram_stop_err;
	}

	mdp3_clk_enable(1, 0);
	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_CANCEL);
	mdp3_clk_enable(0, 0);
	if (ret)
		pr_err("mdp3_histogram_stop error\n");

	session->histo_status = 0;

histogram_stop_err:
	mutex_unlock(&session->histo_lock);
	return ret;
}
Beispiel #5
0
static int mdp3_ctrl_lut_update(struct msm_fb_data_type *mfd,
				struct fb_cmap *cmap)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
	struct mdp3_dma_lut_config lut_config;
	struct mdp3_dma_lut lut;
	static u16 r[MDP_LUT_SIZE];
	static u16 g[MDP_LUT_SIZE];
	static u16 b[MDP_LUT_SIZE];

	if (!mdp3_session->dma->config_lut)
		return -EINVAL;

	if (cmap->start > MDP_LUT_SIZE || cmap->len > MDP_LUT_SIZE ||
			(cmap->start + cmap->len > MDP_LUT_SIZE)) {
		pr_err("mdp3_ctrl_lut_update invalid arguments\n");
		return  -EINVAL;
	}

	rc = copy_from_user(r + cmap->start,
					cmap->red, sizeof(u16)*cmap->len);
	rc |= copy_from_user(g + cmap->start,
					cmap->green, sizeof(u16)*cmap->len);
	rc |= copy_from_user(b + cmap->start,
					cmap->blue, sizeof(u16)*cmap->len);
	if (rc)
		return rc;

	lut_config.lut_enable = 7;
	lut_config.lut_sel = mdp3_session->lut_sel;
	lut_config.lut_position = 0;
	lut_config.lut_dirty = true;
	/* In HW the order is color0 = g, color1 = r and color2 = b*/
	lut.color0_lut = g;
	lut.color1_lut = r;
	lut.color2_lut = b;

	mutex_lock(&mdp3_session->lock);

	if (!mdp3_session->status) {
		pr_err("%s, display off!\n", __func__);
		mutex_unlock(&mdp3_session->lock);
		return -EPERM;
	}

	mdp3_clk_enable(1, 0);
	rc = mdp3_session->dma->config_lut(mdp3_session->dma, &lut_config,
					&lut);
	mdp3_clk_enable(0, 0);
	if (rc)
		pr_err("mdp3_ctrl_lut_update failed\n");

	mdp3_session->lut_sel = (mdp3_session->lut_sel + 1) % 2;

	mutex_unlock(&mdp3_session->lock);
	return rc;
}
Beispiel #6
0
static int mdp3_histogram_start(struct mdp3_session_data *session,
					struct mdp_histogram_start_req *req)
{
	int ret;
	struct mdp3_dma_histogram_config histo_config;

	pr_debug("mdp3_histogram_start\n");

	ret = mdp3_validate_start_req(req);
	if (ret)
		return ret;

	if (!session->dma->histo_op ||
		!session->dma->config_histo) {
		pr_err("mdp3_histogram_start not supported\n");
		return -EINVAL;
	}

	mutex_lock(&session->histo_lock);

	if (session->histo_status) {
		pr_err("mdp3_histogram_start already started\n");
		mutex_unlock(&session->histo_lock);
		return -EBUSY;
	}

	mdp3_clk_enable(1, 0);
	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_RESET);
	if (ret) {
		pr_err("mdp3_histogram_start reset error\n");
		goto histogram_start_err;
	}

	histo_config.frame_count = req->frame_cnt;
	histo_config.bit_mask = req->bit_mask;
	histo_config.auto_clear_en = 1;
	histo_config.bit_mask_polarity = 0;
	ret = session->dma->config_histo(session->dma, &histo_config);
	if (ret) {
		pr_err("mdp3_histogram_start config error\n");
		goto histogram_start_err;
	}

	ret = session->dma->histo_op(session->dma, MDP3_DMA_HISTO_OP_START);
	if (ret) {
		pr_err("mdp3_histogram_start config error\n");
		goto histogram_start_err;
	}

	session->histo_status = 1;

histogram_start_err:
	mdp3_clk_enable(0, 0);
	mutex_unlock(&session->histo_lock);
	return ret;
}
Beispiel #7
0
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
{
	struct mdp3_session_data *mdp3_session;
	struct mdp3_notification vsync_client;
	struct mdp3_notification *arg = NULL;

	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
		!mdp3_session->intf)
		return -ENODEV;

	if (!mdp3_session->status) {
		pr_debug("fb%d is not on yet", mfd->index);
		return -EINVAL;
	}
	if (enable) {
		vsync_client.handler = vsync_notify_handler;
		vsync_client.arg = mdp3_session;
		arg = &vsync_client;
	} else if (atomic_read(&mdp3_session->vsync_countdown)) {
		/*
		 * Now that vsync is no longer needed we will
		 * shutdown dsi clocks as soon as cnt down == 0
		 * for cmd mode panels
		 */
		vsync_client.handler = vsync_count_down;
		vsync_client.arg = mdp3_session;
		arg = &vsync_client;
		enable = 1;
	}

	mdp3_clk_enable(1, 0);
	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
	mdp3_clk_enable(0, 0);

	/*
	 * Need to fake vsync whenever dsi interface is not
	 * active or when dsi clocks are currently off
	 */
	if (enable && mdp3_session->status == 1
			&& (mdp3_session->vsync_before_commit ||
			!mdp3_session->intf->active)) {
		mod_timer(&mdp3_session->vsync_timer,
			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
	} else if (enable && !mdp3_session->clk_on) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_clk_enable(mfd, 1);
	} else if (!enable) {
		del_timer(&mdp3_session->vsync_timer);
	}

	return 0;
}
Beispiel #8
0
static int mdp3_overlay_set(struct msm_fb_data_type *mfd,
				struct mdp_overlay *req)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
	struct mdp3_dma *dma = mdp3_session->dma;
	struct fb_fix_screeninfo *fix;
	struct fb_info *fbi = mfd->fbi;
	int stride;
	int format;

	fix = &fbi->fix;
#if defined (CONFIG_MACH_MSM8X10_W5)
/* At booting up, Between LG Logo and Operation Animation showing, abnormal LG Logo is appearing one time.
Because LG Logo image format is RGB888, Android side image format is RGBA8888, both Image formats are mismatched.
So, We add the code to change MDP_RGBA_8888 to MDP_RGB_888 when is_done_drawing_logo is not "1".
is_done_drawing_logo is set to 1 at mdss_dsi_panel_off. 
*/
	if (!is_done_drawing_logo) {
		req->src.format = MDP_RGB_888;
	}
#endif

	stride = req->src.width * ppp_bpp(req->src.format);
	format = mdp3_ctrl_get_source_format(req->src.format);

	mutex_lock(&mdp3_session->lock);

	if (mdp3_session->overlay.id != req->id)
		pr_err("overlay was not released, continue to recover\n");

	mdp3_session->overlay = *req;
	if (req->id == MSMFB_NEW_REQUEST) {
		if (dma->source_config.stride != stride ||
				dma->source_config.width != req->src.width ||
				dma->source_config.height != req->src.height ||
				dma->source_config.format != format) {
			dma->source_config.width = req->src.width;
			dma->source_config.height = req->src.height,
			dma->source_config.format = format;
			dma->source_config.stride = stride;
			mdp3_clk_enable(1, 0);
			mdp3_session->dma->dma_config_source(dma);
			mdp3_clk_enable(0, 0);
		}
		mdp3_session->overlay.id = 1;
		req->id = 1;
	}

	mutex_unlock(&mdp3_session->lock);

	return rc;
}
Beispiel #9
0
static int mdp3_ctrl_clk_enable(struct msm_fb_data_type *mfd, int enable)
{
	struct mdp3_session_data *session;
	struct mdss_panel_data *panel;
	int rc = 0;

	pr_debug("mdp3_ctrl_clk_enable %d\n", enable);

	session = mfd->mdp.private1;
	panel = session->panel;

	if (!panel->event_handler)
		return 0;

	if ((enable && session->clk_on == 0) ||
				(!enable && session->clk_on == 1)) {
		rc = panel->event_handler(panel,
			MDSS_EVENT_PANEL_CLK_CTRL, (void *)enable);
		rc |= mdp3_clk_enable(enable, 1);
	} else {
		pr_debug("enable = %d, clk_on=%d\n", enable, session->clk_on);
	}

	session->clk_on = enable;
	return rc;
}
static int mdp3_ctrl_res_req_clk(struct msm_fb_data_type *mfd, int status)
{
	int rc = 0;
	if (status) {

		mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE);
		mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE);

		rc = mdp3_clk_enable(true);
		if (rc)
			return rc;

	} else {
		rc = mdp3_clk_enable(false);
	}
	return rc;
}
Beispiel #11
0
static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
{
	struct mdp3_session_data *mdp3_session;
	struct mdp3_notification vsync_client;
	struct mdp3_notification *arg = NULL;

	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
		!mdp3_session->intf)
		return -ENODEV;

	if (!mdp3_session->status) {
		pr_debug("fb%d is not on yet", mfd->index);
		return -EINVAL;
	}
	if (enable) {
		vsync_client.handler = vsync_notify_handler;
		vsync_client.arg = mdp3_session;
		arg = &vsync_client;
	} else if (atomic_read(&mdp3_session->vsync_countdown)) {
		vsync_client.handler = vsync_count_down;
		vsync_client.arg = mdp3_session;
		arg = &vsync_client;
		enable = 1;
	}

	mdp3_clk_enable(1, 0);
	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
	mdp3_clk_enable(0, 0);

	if (enable && mdp3_session->status == 1
			&& (mdp3_session->vsync_before_commit ||
			!mdp3_session->intf->active)) {
		mod_timer(&mdp3_session->vsync_timer,
			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
	} else if (enable && !mdp3_session->clk_on) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_clk_enable(mfd, 1);
	} else if (!enable) {
		del_timer(&mdp3_session->vsync_timer);
	}

	return 0;
}
static int mdp3_overlay_set(struct msm_fb_data_type *mfd,
				struct mdp_overlay *req)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
	struct mdp3_dma *dma = mdp3_session->dma;
	struct fb_fix_screeninfo *fix;
	struct fb_info *fbi = mfd->fbi;
	int stride;
	int format;

	fix = &fbi->fix;
	stride = req->src.width * ppp_bpp(req->src.format);
	format = mdp3_ctrl_get_source_format(req->src.format);

	mutex_lock(&mdp3_session->lock);

	if (mdp3_session->overlay.id != req->id)
		pr_err("overlay was not released, continue to recover\n");

	mdp3_session->overlay = *req;
	if (req->id == MSMFB_NEW_REQUEST) {
		if (dma->source_config.stride != stride ||
				dma->source_config.width != req->src.width ||
				dma->source_config.height != req->src.height ||
				dma->source_config.format != format) {
			dma->source_config.width = req->src.width;
			dma->source_config.height = req->src.height,
			dma->source_config.format = format;
			dma->source_config.stride = stride;
			mdp3_clk_enable(1, 0);
			mdp3_session->dma->dma_config_source(dma);
			mdp3_clk_enable(0, 0);
		}
		mdp3_session->overlay.id = 1;
		req->id = 1;
	}

	mutex_unlock(&mdp3_session->lock);

	return rc;
}
Beispiel #13
0
static int mdp3_csc_config(struct mdp3_session_data *session,
					struct mdp_csc_cfg_data *data)
{
	struct mdp3_dma_color_correct_config config;
	struct mdp3_dma_ccs ccs;
	int ret = -EINVAL;

	if (!data->csc_data.csc_mv || !data->csc_data.csc_pre_bv ||
		!data->csc_data.csc_post_bv || !data->csc_data.csc_pre_lv ||
			!data->csc_data.csc_post_lv) {
		pr_err("%s : Invalid csc vectors", __func__);
		return -EINVAL;
	}

	session->cc_vect_sel = (session->cc_vect_sel + 1) % 2;

	config.ccs_enable = 1;
	config.ccs_sel = session->cc_vect_sel;
	config.pre_limit_sel = session->cc_vect_sel;
	config.post_limit_sel = session->cc_vect_sel;
	config.pre_bias_sel = session->cc_vect_sel;
	config.post_bias_sel = session->cc_vect_sel;
	config.ccs_dirty = true;

	ccs.mv = data->csc_data.csc_mv;
	ccs.pre_bv = data->csc_data.csc_pre_bv;
	ccs.post_bv = data->csc_data.csc_post_bv;
	ccs.pre_lv = data->csc_data.csc_pre_lv;
	ccs.post_lv = data->csc_data.csc_post_lv;

	mutex_lock(&session->lock);
	mdp3_clk_enable(1, 0);
	ret = session->dma->config_ccs(session->dma, &config, &ccs);
	mdp3_clk_enable(0, 0);
	mutex_unlock(&session->lock);
	return ret;
}
Beispiel #14
0
static int mdp3_histogram_collect(struct mdp3_session_data *session,
				struct mdp_histogram_data *hist)
{
	int ret;
	struct mdp3_dma_histogram_data *mdp3_histo;

	pr_debug("%s\n", __func__);
	if (!session->dma->get_histo) {
		pr_err("mdp3_histogram_collect not supported\n");
		return -EINVAL;
	}

	if (!session->clk_on) {
		pr_debug("mdp/dsi clock off currently\n");
		return -EPERM;
	}

	mutex_lock(&session->histo_lock);

	if (!session->histo_status) {
		pr_err("mdp3_histogram_collect not started\n");
		mutex_unlock(&session->histo_lock);
		return -EPERM;
	}

	mutex_unlock(&session->histo_lock);

	mdp3_clk_enable(1, 0);
	ret = session->dma->get_histo(session->dma);
	mdp3_clk_enable(0, 0);
	if (ret) {
		pr_debug("mdp3_histogram_collect error = %d\n", ret);
		return ret;
	}

	mdp3_histo = &session->dma->histo_data;

	ret = copy_to_user(hist->c0, mdp3_histo->r_data,
			sizeof(uint32_t) * MDP_HISTOGRAM_BIN_NUM);
	if (ret)
		return ret;

	ret = copy_to_user(hist->c1, mdp3_histo->g_data,
			sizeof(uint32_t) * MDP_HISTOGRAM_BIN_NUM);
	if (ret)
		return ret;

	ret = copy_to_user(hist->c2, mdp3_histo->b_data,
			sizeof(uint32_t) * MDP_HISTOGRAM_BIN_NUM);
	if (ret)
		return ret;

	ret = copy_to_user(hist->extra_info, mdp3_histo->extra,
			sizeof(uint32_t) * 2);
	if (ret)
		return ret;

	hist->bin_cnt = MDP_HISTOGRAM_BIN_NUM;
	hist->block = MDP_BLOCK_DMA_P;
	return ret;
}
Beispiel #15
0
static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
{
	struct fb_info *fbi;
	struct mdp3_session_data *mdp3_session;
	u32 offset;
	int bpp;
	struct mdss_panel_info *panel_info;
	int rc;

	pr_debug("mdp3_ctrl_pan_display\n");
	if (!mfd || !mfd->mdp.private1)
		return;

	panel_info = mfd->panel_info;
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
	if (!mdp3_session || !mdp3_session->dma)
		return;

	if (mdp3_session->in_splash_screen) {
		pr_debug("continuous splash screen, IOMMU not attached\n");
		rc = mdp3_ctrl_reset(mfd);
		if (rc) {
			pr_err("fail to reset display\n");
			return;
		}
	}

	mutex_lock(&mdp3_session->lock);

	if (!mdp3_session->status) {
		pr_err("mdp3_ctrl_pan_display, display off!\n");
		goto pan_error;
	}

	fbi = mfd->fbi;

	bpp = fbi->var.bits_per_pixel / 8;
	offset = fbi->var.xoffset * bpp +
		 fbi->var.yoffset * fbi->fix.line_length;

	if (offset > fbi->fix.smem_len) {
		pr_err("invalid fb offset=%u total length=%u\n",
			offset, fbi->fix.smem_len);
		goto pan_error;
	}

	if (mfd->fbi->screen_base) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_BEGIN);
		mdp3_ctrl_clk_enable(mfd, 1);
		rc = mdp3_session->dma->update(mdp3_session->dma,
				(void *)(int)(mfd->iova + offset),
				mdp3_session->intf);
		/* This is for the previous frame */
		if (rc < 0) {
			mdp3_ctrl_notify(mdp3_session,
				MDP_NOTIFY_FRAME_TIMEOUT);
		} else {
			if (mdp3_ctrl_get_intf_type(mfd) ==
						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
				mdp3_ctrl_notify(mdp3_session,
					MDP_NOTIFY_FRAME_DONE);
			}
		}
		mdp3_session->dma_active = 1;
		init_completion(&mdp3_session->dma_completion);
		mdp3_ctrl_notify(mdp3_session, MDP_NOTIFY_FRAME_FLUSHED);
	} else {
		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
		mdp3_clk_enable(1, 0);
		mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
		mdp3_clk_enable(0, 0);
	}

	if (mdp3_session->first_commit) {
		/*wait for one frame time to ensure frame is sent to panel*/
		msleep(1000 / panel_info->mipi.frame_rate);
		mdp3_session->first_commit = false;
	}

	mdp3_session->vsync_before_commit = 0;

pan_error:
	mutex_unlock(&mdp3_session->lock);
}
Beispiel #16
0
static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
{
	int rc = 0;
	struct mdp3_session_data *mdp3_session;
	struct mdss_panel_data *panel;

	pr_debug("mdp3_ctrl_off\n");
	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
		!mdp3_session->intf) {
		pr_err("mdp3_ctrl_on no device");
		return -ENODEV;
	}

	panel = mdp3_session->panel;
	mutex_lock(&mdp3_session->lock);
	mutex_lock(&mdp3_session->offlock);

	if (!mdp3_session->status) {
		pr_debug("fb%d is off already", mfd->index);
		goto off_error;
	}

	mdp3_ctrl_clk_enable(mfd, 1);

	mdp3_histogram_stop(mdp3_session, MDP_BLOCK_DMA_P);

	rc = mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
	if (rc)
		pr_debug("fail to stop the MDP3 dma\n");


	if (panel->event_handler)
		rc = panel->event_handler(panel, MDSS_EVENT_PANEL_OFF, NULL);
	if (rc)
		pr_err("fail to turn off the panel\n");

	mdp3_irq_deregister();

	pr_debug("mdp3_ctrl_off stop clock\n");
	if (mdp3_session->clk_on) {
		rc = mdp3_clk_enable(0, 1);
		if (rc)
			pr_err("mdp clock resource release failed\n");

		pr_debug("mdp3_ctrl_off stop dsi controller\n");
		if (panel->event_handler)
			rc = panel->event_handler(panel,
				MDSS_EVENT_BLANK, NULL);
		if (rc)
			pr_err("fail to turn off the panel\n");
	}
	mdp3_clk_unprepare();

	pr_debug("mdp3_ctrl_off release bus\n");
	rc = mdp3_ctrl_res_req_bus(mfd, 0);
	if (rc)
		pr_err("mdp bus resource release failed\n");

	rc = mdp3_iommu_disable(MDP3_CLIENT_DMA_P);
	if (rc)
		pr_err("fail to dettach MDP DMA SMMU\n");

	mdp3_ctrl_notifier_unregister(mdp3_session,
		&mdp3_session->mfd->mdp_sync_pt_data.notifier);
	mdp3_batfet_ctrl(false);
	mdp3_session->vsync_enabled = 0;
	atomic_set(&mdp3_session->vsync_countdown, 0);
	mdp3_session->clk_on = 0;
off_error:
	mdp3_session->status = 0;
	mdp3_bufq_deinit(&mdp3_session->bufq_out);
	if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
		mdp3_bufq_deinit(&mdp3_session->bufq_in);
	}
	mutex_unlock(&mdp3_session->offlock);
	mutex_unlock(&mdp3_session->lock);
	return 0;
}
Beispiel #17
0
static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
{
	struct fb_info *fbi;
	struct mdp3_session_data *mdp3_session;
	u32 offset;
	int bpp;
	struct mdss_panel_info *panel_info = mfd->panel_info;
#if defined(CONFIG_FB_MSM_MIPI_TIANMA_CMD_HVGA_PT) || defined(CONFIG_MACH_MSM8X10_W5) || defined(CONFIG_MACH_MSM8X10_W6)
	bool reset_done = false;
	struct mdss_panel_data *panel;
#endif

	pr_debug("mdp3_ctrl_pan_display\n");
	if (!mfd || !mfd->mdp.private1)
		return;

	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
	if (!mdp3_session || !mdp3_session->dma)
		return;

#if defined(CONFIG_FB_MSM_MIPI_TIANMA_CMD_HVGA_PT) || defined(CONFIG_MACH_MSM8X10_W5) || defined(CONFIG_MACH_MSM8X10_W6)
	panel = mdp3_session->panel;
#endif
	if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
		pr_debug("continuous splash screen, IOMMU not attached\n");
		mdp3_ctrl_reset(mfd);
#if defined(CONFIG_FB_MSM_MIPI_TIANMA_CMD_HVGA_PT) || defined(CONFIG_MACH_MSM8X10_W5) || defined(CONFIG_MACH_MSM8X10_W6)
		reset_done = true;
#endif
	}
	mdp3_release_splash_memory();

	mutex_lock(&mdp3_session->lock);

	if (!mdp3_session->status) {
		pr_err("mdp3_ctrl_pan_display, display off!\n");
		goto pan_error;
	}

	fbi = mfd->fbi;

	bpp = fbi->var.bits_per_pixel / 8;
	offset = fbi->var.xoffset * bpp +
		 fbi->var.yoffset * fbi->fix.line_length;

	if (offset > fbi->fix.smem_len) {
		pr_err("invalid fb offset=%u total length=%u\n",
			offset, fbi->fix.smem_len);
		goto pan_error;
	}

	if (mfd->fbi->screen_base) {
		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
		mdp3_ctrl_clk_enable(mfd, 1);
		mdp3_session->dma->update(mdp3_session->dma,
				(void *)mfd->iova + offset,
				mdp3_session->intf);
	} else {
		pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
		mdp3_clk_enable(1, 0);
		mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
		mdp3_clk_enable(0, 0);
	}

	if (mdp3_session->first_commit) {
		/*wait for one frame time to ensure frame is sent to panel*/
		msleep(1000 / panel_info->mipi.frame_rate);
		mdp3_session->first_commit = false;
	}
#if defined(CONFIG_FB_MSM_MIPI_TIANMA_CMD_HVGA_PT) || defined(CONFIG_MACH_MSM8X10_W5) || defined(CONFIG_MACH_MSM8X10_W6)
	if (reset_done && (panel && panel->set_backlight)){
		panel->set_backlight(panel, panel->panel_info.bl_max);
    }
#endif

	mdp3_session->vsync_before_commit = 0;

pan_error:
	mutex_unlock(&mdp3_session->lock);
}