int decon_get_hdmi_config(struct decon_device *decon,
               struct exynos_hdmi_data *hdmi_data)
{
	struct v4l2_control ctrl;
	int ret = 0;

	ctrl.id = 0;
	ctrl.value = 0;
	decon_dbg("state : %d\n", hdmi_data->state);

	switch (hdmi_data->state) {
	case EXYNOS_HDMI_STATE_PRESET:
		ret = v4l2_subdev_call(decon->output_sd, video, g_dv_timings, &hdmi_data->timings);
		if (ret)
			decon_err("failed to get current timings\n");
		else
			ret = find_subdev_hdmi(decon);
		decon_dbg("%dx%d@%s %lldHz %s(%#x)\n", hdmi_data->timings.bt.width,
			hdmi_data->timings.bt.height,
			hdmi_data->timings.bt.interlaced ? "I" : "P",
			hdmi_data->timings.bt.pixelclock,
			hdmi_data->timings.type ? "S3D" : "2D",
			hdmi_data->timings.type);
		break;
	case EXYNOS_HDMI_STATE_ENUM_PRESET:
		ret = v4l2_subdev_call(decon->output_sd, video, enum_dv_timings, &hdmi_data->etimings);
		if (ret)
			decon_err("failed to enumerate timings\n");
		break;
	case EXYNOS_HDMI_STATE_CEC_ADDR:
		ctrl.id = V4L2_CID_TV_SOURCE_PHY_ADDR;
		ret = v4l2_subdev_call(decon->output_sd, core, g_ctrl, &ctrl);
		if (ret)
			decon_err("failed to get physical address for CEC\n");
		hdmi_data->cec_addr = ctrl.value;
		decon_dbg("get physical address for CEC: %#x\n",
					hdmi_data->cec_addr);
		break;
	case EXYNOS_HDMI_STATE_AUDIO:
		ctrl.id = V4L2_CID_TV_MAX_AUDIO_CHANNELS;
		ret = v4l2_subdev_call(decon->output_sd, core, g_ctrl, &ctrl);
		if (ret)
			decon_err("failed to get hdmi audio information\n");
		hdmi_data->audio_info = ctrl.value;
		break;
	default:
		decon_warn("unrecongnized state %u", hdmi_data->state);
		ret = -EINVAL;
		break;
	}

	return ret;
}
Exemple #2
0
irqreturn_t decon_t_irq_handler(int irq, void *dev_data)
{
	struct decon_device *decon = dev_data;
	u32 irq_sts_reg;

	spin_lock(&decon->slock);
	if ((decon->state == DECON_STATE_OFF) ||
		(decon->state == DECON_STATE_LPD)) {
		goto irq_end;
	}

	irq_sts_reg = decon_reg_get_interrupt_and_clear(decon->id);

	if (irq_sts_reg & INTERRUPT_FIFO_LEVEL_INT_EN) {
		DISP_SS_EVENT_LOG(DISP_EVT_UNDERRUN, &decon->sd, ktime_set(0, 0));
		decon_err("DECON_T FIFO underrun\n");
	}
	if (irq_sts_reg & INTERRUPT_FRAME_DONE_INT_EN) {
		decon_lpd_trig_reset(decon);
		DISP_SS_EVENT_LOG(DISP_EVT_DECON_FRAMEDONE, &decon->sd, ktime_set(0, 0));
		decon_dbg("%s Frame Done is occured. timeline:%d, %d\n",
				__func__, decon->timeline->value, decon->timeline_max);
	}
	if (irq_sts_reg & INTERRUPT_RESOURCE_CONFLICT_INT_EN)
		DISP_SS_EVENT_LOG(DISP_EVT_RSC_CONFLICT, &decon->sd, ktime_set(0, 0));
irq_end:
	spin_unlock(&decon->slock);
	return IRQ_HANDLED;
}
Exemple #3
0
void decon_t_set_clocks(struct decon_device *decon)
{
	struct device *dev = decon->dev;
	struct decon_clocks clks;
	struct decon_param p;

	decon_to_init_param(decon, &p);
	decon_reg_get_clock_ratio(&clks, p.lcd_info);

	/* ECLK */
	decon_clk_set_rate(dev, decon->res.eclk,
			NULL, clks.decon[CLK_ID_ECLK] * MHZ);
	decon_clk_set_rate(dev, decon->res.eclk_leaf,
			NULL, clks.decon[CLK_ID_ECLK] * MHZ);

#if defined(CONFIG_EXYNOS8890_BTS_OPTIMIZATION)
	/* TODO: hard-coded 42 will be changed
	 * default MIC factor is 3, So default VCLK is 42 for calculating DISP */
	decon->vclk_factor = 42 * DECON_PIX_PER_CLK;
#endif

	decon_dbg("%s: pclk %ld eclk %ld Mhz\n",
		__func__,
		clk_get_rate(decon->res.pclk) / MHZ,
		clk_get_rate(decon->res.eclk_leaf) / MHZ);

	return;
}
int decon_set_hdmi_config(struct decon_device *decon,
               struct exynos_hdmi_data *hdmi_data)
{
	struct v4l2_control ctrl;
	int ret = 0;

