Exemple #1
0
static void tegra_dc_rgb_enable(struct tegra_dc *dc)
{
	int i;
	u32 out_sel_pintable[ARRAY_SIZE(tegra_dc_rgb_enable_out_sel_pintable)];

	tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
			PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
			DC_CMD_DISPLAY_POWER_CONTROL);

	tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);

	if (dc->out->out_pins) {
		tegra_dc_set_out_pin_polars(dc, dc->out->out_pins,
			dc->out->n_out_pins);
		tegra_dc_write_table(dc, tegra_dc_rgb_enable_partial_pintable);
	} else {
		tegra_dc_write_table(dc, tegra_dc_rgb_enable_pintable);
	}

	memcpy(out_sel_pintable, tegra_dc_rgb_enable_out_sel_pintable,
		sizeof(tegra_dc_rgb_enable_out_sel_pintable));

	if (dc->out && dc->out->out_sel_configs) {
		u8 *out_sels = dc->out->out_sel_configs;
		for (i = 0; i < dc->out->n_out_sel_configs; i++) {
			switch (out_sels[i]) {
			case TEGRA_PIN_OUT_CONFIG_SEL_LM1_M1:
				out_sel_pintable[5*2+1] =
					(out_sel_pintable[5*2+1] &
					~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
					PIN5_LM1_LCD_M1_OUTPUT_M1;
				break;
			case TEGRA_PIN_OUT_CONFIG_SEL_LM1_LD21:
				out_sel_pintable[5*2+1] =
					(out_sel_pintable[5*2+1] &
					~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
					PIN5_LM1_LCD_M1_OUTPUT_LD21;
				break;
			case TEGRA_PIN_OUT_CONFIG_SEL_LM1_PM1:
				out_sel_pintable[5*2+1] =
					(out_sel_pintable[5*2+1] &
					~PIN5_LM1_LCD_M1_OUTPUT_MASK) |
					PIN5_LM1_LCD_M1_OUTPUT_PM1;
				break;
			default:
				dev_err(&dc->ndev->dev,
					"Invalid pin config[%d]: %d\n",
					 i, out_sels[i]);
				break;
			}
		}
	}

	tegra_dc_write_table(dc, out_sel_pintable);

	/* Inform DC register updated */
	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
}
Exemple #2
0
void tegra_dc_disable_crc(struct tegra_dc *dc)
{
	tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL);
	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);

	tegra_dc_io_end(dc);
}
int tegra_dc_ext_set_cursor(struct tegra_dc_ext_user *user,
			    struct tegra_dc_ext_cursor *args)
{
	struct tegra_dc_ext *ext = user->ext;
	struct tegra_dc *dc = ext->dc;
	u32 val;
	bool enable;
	int ret;

	mutex_lock(&ext->cursor.lock);

	if (ext->cursor.user != user) {
		ret = -EACCES;
		goto unlock;
	}

	if (!ext->enabled) {
		ret = -ENXIO;
		goto unlock;
	}

	enable = !!(args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_VISIBLE);

	mutex_lock(&dc->lock);
	tegra_dc_io_start(dc);
	tegra_dc_hold_dc_out(dc);

	val = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
	if (!!(val & CURSOR_ENABLE) != enable) {
		val &= ~CURSOR_ENABLE;
		if (enable)
			val |= CURSOR_ENABLE;
		tegra_dc_writel(dc, val, DC_DISP_DISP_WIN_OPTIONS);
	}

	tegra_dc_writel(dc, CURSOR_POSITION(args->x, args->y),
		DC_DISP_CURSOR_POSITION);

	tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);

	/* TODO: need to sync here?  hopefully can avoid this, but need to
	 * figure out interaction w/ rest of GENERAL_ACT_REQ */

	tegra_dc_release_dc_out(dc);
	tegra_dc_io_end(dc);
	mutex_unlock(&dc->lock);

	mutex_unlock(&ext->cursor.lock);

	return 0;

