static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config, int pipe) { struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_dpi_timing dpi_timing; struct drm_display_mode *mode = dsi_config->mode; mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), mode->vdisplay << 16 | mode->hdisplay); REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HBP_COUNT_REG(pipe), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HFP_COUNT_REG(pipe), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VBP_COUNT_REG(pipe), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VFP_COUNT_REG(pipe), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); }
/** * Setup DPI timing for video mode MIPI panel. * NOTE: do NOT modify this function */ static void __mdfld_dsi_dpi_set_timing(struct mdfld_dsi_config *config, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_dpi_timing dpi_timing; struct mdfld_dsi_hw_context *ctx; if (!config) { DRM_ERROR("Invalid parameters\n"); return; } struct drm_device *dev = config->dev; mode = adjusted_mode; ctx = &config->dsi_hw_context; mutex_lock(&config->context_lock); /*dpi resolution*/ if (is_dual_dsi(dev)) ctx->dpi_resolution = (mode->vdisplay << 16 | (mode->hdisplay / 2)); else ctx->dpi_resolution = (mode->vdisplay << 16 | mode->hdisplay); /*Calculate DPI timing*/ mdfld_dsi_dpi_timing_calculation(dev, mode, &dpi_timing, config->lane_count, config->bpp); /*update HW context with new DPI timings*/ ctx->hsync_count = dpi_timing.hsync_count; ctx->hbp_count = dpi_timing.hbp_count; ctx->hfp_count = dpi_timing.hfp_count; ctx->hactive_count = dpi_timing.hactive_count; ctx->vsync_count = dpi_timing.vsync_count; ctx->vbp_count = dpi_timing.vbp_count; ctx->vfp_count = dpi_timing.vfp_count; mutex_unlock(&config->context_lock); }
void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) { struct drm_device *dev = dsi_config->dev; int lane_count = dsi_config->lane_count; struct mdfld_dsi_dpi_timing dpi_timing; struct drm_display_mode *mode = dsi_config->mode; u32 val; /*un-ready device*/ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0); /*init dsi adapter before kicking off*/ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); /*enable all interrupts*/ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); /*set up func_prg*/ val = lane_count; val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; switch (dsi_config->bpp) { case 16: val |= DSI_DPI_COLOR_FORMAT_RGB565; break; case 18: val |= DSI_DPI_COLOR_FORMAT_RGB666; break; case 24: val |= DSI_DPI_COLOR_FORMAT_RGB888; break; default: DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); } REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val); REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff & DSI_LP_RX_TIMEOUT_MASK); /*max value: 20 clock cycles of txclkesc*/ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); /*min 21 txclkesc, max: ffffh*/ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xffff & DSI_RESET_TIMER_MASK); REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), mode->vdisplay << 16 | mode->hdisplay); /*set DPI timing registers*/ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HBP_COUNT_REG(pipe), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HFP_COUNT_REG(pipe), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VBP_COUNT_REG(pipe), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VFP_COUNT_REG(pipe), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46); /*min: 7d0 max: 4e20*/ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0); /*set up video mode*/ val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val); REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); /*TODO: figure out how to setup these registers*/ if (mdfld_get_panel_type(dev, pipe) == TC35876X) REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); else REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408); REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); if (mdfld_get_panel_type(dev, pipe) == TC35876X) tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ /*set device ready*/ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0); }