	decon_dbg("state : %d\n", hdmi_data->state);

	switch (hdmi_data->state) {
	case EXYNOS_HDMI_STATE_PRESET:
		ret = v4l2_subdev_call(decon->output_sd, video, s_dv_timings, &hdmi_data->timings);
		if (ret)
			decon_err("failed to set timings newly\n");
		else
			ret = find_subdev_hdmi(decon);
		decon_dbg("%dx%d@%s %lldHz %s(%#x)\n", hdmi_data->timings.bt.width,
			hdmi_data->timings.bt.height,
			hdmi_data->timings.bt.interlaced ? "I" : "P",
			hdmi_data->timings.bt.pixelclock,
			hdmi_data->timings.type ? "S3D" : "2D",
			hdmi_data->timings.type);
		break;
	case EXYNOS_HDMI_STATE_HDCP:
		ctrl.id = V4L2_CID_TV_HDCP_ENABLE;
		ctrl.value = hdmi_data->hdcp;
		ret = v4l2_subdev_call(decon->output_sd, core, s_ctrl, &ctrl);
		if (ret)
			decon_err("failed to enable HDCP\n");
		decon_dbg("HDCP %s\n", ctrl.value ? "enabled" : "disabled");
		break;
	case EXYNOS_HDMI_STATE_AUDIO:
		ctrl.id = V4L2_CID_TV_SET_NUM_CHANNELS;
		ctrl.value = hdmi_data->audio_info;
		ret = v4l2_subdev_call(decon->output_sd, core, s_ctrl, &ctrl);
		if (ret)
			decon_err("failed to set hdmi audio information\n");
		break;
	default:
		decon_warn("unrecongnized state %u", hdmi_data->state);
		ret = -EINVAL;
		break;
	}