unlock:
	mutex_unlock(&ext->cursor.lock);

	return ret;
}
void tegra_dc_rgb_enable(struct tegra_dc *dc)
{
	tegra_dc_writel(dc, PW0_ENABLE | PW1_ENABLE | PW2_ENABLE | PW3_ENABLE |
			PW4_ENABLE | PM0_ENABLE | PM1_ENABLE,
			DC_CMD_DISPLAY_POWER_CONTROL);

	tegra_dc_writel(dc, DISP_CTRL_MODE_C_DISPLAY, DC_CMD_DISPLAY_COMMAND);

	tegra_dc_write_table(dc, tegra_dc_rgb_enable_pintable);
}
Exemple #5
0
void tegra_dc_enable_crc(struct tegra_dc *dc)
{
	u32 val;
	tegra_dc_io_start(dc);

	val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
		CRC_ENABLE_ENABLE;
	tegra_dc_writel(dc, val, DC_COM_CRC_CONTROL);
	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
}
Exemple #6
0
void tegra_dc_disable_crc(struct tegra_dc *dc)
{
	mutex_lock(&dc->lock);
	tegra_dc_hold_dc_out(dc);
	tegra_dc_writel(dc, 0x0, DC_COM_CRC_CONTROL);
	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);

	tegra_dc_io_end(dc);
	tegra_dc_release_dc_out(dc);
	mutex_unlock(&dc->lock);
}
Exemple #7
0
static void tegra_dc_reset_worker(struct work_struct *work)
{
	struct tegra_dc *dc =
		container_of(work, struct tegra_dc, reset_work);

	unsigned long val = 0;

	mutex_lock(&shared_lock);

	dev_warn(&dc->ndev->dev,
		"overlay stuck in underflow state.  resetting.\n");

	tegra_dc_ext_disable(dc->ext);

	mutex_lock(&dc->lock);

	if (dc->enabled == false)
		goto unlock;

	dc->enabled = false;

	/*
	 * off host read bus
	 */
	val = tegra_dc_readl(dc, DC_CMD_CONT_SYNCPT_VSYNC);
	val &= ~(0x00000100);
	tegra_dc_writel(dc, val, DC_CMD_CONT_SYNCPT_VSYNC);

	/*
	 * set DC to STOP mode
	 */
	tegra_dc_writel(dc, DISP_CTRL_MODE_STOP, DC_CMD_DISPLAY_COMMAND);

	msleep(10);

	_tegra_dc_controller_disable(dc);

	/* _tegra_dc_controller_reset_enable deasserts reset */
	_tegra_dc_controller_reset_enable(dc);

	dc->enabled = true;

	/* reopen host read bus */
	val = tegra_dc_readl(dc, DC_CMD_CONT_SYNCPT_VSYNC);
	val &= ~(0x00000100);
	val |= 0x100;
	tegra_dc_writel(dc, val, DC_CMD_CONT_SYNCPT_VSYNC);

unlock:
	mutex_unlock(&dc->lock);
	mutex_unlock(&shared_lock);
	trace_printk("%s:reset complete\n", dc->ndev->name);
}
static void set_cursor_image_hw(struct tegra_dc *dc,
				struct tegra_dc_ext_cursor_image *args,
				dma_addr_t phys_addr)
{
	unsigned long val;
	int clip_win;

	tegra_dc_writel(dc,
		CURSOR_COLOR(args->foreground.r,
			     args->foreground.g,
			     args->foreground.b),
		DC_DISP_CURSOR_FOREGROUND);
	tegra_dc_writel(dc,
		CURSOR_COLOR(args->background.r,
			     args->background.g,
			     args->background.b),
		DC_DISP_CURSOR_BACKGROUND);

	BUG_ON(phys_addr & ~CURSOR_START_ADDR_MASK);

	switch (TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(args->flags)) {
	case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64:
		val = CURSOR_SIZE_64;
		break;
	case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128:
		val = CURSOR_SIZE_128;
		break;
	case TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256:
		val = CURSOR_SIZE_256;
		break;
	default:
		val = 0;
	}

	/* Get the cursor clip window number */
	clip_win = CURSOR_CLIP_GET_WINDOW(tegra_dc_readl(dc,
					  DC_DISP_CURSOR_START_ADDR));
	val |= clip_win;

	tegra_dc_writel(dc,
		val | CURSOR_START_ADDR(((unsigned long) phys_addr)),
		DC_DISP_CURSOR_START_ADDR);

	if (args->flags & TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL)
		tegra_dc_writel(dc,
				CURSOR_MODE_SELECT(1),
				DC_DISP_BLEND_CURSOR_CONTROL);
	else
		tegra_dc_writel(dc,
				CURSOR_MODE_SELECT(0),
				DC_DISP_BLEND_CURSOR_CONTROL);
}
Exemple #9
0
static irqreturn_t tegra_dc_irq(int irq, void *ptr)
{
#ifndef CONFIG_TEGRA_FPGA_PLATFORM
	struct tegra_dc *dc = ptr;
	unsigned long status;
	unsigned long underflow_mask;
	u32 val;

	if (!nvhost_module_powered_ext(nvhost_get_parent(dc->ndev))) {
		WARN(1, "IRQ when DC not powered!\n");
		tegra_dc_io_start(dc);
		status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
		tegra_dc_writel(dc, status, DC_CMD_INT_STATUS);
		tegra_dc_io_end(dc);
		return IRQ_HANDLED;
	}

	/* clear all status flags except underflow, save those for the worker */
	status = tegra_dc_readl(dc, DC_CMD_INT_STATUS);
	tegra_dc_writel(dc, status & ~ALL_UF_INT, DC_CMD_INT_STATUS);
	val = tegra_dc_readl(dc, DC_CMD_INT_MASK);
	tegra_dc_writel(dc, val & ~ALL_UF_INT, DC_CMD_INT_MASK);

	/*
	 * Overlays can get thier internal state corrupted during and underflow
	 * condition.  The only way to fix this state is to reset the DC.
	 * if we get 4 consecutive frames with underflows, assume we're
	 * hosed and reset.
	 */
	underflow_mask = status & ALL_UF_INT;

	/* Check underflow */
	if (underflow_mask) {
		dc->underflow_mask |= underflow_mask;
		schedule_delayed_work(&dc->underflow_work,
			msecs_to_jiffies(1));
	}

	if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
		tegra_dc_one_shot_irq(dc, status);
	else
		tegra_dc_continuous_irq(dc, status);

	return IRQ_HANDLED;
#else /* CONFIG_TEGRA_FPGA_PLATFORM */
	return IRQ_NONE;
#endif /* !CONFIG_TEGRA_FPGA_PLATFORM */
}
Exemple #10
0
/* Periodic update */
bool nvsd_update_brightness(struct tegra_dc *dc)
{
	u32 val = 0;
	int cur_sd_brightness;

	if (sd_brightness) {
		if (atomic_read(&man_k_until_blank)) {
			val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
			val &= ~SD_CORRECTION_MODE_MAN;
			tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);
			atomic_set(&man_k_until_blank, 0);
		}

		cur_sd_brightness = atomic_read(sd_brightness);

		/* read brightness value */
		val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL);
		val = SD_BLC_BRIGHTNESS(val);

		if (val != (u32)cur_sd_brightness) {
			/* set brightness value and note the update */
			atomic_set(sd_brightness, (int)val);
			return true;
		}
	}

	/* No update needed. */
	return false;
}
Exemple #11
0
static void tegra_dc_set_scaling_filter(struct tegra_dc *dc)
{
	unsigned i;
	unsigned v0 = 128;
	unsigned v1 = 0;
	/* linear horizontal and vertical filters */
	for (i = 0; i < 16; i++) {
		tegra_dc_writel(dc, (v1 << 16) | (v0 << 8),
				DC_WIN_H_FILTER_P(i));

		tegra_dc_writel(dc, v0,
				DC_WIN_V_FILTER_P(i));
		v0 -= 8;
		v1 += 8;
	}
}
Exemple #12
0
void tegra_dc_enable_crc(struct tegra_dc *dc)
{
	u32 val;

	mutex_lock(&dc->lock);
	tegra_dc_hold_dc_out(dc);
	tegra_dc_io_start(dc);

	val = CRC_ALWAYS_ENABLE | CRC_INPUT_DATA_ACTIVE_DATA |
		CRC_ENABLE_ENABLE;
	tegra_dc_writel(dc, val, DC_COM_CRC_CONTROL);
	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
	tegra_dc_release_dc_out(dc);
	mutex_unlock(&dc->lock);
}
Exemple #13
0
static int tegra_dc_update_winlut(struct tegra_dc *dc, int win_idx, int fbovr)
{
	struct tegra_dc_win *win = &dc->windows[win_idx];

	mutex_lock(&dc->lock);

	if (!dc->enabled) {
		mutex_unlock(&dc->lock);
		return -EFAULT;
	}

	if (fbovr > 0)
		win->ppflags |= TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;
	else if (fbovr == 0)
		win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_FBOVERRIDE;

	if (!tegra_dc_loop_lut(dc, win, tegra_dc_lut_isdefaults_lambda))
		win->ppflags |= TEGRA_WIN_PPFLAG_CP_ENABLE;
	else
		win->ppflags &= ~TEGRA_WIN_PPFLAG_CP_ENABLE;

	tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx,
			DC_CMD_DISPLAY_WINDOW_HEADER);

	tegra_dc_set_lut(dc, win);

	mutex_unlock(&dc->lock);

	tegra_dc_update_windows(&win, 1);

	return 0;
}
Exemple #14
0
static void tegra_dsi_set_dc_clk(struct tegra_dc *dc,
						struct tegra_dc_dsi_data *dsi)
{
	u32 shift_clk_div;
	u32 val;

