static void tegra_dc_dsi_suspend(struct tegra_dc *dc) { struct tegra_dc_dsi_data *dsi; int err; dsi = tegra_dc_get_outdata(dc); tegra_dc_io_start(dc); mutex_lock(&dsi->lock); if (dsi->ulpm) tegra_dsi_exit_ulpm(dsi); err = tegra_dsi_send_panel_cmd(dc, dsi, dsi->info.dsi_suspend_cmd, dsi->info.n_suspend_cmd); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: error while sending dsi suspend cmd\n"); return; } clk_disable(dsi->dsi_clk); mutex_unlock(&dsi->lock); tegra_dc_io_end(dc); }
static void _tegra_dc_disable(struct tegra_dc *dc) { int i; disable_irq(dc->irq); if (dc->out_ops && dc->out_ops->disable) dc->out_ops->disable(dc); clk_disable(dc->emc_clk); clk_disable(dc->clk); tegra_dvfs_set_rate(dc->clk, 0); if (dc->out && dc->out->disable) dc->out->disable(); /* flush any pending syncpt waits */ for (i = 0; i < dc->n_windows; i++) { while (dc->syncpt[i].min < dc->syncpt[i].max) { dc->syncpt[i].min++; nvhost_syncpt_cpu_incr(&dc->ndev->host->syncpt, dc->syncpt[i].id); } } tegra_dc_io_end(dc); }
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); }
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); }
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); }
static void tegra_dc_dsi_enable(struct tegra_dc *dc) { struct tegra_dc_dsi_data *dsi = tegra_dc_get_outdata(dc); int err; tegra_dc_io_start(dc); mutex_lock(&dsi->lock); if (dsi->ulpm) { tegra_dsi_exit_ulpm(dsi); if (dsi->info.panel_reset) { err = tegra_dsi_send_panel_cmd(dc, dsi, dsi->info.dsi_init_cmd, dsi->info.n_init_cmd); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: error while sending dsi init cmd\n"); return; } } } else { err = tegra_dsi_init_hw(dc, dsi); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: not able to init dsi hardware\n"); return; } err = tegra_dsi_set_to_lp_mode(dc, dsi); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: not able to set to lp mode\n"); return; } err = tegra_dsi_send_panel_cmd(dc, dsi, dsi->info.dsi_init_cmd, dsi->info.n_init_cmd); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: error while sending dsi init cmd\n"); return; } err = tegra_dsi_set_to_hs_mode(dc, dsi); if (err < 0) { dev_err(&dc->ndev->dev, "dsi: not able to set to hs mode\n"); return; } } if (dsi->status.driven == DSI_DRIVEN_MODE_DC) { tegra_dsi_start_dc_stream(dc, dsi); } mutex_unlock(&dsi->lock); tegra_dc_io_end(dc); }
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); }
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; }
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; }
int tegra_dc_config_frame_end_intr(struct tegra_dc *dc, bool enable) { tegra_dc_io_start(dc); 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); tegra_dc_io_end(dc); return 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); }
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 */ }
static bool _tegra_dc_enable(struct tegra_dc *dc) { if (dc->mode.pclk == 0) return false; if (!dc->out) return false; tegra_dc_io_start(dc); if (!_tegra_dc_controller_enable(dc)) { tegra_dc_io_end(dc); return false; } return true; }
static void _tegra_dc_disable(struct tegra_dc *dc) { if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) { mutex_lock(&dc->one_shot_lock); cancel_delayed_work_sync(&dc->one_shot_work); } tegra_dc_hold_dc_out(dc); _tegra_dc_controller_disable(dc); tegra_dc_io_end(dc); tegra_dc_release_dc_out(dc); if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) mutex_unlock(&dc->one_shot_lock); }
int tegra_dc_ext_cursor_clip(struct tegra_dc_ext_user *user, int *args) { struct tegra_dc_ext *ext = user->ext; struct tegra_dc *dc = ext->dc; int ret; unsigned long reg_val; mutex_lock(&ext->cursor.lock); if (ext->cursor.user != user) { ret = -EACCES; goto unlock; } if (!ext->enabled) { ret = -ENXIO; goto unlock; } mutex_lock(&dc->lock); tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); reg_val = tegra_dc_readl(dc, DC_DISP_CURSOR_START_ADDR); reg_val &= ~CURSOR_CLIP_SHIFT_BITS(3); /* Clear out the old value */ tegra_dc_writel(dc, reg_val | CURSOR_CLIP_SHIFT_BITS(*args), DC_DISP_CURSOR_START_ADDR); 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; }
static ssize_t nvsd_registers_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { 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); ssize_t res = 0; clk_enable(dc->clk); tegra_dc_io_start(dc); mutex_lock(&dc->lock); if (!dc->enabled) { mutex_unlock(&dc->lock); return -ENODEV; } mutex_unlock(&dc->lock); NVSD_PRINT_REG(DC_DISP_SD_CONTROL); NVSD_PRINT_REG(DC_DISP_SD_CSC_COEFF); NVSD_PRINT_REG_ARRAY(DC_DISP_SD_LUT); NVSD_PRINT_REG(DC_DISP_SD_FLICKER_CONTROL); NVSD_PRINT_REG(DC_DISP_SD_PIXEL_COUNT); NVSD_PRINT_REG_ARRAY(DC_DISP_SD_HISTOGRAM); NVSD_PRINT_REG(DC_DISP_SD_BL_PARAMETERS); NVSD_PRINT_REG_ARRAY(DC_DISP_SD_BL_TF); NVSD_PRINT_REG(DC_DISP_SD_BL_CONTROL); NVSD_PRINT_REG(DC_DISP_SD_HW_K_VALUES); NVSD_PRINT_REG(DC_DISP_SD_MAN_K_VALUES); #ifdef CONFIG_TEGRA_SD_GEN2 NVSD_PRINT_REG(DC_DISP_SD_K_LIMIT); NVSD_PRINT_REG(DC_DISP_SD_WINDOW_POSITION); NVSD_PRINT_REG(DC_DISP_SD_WINDOW_SIZE); NVSD_PRINT_REG(DC_DISP_SD_SOFT_CLIPPING); NVSD_PRINT_REG(DC_DISP_SD_SMOOTH_K); #endif tegra_dc_io_end(dc); clk_disable(dc->clk); return res; }
int tegra_dc_update_csc(struct tegra_dc *dc, int win_idx) { mutex_lock(&dc->lock); if (!dc->enabled) { mutex_unlock(&dc->lock); return -EFAULT; } tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); tegra_dc_writel(dc, WINDOW_A_SELECT << win_idx, DC_CMD_DISPLAY_WINDOW_HEADER); tegra_dc_set_csc(dc, &dc->windows[win_idx].csc); tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); mutex_unlock(&dc->lock); return 0; }
/* does not support syncing windows on multiple dcs in one call */ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n) { int ret; if (n < 1 || n > DC_N_WINDOWS) return -EINVAL; if (!windows[0]->dc->enabled) return -EFAULT; trace_sync_windows(windows[0]->dc); #ifdef CONFIG_TEGRA_SIMULATION_PLATFORM /* Don't want to timeout on simulator */ ret = wait_event_interruptible(windows[0]->dc->wq, tegra_dc_windows_are_clean(windows, n)); #else ret = wait_event_interruptible_timeout(windows[0]->dc->wq, tegra_dc_windows_are_clean(windows, n), HZ); #endif /* tegra_dc_io_start() done in update_windows */ tegra_dc_io_end(windows[0]->dc); return ret; }
static int dbg_dsi_show(struct seq_file *s, void *unused) { struct tegra_dc_dsi_data *dsi = s->private; unsigned long i = 0, j = 0; u32 col = 0; u32 base[MAX_DSI_INSTANCE] = {TEGRA_DSI_BASE, TEGRA_DSIB_BASE}; if (!dsi->enabled) { seq_puts(s, "DSI controller suspended\n"); return 0; } tegra_dc_io_start(dsi->dc); tegra_dsi_clk_enable(dsi); /* mem dd dump */ for (i = 0; i < dsi->max_instances; i++) { for (col = 0, j = 0; j < 0x64; j++) { if (col == 0) seq_printf(s, "%08lX:", base[i] + 4*j); seq_printf(s, "%c%08lX", col == 2 ? '-' : ' ', tegra_dsi_controller_readl(dsi, j, i)); if (col == 3) { seq_puts(s, "\n"); col = 0; } else col++; } seq_puts(s, "\n"); } #define DUMP_REG(a) seq_printf(s, "%-45s | %#05x | %#010lx |\n", \ #a, a, tegra_dsi_readl(dsi, a)); DUMP_REG(DSI_INCR_SYNCPT_CNTRL); DUMP_REG(DSI_INCR_SYNCPT_ERROR); DUMP_REG(DSI_CTXSW); DUMP_REG(DSI_POWER_CONTROL); DUMP_REG(DSI_INT_ENABLE); DUMP_REG(DSI_HOST_DSI_CONTROL); DUMP_REG(DSI_CONTROL); DUMP_REG(DSI_SOL_DELAY); DUMP_REG(DSI_MAX_THRESHOLD); DUMP_REG(DSI_TRIGGER); DUMP_REG(DSI_TX_CRC); DUMP_REG(DSI_STATUS); DUMP_REG(DSI_INIT_SEQ_CONTROL); DUMP_REG(DSI_INIT_SEQ_DATA_0); DUMP_REG(DSI_INIT_SEQ_DATA_1); DUMP_REG(DSI_INIT_SEQ_DATA_2); DUMP_REG(DSI_INIT_SEQ_DATA_3); DUMP_REG(DSI_INIT_SEQ_DATA_4); DUMP_REG(DSI_INIT_SEQ_DATA_5); DUMP_REG(DSI_INIT_SEQ_DATA_6); DUMP_REG(DSI_INIT_SEQ_DATA_7); DUMP_REG(DSI_PKT_SEQ_0_LO); DUMP_REG(DSI_PKT_SEQ_0_HI); DUMP_REG(DSI_PKT_SEQ_1_LO); DUMP_REG(DSI_PKT_SEQ_1_HI); DUMP_REG(DSI_PKT_SEQ_2_LO); DUMP_REG(DSI_PKT_SEQ_2_HI); DUMP_REG(DSI_PKT_SEQ_3_LO); DUMP_REG(DSI_PKT_SEQ_3_HI); DUMP_REG(DSI_PKT_SEQ_4_LO); DUMP_REG(DSI_PKT_SEQ_4_HI); DUMP_REG(DSI_PKT_SEQ_5_LO); DUMP_REG(DSI_PKT_SEQ_5_HI); DUMP_REG(DSI_DCS_CMDS); DUMP_REG(DSI_PKT_LEN_0_1); DUMP_REG(DSI_PKT_LEN_2_3); DUMP_REG(DSI_PKT_LEN_4_5); DUMP_REG(DSI_PKT_LEN_6_7); DUMP_REG(DSI_PHY_TIMING_0); DUMP_REG(DSI_PHY_TIMING_1); DUMP_REG(DSI_PHY_TIMING_2); DUMP_REG(DSI_BTA_TIMING); DUMP_REG(DSI_TIMEOUT_0); DUMP_REG(DSI_TIMEOUT_1); DUMP_REG(DSI_TO_TALLY); DUMP_REG(DSI_PAD_CONTROL); DUMP_REG(DSI_PAD_CONTROL_CD); DUMP_REG(DSI_PAD_CD_STATUS); DUMP_REG(DSI_VID_MODE_CONTROL); DUMP_REG(DSI_PAD_CONTROL_0_VS1); DUMP_REG(DSI_PAD_CONTROL_CD_VS1); DUMP_REG(DSI_PAD_CD_STATUS_VS1); DUMP_REG(DSI_PAD_CONTROL_1_VS1); DUMP_REG(DSI_PAD_CONTROL_2_VS1); DUMP_REG(DSI_PAD_CONTROL_3_VS1); DUMP_REG(DSI_PAD_CONTROL_4_VS1); DUMP_REG(DSI_GANGED_MODE_CONTROL); DUMP_REG(DSI_GANGED_MODE_START); DUMP_REG(DSI_GANGED_MODE_SIZE); #undef DUMP_REG tegra_dsi_clk_disable(dsi); tegra_dc_io_end(dsi->dc); return 0; }
/* Functional initialization */ void nvsd_init(struct tegra_dc *dc, struct tegra_dc_sd_settings *settings) { u32 i = 0; u32 val = 0; u32 bw = 0; u32 bw_idx = 0; /* TODO: check if HW says SD's available */ tegra_dc_io_start(dc); /* If SD's not present or disabled, clear the register and return. */ if (!settings || settings->enable == 0) { /* clear the brightness val, too. */ if (_sd_brightness) atomic_set(_sd_brightness, 255); _sd_brightness = NULL; if (settings) settings->phase_settings_step = 0; tegra_dc_writel(dc, 0, DC_DISP_SD_CONTROL); tegra_dc_io_end(dc); return; } dev_dbg(&dc->ndev->dev, "NVSD Init:\n"); /* init agg_priorities */ if (!settings->agg_priorities.agg[0]) settings->agg_priorities.agg[0] = settings->aggressiveness; /* WAR: Settings will not be valid until the next flip. * Thus, set manual K to either HW's current value (if * we're already enabled) or a non-effective value (if * we're about to enable). */ val = tegra_dc_readl(dc, DC_DISP_SD_CONTROL); if (val & SD_ENABLE_NORMAL) if (settings->phase_in_adjustments) i = tegra_dc_readl(dc, DC_DISP_SD_MAN_K_VALUES); else i = tegra_dc_readl(dc, DC_DISP_SD_HW_K_VALUES); else i = 0; /* 0 values for RGB = 1.0, i.e. non-affected */ tegra_dc_writel(dc, i, DC_DISP_SD_MAN_K_VALUES); /* Enable manual correction mode here so that changing the * settings won't immediately impact display dehavior. */ val |= SD_CORRECTION_MODE_MAN; tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); bw_idx = nvsd_get_bw_idx(settings); bw = SD_BIN_WIDTH(bw_idx); /* Values of SD LUT & BL TF are different according to bin_width on T30 * due to HW bug. Therefore we use bin_width to select the correct table * on T30. On T114, we will use 1st table by default.*/ #ifdef CONFIG_TEGRA_SD_GEN2 bw_idx = 0; #endif /* Write LUT */ if (!settings->cmd) { dev_dbg(&dc->ndev->dev, " LUT:\n"); for (i = 0; i < DC_DISP_SD_LUT_NUM; i++) { val = SD_LUT_R(settings->lut[bw_idx][i].r) | SD_LUT_G(settings->lut[bw_idx][i].g) | SD_LUT_B(settings->lut[bw_idx][i].b); tegra_dc_writel(dc, val, DC_DISP_SD_LUT(i)); dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val); } } /* Write BL TF */ if (!settings->cmd) { dev_dbg(&dc->ndev->dev, " BL_TF:\n"); for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) { val = SD_BL_TF_POINT_0(settings->bltf[bw_idx][i][0]) | SD_BL_TF_POINT_1(settings->bltf[bw_idx][i][1]) | SD_BL_TF_POINT_2(settings->bltf[bw_idx][i][2]) | SD_BL_TF_POINT_3(settings->bltf[bw_idx][i][3]); tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i)); dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val); } } else if ((settings->cmd & PHASE_IN)) { settings->cmd &= ~PHASE_IN; /* Write NO_OP values for BLTF */ for (i = 0; i < DC_DISP_SD_BL_TF_NUM; i++) { val = SD_BL_TF_POINT_0(0xFF) | SD_BL_TF_POINT_1(0xFF) | SD_BL_TF_POINT_2(0xFF) | SD_BL_TF_POINT_3(0xFF); tegra_dc_writel(dc, val, DC_DISP_SD_BL_TF(i)); dev_dbg(&dc->ndev->dev, " %d: 0x%08x\n", i, val); } } /* Set step correctly on init */ if (!settings->cmd && settings->phase_in_settings) { settings->num_phase_in_steps = STEPS_PER_AGG_LVL * settings->aggressiveness; settings->phase_settings_step = settings->enable ? settings->num_phase_in_steps : 0; } /* Write Coeff */ val = SD_CSC_COEFF_R(settings->coeff.r) | SD_CSC_COEFF_G(settings->coeff.g) | SD_CSC_COEFF_B(settings->coeff.b); tegra_dc_writel(dc, val, DC_DISP_SD_CSC_COEFF); dev_dbg(&dc->ndev->dev, " COEFF: 0x%08x\n", val); /* Write BL Params */ val = SD_BLP_TIME_CONSTANT(settings->blp.time_constant) | SD_BLP_STEP(settings->blp.step); tegra_dc_writel(dc, val, DC_DISP_SD_BL_PARAMETERS); dev_dbg(&dc->ndev->dev, " BLP: 0x%08x\n", val); /* Write Auto/Manual PWM */ val = (settings->use_auto_pwm) ? SD_BLC_MODE_AUTO : SD_BLC_MODE_MAN; tegra_dc_writel(dc, val, DC_DISP_SD_BL_CONTROL); dev_dbg(&dc->ndev->dev, " BL_CONTROL: 0x%08x\n", val); /* Write Flicker Control */ val = SD_FC_TIME_LIMIT(settings->fc.time_limit) | SD_FC_THRESHOLD(settings->fc.threshold); tegra_dc_writel(dc, val, DC_DISP_SD_FLICKER_CONTROL); dev_dbg(&dc->ndev->dev, " FLICKER_CONTROL: 0x%08x\n", val); #ifdef CONFIG_TEGRA_SD_GEN2 /* Write K limit */ if (settings->k_limit_enable) { val = settings->k_limit; if (val < 128) val = 128; else if (val > 255) val = 255; val = SD_K_LIMIT(val); tegra_dc_writel(dc, val, DC_DISP_SD_K_LIMIT); dev_dbg(&dc->ndev->dev, " K_LIMIT: 0x%08x\n", val); } if (settings->sd_window_enable) { /* Write sd window */ val = SD_WIN_H_POSITION(settings->sd_window.h_position) | SD_WIN_V_POSITION(settings->sd_window.v_position); tegra_dc_writel(dc, val, DC_DISP_SD_WINDOW_POSITION); dev_dbg(&dc->ndev->dev, " SD_WINDOW_POSITION: 0x%08x\n", val); val = SD_WIN_H_POSITION(settings->sd_window.h_size) | SD_WIN_V_POSITION(settings->sd_window.v_size); tegra_dc_writel(dc, val, DC_DISP_SD_WINDOW_SIZE); dev_dbg(&dc->ndev->dev, " SD_WINDOW_SIZE: 0x%08x\n", val); } if (settings->soft_clipping_enable) { /* Write soft clipping */ val = (64 * 1024) / (256 - settings->soft_clipping_threshold); val = SD_SOFT_CLIPPING_RECIP(val) | SD_SOFT_CLIPPING_THRESHOLD(settings->soft_clipping_threshold); tegra_dc_writel(dc, val, DC_DISP_SD_SOFT_CLIPPING); dev_dbg(&dc->ndev->dev, " SOFT_CLIPPING: 0x%08x\n", val); } if (settings->smooth_k_enable) { fixed20_12 smooth_k_incr; fixed20_12 num; /* Write K incr value */ val = SD_SMOOTH_K_INCR(settings->smooth_k_incr); tegra_dc_writel(dc, val, DC_DISP_SD_SMOOTH_K); dev_dbg(&dc->ndev->dev, " SMOOTH_K: 0x%08x\n", val); /* Convert 8.6 fixed-point to 20.12 fixed-point */ smooth_k_incr.full = val << 6; /* In the BL_TF LUT, raw K is specified in steps of 8 */ num.full = dfixed_const(8); num.full = dfixed_div(num, smooth_k_incr); num.full = dfixed_ceil(num); smooth_k_frames_left = dfixed_trunc(num); smooth_k_duration_frames = smooth_k_frames_left; dev_dbg(&dc->ndev->dev, " Smooth K duration (frames): %d\n", smooth_k_frames_left); } #endif /* Manage SD Control */ val = 0; /* Stay in manual correction mode until the next flip. */ val |= SD_CORRECTION_MODE_MAN; /* Enable / One-Shot */ val |= (settings->enable == 2) ? (SD_ENABLE_ONESHOT | SD_ONESHOT_ENABLE) : SD_ENABLE_NORMAL; /* HW Update Delay */ val |= SD_HW_UPDATE_DLY(settings->hw_update_delay); /* Video Luma */ val |= (settings->use_vid_luma) ? SD_USE_VID_LUMA : 0; /* Aggressiveness */ val |= SD_AGGRESSIVENESS(settings->aggressiveness); /* Bin Width (value derived above) */ val |= bw; #ifdef CONFIG_TEGRA_SD_GEN2 /* K limit enable */ val |= (settings->k_limit_enable) ? SD_K_LIMIT_ENABLE : 0; /* Programmable sd window enable */ val |= (settings->sd_window_enable) ? SD_WINDOW_ENABLE : 0; /* Soft clipping enable */ val |= (settings->soft_clipping_enable) ? SD_SOFT_CLIPPING_ENABLE : 0; /* Smooth K enable */ val |= (settings->smooth_k_enable) ? SD_SMOOTH_K_ENABLE : 0; /* SD proc control */ val |= (settings->use_vpulse2) ? SD_VPULSE2 : SD_VSYNC; #endif /* Finally, Write SD Control */ tegra_dc_writel(dc, val, DC_DISP_SD_CONTROL); dev_dbg(&dc->ndev->dev, " SD_CONTROL: 0x%08x\n", val); tegra_dc_io_end(dc); /* set the brightness pointer */ _sd_brightness = settings->sd_brightness; /* note that we're in manual K until the next flip */ atomic_set(&man_k_until_blank, 1); }
int tegra_dc_ext_set_cursor_image(struct tegra_dc_ext_user *user, struct tegra_dc_ext_cursor_image *args) { struct tegra_dc_ext *ext = user->ext; struct tegra_dc *dc = ext->dc; struct nvmap_handle_ref *handle, *old_handle; dma_addr_t phys_addr; u32 size; int ret; if (!user->nvmap) return -EFAULT; size = TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE(args->flags); #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64) return -EINVAL; #else if (size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_32x32 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_64x64 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_128x128 && size != TEGRA_DC_EXT_CURSOR_IMAGE_FLAGS_SIZE_256x256) return -EINVAL; #endif #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) if (args->flags && TEGRA_DC_EXT_CURSOR_FLAGS_RGBA_NORMAL) return -EINVAL; #endif mutex_lock(&ext->cursor.lock); if (ext->cursor.user != user) { ret = -EACCES; goto unlock; } if (!ext->enabled) { ret = -ENXIO; goto unlock; } old_handle = ext->cursor.cur_handle; ret = tegra_dc_ext_pin_window(user, args->buff_id, &handle, &phys_addr); if (ret) goto unlock; ext->cursor.cur_handle = handle; mutex_lock(&dc->lock); tegra_dc_io_start(dc); tegra_dc_hold_dc_out(dc); set_cursor_image_hw(dc, args, phys_addr); tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_release_dc_out(dc); tegra_dc_io_end(dc); /* XXX sync here? */ mutex_unlock(&dc->lock); mutex_unlock(&ext->cursor.lock); if (old_handle) { nvmap_unpin(ext->nvmap, old_handle); nvmap_free(ext->nvmap, old_handle); } return 0; unlock: mutex_unlock(&ext->cursor.lock); return ret; }
static void handle_check_edid_l(struct tegra_dc_hdmi_data *hdmi) { struct fb_monspecs specs; #ifdef CONFIG_SWITCH int state; #endif memset(&specs, 0, sizeof(specs)); #ifdef CONFIG_FRAMEBUFFER_CONSOLE /* Set default videomode on dc before enabling it*/ tegra_dc_set_default_videomode(hdmi->dc); #endif if (!tegra_dc_hpd(work_state.hdmi->dc)) { /* hpd dropped - stop EDID read */ pr_info("hpd == 0, aborting EDID read\n"); goto end_disabled; } if (tegra_edid_get_monspecs(hdmi->edid, &specs)) { /* Failed to read EDID. If we still have retry attempts left, * schedule another attempt. Otherwise give up and just go to * the disabled state. */ work_state.edid_reads++; if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) { pr_info("Failed to read EDID after %d times. Giving up.\n", work_state.edid_reads); goto end_disabled; } else { hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID, CHECK_EDID_DELAY_MS); } return; } if (tegra_edid_get_eld(hdmi->edid, &hdmi->eld) < 0) { pr_err("error populating eld\n"); goto end_disabled; } hdmi->eld_retrieved = true; pr_info("panel size %d by %d\n", specs.max_x, specs.max_y); /* monitors like to lie about these but they are still useful for * detecting aspect ratios */ hdmi->dc->out->h_size = specs.max_x * 1000; hdmi->dc->out->v_size = specs.max_y * 1000; hdmi->dvi = !(specs.misc & FB_MISC_HDMI); #ifdef CONFIG_ADF_TEGRA tegra_adf_process_hotplug_connected(hdmi->dc->adf, &specs); #endif #ifdef CONFIG_TEGRA_DC_EXTENSIONS tegra_fb_update_monspecs(hdmi->dc->fb, &specs, tegra_dc_hdmi_mode_filter); #endif #ifdef CONFIG_SWITCH state = tegra_edid_audio_supported(hdmi->edid) ? 1 : 0; switch_set_state(&hdmi->audio_switch, state); pr_info("%s: audio_switch %d\n", __func__, state); switch_set_state(&hdmi->hpd_switch, 1); pr_info("Display connected, hpd_switch 1\n"); #endif hdmi->dc->connected = true; #ifdef CONFIG_TEGRA_DC_EXTENSIONS tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id); #endif if (unlikely(tegra_is_clk_enabled(hdmi->clk))) { /* the only time this should happen is on boot, where the * sequence is that hdmi is enabled before EDID is read. * hdmi_enable() doesn't have EDID information yet so can't * setup audio and infoframes, so we have to do so here. */ pr_info("%s: setting audio and infoframes\n", __func__); tegra_dc_io_start(hdmi->dc); tegra_dc_hdmi_setup_audio_and_infoframes(hdmi->dc); tegra_dc_io_end(hdmi->dc); } hdmi_state_machine_set_state_l(HDMI_STATE_DONE_ENABLED, -1); return; end_disabled: hdmi->eld_retrieved = false; hdmi_disable_l(hdmi); hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1); }
static void _tegra_dc_disable(struct tegra_dc *dc) { _tegra_dc_controller_disable(dc); tegra_dc_io_end(dc); }
static void _dump_regs(struct tegra_dc *dc, void *data, void (* print)(void *data, const char *str)) { int i; char buff[256]; tegra_dc_io_start(dc); clk_enable(dc->clk); DUMP_REG(DC_CMD_DISPLAY_COMMAND_OPTION0); DUMP_REG(DC_CMD_DISPLAY_COMMAND); DUMP_REG(DC_CMD_SIGNAL_RAISE); DUMP_REG(DC_CMD_INT_STATUS); DUMP_REG(DC_CMD_INT_MASK); DUMP_REG(DC_CMD_INT_ENABLE); DUMP_REG(DC_CMD_INT_TYPE); DUMP_REG(DC_CMD_INT_POLARITY); DUMP_REG(DC_CMD_SIGNAL_RAISE1); DUMP_REG(DC_CMD_SIGNAL_RAISE2); DUMP_REG(DC_CMD_SIGNAL_RAISE3); DUMP_REG(DC_CMD_STATE_ACCESS); DUMP_REG(DC_CMD_STATE_CONTROL); DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER); DUMP_REG(DC_CMD_REG_ACT_CONTROL); DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS0); DUMP_REG(DC_DISP_DISP_SIGNAL_OPTIONS1); DUMP_REG(DC_DISP_DISP_WIN_OPTIONS); DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY); DUMP_REG(DC_DISP_MEM_HIGH_PRIORITY_TIMER); DUMP_REG(DC_DISP_DISP_TIMING_OPTIONS); DUMP_REG(DC_DISP_REF_TO_SYNC); DUMP_REG(DC_DISP_SYNC_WIDTH); DUMP_REG(DC_DISP_BACK_PORCH); DUMP_REG(DC_DISP_DISP_ACTIVE); DUMP_REG(DC_DISP_FRONT_PORCH); DUMP_REG(DC_DISP_H_PULSE0_CONTROL); DUMP_REG(DC_DISP_H_PULSE0_POSITION_A); DUMP_REG(DC_DISP_H_PULSE0_POSITION_B); DUMP_REG(DC_DISP_H_PULSE0_POSITION_C); DUMP_REG(DC_DISP_H_PULSE0_POSITION_D); DUMP_REG(DC_DISP_H_PULSE1_CONTROL); DUMP_REG(DC_DISP_H_PULSE1_POSITION_A); DUMP_REG(DC_DISP_H_PULSE1_POSITION_B); DUMP_REG(DC_DISP_H_PULSE1_POSITION_C); DUMP_REG(DC_DISP_H_PULSE1_POSITION_D); DUMP_REG(DC_DISP_H_PULSE2_CONTROL); DUMP_REG(DC_DISP_H_PULSE2_POSITION_A); DUMP_REG(DC_DISP_H_PULSE2_POSITION_B); DUMP_REG(DC_DISP_H_PULSE2_POSITION_C); DUMP_REG(DC_DISP_H_PULSE2_POSITION_D); DUMP_REG(DC_DISP_V_PULSE0_CONTROL); DUMP_REG(DC_DISP_V_PULSE0_POSITION_A); DUMP_REG(DC_DISP_V_PULSE0_POSITION_B); DUMP_REG(DC_DISP_V_PULSE0_POSITION_C); DUMP_REG(DC_DISP_V_PULSE1_CONTROL); DUMP_REG(DC_DISP_V_PULSE1_POSITION_A); DUMP_REG(DC_DISP_V_PULSE1_POSITION_B); DUMP_REG(DC_DISP_V_PULSE1_POSITION_C); DUMP_REG(DC_DISP_V_PULSE2_CONTROL); DUMP_REG(DC_DISP_V_PULSE2_POSITION_A); DUMP_REG(DC_DISP_V_PULSE3_CONTROL); DUMP_REG(DC_DISP_V_PULSE3_POSITION_A); DUMP_REG(DC_DISP_M0_CONTROL); DUMP_REG(DC_DISP_M1_CONTROL); DUMP_REG(DC_DISP_DI_CONTROL); DUMP_REG(DC_DISP_PP_CONTROL); DUMP_REG(DC_DISP_PP_SELECT_A); DUMP_REG(DC_DISP_PP_SELECT_B); DUMP_REG(DC_DISP_PP_SELECT_C); DUMP_REG(DC_DISP_PP_SELECT_D); DUMP_REG(DC_DISP_DISP_CLOCK_CONTROL); DUMP_REG(DC_DISP_DISP_INTERFACE_CONTROL); DUMP_REG(DC_DISP_DISP_COLOR_CONTROL); DUMP_REG(DC_DISP_SHIFT_CLOCK_OPTIONS); DUMP_REG(DC_DISP_DATA_ENABLE_OPTIONS); DUMP_REG(DC_DISP_SERIAL_INTERFACE_OPTIONS); DUMP_REG(DC_DISP_LCD_SPI_OPTIONS); DUMP_REG(DC_DISP_BORDER_COLOR); DUMP_REG(DC_DISP_COLOR_KEY0_LOWER); DUMP_REG(DC_DISP_COLOR_KEY0_UPPER); DUMP_REG(DC_DISP_COLOR_KEY1_LOWER); DUMP_REG(DC_DISP_COLOR_KEY1_UPPER); DUMP_REG(DC_DISP_CURSOR_FOREGROUND); DUMP_REG(DC_DISP_CURSOR_BACKGROUND); DUMP_REG(DC_DISP_CURSOR_START_ADDR); DUMP_REG(DC_DISP_CURSOR_START_ADDR_NS); DUMP_REG(DC_DISP_CURSOR_POSITION); DUMP_REG(DC_DISP_CURSOR_POSITION_NS); DUMP_REG(DC_DISP_INIT_SEQ_CONTROL); DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_A); DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_B); DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_C); DUMP_REG(DC_DISP_SPI_INIT_SEQ_DATA_D); DUMP_REG(DC_DISP_DC_MCCIF_FIFOCTRL); DUMP_REG(DC_DISP_MCCIF_DISPLAY0A_HYST); DUMP_REG(DC_DISP_MCCIF_DISPLAY0B_HYST); DUMP_REG(DC_DISP_MCCIF_DISPLAY0C_HYST); DUMP_REG(DC_DISP_MCCIF_DISPLAY1B_HYST); DUMP_REG(DC_DISP_DAC_CRT_CTRL); DUMP_REG(DC_DISP_DISP_MISC_CONTROL); for (i = 0; i < 3; i++) { print(data, "\n"); snprintf(buff, sizeof(buff), "WINDOW %c:\n", 'A' + i); print(data, buff); tegra_dc_writel(dc, WINDOW_A_SELECT << i, DC_CMD_DISPLAY_WINDOW_HEADER); DUMP_REG(DC_CMD_DISPLAY_WINDOW_HEADER); DUMP_REG(DC_WIN_WIN_OPTIONS); DUMP_REG(DC_WIN_BYTE_SWAP); DUMP_REG(DC_WIN_BUFFER_CONTROL); DUMP_REG(DC_WIN_COLOR_DEPTH); DUMP_REG(DC_WIN_POSITION); DUMP_REG(DC_WIN_SIZE); DUMP_REG(DC_WIN_PRESCALED_SIZE); DUMP_REG(DC_WIN_H_INITIAL_DDA); DUMP_REG(DC_WIN_V_INITIAL_DDA); DUMP_REG(DC_WIN_DDA_INCREMENT); DUMP_REG(DC_WIN_LINE_STRIDE); DUMP_REG(DC_WIN_BUF_STRIDE); DUMP_REG(DC_WIN_UV_BUF_STRIDE); DUMP_REG(DC_WIN_BLEND_NOKEY); DUMP_REG(DC_WIN_BLEND_1WIN); DUMP_REG(DC_WIN_BLEND_2WIN_X); DUMP_REG(DC_WIN_BLEND_2WIN_Y); DUMP_REG(DC_WIN_BLEND_3WIN_XY); DUMP_REG(DC_WINBUF_START_ADDR); DUMP_REG(DC_WINBUF_START_ADDR_U); DUMP_REG(DC_WINBUF_START_ADDR_V); DUMP_REG(DC_WINBUF_ADDR_H_OFFSET); DUMP_REG(DC_WINBUF_ADDR_V_OFFSET); DUMP_REG(DC_WINBUF_UFLOW_STATUS); DUMP_REG(DC_WIN_CSC_YOF); DUMP_REG(DC_WIN_CSC_KYRGB); DUMP_REG(DC_WIN_CSC_KUR); DUMP_REG(DC_WIN_CSC_KVR); DUMP_REG(DC_WIN_CSC_KUG); DUMP_REG(DC_WIN_CSC_KVG); DUMP_REG(DC_WIN_CSC_KUB); DUMP_REG(DC_WIN_CSC_KVB); } clk_disable(dc->clk); tegra_dc_io_end(dc); }
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_io_start(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); 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)); /* The display panel sub-board used on FPGA platforms (panel 86) is non-standard. It expects the Data Enable signal on the WR pin instead of the DE pin. */ if (tegra_platform_is_fpga()) out_sel_pintable[3*2+1] = 0x00200000; 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_ACT_REQ, DC_CMD_STATE_CONTROL); tegra_dc_io_end(dc); }
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; }