int mods_init_tegradc(void)
{
#if defined(CONFIG_TEGRA_NVSD)
	int i;
	int ret = 0;
	LOG_ENT();
	for (i = 0; i < TEGRA_MAX_DC; i++) {
		struct tegra_dc *dc = tegra_dc_get_dc(i);
		if (!dc)
			continue;

		tegra_dc_saved_sd_settings[i] = dc->out->sd_settings;
		dc->out->sd_settings = &mods_sd_settings[i];

		if (dc->enabled)
			nvsd_init(dc, dc->out->sd_settings);

		if (!tegra_dc_saved_sd_settings[i])
			ret = nvsd_create_sysfs(&dc->ndev->dev);
	}
	LOG_EXT();
	return ret;
#else
	return 0;
#endif
}
Beispiel #2
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);
		}
	}
}
void mods_exit_tegradc(void)
{
#if defined(CONFIG_TEGRA_NVSD)
	int i;
	LOG_ENT();
	for (i = 0; i < TEGRA_MAX_DC; i++) {
		struct tegra_dc *dc = tegra_dc_get_dc(i);
		if (!dc)
			continue;
		if (!tegra_dc_saved_sd_settings[i])
			nvsd_remove_sysfs(&dc->ndev->dev);
		dc->out->sd_settings = tegra_dc_saved_sd_settings[i];
		if (dc->enabled)
			nvsd_init(dc, dc->out->sd_settings);
	}
#endif
}
Beispiel #4
0
static ssize_t nvsd_settings_store(struct kobject *kobj,
	struct kobj_attribute *attr, const char *buf, size_t count)
{
	struct device *dev = container_of((kobj->parent), struct device, kobj);
	struct nvhost_device *ndev = to_nvhost_device(dev);
	struct tegra_dc *dc = nvhost_get_drvdata(ndev);
	struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
	ssize_t res = count;
	bool settings_updated = false;
	long int result;
	int err;