	if (dsi->info.video_burst_mode == TEGRA_DSI_VIDEO_NONE_BURST_MODE ||
		dsi->info.video_burst_mode ==
				TEGRA_DSI_VIDEO_NONE_BURST_MODE_WITH_SYNC_END)
		shift_clk_div = NUMOF_BIT_PER_BYTE * dsi->pixel_scaler_mul /
			(dsi->pixel_scaler_div * dsi->info.n_data_lanes) - 2;
	else
		shift_clk_div = (dsi->current_dsi_clk_khz * 2 +
						dsi->default_hs_clk_khz - 1) /
						(dsi->default_hs_clk_khz) - 2;

#ifdef CONFIG_TEGRA_FPGA_PLATFORM
	shift_clk_div = 1;
#endif

	/* TODO: find out if PCD3 option is required */
	val = PIXEL_CLK_DIVIDER_PCD1 | SHIFT_CLK_DIVIDER(shift_clk_div);
	tegra_dc_writel(dc, val, DC_DISP_DISP_CLOCK_CONTROL);

	clk_enable(dsi->dc_clk);
}
static void tegra_dc_blend_sequential(struct tegra_dc *dc,
				struct tegra_dc_blend *blend)
{
	int i;

	tegra_dc_io_start(dc);
	for (i = 0; i < DC_N_WINDOWS; i++) {
		if (!tegra_dc_feature_is_gen2_blender(dc, i))
			continue;

		tegra_dc_writel(dc, WINDOW_A_SELECT << i,
				DC_CMD_DISPLAY_WINDOW_HEADER);

		if (blend->flags[i] & TEGRA_WIN_FLAG_BLEND_COVERAGE) {
			tegra_dc_writel(dc,
					WIN_K1(0xff) |
					WIN_K2(0xff) |
					WIN_BLEND_ENABLE,
					DC_WINBUF_BLEND_LAYER_CONTROL);

			tegra_dc_writel(dc,
			WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1_TIMES_SRC |
			WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1_TIMES_SRC |
			WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 |
			WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO,
			DC_WINBUF_BLEND_MATCH_SELECT);

			tegra_dc_writel(dc,
					WIN_ALPHA_1BIT_WEIGHT0(0) |
					WIN_ALPHA_1BIT_WEIGHT1(0xff),
					DC_WINBUF_BLEND_ALPHA_1BIT);
		} else if (blend->flags[i] & TEGRA_WIN_FLAG_BLEND_PREMULT) {
			tegra_dc_writel(dc,
					WIN_K1(0xff) |
					WIN_K2(0xff) |
					WIN_BLEND_ENABLE,
					DC_WINBUF_BLEND_LAYER_CONTROL);

			tegra_dc_writel(dc,
			WIN_BLEND_FACT_SRC_COLOR_MATCH_SEL_K1 |
			WIN_BLEND_FACT_DST_COLOR_MATCH_SEL_NEG_K1 |
			WIN_BLEND_FACT_SRC_ALPHA_MATCH_SEL_K2 |
			WIN_BLEND_FACT_DST_ALPHA_MATCH_SEL_ZERO,
			DC_WINBUF_BLEND_MATCH_SELECT);

			tegra_dc_writel(dc,
					WIN_ALPHA_1BIT_WEIGHT0(0) |
					WIN_ALPHA_1BIT_WEIGHT1(0xff),
					DC_WINBUF_BLEND_ALPHA_1BIT);
		} else {
			tegra_dc_writel(dc,
					WIN_BLEND_BYPASS,
					DC_WINBUF_BLEND_LAYER_CONTROL);
		}
	}
	tegra_dc_io_end(dc);
}
Exemple #16
0
static void tegra_dc_rgb_disable(struct tegra_dc *dc)
{
	tegra_dc_io_start(dc);
	tegra_dc_writel(dc, 0x00000000, DC_CMD_DISPLAY_POWER_CONTROL);

	tegra_dc_write_table(dc, tegra_dc_rgb_disable_pintable);
	tegra_dc_io_end(dc);
}
Exemple #17
0
static void tegra_dsi_stop_dc_stream(struct tegra_dc *dc,
						struct tegra_dc_dsi_data *dsi)
{
	/*
	 * TODO: It is possible that we are in the middle of video stream,
	 * Add code to wait for vsync and then stop DC from sending data to dsi
	 */
	tegra_dc_writel(dc, 0, DC_DISP_DISP_WIN_OPTIONS);
}
Exemple #18
0
static bool _tegra_dc_controller_enable(struct tegra_dc *dc)
{
	int failed_init = 0;

	if (dc->out->enable)
		dc->out->enable();

	tegra_dc_setup_clk(dc, dc->clk);
	tegra_dc_clk_enable(dc);

	/* do not accept interrupts during initialization */
	tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);

	enable_dc_irq(dc->irq);

	failed_init = tegra_dc_init(dc);
	if (failed_init) {
		tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
		disable_irq(dc->irq);
		tegra_dc_clear_bandwidth(dc);
		tegra_dc_clk_disable(dc);
		if (dc->out && dc->out->disable)
			dc->out->disable();
		return false;
	}

	if (dc->out_ops && dc->out_ops->enable)
		dc->out_ops->enable(dc);

	/* force a full blending update */
	dc->blend.z[0] = -1;

	tegra_dc_ext_enable(dc->ext);

	trace_printk("%s:enable\n", dc->ndev->name);

	tegra_dc_writel(dc, GENERAL_UPDATE, DC_CMD_STATE_CONTROL);
	tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);

	if (dc->out->postpoweron)
		dc->out->postpoweron();

	return true;
}
Exemple #19
0
void tegra_dc_set_csc(struct tegra_dc *dc, struct tegra_dc_csc *csc)
{
	tegra_dc_writel(dc, csc->yof,	DC_WIN_CSC_YOF);
	tegra_dc_writel(dc, csc->kyrgb,	DC_WIN_CSC_KYRGB);
	tegra_dc_writel(dc, csc->kur,	DC_WIN_CSC_KUR);
	tegra_dc_writel(dc, csc->kvr,	DC_WIN_CSC_KVR);
	tegra_dc_writel(dc, csc->kug,	DC_WIN_CSC_KUG);
	tegra_dc_writel(dc, csc->kvg,	DC_WIN_CSC_KVG);
	tegra_dc_writel(dc, csc->kub,	DC_WIN_CSC_KUB);
	tegra_dc_writel(dc, csc->kvb,	DC_WIN_CSC_KVB);
}
Exemple #20
0
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable)
{
	tegra_dc_writel(dc, FRAME_END_INT, DC_CMD_INT_STATUS);
	if (enable) {
		atomic_inc(&frame_end_ref);
		tegra_dc_unmask_interrupt(dc, FRAME_END_INT);
	} else if (!atomic_dec_return(&frame_end_ref))
		tegra_dc_mask_interrupt(dc, FRAME_END_INT);
	return 0;
}
Exemple #21
0
/* handle the commands that may be invoked for phase_in_settings */
static void nvsd_cmd_handler(struct tegra_dc_sd_settings *settings,
	struct tegra_dc *dc)
{
	u32 val;
	u8 bw_idx, bw;

