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 }
/* 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 }
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; }
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; }
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; }