	if (sd_settings) {
		if (IS_NVSD_ATTR(enable)) {
			if (sd_settings->phase_in_settings) {
				err = strict_strtol(buf, 10, &result);
				if (err)
					return err;

				if (nvsd_update_enable(sd_settings, result))
					nvsd_check_and_update(1, 1, enable);

			} else {
				nvsd_check_and_update(0, 1, enable);
			}
		} else if (IS_NVSD_ATTR(aggressiveness)) {
			err = strict_strtol(buf, 10, &result);
			if (err)
				return err;

			if (nvsd_update_agg(sd_settings, result)
					&& !sd_settings->phase_in_settings)
				settings_updated = true;

		} else if (IS_NVSD_ATTR(phase_in_settings)) {
			nvsd_check_and_update(0, 1, phase_in_settings);
		} else if (IS_NVSD_ATTR(phase_in_adjustments)) {
			nvsd_check_and_update(0, 1, phase_in_adjustments);
		} else if (IS_NVSD_ATTR(bin_width)) {
			nvsd_check_and_update(0, 8, bin_width);
		} else if (IS_NVSD_ATTR(hw_update_delay)) {
			nvsd_check_and_update(0, 2, hw_update_delay);
		} else if (IS_NVSD_ATTR(use_vid_luma)) {
			nvsd_check_and_update(0, 1, use_vid_luma);
		} else if (IS_NVSD_ATTR(coeff)) {
			int ele[3], i = 0, num = 3;
			nvsd_get_multi(ele, num, i, 0, 15);

			if (i == num) {
				sd_settings->coeff.r = ele[0];
				sd_settings->coeff.g = ele[1];
				sd_settings->coeff.b = ele[2];
				settings_updated = true;
			} else {
				res = -EINVAL;
			}
		} else if (IS_NVSD_ATTR(blp_time_constant)) {
			nvsd_check_and_update(0, 1024, blp.time_constant);
		} else if (IS_NVSD_ATTR(blp_step)) {
			nvsd_check_and_update(0, 255, blp.step);
		} else if (IS_NVSD_ATTR(fc_time_limit)) {
			nvsd_check_and_update(0, 255, fc.time_limit);
		} else if (IS_NVSD_ATTR(fc_threshold)) {
			nvsd_check_and_update(0, 255, fc.threshold);
#ifdef CONFIG_TEGRA_SD_GEN2
		} else if (IS_NVSD_ATTR(k_limit_enable)) {
			nvsd_check_and_update(0, 1, k_limit_enable);
		} else if (IS_NVSD_ATTR(k_limit)) {
			nvsd_check_and_update(128, 255, k_limit);
		} else if (IS_NVSD_ATTR(sd_window_enable)) {
			nvsd_check_and_update(0, 1, sd_window_enable);
		} else if (IS_NVSD_ATTR(sd_window)) {
			int ele[4], i = 0, num = 4;
			nvsd_get_multi(ele, num, i, 0, LONG_MAX);

			if (i == num) {
				sd_settings->sd_window.h_position = ele[0];
				sd_settings->sd_window.v_position = ele[1];
				sd_settings->sd_window.h_size = ele[2];
				sd_settings->sd_window.v_size = ele[3];
				settings_updated = true;
			} else {
				res = -EINVAL;
			}
		} else if (IS_NVSD_ATTR(soft_clipping_enable)) {
			nvsd_check_and_update(0, 1, soft_clipping_enable);
		} else if (IS_NVSD_ATTR(soft_clipping_threshold)) {
			nvsd_check_and_update(0, 255, soft_clipping_threshold);
		} else if (IS_NVSD_ATTR(smooth_k_enable)) {
			nvsd_check_and_update(0, 1, smooth_k_enable);
		} else if (IS_NVSD_ATTR(smooth_k_incr)) {
			nvsd_check_and_update(0, 16320, smooth_k_incr);
		} else if (IS_NVSD_ATTR(use_vpulse2)) {
			nvsd_check_and_update(0, 1, use_vpulse2);
#endif
		} else if (IS_NVSD_ATTR(lut)) {
			if (nvsd_lut_store(sd_settings, buf))
				res = -EINVAL;
			else
				settings_updated = true;
		} else if (IS_NVSD_ATTR(bltf)) {
			if (nvsd_bltf_store(sd_settings, buf))
				res = -EINVAL;
			else
				settings_updated = true;
		} else {
			res = -EINVAL;
		}

		/* Re-init if our settings were updated. */
		if (settings_updated) {
			mutex_lock(&dc->lock);
			if (!dc->enabled) {
				mutex_unlock(&dc->lock);
				return -ENODEV;
			}

			tegra_dc_hold_dc_out(dc);
			nvsd_init(dc, sd_settings);
			tegra_dc_release_dc_out(dc);

			mutex_unlock(&dc->lock);

			/* Update backlight state IFF we're disabling! */
			if (!sd_settings->enable && sd_settings->bl_device) {
				/* Do the actual brightness update outside of
				 * the mutex */
				struct platform_device *pdev =
					sd_settings->bl_device;
				struct backlight_device *bl =
					platform_get_drvdata(pdev);

				if (bl)
					backlight_update_status(bl);
			}
		}
	} else {
		/* This shouldn't be reachable. But just in case... */
		res = -EINVAL;
	}

	return res;
}
Beispiel #5
0
static ssize_t nvsd_settings_store(struct kobject *kobj,
	struct kobj_attribute *attr, const char *buf, size_t count)
{
	struct device *dev = container_of((kobj->parent), struct device, kobj);
	struct nvhost_device *ndev = to_nvhost_device(dev);
	struct tegra_dc *dc = nvhost_get_drvdata(ndev);
	struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
	ssize_t res = count;
	bool settings_updated = false;