	if (settings->cmd & ENABLE) {
		settings->phase_settings_step++;
		if (settings->phase_settings_step >=
				settings->num_phase_in_steps)
			settings->cmd &= ~ENABLE;

		nvsd_phase_in_luts(settings, dc);
	}
	if (settings->cmd & DISABLE) {
		settings->phase_settings_step--;
		nvsd_phase_in_luts(settings, dc);
		if (settings->phase_settings_step == 0) {
			/* finish up aggressiveness phase in */
			if (settings->cmd & AGG_CHG)
				settings->aggressiveness = settings->final_agg;
			settings->cmd = NO_CMD;
			settings->enable = 0;
			nvsd_init(dc, settings);
		}
	}
	if (settings->cmd & AGG_CHG) {
		if (settings->aggressiveness == settings->final_agg)
			settings->cmd &= ~AGG_CHG;
		if ((settings->cur_agg_step++ & (STEPS_PER_AGG_CHG - 1)) == 0) {
			settings->final_agg > settings->aggressiveness ?
				settings->aggressiveness++ :
				settings->aggressiveness--;

			/* Update aggressiveness value in HW */
			val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
			val &= ~SD_AGGRESSIVENESS(0x7);
			val |= SD_AGGRESSIVENESS(settings->aggressiveness);

			/* Adjust bin_width for automatic setting */
			if (settings->bin_width == -1) {
				bw_idx = nvsd_get_bw_idx(settings);

				bw = bw_idx << 3;

				val &= ~SD_BIN_WIDTH_MASK;
				val |= bw;
			}

			tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL);

			nvsd_phase_in_luts(settings, dc);
		}
	}
}
Exemple #22
0
static bool nvsd_phase_in_adjustments(struct tegra_dc *dc,
	struct tegra_dc_sd_settings *settings)
{
	u8 step, cur_sd_brightness;
	u16 target_k, cur_k;
	u32 man_k, val;

