Merge tag 'drm-next-2019-07-16' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie: "The biggest thing in this is the AMD Navi GPU support, this again contains a bunch of header files that are large. These are the new AMD RX5700 GPUs that just recently became available. New drivers: - ST-Ericsson MCDE driver - Ingenic JZ47xx SoC UAPI change: - HDR source metadata property Core: - HDR inforframes and EDID parsing - drm hdmi infoframe unpacking - remove prime sg_table caching into dma-buf - New gem vram helpers to reduce driver code - Lots of drmP.h removal - reservation fencing fix - documentation updates - drm_fb_helper_connector removed - mode name command handler rewrite fbcon: - Remove the fbcon notifiers ttm: - forward progress fixes dma-buf: - make mmap call optional - debugfs refcount fixes - dma-fence free with pending signals fix - each dma-buf gets an inode Panels: - Lots of additional panel bindings amdgpu: - initial navi10 support - avoid hw reset - HDR metadata support - new thermal sensors for vega asics - RAS fixes - use HMM rather than MMU notifier - xgmi topology via kfd - SR-IOV fixes - driver reload fixes - DC use a core bpc attribute - Aux fixes for DC - Bandwidth calc updates for DC - Clock handling refactor - kfd VEGAM support vmwgfx: - Coherent memory support changes i915: - HDR Support - HDMI i2c link - Icelake multi-segmented gamma support - GuC firmware update - Mule Creek Canyon PCH support for EHL - EHL platform updtes - move i915.alpha_support to i915.force_probe - runtime PM refactoring - VBT parsing refactoring - DSI fixes - struct mutex dependency reduction - GEM code reorg mali-dp: - Komeda driver features msm: - dsi vs EPROBE_DEFER fixes - msm8998 snapdragon 835 support - a540 gpu support - mdp5 and dpu interconnect support exynos: - drmP.h removal tegra: - misc fixes tda998x: - audio support improvements - pixel repeated mode support - quantisation range handling corrections - HDMI vendor info fix armada: - interlace support fix - overlay/video plane register handling refactor - add gamma support rockchip: - RX3328 support panfrost: - expose perf counters via hidden ioctls vkms: - enumerate CRC sources list ast: - rework BO handling mgag200: - rework BO handling dw-hdmi: - suspend/resume support rcar-du: - R8A774A1 Soc Support - LVDS dual-link mode support - Additional formats - Misc fixes omapdrm: - DSI command mode display support stm - fb modifier support - runtime PM support sun4i: - use vmap ops vc4: - binner bo binding rework v3d: - compute shader support - resync/sync fixes - job management refactoring lima: - NULL pointer in irq handler fix - scheduler default timeout virtio: - fence seqno support - trace events bochs: - misc fixes tc458767: - IRQ/HDP handling sii902x: - HDMI audio support atmel-hlcdc: - misc fixes meson: - zpos support" * tag 'drm-next-2019-07-16' of git://anongit.freedesktop.org/drm/drm: (1815 commits) Revert "Merge branch 'vmwgfx-next' of git://people.freedesktop.org/~thomash/linux into drm-next" Revert "mm: adjust apply_to_pfn_range interface for dropped token." mm: adjust apply_to_pfn_range interface for dropped token. drm/amdgpu/navi10: add uclk activity sensor drm/amdgpu: properly guard the generic discovery code drm/amdgpu: add missing documentation on new module parameters drm/amdgpu: don't invalidate caches in RELEASE_MEM, only do the writeback drm/amd/display: avoid 64-bit division drm/amdgpu/psp11: simplify the ucode register logic drm/amdgpu: properly guard DC support in navi code drm/amd/powerplay: vega20: fix uninitialized variable use drm/amd/display: dcn20: include linux/delay.h amdgpu: make pmu support optional drm/amd/powerplay: Zero initialize current_rpm in vega20_get_fan_speed_percent drm/amd/powerplay: Zero initialize freq in smu_v11_0_get_current_clk_freq drm/amd/powerplay: Use memset to initialize metrics structs drm/amdgpu/mes10.1: Fix header guard drm/amd/powerplay: add temperature sensor support for navi10 drm/amdgpu: fix scheduler timeout calc drm/amdgpu: Prepare for hmm_range_register API change (v2) ...
This commit is contained in:
@@ -45,19 +45,28 @@ config DRM_I915
|
||||
config DRM_I915_ALPHA_SUPPORT
|
||||
bool "Enable alpha quality support for new Intel hardware by default"
|
||||
depends on DRM_I915
|
||||
default n
|
||||
help
|
||||
Choose this option if you have new Intel hardware and want to enable
|
||||
the alpha quality i915 driver support for the hardware in this kernel
|
||||
version. You can also enable the support at runtime using the module
|
||||
parameter i915.alpha_support=1; this option changes the default for
|
||||
that module parameter.
|
||||
This option is deprecated. Use DRM_I915_FORCE_PROBE option instead.
|
||||
|
||||
It is recommended to upgrade to a kernel version with proper support
|
||||
as soon as it is available. Generally fixes for platforms with alpha
|
||||
support are not backported to older kernels.
|
||||
config DRM_I915_FORCE_PROBE
|
||||
string "Force probe driver for selected new Intel hardware"
|
||||
depends on DRM_I915
|
||||
default "*" if DRM_I915_ALPHA_SUPPORT
|
||||
help
|
||||
This is the default value for the i915.force_probe module
|
||||
parameter. Using the module parameter overrides this option.
|
||||
|
||||
If in doubt, say "N".
|
||||
Force probe the driver for new Intel graphics devices that are
|
||||
recognized but not properly supported by this kernel version. It is
|
||||
recommended to upgrade to a kernel version with proper support as soon
|
||||
as it is available.
|
||||
|
||||
Use "" to disable force probe. If in doubt, use this.
|
||||
|
||||
Use "<pci-id>[,<pci-id>,...]" to force probe the driver for listed
|
||||
devices. For example, "4500" or "4500,4571".
|
||||
|
||||
Use "*" to force probe the driver for all known devices.
|
||||
|
||||
config DRM_I915_CAPTURE_ERROR
|
||||
bool "Enable capturing GPU state following a hang"
|
||||
@@ -133,3 +142,9 @@ depends on DRM_I915
|
||||
depends on EXPERT
|
||||
source "drivers/gpu/drm/i915/Kconfig.debug"
|
||||
endmenu
|
||||
|
||||
menu "drm/i915 Profile Guided Optimisation"
|
||||
visible if EXPERT
|
||||
depends on DRM_I915
|
||||
source "drivers/gpu/drm/i915/Kconfig.profile"
|
||||
endmenu
|
||||
|
@@ -21,6 +21,7 @@ config DRM_I915_DEBUG
|
||||
depends on DRM_I915
|
||||
select DEBUG_FS
|
||||
select PREEMPT_COUNT
|
||||
select REFCOUNT_FULL
|
||||
select I2C_CHARDEV
|
||||
select STACKDEPOT
|
||||
select DRM_DP_AUX_CHARDEV
|
||||
@@ -32,6 +33,7 @@ config DRM_I915_DEBUG
|
||||
select DRM_I915_SW_FENCE_DEBUG_OBJECTS
|
||||
select DRM_I915_SELFTEST
|
||||
select DRM_I915_DEBUG_RUNTIME_PM
|
||||
select DRM_I915_DEBUG_MMIO
|
||||
default n
|
||||
help
|
||||
Choose this option to turn on extra driver debugging that may affect
|
||||
@@ -41,6 +43,19 @@ config DRM_I915_DEBUG
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_I915_DEBUG_MMIO
|
||||
bool "Always insert extra checks around mmio access by default"
|
||||
default n
|
||||
help
|
||||
By default, always enables the extra sanity checks (extra register
|
||||
reads) around every mmio (register) access that will slow the system
|
||||
down. This sets the default value of i915.mmio_debug to -1 and can
|
||||
be overridden at module load.
|
||||
|
||||
Recommended for driver developers only.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_I915_DEBUG_GEM
|
||||
bool "Insert extra checks into the GEM internals"
|
||||
default n
|
||||
|
27
drivers/gpu/drm/i915/Kconfig.profile
Normal file
27
drivers/gpu/drm/i915/Kconfig.profile
Normal file
@@ -0,0 +1,27 @@
|
||||
config DRM_I915_USERFAULT_AUTOSUSPEND
|
||||
int "Runtime autosuspend delay for userspace GGTT mmaps (ms)"
|
||||
default 250 # milliseconds
|
||||
help
|
||||
On runtime suspend, as we suspend the device, we have to revoke
|
||||
userspace GGTT mmaps and force userspace to take a pagefault on
|
||||
their next access. The revocation and subsequent recreation of
|
||||
the GGTT mmap can be very slow and so we impose a small hysteris
|
||||
that complements the runtime-pm autosuspend and provides a lower
|
||||
floor on the autosuspend delay.
|
||||
|
||||
May be 0 to disable the extra delay and solely use the device level
|
||||
runtime pm autosuspend delay tunable.
|
||||
|
||||
config DRM_I915_SPIN_REQUEST
|
||||
int "Busywait for request completion (us)"
|
||||
default 5 # microseconds
|
||||
help
|
||||
Before sleeping waiting for a request (GPU operation) to complete,
|
||||
we may spend some time polling for its completion. As the IRQ may
|
||||
take a non-negligible time to setup, we do a short spin first to
|
||||
check if the request will complete in the time it would have taken
|
||||
us to enable the interrupt.
|
||||
|
||||
May be 0 to disable the initial spin. In practice, we estimate
|
||||
the cost of enabling the interrupt (if currently disabled) to be
|
||||
a few microseconds.
|
@@ -35,52 +35,93 @@ subdir-ccflags-y += \
|
||||
# Extra header tests
|
||||
include $(src)/Makefile.header-test
|
||||
|
||||
subdir-ccflags-y += -I$(src)
|
||||
|
||||
# Please keep these build lists sorted!
|
||||
|
||||
# core driver code
|
||||
i915-y += i915_drv.o \
|
||||
i915_irq.o \
|
||||
i915_memcpy.o \
|
||||
i915_mm.o \
|
||||
i915_params.o \
|
||||
i915_pci.o \
|
||||
i915_reset.o \
|
||||
i915_scatterlist.o \
|
||||
i915_suspend.o \
|
||||
i915_sw_fence.o \
|
||||
i915_syncmap.o \
|
||||
i915_sysfs.o \
|
||||
i915_user_extensions.o \
|
||||
intel_csr.o \
|
||||
intel_device_info.o \
|
||||
intel_pm.o \
|
||||
intel_runtime_pm.o \
|
||||
intel_workarounds.o
|
||||
intel_sideband.o \
|
||||
intel_uncore.o \
|
||||
intel_wakeref.o
|
||||
|
||||
# core library code
|
||||
i915-y += \
|
||||
i915_memcpy.o \
|
||||
i915_mm.o \
|
||||
i915_sw_fence.o \
|
||||
i915_syncmap.o \
|
||||
i915_user_extensions.o
|
||||
|
||||
i915-$(CONFIG_COMPAT) += i915_ioc32.o
|
||||
i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o intel_pipe_crc.o
|
||||
i915-$(CONFIG_DEBUG_FS) += i915_debugfs.o display/intel_pipe_crc.o
|
||||
i915-$(CONFIG_PERF_EVENTS) += i915_pmu.o
|
||||
|
||||
# GEM code
|
||||
# "Graphics Technology" (aka we talk to the gpu)
|
||||
obj-y += gt/
|
||||
gt-y += \
|
||||
gt/intel_breadcrumbs.o \
|
||||
gt/intel_context.o \
|
||||
gt/intel_engine_cs.o \
|
||||
gt/intel_engine_pm.o \
|
||||
gt/intel_gt_pm.o \
|
||||
gt/intel_hangcheck.o \
|
||||
gt/intel_lrc.o \
|
||||
gt/intel_reset.o \
|
||||
gt/intel_ringbuffer.o \
|
||||
gt/intel_mocs.o \
|
||||
gt/intel_sseu.o \
|
||||
gt/intel_workarounds.o
|
||||
gt-$(CONFIG_DRM_I915_SELFTEST) += \
|
||||
gt/mock_engine.o
|
||||
i915-y += $(gt-y)
|
||||
|
||||
# GEM (Graphics Execution Management) code
|
||||
obj-y += gem/
|
||||
gem-y += \
|
||||
gem/i915_gem_busy.o \
|
||||
gem/i915_gem_clflush.o \
|
||||
gem/i915_gem_client_blt.o \
|
||||
gem/i915_gem_context.o \
|
||||
gem/i915_gem_dmabuf.o \
|
||||
gem/i915_gem_domain.o \
|
||||
gem/i915_gem_execbuffer.o \
|
||||
gem/i915_gem_fence.o \
|
||||
gem/i915_gem_internal.o \
|
||||
gem/i915_gem_object.o \
|
||||
gem/i915_gem_object_blt.o \
|
||||
gem/i915_gem_mman.o \
|
||||
gem/i915_gem_pages.o \
|
||||
gem/i915_gem_phys.o \
|
||||
gem/i915_gem_pm.o \
|
||||
gem/i915_gem_shmem.o \
|
||||
gem/i915_gem_shrinker.o \
|
||||
gem/i915_gem_stolen.o \
|
||||
gem/i915_gem_throttle.o \
|
||||
gem/i915_gem_tiling.o \
|
||||
gem/i915_gem_userptr.o \
|
||||
gem/i915_gem_wait.o \
|
||||
gem/i915_gemfs.o
|
||||
i915-y += \
|
||||
$(gem-y) \
|
||||
i915_active.o \
|
||||
i915_cmd_parser.o \
|
||||
i915_gem_batch_pool.o \
|
||||
i915_gem_clflush.o \
|
||||
i915_gem_context.o \
|
||||
i915_gem_dmabuf.o \
|
||||
i915_gem_evict.o \
|
||||
i915_gem_execbuffer.o \
|
||||
i915_gem_fence_reg.o \
|
||||
i915_gem_gtt.o \
|
||||
i915_gem_internal.o \
|
||||
i915_gem.o \
|
||||
i915_gem_object.o \
|
||||
i915_gem_render_state.o \
|
||||
i915_gem_shrinker.o \
|
||||
i915_gem_stolen.o \
|
||||
i915_gem_tiling.o \
|
||||
i915_gem_userptr.o \
|
||||
i915_gemfs.o \
|
||||
i915_globals.o \
|
||||
i915_query.o \
|
||||
i915_request.o \
|
||||
@@ -88,14 +129,6 @@ i915-y += \
|
||||
i915_timeline.o \
|
||||
i915_trace_points.o \
|
||||
i915_vma.o \
|
||||
intel_breadcrumbs.o \
|
||||
intel_context.o \
|
||||
intel_engine_cs.o \
|
||||
intel_hangcheck.o \
|
||||
intel_lrc.o \
|
||||
intel_mocs.o \
|
||||
intel_ringbuffer.o \
|
||||
intel_uncore.o \
|
||||
intel_wopcm.o
|
||||
|
||||
# general-purpose microcontroller (GuC) support
|
||||
@@ -117,62 +150,71 @@ i915-y += intel_renderstate_gen6.o \
|
||||
intel_renderstate_gen9.o
|
||||
|
||||
# modesetting core code
|
||||
i915-y += intel_audio.o \
|
||||
intel_atomic.o \
|
||||
intel_atomic_plane.o \
|
||||
intel_bios.o \
|
||||
intel_cdclk.o \
|
||||
intel_color.o \
|
||||
intel_combo_phy.o \
|
||||
intel_connector.o \
|
||||
intel_display.o \
|
||||
intel_dpio_phy.o \
|
||||
intel_dpll_mgr.o \
|
||||
intel_fbc.o \
|
||||
intel_fifo_underrun.o \
|
||||
intel_frontbuffer.o \
|
||||
intel_hdcp.o \
|
||||
intel_hotplug.o \
|
||||
intel_overlay.o \
|
||||
intel_psr.o \
|
||||
intel_quirks.o \
|
||||
intel_sideband.o \
|
||||
intel_sprite.o
|
||||
i915-$(CONFIG_ACPI) += intel_acpi.o intel_opregion.o
|
||||
i915-$(CONFIG_DRM_FBDEV_EMULATION) += intel_fbdev.o
|
||||
obj-y += display/
|
||||
i915-y += \
|
||||
display/intel_atomic.o \
|
||||
display/intel_atomic_plane.o \
|
||||
display/intel_audio.o \
|
||||
display/intel_bios.o \
|
||||
display/intel_bw.o \
|
||||
display/intel_cdclk.o \
|
||||
display/intel_color.o \
|
||||
display/intel_combo_phy.o \
|
||||
display/intel_connector.o \
|
||||
display/intel_display.o \
|
||||
display/intel_display_power.o \
|
||||
display/intel_dpio_phy.o \
|
||||
display/intel_dpll_mgr.o \
|
||||
display/intel_fbc.o \
|
||||
display/intel_fifo_underrun.o \
|
||||
display/intel_frontbuffer.o \
|
||||
display/intel_hdcp.o \
|
||||
display/intel_hotplug.o \
|
||||
display/intel_lpe_audio.o \
|
||||
display/intel_overlay.o \
|
||||
display/intel_psr.o \
|
||||
display/intel_quirks.o \
|
||||
display/intel_sprite.o
|
||||
i915-$(CONFIG_ACPI) += \
|
||||
display/intel_acpi.o \
|
||||
display/intel_opregion.o
|
||||
i915-$(CONFIG_DRM_FBDEV_EMULATION) += \
|
||||
display/intel_fbdev.o
|
||||
|
||||
# modesetting output/encoder code
|
||||
i915-y += dvo_ch7017.o \
|
||||
dvo_ch7xxx.o \
|
||||
dvo_ivch.o \
|
||||
dvo_ns2501.o \
|
||||
dvo_sil164.o \
|
||||
dvo_tfp410.o \
|
||||
icl_dsi.o \
|
||||
intel_crt.o \
|
||||
intel_ddi.o \
|
||||
intel_dp_aux_backlight.o \
|
||||
intel_dp_link_training.o \
|
||||
intel_dp_mst.o \
|
||||
intel_dp.o \
|
||||
intel_dsi.o \
|
||||
intel_dsi_dcs_backlight.o \
|
||||
intel_dsi_vbt.o \
|
||||
intel_dvo.o \
|
||||
intel_hdmi.o \
|
||||
intel_i2c.o \
|
||||
intel_lspcon.o \
|
||||
intel_lvds.o \
|
||||
intel_panel.o \
|
||||
intel_sdvo.o \
|
||||
intel_tv.o \
|
||||
vlv_dsi.o \
|
||||
vlv_dsi_pll.o \
|
||||
intel_vdsc.o
|
||||
i915-y += \
|
||||
display/dvo_ch7017.o \
|
||||
display/dvo_ch7xxx.o \
|
||||
display/dvo_ivch.o \
|
||||
display/dvo_ns2501.o \
|
||||
display/dvo_sil164.o \
|
||||
display/dvo_tfp410.o \
|
||||
display/icl_dsi.o \
|
||||
display/intel_crt.o \
|
||||
display/intel_ddi.o \
|
||||
display/intel_dp.o \
|
||||
display/intel_dp_aux_backlight.o \
|
||||
display/intel_dp_link_training.o \
|
||||
display/intel_dp_mst.o \
|
||||
display/intel_dsi.o \
|
||||
display/intel_dsi_dcs_backlight.o \
|
||||
display/intel_dsi_vbt.o \
|
||||
display/intel_dvo.o \
|
||||
display/intel_gmbus.o \
|
||||
display/intel_hdmi.o \
|
||||
display/intel_lspcon.o \
|
||||
display/intel_lvds.o \
|
||||
display/intel_panel.o \
|
||||
display/intel_sdvo.o \
|
||||
display/intel_tv.o \
|
||||
display/intel_vdsc.o \
|
||||
display/vlv_dsi.o \
|
||||
display/vlv_dsi_pll.o
|
||||
|
||||
# Post-mortem debug and GPU hang state capture
|
||||
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
|
||||
i915-$(CONFIG_DRM_I915_SELFTEST) += \
|
||||
gem/selftests/igt_gem_utils.o \
|
||||
selftests/i915_random.o \
|
||||
selftests/i915_selftest.o \
|
||||
selftests/igt_flush_test.o \
|
||||
@@ -205,8 +247,5 @@ i915-y += intel_gvt.o
|
||||
include $(src)/gvt/Makefile
|
||||
endif
|
||||
|
||||
# LPE Audio for VLV and CHT
|
||||
i915-y += intel_lpe_audio.o
|
||||
|
||||
obj-$(CONFIG_DRM_I915) += i915.o
|
||||
obj-$(CONFIG_DRM_I915_GVT_KVMGT) += gvt/kvmgt.o
|
||||
|
@@ -4,34 +4,19 @@
|
||||
# Test the headers are compilable as standalone units
|
||||
header-test-$(CONFIG_DRM_I915_WERROR) := \
|
||||
i915_active_types.h \
|
||||
i915_gem_context_types.h \
|
||||
i915_debugfs.h \
|
||||
i915_drv.h \
|
||||
i915_irq.h \
|
||||
i915_params.h \
|
||||
i915_priolist_types.h \
|
||||
i915_reg.h \
|
||||
i915_scheduler_types.h \
|
||||
i915_timeline_types.h \
|
||||
intel_atomic_plane.h \
|
||||
intel_audio.h \
|
||||
intel_cdclk.h \
|
||||
intel_color.h \
|
||||
intel_connector.h \
|
||||
intel_context_types.h \
|
||||
intel_crt.h \
|
||||
i915_utils.h \
|
||||
intel_csr.h \
|
||||
intel_ddi.h \
|
||||
intel_dp.h \
|
||||
intel_dvo.h \
|
||||
intel_engine_types.h \
|
||||
intel_fbc.h \
|
||||
intel_fbdev.h \
|
||||
intel_frontbuffer.h \
|
||||
intel_hdcp.h \
|
||||
intel_hdmi.h \
|
||||
intel_lspcon.h \
|
||||
intel_lvds.h \
|
||||
intel_panel.h \
|
||||
intel_pipe_crc.h \
|
||||
intel_drv.h \
|
||||
intel_pm.h \
|
||||
intel_psr.h \
|
||||
intel_sdvo.h \
|
||||
intel_sprite.h \
|
||||
intel_tv.h \
|
||||
intel_workarounds_types.h
|
||||
intel_runtime_pm.h \
|
||||
intel_sideband.h \
|
||||
intel_uncore.h \
|
||||
intel_wakeref.h
|
||||
|
2
drivers/gpu/drm/i915/display/Makefile
Normal file
2
drivers/gpu/drm/i915/display/Makefile
Normal file
@@ -0,0 +1,2 @@
|
||||
# Extra header tests
|
||||
include $(src)/Makefile.header-test
|
16
drivers/gpu/drm/i915/display/Makefile.header-test
Normal file
16
drivers/gpu/drm/i915/display/Makefile.header-test
Normal file
@@ -0,0 +1,16 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright © 2019 Intel Corporation
|
||||
|
||||
# Test the headers are compilable as standalone units
|
||||
header_test := $(notdir $(filter-out %/intel_vbt_defs.h,$(wildcard $(src)/*.h)))
|
||||
|
||||
quiet_cmd_header_test = HDRTEST $@
|
||||
cmd_header_test = echo "\#include \"$(<F)\"" > $@
|
||||
|
||||
header_test_%.c: %.h
|
||||
$(call cmd,header_test)
|
||||
|
||||
extra-$(CONFIG_DRM_I915_WERROR) += \
|
||||
$(foreach h,$(header_test),$(patsubst %.h,header_test_%.o,$(h)))
|
||||
|
||||
clean-files += $(foreach h,$(header_test),$(patsubst %.h,header_test_%.c,$(h)))
|
@@ -25,7 +25,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
#define CH7017_TV_DISPLAY_MODE 0x00
|
||||
#define CH7017_FLICKER_FILTER 0x01
|
@@ -26,7 +26,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
#define CH7xxx_REG_VID 0x4a
|
||||
#define CH7xxx_REG_DID 0x4b
|
@@ -29,7 +29,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
/*
|
||||
* register definitions for the i82807aa.
|
@@ -26,9 +26,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "i915_reg.h"
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
#define NS2501_VID 0x1305
|
||||
#define NS2501_DID 0x6726
|
@@ -26,7 +26,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
#define SIL164_VID 0x0001
|
||||
#define SIL164_DID 0x0006
|
@@ -25,7 +25,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dvo.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
|
||||
/* register definitions according to the TFP410 data sheet */
|
||||
#define TFP410_VID 0x014C
|
@@ -28,6 +28,8 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_combo_phy.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_dsi.h"
|
||||
@@ -363,30 +365,10 @@ static void gen11_dsi_power_up_lanes(struct intel_encoder *encoder)
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
enum port port;
|
||||
u32 tmp;
|
||||
u32 lane_mask;
|
||||
|
||||
switch (intel_dsi->lane_count) {
|
||||
case 1:
|
||||
lane_mask = PWR_DOWN_LN_3_1_0;
|
||||
break;
|
||||
case 2:
|
||||
lane_mask = PWR_DOWN_LN_3_1;
|
||||
break;
|
||||
case 3:
|
||||
lane_mask = PWR_DOWN_LN_3;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
lane_mask = PWR_UP_ALL_LANES;
|
||||
break;
|
||||
}
|
||||
|
||||
for_each_dsi_port(port, intel_dsi->ports) {
|
||||
tmp = I915_READ(ICL_PORT_CL_DW10(port));
|
||||
tmp &= ~PWR_DOWN_LN_MASK;
|
||||
I915_WRITE(ICL_PORT_CL_DW10(port), tmp | lane_mask);
|
||||
}
|
||||
for_each_dsi_port(port, intel_dsi->ports)
|
||||
intel_combo_phy_power_up_lanes(dev_priv, port, true,
|
||||
intel_dsi->lane_count, false);
|
||||
}
|
||||
|
||||
static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
|
||||
@@ -1193,17 +1175,51 @@ static void gen11_dsi_disable(struct intel_encoder *encoder,
|
||||
gen11_dsi_disable_io_power(encoder);
|
||||
}
|
||||
|
||||
static void gen11_dsi_get_timings(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
struct drm_display_mode *adjusted_mode =
|
||||
&pipe_config->base.adjusted_mode;
|
||||
|
||||
if (intel_dsi->dual_link) {
|
||||
adjusted_mode->crtc_hdisplay *= 2;
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
|
||||
adjusted_mode->crtc_hdisplay -=
|
||||
intel_dsi->pixel_overlap;
|
||||
adjusted_mode->crtc_htotal *= 2;
|
||||
}
|
||||
adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay;
|
||||
adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_htotal;
|
||||
|
||||
if (intel_dsi->operation_mode == INTEL_DSI_VIDEO_MODE) {
|
||||
if (intel_dsi->dual_link) {
|
||||
adjusted_mode->crtc_hsync_start *= 2;
|
||||
adjusted_mode->crtc_hsync_end *= 2;
|
||||
}
|
||||
}
|
||||
adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay;
|
||||
adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal;
|
||||
}
|
||||
|
||||
static void gen11_dsi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
|
||||
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
|
||||
|
||||
/* FIXME: adapt icl_ddi_clock_get() for DSI and use that? */
|
||||
pipe_config->port_clock =
|
||||
cnl_calc_wrpll_link(dev_priv, &pipe_config->dpll_hw_state);
|
||||
|
||||
pipe_config->base.adjusted_mode.crtc_clock = intel_dsi->pclk;
|
||||
if (intel_dsi->dual_link)
|
||||
pipe_config->base.adjusted_mode.crtc_clock *= 2;
|
||||
|
||||
gen11_dsi_get_timings(encoder, pipe_config);
|
||||
pipe_config->output_types |= BIT(INTEL_OUTPUT_DSI);
|
||||
pipe_config->pipe_bpp = bdw_get_pipemisc_bpp(crtc);
|
||||
}
|
||||
|
||||
static int gen11_dsi_compute_config(struct intel_encoder *encoder,
|
||||
@@ -1219,6 +1235,7 @@ static int gen11_dsi_compute_config(struct intel_encoder *encoder,
|
||||
struct drm_display_mode *adjusted_mode =
|
||||
&pipe_config->base.adjusted_mode;
|
||||
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
intel_fixed_panel_mode(fixed_mode, adjusted_mode);
|
||||
intel_pch_panel_fitting(crtc, pipe_config, conn_state->scaling_mode);
|
||||
|
||||
@@ -1363,6 +1380,113 @@ static const struct mipi_dsi_host_ops gen11_dsi_host_ops = {
|
||||
.transfer = gen11_dsi_host_transfer,
|
||||
};
|
||||
|
||||
#define ICL_PREPARE_CNT_MAX 0x7
|
||||
#define ICL_CLK_ZERO_CNT_MAX 0xf
|
||||
#define ICL_TRAIL_CNT_MAX 0x7
|
||||
#define ICL_TCLK_PRE_CNT_MAX 0x3
|
||||
#define ICL_TCLK_POST_CNT_MAX 0x7
|
||||
#define ICL_HS_ZERO_CNT_MAX 0xf
|
||||
#define ICL_EXIT_ZERO_CNT_MAX 0x7
|
||||
|
||||
static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
u32 tlpx_ns;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 hs_zero_cnt;
|
||||
u32 tclk_pre_cnt, tclk_post_cnt;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare,
|
||||
mipi_config->tclk_prepare);
|
||||
|
||||
/*
|
||||
* prepare cnt in escape clocks
|
||||
* this field represents a hexadecimal value with a precision
|
||||
* of 1.2 – i.e. the most significant bit is the integer
|
||||
* and the least significant 2 bits are fraction bits.
|
||||
* so, the field can represent a range of 0.25 to 1.75
|
||||
*/
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
|
||||
if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("prepare_cnt out of range (%d)\n", prepare_cnt);
|
||||
prepare_cnt = ICL_PREPARE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clk zero count in escape clocks */
|
||||
clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
|
||||
clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* trail cnt in escape clocks*/
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
|
||||
if (trail_cnt > ICL_TRAIL_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("trail_cnt out of range (%d)\n", trail_cnt);
|
||||
trail_cnt = ICL_TRAIL_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk pre count in escape clocks */
|
||||
tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
|
||||
if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
|
||||
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk post count in escape clocks */
|
||||
tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
|
||||
if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_post_cnt out of range (%d)\n", tclk_post_cnt);
|
||||
tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs zero cnt in escape clocks */
|
||||
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("hs_zero_cnt out of range (%d)\n", hs_zero_cnt);
|
||||
hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs exit zero cnt in escape clocks */
|
||||
exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
|
||||
if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("exit_zero_cnt out of range (%d)\n", exit_zero_cnt);
|
||||
exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clock lane dphy timings */
|
||||
intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE |
|
||||
CLK_PREPARE(prepare_cnt) |
|
||||
CLK_ZERO_OVERRIDE |
|
||||
CLK_ZERO(clk_zero_cnt) |
|
||||
CLK_PRE_OVERRIDE |
|
||||
CLK_PRE(tclk_pre_cnt) |
|
||||
CLK_POST_OVERRIDE |
|
||||
CLK_POST(tclk_post_cnt) |
|
||||
CLK_TRAIL_OVERRIDE |
|
||||
CLK_TRAIL(trail_cnt));
|
||||
|
||||
/* data lanes dphy timings */
|
||||
intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE |
|
||||
HS_PREPARE(prepare_cnt) |
|
||||
HS_ZERO_OVERRIDE |
|
||||
HS_ZERO(hs_zero_cnt) |
|
||||
HS_TRAIL_OVERRIDE |
|
||||
HS_TRAIL(trail_cnt) |
|
||||
HS_EXIT_OVERRIDE |
|
||||
HS_EXIT(exit_zero_cnt));
|
||||
|
||||
intel_dsi_log_params(intel_dsi);
|
||||
}
|
||||
|
||||
void icl_dsi_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
@@ -1455,6 +1579,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
|
||||
goto err;
|
||||
}
|
||||
|
||||
icl_dphy_param_init(intel_dsi);
|
||||
return;
|
||||
|
||||
err:
|
@@ -4,9 +4,12 @@
|
||||
*
|
||||
* _DSM related code stolen from nouveau_acpi.c.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_acpi.h"
|
||||
|
||||
#define INTEL_DSM_REVISION_ID 1 /* For Calpella anyway... */
|
||||
#define INTEL_DSM_FN_PLATFORM_MUX_INFO 1 /* No args */
|
17
drivers/gpu/drm/i915/display/intel_acpi.h
Normal file
17
drivers/gpu/drm/i915/display/intel_acpi.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_ACPI_H__
|
||||
#define __INTEL_ACPI_H__
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
void intel_register_dsm_handler(void);
|
||||
void intel_unregister_dsm_handler(void);
|
||||
#else
|
||||
static inline void intel_register_dsm_handler(void) { return; }
|
||||
static inline void intel_unregister_dsm_handler(void) { return; }
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#endif /* __INTEL_ACPI_H__ */
|
@@ -34,6 +34,7 @@
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_sprite.h"
|
||||
@@ -104,13 +105,25 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int intel_digital_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_connector_state *new_state)
|
||||
static bool blob_equal(const struct drm_property_blob *a,
|
||||
const struct drm_property_blob *b)
|
||||
{
|
||||
if (a && b)
|
||||
return a->length == b->length &&
|
||||
!memcmp(a->data, b->data, a->length);
|
||||
|
||||
return !a == !b;
|
||||
}
|
||||
|
||||
int intel_digital_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *new_state =
|
||||
drm_atomic_get_new_connector_state(state, conn);
|
||||
struct intel_digital_connector_state *new_conn_state =
|
||||
to_intel_digital_connector_state(new_state);
|
||||
struct drm_connector_state *old_state =
|
||||
drm_atomic_get_old_connector_state(new_state->state, conn);
|
||||
drm_atomic_get_old_connector_state(state, conn);
|
||||
struct intel_digital_connector_state *old_conn_state =
|
||||
to_intel_digital_connector_state(old_state);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@@ -120,7 +133,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
|
||||
if (!new_state->crtc)
|
||||
return 0;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(new_state->state, new_state->crtc);
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, new_state->crtc);
|
||||
|
||||
/*
|
||||
* These properties are handled by fastset, and might not end
|
||||
@@ -131,7 +144,9 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn,
|
||||
new_conn_state->base.colorspace != old_conn_state->base.colorspace ||
|
||||
new_conn_state->base.picture_aspect_ratio != old_conn_state->base.picture_aspect_ratio ||
|
||||
new_conn_state->base.content_type != old_conn_state->base.content_type ||
|
||||
new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode)
|
||||
new_conn_state->base.scaling_mode != old_conn_state->base.scaling_mode ||
|
||||
!blob_equal(new_conn_state->base.hdr_output_metadata,
|
||||
old_conn_state->base.hdr_output_metadata))
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
return 0;
|
||||
@@ -411,3 +426,15 @@ void intel_atomic_state_clear(struct drm_atomic_state *s)
|
||||
drm_atomic_state_default_clear(&state->base);
|
||||
state->dpll_set = state->modeset = false;
|
||||
}
|
||||
|
||||
struct intel_crtc_state *
|
||||
intel_atomic_get_crtc_state(struct drm_atomic_state *state,
|
||||
struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
crtc_state = drm_atomic_get_crtc_state(state, &crtc->base);
|
||||
if (IS_ERR(crtc_state))
|
||||
return ERR_CAST(crtc_state);
|
||||
|
||||
return to_intel_crtc_state(crtc_state);
|
||||
}
|
49
drivers/gpu/drm/i915/display/intel_atomic.h
Normal file
49
drivers/gpu/drm/i915/display/intel_atomic.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_ATOMIC_H__
|
||||
#define __INTEL_ATOMIC_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_atomic_state;
|
||||
struct drm_connector;
|
||||
struct drm_connector_state;
|
||||
struct drm_crtc;
|
||||
struct drm_crtc_state;
|
||||
struct drm_device;
|
||||
struct drm_i915_private;
|
||||
struct drm_property;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
|
||||
int intel_digital_connector_atomic_get_property(struct drm_connector *connector,
|
||||
const struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
u64 *val);
|
||||
int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
u64 val);
|
||||
int intel_digital_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_atomic_state *state);
|
||||
struct drm_connector_state *
|
||||
intel_digital_connector_duplicate_state(struct drm_connector *connector);
|
||||
|
||||
struct drm_crtc_state *intel_crtc_duplicate_state(struct drm_crtc *crtc);
|
||||
void intel_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state);
|
||||
struct drm_atomic_state *intel_atomic_state_alloc(struct drm_device *dev);
|
||||
void intel_atomic_state_clear(struct drm_atomic_state *state);
|
||||
|
||||
struct intel_crtc_state *
|
||||
intel_atomic_get_crtc_state(struct drm_atomic_state *state,
|
||||
struct intel_crtc *crtc);
|
||||
|
||||
int intel_atomic_setup_scalers(struct drm_i915_private *dev_priv,
|
||||
struct intel_crtc *intel_crtc,
|
||||
struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_ATOMIC_H__ */
|
@@ -114,6 +114,29 @@ intel_plane_destroy_state(struct drm_plane *plane,
|
||||
drm_atomic_helper_plane_destroy_state(plane, state);
|
||||
}
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state)
|
||||
{
|
||||
const struct drm_framebuffer *fb = plane_state->base.fb;
|
||||
unsigned int cpp;
|
||||
|
||||
if (!plane_state->base.visible)
|
||||
return 0;
|
||||
|
||||
cpp = fb->format->cpp[0];
|
||||
|
||||
/*
|
||||
* Based on HSD#:1408715493
|
||||
* NV12 cpp == 4, P010 cpp == 8
|
||||
*
|
||||
* FIXME what is the logic behind this?
|
||||
*/
|
||||
if (fb->format->is_yuv && fb->format->num_planes > 1)
|
||||
cpp *= 4;
|
||||
|
||||
return cpp * crtc_state->pixel_rate;
|
||||
}
|
||||
|
||||
int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_state,
|
||||
struct intel_crtc_state *new_crtc_state,
|
||||
const struct intel_plane_state *old_plane_state,
|
||||
@@ -125,6 +148,7 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
||||
new_crtc_state->active_planes &= ~BIT(plane->id);
|
||||
new_crtc_state->nv12_planes &= ~BIT(plane->id);
|
||||
new_crtc_state->c8_planes &= ~BIT(plane->id);
|
||||
new_crtc_state->data_rate[plane->id] = 0;
|
||||
new_plane_state->base.visible = false;
|
||||
|
||||
if (!new_plane_state->base.crtc && !old_plane_state->base.crtc)
|
||||
@@ -149,6 +173,9 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
||||
if (new_plane_state->base.visible || old_plane_state->base.visible)
|
||||
new_crtc_state->update_planes |= BIT(plane->id);
|
||||
|
||||
new_crtc_state->data_rate[plane->id] =
|
||||
intel_plane_data_rate(new_crtc_state, new_plane_state);
|
||||
|
||||
return intel_plane_atomic_calc_changes(old_crtc_state,
|
||||
&new_crtc_state->base,
|
||||
old_plane_state,
|
||||
@@ -326,48 +353,3 @@ const struct drm_plane_helper_funcs intel_plane_helper_funcs = {
|
||||
.cleanup_fb = intel_cleanup_plane_fb,
|
||||
.atomic_check = intel_plane_atomic_check,
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_plane_atomic_get_property - fetch plane property value
|
||||
* @plane: plane to fetch property for
|
||||
* @state: state containing the property value
|
||||
* @property: property to look up
|
||||
* @val: pointer to write property value into
|
||||
*
|
||||
* The DRM core does not store shadow copies of properties for
|
||||
* atomic-capable drivers. This entrypoint is used to fetch
|
||||
* the current value of a driver-specific plane property.
|
||||
*/
|
||||
int
|
||||
intel_plane_atomic_get_property(struct drm_plane *plane,
|
||||
const struct drm_plane_state *state,
|
||||
struct drm_property *property,
|
||||
u64 *val)
|
||||
{
|
||||
DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
|
||||
property->base.id, property->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_plane_atomic_set_property - set plane property value
|
||||
* @plane: plane to set property for
|
||||
* @state: state to update property value in
|
||||
* @property: property to set
|
||||
* @val: value to set property to
|
||||
*
|
||||
* Writes the specified property value for a plane into the provided atomic
|
||||
* state object.
|
||||
*
|
||||
* Returns 0 on success, -EINVAL on unrecognized properties
|
||||
*/
|
||||
int
|
||||
intel_plane_atomic_set_property(struct drm_plane *plane,
|
||||
struct drm_plane_state *state,
|
||||
struct drm_property *property,
|
||||
u64 val)
|
||||
{
|
||||
DRM_DEBUG_KMS("Unknown property [PROP:%d:%s]\n",
|
||||
property->base.id, property->name);
|
||||
return -EINVAL;
|
||||
}
|
@@ -6,7 +6,11 @@
|
||||
#ifndef __INTEL_ATOMIC_PLANE_H__
|
||||
#define __INTEL_ATOMIC_PLANE_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_crtc_state;
|
||||
struct drm_plane;
|
||||
struct drm_property;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
@@ -15,6 +19,8 @@ struct intel_plane_state;
|
||||
|
||||
extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
|
||||
|
||||
unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
void intel_update_plane(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *plane_state);
|
||||
@@ -36,5 +42,9 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_
|
||||
struct intel_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *old_plane_state,
|
||||
struct intel_plane_state *intel_state);
|
||||
int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
const struct intel_plane_state *old_plane_state,
|
||||
struct drm_plane_state *plane_state);
|
||||
|
||||
#endif /* __INTEL_ATOMIC_PLANE_H__ */
|
@@ -26,11 +26,11 @@
|
||||
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_component.h>
|
||||
#include <drm/intel_lpe_audio.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_lpe_audio.h"
|
||||
|
||||
/**
|
||||
* DOC: High Definition Audio over HDMI and Display Port
|
||||
@@ -319,9 +319,8 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
const struct dp_aud_n_m *nm;
|
||||
int rate;
|
||||
u32 tmp;
|
||||
@@ -333,7 +332,7 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
|
||||
else
|
||||
DRM_DEBUG_KMS("using automatic Maud, Naud\n");
|
||||
|
||||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp = I915_READ(HSW_AUD_CFG(cpu_transcoder));
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
@@ -345,9 +344,9 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
|
||||
tmp |= AUD_CONFIG_N_PROG_ENABLE;
|
||||
}
|
||||
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_CFG(cpu_transcoder), tmp);
|
||||
|
||||
tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
|
||||
tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
|
||||
tmp &= ~AUD_CONFIG_M_MASK;
|
||||
tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
|
||||
tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
|
||||
@@ -358,7 +357,7 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
|
||||
tmp |= AUD_M_CTS_M_PROG_ENABLE;
|
||||
}
|
||||
|
||||
I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -367,15 +366,14 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
int n, rate;
|
||||
u32 tmp;
|
||||
|
||||
rate = acomp ? acomp->aud_sample_rate[port] : 0;
|
||||
|
||||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp = I915_READ(HSW_AUD_CFG(cpu_transcoder));
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
@@ -392,16 +390,16 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
|
||||
DRM_DEBUG_KMS("using automatic N\n");
|
||||
}
|
||||
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_CFG(cpu_transcoder), tmp);
|
||||
|
||||
/*
|
||||
* Let's disable "Enable CTS or M Prog bit"
|
||||
* and let HW calculate the value
|
||||
*/
|
||||
tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(pipe));
|
||||
tmp = I915_READ(HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
|
||||
tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
|
||||
tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
|
||||
I915_WRITE(HSW_AUD_M_CTS_ENABLE(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -419,28 +417,28 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder,
|
||||
const struct drm_connector_state *old_conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
|
||||
u32 tmp;
|
||||
|
||||
DRM_DEBUG_KMS("Disable audio codec on pipe %c\n", pipe_name(pipe));
|
||||
DRM_DEBUG_KMS("Disable audio codec on transcoder %s\n",
|
||||
transcoder_name(cpu_transcoder));
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
|
||||
/* Disable timestamps */
|
||||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp = I915_READ(HSW_AUD_CFG(cpu_transcoder));
|
||||
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
|
||||
tmp |= AUD_CONFIG_N_PROG_ENABLE;
|
||||
tmp &= ~AUD_CONFIG_UPPER_N_MASK;
|
||||
tmp &= ~AUD_CONFIG_LOWER_N_MASK;
|
||||
if (intel_crtc_has_dp_encoder(old_crtc_state))
|
||||
tmp |= AUD_CONFIG_N_VALUE_INDEX;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_CFG(cpu_transcoder), tmp);
|
||||
|
||||
/* Invalidate ELD */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp &= ~AUDIO_ELD_VALID(pipe);
|
||||
tmp &= ~AUDIO_OUTPUT_ENABLE(pipe);
|
||||
tmp &= ~AUDIO_ELD_VALID(cpu_transcoder);
|
||||
tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
@@ -451,22 +449,21 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
|
||||
const u8 *eld = connector->eld;
|
||||
u32 tmp;
|
||||
int len, i;
|
||||
|
||||
DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n",
|
||||
pipe_name(pipe), drm_eld_size(eld));
|
||||
DRM_DEBUG_KMS("Enable audio codec on transcoder %s, %u bytes ELD\n",
|
||||
transcoder_name(cpu_transcoder), drm_eld_size(eld));
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
|
||||
/* Enable audio presence detect, invalidate ELD */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= AUDIO_OUTPUT_ENABLE(pipe);
|
||||
tmp &= ~AUDIO_ELD_VALID(pipe);
|
||||
tmp |= AUDIO_OUTPUT_ENABLE(cpu_transcoder);
|
||||
tmp &= ~AUDIO_ELD_VALID(cpu_transcoder);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
/*
|
||||
@@ -477,18 +474,18 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder,
|
||||
*/
|
||||
|
||||
/* Reset ELD write address */
|
||||
tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(pipe));
|
||||
tmp = I915_READ(HSW_AUD_DIP_ELD_CTRL(cpu_transcoder));
|
||||
tmp &= ~IBX_ELD_ADDRESS_MASK;
|
||||
I915_WRITE(HSW_AUD_DIP_ELD_CTRL(pipe), tmp);
|
||||
I915_WRITE(HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), tmp);
|
||||
|
||||
/* Up to 84 bytes of hw ELD buffer */
|
||||
len = min(drm_eld_size(eld), 84);
|
||||
for (i = 0; i < len / 4; i++)
|
||||
I915_WRITE(HSW_AUD_EDID_DATA(pipe), *((const u32 *)eld + i));
|
||||
I915_WRITE(HSW_AUD_EDID_DATA(cpu_transcoder), *((const u32 *)eld + i));
|
||||
|
||||
/* ELD valid */
|
||||
tmp = I915_READ(HSW_AUD_PIN_ELD_CP_VLD);
|
||||
tmp |= AUDIO_ELD_VALID(pipe);
|
||||
tmp |= AUDIO_ELD_VALID(cpu_transcoder);
|
||||
I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp);
|
||||
|
||||
/* Enable timestamps */
|
||||
@@ -644,8 +641,10 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
|
||||
enum port port = encoder->port;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
/* FIXME precompute the ELD in .compute_config() */
|
||||
if (!connector->eld[0])
|
||||
return;
|
||||
DRM_DEBUG_KMS("Bogus ELD on [CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
|
||||
DRM_DEBUG_DRIVER("ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
|
||||
connector->base.id,
|
@@ -27,6 +27,9 @@
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_gmbus.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
|
||||
#define _INTEL_BIOS_PRIVATE
|
||||
@@ -74,13 +77,13 @@ static u32 get_blocksize(const void *block_data)
|
||||
}
|
||||
|
||||
static const void *
|
||||
find_section(const void *_bdb, int section_id)
|
||||
find_section(const void *_bdb, enum bdb_block_id section_id)
|
||||
{
|
||||
const struct bdb_header *bdb = _bdb;
|
||||
const u8 *base = _bdb;
|
||||
int index = 0;
|
||||
u32 total, current_size;
|
||||
u8 current_id;
|
||||
enum bdb_block_id current_id;
|
||||
|
||||
/* skip to first section */
|
||||
index += bdb->header_size;
|
||||
@@ -300,7 +303,7 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv,
|
||||
const struct bdb_header *bdb)
|
||||
{
|
||||
const struct bdb_lfp_backlight_data *backlight_data;
|
||||
const struct bdb_lfp_backlight_data_entry *entry;
|
||||
const struct lfp_backlight_data_entry *entry;
|
||||
int panel_type = dev_priv->vbt.panel_type;
|
||||
|
||||
backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
|
||||
@@ -325,7 +328,7 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv,
|
||||
dev_priv->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
|
||||
if (bdb->version >= 191 &&
|
||||
get_blocksize(backlight_data) >= sizeof(*backlight_data)) {
|
||||
const struct bdb_lfp_backlight_control_method *method;
|
||||
const struct lfp_backlight_control_method *method;
|
||||
|
||||
method = &backlight_data->backlight_control[panel_type];
|
||||
dev_priv->vbt.backlight.type = method->type;
|
||||
@@ -349,7 +352,7 @@ static void
|
||||
parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
|
||||
const struct bdb_header *bdb)
|
||||
{
|
||||
const struct lvds_dvo_timing *dvo_timing;
|
||||
const struct bdb_sdvo_panel_dtds *dtds;
|
||||
struct drm_display_mode *panel_fixed_mode;
|
||||
int index;
|
||||
|
||||
@@ -369,15 +372,15 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
|
||||
index = sdvo_lvds_options->panel_type;
|
||||
}
|
||||
|
||||
dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
|
||||
if (!dvo_timing)
|
||||
dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
|
||||
if (!dtds)
|
||||
return;
|
||||
|
||||
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
|
||||
if (!panel_fixed_mode)
|
||||
return;
|
||||
|
||||
fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
|
||||
fill_detail_timing_data(panel_fixed_mode, &dtds->dtds[index]);
|
||||
|
||||
dev_priv->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode;
|
||||
|
||||
@@ -1237,27 +1240,36 @@ static u8 translate_iboost(u8 val)
|
||||
return mapping[val];
|
||||
}
|
||||
|
||||
static enum port get_port_by_ddc_pin(struct drm_i915_private *i915, u8 ddc_pin)
|
||||
{
|
||||
const struct ddi_vbt_port_info *info;
|
||||
enum port port;
|
||||
|
||||
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
||||
info = &i915->vbt.ddi_port_info[port];
|
||||
|
||||
if (info->child && ddc_pin == info->alternate_ddc_pin)
|
||||
return port;
|
||||
}
|
||||
|
||||
return PORT_NONE;
|
||||
}
|
||||
|
||||
static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
const struct ddi_vbt_port_info *info =
|
||||
&dev_priv->vbt.ddi_port_info[port];
|
||||
struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
|
||||
enum port p;
|
||||
|
||||
if (!info->alternate_ddc_pin)
|
||||
return;
|
||||
|
||||
for (p = PORT_A; p < I915_MAX_PORTS; p++) {
|
||||
struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
|
||||
|
||||
if (p == port || !i->present ||
|
||||
info->alternate_ddc_pin != i->alternate_ddc_pin)
|
||||
continue;
|
||||
|
||||
p = get_port_by_ddc_pin(dev_priv, info->alternate_ddc_pin);
|
||||
if (p != PORT_NONE) {
|
||||
DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, "
|
||||
"disabling port %c DVI/HDMI support\n",
|
||||
port_name(p), i->alternate_ddc_pin,
|
||||
port_name(port), port_name(p));
|
||||
port_name(port), info->alternate_ddc_pin,
|
||||
port_name(p), port_name(port));
|
||||
|
||||
/*
|
||||
* If we have multiple ports supposedly sharing the
|
||||
@@ -1265,36 +1277,45 @@ static void sanitize_ddc_pin(struct drm_i915_private *dev_priv,
|
||||
* port. Otherwise they share the same ddc bin and
|
||||
* system couldn't communicate with them separately.
|
||||
*
|
||||
* Due to parsing the ports in child device order,
|
||||
* a later device will always clobber an earlier one.
|
||||
* Give child device order the priority, first come first
|
||||
* served.
|
||||
*/
|
||||
i->supports_dvi = false;
|
||||
i->supports_hdmi = false;
|
||||
i->alternate_ddc_pin = 0;
|
||||
info->supports_dvi = false;
|
||||
info->supports_hdmi = false;
|
||||
info->alternate_ddc_pin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static enum port get_port_by_aux_ch(struct drm_i915_private *i915, u8 aux_ch)
|
||||
{
|
||||
const struct ddi_vbt_port_info *info;
|
||||
enum port port;
|
||||
|
||||
for (port = PORT_A; port < I915_MAX_PORTS; port++) {
|
||||
info = &i915->vbt.ddi_port_info[port];
|
||||
|
||||
if (info->child && aux_ch == info->alternate_aux_channel)
|
||||
return port;
|
||||
}
|
||||
|
||||
return PORT_NONE;
|
||||
}
|
||||
|
||||
static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
const struct ddi_vbt_port_info *info =
|
||||
&dev_priv->vbt.ddi_port_info[port];
|
||||
struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port];
|
||||
enum port p;
|
||||
|
||||
if (!info->alternate_aux_channel)
|
||||
return;
|
||||
|
||||
for (p = PORT_A; p < I915_MAX_PORTS; p++) {
|
||||
struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p];
|
||||
|
||||
if (p == port || !i->present ||
|
||||
info->alternate_aux_channel != i->alternate_aux_channel)
|
||||
continue;
|
||||
|
||||
p = get_port_by_aux_ch(dev_priv, info->alternate_aux_channel);
|
||||
if (p != PORT_NONE) {
|
||||
DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, "
|
||||
"disabling port %c DP support\n",
|
||||
port_name(p), i->alternate_aux_channel,
|
||||
port_name(port), port_name(p));
|
||||
port_name(port), info->alternate_aux_channel,
|
||||
port_name(p), port_name(port));
|
||||
|
||||
/*
|
||||
* If we have multiple ports supposedlt sharing the
|
||||
@@ -1302,11 +1323,11 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv,
|
||||
* port. Otherwise they share the same aux channel
|
||||
* and system couldn't communicate with them separately.
|
||||
*
|
||||
* Due to parsing the ports in child device order,
|
||||
* a later device will always clobber an earlier one.
|
||||
* Give child device order the priority, first come first
|
||||
* served.
|
||||
*/
|
||||
i->supports_dp = false;
|
||||
i->alternate_aux_channel = 0;
|
||||
info->supports_dp = false;
|
||||
info->alternate_aux_channel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1327,12 +1348,21 @@ static const u8 icp_ddc_pin_map[] = {
|
||||
[ICL_DDC_BUS_PORT_4] = GMBUS_PIN_12_TC4_ICP,
|
||||
};
|
||||
|
||||
static const u8 mcc_ddc_pin_map[] = {
|
||||
[MCC_DDC_BUS_DDI_A] = GMBUS_PIN_1_BXT,
|
||||
[MCC_DDC_BUS_DDI_B] = GMBUS_PIN_2_BXT,
|
||||
[MCC_DDC_BUS_DDI_C] = GMBUS_PIN_9_TC1_ICP,
|
||||
};
|
||||
|
||||
static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin)
|
||||
{
|
||||
const u8 *ddc_pin_map;
|
||||
int n_entries;
|
||||
|
||||
if (HAS_PCH_ICP(dev_priv)) {
|
||||
if (HAS_PCH_MCC(dev_priv)) {
|
||||
ddc_pin_map = mcc_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(mcc_ddc_pin_map);
|
||||
} else if (HAS_PCH_ICP(dev_priv)) {
|
||||
ddc_pin_map = icp_ddc_pin_map;
|
||||
n_entries = ARRAY_SIZE(icp_ddc_pin_map);
|
||||
} else if (HAS_PCH_CNP(dev_priv)) {
|
||||
@@ -1395,14 +1425,12 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
|
||||
|
||||
info = &dev_priv->vbt.ddi_port_info[port];
|
||||
|
||||
if (info->present) {
|
||||
if (info->child) {
|
||||
DRM_DEBUG_KMS("More than one child device for port %c in VBT, using the first.\n",
|
||||
port_name(port));
|
||||
return;
|
||||
}
|
||||
|
||||
info->present = true;
|
||||
|
||||
is_dvi = child->device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING;
|
||||
is_dp = child->device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT;
|
||||
is_crt = child->device_type & DEVICE_TYPE_ANALOG_OUTPUT;
|
||||
@@ -1427,8 +1455,9 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
|
||||
if (bdb_version >= 209)
|
||||
info->supports_tbt = child->tbt;
|
||||
|
||||
DRM_DEBUG_KMS("Port %c VBT info: DP:%d HDMI:%d DVI:%d EDP:%d CRT:%d TCUSB:%d TBT:%d\n",
|
||||
port_name(port), is_dp, is_hdmi, is_dvi, is_edp, is_crt,
|
||||
DRM_DEBUG_KMS("Port %c VBT info: CRT:%d DVI:%d HDMI:%d DP:%d eDP:%d LSPCON:%d USB-Type-C:%d TBT:%d\n",
|
||||
port_name(port), is_crt, is_dvi, is_hdmi, is_dp, is_edp,
|
||||
HAS_LSPCON(dev_priv) && child->lspcon,
|
||||
info->supports_typec_usb, info->supports_tbt);
|
||||
|
||||
if (is_edp && is_dvi)
|
||||
@@ -1530,6 +1559,8 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv,
|
||||
DRM_DEBUG_KMS("VBT DP max link rate for port %c: %d\n",
|
||||
port_name(port), info->dp_max_link_rate);
|
||||
}
|
||||
|
||||
info->child = child;
|
||||
}
|
||||
|
||||
static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version)
|
||||
@@ -2149,106 +2180,39 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
|
||||
|
||||
/**
|
||||
* intel_bios_is_port_hpd_inverted - is HPD inverted for %port
|
||||
* @dev_priv: i915 device instance
|
||||
* @i915: i915 device instance
|
||||
* @port: port to check
|
||||
*
|
||||
* Return true if HPD should be inverted for %port.
|
||||
*/
|
||||
bool
|
||||
intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
|
||||
intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
|
||||
enum port port)
|
||||
{
|
||||
const struct child_device_config *child;
|
||||
int i;
|
||||
const struct child_device_config *child =
|
||||
i915->vbt.ddi_port_info[port].child;
|
||||
|
||||
if (WARN_ON_ONCE(!IS_GEN9_LP(dev_priv)))
|
||||
if (WARN_ON_ONCE(!IS_GEN9_LP(i915)))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
|
||||
child = dev_priv->vbt.child_dev + i;
|
||||
|
||||
if (!child->hpd_invert)
|
||||
continue;
|
||||
|
||||
switch (child->dvo_port) {
|
||||
case DVO_PORT_DPA:
|
||||
case DVO_PORT_HDMIA:
|
||||
if (port == PORT_A)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPB:
|
||||
case DVO_PORT_HDMIB:
|
||||
if (port == PORT_B)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPC:
|
||||
case DVO_PORT_HDMIC:
|
||||
if (port == PORT_C)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return child && child->hpd_invert;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_bios_is_lspcon_present - if LSPCON is attached on %port
|
||||
* @dev_priv: i915 device instance
|
||||
* @i915: i915 device instance
|
||||
* @port: port to check
|
||||
*
|
||||
* Return true if LSPCON is present on this port
|
||||
*/
|
||||
bool
|
||||
intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
intel_bios_is_lspcon_present(const struct drm_i915_private *i915,
|
||||
enum port port)
|
||||
{
|
||||
const struct child_device_config *child;
|
||||
int i;
|
||||
const struct child_device_config *child =
|
||||
i915->vbt.ddi_port_info[port].child;
|
||||
|
||||
if (!HAS_LSPCON(dev_priv))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
|
||||
child = dev_priv->vbt.child_dev + i;
|
||||
|
||||
if (!child->lspcon)
|
||||
continue;
|
||||
|
||||
switch (child->dvo_port) {
|
||||
case DVO_PORT_DPA:
|
||||
case DVO_PORT_HDMIA:
|
||||
if (port == PORT_A)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPB:
|
||||
case DVO_PORT_HDMIB:
|
||||
if (port == PORT_B)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPC:
|
||||
case DVO_PORT_HDMIC:
|
||||
if (port == PORT_C)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPD:
|
||||
case DVO_PORT_HDMID:
|
||||
if (port == PORT_D)
|
||||
return true;
|
||||
break;
|
||||
case DVO_PORT_DPF:
|
||||
case DVO_PORT_HDMIF:
|
||||
if (port == PORT_F)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return HAS_LSPCON(i915) && child && child->lspcon;
|
||||
}
|
||||
|
||||
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv,
|
@@ -30,6 +30,12 @@
|
||||
#ifndef _INTEL_BIOS_H_
|
||||
#define _INTEL_BIOS_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
enum intel_backlight_type {
|
||||
INTEL_BACKLIGHT_PMIC,
|
||||
INTEL_BACKLIGHT_LPSS,
|
||||
@@ -220,4 +226,19 @@ struct mipi_pps_data {
|
||||
u16 panel_power_cycle_delay;
|
||||
} __packed;
|
||||
|
||||
void intel_bios_init(struct drm_i915_private *dev_priv);
|
||||
void intel_bios_cleanup(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_valid_vbt(const void *buf, size_t size);
|
||||
bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
|
||||
bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
|
||||
bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
|
||||
enum port port);
|
||||
bool intel_bios_is_lspcon_present(const struct drm_i915_private *i915,
|
||||
enum port port);
|
||||
enum aux_ch intel_bios_port_aux_ch(struct drm_i915_private *dev_priv, enum port port);
|
||||
|
||||
#endif /* _INTEL_BIOS_H_ */
|
421
drivers/gpu/drm/i915/display/intel_bw.c
Normal file
421
drivers/gpu/drm/i915/display/intel_bw.c
Normal file
@@ -0,0 +1,421 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
|
||||
#include "intel_bw.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
/* Parameters for Qclk Geyserville (QGV) */
|
||||
struct intel_qgv_point {
|
||||
u16 dclk, t_rp, t_rdpre, t_rc, t_ras, t_rcd;
|
||||
};
|
||||
|
||||
struct intel_qgv_info {
|
||||
struct intel_qgv_point points[3];
|
||||
u8 num_points;
|
||||
u8 num_channels;
|
||||
u8 t_bl;
|
||||
enum intel_dram_type dram_type;
|
||||
};
|
||||
|
||||
static int icl_pcode_read_mem_global_info(struct drm_i915_private *dev_priv,
|
||||
struct intel_qgv_info *qi)
|
||||
{
|
||||
u32 val = 0;
|
||||
int ret;
|
||||
|
||||
ret = sandybridge_pcode_read(dev_priv,
|
||||
ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
|
||||
ICL_PCODE_MEM_SS_READ_GLOBAL_INFO,
|
||||
&val, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (val & 0xf) {
|
||||
case 0:
|
||||
qi->dram_type = INTEL_DRAM_DDR4;
|
||||
break;
|
||||
case 1:
|
||||
qi->dram_type = INTEL_DRAM_DDR3;
|
||||
break;
|
||||
case 2:
|
||||
qi->dram_type = INTEL_DRAM_LPDDR3;
|
||||
break;
|
||||
case 3:
|
||||
qi->dram_type = INTEL_DRAM_LPDDR3;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(val & 0xf);
|
||||
break;
|
||||
}
|
||||
|
||||
qi->num_channels = (val & 0xf0) >> 4;
|
||||
qi->num_points = (val & 0xf00) >> 8;
|
||||
|
||||
qi->t_bl = qi->dram_type == INTEL_DRAM_DDR4 ? 4 : 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_pcode_read_qgv_point_info(struct drm_i915_private *dev_priv,
|
||||
struct intel_qgv_point *sp,
|
||||
int point)
|
||||
{
|
||||
u32 val = 0, val2;
|
||||
int ret;
|
||||
|
||||
ret = sandybridge_pcode_read(dev_priv,
|
||||
ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
|
||||
ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
|
||||
&val, &val2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sp->dclk = val & 0xffff;
|
||||
sp->t_rp = (val & 0xff0000) >> 16;
|
||||
sp->t_rcd = (val & 0xff000000) >> 24;
|
||||
|
||||
sp->t_rdpre = val2 & 0xff;
|
||||
sp->t_ras = (val2 & 0xff00) >> 8;
|
||||
|
||||
sp->t_rc = sp->t_rp + sp->t_ras;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_get_qgv_points(struct drm_i915_private *dev_priv,
|
||||
struct intel_qgv_info *qi)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
ret = icl_pcode_read_mem_global_info(dev_priv, qi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (WARN_ON(qi->num_points > ARRAY_SIZE(qi->points)))
|
||||
qi->num_points = ARRAY_SIZE(qi->points);
|
||||
|
||||
for (i = 0; i < qi->num_points; i++) {
|
||||
struct intel_qgv_point *sp = &qi->points[i];
|
||||
|
||||
ret = icl_pcode_read_qgv_point_info(dev_priv, sp, i);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_DEBUG_KMS("QGV %d: DCLK=%d tRP=%d tRDPRE=%d tRAS=%d tRCD=%d tRC=%d\n",
|
||||
i, sp->dclk, sp->t_rp, sp->t_rdpre, sp->t_ras,
|
||||
sp->t_rcd, sp->t_rc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_calc_bw(int dclk, int num, int den)
|
||||
{
|
||||
/* multiples of 16.666MHz (100/6) */
|
||||
return DIV_ROUND_CLOSEST(num * dclk * 100, den * 6);
|
||||
}
|
||||
|
||||
static int icl_sagv_max_dclk(const struct intel_qgv_info *qi)
|
||||
{
|
||||
u16 dclk = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < qi->num_points; i++)
|
||||
dclk = max(dclk, qi->points[i].dclk);
|
||||
|
||||
return dclk;
|
||||
}
|
||||
|
||||
struct intel_sa_info {
|
||||
u8 deburst, mpagesize, deprogbwlimit, displayrtids;
|
||||
};
|
||||
|
||||
static const struct intel_sa_info icl_sa_info = {
|
||||
.deburst = 8,
|
||||
.mpagesize = 16,
|
||||
.deprogbwlimit = 25, /* GB/s */
|
||||
.displayrtids = 128,
|
||||
};
|
||||
|
||||
static int icl_get_bw_info(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_qgv_info qi = {};
|
||||
const struct intel_sa_info *sa = &icl_sa_info;
|
||||
bool is_y_tile = true; /* assume y tile may be used */
|
||||
int num_channels;
|
||||
int deinterleave;
|
||||
int ipqdepth, ipqdepthpch;
|
||||
int dclk_max;
|
||||
int maxdebw;
|
||||
int i, ret;
|
||||
|
||||
ret = icl_get_qgv_points(dev_priv, &qi);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("Failed to get memory subsystem information, ignoring bandwidth limits");
|
||||
return ret;
|
||||
}
|
||||
num_channels = qi.num_channels;
|
||||
|
||||
deinterleave = DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
|
||||
dclk_max = icl_sagv_max_dclk(&qi);
|
||||
|
||||
ipqdepthpch = 16;
|
||||
|
||||
maxdebw = min(sa->deprogbwlimit * 1000,
|
||||
icl_calc_bw(dclk_max, 16, 1) * 6 / 10); /* 60% */
|
||||
ipqdepth = min(ipqdepthpch, sa->displayrtids / num_channels);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
|
||||
struct intel_bw_info *bi = &dev_priv->max_bw[i];
|
||||
int clpchgroup;
|
||||
int j;
|
||||
|
||||
clpchgroup = (sa->deburst * deinterleave / num_channels) << i;
|
||||
bi->num_planes = (ipqdepth - clpchgroup) / clpchgroup + 1;
|
||||
|
||||
for (j = 0; j < qi.num_points; j++) {
|
||||
const struct intel_qgv_point *sp = &qi.points[j];
|
||||
int ct, bw;
|
||||
|
||||
/*
|
||||
* Max row cycle time
|
||||
*
|
||||
* FIXME what is the logic behind the
|
||||
* assumed burst length?
|
||||
*/
|
||||
ct = max_t(int, sp->t_rc, sp->t_rp + sp->t_rcd +
|
||||
(clpchgroup - 1) * qi.t_bl + sp->t_rdpre);
|
||||
bw = icl_calc_bw(sp->dclk, clpchgroup * 32 * num_channels, ct);
|
||||
|
||||
bi->deratedbw[j] = min(maxdebw,
|
||||
bw * 9 / 10); /* 90% */
|
||||
|
||||
DRM_DEBUG_KMS("BW%d / QGV %d: num_planes=%d deratedbw=%d\n",
|
||||
i, j, bi->num_planes, bi->deratedbw[j]);
|
||||
}
|
||||
|
||||
if (bi->num_planes == 1)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int icl_max_bw(struct drm_i915_private *dev_priv,
|
||||
int num_planes, int qgv_point)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Did we initialize the bw limits successfully? */
|
||||
if (dev_priv->max_bw[0].num_planes == 0)
|
||||
return UINT_MAX;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_priv->max_bw); i++) {
|
||||
const struct intel_bw_info *bi =
|
||||
&dev_priv->max_bw[i];
|
||||
|
||||
if (num_planes >= bi->num_planes)
|
||||
return bi->deratedbw[qgv_point];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_bw_init_hw(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (IS_GEN(dev_priv, 11))
|
||||
icl_get_bw_info(dev_priv);
|
||||
}
|
||||
|
||||
static unsigned int intel_max_data_rate(struct drm_i915_private *dev_priv,
|
||||
int num_planes)
|
||||
{
|
||||
if (IS_GEN(dev_priv, 11))
|
||||
/*
|
||||
* FIXME with SAGV disabled maybe we can assume
|
||||
* point 1 will always be used? Seems to match
|
||||
* the behaviour observed in the wild.
|
||||
*/
|
||||
return min3(icl_max_bw(dev_priv, num_planes, 0),
|
||||
icl_max_bw(dev_priv, num_planes, 1),
|
||||
icl_max_bw(dev_priv, num_planes, 2));
|
||||
else
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
/*
|
||||
* We assume cursors are small enough
|
||||
* to not not cause bandwidth problems.
|
||||
*/
|
||||
return hweight8(crtc_state->active_planes & ~BIT(PLANE_CURSOR));
|
||||
}
|
||||
|
||||
static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
unsigned int data_rate = 0;
|
||||
enum plane_id plane_id;
|
||||
|
||||
for_each_plane_id_on_crtc(crtc, plane_id) {
|
||||
/*
|
||||
* We assume cursors are small enough
|
||||
* to not not cause bandwidth problems.
|
||||
*/
|
||||
if (plane_id == PLANE_CURSOR)
|
||||
continue;
|
||||
|
||||
data_rate += crtc_state->data_rate[plane_id];
|
||||
}
|
||||
|
||||
return data_rate;
|
||||
}
|
||||
|
||||
void intel_bw_crtc_update(struct intel_bw_state *bw_state,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
|
||||
bw_state->data_rate[crtc->pipe] =
|
||||
intel_bw_crtc_data_rate(crtc_state);
|
||||
bw_state->num_active_planes[crtc->pipe] =
|
||||
intel_bw_crtc_num_active_planes(crtc_state);
|
||||
|
||||
DRM_DEBUG_KMS("pipe %c data rate %u num active planes %u\n",
|
||||
pipe_name(crtc->pipe),
|
||||
bw_state->data_rate[crtc->pipe],
|
||||
bw_state->num_active_planes[crtc->pipe]);
|
||||
}
|
||||
|
||||
static unsigned int intel_bw_num_active_planes(struct drm_i915_private *dev_priv,
|
||||
const struct intel_bw_state *bw_state)
|
||||
{
|
||||
unsigned int num_active_planes = 0;
|
||||
enum pipe pipe;
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
num_active_planes += bw_state->num_active_planes[pipe];
|
||||
|
||||
return num_active_planes;
|
||||
}
|
||||
|
||||
static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv,
|
||||
const struct intel_bw_state *bw_state)
|
||||
{
|
||||
unsigned int data_rate = 0;
|
||||
enum pipe pipe;
|
||||
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
data_rate += bw_state->data_rate[pipe];
|
||||
|
||||
return data_rate;
|
||||
}
|
||||
|
||||
int intel_bw_atomic_check(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_crtc_state *new_crtc_state, *old_crtc_state;
|
||||
struct intel_bw_state *bw_state = NULL;
|
||||
unsigned int data_rate, max_data_rate;
|
||||
unsigned int num_active_planes;
|
||||
struct intel_crtc *crtc;
|
||||
int i;
|
||||
|
||||
/* FIXME earlier gens need some checks too */
|
||||
if (INTEL_GEN(dev_priv) < 11)
|
||||
return 0;
|
||||
|
||||
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
|
||||
new_crtc_state, i) {
|
||||
unsigned int old_data_rate =
|
||||
intel_bw_crtc_data_rate(old_crtc_state);
|
||||
unsigned int new_data_rate =
|
||||
intel_bw_crtc_data_rate(new_crtc_state);
|
||||
unsigned int old_active_planes =
|
||||
intel_bw_crtc_num_active_planes(old_crtc_state);
|
||||
unsigned int new_active_planes =
|
||||
intel_bw_crtc_num_active_planes(new_crtc_state);
|
||||
|
||||
/*
|
||||
* Avoid locking the bw state when
|
||||
* nothing significant has changed.
|
||||
*/
|
||||
if (old_data_rate == new_data_rate &&
|
||||
old_active_planes == new_active_planes)
|
||||
continue;
|
||||
|
||||
bw_state = intel_atomic_get_bw_state(state);
|
||||
if (IS_ERR(bw_state))
|
||||
return PTR_ERR(bw_state);
|
||||
|
||||
bw_state->data_rate[crtc->pipe] = new_data_rate;
|
||||
bw_state->num_active_planes[crtc->pipe] = new_active_planes;
|
||||
|
||||
DRM_DEBUG_KMS("pipe %c data rate %u num active planes %u\n",
|
||||
pipe_name(crtc->pipe),
|
||||
bw_state->data_rate[crtc->pipe],
|
||||
bw_state->num_active_planes[crtc->pipe]);
|
||||
}
|
||||
|
||||
if (!bw_state)
|
||||
return 0;
|
||||
|
||||
data_rate = intel_bw_data_rate(dev_priv, bw_state);
|
||||
num_active_planes = intel_bw_num_active_planes(dev_priv, bw_state);
|
||||
|
||||
max_data_rate = intel_max_data_rate(dev_priv, num_active_planes);
|
||||
|
||||
data_rate = DIV_ROUND_UP(data_rate, 1000);
|
||||
|
||||
if (data_rate > max_data_rate) {
|
||||
DRM_DEBUG_KMS("Bandwidth %u MB/s exceeds max available %d MB/s (%d active planes)\n",
|
||||
data_rate, max_data_rate, num_active_planes);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_private_state *intel_bw_duplicate_state(struct drm_private_obj *obj)
|
||||
{
|
||||
struct intel_bw_state *state;
|
||||
|
||||
state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return NULL;
|
||||
|
||||
__drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
|
||||
|
||||
return &state->base;
|
||||
}
|
||||
|
||||
static void intel_bw_destroy_state(struct drm_private_obj *obj,
|
||||
struct drm_private_state *state)
|
||||
{
|
||||
kfree(state);
|
||||
}
|
||||
|
||||
static const struct drm_private_state_funcs intel_bw_funcs = {
|
||||
.atomic_duplicate_state = intel_bw_duplicate_state,
|
||||
.atomic_destroy_state = intel_bw_destroy_state,
|
||||
};
|
||||
|
||||
int intel_bw_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_bw_state *state;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
drm_atomic_private_obj_init(&dev_priv->drm, &dev_priv->bw_obj,
|
||||
&state->base, &intel_bw_funcs);
|
||||
|
||||
return 0;
|
||||
}
|
47
drivers/gpu/drm/i915/display/intel_bw.h
Normal file
47
drivers/gpu/drm/i915/display/intel_bw.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_BW_H__
|
||||
#define __INTEL_BW_H__
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_atomic_state;
|
||||
struct intel_crtc_state;
|
||||
|
||||
struct intel_bw_state {
|
||||
struct drm_private_state base;
|
||||
|
||||
unsigned int data_rate[I915_MAX_PIPES];
|
||||
u8 num_active_planes[I915_MAX_PIPES];
|
||||
};
|
||||
|
||||
#define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base)
|
||||
|
||||
static inline struct intel_bw_state *
|
||||
intel_atomic_get_bw_state(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct drm_private_state *bw_state;
|
||||
|
||||
bw_state = drm_atomic_get_private_obj_state(&state->base,
|
||||
&dev_priv->bw_obj);
|
||||
if (IS_ERR(bw_state))
|
||||
return ERR_CAST(bw_state);
|
||||
|
||||
return to_intel_bw_state(bw_state);
|
||||
}
|
||||
|
||||
void intel_bw_init_hw(struct drm_i915_private *dev_priv);
|
||||
int intel_bw_init(struct drm_i915_private *dev_priv);
|
||||
int intel_bw_atomic_check(struct intel_atomic_state *state);
|
||||
void intel_bw_crtc_update(struct intel_bw_state *bw_state,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_BW_H__ */
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "intel_cdclk.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
/**
|
||||
* DOC: CDCLK / RAWCLK
|
||||
@@ -464,14 +465,18 @@ static void vlv_get_cdclk(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
u32 val;
|
||||
|
||||
vlv_iosf_sb_get(dev_priv,
|
||||
BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
|
||||
|
||||
cdclk_state->vco = vlv_get_hpll_vco(dev_priv);
|
||||
cdclk_state->cdclk = vlv_get_cck_clock(dev_priv, "cdclk",
|
||||
CCK_DISPLAY_CLOCK_CONTROL,
|
||||
cdclk_state->vco);
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
vlv_iosf_sb_put(dev_priv,
|
||||
BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
cdclk_state->voltage_level = (val & DSPFREQGUAR_MASK) >>
|
||||
@@ -545,7 +550,11 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
*/
|
||||
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
vlv_iosf_sb_get(dev_priv,
|
||||
BIT(VLV_IOSF_SB_CCK) |
|
||||
BIT(VLV_IOSF_SB_BUNIT) |
|
||||
BIT(VLV_IOSF_SB_PUNIT));
|
||||
|
||||
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
|
||||
val &= ~DSPFREQGUAR_MASK;
|
||||
val |= (cmd << DSPFREQGUAR_SHIFT);
|
||||
@@ -555,9 +564,6 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
50)) {
|
||||
DRM_ERROR("timed out waiting for CDclk change\n");
|
||||
}
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
|
||||
if (cdclk == 400000) {
|
||||
u32 divider;
|
||||
@@ -591,7 +597,10 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
val |= 3000 / 250; /* 3.0 usec */
|
||||
vlv_bunit_write(dev_priv, BUNIT_REG_BISOC, val);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_iosf_sb_put(dev_priv,
|
||||
BIT(VLV_IOSF_SB_CCK) |
|
||||
BIT(VLV_IOSF_SB_BUNIT) |
|
||||
BIT(VLV_IOSF_SB_PUNIT));
|
||||
|
||||
intel_update_cdclk(dev_priv);
|
||||
|
||||
@@ -627,7 +636,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
*/
|
||||
wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A);
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
vlv_punit_get(dev_priv);
|
||||
val = vlv_punit_read(dev_priv, PUNIT_REG_DSPSSPM);
|
||||
val &= ~DSPFREQGUAR_MASK_CHV;
|
||||
val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
|
||||
@@ -637,7 +646,8 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
50)) {
|
||||
DRM_ERROR("timed out waiting for CDclk change\n");
|
||||
}
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
vlv_punit_put(dev_priv);
|
||||
|
||||
intel_update_cdclk(dev_priv);
|
||||
|
||||
@@ -716,10 +726,8 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
"trying to change cdclk frequency with cdclk not enabled\n"))
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = sandybridge_pcode_write(dev_priv,
|
||||
BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to inform pcode about cdclk change\n");
|
||||
return;
|
||||
@@ -768,10 +776,8 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
|
||||
DRM_ERROR("Switching back to LCPLL failed\n");
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ,
|
||||
cdclk_state->voltage_level);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
|
||||
|
||||
@@ -803,20 +809,14 @@ static int skl_calc_cdclk(int min_cdclk, int vco)
|
||||
|
||||
static u8 skl_calc_voltage_level(int cdclk)
|
||||
{
|
||||
switch (cdclk) {
|
||||
default:
|
||||
case 308571:
|
||||
case 337500:
|
||||
return 0;
|
||||
case 450000:
|
||||
case 432000:
|
||||
return 1;
|
||||
case 540000:
|
||||
return 2;
|
||||
case 617143:
|
||||
case 675000:
|
||||
if (cdclk > 540000)
|
||||
return 3;
|
||||
}
|
||||
else if (cdclk > 450000)
|
||||
return 2;
|
||||
else if (cdclk > 337500)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skl_dpll0_update(struct drm_i915_private *dev_priv,
|
||||
@@ -1010,12 +1010,10 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
*/
|
||||
WARN_ON_ONCE(IS_SKYLAKE(dev_priv) && vco == 8640000);
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
SKL_CDCLK_PREPARE_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE, 3);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
|
||||
ret);
|
||||
@@ -1079,10 +1077,8 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
POSTING_READ(CDCLK_CTL);
|
||||
|
||||
/* inform PCU of the change */
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
cdclk_state->voltage_level);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
intel_update_cdclk(dev_priv);
|
||||
}
|
||||
@@ -1379,12 +1375,9 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
* requires us to wait up to 150usec, but that leads to timeouts;
|
||||
* the 2ms used here is based on experiment.
|
||||
*/
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = sandybridge_pcode_write_timeout(dev_priv,
|
||||
HSW_PCODE_DE_WRITE_FREQ_REQ,
|
||||
0x80000000, 150, 2);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n",
|
||||
ret, cdclk);
|
||||
@@ -1414,7 +1407,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
if (pipe != INVALID_PIPE)
|
||||
intel_wait_for_vblank(dev_priv, pipe);
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
/*
|
||||
* The timeout isn't specified, the 2ms used here is based on
|
||||
* experiment.
|
||||
@@ -1424,8 +1416,6 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
ret = sandybridge_pcode_write_timeout(dev_priv,
|
||||
HSW_PCODE_DE_WRITE_FREQ_REQ,
|
||||
cdclk_state->voltage_level, 150, 2);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n",
|
||||
ret, cdclk);
|
||||
@@ -1535,15 +1525,12 @@ static int cnl_calc_cdclk(int min_cdclk)
|
||||
|
||||
static u8 cnl_calc_voltage_level(int cdclk)
|
||||
{
|
||||
switch (cdclk) {
|
||||
default:
|
||||
case 168000:
|
||||
return 0;
|
||||
case 336000:
|
||||
return 1;
|
||||
case 528000:
|
||||
if (cdclk > 336000)
|
||||
return 2;
|
||||
}
|
||||
else if (cdclk > 168000)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cnl_cdclk_pll_update(struct drm_i915_private *dev_priv,
|
||||
@@ -1648,12 +1635,10 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
u32 val, divider;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
SKL_CDCLK_PREPARE_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE, 3);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
|
||||
ret);
|
||||
@@ -1692,10 +1677,8 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
intel_wait_for_vblank(dev_priv, pipe);
|
||||
|
||||
/* inform PCU of the change */
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
cdclk_state->voltage_level);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
intel_update_cdclk(dev_priv);
|
||||
|
||||
@@ -1834,12 +1817,10 @@ static void icl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
unsigned int vco = cdclk_state->vco;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
SKL_CDCLK_PREPARE_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE,
|
||||
SKL_CDCLK_READY_FOR_CHANGE, 3);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n",
|
||||
ret);
|
||||
@@ -1861,10 +1842,8 @@ static void icl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
I915_WRITE(CDCLK_CTL, ICL_CDCLK_CD2X_PIPE_NONE |
|
||||
skl_cdclk_decimal(cdclk));
|
||||
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL,
|
||||
cdclk_state->voltage_level);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
|
||||
intel_update_cdclk(dev_priv);
|
||||
|
||||
@@ -1877,21 +1856,12 @@ static void icl_set_cdclk(struct drm_i915_private *dev_priv,
|
||||
|
||||
static u8 icl_calc_voltage_level(int cdclk)
|
||||
{
|
||||
switch (cdclk) {
|
||||
case 50000:
|
||||
case 307200:
|
||||
case 312000:
|
||||
return 0;
|
||||
case 556800:
|
||||
case 552000:
|
||||
return 1;
|
||||
default:
|
||||
MISSING_CASE(cdclk);
|
||||
/* fall through */
|
||||
case 652800:
|
||||
case 648000:
|
||||
if (cdclk > 556800)
|
||||
return 2;
|
||||
}
|
||||
else if (cdclk > 312000)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void icl_get_cdclk(struct drm_i915_private *dev_priv,
|
||||
@@ -2277,6 +2247,15 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
|
||||
IS_VALLEYVIEW(dev_priv))
|
||||
min_cdclk = max(320000, min_cdclk);
|
||||
|
||||
/*
|
||||
* On Geminilake once the CDCLK gets as low as 79200
|
||||
* picture gets unstable, despite that values are
|
||||
* correct for DSI PLL and DE PLL.
|
||||
*/
|
||||
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) &&
|
||||
IS_GEMINILAKE(dev_priv))
|
||||
min_cdclk = max(158400, min_cdclk);
|
||||
|
||||
if (min_cdclk > dev_priv->max_cdclk_freq) {
|
||||
DRM_DEBUG_KMS("required cdclk (%d kHz) exceeds max (%d kHz)\n",
|
||||
min_cdclk, dev_priv->max_cdclk_freq);
|
||||
@@ -2286,29 +2265,28 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
|
||||
return min_cdclk;
|
||||
}
|
||||
|
||||
static int intel_compute_min_cdclk(struct drm_atomic_state *state)
|
||||
static int intel_compute_min_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int min_cdclk, i;
|
||||
enum pipe pipe;
|
||||
|
||||
memcpy(intel_state->min_cdclk, dev_priv->min_cdclk,
|
||||
sizeof(intel_state->min_cdclk));
|
||||
memcpy(state->min_cdclk, dev_priv->min_cdclk,
|
||||
sizeof(state->min_cdclk));
|
||||
|
||||
for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
|
||||
if (min_cdclk < 0)
|
||||
return min_cdclk;
|
||||
|
||||
intel_state->min_cdclk[i] = min_cdclk;
|
||||
state->min_cdclk[i] = min_cdclk;
|
||||
}
|
||||
|
||||
min_cdclk = intel_state->cdclk.force_min_cdclk;
|
||||
min_cdclk = state->cdclk.force_min_cdclk;
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
min_cdclk = max(intel_state->min_cdclk[pipe], min_cdclk);
|
||||
min_cdclk = max(state->min_cdclk[pipe], min_cdclk);
|
||||
|
||||
return min_cdclk;
|
||||
}
|
||||
@@ -2350,10 +2328,9 @@ static u8 cnl_compute_min_voltage_level(struct intel_atomic_state *state)
|
||||
return min_voltage_level;
|
||||
}
|
||||
|
||||
static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int vlv_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
int min_cdclk, cdclk;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
@@ -2362,28 +2339,25 @@ static int vlv_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
|
||||
cdclk = vlv_calc_cdclk(dev_priv, min_cdclk);
|
||||
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
vlv_calc_voltage_level(dev_priv, cdclk);
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
cdclk = vlv_calc_cdclk(dev_priv,
|
||||
intel_state->cdclk.force_min_cdclk);
|
||||
if (!state->active_crtcs) {
|
||||
cdclk = vlv_calc_cdclk(dev_priv, state->cdclk.force_min_cdclk);
|
||||
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
vlv_calc_voltage_level(dev_priv, cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual =
|
||||
intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int bdw_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
int min_cdclk, cdclk;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
@@ -2396,36 +2370,35 @@ static int bdw_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
*/
|
||||
cdclk = bdw_calc_cdclk(min_cdclk);
|
||||
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
bdw_calc_voltage_level(cdclk);
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
cdclk = bdw_calc_cdclk(intel_state->cdclk.force_min_cdclk);
|
||||
if (!state->active_crtcs) {
|
||||
cdclk = bdw_calc_cdclk(state->cdclk.force_min_cdclk);
|
||||
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
bdw_calc_voltage_level(cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual =
|
||||
intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int skl_dpll0_vco(struct intel_atomic_state *intel_state)
|
||||
static int skl_dpll0_vco(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(intel_state->base.dev);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
struct intel_crtc *crtc;
|
||||
struct intel_crtc_state *crtc_state;
|
||||
int vco, i;
|
||||
|
||||
vco = intel_state->cdclk.logical.vco;
|
||||
vco = state->cdclk.logical.vco;
|
||||
if (!vco)
|
||||
vco = dev_priv->skl_preferred_vco_freq;
|
||||
|
||||
for_each_new_intel_crtc_in_state(intel_state, crtc, crtc_state, i) {
|
||||
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
if (!crtc_state->base.enable)
|
||||
continue;
|
||||
|
||||
@@ -2450,16 +2423,15 @@ static int skl_dpll0_vco(struct intel_atomic_state *intel_state)
|
||||
return vco;
|
||||
}
|
||||
|
||||
static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int skl_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
int min_cdclk, cdclk, vco;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
if (min_cdclk < 0)
|
||||
return min_cdclk;
|
||||
|
||||
vco = skl_dpll0_vco(intel_state);
|
||||
vco = skl_dpll0_vco(state);
|
||||
|
||||
/*
|
||||
* FIXME should also account for plane ratio
|
||||
@@ -2467,30 +2439,28 @@ static int skl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
*/
|
||||
cdclk = skl_calc_cdclk(min_cdclk, vco);
|
||||
|
||||
intel_state->cdclk.logical.vco = vco;
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.vco = vco;
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
skl_calc_voltage_level(cdclk);
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
cdclk = skl_calc_cdclk(intel_state->cdclk.force_min_cdclk, vco);
|
||||
if (!state->active_crtcs) {
|
||||
cdclk = skl_calc_cdclk(state->cdclk.force_min_cdclk, vco);
|
||||
|
||||
intel_state->cdclk.actual.vco = vco;
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.vco = vco;
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
skl_calc_voltage_level(cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual =
|
||||
intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int bxt_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
int min_cdclk, cdclk, vco;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
@@ -2505,36 +2475,34 @@ static int bxt_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
vco = bxt_de_pll_vco(dev_priv, cdclk);
|
||||
}
|
||||
|
||||
intel_state->cdclk.logical.vco = vco;
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.vco = vco;
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
bxt_calc_voltage_level(cdclk);
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
if (!state->active_crtcs) {
|
||||
if (IS_GEMINILAKE(dev_priv)) {
|
||||
cdclk = glk_calc_cdclk(intel_state->cdclk.force_min_cdclk);
|
||||
cdclk = glk_calc_cdclk(state->cdclk.force_min_cdclk);
|
||||
vco = glk_de_pll_vco(dev_priv, cdclk);
|
||||
} else {
|
||||
cdclk = bxt_calc_cdclk(intel_state->cdclk.force_min_cdclk);
|
||||
cdclk = bxt_calc_cdclk(state->cdclk.force_min_cdclk);
|
||||
vco = bxt_de_pll_vco(dev_priv, cdclk);
|
||||
}
|
||||
|
||||
intel_state->cdclk.actual.vco = vco;
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.vco = vco;
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
bxt_calc_voltage_level(cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual =
|
||||
intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int cnl_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
int min_cdclk, cdclk, vco;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
@@ -2544,33 +2512,31 @@ static int cnl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
cdclk = cnl_calc_cdclk(min_cdclk);
|
||||
vco = cnl_cdclk_pll_vco(dev_priv, cdclk);
|
||||
|
||||
intel_state->cdclk.logical.vco = vco;
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.vco = vco;
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
max(cnl_calc_voltage_level(cdclk),
|
||||
cnl_compute_min_voltage_level(intel_state));
|
||||
cnl_compute_min_voltage_level(state));
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
cdclk = cnl_calc_cdclk(intel_state->cdclk.force_min_cdclk);
|
||||
if (!state->active_crtcs) {
|
||||
cdclk = cnl_calc_cdclk(state->cdclk.force_min_cdclk);
|
||||
vco = cnl_cdclk_pll_vco(dev_priv, cdclk);
|
||||
|
||||
intel_state->cdclk.actual.vco = vco;
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.vco = vco;
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
cnl_calc_voltage_level(cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual =
|
||||
intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int icl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
static int icl_modeset_calc_cdclk(struct intel_atomic_state *state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(state->dev);
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
unsigned int ref = intel_state->cdclk.logical.ref;
|
||||
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
unsigned int ref = state->cdclk.logical.ref;
|
||||
int min_cdclk, cdclk, vco;
|
||||
|
||||
min_cdclk = intel_compute_min_cdclk(state);
|
||||
@@ -2580,22 +2546,22 @@ static int icl_modeset_calc_cdclk(struct drm_atomic_state *state)
|
||||
cdclk = icl_calc_cdclk(min_cdclk, ref);
|
||||
vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk);
|
||||
|
||||
intel_state->cdclk.logical.vco = vco;
|
||||
intel_state->cdclk.logical.cdclk = cdclk;
|
||||
intel_state->cdclk.logical.voltage_level =
|
||||
state->cdclk.logical.vco = vco;
|
||||
state->cdclk.logical.cdclk = cdclk;
|
||||
state->cdclk.logical.voltage_level =
|
||||
max(icl_calc_voltage_level(cdclk),
|
||||
cnl_compute_min_voltage_level(intel_state));
|
||||
cnl_compute_min_voltage_level(state));
|
||||
|
||||
if (!intel_state->active_crtcs) {
|
||||
cdclk = icl_calc_cdclk(intel_state->cdclk.force_min_cdclk, ref);
|
||||
if (!state->active_crtcs) {
|
||||
cdclk = icl_calc_cdclk(state->cdclk.force_min_cdclk, ref);
|
||||
vco = icl_calc_cdclk_pll_vco(dev_priv, cdclk);
|
||||
|
||||
intel_state->cdclk.actual.vco = vco;
|
||||
intel_state->cdclk.actual.cdclk = cdclk;
|
||||
intel_state->cdclk.actual.voltage_level =
|
||||
state->cdclk.actual.vco = vco;
|
||||
state->cdclk.actual.cdclk = cdclk;
|
||||
state->cdclk.actual.voltage_level =
|
||||
icl_calc_voltage_level(cdclk);
|
||||
} else {
|
||||
intel_state->cdclk.actual = intel_state->cdclk.logical;
|
||||
state->cdclk.actual = state->cdclk.logical;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2817,28 +2783,22 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv)
|
||||
dev_priv->display.modeset_calc_cdclk = icl_modeset_calc_cdclk;
|
||||
} else if (IS_CANNONLAKE(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = cnl_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
cnl_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = cnl_modeset_calc_cdclk;
|
||||
} else if (IS_GEN9_LP(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = bxt_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
bxt_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = bxt_modeset_calc_cdclk;
|
||||
} else if (IS_GEN9_BC(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = skl_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
skl_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = skl_modeset_calc_cdclk;
|
||||
} else if (IS_BROADWELL(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = bdw_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
bdw_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = bdw_modeset_calc_cdclk;
|
||||
} else if (IS_CHERRYVIEW(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = chv_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
vlv_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = vlv_modeset_calc_cdclk;
|
||||
} else if (IS_VALLEYVIEW(dev_priv)) {
|
||||
dev_priv->display.set_cdclk = vlv_set_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk =
|
||||
vlv_modeset_calc_cdclk;
|
||||
dev_priv->display.modeset_calc_cdclk = vlv_modeset_calc_cdclk;
|
||||
}
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
@@ -41,6 +41,7 @@
|
||||
#define CTM_COEFF_ABS(coeff) ((coeff) & (CTM_COEFF_SIGN - 1))
|
||||
|
||||
#define LEGACY_LUT_LENGTH 256
|
||||
|
||||
/*
|
||||
* Extract the CSC coefficient from a CTM coefficient (in U32.32 fixed point
|
||||
* format). This macro takes the coefficient we want transformed and the
|
||||
@@ -607,7 +608,7 @@ static void bdw_load_lut_10(struct intel_crtc *crtc,
|
||||
I915_WRITE(PREC_PAL_INDEX(pipe), 0);
|
||||
}
|
||||
|
||||
static void ivb_load_lut_10_max(struct intel_crtc *crtc)
|
||||
static void ivb_load_lut_ext_max(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
@@ -640,7 +641,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
|
||||
ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(512));
|
||||
} else {
|
||||
@@ -648,7 +649,7 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
ivb_load_lut_10(crtc, blob,
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,7 +664,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
} else if (crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) {
|
||||
bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
|
||||
PAL_PREC_INDEX_VALUE(512));
|
||||
} else {
|
||||
@@ -671,7 +672,7 @@ static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
|
||||
bdw_load_lut_10(crtc, blob,
|
||||
PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,10 +764,120 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
i9xx_load_luts(crtc_state);
|
||||
} else {
|
||||
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
/* ilk+ "12.4" interpolated format (high 10 bits) */
|
||||
static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color)
|
||||
{
|
||||
return (color->red >> 6) << 20 | (color->green >> 6) << 10 |
|
||||
(color->blue >> 6);
|
||||
}
|
||||
|
||||
/* ilk+ "12.4" interpolated format (low 6 bits) */
|
||||
static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color)
|
||||
{
|
||||
return (color->red & 0x3f) << 24 | (color->green & 0x3f) << 14 |
|
||||
(color->blue & 0x3f) << 4;
|
||||
}
|
||||
|
||||
static void
|
||||
icl_load_gcmax(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_color_lut *color)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
/* Fixme: LUT entries are 16 bit only, so we can prog 0xFFFF max */
|
||||
I915_WRITE(PREC_PAL_GC_MAX(pipe, 0), color->red);
|
||||
I915_WRITE(PREC_PAL_GC_MAX(pipe, 1), color->green);
|
||||
I915_WRITE(PREC_PAL_GC_MAX(pipe, 2), color->blue);
|
||||
}
|
||||
|
||||
static void
|
||||
icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_property_blob *blob = crtc_state->base.gamma_lut;
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* Every entry in the multi-segment LUT is corresponding to a superfine
|
||||
* segment step which is 1/(8 * 128 * 256).
|
||||
*
|
||||
* Superfine segment has 9 entries, corresponding to values
|
||||
* 0, 1/(8 * 128 * 256), 2/(8 * 128 * 256) .... 8/(8 * 128 * 256).
|
||||
*/
|
||||
I915_WRITE(PREC_PAL_MULTI_SEG_INDEX(pipe), PAL_PREC_AUTO_INCREMENT);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
const struct drm_color_lut *entry = &lut[i];
|
||||
|
||||
I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe),
|
||||
ilk_lut_12p4_ldw(entry));
|
||||
I915_WRITE(PREC_PAL_MULTI_SEG_DATA(pipe),
|
||||
ilk_lut_12p4_udw(entry));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_property_blob *blob = crtc_state->base.gamma_lut;
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
const struct drm_color_lut *entry;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
*
|
||||
* Program Fine segment (let's call it seg2)...
|
||||
*
|
||||
* Fine segment's step is 1/(128 * 256) ie 1/(128 * 256), 2/(128*256)
|
||||
* ... 256/(128*256). So in order to program fine segment of LUT we
|
||||
* need to pick every 8'th entry in LUT, and program 256 indexes.
|
||||
*
|
||||
* PAL_PREC_INDEX[0] and PAL_PREC_INDEX[1] map to seg2[1],
|
||||
* with seg2[0] being unused by the hardware.
|
||||
*/
|
||||
I915_WRITE(PREC_PAL_INDEX(pipe), PAL_PREC_AUTO_INCREMENT);
|
||||
for (i = 1; i < 257; i++) {
|
||||
entry = &lut[i * 8];
|
||||
I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_12p4_ldw(entry));
|
||||
I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_12p4_udw(entry));
|
||||
}
|
||||
|
||||
/*
|
||||
* Program Coarse segment (let's call it seg3)...
|
||||
*
|
||||
* Coarse segment's starts from index 0 and it's step is 1/256 ie 0,
|
||||
* 1/256, 2/256 ...256/256. As per the description of each entry in LUT
|
||||
* above, we need to pick every (8 * 128)th entry in LUT, and
|
||||
* program 256 of those.
|
||||
*
|
||||
* Spec is not very clear about if entries seg3[0] and seg3[1] are
|
||||
* being used or not, but we still need to program these to advance
|
||||
* the index.
|
||||
*/
|
||||
for (i = 0; i < 256; i++) {
|
||||
entry = &lut[i * 8 * 128];
|
||||
I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_12p4_ldw(entry));
|
||||
I915_WRITE(PREC_PAL_DATA(pipe), ilk_lut_12p4_udw(entry));
|
||||
}
|
||||
|
||||
/* The last entry in the LUT is to be programmed in GCMAX */
|
||||
entry = &lut[256 * 8 * 128];
|
||||
icl_load_gcmax(crtc_state, entry);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
}
|
||||
|
||||
static void icl_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
|
||||
@@ -775,22 +886,81 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
if (crtc_state->base.degamma_lut)
|
||||
glk_load_degamma_lut(crtc_state);
|
||||
|
||||
if ((crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) ==
|
||||
GAMMA_MODE_MODE_8BIT) {
|
||||
switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
|
||||
case GAMMA_MODE_MODE_8BIT:
|
||||
i9xx_load_luts(crtc_state);
|
||||
} else {
|
||||
break;
|
||||
|
||||
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
|
||||
icl_program_gamma_superfine_segment(crtc_state);
|
||||
icl_program_gamma_multi_segment(crtc_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
|
||||
ivb_load_lut_10_max(crtc);
|
||||
ivb_load_lut_ext_max(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color)
|
||||
{
|
||||
return drm_color_lut_extract(color->green, 14) << 16 |
|
||||
drm_color_lut_extract(color->blue, 14);
|
||||
}
|
||||
|
||||
static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
|
||||
{
|
||||
return drm_color_lut_extract(color->red, 14);
|
||||
}
|
||||
|
||||
static void chv_load_cgm_degamma(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
int i, lut_size = drm_color_lut_size(blob);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0),
|
||||
chv_cgm_degamma_ldw(&lut[i]));
|
||||
I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1),
|
||||
chv_cgm_degamma_udw(&lut[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static u32 chv_cgm_gamma_ldw(const struct drm_color_lut *color)
|
||||
{
|
||||
return drm_color_lut_extract(color->green, 10) << 16 |
|
||||
drm_color_lut_extract(color->blue, 10);
|
||||
}
|
||||
|
||||
static u32 chv_cgm_gamma_udw(const struct drm_color_lut *color)
|
||||
{
|
||||
return drm_color_lut_extract(color->red, 10);
|
||||
}
|
||||
|
||||
static void chv_load_cgm_gamma(struct intel_crtc *crtc,
|
||||
const struct drm_property_blob *blob)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_color_lut *lut = blob->data;
|
||||
int i, lut_size = drm_color_lut_size(blob);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0),
|
||||
chv_cgm_gamma_ldw(&lut[i]));
|
||||
I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1),
|
||||
chv_cgm_gamma_udw(&lut[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void chv_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||
const struct drm_property_blob *gamma_lut = crtc_state->base.gamma_lut;
|
||||
const struct drm_property_blob *degamma_lut = crtc_state->base.degamma_lut;
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
cherryview_load_csc_matrix(crtc_state);
|
||||
|
||||
@@ -799,41 +969,11 @@ static void cherryview_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (degamma_lut) {
|
||||
const struct drm_color_lut *lut = degamma_lut->data;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
if (degamma_lut)
|
||||
chv_load_cgm_degamma(crtc, degamma_lut);
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 word0, word1;
|
||||
|
||||
/* Write LUT in U0.14 format. */
|
||||
word0 =
|
||||
(drm_color_lut_extract(lut[i].green, 14) << 16) |
|
||||
drm_color_lut_extract(lut[i].blue, 14);
|
||||
word1 = drm_color_lut_extract(lut[i].red, 14);
|
||||
|
||||
I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 0), word0);
|
||||
I915_WRITE(CGM_PIPE_DEGAMMA(pipe, i, 1), word1);
|
||||
}
|
||||
}
|
||||
|
||||
if (gamma_lut) {
|
||||
const struct drm_color_lut *lut = gamma_lut->data;
|
||||
int i, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
|
||||
for (i = 0; i < lut_size; i++) {
|
||||
u32 word0, word1;
|
||||
|
||||
/* Write LUT in U0.10 format. */
|
||||
word0 =
|
||||
(drm_color_lut_extract(lut[i].green, 10) << 16) |
|
||||
drm_color_lut_extract(lut[i].blue, 10);
|
||||
word1 = drm_color_lut_extract(lut[i].red, 10);
|
||||
|
||||
I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 0), word0);
|
||||
I915_WRITE(CGM_PIPE_GAMMA(pipe, i, 1), word1);
|
||||
}
|
||||
}
|
||||
if (gamma_lut)
|
||||
chv_load_cgm_gamma(crtc, gamma_lut);
|
||||
}
|
||||
|
||||
void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
|
||||
@@ -857,6 +997,14 @@ int intel_color_check(struct intel_crtc_state *crtc_state)
|
||||
return dev_priv->display.color_check(crtc_state);
|
||||
}
|
||||
|
||||
void intel_color_get_config(struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
|
||||
|
||||
if (dev_priv->display.read_luts)
|
||||
dev_priv->display.read_luts(crtc_state);
|
||||
}
|
||||
|
||||
static bool need_plane_update(struct intel_plane *plane,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
@@ -937,8 +1085,10 @@ static int check_luts(const struct intel_crtc_state *crtc_state)
|
||||
return 0;
|
||||
|
||||
/* C8 relies on its palette being stored in the legacy LUT */
|
||||
if (crtc_state->c8_planes)
|
||||
if (crtc_state->c8_planes) {
|
||||
DRM_DEBUG_KMS("C8 pixelformat requires the legacy LUT\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size;
|
||||
gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size;
|
||||
@@ -1187,7 +1337,7 @@ static u32 icl_gamma_mode(const struct intel_crtc_state *crtc_state)
|
||||
crtc_state_is_legacy_gamma(crtc_state))
|
||||
gamma_mode |= GAMMA_MODE_MODE_8BIT;
|
||||
else
|
||||
gamma_mode |= GAMMA_MODE_MODE_10BIT;
|
||||
gamma_mode |= GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED;
|
||||
|
||||
return gamma_mode;
|
||||
}
|
||||
@@ -1232,7 +1382,7 @@ void intel_color_init(struct intel_crtc *crtc)
|
||||
if (IS_CHERRYVIEW(dev_priv)) {
|
||||
dev_priv->display.color_check = chv_color_check;
|
||||
dev_priv->display.color_commit = i9xx_color_commit;
|
||||
dev_priv->display.load_luts = cherryview_load_luts;
|
||||
dev_priv->display.load_luts = chv_load_luts;
|
||||
} else if (INTEL_GEN(dev_priv) >= 4) {
|
||||
dev_priv->display.color_check = i9xx_color_check;
|
||||
dev_priv->display.color_commit = i9xx_color_commit;
|
@@ -13,5 +13,6 @@ void intel_color_init(struct intel_crtc *crtc);
|
||||
int intel_color_check(struct intel_crtc_state *crtc_state);
|
||||
void intel_color_commit(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_load_luts(const struct intel_crtc_state *crtc_state);
|
||||
void intel_color_get_config(struct intel_crtc_state *crtc_state);
|
||||
|
||||
#endif /* __INTEL_COLOR_H__ */
|
@@ -3,6 +3,7 @@
|
||||
* Copyright © 2018 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "intel_combo_phy.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
#define for_each_combo_port(__dev_priv, __port) \
|
||||
@@ -147,7 +148,7 @@ static bool cnl_combo_phy_verify_state(struct drm_i915_private *dev_priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
static void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -167,7 +168,7 @@ void cnl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
I915_WRITE(CNL_PORT_CL1CM_DW5, val);
|
||||
}
|
||||
|
||||
void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
static void cnl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
@@ -197,13 +198,69 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
ret = cnl_verify_procmon_ref_values(dev_priv, port);
|
||||
|
||||
if (port == PORT_A)
|
||||
ret &= check_phy_reg(dev_priv, port, ICL_PORT_COMP_DW8(port),
|
||||
IREFGEN, IREFGEN);
|
||||
|
||||
ret &= check_phy_reg(dev_priv, port, ICL_PORT_CL_DW5(port),
|
||||
CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
|
||||
enum port port, bool is_dsi,
|
||||
int lane_count, bool lane_reversal)
|
||||
{
|
||||
u8 lane_mask;
|
||||
u32 val;
|
||||
|
||||
if (is_dsi) {
|
||||
WARN_ON(lane_reversal);
|
||||
|
||||
switch (lane_count) {
|
||||
case 1:
|
||||
lane_mask = PWR_DOWN_LN_3_1_0;
|
||||
break;
|
||||
case 2:
|
||||
lane_mask = PWR_DOWN_LN_3_1;
|
||||
break;
|
||||
case 3:
|
||||
lane_mask = PWR_DOWN_LN_3;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(lane_count);
|
||||
/* fall-through */
|
||||
case 4:
|
||||
lane_mask = PWR_UP_ALL_LANES;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (lane_count) {
|
||||
case 1:
|
||||
lane_mask = lane_reversal ? PWR_DOWN_LN_2_1_0 :
|
||||
PWR_DOWN_LN_3_2_1;
|
||||
break;
|
||||
case 2:
|
||||
lane_mask = lane_reversal ? PWR_DOWN_LN_1_0 :
|
||||
PWR_DOWN_LN_3_2;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(lane_count);
|
||||
/* fall-through */
|
||||
case 4:
|
||||
lane_mask = PWR_UP_ALL_LANES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val = I915_READ(ICL_PORT_CL_DW10(port));
|
||||
val &= ~PWR_DOWN_LN_MASK;
|
||||
val |= lane_mask << PWR_DOWN_LN_SHIFT;
|
||||
I915_WRITE(ICL_PORT_CL_DW10(port), val);
|
||||
}
|
||||
|
||||
static void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
@@ -222,6 +279,12 @@ void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
|
||||
cnl_set_procmon_ref_values(dev_priv, port);
|
||||
|
||||
if (port == PORT_A) {
|
||||
val = I915_READ(ICL_PORT_COMP_DW8(port));
|
||||
val |= IREFGEN;
|
||||
I915_WRITE(ICL_PORT_COMP_DW8(port), val);
|
||||
}
|
||||
|
||||
val = I915_READ(ICL_PORT_COMP_DW0(port));
|
||||
val |= COMP_INIT;
|
||||
I915_WRITE(ICL_PORT_COMP_DW0(port), val);
|
||||
@@ -232,7 +295,7 @@ void icl_combo_phys_init(struct drm_i915_private *dev_priv)
|
||||
}
|
||||
}
|
||||
|
||||
void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
static void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum port port;
|
||||
|
||||
@@ -253,3 +316,19 @@ void icl_combo_phys_uninit(struct drm_i915_private *dev_priv)
|
||||
I915_WRITE(ICL_PORT_COMP_DW0(port), val);
|
||||
}
|
||||
}
|
||||
|
||||
void intel_combo_phy_init(struct drm_i915_private *i915)
|
||||
{
|
||||
if (INTEL_GEN(i915) >= 11)
|
||||
icl_combo_phys_init(i915);
|
||||
else if (IS_CANNONLAKE(i915))
|
||||
cnl_combo_phys_init(i915);
|
||||
}
|
||||
|
||||
void intel_combo_phy_uninit(struct drm_i915_private *i915)
|
||||
{
|
||||
if (INTEL_GEN(i915) >= 11)
|
||||
icl_combo_phys_uninit(i915);
|
||||
else if (IS_CANNONLAKE(i915))
|
||||
cnl_combo_phys_uninit(i915);
|
||||
}
|
20
drivers/gpu/drm/i915/display/intel_combo_phy.h
Normal file
20
drivers/gpu/drm/i915/display/intel_combo_phy.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_COMBO_PHY_H__
|
||||
#define __INTEL_COMBO_PHY_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
void intel_combo_phy_init(struct drm_i915_private *dev_priv);
|
||||
void intel_combo_phy_uninit(struct drm_i915_private *dev_priv);
|
||||
void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv,
|
||||
enum port port, bool is_dsi,
|
||||
int lane_count, bool lane_reversal);
|
||||
|
||||
#endif /* __INTEL_COMBO_PHY_H__ */
|
@@ -29,11 +29,12 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include "display/intel_panel.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
int intel_connector_init(struct intel_connector *connector)
|
||||
{
|
@@ -39,6 +39,9 @@
|
||||
#include "intel_crt.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hotplug.h"
|
||||
|
||||
/* Here's the desired hotplug mode */
|
||||
#define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \
|
||||
@@ -640,6 +643,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
{
|
||||
struct drm_device *dev = crt->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_uncore *uncore = &dev_priv->uncore;
|
||||
u32 save_bclrpat;
|
||||
u32 save_vtotal;
|
||||
u32 vtotal, vactive;
|
||||
@@ -660,9 +664,9 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
pipeconf_reg = PIPECONF(pipe);
|
||||
pipe_dsl_reg = PIPEDSL(pipe);
|
||||
|
||||
save_bclrpat = I915_READ(bclrpat_reg);
|
||||
save_vtotal = I915_READ(vtotal_reg);
|
||||
vblank = I915_READ(vblank_reg);
|
||||
save_bclrpat = intel_uncore_read(uncore, bclrpat_reg);
|
||||
save_vtotal = intel_uncore_read(uncore, vtotal_reg);
|
||||
vblank = intel_uncore_read(uncore, vblank_reg);
|
||||
|
||||
vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
|
||||
vactive = (save_vtotal & 0x7ff) + 1;
|
||||
@@ -671,21 +675,23 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
vblank_end = ((vblank >> 16) & 0xfff) + 1;
|
||||
|
||||
/* Set the border color to purple. */
|
||||
I915_WRITE(bclrpat_reg, 0x500050);
|
||||
intel_uncore_write(uncore, bclrpat_reg, 0x500050);
|
||||
|
||||
if (!IS_GEN(dev_priv, 2)) {
|
||||
u32 pipeconf = I915_READ(pipeconf_reg);
|
||||
I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
|
||||
POSTING_READ(pipeconf_reg);
|
||||
u32 pipeconf = intel_uncore_read(uncore, pipeconf_reg);
|
||||
intel_uncore_write(uncore,
|
||||
pipeconf_reg,
|
||||
pipeconf | PIPECONF_FORCE_BORDER);
|
||||
intel_uncore_posting_read(uncore, pipeconf_reg);
|
||||
/* Wait for next Vblank to substitue
|
||||
* border color for Color info */
|
||||
intel_wait_for_vblank(dev_priv, pipe);
|
||||
st00 = I915_READ8(_VGA_MSR_WRITE);
|
||||
st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE);
|
||||
status = ((st00 & (1 << 4)) != 0) ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
|
||||
I915_WRITE(pipeconf_reg, pipeconf);
|
||||
intel_uncore_write(uncore, pipeconf_reg, pipeconf);
|
||||
} else {
|
||||
bool restore_vblank = false;
|
||||
int count, detect;
|
||||
@@ -699,9 +705,10 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
u32 vsync_start = (vsync & 0xffff) + 1;
|
||||
|
||||
vblank_start = vsync_start;
|
||||
I915_WRITE(vblank_reg,
|
||||
(vblank_start - 1) |
|
||||
((vblank_end - 1) << 16));
|
||||
intel_uncore_write(uncore,
|
||||
vblank_reg,
|
||||
(vblank_start - 1) |
|
||||
((vblank_end - 1) << 16));
|
||||
restore_vblank = true;
|
||||
}
|
||||
/* sample in the vertical border, selecting the larger one */
|
||||
@@ -713,9 +720,10 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
/*
|
||||
* Wait for the border to be displayed
|
||||
*/
|
||||
while (I915_READ(pipe_dsl_reg) >= vactive)
|
||||
while (intel_uncore_read(uncore, pipe_dsl_reg) >= vactive)
|
||||
;
|
||||
while ((dsl = I915_READ(pipe_dsl_reg)) <= vsample)
|
||||
while ((dsl = intel_uncore_read(uncore, pipe_dsl_reg)) <=
|
||||
vsample)
|
||||
;
|
||||
/*
|
||||
* Watch ST00 for an entire scanline
|
||||
@@ -725,14 +733,14 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
do {
|
||||
count++;
|
||||
/* Read the ST00 VGA status register */
|
||||
st00 = I915_READ8(_VGA_MSR_WRITE);
|
||||
st00 = intel_uncore_read8(uncore, _VGA_MSR_WRITE);
|
||||
if (st00 & (1 << 4))
|
||||
detect++;
|
||||
} while ((I915_READ(pipe_dsl_reg) == dsl));
|
||||
} while ((intel_uncore_read(uncore, pipe_dsl_reg) == dsl));
|
||||
|
||||
/* restore vblank if necessary */
|
||||
if (restore_vblank)
|
||||
I915_WRITE(vblank_reg, vblank);
|
||||
intel_uncore_write(uncore, vblank_reg, vblank);
|
||||
/*
|
||||
* If more than 3/4 of the scanline detected a monitor,
|
||||
* then it is assumed to be present. This works even on i830,
|
||||
@@ -745,7 +753,7 @@ intel_crt_load_detect(struct intel_crt *crt, u32 pipe)
|
||||
}
|
||||
|
||||
/* Restore previous settings */
|
||||
I915_WRITE(bclrpat_reg, save_bclrpat);
|
||||
intel_uncore_write(uncore, bclrpat_reg, save_bclrpat);
|
||||
|
||||
return status;
|
||||
}
|
@@ -29,16 +29,23 @@
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_combo_phy.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_lspcon.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_vdsc.h"
|
||||
|
||||
struct ddi_buf_trans {
|
||||
u32 trans1; /* balance leg enable, de-emph level */
|
||||
@@ -608,7 +615,7 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
|
||||
static const struct ddi_buf_trans *
|
||||
kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries)
|
||||
{
|
||||
if (IS_KBL_ULX(dev_priv) || IS_AML_ULX(dev_priv)) {
|
||||
if (IS_KBL_ULX(dev_priv) || IS_CFL_ULX(dev_priv)) {
|
||||
*n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp);
|
||||
return kbl_y_ddi_translations_dp;
|
||||
} else if (IS_KBL_ULT(dev_priv) || IS_CFL_ULT(dev_priv)) {
|
||||
@@ -624,7 +631,8 @@ static const struct ddi_buf_trans *
|
||||
skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
|
||||
{
|
||||
if (dev_priv->vbt.edp.low_vswing) {
|
||||
if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) || IS_AML_ULX(dev_priv)) {
|
||||
if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) ||
|
||||
IS_CFL_ULX(dev_priv)) {
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_edp);
|
||||
return skl_y_ddi_translations_edp;
|
||||
} else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv) ||
|
||||
@@ -646,7 +654,8 @@ skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
|
||||
static const struct ddi_buf_trans *
|
||||
skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries)
|
||||
{
|
||||
if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) || IS_AML_ULX(dev_priv)) {
|
||||
if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv) ||
|
||||
IS_CFL_ULX(dev_priv)) {
|
||||
*n_entries = ARRAY_SIZE(skl_y_ddi_translations_hdmi);
|
||||
return skl_y_ddi_translations_hdmi;
|
||||
} else {
|
||||
@@ -1214,19 +1223,30 @@ intel_ddi_get_crtc_encoder(struct intel_crtc *crtc)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define LC_FREQ 2700
|
||||
|
||||
static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
i915_reg_t reg)
|
||||
{
|
||||
int refclk = LC_FREQ;
|
||||
int refclk;
|
||||
int n, p, r;
|
||||
u32 wrpll;
|
||||
|
||||
wrpll = I915_READ(reg);
|
||||
switch (wrpll & WRPLL_PLL_REF_MASK) {
|
||||
case WRPLL_PLL_SSC:
|
||||
case WRPLL_PLL_NON_SSC:
|
||||
switch (wrpll & WRPLL_REF_MASK) {
|
||||
case WRPLL_REF_SPECIAL_HSW:
|
||||
/*
|
||||
* muxed-SSC for BDW.
|
||||
* non-SSC for non-ULT HSW. Check FUSE_STRAP3
|
||||
* for the non-SSC reference frequency.
|
||||
*/
|
||||
if (IS_HASWELL(dev_priv) && !IS_HSW_ULT(dev_priv)) {
|
||||
if (I915_READ(FUSE_STRAP3) & HSW_REF_CLK_SELECT)
|
||||
refclk = 24;
|
||||
else
|
||||
refclk = 135;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case WRPLL_REF_PCH_SSC:
|
||||
/*
|
||||
* We could calculate spread here, but our checking
|
||||
* code only cares about 5% accuracy, and spread is a max of
|
||||
@@ -1234,11 +1254,11 @@ static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv,
|
||||
*/
|
||||
refclk = 135;
|
||||
break;
|
||||
case WRPLL_PLL_LCPLL:
|
||||
refclk = LC_FREQ;
|
||||
case WRPLL_REF_LCPLL:
|
||||
refclk = 2700;
|
||||
break;
|
||||
default:
|
||||
WARN(1, "bad wrpll refclk\n");
|
||||
MISSING_CASE(wrpll);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1450,7 +1470,8 @@ static void ddi_dotclock_get(struct intel_crtc_state *pipe_config)
|
||||
else
|
||||
dotclock = pipe_config->port_clock;
|
||||
|
||||
if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
if (pipe_config->output_format == INTEL_OUTPUT_FORMAT_YCBCR420 &&
|
||||
!intel_crtc_has_dp_encoder(pipe_config))
|
||||
dotclock *= 2;
|
||||
|
||||
if (pipe_config->pixel_multiplier)
|
||||
@@ -1605,12 +1626,12 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder,
|
||||
link_clock = hsw_ddi_calc_wrpll_link(dev_priv, WRPLL_CTL(1));
|
||||
break;
|
||||
case PORT_CLK_SEL_SPLL:
|
||||
pll = I915_READ(SPLL_CTL) & SPLL_PLL_FREQ_MASK;
|
||||
if (pll == SPLL_PLL_FREQ_810MHz)
|
||||
pll = I915_READ(SPLL_CTL) & SPLL_FREQ_MASK;
|
||||
if (pll == SPLL_FREQ_810MHz)
|
||||
link_clock = 81000;
|
||||
else if (pll == SPLL_PLL_FREQ_1350MHz)
|
||||
else if (pll == SPLL_FREQ_1350MHz)
|
||||
link_clock = 135000;
|
||||
else if (pll == SPLL_PLL_FREQ_2700MHz)
|
||||
else if (pll == SPLL_FREQ_2700MHz)
|
||||
link_clock = 270000;
|
||||
else {
|
||||
WARN(1, "bad spll freq\n");
|
||||
@@ -1710,6 +1731,14 @@ void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state)
|
||||
*/
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444)
|
||||
temp |= TRANS_MSA_SAMPLING_444 | TRANS_MSA_CLRSP_YCBCR;
|
||||
/*
|
||||
* As per DP 1.4a spec section 2.2.4.3 [MSA Field for Indication
|
||||
* of Color Encoding Format and Content Color Gamut] while sending
|
||||
* YCBCR 420 signals we should program MSA MISC1 fields which
|
||||
* indicate VSC SDP for the Pixel Encoding/Colorimetry Format.
|
||||
*/
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
temp |= TRANS_MSA_USE_VSC_SDP;
|
||||
I915_WRITE(TRANS_MSA_MISC(cpu_transcoder), temp);
|
||||
}
|
||||
|
||||
@@ -1772,9 +1801,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)
|
||||
* eDP when not using the panel fitter, and when not
|
||||
* using motion blur mitigation (which we don't
|
||||
* support). */
|
||||
if (IS_HASWELL(dev_priv) &&
|
||||
(crtc_state->pch_pfit.enabled ||
|
||||
crtc_state->pch_pfit.force_thru))
|
||||
if (crtc_state->pch_pfit.force_thru)
|
||||
temp |= TRANS_DDI_EDP_INPUT_A_ONOFF;
|
||||
else
|
||||
temp |= TRANS_DDI_EDP_INPUT_A_ON;
|
||||
@@ -3111,6 +3138,15 @@ static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
|
||||
else
|
||||
intel_prepare_dp_ddi_buffers(encoder, crtc_state);
|
||||
|
||||
if (intel_port_is_combophy(dev_priv, port)) {
|
||||
bool lane_reversal =
|
||||
dig_port->saved_port_bits & DDI_BUF_PORT_REVERSAL;
|
||||
|
||||
intel_combo_phy_power_up_lanes(dev_priv, port, false,
|
||||
crtc_state->lane_count,
|
||||
lane_reversal);
|
||||
}
|
||||
|
||||
intel_ddi_init_dp_buf_reg(encoder);
|
||||
if (!is_mst)
|
||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
|
||||
@@ -3375,6 +3411,7 @@ static void intel_enable_ddi_dp(struct intel_encoder *encoder,
|
||||
|
||||
intel_edp_backlight_on(crtc_state, conn_state);
|
||||
intel_psr_enable(intel_dp, crtc_state);
|
||||
intel_dp_ycbcr_420_enable(intel_dp, crtc_state);
|
||||
intel_edp_drrs_enable(intel_dp, crtc_state);
|
||||
|
||||
if (crtc_state->has_audio)
|
||||
@@ -3626,7 +3663,7 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,
|
||||
intel_ddi_main_link_aux_domain(dig_port));
|
||||
}
|
||||
|
||||
void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
|
||||
static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv =
|
||||
@@ -3820,6 +3857,9 @@ void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
intel_read_infoframe(encoder, pipe_config,
|
||||
HDMI_INFOFRAME_TYPE_VENDOR,
|
||||
&pipe_config->infoframes.hdmi);
|
||||
intel_read_infoframe(encoder, pipe_config,
|
||||
HDMI_INFOFRAME_TYPE_DRM,
|
||||
&pipe_config->infoframes.drm);
|
||||
}
|
||||
|
||||
static enum intel_output_type
|
||||
@@ -3844,6 +3884,7 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
enum port port = encoder->port;
|
||||
int ret;
|
||||
@@ -3858,6 +3899,12 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (IS_HASWELL(dev_priv) && crtc->pipe == PIPE_A &&
|
||||
pipe_config->cpu_transcoder == TRANSCODER_EDP)
|
||||
pipe_config->pch_pfit.force_thru =
|
||||
pipe_config->pch_pfit.enabled ||
|
||||
pipe_config->crc_enabled;
|
||||
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
pipe_config->lane_lat_optim_mask =
|
||||
bxt_ddi_phy_calc_lane_lat_optim_mask(pipe_config->lane_count);
|
||||
@@ -3865,7 +3912,6 @@ static int intel_ddi_compute_config(struct intel_encoder *encoder,
|
||||
intel_ddi_compute_min_voltage_level(dev_priv, pipe_config);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void intel_ddi_encoder_suspend(struct intel_encoder *encoder)
|
||||
@@ -3925,6 +3971,9 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
|
||||
return NULL;
|
||||
|
||||
intel_dig_port->dp.output_reg = DDI_BUF_CTL(port);
|
||||
intel_dig_port->dp.prepare_link_retrain =
|
||||
intel_ddi_prepare_link_retrain;
|
||||
|
||||
if (!intel_dp_init_connector(intel_dig_port, connector)) {
|
||||
kfree(connector);
|
||||
return NULL;
|
@@ -31,7 +31,6 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state
|
||||
void intel_ddi_enable_pipe_clock(const struct intel_crtc_state *crtc_state);
|
||||
void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state);
|
||||
void intel_ddi_set_pipe_settings(const struct intel_crtc_state *crtc_state);
|
||||
void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp);
|
||||
bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector);
|
||||
void intel_ddi_get_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config);
|
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,9 @@
|
||||
#include <drm/drm_util.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_plane_state;
|
||||
|
||||
enum i915_gpio {
|
||||
GPIOA,
|
||||
GPIOB,
|
||||
@@ -217,64 +220,6 @@ enum aux_ch {
|
||||
|
||||
#define aux_ch_name(a) ((a) + 'A')
|
||||
|
||||
enum intel_display_power_domain {
|
||||
POWER_DOMAIN_PIPE_A,
|
||||
POWER_DOMAIN_PIPE_B,
|
||||
POWER_DOMAIN_PIPE_C,
|
||||
POWER_DOMAIN_PIPE_A_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_B_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_C_PANEL_FITTER,
|
||||
POWER_DOMAIN_TRANSCODER_A,
|
||||
POWER_DOMAIN_TRANSCODER_B,
|
||||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_EDP,
|
||||
POWER_DOMAIN_TRANSCODER_EDP_VDSC,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_A,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_C,
|
||||
POWER_DOMAIN_PORT_DDI_A_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_B_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_C_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_D_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_E_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_F_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_A_IO,
|
||||
POWER_DOMAIN_PORT_DDI_B_IO,
|
||||
POWER_DOMAIN_PORT_DDI_C_IO,
|
||||
POWER_DOMAIN_PORT_DDI_D_IO,
|
||||
POWER_DOMAIN_PORT_DDI_E_IO,
|
||||
POWER_DOMAIN_PORT_DDI_F_IO,
|
||||
POWER_DOMAIN_PORT_DSI,
|
||||
POWER_DOMAIN_PORT_CRT,
|
||||
POWER_DOMAIN_PORT_OTHER,
|
||||
POWER_DOMAIN_VGA,
|
||||
POWER_DOMAIN_AUDIO,
|
||||
POWER_DOMAIN_PLLS,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_AUX_C,
|
||||
POWER_DOMAIN_AUX_D,
|
||||
POWER_DOMAIN_AUX_E,
|
||||
POWER_DOMAIN_AUX_F,
|
||||
POWER_DOMAIN_AUX_IO_A,
|
||||
POWER_DOMAIN_AUX_TBT1,
|
||||
POWER_DOMAIN_AUX_TBT2,
|
||||
POWER_DOMAIN_AUX_TBT3,
|
||||
POWER_DOMAIN_AUX_TBT4,
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_INIT,
|
||||
|
||||
POWER_DOMAIN_NUM,
|
||||
};
|
||||
|
||||
#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
|
||||
#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
|
||||
((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
|
||||
#define POWER_DOMAIN_TRANSCODER(tran) \
|
||||
((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
|
||||
(tran) + POWER_DOMAIN_TRANSCODER_A)
|
||||
|
||||
/* Used by dp and fdi links */
|
||||
struct intel_link_m_n {
|
||||
u32 tu;
|
||||
@@ -361,30 +306,6 @@ struct intel_link_m_n {
|
||||
list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
|
||||
for_each_if((intel_connector)->base.encoder == (__encoder))
|
||||
|
||||
#define for_each_power_domain(domain, mask) \
|
||||
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
|
||||
for_each_if(BIT_ULL(domain) & (mask))
|
||||
|
||||
#define for_each_power_well(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells < \
|
||||
(__dev_priv)->power_domains.power_well_count; \
|
||||
(__power_well)++)
|
||||
|
||||
#define for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells + \
|
||||
(__dev_priv)->power_domains.power_well_count - 1; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells >= 0; \
|
||||
(__power_well)--)
|
||||
|
||||
#define for_each_power_domain_well(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
#define for_each_power_domain_well_reverse(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
#define for_each_old_intel_plane_in_state(__state, plane, old_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
|
||||
@@ -432,4 +353,9 @@ void intel_link_compute_m_n(u16 bpp, int nlanes,
|
||||
struct intel_link_m_n *m_n,
|
||||
bool constant_n);
|
||||
bool is_ccs_modifier(u64 modifier);
|
||||
void lpt_disable_clkout_dp(struct drm_i915_private *dev_priv);
|
||||
u32 intel_plane_fb_max_stride(struct drm_i915_private *dev_priv,
|
||||
u32 pixel_format, u64 modifier);
|
||||
bool intel_plane_can_remap(const struct intel_plane_state *plane_state);
|
||||
|
||||
#endif
|
4618
drivers/gpu/drm/i915/display/intel_display_power.c
Normal file
4618
drivers/gpu/drm/i915/display/intel_display_power.c
Normal file
File diff suppressed because it is too large
Load Diff
288
drivers/gpu/drm/i915/display/intel_display_power.h
Normal file
288
drivers/gpu/drm/i915/display/intel_display_power.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DISPLAY_POWER_H__
|
||||
#define __INTEL_DISPLAY_POWER_H__
|
||||
|
||||
#include "intel_display.h"
|
||||
#include "intel_runtime_pm.h"
|
||||
#include "i915_reg.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_encoder;
|
||||
|
||||
enum intel_display_power_domain {
|
||||
POWER_DOMAIN_DISPLAY_CORE,
|
||||
POWER_DOMAIN_PIPE_A,
|
||||
POWER_DOMAIN_PIPE_B,
|
||||
POWER_DOMAIN_PIPE_C,
|
||||
POWER_DOMAIN_PIPE_A_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_B_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_C_PANEL_FITTER,
|
||||
POWER_DOMAIN_TRANSCODER_A,
|
||||
POWER_DOMAIN_TRANSCODER_B,
|
||||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_EDP,
|
||||
POWER_DOMAIN_TRANSCODER_EDP_VDSC,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_A,
|
||||
POWER_DOMAIN_TRANSCODER_DSI_C,
|
||||
POWER_DOMAIN_PORT_DDI_A_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_B_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_C_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_D_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_E_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_F_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_A_IO,
|
||||
POWER_DOMAIN_PORT_DDI_B_IO,
|
||||
POWER_DOMAIN_PORT_DDI_C_IO,
|
||||
POWER_DOMAIN_PORT_DDI_D_IO,
|
||||
POWER_DOMAIN_PORT_DDI_E_IO,
|
||||
POWER_DOMAIN_PORT_DDI_F_IO,
|
||||
POWER_DOMAIN_PORT_DSI,
|
||||
POWER_DOMAIN_PORT_CRT,
|
||||
POWER_DOMAIN_PORT_OTHER,
|
||||
POWER_DOMAIN_VGA,
|
||||
POWER_DOMAIN_AUDIO,
|
||||
POWER_DOMAIN_AUX_A,
|
||||
POWER_DOMAIN_AUX_B,
|
||||
POWER_DOMAIN_AUX_C,
|
||||
POWER_DOMAIN_AUX_D,
|
||||
POWER_DOMAIN_AUX_E,
|
||||
POWER_DOMAIN_AUX_F,
|
||||
POWER_DOMAIN_AUX_IO_A,
|
||||
POWER_DOMAIN_AUX_TBT1,
|
||||
POWER_DOMAIN_AUX_TBT2,
|
||||
POWER_DOMAIN_AUX_TBT3,
|
||||
POWER_DOMAIN_AUX_TBT4,
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_GT_IRQ,
|
||||
POWER_DOMAIN_INIT,
|
||||
|
||||
POWER_DOMAIN_NUM,
|
||||
};
|
||||
|
||||
#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
|
||||
#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
|
||||
((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
|
||||
#define POWER_DOMAIN_TRANSCODER(tran) \
|
||||
((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \
|
||||
(tran) + POWER_DOMAIN_TRANSCODER_A)
|
||||
|
||||
struct i915_power_well;
|
||||
|
||||
struct i915_power_well_ops {
|
||||
/*
|
||||
* Synchronize the well's hw state to match the current sw state, for
|
||||
* example enable/disable it based on the current refcount. Called
|
||||
* during driver init and resume time, possibly after first calling
|
||||
* the enable/disable handlers.
|
||||
*/
|
||||
void (*sync_hw)(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well);
|
||||
/*
|
||||
* Enable the well and resources that depend on it (for example
|
||||
* interrupts located on the well). Called after the 0->1 refcount
|
||||
* transition.
|
||||
*/
|
||||
void (*enable)(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well);
|
||||
/*
|
||||
* Disable the well and resources that depend on it. Called after
|
||||
* the 1->0 refcount transition.
|
||||
*/
|
||||
void (*disable)(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well);
|
||||
/* Returns the hw enabled state. */
|
||||
bool (*is_enabled)(struct drm_i915_private *dev_priv,
|
||||
struct i915_power_well *power_well);
|
||||
};
|
||||
|
||||
struct i915_power_well_regs {
|
||||
i915_reg_t bios;
|
||||
i915_reg_t driver;
|
||||
i915_reg_t kvmr;
|
||||
i915_reg_t debug;
|
||||
};
|
||||
|
||||
/* Power well structure for haswell */
|
||||
struct i915_power_well_desc {
|
||||
const char *name;
|
||||
bool always_on;
|
||||
u64 domains;
|
||||
/* unique identifier for this power well */
|
||||
enum i915_power_well_id id;
|
||||
/*
|
||||
* Arbitraty data associated with this power well. Platform and power
|
||||
* well specific.
|
||||
*/
|
||||
union {
|
||||
struct {
|
||||
/*
|
||||
* request/status flag index in the PUNIT power well
|
||||
* control/status registers.
|
||||
*/
|
||||
u8 idx;
|
||||
} vlv;
|
||||
struct {
|
||||
enum dpio_phy phy;
|
||||
} bxt;
|
||||
struct {
|
||||
const struct i915_power_well_regs *regs;
|
||||
/*
|
||||
* request/status flag index in the power well
|
||||
* constrol/status registers.
|
||||
*/
|
||||
u8 idx;
|
||||
/* Mask of pipes whose IRQ logic is backed by the pw */
|
||||
u8 irq_pipe_mask;
|
||||
/* The pw is backing the VGA functionality */
|
||||
bool has_vga:1;
|
||||
bool has_fuses:1;
|
||||
/*
|
||||
* The pw is for an ICL+ TypeC PHY port in
|
||||
* Thunderbolt mode.
|
||||
*/
|
||||
bool is_tc_tbt:1;
|
||||
} hsw;
|
||||
};
|
||||
const struct i915_power_well_ops *ops;
|
||||
};
|
||||
|
||||
struct i915_power_well {
|
||||
const struct i915_power_well_desc *desc;
|
||||
/* power well enable/disable usage count */
|
||||
int count;
|
||||
/* cached hw enabled state */
|
||||
bool hw_enabled;
|
||||
};
|
||||
|
||||
struct i915_power_domains {
|
||||
/*
|
||||
* Power wells needed for initialization at driver init and suspend
|
||||
* time are on. They are kept on until after the first modeset.
|
||||
*/
|
||||
bool initializing;
|
||||
bool display_core_suspended;
|
||||
int power_well_count;
|
||||
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
struct mutex lock;
|
||||
int domain_use_count[POWER_DOMAIN_NUM];
|
||||
|
||||
struct delayed_work async_put_work;
|
||||
intel_wakeref_t async_put_wakeref;
|
||||
u64 async_put_domains[2];
|
||||
|
||||
struct i915_power_well *power_wells;
|
||||
};
|
||||
|
||||
#define for_each_power_domain(domain, mask) \
|
||||
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
|
||||
for_each_if(BIT_ULL(domain) & (mask))
|
||||
|
||||
#define for_each_power_well(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells < \
|
||||
(__dev_priv)->power_domains.power_well_count; \
|
||||
(__power_well)++)
|
||||
|
||||
#define for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for ((__power_well) = (__dev_priv)->power_domains.power_wells + \
|
||||
(__dev_priv)->power_domains.power_well_count - 1; \
|
||||
(__power_well) - (__dev_priv)->power_domains.power_wells >= 0; \
|
||||
(__power_well)--)
|
||||
|
||||
#define for_each_power_domain_well(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
#define for_each_power_domain_well_reverse(__dev_priv, __power_well, __domain_mask) \
|
||||
for_each_power_well_reverse(__dev_priv, __power_well) \
|
||||
for_each_if((__power_well)->desc->domains & (__domain_mask))
|
||||
|
||||
void skl_enable_dc6(struct drm_i915_private *dev_priv);
|
||||
void gen9_sanitize_dc_state(struct drm_i915_private *dev_priv);
|
||||
void bxt_enable_dc9(struct drm_i915_private *dev_priv);
|
||||
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
|
||||
void gen9_enable_dc5(struct drm_i915_private *dev_priv);
|
||||
|
||||
int intel_power_domains_init(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_cleanup(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume);
|
||||
void intel_power_domains_fini_hw(struct drm_i915_private *dev_priv);
|
||||
void icl_display_core_init(struct drm_i915_private *dev_priv, bool resume);
|
||||
void icl_display_core_uninit(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_enable(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_disable(struct drm_i915_private *dev_priv);
|
||||
void intel_power_domains_suspend(struct drm_i915_private *dev_priv,
|
||||
enum i915_drm_suspend_mode);
|
||||
void intel_power_domains_resume(struct drm_i915_private *dev_priv);
|
||||
void hsw_enable_pc8(struct drm_i915_private *dev_priv);
|
||||
void hsw_disable_pc8(struct drm_i915_private *dev_priv);
|
||||
void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume);
|
||||
void bxt_display_core_uninit(struct drm_i915_private *dev_priv);
|
||||
|
||||
const char *
|
||||
intel_display_power_domain_str(enum intel_display_power_domain domain);
|
||||
|
||||
bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
intel_wakeref_t
|
||||
intel_display_power_get_if_enabled(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
void intel_display_power_put_unchecked(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain);
|
||||
void __intel_display_power_put_async(struct drm_i915_private *i915,
|
||||
enum intel_display_power_domain domain,
|
||||
intel_wakeref_t wakeref);
|
||||
void intel_display_power_flush_work(struct drm_i915_private *i915);
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
|
||||
void intel_display_power_put(struct drm_i915_private *dev_priv,
|
||||
enum intel_display_power_domain domain,
|
||||
intel_wakeref_t wakeref);
|
||||
static inline void
|
||||
intel_display_power_put_async(struct drm_i915_private *i915,
|
||||
enum intel_display_power_domain domain,
|
||||
intel_wakeref_t wakeref)
|
||||
{
|
||||
__intel_display_power_put_async(i915, domain, wakeref);
|
||||
}
|
||||
#else
|
||||
static inline void
|
||||
intel_display_power_put(struct drm_i915_private *i915,
|
||||
enum intel_display_power_domain domain,
|
||||
intel_wakeref_t wakeref)
|
||||
{
|
||||
intel_display_power_put_unchecked(i915, domain);
|
||||
}
|
||||
|
||||
static inline void
|
||||
intel_display_power_put_async(struct drm_i915_private *i915,
|
||||
enum intel_display_power_domain domain,
|
||||
intel_wakeref_t wakeref)
|
||||
{
|
||||
__intel_display_power_put_async(i915, domain, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define with_intel_display_power(i915, domain, wf) \
|
||||
for ((wf) = intel_display_power_get((i915), (domain)); (wf); \
|
||||
intel_display_power_put_async((i915), (domain), (wf)), (wf) = 0)
|
||||
|
||||
void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,
|
||||
u8 req_slices);
|
||||
|
||||
void chv_phy_powergate_lanes(struct intel_encoder *encoder,
|
||||
bool override, unsigned int mask);
|
||||
bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy,
|
||||
enum dpio_channel ch, bool override);
|
||||
|
||||
#endif /* __INTEL_DISPLAY_POWER_H__ */
|
@@ -31,6 +31,7 @@
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
@@ -41,18 +42,27 @@
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_debugfs.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_lspcon.h"
|
||||
#include "intel_lvds.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sideband.h"
|
||||
#include "intel_vdsc.h"
|
||||
|
||||
#define DP_DPRX_ESI_LEN 14
|
||||
|
||||
@@ -206,14 +216,17 @@ static int intel_dp_get_fia_supported_lane_count(struct intel_dp *intel_dp)
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
|
||||
enum tc_port tc_port = intel_port_to_tc(dev_priv, dig_port->base.port);
|
||||
intel_wakeref_t wakeref;
|
||||
u32 lane_info;
|
||||
|
||||
if (tc_port == PORT_TC_NONE || dig_port->tc_type != TC_PORT_TYPEC)
|
||||
return 4;
|
||||
|
||||
lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
|
||||
DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
|
||||
DP_LANE_ASSIGNMENT_SHIFT(tc_port);
|
||||
lane_info = 0;
|
||||
with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
|
||||
lane_info = (I915_READ(PORT_TX_DFLEXDPSP) &
|
||||
DP_LANE_ASSIGNMENT_MASK(tc_port)) >>
|
||||
DP_LANE_ASSIGNMENT_SHIFT(tc_port);
|
||||
|
||||
switch (lane_info) {
|
||||
default:
|
||||
@@ -319,6 +332,7 @@ static int icl_max_source_rate(struct intel_dp *intel_dp)
|
||||
enum port port = dig_port->base.port;
|
||||
|
||||
if (intel_port_is_combophy(dev_priv, port) &&
|
||||
!IS_ELKHARTLAKE(dev_priv) &&
|
||||
!intel_dp_is_edp(intel_dp))
|
||||
return 540000;
|
||||
|
||||
@@ -1068,13 +1082,13 @@ intel_dp_check_edp(struct intel_dp *intel_dp)
|
||||
static u32
|
||||
intel_dp_aux_wait_done(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct drm_i915_private *i915 = dp_to_i915(intel_dp);
|
||||
i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
|
||||
u32 status;
|
||||
bool done;
|
||||
|
||||
#define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
|
||||
done = wait_event_timeout(dev_priv->gmbus_wait_queue, C,
|
||||
#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
|
||||
done = wait_event_timeout(i915->gmbus_wait_queue, C,
|
||||
msecs_to_jiffies_timeout(10));
|
||||
|
||||
/* just trace the final value */
|
||||
@@ -1207,11 +1221,15 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
|
||||
u32 aux_send_ctl_flags)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv =
|
||||
struct drm_i915_private *i915 =
|
||||
to_i915(intel_dig_port->base.base.dev);
|
||||
struct intel_uncore *uncore = &i915->uncore;
|
||||
i915_reg_t ch_ctl, ch_data[5];
|
||||
u32 aux_clock_divider;
|
||||
intel_wakeref_t wakeref;
|
||||
enum intel_display_power_domain aux_domain =
|
||||
intel_aux_power_domain(intel_dig_port);
|
||||
intel_wakeref_t aux_wakeref;
|
||||
intel_wakeref_t pps_wakeref;
|
||||
int i, ret, recv_bytes;
|
||||
int try, clock = 0;
|
||||
u32 status;
|
||||
@@ -1221,7 +1239,8 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
|
||||
for (i = 0; i < ARRAY_SIZE(ch_data); i++)
|
||||
ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
|
||||
|
||||
wakeref = pps_lock(intel_dp);
|
||||
aux_wakeref = intel_display_power_get(i915, aux_domain);
|
||||
pps_wakeref = pps_lock(intel_dp);
|
||||
|
||||
/*
|
||||
* We will be called with VDD already enabled for dpcd/edid/oui reads.
|
||||
@@ -1235,13 +1254,13 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
|
||||
* lowest possible wakeup latency and so prevent the cpu from going into
|
||||
* deep sleep states.
|
||||
*/
|
||||
pm_qos_update_request(&dev_priv->pm_qos, 0);
|
||||
pm_qos_update_request(&i915->pm_qos, 0);
|
||||
|
||||
intel_dp_check_edp(intel_dp);
|
||||
|
||||
/* Try to wait for any previous AUX channel activity */
|
||||
for (try = 0; try < 3; try++) {
|
||||
status = I915_READ_NOTRACE(ch_ctl);
|
||||
status = intel_uncore_read_notrace(uncore, ch_ctl);
|
||||
if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
|
||||
break;
|
||||
msleep(1);
|
||||
@@ -1251,7 +1270,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
|
||||
|
||||
if (try == 3) {
|
||||
static u32 last_status = -1;
|
||||
const u32 status = I915_READ(ch_ctl);
|
||||
const u32 status = intel_uncore_read(uncore, ch_ctl);
|
||||
|
||||
if (status != last_status) {
|
||||
WARN(1, "dp_aux_ch not started status 0x%08x\n",
|
||||
@@ -1280,21 +1299,23 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
|
||||
for (try = 0; try < 5; try++) {
|
||||
/* Load the send data into the aux channel data registers */
|
||||
for (i = 0; i < send_bytes; i += 4)
|
||||
I915_WRITE(ch_data[i >> 2],
|
||||
intel_dp_pack_aux(send + i,
|
||||
send_bytes - i));
|
||||
intel_uncore_write(uncore,
|
||||
ch_data[i >> 2],
|
||||
intel_dp_pack_aux(send + i,
|
||||
send_bytes - i));
|
||||
|
||||
/* Send the command and wait for it to complete */
|
||||
I915_WRITE(ch_ctl, send_ctl);
|
||||
intel_uncore_write(uncore, ch_ctl, send_ctl);
|
||||
|
||||
status = intel_dp_aux_wait_done(intel_dp);
|
||||
|
||||
/* Clear done status and any errors */
|
||||
I915_WRITE(ch_ctl,
|
||||
status |
|
||||
DP_AUX_CH_CTL_DONE |
|
||||
DP_AUX_CH_CTL_TIME_OUT_ERROR |
|
||||
DP_AUX_CH_CTL_RECEIVE_ERROR);
|
||||
intel_uncore_write(uncore,
|
||||
ch_ctl,
|
||||
status |
|
||||
DP_AUX_CH_CTL_DONE |
|
||||
DP_AUX_CH_CTL_TIME_OUT_ERROR |
|
||||
DP_AUX_CH_CTL_RECEIVE_ERROR);
|
||||
|
||||
/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
|
||||
* 400us delay required for errors and timeouts
|
||||
@@ -1357,17 +1378,18 @@ done:
|
||||
recv_bytes = recv_size;
|
||||
|
||||
for (i = 0; i < recv_bytes; i += 4)
|
||||
intel_dp_unpack_aux(I915_READ(ch_data[i >> 2]),
|
||||
intel_dp_unpack_aux(intel_uncore_read(uncore, ch_data[i >> 2]),
|
||||
recv + i, recv_bytes - i);
|
||||
|
||||
ret = recv_bytes;
|
||||
out:
|
||||
pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
pm_qos_update_request(&i915->pm_qos, PM_QOS_DEFAULT_VALUE);
|
||||
|
||||
if (vdd)
|
||||
edp_panel_vdd_off(intel_dp, false);
|
||||
|
||||
pps_unlock(intel_dp, wakeref);
|
||||
pps_unlock(intel_dp, pps_wakeref);
|
||||
intel_display_power_put_async(i915, aux_domain, aux_wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1832,6 +1854,19 @@ intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_dp_output_bpp(const struct intel_crtc_state *crtc_state, int bpp)
|
||||
{
|
||||
/*
|
||||
* bpp value was assumed to RGB format. And YCbCr 4:2:0 output
|
||||
* format of the number of bytes per pixel will be half the number
|
||||
* of bytes of RGB pixel.
|
||||
*/
|
||||
if (crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
bpp /= 2;
|
||||
|
||||
return bpp;
|
||||
}
|
||||
|
||||
/* Optimize link config in order: max bpp, min clock, min lanes */
|
||||
static int
|
||||
intel_dp_compute_link_config_wide(struct intel_dp *intel_dp,
|
||||
@@ -2075,6 +2110,36 @@ intel_dp_compute_link_config(struct intel_encoder *encoder,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_dp_ycbcr420_config(struct intel_dp *intel_dp,
|
||||
struct drm_connector *connector,
|
||||
struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->display_info;
|
||||
const struct drm_display_mode *adjusted_mode =
|
||||
&crtc_state->base.adjusted_mode;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
|
||||
int ret;
|
||||
|
||||
if (!drm_mode_is_420_only(info, adjusted_mode) ||
|
||||
!intel_dp_get_colorimetry_status(intel_dp) ||
|
||||
!connector->ycbcr_420_allowed)
|
||||
return 0;
|
||||
|
||||
crtc_state->output_format = INTEL_OUTPUT_FORMAT_YCBCR420;
|
||||
|
||||
/* YCBCR 420 output conversion needs a scaler */
|
||||
ret = skl_update_scaler_crtc(crtc_state);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("Scaler allocation for output failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
intel_pch_panel_fitting(crtc, crtc_state, DRM_MODE_SCALE_FULLSCREEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool intel_dp_limited_color_range(const struct intel_crtc_state *crtc_state,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
@@ -2114,7 +2179,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
to_intel_digital_connector_state(conn_state);
|
||||
bool constant_n = drm_dp_has_quirk(&intel_dp->desc,
|
||||
DP_DPCD_QUIRK_CONSTANT_N);
|
||||
int ret, output_bpp;
|
||||
int ret = 0, output_bpp;
|
||||
|
||||
if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A)
|
||||
pipe_config->has_pch_encoder = true;
|
||||
@@ -2122,6 +2187,12 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
|
||||
if (lspcon->active)
|
||||
lspcon_ycbcr420_config(&intel_connector->base, pipe_config);
|
||||
else
|
||||
ret = intel_dp_ycbcr420_config(intel_dp, &intel_connector->base,
|
||||
pipe_config);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pipe_config->has_drrs = false;
|
||||
if (IS_G4X(dev_priv) || port == PORT_A)
|
||||
@@ -2169,7 +2240,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
if (pipe_config->dsc_params.compression_enable)
|
||||
output_bpp = pipe_config->dsc_params.compressed_bpp;
|
||||
else
|
||||
output_bpp = pipe_config->pipe_bpp;
|
||||
output_bpp = intel_dp_output_bpp(pipe_config, pipe_config->pipe_bpp);
|
||||
|
||||
intel_link_compute_m_n(output_bpp,
|
||||
pipe_config->lane_count,
|
||||
@@ -3148,12 +3219,12 @@ static void chv_post_disable_dp(struct intel_encoder *encoder,
|
||||
|
||||
intel_dp_link_down(encoder, old_crtc_state);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, old_crtc_state, true);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -3927,9 +3998,6 @@ intel_dp_link_down(struct intel_encoder *encoder,
|
||||
enum port port = encoder->port;
|
||||
u32 DP = intel_dp->DP;
|
||||
|
||||
if (WARN_ON(HAS_DDI(dev_priv)))
|
||||
return;
|
||||
|
||||
if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0))
|
||||
return;
|
||||
|
||||
@@ -4041,6 +4109,16 @@ intel_dp_read_dpcd(struct intel_dp *intel_dp)
|
||||
return intel_dp->dpcd[DP_DPCD_REV] != 0;
|
||||
}
|
||||
|
||||
bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
u8 dprx = 0;
|
||||
|
||||
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
|
||||
&dprx) != 1)
|
||||
return false;
|
||||
return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
|
||||
}
|
||||
|
||||
static void intel_dp_get_dsc_sink_cap(struct intel_dp *intel_dp)
|
||||
{
|
||||
/*
|
||||
@@ -4351,6 +4429,96 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_pixel_encoding_setup_vsc(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct dp_sdp vsc_sdp = {};
|
||||
|
||||
/* Prepare VSC Header for SU as per DP 1.4a spec, Table 2-119 */
|
||||
vsc_sdp.sdp_header.HB0 = 0;
|
||||
vsc_sdp.sdp_header.HB1 = 0x7;
|
||||
|
||||
/*
|
||||
* VSC SDP supporting 3D stereo, PSR2, and Pixel Encoding/
|
||||
* Colorimetry Format indication.
|
||||
*/
|
||||
vsc_sdp.sdp_header.HB2 = 0x5;
|
||||
|
||||
/*
|
||||
* VSC SDP supporting 3D stereo, + PSR2, + Pixel Encoding/
|
||||
* Colorimetry Format indication (HB2 = 05h).
|
||||
*/
|
||||
vsc_sdp.sdp_header.HB3 = 0x13;
|
||||
|
||||
/*
|
||||
* YCbCr 420 = 3h DB16[7:4] ITU-R BT.601 = 0h, ITU-R BT.709 = 1h
|
||||
* DB16[3:0] DP 1.4a spec, Table 2-120
|
||||
*/
|
||||
vsc_sdp.db[16] = 0x3 << 4; /* 0x3 << 4 , YCbCr 420*/
|
||||
/* RGB->YCBCR color conversion uses the BT.709 color space. */
|
||||
vsc_sdp.db[16] |= 0x1; /* 0x1, ITU-R BT.709 */
|
||||
|
||||
/*
|
||||
* For pixel encoding formats YCbCr444, YCbCr422, YCbCr420, and Y Only,
|
||||
* the following Component Bit Depth values are defined:
|
||||
* 001b = 8bpc.
|
||||
* 010b = 10bpc.
|
||||
* 011b = 12bpc.
|
||||
* 100b = 16bpc.
|
||||
*/
|
||||
switch (crtc_state->pipe_bpp) {
|
||||
case 24: /* 8bpc */
|
||||
vsc_sdp.db[17] = 0x1;
|
||||
break;
|
||||
case 30: /* 10bpc */
|
||||
vsc_sdp.db[17] = 0x2;
|
||||
break;
|
||||
case 36: /* 12bpc */
|
||||
vsc_sdp.db[17] = 0x3;
|
||||
break;
|
||||
case 48: /* 16bpc */
|
||||
vsc_sdp.db[17] = 0x4;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(crtc_state->pipe_bpp);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Dynamic Range (Bit 7)
|
||||
* 0 = VESA range, 1 = CTA range.
|
||||
* all YCbCr are always limited range
|
||||
*/
|
||||
vsc_sdp.db[17] |= 0x80;
|
||||
|
||||
/*
|
||||
* Content Type (Bits 2:0)
|
||||
* 000b = Not defined.
|
||||
* 001b = Graphics.
|
||||
* 010b = Photo.
|
||||
* 011b = Video.
|
||||
* 100b = Game
|
||||
* All other values are RESERVED.
|
||||
* Note: See CTA-861-G for the definition and expected
|
||||
* processing by a stream sink for the above contect types.
|
||||
*/
|
||||
vsc_sdp.db[18] = 0;
|
||||
|
||||
intel_dig_port->write_infoframe(&intel_dig_port->base,
|
||||
crtc_state, DP_SDP_VSC, &vsc_sdp, sizeof(vsc_sdp));
|
||||
}
|
||||
|
||||
void intel_dp_ycbcr_420_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
|
||||
return;
|
||||
|
||||
intel_pixel_encoding_setup_vsc(intel_dp, crtc_state);
|
||||
}
|
||||
|
||||
static u8 intel_dp_autotest_link_training(struct intel_dp *intel_dp)
|
||||
{
|
||||
int status = 0;
|
||||
@@ -4829,15 +4997,15 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
|
||||
u8 *dpcd = intel_dp->dpcd;
|
||||
u8 type;
|
||||
|
||||
if (WARN_ON(intel_dp_is_edp(intel_dp)))
|
||||
return connector_status_connected;
|
||||
|
||||
if (lspcon->active)
|
||||
lspcon_resume(lspcon);
|
||||
|
||||
if (!intel_dp_get_dpcd(intel_dp))
|
||||
return connector_status_disconnected;
|
||||
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
return connector_status_connected;
|
||||
|
||||
/* if there's no downstream port, we're done */
|
||||
if (!drm_dp_is_branch(dpcd))
|
||||
return connector_status_connected;
|
||||
@@ -5219,12 +5387,15 @@ static bool icl_tc_port_connected(struct drm_i915_private *dev_priv,
|
||||
u32 dpsp;
|
||||
|
||||
/*
|
||||
* WARN if we got a legacy port HPD, but VBT didn't mark the port as
|
||||
* Complain if we got a legacy port HPD, but VBT didn't mark the port as
|
||||
* legacy. Treat the port as legacy from now on.
|
||||
*/
|
||||
if (WARN_ON(!intel_dig_port->tc_legacy_port &&
|
||||
I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)))
|
||||
if (!intel_dig_port->tc_legacy_port &&
|
||||
I915_READ(SDEISR) & SDE_TC_HOTPLUG_ICP(tc_port)) {
|
||||
DRM_ERROR("VBT incorrectly claims port %c is not TypeC legacy\n",
|
||||
port_name(port));
|
||||
intel_dig_port->tc_legacy_port = true;
|
||||
}
|
||||
is_legacy = intel_dig_port->tc_legacy_port;
|
||||
|
||||
/*
|
||||
@@ -5276,7 +5447,7 @@ static bool icl_digital_port_connected(struct intel_encoder *encoder)
|
||||
*
|
||||
* Return %true if port is connected, %false otherwise.
|
||||
*/
|
||||
bool intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
static bool __intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
|
||||
@@ -5306,6 +5477,18 @@ bool intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool intel_digital_port_connected(struct intel_encoder *encoder)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
bool is_connected = false;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
with_intel_display_power(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref)
|
||||
is_connected = __intel_digital_port_connected(encoder);
|
||||
|
||||
return is_connected;
|
||||
}
|
||||
|
||||
static struct edid *
|
||||
intel_dp_get_edid(struct intel_dp *intel_dp)
|
||||
{
|
||||
@@ -5359,16 +5542,11 @@ intel_dp_detect(struct drm_connector *connector,
|
||||
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
|
||||
struct intel_encoder *encoder = &dig_port->base;
|
||||
enum drm_connector_status status;
|
||||
enum intel_display_power_domain aux_domain =
|
||||
intel_aux_power_domain(dig_port);
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
|
||||
connector->base.id, connector->name);
|
||||
WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex));
|
||||
|
||||
wakeref = intel_display_power_get(dev_priv, aux_domain);
|
||||
|
||||
/* Can't disconnect eDP */
|
||||
if (intel_dp_is_edp(intel_dp))
|
||||
status = edp_detect(intel_dp);
|
||||
@@ -5432,10 +5610,8 @@ intel_dp_detect(struct drm_connector *connector,
|
||||
int ret;
|
||||
|
||||
ret = intel_dp_retrain_link(encoder, ctx);
|
||||
if (ret) {
|
||||
intel_display_power_put(dev_priv, aux_domain, wakeref);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -5457,7 +5633,6 @@ out:
|
||||
if (status != connector_status_connected && !intel_dp->is_mst)
|
||||
intel_dp_unset_edid(intel_dp);
|
||||
|
||||
intel_display_power_put(dev_priv, aux_domain, wakeref);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -6235,6 +6410,10 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
|
||||
|
||||
intel_dp->reset_link_params = true;
|
||||
|
||||
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
|
||||
!intel_dp_is_edp(intel_dp))
|
||||
return;
|
||||
|
||||
with_pps_lock(intel_dp, wakeref) {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
intel_dp->active_pipe = vlv_active_pipe(intel_dp);
|
||||
@@ -6278,9 +6457,6 @@ enum irqreturn
|
||||
intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||
{
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
enum irqreturn ret = IRQ_NONE;
|
||||
intel_wakeref_t wakeref;
|
||||
|
||||
if (long_hpd && intel_dig_port->base.type == INTEL_OUTPUT_EDP) {
|
||||
/*
|
||||
@@ -6303,9 +6479,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
wakeref = intel_display_power_get(dev_priv,
|
||||
intel_aux_power_domain(intel_dig_port));
|
||||
|
||||
if (intel_dp->is_mst) {
|
||||
if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
|
||||
/*
|
||||
@@ -6317,7 +6490,8 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||
intel_dp->is_mst = false;
|
||||
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
|
||||
intel_dp->is_mst);
|
||||
goto put_power;
|
||||
|
||||
return IRQ_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6327,17 +6501,10 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
|
||||
handled = intel_dp_short_pulse(intel_dp);
|
||||
|
||||
if (!handled)
|
||||
goto put_power;
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
put_power:
|
||||
intel_display_power_put(dev_priv,
|
||||
intel_aux_power_domain(intel_dig_port),
|
||||
wakeref);
|
||||
|
||||
return ret;
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* check the VBT to see whether the eDP is on another port */
|
||||
@@ -7182,18 +7349,20 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
intel_dp->pps_pipe = INVALID_PIPE;
|
||||
intel_dp->active_pipe = INVALID_PIPE;
|
||||
|
||||
/* intel_dp vfuncs */
|
||||
if (HAS_DDI(dev_priv))
|
||||
intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain;
|
||||
|
||||
/* Preserve the current hw state. */
|
||||
intel_dp->DP = I915_READ(intel_dp->output_reg);
|
||||
intel_dp->attached_connector = intel_connector;
|
||||
|
||||
if (intel_dp_is_port_edp(dev_priv, port))
|
||||
if (intel_dp_is_port_edp(dev_priv, port)) {
|
||||
/*
|
||||
* Currently we don't support eDP on TypeC ports, although in
|
||||
* theory it could work on TypeC legacy ports.
|
||||
*/
|
||||
WARN_ON(intel_port_is_tc(dev_priv, port));
|
||||
type = DRM_MODE_CONNECTOR_eDP;
|
||||
else
|
||||
} else {
|
||||
type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
}
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
intel_dp->active_pipe = vlv_active_pipe(intel_dp);
|
||||
@@ -7223,6 +7392,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
||||
connector->interlace_allowed = true;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
||||
connector->ycbcr_420_allowed = true;
|
||||
|
||||
intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
|
||||
|
||||
intel_dp_aux_init(intel_dp);
|
@@ -108,6 +108,7 @@ u8 intel_dp_dsc_get_slice_count(struct intel_dp *intel_dp, int mode_clock,
|
||||
int mode_hdisplay);
|
||||
|
||||
bool intel_dp_read_dpcd(struct intel_dp *intel_dp);
|
||||
bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp);
|
||||
int intel_dp_link_required(int pixel_clock, int bpp);
|
||||
int intel_dp_max_data_rate(int max_link_clock, int max_lanes);
|
||||
bool intel_digital_port_connected(struct intel_encoder *encoder);
|
@@ -22,6 +22,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "intel_dp_aux_backlight.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
static void set_aux_backlight_enable(struct intel_dp *intel_dp, bool enable)
|
13
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.h
Normal file
13
drivers/gpu/drm/i915/display/intel_dp_aux_backlight.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DP_AUX_BACKLIGHT_H__
|
||||
#define __INTEL_DP_AUX_BACKLIGHT_H__
|
||||
|
||||
struct intel_connector;
|
||||
|
||||
int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector);
|
||||
|
||||
#endif /* __INTEL_DP_AUX_BACKLIGHT_H__ */
|
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
static void
|
14
drivers/gpu/drm/i915/display/intel_dp_link_training.h
Normal file
14
drivers/gpu/drm/i915/display/intel_dp_link_training.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DP_LINK_TRAINING_H__
|
||||
#define __INTEL_DP_LINK_TRAINING_H__
|
||||
|
||||
struct intel_dp;
|
||||
|
||||
void intel_dp_start_link_train(struct intel_dp *intel_dp);
|
||||
void intel_dp_stop_link_train(struct intel_dp *intel_dp);
|
||||
|
||||
#endif /* __INTEL_DP_LINK_TRAINING_H__ */
|
@@ -28,10 +28,13 @@
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
|
||||
@@ -148,9 +151,10 @@ static int intel_dp_mst_compute_config(struct intel_encoder *encoder,
|
||||
|
||||
static int
|
||||
intel_dp_mst_atomic_check(struct drm_connector *connector,
|
||||
struct drm_connector_state *new_conn_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = new_conn_state->state;
|
||||
struct drm_connector_state *new_conn_state =
|
||||
drm_atomic_get_new_connector_state(state, connector);
|
||||
struct drm_connector_state *old_conn_state =
|
||||
drm_atomic_get_old_connector_state(state, connector);
|
||||
struct intel_connector *intel_connector =
|
||||
@@ -160,7 +164,7 @@ intel_dp_mst_atomic_check(struct drm_connector *connector,
|
||||
struct drm_dp_mst_topology_mgr *mgr;
|
||||
int ret;
|
||||
|
||||
ret = intel_digital_connector_atomic_check(connector, new_conn_state);
|
||||
ret = intel_digital_connector_atomic_check(connector, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
14
drivers/gpu/drm/i915/display/intel_dp_mst.h
Normal file
14
drivers/gpu/drm/i915/display/intel_dp_mst.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DP_MST_H__
|
||||
#define __INTEL_DP_MST_H__
|
||||
|
||||
struct intel_digital_port;
|
||||
|
||||
int intel_dp_mst_encoder_init(struct intel_digital_port *intel_dig_port, int conn_id);
|
||||
void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
|
||||
|
||||
#endif /* __INTEL_DP_MST_H__ */
|
@@ -21,8 +21,11 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "intel_dp.h"
|
||||
#include "display/intel_dp.h"
|
||||
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
/**
|
||||
* DOC: DPIO
|
||||
@@ -648,7 +651,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
u32 val;
|
||||
int i;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Clear calc init */
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch));
|
||||
@@ -729,8 +732,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
@@ -800,7 +802,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
|
||||
chv_phy_powergate_lanes(encoder, true, lane_mask);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, crtc_state, true);
|
||||
@@ -855,7 +857,7 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
val |= CHV_CMN_USEDCLKCHANNEL;
|
||||
vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
@@ -870,7 +872,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
int data, i, stagger;
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* allow hardware to manage TX FIFO reset source */
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch));
|
||||
@@ -935,7 +937,7 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
/* Deassert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, crtc_state, false);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void chv_phy_release_cl2_override(struct intel_encoder *encoder)
|
||||
@@ -956,7 +958,7 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder,
|
||||
enum pipe pipe = to_intel_crtc(old_crtc_state->base.crtc)->pipe;
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* disable left/right clock distribution */
|
||||
if (pipe != PIPE_B) {
|
||||
@@ -969,7 +971,7 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder,
|
||||
vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
|
||||
/*
|
||||
* Leave the power down bit cleared for at least one
|
||||
@@ -993,7 +995,8 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
enum dpio_channel port = vlv_dport_to_channel(dport);
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port),
|
||||
@@ -1006,7 +1009,8 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN);
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
@@ -1019,7 +1023,8 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
/* Program Tx lane resets to default */
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port),
|
||||
DPIO_PCS_TX_LANE2_RESET |
|
||||
DPIO_PCS_TX_LANE1_RESET);
|
||||
@@ -1033,7 +1038,8 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000);
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
@@ -1047,7 +1053,7 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
enum pipe pipe = crtc->pipe;
|
||||
u32 val;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Enable clock channels for this port */
|
||||
val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port));
|
||||
@@ -1063,7 +1069,7 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
|
||||
@@ -1075,8 +1081,8 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder,
|
||||
enum dpio_channel port = vlv_dport_to_channel(dport);
|
||||
enum pipe pipe = crtc->pipe;
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000);
|
||||
vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060);
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
58
drivers/gpu/drm/i915/display/intel_dpio_phy.h
Normal file
58
drivers/gpu/drm/i915/display/intel_dpio_phy.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DPIO_PHY_H__
|
||||
#define __INTEL_DPIO_PHY_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum dpio_channel;
|
||||
enum dpio_phy;
|
||||
enum port;
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
|
||||
void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
|
||||
enum dpio_phy *phy, enum dpio_channel *ch);
|
||||
void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv,
|
||||
enum port port, u32 margin, u32 scale,
|
||||
u32 enable, u32 deemphasis);
|
||||
void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy);
|
||||
void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy);
|
||||
bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv,
|
||||
enum dpio_phy phy);
|
||||
bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv,
|
||||
enum dpio_phy phy);
|
||||
u8 bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count);
|
||||
void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
|
||||
u8 lane_lat_optim_mask);
|
||||
u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
|
||||
|
||||
void chv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
u32 deemph_reg_value, u32 margin_reg_value,
|
||||
bool uniq_trans_scale);
|
||||
void chv_data_lane_soft_reset(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
bool reset);
|
||||
void chv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void chv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void chv_phy_release_cl2_override(struct intel_encoder *encoder);
|
||||
void chv_phy_post_pll_disable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state);
|
||||
|
||||
void vlv_set_phy_signal_level(struct intel_encoder *encoder,
|
||||
u32 demph_reg_value, u32 preemph_reg_value,
|
||||
u32 uniqtranscale_reg_value, u32 tx3_demph);
|
||||
void vlv_phy_pre_pll_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void vlv_phy_reset_lanes(struct intel_encoder *encoder,
|
||||
const struct intel_crtc_state *old_crtc_state);
|
||||
|
||||
#endif /* __INTEL_DPIO_PHY_H__ */
|
@@ -21,6 +21,8 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_dpll_mgr.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
/**
|
||||
@@ -349,7 +351,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
u32 val;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -358,7 +360,7 @@ static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
hw_state->fp0 = I915_READ(PCH_FP0(id));
|
||||
hw_state->fp1 = I915_READ(PCH_FP1(id));
|
||||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return val & DPLL_VCO_ENABLE;
|
||||
}
|
||||
@@ -452,7 +454,7 @@ ibx_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
static void ibx_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
|
||||
"fp0: 0x%x, fp1: 0x%x\n",
|
||||
@@ -517,14 +519,14 @@ static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
u32 val;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
val = I915_READ(WRPLL_CTL(id));
|
||||
hw_state->wrpll = val;
|
||||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return val & WRPLL_PLL_ENABLE;
|
||||
}
|
||||
@@ -537,14 +539,14 @@ static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
u32 val;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
val = I915_READ(SPLL_CTL);
|
||||
hw_state->spll = val;
|
||||
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return val & SPLL_PLL_ENABLE;
|
||||
}
|
||||
@@ -773,7 +775,7 @@ static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(struct intel_crtc_state *
|
||||
|
||||
hsw_ddi_calculate_wrpll(crtc_state->port_clock * 1000, &r2, &n2, &p);
|
||||
|
||||
val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
|
||||
val = WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL |
|
||||
WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
|
||||
WRPLL_DIVIDER_POST(p);
|
||||
|
||||
@@ -837,7 +839,7 @@ hsw_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
return NULL;
|
||||
|
||||
crtc_state->dpll_hw_state.spll =
|
||||
SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
|
||||
SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC;
|
||||
|
||||
pll = intel_find_shared_dpll(crtc_state,
|
||||
DPLL_ID_SPLL, DPLL_ID_SPLL);
|
||||
@@ -854,7 +856,7 @@ hsw_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
static void hsw_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
|
||||
hw_state->wrpll, hw_state->spll);
|
||||
@@ -1002,7 +1004,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
bool ret;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -1023,7 +1025,7 @@ static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1039,7 +1041,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
bool ret;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -1056,7 +1058,7 @@ static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1423,7 +1425,7 @@ skl_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
static void skl_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: "
|
||||
"ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
|
||||
@@ -1600,7 +1602,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -1658,7 +1660,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1855,7 +1857,7 @@ bxt_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
static void bxt_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
|
||||
"pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
|
||||
@@ -1879,27 +1881,6 @@ static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
|
||||
.get_hw_state = bxt_ddi_pll_get_hw_state,
|
||||
};
|
||||
|
||||
static void intel_ddi_pll_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
|
||||
if (INTEL_GEN(dev_priv) < 9) {
|
||||
u32 val = I915_READ(LCPLL_CTL);
|
||||
|
||||
/*
|
||||
* The LCPLL register should be turned on by the BIOS. For now
|
||||
* let's just check its state and print errors in case
|
||||
* something is wrong. Don't even try to turn it on.
|
||||
*/
|
||||
|
||||
if (val & LCPLL_CD_SOURCE_FCLK)
|
||||
DRM_ERROR("CDCLK source is not LCPLL\n");
|
||||
|
||||
if (val & LCPLL_PLL_DISABLE)
|
||||
DRM_ERROR("LCPLL is disabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dpll_mgr {
|
||||
const struct dpll_info *dpll_info;
|
||||
|
||||
@@ -1907,7 +1888,7 @@ struct intel_dpll_mgr {
|
||||
struct intel_encoder *encoder);
|
||||
|
||||
void (*dump_hw_state)(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state);
|
||||
const struct intel_dpll_hw_state *hw_state);
|
||||
};
|
||||
|
||||
static const struct dpll_info pch_plls[] = {
|
||||
@@ -2106,7 +2087,7 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
bool ret;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -2126,7 +2107,7 @@ static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
ret = true;
|
||||
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2390,7 +2371,7 @@ cnl_get_dpll(struct intel_crtc_state *crtc_state,
|
||||
}
|
||||
|
||||
static void cnl_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: "
|
||||
"cfgcr0: 0x%x, cfgcr1: 0x%x\n",
|
||||
@@ -2741,11 +2722,11 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state)
|
||||
}
|
||||
|
||||
if (use_ssc) {
|
||||
tmp = (u64)dco_khz * 47 * 32;
|
||||
tmp = mul_u32_u32(dco_khz, 47 * 32);
|
||||
do_div(tmp, refclk_khz * m1div * 10000);
|
||||
ssc_stepsize = tmp;
|
||||
|
||||
tmp = (u64)dco_khz * 1000;
|
||||
tmp = mul_u32_u32(dco_khz, 1000);
|
||||
ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32);
|
||||
} else {
|
||||
ssc_stepsize = 0;
|
||||
@@ -2881,7 +2862,7 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
u32 val;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -2928,7 +2909,7 @@ static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
ret = true;
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2943,7 +2924,7 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
u32 val;
|
||||
|
||||
wakeref = intel_display_power_get_if_enabled(dev_priv,
|
||||
POWER_DOMAIN_PLLS);
|
||||
POWER_DOMAIN_DISPLAY_CORE);
|
||||
if (!wakeref)
|
||||
return false;
|
||||
|
||||
@@ -2956,7 +2937,7 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
|
||||
|
||||
ret = true;
|
||||
out:
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS, wakeref);
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -3190,7 +3171,7 @@ static void mg_pll_disable(struct drm_i915_private *dev_priv,
|
||||
}
|
||||
|
||||
static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
|
||||
"mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
|
||||
@@ -3303,10 +3284,6 @@ void intel_shared_dpll_init(struct drm_device *dev)
|
||||
mutex_init(&dev_priv->dpll_lock);
|
||||
|
||||
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
|
||||
|
||||
/* FIXME: Move this to a more suitable place */
|
||||
if (HAS_DDI(dev_priv))
|
||||
intel_ddi_pll_init(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3364,7 +3341,7 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
|
||||
* Write the relevant values in @hw_state to dmesg using DRM_DEBUG_KMS.
|
||||
*/
|
||||
void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state)
|
||||
const struct intel_dpll_hw_state *hw_state)
|
||||
{
|
||||
if (dev_priv->dpll_mgr) {
|
||||
dev_priv->dpll_mgr->dump_hw_state(dev_priv, hw_state);
|
@@ -25,6 +25,10 @@
|
||||
#ifndef _INTEL_DPLL_MGR_H_
|
||||
#define _INTEL_DPLL_MGR_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "intel_display.h"
|
||||
|
||||
/*FIXME: Move this to a more appropriate place. */
|
||||
#define abs_diff(a, b) ({ \
|
||||
typeof(a) __a = (a); \
|
||||
@@ -32,13 +36,13 @@
|
||||
(void) (&__a == &__b); \
|
||||
__a > __b ? (__a - __b) : (__b - __a); })
|
||||
|
||||
struct drm_atomic_state;
|
||||
struct drm_device;
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc;
|
||||
struct intel_crtc_state;
|
||||
struct intel_encoder;
|
||||
|
||||
struct intel_shared_dpll;
|
||||
struct intel_dpll_mgr;
|
||||
|
||||
/**
|
||||
* enum intel_dpll_id - possible DPLL ids
|
||||
@@ -289,7 +293,7 @@ struct intel_shared_dpll {
|
||||
/**
|
||||
* @state:
|
||||
*
|
||||
* Store the state for the pll, including the its hw state
|
||||
* Store the state for the pll, including its hw state
|
||||
* and CRTCs using it.
|
||||
*/
|
||||
struct intel_shared_dpll_state state;
|
||||
@@ -339,7 +343,7 @@ void intel_shared_dpll_swap_state(struct drm_atomic_state *state);
|
||||
void intel_shared_dpll_init(struct drm_device *dev);
|
||||
|
||||
void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
|
||||
struct intel_dpll_hw_state *hw_state);
|
||||
const struct intel_dpll_hw_state *hw_state);
|
||||
int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv);
|
||||
enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port);
|
||||
bool intel_dpll_is_combophy(enum intel_dpll_id id);
|
@@ -28,6 +28,9 @@
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include "intel_drv.h"
|
||||
|
||||
#define INTEL_DSI_VIDEO_MODE 0
|
||||
#define INTEL_DSI_COMMAND_MODE 1
|
||||
|
||||
/* Dual Link support */
|
||||
#define DSI_DUAL_LINK_NONE 0
|
||||
#define DSI_DUAL_LINK_FRONT_BACK 1
|
||||
@@ -151,6 +154,9 @@ static inline u16 intel_dsi_encoder_ports(struct intel_encoder *encoder)
|
||||
return enc_to_intel_dsi(&encoder->base)->ports;
|
||||
}
|
||||
|
||||
/* icl_dsi.c */
|
||||
void icl_dsi_init(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* intel_dsi.c */
|
||||
int intel_dsi_bitrate(const struct intel_dsi *intel_dsi);
|
||||
int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi);
|
||||
@@ -166,6 +172,7 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector,
|
||||
struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
|
||||
const struct mipi_dsi_host_ops *funcs,
|
||||
enum port port);
|
||||
void vlv_dsi_init(struct drm_i915_private *dev_priv);
|
||||
|
||||
/* vlv_dsi_pll.c */
|
||||
int vlv_dsi_pll_compute(struct intel_encoder *encoder,
|
||||
@@ -192,5 +199,6 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id);
|
||||
void intel_dsi_vbt_exec_sequence(struct intel_dsi *intel_dsi,
|
||||
enum mipi_seq seq_id);
|
||||
void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec);
|
||||
void intel_dsi_log_params(struct intel_dsi *intel_dsi);
|
||||
|
||||
#endif /* _INTEL_DSI_H */
|
@@ -23,11 +23,13 @@
|
||||
* Author: Deepak M <m.deepak at intel.com>
|
||||
*/
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "i915_drv.h"
|
||||
#include <video/mipi_display.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include "intel_dsi_dcs_backlight.h"
|
||||
|
||||
#define CONTROL_DISPLAY_BCTRL (1 << 5)
|
||||
#define CONTROL_DISPLAY_DD (1 << 3)
|
13
drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.h
Normal file
13
drivers/gpu/drm/i915/display/intel_dsi_dcs_backlight.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DSI_DCS_BACKLIGHT_H__
|
||||
#define __INTEL_DSI_DCS_BACKLIGHT_H__
|
||||
|
||||
struct intel_connector;
|
||||
|
||||
int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector);
|
||||
|
||||
#endif /* __INTEL_DSI_DCS_BACKLIGHT_H__ */
|
@@ -24,30 +24,28 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/mfd/intel_soc_pmic.h>
|
||||
#include <linux/slab.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <asm/intel-mid.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
#define MIPI_TRANSFER_MODE_SHIFT 0
|
||||
#define MIPI_VIRTUAL_CHANNEL_SHIFT 1
|
||||
#define MIPI_PORT_SHIFT 3
|
||||
|
||||
#define PREPARE_CNT_MAX 0x3F
|
||||
#define EXIT_ZERO_CNT_MAX 0x3F
|
||||
#define CLK_ZERO_CNT_MAX 0xFF
|
||||
#define TRAIL_CNT_MAX 0x1F
|
||||
|
||||
#define NS_KHZ_RATIO 1000000
|
||||
|
||||
/* base offsets for gpio pads */
|
||||
#define VLV_GPIO_NC_0_HV_DDI0_HPD 0x4130
|
||||
#define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120
|
||||
@@ -248,7 +246,7 @@ static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
pconf0 = VLV_GPIO_PCONF0(map->base_offset);
|
||||
padval = VLV_GPIO_PAD_VAL(map->base_offset);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO));
|
||||
if (!map->init) {
|
||||
/* FIXME: remove constant below */
|
||||
vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00);
|
||||
@@ -257,7 +255,7 @@ static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
|
||||
tmp = 0x4 | value;
|
||||
vlv_iosf_sb_write(dev_priv, port, padval, tmp);
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
|
||||
}
|
||||
|
||||
static void chv_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
@@ -303,12 +301,12 @@ static void chv_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
cfg0 = CHV_GPIO_PAD_CFG0(family_num, gpio_index);
|
||||
cfg1 = CHV_GPIO_PAD_CFG1(family_num, gpio_index);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_iosf_sb_get(dev_priv, BIT(VLV_IOSF_SB_GPIO));
|
||||
vlv_iosf_sb_write(dev_priv, port, cfg1, 0);
|
||||
vlv_iosf_sb_write(dev_priv, port, cfg0,
|
||||
CHV_GPIO_GPIOEN | CHV_GPIO_GPIOCFG_GPO |
|
||||
CHV_GPIO_GPIOTXSTATE(value));
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_iosf_sb_put(dev_priv, BIT(VLV_IOSF_SB_GPIO));
|
||||
}
|
||||
|
||||
static void bxt_exec_gpio(struct drm_i915_private *dev_priv,
|
||||
@@ -532,268 +530,42 @@ void intel_dsi_msleep(struct intel_dsi *intel_dsi, int msec)
|
||||
msleep(msec);
|
||||
}
|
||||
|
||||
#define ICL_PREPARE_CNT_MAX 0x7
|
||||
#define ICL_CLK_ZERO_CNT_MAX 0xf
|
||||
#define ICL_TRAIL_CNT_MAX 0x7
|
||||
#define ICL_TCLK_PRE_CNT_MAX 0x3
|
||||
#define ICL_TCLK_POST_CNT_MAX 0x7
|
||||
#define ICL_HS_ZERO_CNT_MAX 0xf
|
||||
#define ICL_EXIT_ZERO_CNT_MAX 0x7
|
||||
|
||||
static void icl_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
void intel_dsi_log_params(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
u32 tlpx_ns;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 hs_zero_cnt;
|
||||
u32 tclk_pre_cnt, tclk_post_cnt;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare,
|
||||
mipi_config->tclk_prepare);
|
||||
|
||||
/*
|
||||
* prepare cnt in escape clocks
|
||||
* this field represents a hexadecimal value with a precision
|
||||
* of 1.2 – i.e. the most significant bit is the integer
|
||||
* and the least significant 2 bits are fraction bits.
|
||||
* so, the field can represent a range of 0.25 to 1.75
|
||||
*/
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
|
||||
if (prepare_cnt > ICL_PREPARE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("prepare_cnt out of range (%d)\n", prepare_cnt);
|
||||
prepare_cnt = ICL_PREPARE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clk zero count in escape clocks */
|
||||
clk_zero_cnt = DIV_ROUND_UP(mipi_config->tclk_prepare_clkzero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (clk_zero_cnt > ICL_CLK_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("clk_zero_cnt out of range (%d)\n", clk_zero_cnt);
|
||||
clk_zero_cnt = ICL_CLK_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* trail cnt in escape clocks*/
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
|
||||
if (trail_cnt > ICL_TRAIL_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("trail_cnt out of range (%d)\n", trail_cnt);
|
||||
trail_cnt = ICL_TRAIL_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk pre count in escape clocks */
|
||||
tclk_pre_cnt = DIV_ROUND_UP(mipi_config->tclk_pre, tlpx_ns);
|
||||
if (tclk_pre_cnt > ICL_TCLK_PRE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_pre_cnt out of range (%d)\n", tclk_pre_cnt);
|
||||
tclk_pre_cnt = ICL_TCLK_PRE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* tclk post count in escape clocks */
|
||||
tclk_post_cnt = DIV_ROUND_UP(mipi_config->tclk_post, tlpx_ns);
|
||||
if (tclk_post_cnt > ICL_TCLK_POST_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("tclk_post_cnt out of range (%d)\n", tclk_post_cnt);
|
||||
tclk_post_cnt = ICL_TCLK_POST_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs zero cnt in escape clocks */
|
||||
hs_zero_cnt = DIV_ROUND_UP(mipi_config->ths_prepare_hszero -
|
||||
ths_prepare_ns, tlpx_ns);
|
||||
if (hs_zero_cnt > ICL_HS_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("hs_zero_cnt out of range (%d)\n", hs_zero_cnt);
|
||||
hs_zero_cnt = ICL_HS_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* hs exit zero cnt in escape clocks */
|
||||
exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
|
||||
if (exit_zero_cnt > ICL_EXIT_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("exit_zero_cnt out of range (%d)\n", exit_zero_cnt);
|
||||
exit_zero_cnt = ICL_EXIT_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clock lane dphy timings */
|
||||
intel_dsi->dphy_reg = (CLK_PREPARE_OVERRIDE |
|
||||
CLK_PREPARE(prepare_cnt) |
|
||||
CLK_ZERO_OVERRIDE |
|
||||
CLK_ZERO(clk_zero_cnt) |
|
||||
CLK_PRE_OVERRIDE |
|
||||
CLK_PRE(tclk_pre_cnt) |
|
||||
CLK_POST_OVERRIDE |
|
||||
CLK_POST(tclk_post_cnt) |
|
||||
CLK_TRAIL_OVERRIDE |
|
||||
CLK_TRAIL(trail_cnt));
|
||||
|
||||
/* data lanes dphy timings */
|
||||
intel_dsi->dphy_data_lane_reg = (HS_PREPARE_OVERRIDE |
|
||||
HS_PREPARE(prepare_cnt) |
|
||||
HS_ZERO_OVERRIDE |
|
||||
HS_ZERO(hs_zero_cnt) |
|
||||
HS_TRAIL_OVERRIDE |
|
||||
HS_TRAIL(trail_cnt) |
|
||||
HS_EXIT_OVERRIDE |
|
||||
HS_EXIT(exit_zero_cnt));
|
||||
}
|
||||
|
||||
static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
|
||||
{
|
||||
struct drm_device *dev = intel_dsi->base.base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct mipi_config *mipi_config = dev_priv->vbt.dsi.config;
|
||||
u32 tlpx_ns, extra_byte_count, tlpx_ui;
|
||||
u32 ui_num, ui_den;
|
||||
u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
|
||||
u32 ths_prepare_ns, tclk_trail_ns;
|
||||
u32 tclk_prepare_clkzero, ths_prepare_hszero;
|
||||
u32 lp_to_hs_switch, hs_to_lp_switch;
|
||||
u32 mul;
|
||||
|
||||
tlpx_ns = intel_dsi_tlpx_ns(intel_dsi);
|
||||
|
||||
switch (intel_dsi->lane_count) {
|
||||
case 1:
|
||||
case 2:
|
||||
extra_byte_count = 2;
|
||||
break;
|
||||
case 3:
|
||||
extra_byte_count = 4;
|
||||
break;
|
||||
case 4:
|
||||
default:
|
||||
extra_byte_count = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
/* in Kbps */
|
||||
ui_num = NS_KHZ_RATIO;
|
||||
ui_den = intel_dsi_bitrate(intel_dsi);
|
||||
|
||||
tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
|
||||
ths_prepare_hszero = mipi_config->ths_prepare_hszero;
|
||||
|
||||
/*
|
||||
* B060
|
||||
* LP byte clock = TLPX/ (8UI)
|
||||
*/
|
||||
intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
|
||||
|
||||
/* DDR clock period = 2 * UI
|
||||
* UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
|
||||
* UI(nsec) = 10^6 / bitrate
|
||||
* DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
|
||||
* DDR clock count = ns_value / DDR clock period
|
||||
*
|
||||
* For GEMINILAKE dphy_param_reg will be programmed in terms of
|
||||
* HS byte clock count for other platform in HS ddr clock count
|
||||
*/
|
||||
mul = IS_GEMINILAKE(dev_priv) ? 8 : 2;
|
||||
ths_prepare_ns = max(mipi_config->ths_prepare,
|
||||
mipi_config->tclk_prepare);
|
||||
|
||||
/* prepare count */
|
||||
prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul);
|
||||
|
||||
if (prepare_cnt > PREPARE_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt);
|
||||
prepare_cnt = PREPARE_CNT_MAX;
|
||||
}
|
||||
|
||||
/* exit zero count */
|
||||
exit_zero_cnt = DIV_ROUND_UP(
|
||||
(ths_prepare_hszero - ths_prepare_ns) * ui_den,
|
||||
ui_num * mul
|
||||
);
|
||||
|
||||
/*
|
||||
* Exit zero is unified val ths_zero and ths_exit
|
||||
* minimum value for ths_exit = 110ns
|
||||
* min (exit_zero_cnt * 2) = 110/UI
|
||||
* exit_zero_cnt = 55/UI
|
||||
*/
|
||||
if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num)
|
||||
exit_zero_cnt += 1;
|
||||
|
||||
if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt);
|
||||
exit_zero_cnt = EXIT_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* clk zero count */
|
||||
clk_zero_cnt = DIV_ROUND_UP(
|
||||
(tclk_prepare_clkzero - ths_prepare_ns)
|
||||
* ui_den, ui_num * mul);
|
||||
|
||||
if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt);
|
||||
clk_zero_cnt = CLK_ZERO_CNT_MAX;
|
||||
}
|
||||
|
||||
/* trail count */
|
||||
tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
|
||||
trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
|
||||
|
||||
if (trail_cnt > TRAIL_CNT_MAX) {
|
||||
DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
|
||||
trail_cnt = TRAIL_CNT_MAX;
|
||||
}
|
||||
|
||||
/* B080 */
|
||||
intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
|
||||
clk_zero_cnt << 8 | prepare_cnt;
|
||||
|
||||
/*
|
||||
* LP to HS switch count = 4TLPX + PREP_COUNT * mul + EXIT_ZERO_COUNT *
|
||||
* mul + 10UI + Extra Byte Count
|
||||
*
|
||||
* HS to LP switch count = THS-TRAIL + 2TLPX + Extra Byte Count
|
||||
* Extra Byte Count is calculated according to number of lanes.
|
||||
* High Low Switch Count is the Max of LP to HS and
|
||||
* HS to LP switch count
|
||||
*
|
||||
*/
|
||||
tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
|
||||
|
||||
/* B044 */
|
||||
/* FIXME:
|
||||
* The comment above does not match with the code */
|
||||
lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul +
|
||||
exit_zero_cnt * mul + 10, 8);
|
||||
|
||||
hs_to_lp_switch = DIV_ROUND_UP(mipi_config->ths_trail + 2 * tlpx_ui, 8);
|
||||
|
||||
intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
|
||||
intel_dsi->hs_to_lp_count += extra_byte_count;
|
||||
|
||||
/* B088 */
|
||||
/* LP -> HS for clock lanes
|
||||
* LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
|
||||
* extra byte count
|
||||
* 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
|
||||
* 2(in UI) + extra byte count
|
||||
* In byteclks = (4TLPX + prepare_cnt * 2 + clk_zero_cnt *2 (in UI)) /
|
||||
* 8 + extra byte count
|
||||
*/
|
||||
intel_dsi->clk_lp_to_hs_count =
|
||||
DIV_ROUND_UP(
|
||||
4 * tlpx_ui + prepare_cnt * 2 +
|
||||
clk_zero_cnt * 2,
|
||||
8);
|
||||
|
||||
intel_dsi->clk_lp_to_hs_count += extra_byte_count;
|
||||
|
||||
/* HS->LP for Clock Lanes
|
||||
* Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
|
||||
* Extra byte count
|
||||
* 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
|
||||
* In byteclks = (2*TLpx(in UI) + trail_count*2 +8)(in UI)/8 +
|
||||
* Extra byte count
|
||||
*/
|
||||
intel_dsi->clk_hs_to_lp_count =
|
||||
DIV_ROUND_UP(2 * tlpx_ui + trail_cnt * 2 + 8,
|
||||
8);
|
||||
intel_dsi->clk_hs_to_lp_count += extra_byte_count;
|
||||
DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk);
|
||||
DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap);
|
||||
DRM_DEBUG_KMS("Lane count %d\n", intel_dsi->lane_count);
|
||||
DRM_DEBUG_KMS("DPHY param reg 0x%x\n", intel_dsi->dphy_reg);
|
||||
DRM_DEBUG_KMS("Video mode format %s\n",
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE ?
|
||||
"non-burst with sync pulse" :
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS ?
|
||||
"non-burst with sync events" :
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_BURST ?
|
||||
"burst" : "<unknown>");
|
||||
DRM_DEBUG_KMS("Burst mode ratio %d\n", intel_dsi->burst_mode_ratio);
|
||||
DRM_DEBUG_KMS("Reset timer %d\n", intel_dsi->rst_timer_val);
|
||||
DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt));
|
||||
DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop));
|
||||
DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
|
||||
DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
|
||||
else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
|
||||
DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
|
||||
else
|
||||
DRM_DEBUG_KMS("Dual link: NONE\n");
|
||||
DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
|
||||
DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
|
||||
DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);
|
||||
DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val);
|
||||
DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count);
|
||||
DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
|
||||
DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
|
||||
DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
|
||||
DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("BTA %s\n",
|
||||
enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
|
||||
}
|
||||
|
||||
bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
@@ -883,46 +655,6 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
|
||||
|
||||
intel_dsi->burst_mode_ratio = burst_mode_ratio;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 11)
|
||||
icl_dphy_param_init(intel_dsi);
|
||||
else
|
||||
vlv_dphy_param_init(intel_dsi);
|
||||
|
||||
DRM_DEBUG_KMS("Pclk %d\n", intel_dsi->pclk);
|
||||
DRM_DEBUG_KMS("Pixel overlap %d\n", intel_dsi->pixel_overlap);
|
||||
DRM_DEBUG_KMS("Lane count %d\n", intel_dsi->lane_count);
|
||||
DRM_DEBUG_KMS("DPHY param reg 0x%x\n", intel_dsi->dphy_reg);
|
||||
DRM_DEBUG_KMS("Video mode format %s\n",
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_PULSE ?
|
||||
"non-burst with sync pulse" :
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS ?
|
||||
"non-burst with sync events" :
|
||||
intel_dsi->video_mode_format == VIDEO_MODE_BURST ?
|
||||
"burst" : "<unknown>");
|
||||
DRM_DEBUG_KMS("Burst mode ratio %d\n", intel_dsi->burst_mode_ratio);
|
||||
DRM_DEBUG_KMS("Reset timer %d\n", intel_dsi->rst_timer_val);
|
||||
DRM_DEBUG_KMS("Eot %s\n", enableddisabled(intel_dsi->eotp_pkt));
|
||||
DRM_DEBUG_KMS("Clockstop %s\n", enableddisabled(!intel_dsi->clock_stop));
|
||||
DRM_DEBUG_KMS("Mode %s\n", intel_dsi->operation_mode ? "command" : "video");
|
||||
if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK)
|
||||
DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_FRONT_BACK\n");
|
||||
else if (intel_dsi->dual_link == DSI_DUAL_LINK_PIXEL_ALT)
|
||||
DRM_DEBUG_KMS("Dual link: DSI_DUAL_LINK_PIXEL_ALT\n");
|
||||
else
|
||||
DRM_DEBUG_KMS("Dual link: NONE\n");
|
||||
DRM_DEBUG_KMS("Pixel Format %d\n", intel_dsi->pixel_format);
|
||||
DRM_DEBUG_KMS("TLPX %d\n", intel_dsi->escape_clk_div);
|
||||
DRM_DEBUG_KMS("LP RX Timeout 0x%x\n", intel_dsi->lp_rx_timeout);
|
||||
DRM_DEBUG_KMS("Turnaround Timeout 0x%x\n", intel_dsi->turn_arnd_val);
|
||||
DRM_DEBUG_KMS("Init Count 0x%x\n", intel_dsi->init_count);
|
||||
DRM_DEBUG_KMS("HS to LP Count 0x%x\n", intel_dsi->hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("LP Byte Clock %d\n", intel_dsi->lp_byte_clk);
|
||||
DRM_DEBUG_KMS("DBI BW Timer 0x%x\n", intel_dsi->bw_timer);
|
||||
DRM_DEBUG_KMS("LP to HS Clock Count 0x%x\n", intel_dsi->clk_lp_to_hs_count);
|
||||
DRM_DEBUG_KMS("HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count);
|
||||
DRM_DEBUG_KMS("BTA %s\n",
|
||||
enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
|
||||
|
||||
/* delays in VBT are in unit of 100us, so need to convert
|
||||
* here in ms
|
||||
* Delay (100us) * 100 /1000 = Delay / 10 (ms) */
|
@@ -32,13 +32,19 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "dvo.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dvo.h"
|
||||
#include "intel_dvo_dev.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
#define INTEL_DVO_CHIP_NONE 0
|
||||
#define INTEL_DVO_CHIP_LVDS 1
|
||||
#define INTEL_DVO_CHIP_TMDS 2
|
||||
#define INTEL_DVO_CHIP_TVOUT 4
|
||||
|
||||
#define SIL164_ADDR 0x38
|
||||
#define CH7xxx_ADDR 0x76
|
||||
#define TFP410_ADDR 0x38
|
@@ -20,12 +20,14 @@
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _INTEL_DVO_H
|
||||
#define _INTEL_DVO_H
|
||||
#ifndef __INTEL_DVO_DEV_H__
|
||||
#define __INTEL_DVO_DEV_H__
|
||||
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include "intel_drv.h"
|
||||
|
||||
#include "i915_reg.h"
|
||||
|
||||
struct intel_dvo_device {
|
||||
const char *name;
|
||||
@@ -135,4 +137,4 @@ extern const struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern const struct intel_dvo_dev_ops ch7017_ops;
|
||||
extern const struct intel_dvo_dev_ops ns2501_ops;
|
||||
|
||||
#endif /* _INTEL_DVO_H */
|
||||
#endif /* __INTEL_DVO_DEV_H__ */
|
@@ -344,6 +344,10 @@ static void gen7_fbc_activate(struct drm_i915_private *dev_priv)
|
||||
HSW_FBCQ_DIS);
|
||||
}
|
||||
|
||||
if (IS_GEN(dev_priv, 11))
|
||||
/* Wa_1409120013:icl,ehl */
|
||||
I915_WRITE(ILK_DPFC_CHICKEN, ILK_DPFC_CHICKEN_COMP_DUMMY_PIXEL);
|
||||
|
||||
I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN);
|
||||
|
||||
intel_fbc_recompress(dev_priv);
|
@@ -144,7 +144,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
|
||||
if (size * 2 < dev_priv->stolen_usable_size)
|
||||
obj = i915_gem_object_create_stolen(dev_priv, size);
|
||||
if (obj == NULL)
|
||||
obj = i915_gem_object_create(dev_priv, size);
|
||||
obj = i915_gem_object_create_shmem(dev_priv, size);
|
||||
if (IS_ERR(obj)) {
|
||||
DRM_ERROR("failed to allocate framebuffer\n");
|
||||
ret = PTR_ERR(obj);
|
||||
@@ -213,7 +213,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
wakeref = intel_runtime_pm_get(dev_priv);
|
||||
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
|
||||
|
||||
/* Pin the GGTT vma for our access via info->screen_base.
|
||||
* This also validates that any existing fb inherited from the
|
||||
@@ -272,7 +272,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
ifbdev->vma = vma;
|
||||
ifbdev->vma_flags = flags;
|
||||
|
||||
intel_runtime_pm_put(dev_priv, wakeref);
|
||||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
vga_switcheroo_client_fb_set(pdev, info);
|
||||
return 0;
|
||||
@@ -280,7 +280,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
|
||||
out_unpin:
|
||||
intel_unpin_fb_vma(vma, flags);
|
||||
out_unlock:
|
||||
intel_runtime_pm_put(dev_priv, wakeref);
|
||||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
}
|
@@ -28,6 +28,7 @@
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
|
||||
/**
|
||||
* DOC: fifo underrun handling
|
27
drivers/gpu/drm/i915/display/intel_fifo_underrun.h
Normal file
27
drivers/gpu/drm/i915/display/intel_fifo_underrun.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_FIFO_UNDERRUN_H__
|
||||
#define __INTEL_FIFO_UNDERRUN_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "intel_display.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, bool enable);
|
||||
bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
|
||||
enum pipe pch_transcoder,
|
||||
bool enable);
|
||||
void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe);
|
||||
void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
|
||||
enum pipe pch_transcoder);
|
||||
void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv);
|
||||
void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv);
|
||||
|
||||
#endif /* __INTEL_FIFO_UNDERRUN_H__ */
|
@@ -53,16 +53,11 @@
|
||||
* busyness. There is no direct way to detect idleness. Instead an idle timer
|
||||
* work delayed work should be started from the flush and flip functions and
|
||||
* cancelled as soon as busyness is detected.
|
||||
*
|
||||
* Note that there's also an older frontbuffer activity tracking scheme which
|
||||
* just tracks general activity. This is done by the various mark_busy and
|
||||
* mark_idle functions. For display power management features using these
|
||||
* functions is deprecated and should be avoided.
|
||||
*/
|
||||
|
||||
#include "display/intel_dp.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_frontbuffer.h"
|
@@ -24,7 +24,7 @@
|
||||
#ifndef __INTEL_FRONTBUFFER_H__
|
||||
#define __INTEL_FRONTBUFFER_H__
|
||||
|
||||
#include "i915_gem_object.h"
|
||||
#include "gem/i915_gem_object.h"
|
||||
|
||||
struct drm_i915_private;
|
||||
struct drm_i915_gem_object;
|
@@ -26,13 +26,17 @@
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include "intel_drv.h"
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_gmbus.h"
|
||||
|
||||
struct gmbus_pin {
|
||||
const char *name;
|
||||
@@ -84,11 +88,19 @@ static const struct gmbus_pin gmbus_pins_icp[] = {
|
||||
[GMBUS_PIN_12_TC4_ICP] = { "tc4", GPIOM },
|
||||
};
|
||||
|
||||
static const struct gmbus_pin gmbus_pins_mcc[] = {
|
||||
[GMBUS_PIN_1_BXT] = { "dpa", GPIOB },
|
||||
[GMBUS_PIN_2_BXT] = { "dpb", GPIOC },
|
||||
[GMBUS_PIN_9_TC1_ICP] = { "dpc", GPIOJ },
|
||||
};
|
||||
|
||||
/* pin is expected to be valid */
|
||||
static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv,
|
||||
unsigned int pin)
|
||||
{
|
||||
if (HAS_PCH_ICP(dev_priv))
|
||||
if (HAS_PCH_MCC(dev_priv))
|
||||
return &gmbus_pins_mcc[pin];
|
||||
else if (HAS_PCH_ICP(dev_priv))
|
||||
return &gmbus_pins_icp[pin];
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
return &gmbus_pins_cnp[pin];
|
||||
@@ -107,7 +119,9 @@ bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
if (HAS_PCH_ICP(dev_priv))
|
||||
if (HAS_PCH_MCC(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_mcc);
|
||||
else if (HAS_PCH_ICP(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_icp);
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
size = ARRAY_SIZE(gmbus_pins_cnp);
|
||||
@@ -134,7 +148,7 @@ to_intel_gmbus(struct i2c_adapter *i2c)
|
||||
}
|
||||
|
||||
void
|
||||
intel_i2c_reset(struct drm_i915_private *dev_priv)
|
||||
intel_gmbus_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE(GMBUS0, 0);
|
||||
I915_WRITE(GMBUS4, 0);
|
||||
@@ -182,14 +196,15 @@ static void bxt_gmbus_clock_gating(struct drm_i915_private *dev_priv,
|
||||
|
||||
static u32 get_reserved(struct intel_gmbus *bus)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct drm_i915_private *i915 = bus->dev_priv;
|
||||
struct intel_uncore *uncore = &i915->uncore;
|
||||
u32 reserved = 0;
|
||||
|
||||
/* On most chips, these bits must be preserved in software. */
|
||||
if (!IS_I830(dev_priv) && !IS_I845G(dev_priv))
|
||||
reserved = I915_READ_NOTRACE(bus->gpio_reg) &
|
||||
(GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
if (!IS_I830(i915) && !IS_I845G(i915))
|
||||
reserved = intel_uncore_read_notrace(uncore, bus->gpio_reg) &
|
||||
(GPIO_DATA_PULLUP_DISABLE |
|
||||
GPIO_CLOCK_PULLUP_DISABLE);
|
||||
|
||||
return reserved;
|
||||
}
|
||||
@@ -197,27 +212,37 @@ static u32 get_reserved(struct intel_gmbus *bus)
|
||||
static int get_clock(void *data)
|
||||
{
|
||||
struct intel_gmbus *bus = data;
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct intel_uncore *uncore = &bus->dev_priv->uncore;
|
||||
u32 reserved = get_reserved(bus);
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_CLOCK_DIR_MASK);
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved);
|
||||
return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_CLOCK_VAL_IN) != 0;
|
||||
|
||||
intel_uncore_write_notrace(uncore,
|
||||
bus->gpio_reg,
|
||||
reserved | GPIO_CLOCK_DIR_MASK);
|
||||
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved);
|
||||
|
||||
return (intel_uncore_read_notrace(uncore, bus->gpio_reg) &
|
||||
GPIO_CLOCK_VAL_IN) != 0;
|
||||
}
|
||||
|
||||
static int get_data(void *data)
|
||||
{
|
||||
struct intel_gmbus *bus = data;
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct intel_uncore *uncore = &bus->dev_priv->uncore;
|
||||
u32 reserved = get_reserved(bus);
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | GPIO_DATA_DIR_MASK);
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved);
|
||||
return (I915_READ_NOTRACE(bus->gpio_reg) & GPIO_DATA_VAL_IN) != 0;
|
||||
|
||||
intel_uncore_write_notrace(uncore,
|
||||
bus->gpio_reg,
|
||||
reserved | GPIO_DATA_DIR_MASK);
|
||||
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved);
|
||||
|
||||
return (intel_uncore_read_notrace(uncore, bus->gpio_reg) &
|
||||
GPIO_DATA_VAL_IN) != 0;
|
||||
}
|
||||
|
||||
static void set_clock(void *data, int state_high)
|
||||
{
|
||||
struct intel_gmbus *bus = data;
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct intel_uncore *uncore = &bus->dev_priv->uncore;
|
||||
u32 reserved = get_reserved(bus);
|
||||
u32 clock_bits;
|
||||
|
||||
@@ -225,16 +250,18 @@ static void set_clock(void *data, int state_high)
|
||||
clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
|
||||
else
|
||||
clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
|
||||
GPIO_CLOCK_VAL_MASK;
|
||||
GPIO_CLOCK_VAL_MASK;
|
||||
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | clock_bits);
|
||||
POSTING_READ(bus->gpio_reg);
|
||||
intel_uncore_write_notrace(uncore,
|
||||
bus->gpio_reg,
|
||||
reserved | clock_bits);
|
||||
intel_uncore_posting_read(uncore, bus->gpio_reg);
|
||||
}
|
||||
|
||||
static void set_data(void *data, int state_high)
|
||||
{
|
||||
struct intel_gmbus *bus = data;
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
struct intel_uncore *uncore = &bus->dev_priv->uncore;
|
||||
u32 reserved = get_reserved(bus);
|
||||
u32 data_bits;
|
||||
|
||||
@@ -244,8 +271,8 @@ static void set_data(void *data, int state_high)
|
||||
data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
|
||||
GPIO_DATA_VAL_MASK;
|
||||
|
||||
I915_WRITE_NOTRACE(bus->gpio_reg, reserved | data_bits);
|
||||
POSTING_READ(bus->gpio_reg);
|
||||
intel_uncore_write_notrace(uncore, bus->gpio_reg, reserved | data_bits);
|
||||
intel_uncore_posting_read(uncore, bus->gpio_reg);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -256,7 +283,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter)
|
||||
adapter);
|
||||
struct drm_i915_private *dev_priv = bus->dev_priv;
|
||||
|
||||
intel_i2c_reset(dev_priv);
|
||||
intel_gmbus_reset(dev_priv);
|
||||
|
||||
if (IS_PINEVIEW(dev_priv))
|
||||
pnv_gmbus_clock_gating(dev_priv, false);
|
||||
@@ -577,8 +604,7 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num,
|
||||
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
bxt_gmbus_clock_gating(dev_priv, false);
|
||||
else if (HAS_PCH_SPT(dev_priv) ||
|
||||
HAS_PCH_KBP(dev_priv) || HAS_PCH_CNP(dev_priv))
|
||||
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
|
||||
pch_gmbus_clock_gating(dev_priv, false);
|
||||
|
||||
retry:
|
||||
@@ -687,8 +713,7 @@ out:
|
||||
/* Display WA #0868: skl,bxt,kbl,cfl,glk,cnl */
|
||||
if (IS_GEN9_LP(dev_priv))
|
||||
bxt_gmbus_clock_gating(dev_priv, true);
|
||||
else if (HAS_PCH_SPT(dev_priv) ||
|
||||
HAS_PCH_KBP(dev_priv) || HAS_PCH_CNP(dev_priv))
|
||||
else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_CNP(dev_priv))
|
||||
pch_gmbus_clock_gating(dev_priv, true);
|
||||
|
||||
return ret;
|
||||
@@ -811,7 +836,7 @@ static const struct i2c_lock_operations gmbus_lock_ops = {
|
||||
* intel_gmbus_setup - instantiate all Intel i2c GMBuses
|
||||
* @dev_priv: i915 device private
|
||||
*/
|
||||
int intel_setup_gmbus(struct drm_i915_private *dev_priv)
|
||||
int intel_gmbus_setup(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct pci_dev *pdev = dev_priv->drm.pdev;
|
||||
struct intel_gmbus *bus;
|
||||
@@ -872,7 +897,7 @@ int intel_setup_gmbus(struct drm_i915_private *dev_priv)
|
||||
goto err;
|
||||
}
|
||||
|
||||
intel_i2c_reset(dev_priv);
|
||||
intel_gmbus_reset(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -918,7 +943,14 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)
|
||||
mutex_unlock(&dev_priv->gmbus_mutex);
|
||||
}
|
||||
|
||||
void intel_teardown_gmbus(struct drm_i915_private *dev_priv)
|
||||
bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
{
|
||||
struct intel_gmbus *bus = to_intel_gmbus(adapter);
|
||||
|
||||
return bus->force_bit;
|
||||
}
|
||||
|
||||
void intel_gmbus_teardown(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct intel_gmbus *bus;
|
||||
unsigned int pin;
|
27
drivers/gpu/drm/i915/display/intel_gmbus.h
Normal file
27
drivers/gpu/drm/i915/display/intel_gmbus.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_GMBUS_H__
|
||||
#define __INTEL_GMBUS_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct i2c_adapter;
|
||||
|
||||
int intel_gmbus_setup(struct drm_i915_private *dev_priv);
|
||||
void intel_gmbus_teardown(struct drm_i915_private *dev_priv);
|
||||
bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
|
||||
unsigned int pin);
|
||||
int intel_gmbus_output_aksv(struct i2c_adapter *adapter);
|
||||
|
||||
struct i2c_adapter *
|
||||
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
|
||||
void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
|
||||
void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
|
||||
bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter);
|
||||
void intel_gmbus_reset(struct drm_i915_private *dev_priv);
|
||||
|
||||
#endif /* __INTEL_GMBUS_H__ */
|
@@ -16,6 +16,7 @@
|
||||
#include "i915_reg.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
#define KEY_LOAD_TRIES 5
|
||||
#define ENCRYPT_STATUS_CHANGE_TIMEOUT_MS 50
|
||||
@@ -78,7 +79,7 @@ bool intel_hdcp_capable(struct intel_connector *connector)
|
||||
}
|
||||
|
||||
/* Is HDCP2.2 capable on Platform and Sink */
|
||||
static bool intel_hdcp2_capable(struct intel_connector *connector)
|
||||
bool intel_hdcp2_capable(struct intel_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
@@ -213,10 +214,8 @@ static int intel_hdcp_load_keys(struct drm_i915_private *dev_priv)
|
||||
* from other platforms. So GEN9_BC uses the GT Driver Mailbox i/f.
|
||||
*/
|
||||
if (IS_GEN9_BC(dev_priv)) {
|
||||
mutex_lock(&dev_priv->pcu_lock);
|
||||
ret = sandybridge_pcode_write(dev_priv,
|
||||
SKL_PCODE_LOAD_HDCP_KEYS, 1);
|
||||
mutex_unlock(&dev_priv->pcu_lock);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to initiate HDCP key load (%d)\n",
|
||||
ret);
|
||||
@@ -492,9 +491,11 @@ int intel_hdcp_validate_v_prime(struct intel_digital_port *intel_dig_port,
|
||||
|
||||
/* Implements Part 2 of the HDCP authorization procedure */
|
||||
static
|
||||
int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim)
|
||||
int intel_hdcp_auth_downstream(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
const struct intel_hdcp_shim *shim = connector->hdcp.shim;
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
u8 bstatus[2], num_downstream, *ksv_fifo;
|
||||
int ret, i, tries = 3;
|
||||
|
||||
@@ -533,6 +534,11 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
if (drm_hdcp_check_ksvs_revoked(dev, ksv_fifo, num_downstream)) {
|
||||
DRM_ERROR("Revoked Ksv(s) in ksv_fifo\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* When V prime mismatches, DP Spec mandates re-read of
|
||||
* V prime atleast twice.
|
||||
@@ -559,9 +565,12 @@ err:
|
||||
}
|
||||
|
||||
/* Implements Part 1 of the HDCP authorization procedure */
|
||||
static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
const struct intel_hdcp_shim *shim)
|
||||
static int intel_hdcp_auth(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
const struct intel_hdcp_shim *shim = hdcp->shim;
|
||||
struct drm_i915_private *dev_priv;
|
||||
enum port port;
|
||||
unsigned long r0_prime_gen_start;
|
||||
@@ -627,6 +636,11 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (drm_hdcp_check_ksvs_revoked(dev, bksv.shim, 1)) {
|
||||
DRM_ERROR("BKSV is revoked\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
I915_WRITE(PORT_HDCP_BKSVLO(port), bksv.reg[0]);
|
||||
I915_WRITE(PORT_HDCP_BKSVHI(port), bksv.reg[1]);
|
||||
|
||||
@@ -700,7 +714,7 @@ static int intel_hdcp_auth(struct intel_digital_port *intel_dig_port,
|
||||
*/
|
||||
|
||||
if (repeater_present)
|
||||
return intel_hdcp_auth_downstream(intel_dig_port, shim);
|
||||
return intel_hdcp_auth_downstream(connector);
|
||||
|
||||
DRM_DEBUG_KMS("HDCP is enabled (no repeater present)\n");
|
||||
return 0;
|
||||
@@ -763,7 +777,7 @@ static int _intel_hdcp_enable(struct intel_connector *connector)
|
||||
|
||||
/* Incase of authentication failures, HDCP spec expects reauth. */
|
||||
for (i = 0; i < tries; i++) {
|
||||
ret = intel_hdcp_auth(conn_to_dig_port(connector), hdcp->shim);
|
||||
ret = intel_hdcp_auth(connector);
|
||||
if (!ret) {
|
||||
hdcp->hdcp_encrypted = true;
|
||||
return 0;
|
||||
@@ -1162,6 +1176,7 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
union {
|
||||
struct hdcp2_ake_init ake_init;
|
||||
struct hdcp2_ake_send_cert send_cert;
|
||||
@@ -1196,6 +1211,12 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
|
||||
|
||||
hdcp->is_repeater = HDCP_2_2_RX_REPEATER(msgs.send_cert.rx_caps[2]);
|
||||
|
||||
if (drm_hdcp_check_ksvs_revoked(dev, msgs.send_cert.cert_rx.receiver_id,
|
||||
1)) {
|
||||
DRM_ERROR("Receiver ID is revoked\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Here msgs.no_stored_km will hold msgs corresponding to the km
|
||||
* stored also.
|
||||
@@ -1306,7 +1327,7 @@ int hdcp2_propagate_stream_management_info(struct intel_connector *connector)
|
||||
|
||||
/* Prepare RepeaterAuth_Stream_Manage msg */
|
||||
msgs.stream_manage.msg_id = HDCP_2_2_REP_STREAM_MANAGE;
|
||||
drm_hdcp2_u32_to_seq_num(msgs.stream_manage.seq_num_m, hdcp->seq_num_m);
|
||||
drm_hdcp_cpu_to_be24(msgs.stream_manage.seq_num_m, hdcp->seq_num_m);
|
||||
|
||||
/* K no of streams is fixed as 1. Stored as big-endian. */
|
||||
msgs.stream_manage.k = cpu_to_be16(1);
|
||||
@@ -1348,13 +1369,14 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector);
|
||||
struct intel_hdcp *hdcp = &connector->hdcp;
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
union {
|
||||
struct hdcp2_rep_send_receiverid_list recvid_list;
|
||||
struct hdcp2_rep_send_ack rep_ack;
|
||||
} msgs;
|
||||
const struct intel_hdcp_shim *shim = hdcp->shim;
|
||||
u32 seq_num_v, device_cnt;
|
||||
u8 *rx_info;
|
||||
u32 seq_num_v;
|
||||
int ret;
|
||||
|
||||
ret = shim->read_2_2_msg(intel_dig_port, HDCP_2_2_REP_SEND_RECVID_LIST,
|
||||
@@ -1371,7 +1393,8 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
}
|
||||
|
||||
/* Converting and Storing the seq_num_v to local variable as DWORD */
|
||||
seq_num_v = drm_hdcp2_seq_num_to_u32(msgs.recvid_list.seq_num_v);
|
||||
seq_num_v =
|
||||
drm_hdcp_be24_to_cpu((const u8 *)msgs.recvid_list.seq_num_v);
|
||||
|
||||
if (seq_num_v < hdcp->seq_num_v) {
|
||||
/* Roll over of the seq_num_v from repeater. Reauthenticate. */
|
||||
@@ -1379,6 +1402,14 @@ int hdcp2_authenticate_repeater_topology(struct intel_connector *connector)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
device_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
|
||||
HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
|
||||
if (drm_hdcp_check_ksvs_revoked(dev, msgs.recvid_list.receiver_ids,
|
||||
device_cnt)) {
|
||||
DRM_ERROR("Revoked receiver ID(s) is in list\n");
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ret = hdcp2_verify_rep_topology_prepare_ack(connector,
|
||||
&msgs.recvid_list,
|
||||
&msgs.rep_ack);
|
@@ -25,6 +25,7 @@ int intel_hdcp_enable(struct intel_connector *connector);
|
||||
int intel_hdcp_disable(struct intel_connector *connector);
|
||||
bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
|
||||
bool intel_hdcp_capable(struct intel_connector *connector);
|
||||
bool intel_hdcp2_capable(struct intel_connector *connector);
|
||||
void intel_hdcp_component_init(struct drm_i915_private *dev_priv);
|
||||
void intel_hdcp_component_fini(struct drm_i915_private *dev_priv);
|
||||
void intel_hdcp_cleanup(struct intel_connector *connector);
|
@@ -39,17 +39,24 @@
|
||||
#include <drm/i915_drm.h>
|
||||
#include <drm/intel_lpe_audio.h>
|
||||
|
||||
#include "i915_debugfs.h"
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_audio.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_lspcon.h"
|
||||
#include "intel_sdvo.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_sideband.h"
|
||||
|
||||
static struct drm_device *intel_hdmi_to_dev(struct intel_hdmi *intel_hdmi)
|
||||
{
|
||||
@@ -122,6 +129,8 @@ static u32 g4x_infoframe_enable(unsigned int type)
|
||||
return VIDEO_DIP_ENABLE_SPD;
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return VIDEO_DIP_ENABLE_VENDOR;
|
||||
case HDMI_INFOFRAME_TYPE_DRM:
|
||||
return 0;
|
||||
default:
|
||||
MISSING_CASE(type);
|
||||
return 0;
|
||||
@@ -145,6 +154,8 @@ static u32 hsw_infoframe_enable(unsigned int type)
|
||||
return VIDEO_DIP_ENABLE_SPD_HSW;
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return VIDEO_DIP_ENABLE_VS_HSW;
|
||||
case HDMI_INFOFRAME_TYPE_DRM:
|
||||
return VIDEO_DIP_ENABLE_DRM_GLK;
|
||||
default:
|
||||
MISSING_CASE(type);
|
||||
return 0;
|
||||
@@ -170,6 +181,8 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv,
|
||||
return HSW_TVIDEO_DIP_SPD_DATA(cpu_transcoder, i);
|
||||
case HDMI_INFOFRAME_TYPE_VENDOR:
|
||||
return HSW_TVIDEO_DIP_VS_DATA(cpu_transcoder, i);
|
||||
case HDMI_INFOFRAME_TYPE_DRM:
|
||||
return GLK_TVIDEO_DIP_DRM_DATA(cpu_transcoder, i);
|
||||
default:
|
||||
MISSING_CASE(type);
|
||||
return INVALID_MMIO_REG;
|
||||
@@ -543,10 +556,16 @@ static u32 hsw_infoframes_enabled(struct intel_encoder *encoder,
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
u32 val = I915_READ(HSW_TVIDEO_DIP_CTL(pipe_config->cpu_transcoder));
|
||||
u32 mask;
|
||||
|
||||
return val & (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW |
|
||||
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW |
|
||||
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW);
|
||||
mask = (VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW |
|
||||
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW |
|
||||
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW);
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
|
||||
mask |= VIDEO_DIP_ENABLE_DRM_GLK;
|
||||
|
||||
return val & mask;
|
||||
}
|
||||
|
||||
static const u8 infoframe_type_to_idx[] = {
|
||||
@@ -556,6 +575,7 @@ static const u8 infoframe_type_to_idx[] = {
|
||||
HDMI_INFOFRAME_TYPE_AVI,
|
||||
HDMI_INFOFRAME_TYPE_SPD,
|
||||
HDMI_INFOFRAME_TYPE_VENDOR,
|
||||
HDMI_INFOFRAME_TYPE_DRM,
|
||||
};
|
||||
|
||||
u32 intel_hdmi_infoframe_enable(unsigned int type)
|
||||
@@ -778,6 +798,40 @@ intel_hdmi_compute_hdmi_infoframe(struct intel_encoder *encoder,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_hdmi_compute_drm_infoframe(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct hdmi_drm_infoframe *frame = &crtc_state->infoframes.drm.drm;
|
||||
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
|
||||
int ret;
|
||||
|
||||
if (!(INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)))
|
||||
return true;
|
||||
|
||||
if (!crtc_state->has_infoframe)
|
||||
return true;
|
||||
|
||||
if (!conn_state->hdr_output_metadata)
|
||||
return true;
|
||||
|
||||
crtc_state->infoframes.enable |=
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_DRM);
|
||||
|
||||
ret = drm_hdmi_infoframe_set_hdr_metadata(frame, conn_state);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_KMS("couldn't set HDR metadata in infoframe\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = hdmi_drm_infoframe_check(frame);
|
||||
if (WARN_ON(ret))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void g4x_set_infoframes(struct intel_encoder *encoder,
|
||||
bool enable,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
@@ -846,19 +900,6 @@ static void g4x_set_infoframes(struct intel_encoder *encoder,
|
||||
&crtc_state->infoframes.hdmi);
|
||||
}
|
||||
|
||||
static bool hdmi_sink_is_deep_color(const struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_connector *connector = conn_state->connector;
|
||||
|
||||
/*
|
||||
* HDMI cloning is only supported on g4x which doesn't
|
||||
* support deep color or GCP infoframes anyway so no
|
||||
* need to worry about multiple HDMI sinks here.
|
||||
*/
|
||||
|
||||
return connector->display_info.bpc > 8;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if default_phase=1 can be indicated in the GCP infoframe.
|
||||
*
|
||||
@@ -963,8 +1004,8 @@ static void intel_hdmi_compute_gcp_infoframe(struct intel_encoder *encoder,
|
||||
crtc_state->infoframes.enable |=
|
||||
intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GENERAL_CONTROL);
|
||||
|
||||
/* Indicate color depth whenever the sink supports deep color */
|
||||
if (hdmi_sink_is_deep_color(conn_state))
|
||||
/* Indicate color indication for deep color mode */
|
||||
if (crtc_state->pipe_bpp > 24)
|
||||
crtc_state->infoframes.gcp |= GCP_COLOR_INDICATION;
|
||||
|
||||
/* Enable default_phase whenever the display mode is suitably aligned */
|
||||
@@ -1153,7 +1194,8 @@ static void hsw_set_infoframes(struct intel_encoder *encoder,
|
||||
|
||||
val &= ~(VIDEO_DIP_ENABLE_VSC_HSW | VIDEO_DIP_ENABLE_AVI_HSW |
|
||||
VIDEO_DIP_ENABLE_GCP_HSW | VIDEO_DIP_ENABLE_VS_HSW |
|
||||
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW);
|
||||
VIDEO_DIP_ENABLE_GMP_HSW | VIDEO_DIP_ENABLE_SPD_HSW |
|
||||
VIDEO_DIP_ENABLE_DRM_GLK);
|
||||
|
||||
if (!enable) {
|
||||
I915_WRITE(reg, val);
|
||||
@@ -1176,6 +1218,9 @@ static void hsw_set_infoframes(struct intel_encoder *encoder,
|
||||
intel_write_infoframe(encoder, crtc_state,
|
||||
HDMI_INFOFRAME_TYPE_VENDOR,
|
||||
&crtc_state->infoframes.hdmi);
|
||||
intel_write_infoframe(encoder, crtc_state,
|
||||
HDMI_INFOFRAME_TYPE_DRM,
|
||||
&crtc_state->infoframes.drm);
|
||||
}
|
||||
|
||||
void intel_dp_dual_mode_set_tmds_output(struct intel_hdmi *hdmi, bool enable)
|
||||
@@ -1762,7 +1807,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder,
|
||||
if (pipe_config->infoframes.enable)
|
||||
pipe_config->has_infoframe = true;
|
||||
|
||||
if (tmp & SDVO_AUDIO_ENABLE)
|
||||
if (tmp & HDMI_AUDIO_ENABLE)
|
||||
pipe_config->has_audio = true;
|
||||
|
||||
if (!HAS_PCH_SPLIT(dev_priv) &&
|
||||
@@ -1821,7 +1866,7 @@ static void g4x_enable_hdmi(struct intel_encoder *encoder,
|
||||
|
||||
temp |= SDVO_ENABLE;
|
||||
if (pipe_config->has_audio)
|
||||
temp |= SDVO_AUDIO_ENABLE;
|
||||
temp |= HDMI_AUDIO_ENABLE;
|
||||
|
||||
I915_WRITE(intel_hdmi->hdmi_reg, temp);
|
||||
POSTING_READ(intel_hdmi->hdmi_reg);
|
||||
@@ -1843,7 +1888,7 @@ static void ibx_enable_hdmi(struct intel_encoder *encoder,
|
||||
|
||||
temp |= SDVO_ENABLE;
|
||||
if (pipe_config->has_audio)
|
||||
temp |= SDVO_AUDIO_ENABLE;
|
||||
temp |= HDMI_AUDIO_ENABLE;
|
||||
|
||||
/*
|
||||
* HW workaround, need to write this twice for issue
|
||||
@@ -1895,7 +1940,7 @@ static void cpt_enable_hdmi(struct intel_encoder *encoder,
|
||||
|
||||
temp |= SDVO_ENABLE;
|
||||
if (pipe_config->has_audio)
|
||||
temp |= SDVO_AUDIO_ENABLE;
|
||||
temp |= HDMI_AUDIO_ENABLE;
|
||||
|
||||
/*
|
||||
* WaEnableHDMI8bpcBefore12bpc:snb,ivb
|
||||
@@ -1955,7 +2000,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder,
|
||||
|
||||
temp = I915_READ(intel_hdmi->hdmi_reg);
|
||||
|
||||
temp &= ~(SDVO_ENABLE | SDVO_AUDIO_ENABLE);
|
||||
temp &= ~(SDVO_ENABLE | HDMI_AUDIO_ENABLE);
|
||||
I915_WRITE(intel_hdmi->hdmi_reg, temp);
|
||||
POSTING_READ(intel_hdmi->hdmi_reg);
|
||||
|
||||
@@ -2162,7 +2207,7 @@ static bool hdmi_deep_color_possible(const struct intel_crtc_state *crtc_state,
|
||||
if (bpc == 10 && INTEL_GEN(dev_priv) < 11)
|
||||
return false;
|
||||
|
||||
if (crtc_state->pipe_bpp <= 8*3)
|
||||
if (crtc_state->pipe_bpp < bpc * 3)
|
||||
return false;
|
||||
|
||||
if (!crtc_state->has_hdmi_sink)
|
||||
@@ -2382,6 +2427,11 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!intel_hdmi_compute_drm_infoframe(encoder, pipe_config, conn_state)) {
|
||||
DRM_DEBUG_KMS("bad DRM infoframe\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2620,12 +2670,12 @@ static void chv_hdmi_post_disable(struct intel_encoder *encoder,
|
||||
struct drm_device *dev = encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
|
||||
mutex_lock(&dev_priv->sb_lock);
|
||||
vlv_dpio_get(dev_priv);
|
||||
|
||||
/* Assert data lane reset */
|
||||
chv_data_lane_soft_reset(encoder, old_crtc_state, true);
|
||||
|
||||
mutex_unlock(&dev_priv->sb_lock);
|
||||
vlv_dpio_put(dev_priv);
|
||||
}
|
||||
|
||||
static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
@@ -2654,6 +2704,36 @@ static void chv_hdmi_pre_enable(struct intel_encoder *encoder,
|
||||
chv_phy_release_cl2_override(encoder);
|
||||
}
|
||||
|
||||
static struct i2c_adapter *
|
||||
intel_hdmi_get_i2c_adapter(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->dev);
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
|
||||
return intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus);
|
||||
}
|
||||
|
||||
static void intel_hdmi_create_i2c_symlink(struct drm_connector *connector)
|
||||
{
|
||||
struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
|
||||
struct kobject *i2c_kobj = &adapter->dev.kobj;
|
||||
struct kobject *connector_kobj = &connector->kdev->kobj;
|
||||
int ret;
|
||||
|
||||
ret = sysfs_create_link(connector_kobj, i2c_kobj, i2c_kobj->name);
|
||||
if (ret)
|
||||
DRM_ERROR("Failed to create i2c symlink (%d)\n", ret);
|
||||
}
|
||||
|
||||
static void intel_hdmi_remove_i2c_symlink(struct drm_connector *connector)
|
||||
{
|
||||
struct i2c_adapter *adapter = intel_hdmi_get_i2c_adapter(connector);
|
||||
struct kobject *i2c_kobj = &adapter->dev.kobj;
|
||||
struct kobject *connector_kobj = &connector->kdev->kobj;
|
||||
|
||||
sysfs_remove_link(connector_kobj, i2c_kobj->name);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
{
|
||||
@@ -2665,6 +2745,8 @@ intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
|
||||
i915_debugfs_connector_add(connector);
|
||||
|
||||
intel_hdmi_create_i2c_symlink(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2676,6 +2758,13 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
|
||||
intel_connector_destroy(connector);
|
||||
}
|
||||
|
||||
static void intel_hdmi_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
intel_hdmi_remove_i2c_symlink(connector);
|
||||
|
||||
intel_connector_unregister(connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
.detect = intel_hdmi_detect,
|
||||
.force = intel_hdmi_force,
|
||||
@@ -2683,7 +2772,7 @@ static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
|
||||
.atomic_get_property = intel_digital_connector_atomic_get_property,
|
||||
.atomic_set_property = intel_digital_connector_atomic_set_property,
|
||||
.late_register = intel_hdmi_connector_register,
|
||||
.early_unregister = intel_connector_unregister,
|
||||
.early_unregister = intel_hdmi_connector_unregister,
|
||||
.destroy = intel_hdmi_destroy,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_duplicate_state = intel_digital_connector_duplicate_state,
|
||||
@@ -2721,6 +2810,10 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
|
||||
drm_connector_attach_content_type_property(connector);
|
||||
connector->state->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
|
||||
drm_object_attach_property(&connector->base,
|
||||
connector->dev->mode_config.hdr_output_metadata_property, 0);
|
||||
|
||||
if (!HAS_GMCH(dev_priv))
|
||||
drm_connector_attach_max_bpc_property(connector, 8, 12);
|
||||
}
|
||||
@@ -2866,6 +2959,28 @@ static u8 icl_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port)
|
||||
return ddc_pin;
|
||||
}
|
||||
|
||||
static u8 mcc_port_to_ddc_pin(struct drm_i915_private *dev_priv, enum port port)
|
||||
{
|
||||
u8 ddc_pin;
|
||||
|
||||
switch (port) {
|
||||
case PORT_A:
|
||||
ddc_pin = GMBUS_PIN_1_BXT;
|
||||
break;
|
||||
case PORT_B:
|
||||
ddc_pin = GMBUS_PIN_2_BXT;
|
||||
break;
|
||||
case PORT_C:
|
||||
ddc_pin = GMBUS_PIN_9_TC1_ICP;
|
||||
break;
|
||||
default:
|
||||
MISSING_CASE(port);
|
||||
ddc_pin = GMBUS_PIN_1_BXT;
|
||||
break;
|
||||
}
|
||||
return ddc_pin;
|
||||
}
|
||||
|
||||
static u8 g4x_port_to_ddc_pin(struct drm_i915_private *dev_priv,
|
||||
enum port port)
|
||||
{
|
||||
@@ -2902,7 +3017,9 @@ static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv,
|
||||
return info->alternate_ddc_pin;
|
||||
}
|
||||
|
||||
if (HAS_PCH_ICP(dev_priv))
|
||||
if (HAS_PCH_MCC(dev_priv))
|
||||
ddc_pin = mcc_port_to_ddc_pin(dev_priv, port);
|
||||
else if (HAS_PCH_ICP(dev_priv))
|
||||
ddc_pin = icl_port_to_ddc_pin(dev_priv, port);
|
||||
else if (HAS_PCH_CNP(dev_priv))
|
||||
ddc_pin = cnp_port_to_ddc_pin(dev_priv, port);
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_hotplug.h"
|
||||
|
||||
/**
|
||||
* DOC: Hotplug
|
||||
@@ -229,7 +230,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
intel_wakeref_t wakeref;
|
||||
enum hpd_pin pin;
|
||||
|
||||
wakeref = intel_runtime_pm_get(dev_priv);
|
||||
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
for_each_hpd_pin(pin) {
|
||||
@@ -262,7 +263,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
|
||||
dev_priv->display.hpd_irq_setup(dev_priv);
|
||||
spin_unlock_irq(&dev_priv->irq_lock);
|
||||
|
||||
intel_runtime_pm_put(dev_priv, wakeref);
|
||||
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
|
||||
}
|
||||
|
||||
bool intel_encoder_hotplug(struct intel_encoder *encoder,
|
30
drivers/gpu/drm/i915/display/intel_hotplug.h
Normal file
30
drivers/gpu/drm/i915/display/intel_hotplug.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_HOTPLUG_H__
|
||||
#define __INTEL_HOTPLUG_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_connector;
|
||||
struct intel_encoder;
|
||||
|
||||
void intel_hpd_poll_init(struct drm_i915_private *dev_priv);
|
||||
bool intel_encoder_hotplug(struct intel_encoder *encoder,
|
||||
struct intel_connector *connector);
|
||||
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
||||
u32 pin_mask, u32 long_mask);
|
||||
void intel_hpd_init(struct drm_i915_private *dev_priv);
|
||||
void intel_hpd_init_work(struct drm_i915_private *dev_priv);
|
||||
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
|
||||
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
|
||||
enum port port);
|
||||
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
|
||||
void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
|
||||
|
||||
#endif /* __INTEL_HOTPLUG_H__ */
|
@@ -61,15 +61,17 @@
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/intel_lpe_audio.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include <linux/delay.h>
|
||||
#include <drm/intel_lpe_audio.h>
|
||||
#include "intel_lpe_audio.h"
|
||||
|
||||
#define HAS_LPE_AUDIO(dev_priv) ((dev_priv)->lpe_audio.platdev != NULL)
|
||||
|
22
drivers/gpu/drm/i915/display/intel_lpe_audio.h
Normal file
22
drivers/gpu/drm/i915/display/intel_lpe_audio.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_LPE_AUDIO_H__
|
||||
#define __INTEL_LPE_AUDIO_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum pipe;
|
||||
enum port;
|
||||
struct drm_i915_private;
|
||||
|
||||
int intel_lpe_audio_init(struct drm_i915_private *dev_priv);
|
||||
void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv);
|
||||
void intel_lpe_audio_irq_handler(struct drm_i915_private *dev_priv);
|
||||
void intel_lpe_audio_notify(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, enum port port,
|
||||
const void *eld, int ls_clock, bool dp_output);
|
||||
|
||||
#endif /* __INTEL_LPE_AUDIO_H__ */
|
@@ -40,8 +40,10 @@
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_lvds.h"
|
||||
#include "intel_panel.h"
|
||||
|
@@ -32,10 +32,11 @@
|
||||
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_panel.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_opregion.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
#define OPREGION_HEADER_OFFSET 0
|
||||
#define OPREGION_ACPI_OFFSET 0x100
|
@@ -25,13 +25,17 @@
|
||||
*
|
||||
* Derived from Xorg ddx, xf86-video-intel, src/i830_video.c
|
||||
*/
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "gem/i915_gem_pm.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_overlay.h"
|
||||
|
||||
/* Limits for overlay size. According to intel doc, the real limits are:
|
||||
* Y width: 4095, UV width (planar): 2047, Y height: 2047,
|
||||
@@ -235,10 +239,9 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
|
||||
|
||||
static struct i915_request *alloc_request(struct intel_overlay *overlay)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = overlay->i915;
|
||||
struct intel_engine_cs *engine = dev_priv->engine[RCS0];
|
||||
struct intel_engine_cs *engine = overlay->i915->engine[RCS0];
|
||||
|
||||
return i915_request_alloc(engine, dev_priv->kernel_context);
|
||||
return i915_request_create(engine->kernel_context);
|
||||
}
|
||||
|
||||
/* overlay needs to be disable in OCMD reg */
|
||||
@@ -762,8 +765,10 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
|
||||
|
||||
atomic_inc(&dev_priv->gpu_error.pending_fb_pin);
|
||||
|
||||
i915_gem_object_lock(new_bo);
|
||||
vma = i915_gem_object_pin_to_display_plane(new_bo,
|
||||
0, NULL, PIN_MAPPABLE);
|
||||
i915_gem_object_unlock(new_bo);
|
||||
if (IS_ERR(vma)) {
|
||||
ret = PTR_ERR(vma);
|
||||
goto out_pin_section;
|
||||
@@ -1302,15 +1307,20 @@ out_unlock:
|
||||
|
||||
static int get_registers(struct intel_overlay *overlay, bool use_phys)
|
||||
{
|
||||
struct drm_i915_private *i915 = overlay->i915;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
int err;
|
||||
|
||||
obj = i915_gem_object_create_stolen(overlay->i915, PAGE_SIZE);
|
||||
mutex_lock(&i915->drm.struct_mutex);
|
||||
|
||||
obj = i915_gem_object_create_stolen(i915, PAGE_SIZE);
|
||||
if (obj == NULL)
|
||||
obj = i915_gem_object_create_internal(overlay->i915, PAGE_SIZE);
|
||||
if (IS_ERR(obj))
|
||||
return PTR_ERR(obj);
|
||||
obj = i915_gem_object_create_internal(i915, PAGE_SIZE);
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
|
||||
if (IS_ERR(vma)) {
|
||||
@@ -1331,10 +1341,13 @@ static int get_registers(struct intel_overlay *overlay, bool use_phys)
|
||||
}
|
||||
|
||||
overlay->reg_bo = obj;
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
return 0;
|
||||
|
||||
err_put_bo:
|
||||
i915_gem_object_put(obj);
|
||||
err_unlock:
|
||||
mutex_unlock(&i915->drm.struct_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1360,18 +1373,10 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
|
||||
|
||||
INIT_ACTIVE_REQUEST(&overlay->last_flip);
|
||||
|
||||
mutex_lock(&dev_priv->drm.struct_mutex);
|
||||
|
||||
ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv));
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
ret = i915_gem_object_set_to_gtt_domain(overlay->reg_bo, true);
|
||||
if (ret)
|
||||
goto out_reg_bo;
|
||||
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
|
||||
memset_io(overlay->regs, 0, sizeof(struct overlay_registers));
|
||||
update_polyphase_filter(overlay->regs);
|
||||
update_reg_attrs(overlay, overlay->regs);
|
||||
@@ -1380,10 +1385,7 @@ void intel_overlay_setup(struct drm_i915_private *dev_priv)
|
||||
DRM_INFO("Initialized overlay support.\n");
|
||||
return;
|
||||
|
||||
out_reg_bo:
|
||||
i915_gem_object_put(overlay->reg_bo);
|
||||
out_free:
|
||||
mutex_unlock(&dev_priv->drm.struct_mutex);
|
||||
kfree(overlay);
|
||||
}
|
||||
|
29
drivers/gpu/drm/i915/display/intel_overlay.h
Normal file
29
drivers/gpu/drm/i915/display/intel_overlay.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_OVERLAY_H__
|
||||
#define __INTEL_OVERLAY_H__
|
||||
|
||||
struct drm_device;
|
||||
struct drm_file;
|
||||
struct drm_i915_error_state_buf;
|
||||
struct drm_i915_private;
|
||||
struct intel_overlay;
|
||||
struct intel_overlay_error_state;
|
||||
|
||||
void intel_overlay_setup(struct drm_i915_private *dev_priv);
|
||||
void intel_overlay_cleanup(struct drm_i915_private *dev_priv);
|
||||
int intel_overlay_switch_off(struct intel_overlay *overlay);
|
||||
int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
void intel_overlay_reset(struct drm_i915_private *dev_priv);
|
||||
struct intel_overlay_error_state *
|
||||
intel_overlay_capture_error_state(struct drm_i915_private *dev_priv);
|
||||
void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
struct intel_overlay_error_state *error);
|
||||
|
||||
#endif /* __INTEL_OVERLAY_H__ */
|
@@ -35,7 +35,9 @@
|
||||
#include <linux/pwm.h>
|
||||
|
||||
#include "intel_connector.h"
|
||||
#include "intel_dp_aux_backlight.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_dsi_dcs_backlight.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
#define CRC_PMIC_PWM_PERIOD_NS 21333
|
||||
@@ -1286,7 +1288,7 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
|
||||
intel_wakeref_t wakeref;
|
||||
int ret = 0;
|
||||
|
||||
with_intel_runtime_pm(dev_priv, wakeref) {
|
||||
with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) {
|
||||
u32 hw_level;
|
||||
|
||||
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
@@ -29,6 +29,7 @@
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_pipe_crc.h"
|
||||
|
||||
@@ -313,17 +314,8 @@ retry:
|
||||
|
||||
if (IS_HASWELL(dev_priv) &&
|
||||
pipe_config->base.active && crtc->pipe == PIPE_A &&
|
||||
pipe_config->cpu_transcoder == TRANSCODER_EDP) {
|
||||
bool old_need_power_well = pipe_config->pch_pfit.enabled ||
|
||||
pipe_config->pch_pfit.force_thru;
|
||||
bool new_need_power_well = pipe_config->pch_pfit.enabled ||
|
||||
enable;
|
||||
|
||||
pipe_config->pch_pfit.force_thru = enable;
|
||||
|
||||
if (old_need_power_well != new_need_power_well)
|
||||
pipe_config->base.connectors_changed = true;
|
||||
}
|
||||
pipe_config->cpu_transcoder == TRANSCODER_EDP)
|
||||
pipe_config->base.mode_changed = true;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
|
@@ -9,9 +9,11 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void intel_display_crc_init(struct drm_i915_private *dev_priv);
|
||||
int intel_crtc_set_crc_source(struct drm_crtc *crtc, const char *source_name);
|
||||
int intel_crtc_verify_crc_source(struct drm_crtc *crtc,
|
||||
const char *source_name, size_t *values_cnt);
|
||||
@@ -20,6 +22,7 @@ const char *const *intel_crtc_get_crc_sources(struct drm_crtc *crtc,
|
||||
void intel_crtc_disable_pipe_crc(struct intel_crtc *crtc);
|
||||
void intel_crtc_enable_pipe_crc(struct intel_crtc *crtc);
|
||||
#else
|
||||
static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {}
|
||||
#define intel_crtc_set_crc_source NULL
|
||||
#define intel_crtc_verify_crc_source NULL
|
||||
#define intel_crtc_get_crc_sources NULL
|
@@ -23,8 +23,9 @@
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
|
||||
#include "display/intel_dp.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_psr.h"
|
||||
#include "intel_sprite.h"
|
||||
@@ -229,16 +230,6 @@ void intel_psr_irq_handler(struct drm_i915_private *dev_priv, u32 psr_iir)
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
u8 dprx = 0;
|
||||
|
||||
if (drm_dp_dpcd_readb(&intel_dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST,
|
||||
&dprx) != 1)
|
||||
return false;
|
||||
return dprx & DP_VSC_SDP_EXT_FOR_COLORIMETRY_SUPPORTED;
|
||||
}
|
||||
|
||||
static bool intel_dp_get_alpm_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
u8 alpm_caps = 0;
|
||||
@@ -352,7 +343,7 @@ static void intel_psr_setup_vsc(struct intel_dp *intel_dp,
|
||||
{
|
||||
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
struct edp_vsc_psr psr_vsc;
|
||||
struct dp_sdp psr_vsc;
|
||||
|
||||
if (dev_priv->psr.psr2_enabled) {
|
||||
/* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */
|
||||
@@ -872,16 +863,23 @@ void intel_psr_disable(struct intel_dp *intel_dp,
|
||||
|
||||
static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/*
|
||||
* Display WA #0884: all
|
||||
* This documented WA for bxt can be safely applied
|
||||
* broadly so we can force HW tracking to exit PSR
|
||||
* instead of disabling and re-enabling.
|
||||
* Workaround tells us to write 0 to CUR_SURFLIVE_A,
|
||||
* but it makes more sense write to the current active
|
||||
* pipe.
|
||||
*/
|
||||
I915_WRITE(CURSURFLIVE(dev_priv->psr.pipe), 0);
|
||||
if (INTEL_GEN(dev_priv) >= 9)
|
||||
/*
|
||||
* Display WA #0884: skl+
|
||||
* This documented WA for bxt can be safely applied
|
||||
* broadly so we can force HW tracking to exit PSR
|
||||
* instead of disabling and re-enabling.
|
||||
* Workaround tells us to write 0 to CUR_SURFLIVE_A,
|
||||
* but it makes more sense write to the current active
|
||||
* pipe.
|
||||
*/
|
||||
I915_WRITE(CURSURFLIVE(dev_priv->psr.pipe), 0);
|
||||
else
|
||||
/*
|
||||
* A write to CURSURFLIVE do not cause HW tracking to exit PSR
|
||||
* on older gens so doing the manual exit instead.
|
||||
*/
|
||||
intel_psr_exit(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -912,6 +910,15 @@ void intel_psr_update(struct intel_dp *intel_dp,
|
||||
/* Force a PSR exit when enabling CRC to avoid CRC timeouts */
|
||||
if (crtc_state->crc_enabled && psr->enabled)
|
||||
psr_force_hw_tracking_exit(dev_priv);
|
||||
else if (INTEL_GEN(dev_priv) < 9 && psr->enabled) {
|
||||
/*
|
||||
* Activate PSR again after a force exit when enabling
|
||||
* CRC in older gens
|
||||
*/
|
||||
if (!dev_priv->psr.active &&
|
||||
!dev_priv->psr.busy_frontbuffer_bits)
|
||||
schedule_work(&dev_priv->psr.work);
|
||||
}
|
||||
|
||||
goto unlock;
|
||||
}
|
@@ -6,6 +6,7 @@
|
||||
#include <linux/dmi.h>
|
||||
|
||||
#include "intel_drv.h"
|
||||
#include "intel_quirks.h"
|
||||
|
||||
/*
|
||||
* Some machines (Lenovo U160) do not work with SSC on LVDS for some reason
|
13
drivers/gpu/drm/i915/display/intel_quirks.h
Normal file
13
drivers/gpu/drm/i915/display/intel_quirks.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2019 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_QUIRKS_H__
|
||||
#define __INTEL_QUIRKS_H__
|
||||
|
||||
struct drm_i915_private;
|
||||
|
||||
void intel_init_quirks(struct drm_i915_private *dev_priv);
|
||||
|
||||
#endif /* __INTEL_QUIRKS_H__ */
|
@@ -37,9 +37,13 @@
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_connector.h"
|
||||
#include "intel_drv.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_gmbus.h"
|
||||
#include "intel_hdmi.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_panel.h"
|
||||
#include "intel_sdvo.h"
|
||||
#include "intel_sdvo_regs.h"
|
||||
@@ -518,6 +522,7 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
|
||||
#define BUF_LEN 256
|
||||
char buffer[BUF_LEN];
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
/*
|
||||
* The documentation states that all commands will be
|
||||
@@ -581,7 +586,8 @@ static bool intel_sdvo_read_response(struct intel_sdvo *intel_sdvo,
|
||||
return true;
|
||||
|
||||
log_fail:
|
||||
DRM_DEBUG_KMS("%s: R: ... failed\n", SDVO_NAME(intel_sdvo));
|
||||
DRM_DEBUG_KMS("%s: R: ... failed %s\n",
|
||||
SDVO_NAME(intel_sdvo), buffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -976,6 +982,9 @@ static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
|
||||
if_index, length, hbuf_size);
|
||||
|
||||
if (hbuf_size < length)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < hbuf_size; i += 8) {
|
||||
memset(tmp, 0, 8);
|
||||
if (i < length)
|
||||
@@ -1008,6 +1017,11 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
if (av_split < if_index)
|
||||
return 0;
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return -ENXIO;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo,
|
||||
SDVO_CMD_GET_HBUF_TXRATE,
|
||||
&tx_rate, 1))
|
||||
@@ -1016,11 +1030,6 @@ static ssize_t intel_sdvo_read_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
if (tx_rate == SDVO_HBUF_TX_DISABLED)
|
||||
return 0;
|
||||
|
||||
if (!intel_sdvo_set_value(intel_sdvo,
|
||||
SDVO_CMD_SET_HBUF_INDEX,
|
||||
set_buf_index, 2))
|
||||
return -ENXIO;
|
||||
|
||||
if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
|
||||
&hbuf_size, 1))
|
||||
return -ENXIO;
|
||||
@@ -1099,7 +1108,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
|
||||
return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
|
||||
SDVO_HBUF_TX_VSYNC,
|
||||
sdvo_data, sizeof(sdvo_data));
|
||||
sdvo_data, len);
|
||||
}
|
||||
|
||||
static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
@@ -1125,7 +1134,7 @@ static void intel_sdvo_get_avi_infoframe(struct intel_sdvo *intel_sdvo,
|
||||
crtc_state->infoframes.enable |=
|
||||
intel_hdmi_infoframe_enable(HDMI_INFOFRAME_TYPE_AVI);
|
||||
|
||||
ret = hdmi_infoframe_unpack(frame, sdvo_data, sizeof(sdvo_data));
|
||||
ret = hdmi_infoframe_unpack(frame, sdvo_data, len);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("Failed to unpack AVI infoframe\n");
|
||||
return;
|
||||
@@ -2388,9 +2397,10 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
|
||||
};
|
||||
|
||||
static int intel_sdvo_atomic_check(struct drm_connector *conn,
|
||||
struct drm_connector_state *new_conn_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = new_conn_state->state;
|
||||
struct drm_connector_state *new_conn_state =
|
||||
drm_atomic_get_new_connector_state(state, conn);
|
||||
struct drm_connector_state *old_conn_state =
|
||||
drm_atomic_get_old_connector_state(state, conn);
|
||||
struct intel_sdvo_connector_state *old_state =
|
||||
@@ -2402,13 +2412,13 @@ static int intel_sdvo_atomic_check(struct drm_connector *conn,
|
||||
(memcmp(&old_state->tv, &new_state->tv, sizeof(old_state->tv)) ||
|
||||
memcmp(&old_conn_state->tv, &new_conn_state->tv, sizeof(old_conn_state->tv)))) {
|
||||
struct drm_crtc_state *crtc_state =
|
||||
drm_atomic_get_new_crtc_state(new_conn_state->state,
|
||||
drm_atomic_get_new_crtc_state(state,
|
||||
new_conn_state->crtc);
|
||||
|
||||
crtc_state->connectors_changed = true;
|
||||
}
|
||||
|
||||
return intel_digital_connector_atomic_check(conn, new_conn_state);
|
||||
return intel_digital_connector_atomic_check(conn, state);
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = {
|
@@ -24,6 +24,12 @@
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_SDVO_REGS_H__
|
||||
#define __INTEL_SDVO_REGS_H__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* SDVO command definitions and structures.
|
||||
*/
|
||||
@@ -731,3 +737,5 @@ struct intel_sdvo_encode {
|
||||
u8 dvi_rev;
|
||||
u8 hdmi_rev;
|
||||
} __packed;
|
||||
|
||||
#endif /* __INTEL_SDVO_REGS_H__ */
|
@@ -256,6 +256,16 @@ int intel_plane_check_stride(const struct intel_plane_state *plane_state)
|
||||
unsigned int rotation = plane_state->base.rotation;
|
||||
u32 stride, max_stride;
|
||||
|
||||
/*
|
||||
* We ignore stride for all invisible planes that
|
||||
* can be remapped. Otherwise we could end up
|
||||
* with a false positive when the remapping didn't
|
||||
* kick in due the plane being invisible.
|
||||
*/
|
||||
if (intel_plane_can_remap(plane_state) &&
|
||||
!plane_state->base.visible)
|
||||
return 0;
|
||||
|
||||
/* FIXME other color planes? */
|
||||
stride = plane_state->color_plane[0].stride;
|
||||
max_stride = plane->max_stride(plane, fb->format->format,
|
||||
@@ -325,7 +335,8 @@ skl_plane_max_stride(struct intel_plane *plane,
|
||||
u32 pixel_format, u64 modifier,
|
||||
unsigned int rotation)
|
||||
{
|
||||
int cpp = drm_format_plane_cpp(pixel_format, 0);
|
||||
const struct drm_format_info *info = drm_format_info(pixel_format);
|
||||
int cpp = info->cpp[0];
|
||||
|
||||
/*
|
||||
* "The stride in bytes must not exceed the
|
||||
@@ -1417,6 +1428,10 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i9xx_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!plane_state->base.visible)
|
||||
return 0;
|
||||
|
||||
@@ -1428,10 +1443,6 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i9xx_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (INTEL_GEN(dev_priv) >= 7)
|
||||
plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state);
|
||||
else
|
||||
@@ -1475,6 +1486,10 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i9xx_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!plane_state->base.visible)
|
||||
return 0;
|
||||
|
||||
@@ -1482,10 +1497,6 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i9xx_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state);
|
||||
|
||||
return 0;
|
||||
@@ -1639,6 +1650,10 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = skl_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!plane_state->base.visible)
|
||||
return 0;
|
||||
|
||||
@@ -1654,10 +1669,6 @@ static int skl_plane_check(struct intel_crtc_state *crtc_state,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = skl_check_plane_surface(plane_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* HW only has 8 bits pixel precision, disable plane if invisible */
|
||||
if (!(plane_state->base.alpha >> 8))
|
||||
plane_state->base.visible = false;
|
||||
@@ -2146,8 +2157,6 @@ static const struct drm_plane_funcs g4x_sprite_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = intel_plane_destroy,
|
||||
.atomic_get_property = intel_plane_atomic_get_property,
|
||||
.atomic_set_property = intel_plane_atomic_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
.format_mod_supported = g4x_sprite_format_mod_supported,
|
||||
@@ -2157,8 +2166,6 @@ static const struct drm_plane_funcs snb_sprite_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = intel_plane_destroy,
|
||||
.atomic_get_property = intel_plane_atomic_get_property,
|
||||
.atomic_set_property = intel_plane_atomic_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
.format_mod_supported = snb_sprite_format_mod_supported,
|
||||
@@ -2168,8 +2175,6 @@ static const struct drm_plane_funcs vlv_sprite_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = intel_plane_destroy,
|
||||
.atomic_get_property = intel_plane_atomic_get_property,
|
||||
.atomic_set_property = intel_plane_atomic_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
.format_mod_supported = vlv_sprite_format_mod_supported,
|
||||
@@ -2179,8 +2184,6 @@ static const struct drm_plane_funcs skl_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = intel_plane_destroy,
|
||||
.atomic_get_property = intel_plane_atomic_get_property,
|
||||
.atomic_set_property = intel_plane_atomic_set_property,
|
||||
.atomic_duplicate_state = intel_plane_duplicate_state,
|
||||
.atomic_destroy_state = intel_plane_destroy_state,
|
||||
.format_mod_supported = skl_plane_format_mod_supported,
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user