	if (sd_settings) {
		if (IS_NVSD_ATTR(enable)) {
			nvsd_check_and_update(0, 1, enable);
		} else if (IS_NVSD_ATTR(aggressiveness)) {
			nvsd_check_and_update(1, 5, aggressiveness);
		} else if (IS_NVSD_ATTR(bin_width)) {
			nvsd_check_and_update(0, 8, bin_width);
		} else if (IS_NVSD_ATTR(hw_update_delay)) {
			nvsd_check_and_update(0, 2, hw_update_delay);
		} else if (IS_NVSD_ATTR(use_vid_luma)) {
			nvsd_check_and_update(0, 1, use_vid_luma);
		} else if (IS_NVSD_ATTR(coeff)) {
			int ele[3], i = 0, num = 3;
			nvsd_get_multi(ele, num, i, 0, 15);

			if (i == num) {
				sd_settings->coeff.r = ele[0];
				sd_settings->coeff.g = ele[1];
				sd_settings->coeff.b = ele[2];
				settings_updated = true;
			} else {
				res = -EINVAL;
			}
		} else if (IS_NVSD_ATTR(blp_time_constant)) {
			nvsd_check_and_update(0, 1024, blp.time_constant);
		} else if (IS_NVSD_ATTR(blp_step)) {
			nvsd_check_and_update(0, 255, blp.step);
		} else if (IS_NVSD_ATTR(fc_time_limit)) {
			nvsd_check_and_update(0, 255, fc.time_limit);
		} else if (IS_NVSD_ATTR(fc_threshold)) {
			nvsd_check_and_update(0, 255, fc.threshold);
		} else if (IS_NVSD_ATTR(lut)) {
			if (nvsd_lut_store(sd_settings, buf))
				res = -EINVAL;
			else
				settings_updated = true;
		} else if (IS_NVSD_ATTR(bltf)) {
			if (nvsd_bltf_store(sd_settings, buf))
				res = -EINVAL;
			else
				settings_updated = true;
		} else {
			res = -EINVAL;
		}

		/* Re-init if our settings were updated. */
		if (settings_updated) {
			nvsd_init(dc, sd_settings);

			/* Update backlight state IFF we're disabling! */
			if (!sd_settings->enable && sd_settings->bl_device) {
				/* Do the actual brightness update outside of
				 * the mutex */
				struct platform_device *pdev =
					sd_settings->bl_device;
				struct backlight_device *bl =
					platform_get_drvdata(pdev);

				if (bl)
					backlight_update_status(bl);
			}
		}
	} else {
		/* This shouldn't be reachable. But just in case... */
		res = -EINVAL;
	}

	return res;
}
Beispiel #6
0
static int tegra_dc_init(struct tegra_dc *dc)
{
	int i;
	int int_enable;

	tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
	if (dc->ndev->id == 0) {
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0A,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0B,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0C,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1B,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHC,
				      TEGRA_MC_PRIO_HIGH);
	} else if (dc->ndev->id == 1) {
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0AB,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0BB,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY0CB,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAY1BB,
				      TEGRA_MC_PRIO_MED);
		tegra_mc_set_priority(TEGRA_MC_CLIENT_DISPLAYHCB,
				      TEGRA_MC_PRIO_HIGH);
	}
	tegra_dc_writel(dc, 0x00000100 | dc->vblank_syncpt,
			DC_CMD_CONT_SYNCPT_VSYNC);
	tegra_dc_writel(dc, 0x00004700, DC_CMD_INT_TYPE);
	tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY);
	tegra_dc_writel(dc, 0x00202020, DC_DISP_MEM_HIGH_PRIORITY);
	tegra_dc_writel(dc, 0x00010101, DC_DISP_MEM_HIGH_PRIORITY_TIMER);
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
	tegra_dc_writel(dc, 0x00000000, DC_DISP_DISP_MISC_CONTROL);
#endif
	/* enable interrupts for vblank, frame_end and underflows */
	int_enable = (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT);
	/* for panels with one-shot mode enable tearing effect interrupt */
	if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE)
		int_enable |= MSF_INT;

	tegra_dc_writel(dc, int_enable, DC_CMD_INT_ENABLE);
	tegra_dc_writel(dc, ALL_UF_INT, DC_CMD_INT_MASK);

	tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);

	tegra_dc_set_color_control(dc);
	for (i = 0; i < DC_N_WINDOWS; i++) {
		struct tegra_dc_win *win = &dc->windows[i];
		tegra_dc_writel(dc, WINDOW_A_SELECT << i,
				DC_CMD_DISPLAY_WINDOW_HEADER);
		tegra_dc_set_csc(dc, &win->csc);
		tegra_dc_set_lut(dc, win);
		tegra_dc_set_scaling_filter(dc);
	}


	for (i = 0; i < dc->n_windows; i++) {
		u32 syncpt = get_syncpt(dc, i);

		dc->syncpt[i].id = syncpt;

		dc->syncpt[i].min = dc->syncpt[i].max =
			nvhost_syncpt_read_ext(dc->ndev, syncpt);
	}

	print_mode_info(dc, dc->mode);

	if (dc->mode.pclk)
		if (tegra_dc_program_mode(dc, &dc->mode))
			return -EINVAL;

	/* Initialize SD AFTER the modeset.
	   nvsd_init handles the sd_settings = NULL case. */
	nvsd_init(dc, dc->out->sd_settings);

	return 0;
}
int esc_mods_tegra_dc_setup_sd(struct file *fp,
	struct MODS_TEGRA_DC_SETUP_SD *args)
{
	int i;
	struct tegra_dc *dc = tegra_dc_get_dc(args->head);
	struct tegra_dc_sd_settings *sd_settings = dc->out->sd_settings;
#if defined(CONFIG_ARCH_TEGRA_12x_SOC)
	u32 val;
#endif
	u32 bw_idx;
	LOG_ENT();