	cur_sd_brightness = atomic_read(_sd_brightness);

	target_k = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES);
	target_k = SD_HW_K_R(target_k);
	cur_k = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES);
	cur_k = SD_HW_K_R(cur_k);

	/* read brightness value */
	val = tegra_dc_readl(dc, DC_DISP_SD_BL_CONTROL);
	val = SD_BLC_BRIGHTNESS(val);

	step = settings->phase_adj_step;
	if (cur_sd_brightness != val || target_k != cur_k) {
		if (!step)
			step = ADJ_PHASE_STEP;

		/* Phase in Backlight and Pixel K
		every ADJ_PHASE_STEP frames*/
		if ((step-- & ADJ_PHASE_STEP) == ADJ_PHASE_STEP) {

			if (val != cur_sd_brightness) {
				val > cur_sd_brightness ?
				(cur_sd_brightness++) :
				(cur_sd_brightness--);
			}

			if (target_k != cur_k) {
				if (target_k > cur_k)
					cur_k += K_STEP;
				else
					cur_k -= K_STEP;
			}

			/* Set manual k value */
			man_k = SD_MAN_K_R(cur_k) |
				SD_MAN_K_G(cur_k) | SD_MAN_K_B(cur_k);
			tegra_dc_io_start(dc);
			tegra_dc_writel(dc, man_k, DC_DISP_SD_MAN_K_VALUES);
			tegra_dc_io_end(dc);
			/* Set manual brightness value */
			atomic_set(_sd_brightness, cur_sd_brightness);
		}
		settings->phase_adj_step = step;
		return true;
	} else
		return false;
}
Exemple #23
0
/* get the stride size of a window.
 * return: stride size in bytes for window win. or 0 if unavailble. */
