drm/tegra: dc: Register debugfs in ->late_register()

The ->late_register() and ->early_unregister() callbacks are called at
the right time to make sure userspace only accesses interfaces when it
should. Move debugfs registration and unregistration to these callback
functions to avoid potential races with userspace.

Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Thierry Reding 2017-11-08 13:40:54 +01:00
Родитель c49c81e21c
Коммит b95800eeef
2 изменённых файлов: 335 добавлений и 365 удалений

Просмотреть файл

@ -959,6 +959,339 @@ static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
kfree(state); kfree(state);
} }
#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
static const struct debugfs_reg32 tegra_dc_regs[] = {
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
DEBUGFS_REG32(DC_CMD_INT_STATUS),
DEBUGFS_REG32(DC_CMD_INT_MASK),
DEBUGFS_REG32(DC_CMD_INT_ENABLE),
DEBUGFS_REG32(DC_CMD_INT_TYPE),
DEBUGFS_REG32(DC_CMD_INT_POLARITY),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
DEBUGFS_REG32(DC_COM_CRC_CONTROL),
DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
DEBUGFS_REG32(DC_COM_SPI_CONTROL),
DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
DEBUGFS_REG32(DC_COM_GPIO_CTRL),
DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
DEBUGFS_REG32(DC_DISP_BACK_PORCH),
DEBUGFS_REG32(DC_DISP_ACTIVE),
DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
DEBUGFS_REG32(DC_DISP_M0_CONTROL),
DEBUGFS_REG32(DC_DISP_M1_CONTROL),
DEBUGFS_REG32(DC_DISP_DI_CONTROL),
DEBUGFS_REG32(DC_DISP_PP_CONTROL),
DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
DEBUGFS_REG32(DC_WIN_POSITION),
DEBUGFS_REG32(DC_WIN_SIZE),
DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
DEBUGFS_REG32(DC_WIN_DDA_INC),
DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
DEBUGFS_REG32(DC_WIN_DV_CONTROL),
DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
DEBUGFS_REG32(DC_WINBUF_START_ADDR),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
};
static int tegra_dc_show_regs(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
unsigned int i;
int err = 0;
drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
goto unlock;
}
for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
unsigned int offset = tegra_dc_regs[i].offset;
seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
offset, tegra_dc_readl(dc, offset));
}
unlock:
drm_modeset_unlock(&dc->base.mutex);
return err;
}
static int tegra_dc_show_crc(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
int err = 0;
u32 value;
drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
goto unlock;
}
value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
tegra_dc_commit(dc);
drm_crtc_wait_one_vblank(&dc->base);
drm_crtc_wait_one_vblank(&dc->base);
value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
seq_printf(s, "%08x\n", value);
tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
unlock:
drm_modeset_unlock(&dc->base.mutex);
return err;
}
static int tegra_dc_show_stats(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
seq_printf(s, "frames: %lu\n", dc->stats.frames);
seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
return 0;
}
static struct drm_info_list debugfs_files[] = {
{ "regs", tegra_dc_show_regs, 0, NULL },
{ "crc", tegra_dc_show_crc, 0, NULL },
{ "stats", tegra_dc_show_stats, 0, NULL },
};
static int tegra_dc_late_register(struct drm_crtc *crtc)
{
unsigned int i, count = ARRAY_SIZE(debugfs_files);
struct drm_minor *minor = crtc->dev->primary;
struct dentry *root = crtc->debugfs_entry;
struct tegra_dc *dc = to_tegra_dc(crtc);
int err;
dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
GFP_KERNEL);
if (!dc->debugfs_files)
return -ENOMEM;
for (i = 0; i < count; i++)
dc->debugfs_files[i].data = dc;
err = drm_debugfs_create_files(dc->debugfs_files, count, root, minor);
if (err < 0)
goto free;
return 0;
free:
kfree(dc->debugfs_files);
dc->debugfs_files = NULL;
return err;
}
static void tegra_dc_early_unregister(struct drm_crtc *crtc)
{
unsigned int count = ARRAY_SIZE(debugfs_files);
struct drm_minor *minor = crtc->dev->primary;
struct tegra_dc *dc = to_tegra_dc(crtc);
drm_debugfs_remove_files(dc->debugfs_files, count, minor);
kfree(dc->debugfs_files);
dc->debugfs_files = NULL;
}
static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc) static u32 tegra_dc_get_vblank_counter(struct drm_crtc *crtc)
{ {
struct tegra_dc *dc = to_tegra_dc(crtc); struct tegra_dc *dc = to_tegra_dc(crtc);
@ -1007,6 +1340,8 @@ static const struct drm_crtc_funcs tegra_crtc_funcs = {
.reset = tegra_crtc_reset, .reset = tegra_crtc_reset,
.atomic_duplicate_state = tegra_crtc_atomic_duplicate_state, .atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
.atomic_destroy_state = tegra_crtc_atomic_destroy_state, .atomic_destroy_state = tegra_crtc_atomic_destroy_state,
.late_register = tegra_dc_late_register,
.early_unregister = tegra_dc_early_unregister,
.get_vblank_counter = tegra_dc_get_vblank_counter, .get_vblank_counter = tegra_dc_get_vblank_counter,
.enable_vblank = tegra_dc_enable_vblank, .enable_vblank = tegra_dc_enable_vblank,
.disable_vblank = tegra_dc_disable_vblank, .disable_vblank = tegra_dc_disable_vblank,
@ -1383,357 +1718,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#define DEBUGFS_REG32(_name) { .name = #_name, .offset = _name }
static const struct debugfs_reg32 tegra_dc_regs[] = {
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_GENERAL_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_A_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_B_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_CNTRL),
DEBUGFS_REG32(DC_CMD_WIN_C_INCR_SYNCPT_ERROR),
DEBUGFS_REG32(DC_CMD_CONT_SYNCPT_VSYNC),
DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND_OPTION0),
DEBUGFS_REG32(DC_CMD_DISPLAY_COMMAND),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE),
DEBUGFS_REG32(DC_CMD_DISPLAY_POWER_CONTROL),
DEBUGFS_REG32(DC_CMD_INT_STATUS),
DEBUGFS_REG32(DC_CMD_INT_MASK),
DEBUGFS_REG32(DC_CMD_INT_ENABLE),
DEBUGFS_REG32(DC_CMD_INT_TYPE),
DEBUGFS_REG32(DC_CMD_INT_POLARITY),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE1),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE2),
DEBUGFS_REG32(DC_CMD_SIGNAL_RAISE3),
DEBUGFS_REG32(DC_CMD_STATE_ACCESS),
DEBUGFS_REG32(DC_CMD_STATE_CONTROL),
DEBUGFS_REG32(DC_CMD_DISPLAY_WINDOW_HEADER),
DEBUGFS_REG32(DC_CMD_REG_ACT_CONTROL),
DEBUGFS_REG32(DC_COM_CRC_CONTROL),
DEBUGFS_REG32(DC_COM_CRC_CHECKSUM),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_ENABLE(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_POLARITY(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_DATA(3)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(0)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(1)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(2)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_ENABLE(3)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(0)),
DEBUGFS_REG32(DC_COM_PIN_INPUT_DATA(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(0)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(1)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(2)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(3)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(4)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(5)),
DEBUGFS_REG32(DC_COM_PIN_OUTPUT_SELECT(6)),
DEBUGFS_REG32(DC_COM_PIN_MISC_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM0_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM0_DUTY_CYCLE),
DEBUGFS_REG32(DC_COM_PIN_PM1_CONTROL),
DEBUGFS_REG32(DC_COM_PIN_PM1_DUTY_CYCLE),
DEBUGFS_REG32(DC_COM_SPI_CONTROL),
DEBUGFS_REG32(DC_COM_SPI_START_BYTE),
DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_AB),
DEBUGFS_REG32(DC_COM_HSPI_WRITE_DATA_CD),
DEBUGFS_REG32(DC_COM_HSPI_CS_DC),
DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_A),
DEBUGFS_REG32(DC_COM_SCRATCH_REGISTER_B),
DEBUGFS_REG32(DC_COM_GPIO_CTRL),
DEBUGFS_REG32(DC_COM_GPIO_DEBOUNCE_COUNTER),
DEBUGFS_REG32(DC_COM_CRC_CHECKSUM_LATCHED),
DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS0),
DEBUGFS_REG32(DC_DISP_DISP_SIGNAL_OPTIONS1),
DEBUGFS_REG32(DC_DISP_DISP_WIN_OPTIONS),
DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY),
DEBUGFS_REG32(DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER),
DEBUGFS_REG32(DC_DISP_DISP_TIMING_OPTIONS),
DEBUGFS_REG32(DC_DISP_REF_TO_SYNC),
DEBUGFS_REG32(DC_DISP_SYNC_WIDTH),
DEBUGFS_REG32(DC_DISP_BACK_PORCH),
DEBUGFS_REG32(DC_DISP_ACTIVE),
DEBUGFS_REG32(DC_DISP_FRONT_PORCH),
DEBUGFS_REG32(DC_DISP_H_PULSE0_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE0_POSITION_D),
DEBUGFS_REG32(DC_DISP_H_PULSE1_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE1_POSITION_D),
DEBUGFS_REG32(DC_DISP_H_PULSE2_CONTROL),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_A),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_B),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_C),
DEBUGFS_REG32(DC_DISP_H_PULSE2_POSITION_D),
DEBUGFS_REG32(DC_DISP_V_PULSE0_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_B),
DEBUGFS_REG32(DC_DISP_V_PULSE0_POSITION_C),
DEBUGFS_REG32(DC_DISP_V_PULSE1_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_B),
DEBUGFS_REG32(DC_DISP_V_PULSE1_POSITION_C),
DEBUGFS_REG32(DC_DISP_V_PULSE2_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE2_POSITION_A),
DEBUGFS_REG32(DC_DISP_V_PULSE3_CONTROL),
DEBUGFS_REG32(DC_DISP_V_PULSE3_POSITION_A),
DEBUGFS_REG32(DC_DISP_M0_CONTROL),
DEBUGFS_REG32(DC_DISP_M1_CONTROL),
DEBUGFS_REG32(DC_DISP_DI_CONTROL),
DEBUGFS_REG32(DC_DISP_PP_CONTROL),
DEBUGFS_REG32(DC_DISP_PP_SELECT_A),
DEBUGFS_REG32(DC_DISP_PP_SELECT_B),
DEBUGFS_REG32(DC_DISP_PP_SELECT_C),
DEBUGFS_REG32(DC_DISP_PP_SELECT_D),
DEBUGFS_REG32(DC_DISP_DISP_CLOCK_CONTROL),
DEBUGFS_REG32(DC_DISP_DISP_INTERFACE_CONTROL),
DEBUGFS_REG32(DC_DISP_DISP_COLOR_CONTROL),
DEBUGFS_REG32(DC_DISP_SHIFT_CLOCK_OPTIONS),
DEBUGFS_REG32(DC_DISP_DATA_ENABLE_OPTIONS),
DEBUGFS_REG32(DC_DISP_SERIAL_INTERFACE_OPTIONS),
DEBUGFS_REG32(DC_DISP_LCD_SPI_OPTIONS),
DEBUGFS_REG32(DC_DISP_BORDER_COLOR),
DEBUGFS_REG32(DC_DISP_COLOR_KEY0_LOWER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY0_UPPER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY1_LOWER),
DEBUGFS_REG32(DC_DISP_COLOR_KEY1_UPPER),
DEBUGFS_REG32(DC_DISP_CURSOR_FOREGROUND),
DEBUGFS_REG32(DC_DISP_CURSOR_BACKGROUND),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_NS),
DEBUGFS_REG32(DC_DISP_CURSOR_POSITION),
DEBUGFS_REG32(DC_DISP_CURSOR_POSITION_NS),
DEBUGFS_REG32(DC_DISP_INIT_SEQ_CONTROL),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_A),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_B),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_C),
DEBUGFS_REG32(DC_DISP_SPI_INIT_SEQ_DATA_D),
DEBUGFS_REG32(DC_DISP_DC_MCCIF_FIFOCTRL),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0A_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY0B_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1A_HYST),
DEBUGFS_REG32(DC_DISP_MCCIF_DISPLAY1B_HYST),
DEBUGFS_REG32(DC_DISP_DAC_CRT_CTRL),
DEBUGFS_REG32(DC_DISP_DISP_MISC_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_CSC_COEFF),
DEBUGFS_REG32(DC_DISP_SD_LUT(0)),
DEBUGFS_REG32(DC_DISP_SD_LUT(1)),
DEBUGFS_REG32(DC_DISP_SD_LUT(2)),
DEBUGFS_REG32(DC_DISP_SD_LUT(3)),
DEBUGFS_REG32(DC_DISP_SD_LUT(4)),
DEBUGFS_REG32(DC_DISP_SD_LUT(5)),
DEBUGFS_REG32(DC_DISP_SD_LUT(6)),
DEBUGFS_REG32(DC_DISP_SD_LUT(7)),
DEBUGFS_REG32(DC_DISP_SD_LUT(8)),
DEBUGFS_REG32(DC_DISP_SD_FLICKER_CONTROL),
DEBUGFS_REG32(DC_DISP_DC_PIXEL_COUNT),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(0)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(1)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(2)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(3)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(4)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(5)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(6)),
DEBUGFS_REG32(DC_DISP_SD_HISTOGRAM(7)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(0)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(1)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(2)),
DEBUGFS_REG32(DC_DISP_SD_BL_TF(3)),
DEBUGFS_REG32(DC_DISP_SD_BL_CONTROL),
DEBUGFS_REG32(DC_DISP_SD_HW_K_VALUES),
DEBUGFS_REG32(DC_DISP_SD_MAN_K_VALUES),
DEBUGFS_REG32(DC_DISP_CURSOR_START_ADDR_HI),
DEBUGFS_REG32(DC_DISP_BLEND_CURSOR_CONTROL),
DEBUGFS_REG32(DC_WIN_WIN_OPTIONS),
DEBUGFS_REG32(DC_WIN_BYTE_SWAP),
DEBUGFS_REG32(DC_WIN_BUFFER_CONTROL),
DEBUGFS_REG32(DC_WIN_COLOR_DEPTH),
DEBUGFS_REG32(DC_WIN_POSITION),
DEBUGFS_REG32(DC_WIN_SIZE),
DEBUGFS_REG32(DC_WIN_PRESCALED_SIZE),
DEBUGFS_REG32(DC_WIN_H_INITIAL_DDA),
DEBUGFS_REG32(DC_WIN_V_INITIAL_DDA),
DEBUGFS_REG32(DC_WIN_DDA_INC),
DEBUGFS_REG32(DC_WIN_LINE_STRIDE),
DEBUGFS_REG32(DC_WIN_BUF_STRIDE),
DEBUGFS_REG32(DC_WIN_UV_BUF_STRIDE),
DEBUGFS_REG32(DC_WIN_BUFFER_ADDR_MODE),
DEBUGFS_REG32(DC_WIN_DV_CONTROL),
DEBUGFS_REG32(DC_WIN_BLEND_NOKEY),
DEBUGFS_REG32(DC_WIN_BLEND_1WIN),
DEBUGFS_REG32(DC_WIN_BLEND_2WIN_X),
DEBUGFS_REG32(DC_WIN_BLEND_2WIN_Y),
DEBUGFS_REG32(DC_WIN_BLEND_3WIN_XY),
DEBUGFS_REG32(DC_WIN_HP_FETCH_CONTROL),
DEBUGFS_REG32(DC_WINBUF_START_ADDR),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_NS),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_U),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_U_NS),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_V),
DEBUGFS_REG32(DC_WINBUF_START_ADDR_V_NS),
DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET),
DEBUGFS_REG32(DC_WINBUF_ADDR_H_OFFSET_NS),
DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET),
DEBUGFS_REG32(DC_WINBUF_ADDR_V_OFFSET_NS),
DEBUGFS_REG32(DC_WINBUF_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_AD_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_BD_UFLOW_STATUS),
DEBUGFS_REG32(DC_WINBUF_CD_UFLOW_STATUS),
};
static int tegra_dc_show_regs(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
unsigned int i;
int err = 0;
drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
goto unlock;
}
for (i = 0; i < ARRAY_SIZE(tegra_dc_regs); i++) {
unsigned int offset = tegra_dc_regs[i].offset;
seq_printf(s, "%-40s %#05x %08x\n", tegra_dc_regs[i].name,
offset, tegra_dc_readl(dc, offset));
}
unlock:
drm_modeset_unlock(&dc->base.mutex);
return err;
}
static int tegra_dc_show_crc(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
int err = 0;
u32 value;
drm_modeset_lock(&dc->base.mutex, NULL);
if (!dc->base.state->active) {
err = -EBUSY;
goto unlock;
}
value = DC_COM_CRC_CONTROL_ACTIVE_DATA | DC_COM_CRC_CONTROL_ENABLE;
tegra_dc_writel(dc, value, DC_COM_CRC_CONTROL);
tegra_dc_commit(dc);
drm_crtc_wait_one_vblank(&dc->base);
drm_crtc_wait_one_vblank(&dc->base);
value = tegra_dc_readl(dc, DC_COM_CRC_CHECKSUM);
seq_printf(s, "%08x\n", value);
tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
unlock:
drm_modeset_unlock(&dc->base.mutex);
return err;
}
static int tegra_dc_show_stats(struct seq_file *s, void *data)
{
struct drm_info_node *node = s->private;
struct tegra_dc *dc = node->info_ent->data;
seq_printf(s, "frames: %lu\n", dc->stats.frames);
seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
return 0;
}
static struct drm_info_list debugfs_files[] = {
{ "regs", tegra_dc_show_regs, 0, NULL },
{ "crc", tegra_dc_show_crc, 0, NULL },
{ "stats", tegra_dc_show_stats, 0, NULL },
};
static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
{
unsigned int i;
char *name;
int err;
name = kasprintf(GFP_KERNEL, "dc.%d", dc->pipe);
dc->debugfs = debugfs_create_dir(name, minor->debugfs_root);
kfree(name);
if (!dc->debugfs)
return -ENOMEM;
dc->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
GFP_KERNEL);
if (!dc->debugfs_files) {
err = -ENOMEM;
goto remove;
}
for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
dc->debugfs_files[i].data = dc;
err = drm_debugfs_create_files(dc->debugfs_files,
ARRAY_SIZE(debugfs_files),
dc->debugfs, minor);
if (err < 0)
goto free;
dc->minor = minor;
return 0;
free:
kfree(dc->debugfs_files);
dc->debugfs_files = NULL;
remove:
debugfs_remove(dc->debugfs);
dc->debugfs = NULL;
return err;
}
static int tegra_dc_debugfs_exit(struct tegra_dc *dc)
{
drm_debugfs_remove_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files),
dc->minor);
dc->minor = NULL;
kfree(dc->debugfs_files);
dc->debugfs_files = NULL;
debugfs_remove(dc->debugfs);
dc->debugfs = NULL;
return 0;
}
static int tegra_dc_init(struct host1x_client *client) static int tegra_dc_init(struct host1x_client *client)
{ {
struct drm_device *drm = dev_get_drvdata(client->parent); struct drm_device *drm = dev_get_drvdata(client->parent);
@ -1797,12 +1781,6 @@ static int tegra_dc_init(struct host1x_client *client)
if (err < 0) if (err < 0)
goto cleanup; goto cleanup;
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
err = tegra_dc_debugfs_init(dc, drm->primary);
if (err < 0)
dev_err(dc->dev, "debugfs setup failed: %d\n", err);
}
err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0, err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0,
dev_name(dc->dev), dc); dev_name(dc->dev), dc);
if (err < 0) { if (err < 0) {
@ -1835,12 +1813,6 @@ static int tegra_dc_exit(struct host1x_client *client)
devm_free_irq(dc->dev, dc->irq, dc); devm_free_irq(dc->dev, dc->irq, dc);
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
err = tegra_dc_debugfs_exit(dc);
if (err < 0)
dev_err(dc->dev, "debugfs cleanup failed: %d\n", err);
}
err = tegra_dc_rgb_exit(dc); err = tegra_dc_rgb_exit(dc);
if (err) { if (err) {
dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err); dev_err(dc->dev, "failed to shutdown RGB output: %d\n", err);

Просмотреть файл

@ -56,8 +56,6 @@ struct tegra_dc {
struct list_head list; struct list_head list;
struct drm_info_list *debugfs_files; struct drm_info_list *debugfs_files;
struct drm_minor *minor;
struct dentry *debugfs;
/* page-flip handling */ /* page-flip handling */
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;