	BUG_ON(args->head > TEGRA_MAX_DC);

	sd_settings->enable = args->enable ? 1 : 0;
	sd_settings->use_auto_pwm = false;
	sd_settings->hw_update_delay = 0;

	sd_settings->aggressiveness = args->aggressiveness;
	sd_settings->bin_width = (1 << args->bin_width_log2);

	sd_settings->phase_in_settings = 0;
	sd_settings->phase_in_adjustments = 0;
	sd_settings->cmd = 0;
	sd_settings->final_agg = args->aggressiveness;
	sd_settings->cur_agg_step = 0;
	sd_settings->phase_settings_step = 0;
	sd_settings->phase_adj_step = 0;
	sd_settings->num_phase_in_steps = 0;

	sd_settings->agg_priorities.agg[0] = args->aggressiveness;

	sd_settings->use_vid_luma = args->use_vid_luma;
	sd_settings->coeff.r = args->csc_r;
	sd_settings->coeff.g = args->csc_g;
	sd_settings->coeff.b = args->csc_b;

	sd_settings->k_limit_enable = (args->klimit != 0);
	sd_settings->k_limit = args->klimit;
	sd_settings->sd_window_enable = true;

	sd_settings->sd_window.h_position = args->win_x;
	sd_settings->sd_window.v_position = args->win_y;
	sd_settings->sd_window.h_size     = args->win_w;
	sd_settings->sd_window.v_size     = args->win_h;

	sd_settings->soft_clipping_enable    = true;
	sd_settings->soft_clipping_threshold = args->soft_clipping_threshold;


	sd_settings->smooth_k_enable = (args->smooth_k_inc != 0);
	sd_settings->smooth_k_incr   = args->smooth_k_inc;

	sd_settings->sd_proc_control = false;
	sd_settings->soft_clipping_correction = false;
	sd_settings->use_vpulse2 = false;

	sd_settings->fc.time_limit = 0;
	sd_settings->fc.threshold  = 0;

	sd_settings->blp.time_constant = 1024;
	sd_settings->blp.step          = 0;


#ifdef CONFIG_TEGRA_SD_GEN2
	bw_idx = 0;
#else
	bw_idx = args->bin_width_log2;
#endif
	for (i = 0; i < MODS_TEGRA_DC_SETUP_BLTF_SIZE; i++) {
		sd_settings->bltf[bw_idx][i/4][i%4] =
			args->bltf[i];
	}

	for (i = 0; i < MODS_TEGRA_DC_SETUP_SD_LUT_SIZE; i++) {
		sd_settings->lut[bw_idx][i].r =
			args->lut[i] & 0xff;
		sd_settings->lut[bw_idx][i].g =
			(args->lut[i] >> 8) & 0xff;
		sd_settings->lut[bw_idx][i].b =
			(args->lut[i] >> 16) & 0xff;
	}

#if defined(CONFIG_TEGRA_NVSD)
	nvsd_init(dc, sd_settings);
#endif
#if defined(CONFIG_ARCH_TEGRA_12x_SOC)
	tegra_dc_io_start(dc);
	val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL);
	val &= ~SD_KINIT_BIAS(0);
	val &= ~SD_CORRECTION_MODE_MAN;
	tegra_dc_writel(dc, val | SD_KINIT_BIAS(args->k_init_bias),
		DC_DISP_SD_CONTROL);
	tegra_dc_io_end(dc);
#endif

	if (dc->enabled) {
		mutex_lock(&dc->lock);
		tegra_dc_get(dc);
		tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
		tegra_dc_put(dc);
		mutex_unlock(&dc->lock);
	}

	LOG_EXT();
	return 0;
}