int tegra_dc_get_stride(struct tegra_dc *dc, unsigned win)
{
	u32 stride;

	if (!dc->enabled)
		return 0;
	BUG_ON(win > DC_N_WINDOWS);
	tegra_dc_writel(dc, WINDOW_A_SELECT << win,
		DC_CMD_DISPLAY_WINDOW_HEADER);
	stride = tegra_dc_readl(dc, DC_WIN_LINE_STRIDE);
	return GET_LINE_STRIDE(stride);
}
Exemple #24
0
static void _tegra_dc_controller_disable(struct tegra_dc *dc)
{
	unsigned i;

	if (dc->out && dc->out->prepoweroff)
		dc->out->prepoweroff();

	if (dc->out_ops && dc->out_ops->disable)
		dc->out_ops->disable(dc);

	tegra_dc_writel(dc, 0, DC_CMD_INT_MASK);
	tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE);
	disable_irq(dc->irq);

	tegra_dc_clear_bandwidth(dc);
	tegra_dc_clk_disable(dc);

	if (dc->out && dc->out->disable)
		dc->out->disable();

	for (i = 0; i < dc->n_windows; i++) {
		struct tegra_dc_win *w = &dc->windows[i];

		/* reset window bandwidth */
		w->bandwidth = 0;
		w->new_bandwidth = 0;

		/* disable windows */
		w->flags &= ~TEGRA_WIN_FLAG_ENABLED;

		/* flush any pending syncpt waits */
		while (dc->syncpt[i].min < dc->syncpt[i].max) {
			trace_printk("%s:syncpt flush id=%d\n", dc->ndev->name,
				dc->syncpt[i].id);
			dc->syncpt[i].min++;
			nvhost_syncpt_cpu_incr_ext(dc->ndev, dc->syncpt[i].id);
		}
	}
	trace_printk("%s:disabled\n", dc->ndev->name);
}
Exemple #25
0
void
tegra_dc_config_pwm(struct tegra_dc *dc, struct tegra_dc_pwm_params *cfg)
{
	unsigned int ctrl;
	unsigned long out_sel;
	unsigned long cmd_state;

	mutex_lock(&dc->lock);
	if (!dc->enabled) {
		mutex_unlock(&dc->lock);
		return;
	}

	tegra_dc_hold_dc_out(dc);

	ctrl = ((cfg->period << PM_PERIOD_SHIFT) |
		(cfg->clk_div << PM_CLK_DIVIDER_SHIFT) |
		cfg->clk_select);

	/* The new value should be effected immediately */
	cmd_state = tegra_dc_readl(dc, DC_CMD_STATE_ACCESS);
	tegra_dc_writel(dc, (cmd_state | (1 << 2)), DC_CMD_STATE_ACCESS);

	switch (cfg->which_pwm) {
	case TEGRA_PWM_PM0:
		/* Select the LM0 on PM0 */
		out_sel = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_SELECT5);
		out_sel &= ~(7 << 0);
		out_sel |= (3 << 0);
		tegra_dc_writel(dc, out_sel, DC_COM_PIN_OUTPUT_SELECT5);
		tegra_dc_writel(dc, ctrl, DC_COM_PM0_CONTROL);
		tegra_dc_writel(dc, cfg->duty_cycle, DC_COM_PM0_DUTY_CYCLE);
		break;
	case TEGRA_PWM_PM1:
		/* Select the LM1 on PM1 */
		out_sel = tegra_dc_readl(dc, DC_COM_PIN_OUTPUT_SELECT5);
		out_sel &= ~(7 << 4);
		out_sel |= (3 << 4);
		tegra_dc_writel(dc, out_sel, DC_COM_PIN_OUTPUT_SELECT5);
		tegra_dc_writel(dc, ctrl, DC_COM_PM1_CONTROL);
		tegra_dc_writel(dc, cfg->duty_cycle, DC_COM_PM1_DUTY_CYCLE);
		break;
	default:
		dev_err(&dc->ndev->dev, "Error: Need which_pwm\n");
		break;
	}
	tegra_dc_writel(dc, cmd_state, DC_CMD_STATE_ACCESS);
	tegra_dc_release_dc_out(dc);
	mutex_unlock(&dc->lock);
}
static void tegra_dc_blend_parallel(struct tegra_dc *dc,
				struct tegra_dc_blend *blend)
{
	int win_num = dc->gen1_blend_num;
	unsigned long mask = BIT(win_num) - 1;

