diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 08:16:33 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-06-06 08:16:33 -0700 |
commit | 135c5504a600ff9b06e321694fbcac78a9530cd4 (patch) | |
tree | 8d22ed739b0e85954010a964a9aeadf3c692c977 /drivers/gpu/drm/sun4i/sun4i_tcon.c | |
parent | Merge branch 'for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/wq (diff) | |
parent | Merge tag 'drm-amdkfd-next-2018-05-28' of git://people.freedesktop.org/~gabbayo/linux into drm-next (diff) | |
download | linux-dev-135c5504a600ff9b06e321694fbcac78a9530cd4.tar.xz linux-dev-135c5504a600ff9b06e321694fbcac78a9530cd4.zip |
Merge tag 'drm-next-2018-06-06-1' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie:
"This starts to support NVIDIA volta hardware with nouveau, and adds
amdgpu support for the GPU in the Kabylake-G (the intel + radeon
single package chip), along with some initial Intel icelake enabling.
Summary:
New Drivers:
- v3d - driver for broadcom V3D V3.x+ hardware
- xen-front - XEN PV display frontend
core:
- handle zpos normalization in the core
- stop looking at legacy pointers in atomic paths
- improved scheduler documentation
- improved aspect ratio validation
- aspect ratio support for 64:27 and 256:135
- drop unused control node code.
i915:
- Icelake (ICL) enabling
- GuC/HuC refactoring
- PSR/PSR2 enabling and fixes
- DPLL management refactoring
- DP MST fixes
- NV12 enabling
- HDCP improvements
- GEM/Execlist/reset improvements
- GVT improvements
- stolen memory first 4k fix
amdgpu:
- Vega 20 support
- VEGAM support (Kabylake-G)
- preOS scanout buffer reservation
- power management gfxoff support for raven
- SR-IOV fixes
- Vega10 power profiles and clock voltage control
- scatter/gather display support on CZ/ST
amdkfd:
- GFX9 dGPU support
- userptr memory mapping
nouveau:
- major refactoring for Volta GV100 support
tda998x:
- HDMI i2c CEC support
etnaviv:
- removed unused logging code
- license text cleanups
- MMU handling improvements
- timeout fence fix for 50 days uptime
tegra:
- IOMMU support in gr2d/gr3d drivers
- zpos support
vc4:
- syncobj support
- CTM, plane alpha and async cursor support
analogix_dp:
- HPD and aux chan fixes
sun4i:
- MIPI DSI support
tilcdc:
- clock divider fixes for OMAP-l138 LCDK board
rcar-du:
- R8A77965 support
- dma-buf fences fixes
- hardware indexed crtc/du group handling
- generic zplane property support
atmel-hclcdc:
- generic zplane property support
mediatek:
- use generic video mode function
exynos:
- S5PV210 FIMD variant support
- IPP v2 framework
- more HW overlays support"
* tag 'drm-next-2018-06-06-1' of git://anongit.freedesktop.org/drm/drm: (1286 commits)
drm/amdgpu: fix 32-bit build warning
drm/exynos: fimc: signedness bug in fimc_setup_clocks()
drm/exynos: scaler: fix static checker warning
drm/amdgpu: Use dev_info() to report amdkfd is not supported for this ASIC
drm/amd/display: Remove use of division operator for long longs
drm/amdgpu: Update GFX info structure to match what vega20 used
drm/amdgpu/pp: remove duplicate assignment
drm/sched: add rcu_barrier after entity fini
drm/amdgpu: move VM BOs on LRU again
drm/amdgpu: consistenly use VM moved flag
drm/amdgpu: kmap PDs/PTs in amdgpu_vm_update_directories
drm/amdgpu: further optimize amdgpu_vm_handle_moved
drm/amdgpu: cleanup amdgpu_vm_validate_pt_bos v2
drm/amdgpu: rework VM state machine lock handling v2
drm/amdgpu: Add runtime VCN PG support
drm/amdgpu: Enable VCN static PG by default on RV
drm/amdgpu: Add VCN static PG support on RV
drm/amdgpu: Enable VCN CG by default on RV
drm/amdgpu: Add static CG control for VCN on RV
drm/exynos: Fix default value for zpos plane property
...
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_tcon.c')
-rw-r--r-- | drivers/gpu/drm/sun4i/sun4i_tcon.c | 86 |
1 files changed, 83 insertions, 3 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index c3d92d537240..08747fc3ee71 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -35,6 +35,7 @@ #include "sun4i_lvds.h" #include "sun4i_rgb.h" #include "sun4i_tcon.h" +#include "sun6i_mipi_dsi.h" #include "sunxi_engine.h" static struct drm_connector *sun4i_tcon_get_connector(const struct drm_encoder *encoder) @@ -169,6 +170,7 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, case DRM_MODE_ENCODER_LVDS: is_lvds = true; /* Fallthrough */ + case DRM_MODE_ENCODER_DSI: case DRM_MODE_ENCODER_NONE: channel = 0; break; @@ -201,7 +203,8 @@ void sun4i_tcon_enable_vblank(struct sun4i_tcon *tcon, bool enable) DRM_DEBUG_DRIVER("%sabling VBLANK interrupt\n", enable ? "En" : "Dis"); mask = SUN4I_TCON_GINT0_VBLANK_ENABLE(0) | - SUN4I_TCON_GINT0_VBLANK_ENABLE(1); + SUN4I_TCON_GINT0_VBLANK_ENABLE(1) | + SUN4I_TCON_GINT0_TCON0_TRI_FINISH_ENABLE; if (enable) val = mask; @@ -273,6 +276,71 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon, SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay)); } +static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon, + struct mipi_dsi_device *device, + const struct drm_display_mode *mode) +{ + u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format); + u8 lanes = device->lanes; + u32 block_space, start_delay; + u32 tcon_div; + + tcon->dclk_min_div = 4; + tcon->dclk_max_div = 127; + + sun4i_tcon0_mode_set_common(tcon, mode); + + regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG, + SUN4I_TCON0_CTL_IF_MASK, + SUN4I_TCON0_CTL_IF_8080); + + regmap_write(tcon->regs, SUN4I_TCON_ECC_FIFO_REG, + SUN4I_TCON_ECC_FIFO_EN); + + regmap_write(tcon->regs, SUN4I_TCON0_CPU_IF_REG, + SUN4I_TCON0_CPU_IF_MODE_DSI | + SUN4I_TCON0_CPU_IF_TRI_FIFO_FLUSH | + SUN4I_TCON0_CPU_IF_TRI_FIFO_EN | + SUN4I_TCON0_CPU_IF_TRI_EN); + + /* + * This looks suspicious, but it works... + * + * The datasheet says that this should be set higher than 20 * + * pixel cycle, but it's not clear what a pixel cycle is. + */ + regmap_read(tcon->regs, SUN4I_TCON0_DCLK_REG, &tcon_div); + tcon_div &= GENMASK(6, 0); + block_space = mode->htotal * bpp / (tcon_div * lanes); + block_space -= mode->hdisplay + 40; + + regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI0_REG, + SUN4I_TCON0_CPU_TRI0_BLOCK_SPACE(block_space) | + SUN4I_TCON0_CPU_TRI0_BLOCK_SIZE(mode->hdisplay)); + + regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI1_REG, + SUN4I_TCON0_CPU_TRI1_BLOCK_NUM(mode->vdisplay)); + + start_delay = (mode->crtc_vtotal - mode->crtc_vdisplay - 10 - 1); + start_delay = start_delay * mode->crtc_htotal * 149; + start_delay = start_delay / (mode->crtc_clock / 1000) / 8; + regmap_write(tcon->regs, SUN4I_TCON0_CPU_TRI2_REG, + SUN4I_TCON0_CPU_TRI2_TRANS_START_SET(10) | + SUN4I_TCON0_CPU_TRI2_START_DELAY(start_delay)); + + /* + * The Allwinner BSP has a comment that the period should be + * the display clock * 15, but uses an hardcoded 3000... + */ + regmap_write(tcon->regs, SUN4I_TCON_SAFE_PERIOD_REG, + SUN4I_TCON_SAFE_PERIOD_NUM(3000) | + SUN4I_TCON_SAFE_PERIOD_MODE(3)); + + /* Enable the output on the pins */ + regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, + 0xe0000000); +} + static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon, const struct drm_encoder *encoder, const struct drm_display_mode *mode) @@ -538,7 +606,17 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon, const struct drm_encoder *encoder, const struct drm_display_mode *mode) { + struct sun6i_dsi *dsi; + switch (encoder->encoder_type) { + case DRM_MODE_ENCODER_DSI: + /* + * This is not really elegant, but it's the "cleaner" + * way I could think of... + */ + dsi = encoder_to_sun6i_dsi(encoder); + sun4i_tcon0_mode_set_cpu(tcon, dsi->device, mode); + break; case DRM_MODE_ENCODER_LVDS: sun4i_tcon0_mode_set_lvds(tcon, encoder, mode); break; @@ -582,7 +660,8 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) regmap_read(tcon->regs, SUN4I_TCON_GINT0_REG, &status); if (!(status & (SUN4I_TCON_GINT0_VBLANK_INT(0) | - SUN4I_TCON_GINT0_VBLANK_INT(1)))) + SUN4I_TCON_GINT0_VBLANK_INT(1) | + SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT))) return IRQ_NONE; drm_crtc_handle_vblank(&scrtc->crtc); @@ -591,7 +670,8 @@ static irqreturn_t sun4i_tcon_handler(int irq, void *private) /* Acknowledge the interrupt */ regmap_update_bits(tcon->regs, SUN4I_TCON_GINT0_REG, SUN4I_TCON_GINT0_VBLANK_INT(0) | - SUN4I_TCON_GINT0_VBLANK_INT(1), + SUN4I_TCON_GINT0_VBLANK_INT(1) | + SUN4I_TCON_GINT0_TCON0_TRI_FINISH_INT, 0); if (engine->ops->vblank_quirk) |