	return ret;
}
irqreturn_t decon_ext_dsi_irq_handler(int irq, void *dev_data)
{
	struct decon_device *decon = dev_data;
	ktime_t timestamp = ktime_get();
	u32 irq_sts_reg;
	u32 wb_irq_sts_reg;

	spin_lock(&decon->slock);

	irq_sts_reg = decon_read(decon->id, VIDINTCON1);
	wb_irq_sts_reg = decon_read(decon->id, VIDINTCON3);
	if (irq_sts_reg & VIDINTCON1_INT_FRAME) {
		/* VSYNC interrupt, accept it */
		decon_write_mask(decon->id, VIDINTCON1, ~0, VIDINTCON1_INT_FRAME);
		decon->vsync_info.timestamp = timestamp;
		wake_up_interruptible_all(&decon->vsync_info.wait);
	}
	if (irq_sts_reg & VIDINTCON1_INT_FIFO) {
		decon_err("DECON-ext FIFO underrun\n");
		decon_write_mask(decon->id, VIDINTCON1, ~0, VIDINTCON1_INT_FIFO);
	}
	if (irq_sts_reg & VIDINTCON1_INT_I80) {
		decon_write_mask(decon->id, VIDINTCON1, ~0, VIDINTCON1_INT_I80);
		wake_up_interruptible_all(&decon->wait_frmdone);
	}
#if 0 
	if (wb_irq_sts_reg & VIDINTCON3_WB_FRAME_DONE) {
		decon_dbg("write-back frame done\n");
		DISP_SS_EVENT_LOG(DISP_EVT_WB_FRAME_DONE, &decon->sd, ktime_set(0, 0));
		decon_write_mask(decon->id, VIDINTCON3, ~0, VIDINTCON3_WB_FRAME_DONE);
		atomic_set(&decon->wb_done, STATE_DONE);
		wake_up_interruptible_all(&decon->wait_frmdone);
		decon_reg_per_frame_off(decon->id);
		decon_reg_update_standalone(decon->id);
		decon_reg_wb_swtrigger(decon->id);
		decon_reg_wait_stop_status_timeout(decon->id, 20 * 1000);
	}
#endif
	spin_unlock(&decon->slock);
	return IRQ_HANDLED;
}
int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
	struct decon_win *win = info->par;
	struct decon_device *decon = win->decon;
	int x, y;
	unsigned long long hz;

	var->xres_virtual = max(var->xres_virtual, var->xres);
	var->yres_virtual = max(var->yres_virtual, var->yres);

	if (!decon_validate_x_alignment(decon, 0, var->xres,
			var->bits_per_pixel))
		return -EINVAL;

	/* always ensure these are zero, for drop through cases below */
	var->transp.offset = 0;
	var->transp.length = 0;

	switch (var->bits_per_pixel) {
	case 1:
	case 2:
	case 4:
	case 8:
		var->red.offset		= 4;
		var->green.offset	= 2;
		var->blue.offset	= 0;
		var->red.length		= 5;
		var->green.length	= 3;
		var->blue.length	= 2;
		var->transp.offset	= 7;
		var->transp.length	= 1;
		break;

	case 19:
		/* 666 with one bit alpha/transparency */
		var->transp.offset	= 18;
		var->transp.length	= 1;
	case 18:
		var->bits_per_pixel	= 32;

		/* 666 format */
		var->red.offset		= 12;
		var->green.offset	= 6;
		var->blue.offset	= 0;
		var->red.length		= 6;
		var->green.length	= 6;
		var->blue.length	= 6;
		break;

	case 16:
		/* 16 bpp, 565 format */
		var->red.offset		= 11;
		var->green.offset	= 5;
		var->blue.offset	= 0;
		var->red.length		= 5;
		var->green.length	= 6;
		var->blue.length	= 5;
		break;

	case 32:
	case 28:
	case 25:
		var->transp.length	= var->bits_per_pixel - 24;
		var->transp.offset	= 24;
		/* drop through */
	case 24:
		/* our 24bpp is unpacked, so 32bpp */
		var->bits_per_pixel	= 32;
		var->red.offset		= 16;
		var->red.length		= 8;
		var->green.offset	= 8;
		var->green.length	= 8;
		var->blue.offset	= 0;
		var->blue.length	= 8;
		break;

	default:
		decon_err("invalid bpp %d\n", var->bits_per_pixel);
		return -EINVAL;
	}

	if (decon->pdata->psr_mode == DECON_MIPI_COMMAND_MODE) {
		x = var->xres;
		y = var->yres;
	} else {
		x = var->xres + var->left_margin + var->right_margin + var->hsync_len;
		y = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
	}
	hz = 1000000000000ULL;		/* 1e12 picoseconds per second */

	hz += (x * y) / 2;
	do_div(hz, x * y);		/* divide by x * y with rounding */

	hz += var->pixclock / 2;
	do_div(hz, var->pixclock);	/* divide by pixclock with rounding */

	win->fps = hz;
	decon_dbg("xres:%d, yres:%d, v_xres:%d, v_yres:%d, bpp:%d, %lldhz\n",
			var->xres, var->yres, var->xres_virtual,
			var->yres_virtual, var->bits_per_pixel, hz);

	return 0;
}