	tegra_dc_io_start(dc);
	while (mask) {
		int idx = get_topmost_window(blend->z, &mask, win_num);

		tegra_dc_writel(dc, WINDOW_A_SELECT << idx,
				DC_CMD_DISPLAY_WINDOW_HEADER);
		tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
				DC_WIN_BLEND_NOKEY);
		tegra_dc_writel(dc, BLEND(NOKEY, FIX, 0xff, 0xff),
				DC_WIN_BLEND_1WIN);
		tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 0,
				win_num), DC_WIN_BLEND_2WIN_X);
		tegra_dc_writel(dc, blend_2win(idx, mask, blend->flags, 1,
				win_num), DC_WIN_BLEND_2WIN_Y);
		tegra_dc_writel(dc, blend_3win(idx, mask, blend->flags,
				win_num), DC_WIN_BLEND_3WIN_XY);
	}
	tegra_dc_io_end(dc);
}
Exemple #27
0
void tegra_dc_set_lut(struct tegra_dc *dc, struct tegra_dc_win *win)
{
	unsigned long val = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS);

	tegra_dc_loop_lut(dc, win, tegra_dc_set_lut_setreg_lambda);

	if (win->ppflags & TEGRA_WIN_PPFLAG_CP_ENABLE)
		val |= CP_ENABLE;
	else
		val &= ~CP_ENABLE;

	tegra_dc_writel(dc, val, DC_WIN_WIN_OPTIONS);
}
Exemple #28
0
static void set_cursor_image_hw(struct tegra_dc *dc,
				struct tegra_dc_ext_cursor_image *args,
				dma_addr_t phys_addr)
{
	tegra_dc_writel(dc,
		CURSOR_COLOR(args->foreground.r,
			     args->foreground.g,
			     args->foreground.b),
		DC_DISP_CURSOR_FOREGROUND);
	tegra_dc_writel(dc,
		CURSOR_COLOR(args->background.r,
			     args->background.g,
			     args->background.b),
		DC_DISP_CURSOR_BACKGROUND);

	BUG_ON(phys_addr & ~CURSOR_START_ADDR_MASK);

	tegra_dc_writel(dc,
		CURSOR_START_ADDR(((unsigned long) phys_addr)) |
		((args->flags & TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) ?
			CURSOR_SIZE_64 : 0),
		DC_DISP_CURSOR_START_ADDR);
}
Exemple #29
0
void tegra_dc_stats_enable(struct tegra_dc *dc, bool enable)
{
#if 0 /* underflow interrupt is already enabled by dc reset worker */
	u32 val;
	if (dc->enabled)  {
		val = tegra_dc_readl(dc, DC_CMD_INT_ENABLE);
		if (enable)
			val |= (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT);
		else
			val &= ~(WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT);
		tegra_dc_writel(dc, val, DC_CMD_INT_ENABLE);
	}
#endif
}
Exemple #30
0
/* phase in the luts based on the current and max step */
static void nvsd_phase_in_luts(struct tegra_dc_sd_settings *settings,
	struct tegra_dc *dc)
{
	u32 val;
	u8 bw_idx;
	int i;
	u16 phase_settings_step = settings->phase_settings_step;
	u16 num_phase_in_steps = settings->num_phase_in_steps;

