mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 16:53:54 +08:00
Features:
- HDR support (Uma, Ville) - Add I2C symlink under HDMI connector similar to DP (Oleg) - Add ICL multi-segmented gamma support (Shashank, Uma) - Update register whitelist support for new hardware (Robert, John) - GuC firmware update with updated ABI interface (Michal, Oscar) - Add support for new DMC header versions (Lucas) - In-kernel blitter client for selftest use (Matthew) - Add Mule Creec Canyon (MCC) PCH support to go with EHL (Matt) - EHL platform feature updates (Matt) - Use Command Transport Buffers with GuC on all gens (Daniele) - New i915.force_probe module parameter to replace i915.alpha_support (Jani) Refactoring: - Better runtime PM code abstraction/encapsulation (Daniele) - VBT parsing cleanup and improvements (Jani) - Move display code to its own subdirectory (Jani) - Header cleanup (Jani, Daniele) - Prep work for subsclice mask expansion (Stuart) - Use uncore mmio register accessors more, remove unused macro wrappers (Tvrtko) - Remove unused atomic property get/set stubs (Maarten) - GTT cleanups and improvements (Mika) - Pass intel_ types instead of drm_ types in plenty of display code (Ville) - Engine reset, hangcheck, fault code cleanups and improvements (Tvrtko) - Consider AML variants simply as either KBL or CFL ULX (Ville) - State checker cleanups and improvements (Ville) - GEM code reorganization to more files under gem subdirectory (Chris) - Reducing dependency on a coarse struct_mutex (Chris) Fixes: - Fix use of uninitialized/incorrect error pointers (Colin, Dan) - Fix DSI fastboot on some VLV/CHV platforms (Hans) - Fix DSI error path (Hans) - Add ICL port A combo PHY HW state check (Imre) - Fix ICL AUX-B HW not done issue (Imre) - Fix perf whitelist on gen10+ (Lionel) - Fix PSR exit by forcing manual exit on older gens (José) - Match voltage ranges instead of exact values (Lucas) - Fix SDVO HDMI audio, with cleanups (Ville) - Fix plane state dumps (Ville) - Fix driver cleanup code to support driver hot unbind (Janusz) - Add checks for ICL memory bandwidth requirements (Ville) - Fix toggling between no C8 planes vs. at least one C8 plane (Ville) - Improved checks on PLL usage conditions, refactoring (Ville) - Avoid clobbering M/N values in fastset fuzzy checks (Ville) - Take a runtime pm wakeref for atomic commits (Chris) - Do not allow runtime pm autosuspend to remove userspace GGTT mmaps too quickly (Chris) - Avoid refcount_inc on known zero count to avoid debug flagging (Chris) -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEFWWmW3ewYy4RJOWc05gHnSar7m8FAl0KK/QACgkQ05gHnSar 7m9IdRAAp5f3CRqEd2nqo4mQwNPjw5jggt4VjfijWJErLzVGdqcrY3Gn5v15AgNE lL4ybjcq840rs8fuRp2WicBXdjGCVxH4sQgtMMQTnpf4B2i4FqiWx+WfBkKgGG1Z Xf1FZwpClm86Ggf/RzASsCSbe31Sf8Jio6QONulQnDoQR46bmqhVWRcPZ4FVLX7O lUPudbJR/q6yW6Q6N9oJ+2h6/QBEVBEU79EZmcrG/w8HMtMh6yteAY6dFM6HMkKV u+3is1p4Ww5pu1t+1AJC818TCfyaLs0gveyAxnaz8ClSlzhPh/ccwSvqQUzIIKxm CcU3ruGGWDa0ZMl3bq+kipJdfghBnU43M0sXZ82IGSS7fkgS+csXGhp4sL/7LeH5 7u0XE40zSpa4qeUcqLF/mkTsmD5xIxUEQ8rO4xT5Niayau74KfP/uCo+loLAZicl ig8OB7o8AG6RAjMkivPl2iAiWVu+MUEzWQqIZzKmkXdZ3v6JN7jQWGketzSfT8D+ yg4GYGXqAyDisRgGlDacikUzQodD88ULKiuiqpwzr/xzO0NIvTMyOixEDvquO0c7 +zcG6g8vJTjnHyNjUtwRlfLus30tCyZ2JExnscSOwyxRSEvKL8ds5IZHs4XVme42 KZvVTk1aD1o90h/YUiL9YMFUB/Bu4rb9RMo7N6EEmEl5exwbDp0= =hS8b -----END PGP SIGNATURE----- Merge tag 'drm-intel-next-2019-06-19' of git://anongit.freedesktop.org/drm/drm-intel into drm-next Features: - HDR support (Uma, Ville) - Add I2C symlink under HDMI connector similar to DP (Oleg) - Add ICL multi-segmented gamma support (Shashank, Uma) - Update register whitelist support for new hardware (Robert, John) - GuC firmware update with updated ABI interface (Michal, Oscar) - Add support for new DMC header versions (Lucas) - In-kernel blitter client for selftest use (Matthew) - Add Mule Creec Canyon (MCC) PCH support to go with EHL (Matt) - EHL platform feature updates (Matt) - Use Command Transport Buffers with GuC on all gens (Daniele) - New i915.force_probe module parameter to replace i915.alpha_support (Jani) Refactoring: - Better runtime PM code abstraction/encapsulation (Daniele) - VBT parsing cleanup and improvements (Jani) - Move display code to its own subdirectory (Jani) - Header cleanup (Jani, Daniele) - Prep work for subsclice mask expansion (Stuart) - Use uncore mmio register accessors more, remove unused macro wrappers (Tvrtko) - Remove unused atomic property get/set stubs (Maarten) - GTT cleanups and improvements (Mika) - Pass intel_ types instead of drm_ types in plenty of display code (Ville) - Engine reset, hangcheck, fault code cleanups and improvements (Tvrtko) - Consider AML variants simply as either KBL or CFL ULX (Ville) - State checker cleanups and improvements (Ville) - GEM code reorganization to more files under gem subdirectory (Chris) - Reducing dependency on a coarse struct_mutex (Chris) Fixes: - Fix use of uninitialized/incorrect error pointers (Colin, Dan) - Fix DSI fastboot on some VLV/CHV platforms (Hans) - Fix DSI error path (Hans) - Add ICL port A combo PHY HW state check (Imre) - Fix ICL AUX-B HW not done issue (Imre) - Fix perf whitelist on gen10+ (Lionel) - Fix PSR exit by forcing manual exit on older gens (José) - Match voltage ranges instead of exact values (Lucas) - Fix SDVO HDMI audio, with cleanups (Ville) - Fix plane state dumps (Ville) - Fix driver cleanup code to support driver hot unbind (Janusz) - Add checks for ICL memory bandwidth requirements (Ville) - Fix toggling between no C8 planes vs. at least one C8 plane (Ville) - Improved checks on PLL usage conditions, refactoring (Ville) - Avoid clobbering M/N values in fastset fuzzy checks (Ville) - Take a runtime pm wakeref for atomic commits (Chris) - Do not allow runtime pm autosuspend to remove userspace GGTT mmaps too quickly (Chris) - Avoid refcount_inc on known zero count to avoid debug flagging (Chris) Signed-off-by: Dave Airlie <airlied@redhat.com> From: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/87v9x1lpdh.fsf@intel.com
This commit is contained in:
commit
417f2544f4
@ -61,7 +61,7 @@ Intel GVT-g Host Support(vGPU device model)
|
||||
Workarounds
|
||||
-----------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_workarounds.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/intel_workarounds.c
|
||||
:doc: Hardware workarounds
|
||||
|
||||
Display Hardware Handling
|
||||
@ -82,13 +82,13 @@ change.
|
||||
Frontbuffer Tracking
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_frontbuffer.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c
|
||||
:doc: frontbuffer tracking
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_frontbuffer.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_frontbuffer.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_frontbuffer.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem.c
|
||||
@ -97,10 +97,10 @@ Frontbuffer Tracking
|
||||
Display FIFO Underrun Reporting
|
||||
-------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_fifo_underrun.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_fifo_underrun.c
|
||||
:doc: fifo underrun handling
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_fifo_underrun.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_fifo_underrun.c
|
||||
:internal:
|
||||
|
||||
Plane Configuration
|
||||
@ -115,10 +115,10 @@ panel self refresh.
|
||||
Atomic Plane Helpers
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_atomic_plane.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_atomic_plane.c
|
||||
:doc: atomic plane helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_atomic_plane.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_atomic_plane.c
|
||||
:internal:
|
||||
|
||||
Output Probing
|
||||
@ -132,19 +132,19 @@ probing, so those sections fully apply.
|
||||
Hotplug
|
||||
-------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_hotplug.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_hotplug.c
|
||||
:doc: Hotplug
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_hotplug.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_hotplug.c
|
||||
:internal:
|
||||
|
||||
High Definition Audio
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_audio.c
|
||||
:doc: High Definition Audio over HDMI and Display Port
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_audio.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: include/drm/i915_component.h
|
||||
@ -153,58 +153,58 @@ High Definition Audio
|
||||
Intel HDMI LPE Audio Support
|
||||
----------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_lpe_audio.c
|
||||
:doc: LPE Audio integration for HDMI or DP playback
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_lpe_audio.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_lpe_audio.c
|
||||
:internal:
|
||||
|
||||
Panel Self Refresh PSR (PSR/SRD)
|
||||
--------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_psr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_psr.c
|
||||
:doc: Panel Self Refresh (PSR/SRD)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_psr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_psr.c
|
||||
:internal:
|
||||
|
||||
Frame Buffer Compression (FBC)
|
||||
------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_fbc.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_fbc.c
|
||||
:doc: Frame Buffer Compression (FBC)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_fbc.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_fbc.c
|
||||
:internal:
|
||||
|
||||
Display Refresh Rate Switching (DRRS)
|
||||
-------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:doc: Display Refresh Rate Switching (DRRS)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_dp_set_drrs_state
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_edp_drrs_enable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_edp_drrs_disable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_edp_drrs_invalidate
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_edp_drrs_flush
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
:functions: intel_dp_drrs_init
|
||||
|
||||
DPIO
|
||||
----
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dpio_phy.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dpio_phy.c
|
||||
:doc: DPIO
|
||||
|
||||
CSR firmware support for DMC
|
||||
@ -219,34 +219,34 @@ CSR firmware support for DMC
|
||||
Video BIOS Table (VBT)
|
||||
----------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_bios.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_bios.c
|
||||
:doc: Video BIOS Table (VBT)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_bios.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_bios.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_vbt_defs.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_vbt_defs.h
|
||||
:internal:
|
||||
|
||||
Display clocks
|
||||
--------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_cdclk.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_cdclk.c
|
||||
:doc: CDCLK / RAWCLK
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_cdclk.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_cdclk.c
|
||||
:internal:
|
||||
|
||||
Display PLLs
|
||||
------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dpll_mgr.c
|
||||
:doc: Display PLLs
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dpll_mgr.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_dpll_mgr.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dpll_mgr.h
|
||||
:internal:
|
||||
|
||||
Memory Management and Command Submission
|
||||
@ -349,7 +349,7 @@ of buffer object caches. Shrinking is used to make main memory
|
||||
available. Note that this is mostly orthogonal to evicting buffer
|
||||
objects, which has the goal to make space in gpu virtual address spaces.
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_shrinker.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
|
||||
:internal:
|
||||
|
||||
Batchbuffer Parsing
|
||||
@ -373,18 +373,15 @@ Batchbuffer Pools
|
||||
User Batchbuffer Execution
|
||||
--------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_execbuffer.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
|
||||
:doc: User command execution
|
||||
|
||||
Logical Rings, Logical Ring Contexts and Execlists
|
||||
--------------------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_lrc.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/intel_lrc.c
|
||||
:doc: Logical Rings, Logical Ring Contexts and Execlists
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/intel_lrc.c
|
||||
:internal:
|
||||
|
||||
Global GTT views
|
||||
----------------
|
||||
|
||||
@ -415,10 +412,10 @@ Hardware Tiling and Swizzling Details
|
||||
Object Tiling IOCTLs
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_tiling.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_tiling.c
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_tiling.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_tiling.c
|
||||
:doc: buffer object tiling
|
||||
|
||||
WOPCM
|
||||
@ -478,12 +475,6 @@ i915_context_create and i915_context_free
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_trace.h
|
||||
:doc: i915_context_create and i915_context_free tracepoints
|
||||
|
||||
switch_mm
|
||||
---------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/i915_trace.h
|
||||
:doc: switch_mm tracepoint
|
||||
|
||||
Perf
|
||||
====
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,19 @@
|
||||
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
|
||||
int "Busywait for request completion (us)"
|
||||
default 5 # microseconds
|
||||
help
|
||||
Before sleeping waiting for a request (GPU operation) to complete,
|
||||
|
@ -44,14 +44,16 @@ i915-y += i915_drv.o \
|
||||
i915_irq.o \
|
||||
i915_params.o \
|
||||
i915_pci.o \
|
||||
i915_scatterlist.o \
|
||||
i915_suspend.o \
|
||||
i915_sysfs.o \
|
||||
intel_csr.o \
|
||||
intel_device_info.o \
|
||||
intel_pm.o \
|
||||
intel_runtime_pm.o \
|
||||
intel_wakeref.o \
|
||||
intel_uncore.o
|
||||
intel_sideband.o \
|
||||
intel_uncore.o \
|
||||
intel_wakeref.o
|
||||
|
||||
# core library code
|
||||
i915-y += \
|
||||
@ -62,7 +64,7 @@ i915-y += \
|
||||
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
|
||||
|
||||
# "Graphics Technology" (aka we talk to the gpu)
|
||||
@ -85,27 +87,41 @@ gt-$(CONFIG_DRM_I915_SELFTEST) += \
|
||||
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_pm.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 \
|
||||
@ -134,66 +150,74 @@ 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_gmbus.o \
|
||||
intel_hdmi.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 \
|
||||
selftests/igt_gem_utils.o \
|
||||
selftests/igt_live_test.o \
|
||||
selftests/igt_reset.o \
|
||||
selftests/igt_spinner.o
|
||||
@ -223,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
|
||||
|
@ -6,8 +6,6 @@ header_test := \
|
||||
i915_active_types.h \
|
||||
i915_debugfs.h \
|
||||
i915_drv.h \
|
||||
i915_gem_context_types.h \
|
||||
i915_gem_pm.h \
|
||||
i915_irq.h \
|
||||
i915_params.h \
|
||||
i915_priolist_types.h \
|
||||
@ -15,53 +13,12 @@ header_test := \
|
||||
i915_scheduler_types.h \
|
||||
i915_timeline_types.h \
|
||||
i915_utils.h \
|
||||
intel_acpi.h \
|
||||
intel_atomic.h \
|
||||
intel_atomic_plane.h \
|
||||
intel_audio.h \
|
||||
intel_bios.h \
|
||||
intel_cdclk.h \
|
||||
intel_color.h \
|
||||
intel_combo_phy.h \
|
||||
intel_connector.h \
|
||||
intel_crt.h \
|
||||
intel_csr.h \
|
||||
intel_ddi.h \
|
||||
intel_dp.h \
|
||||
intel_dp_aux_backlight.h \
|
||||
intel_dp_link_training.h \
|
||||
intel_dp_mst.h \
|
||||
intel_dpio_phy.h \
|
||||
intel_dpll_mgr.h \
|
||||
intel_drv.h \
|
||||
intel_dsi.h \
|
||||
intel_dsi_dcs_backlight.h \
|
||||
intel_dvo.h \
|
||||
intel_dvo_dev.h \
|
||||
intel_fbc.h \
|
||||
intel_fbdev.h \
|
||||
intel_fifo_underrun.h \
|
||||
intel_frontbuffer.h \
|
||||
intel_gmbus.h \
|
||||
intel_hdcp.h \
|
||||
intel_hdmi.h \
|
||||
intel_hotplug.h \
|
||||
intel_lpe_audio.h \
|
||||
intel_lspcon.h \
|
||||
intel_lvds.h \
|
||||
intel_overlay.h \
|
||||
intel_panel.h \
|
||||
intel_pipe_crc.h \
|
||||
intel_pm.h \
|
||||
intel_psr.h \
|
||||
intel_quirks.h \
|
||||
intel_runtime_pm.h \
|
||||
intel_sdvo.h \
|
||||
intel_sideband.h \
|
||||
intel_sprite.h \
|
||||
intel_tv.h \
|
||||
intel_uncore.h \
|
||||
intel_vdsc.h \
|
||||
intel_wakeref.h
|
||||
|
||||
quiet_cmd_header_test = HDRTEST $@
|
||||
|
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)))
|
@ -1380,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;
|
||||
@ -1472,6 +1579,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
|
||||
goto err;
|
||||
}
|
||||
|
||||
icl_dphy_param_init(intel_dsi);
|
||||
return;
|
||||
|
||||
err:
|
@ -105,6 +105,16 @@ int intel_digital_connector_atomic_set_property(struct drm_connector *connector,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -134,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;
|
@ -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__ */
|
@ -28,8 +28,9 @@
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/i915_drm.h>
|
||||
|
||||
#include "display/intel_gmbus.h"
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_gmbus.h"
|
||||
|
||||
#define _INTEL_BIOS_PRIVATE
|
||||
#include "intel_vbt_defs.h"
|
||||
@ -76,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;
|
||||
@ -302,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);
|
||||
@ -327,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;
|
||||
@ -351,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;
|
||||
|
||||
@ -371,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;
|
||||
|
||||
@ -1239,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
|
||||
@ -1267,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
|
||||
@ -1304,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1329,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)) {
|
||||
@ -1397,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;
|
||||
@ -1429,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)
|
||||
@ -1532,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)
|
||||
@ -2151,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,
|
@ -235,9 +235,9 @@ bool intel_bios_is_port_present(struct drm_i915_private *dev_priv, enum port por
|
||||
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(struct drm_i915_private *dev_priv,
|
||||
bool intel_bios_is_port_hpd_inverted(const struct drm_i915_private *i915,
|
||||
enum port port);
|
||||
bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv,
|
||||
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);
|
||||
|
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__ */
|
@ -809,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,
|
||||
@ -1531,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,
|
||||
@ -1865,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,
|
||||
@ -2283,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;
|
||||
}
|
||||
@ -2347,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);
|
||||
@ -2359,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);
|
||||
@ -2393,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;
|
||||
|
||||
@ -2447,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
|
||||
@ -2464,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);
|
||||
@ -2502,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);
|
||||
@ -2541,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);
|
||||
@ -2577,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;
|
||||
@ -2814,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,12 +886,19 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -879,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)
|
||||
{
|
||||
@ -959,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;
|
||||
@ -1209,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;
|
||||
}
|
@ -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__ */
|
@ -198,6 +198,10 @@ 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);
|
||||
|
||||
@ -275,6 +279,12 @@ static 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);
|
@ -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)
|
||||
{
|
@ -643,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;
|
||||
@ -663,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;
|
||||
@ -674,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;
|
||||
@ -702,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 */
|
||||
@ -716,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
|
||||
@ -728,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,
|
||||
@ -748,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;
|
||||
}
|
@ -615,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)) {
|
||||
@ -631,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) ||
|
||||
@ -653,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 {
|
||||
@ -1221,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
|
||||
@ -1241,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;
|
||||
}
|
||||
|
||||
@ -1613,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");
|
||||
@ -3650,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 =
|
||||
@ -3844,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
|
||||
@ -3955,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
@ -220,64 +220,6 @@ enum aux_ch {
|
||||
|
||||
#define aux_ch_name(a) ((a) + 'A')
|
||||
|
||||
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)
|
||||
|
||||
/* Used by dp and fdi links */
|
||||
struct intel_link_m_n {
|
||||
u32 tu;
|
||||
@ -364,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 && \
|
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__ */
|
@ -332,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;
|
||||
|
||||
@ -1081,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 */
|
||||
@ -1220,8 +1221,9 @@ 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;
|
||||
enum intel_display_power_domain aux_domain =
|
||||
@ -1237,7 +1239,7 @@ 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);
|
||||
|
||||
aux_wakeref = intel_display_power_get(dev_priv, aux_domain);
|
||||
aux_wakeref = intel_display_power_get(i915, aux_domain);
|
||||
pps_wakeref = pps_lock(intel_dp);
|
||||
|
||||
/*
|
||||
@ -1252,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);
|
||||
@ -1268,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",
|
||||
@ -1297,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
|
||||
@ -1374,18 +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, pps_wakeref);
|
||||
intel_display_power_put_async(dev_priv, aux_domain, aux_wakeref);
|
||||
intel_display_power_put_async(i915, aux_domain, aux_wakeref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -3994,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;
|
||||
|
||||
@ -7348,10 +7349,6 @@ 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;
|
@ -21,7 +21,8 @@
|
||||
* 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"
|
@ -454,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",
|
||||
@ -775,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);
|
||||
|
||||
@ -839,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);
|
||||
@ -856,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);
|
||||
@ -1425,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",
|
||||
@ -1857,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, "
|
||||
@ -1888,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[] = {
|
||||
@ -2371,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",
|
||||
@ -3171,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, "
|
||||
@ -3341,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);
|
@ -293,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;
|
||||
@ -343,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);
|
@ -199,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 */
|
@ -46,13 +46,6 @@
|
||||
#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
|
||||
@ -537,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)
|
||||
@ -888,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) */
|
@ -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;
|
||||
}
|
@ -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;
|
@ -88,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];
|
||||
@ -111,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);
|
||||
@ -186,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;
|
||||
}
|
||||
@ -201,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;
|
||||
|
||||
@ -229,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;
|
||||
|
||||
@ -248,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
|
@ -129,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;
|
||||
@ -152,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;
|
||||
@ -177,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;
|
||||
@ -550,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[] = {
|
||||
@ -563,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)
|
||||
@ -785,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,
|
||||
@ -1147,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);
|
||||
@ -1170,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)
|
||||
@ -1756,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) &&
|
||||
@ -1815,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);
|
||||
@ -1837,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
|
||||
@ -1889,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
|
||||
@ -1949,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);
|
||||
|
||||
@ -2376,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;
|
||||
}
|
||||
|
||||
@ -2648,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)
|
||||
{
|
||||
@ -2659,6 +2745,8 @@ intel_hdmi_connector_register(struct drm_connector *connector)
|
||||
|
||||
i915_debugfs_connector_add(connector);
|
||||
|
||||
intel_hdmi_create_i2c_symlink(connector);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2670,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,
|
||||
@ -2677,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,
|
||||
@ -2715,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);
|
||||
}
|
||||
@ -2860,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)
|
||||
{
|
||||
@ -2896,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);
|
@ -230,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) {
|
||||
@ -263,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,
|
@ -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
|
@ -29,6 +29,8 @@
|
||||
#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"
|
||||
@ -763,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;
|
||||
@ -1303,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)) {
|
||||
@ -1332,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;
|
||||
}
|
||||
|
||||
@ -1361,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);
|
||||
@ -1381,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);
|
||||
}
|
||||
|
@ -1288,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);
|
@ -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"
|
||||
@ -862,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -902,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;
|
||||
}
|
@ -522,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
|
||||
@ -585,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;
|
||||
}
|
||||
|
||||
@ -980,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)
|
||||
@ -1012,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))
|
||||
@ -1020,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;
|
||||
@ -1103,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,
|
||||
@ -1129,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;
|
@ -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__ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user