	bw_idx = nvsd_get_bw_idx(settings);

	/* Phase in Final LUT */
	for (i = 0; i < DC_DISP_SD_LUT_NUM; i++) {
		val = SD_LUT_R((settings->lut[bw_idx][i].r *
				phase_settings_step)/num_phase_in_steps) |
			SD_LUT_G((settings->lut[bw_idx][i].g *
				phase_settings_step)/num_phase_in_steps) |
			SD_LUT_B((settings->lut[bw_idx][i].b *
				phase_settings_step)/num_phase_in_steps);

		tegra_dc_writel(dc, val, DC_DISP_SD_LUT(i));
	}
	/* Phase in Final BLTF */
	for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) {
		val = SD_BL_TF_POINT_0(255-((255-settings->bltf[bw_idx][i][0])
				* phase_settings_step)/num_phase_in_steps) |
			SD_BL_TF_POINT_1(255-((255-settings->bltf[bw_idx][i][1])
				* phase_settings_step)/num_phase_in_steps) |
			SD_BL_TF_POINT_2(255-((255-settings->bltf[bw_idx][i][2])
				* phase_settings_step)/num_phase_in_steps) |
			SD_BL_TF_POINT_3(255-((255-settings->bltf[bw_idx][i][3])
				* phase_settings_step)/num_phase_in_steps);

		tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i));
	}
}