sound updates for 4.5-rc1
We've had quite busy weeks in this cycle. Looking at ALSA core, the significant changes are a few fixes wrt timer and sequencer ioctls that have been revealed by fuzzer recently. Other than that, ASoC core got a few updates about DAI link handling, but these are rather straightforward refactoring. In drivers scene, ASoC received quite lots of new drivers in addition to bunch of updates for still ongoing Intel Skylake support and topology API. HD-audio gained a new HDMI/DP hotplug notification via component. FireWire got a pile of code refactoring/updates with SCS.1x driver integration. More highlights are shown below. [NOTE: this contains also many commits for DRM. This is due to the pull of drm stable branch into sound tree, as the base of i915 audio component work for HD-audio. The highlights below don't contain these DRM changes, as these are supposed to be pulled via drm tree in anyway sooner or later.] Core - Handful fixes to harden ALSA timer and sequencer ioctls against races reported by syzkaller fuzzer - Irq description string can be unique to each card; only for HD-audio for now ASoC - Conversion of the array of DAI links to a list for supporting dynamically adding and removing DAI links - Topology API enhancements to make everything more component based and being able to specify PCM links via topology - Some more fixes for the topology code, though it is still not final and ready for enabling in production; we really need to get to the point where that can be done - A pile of changes for Intel SkyLake drivers which hopefully deliver some useful initial functionality for systems with this chipset, though there is more work still to come - Lots of new features and cleanups for the Renesas drivers - ANC support for WM5110 - New drivers: Imagination Technologies IPs, Atmel class D speaker, Cirrus CS47L24 and WM1831, Dialog DA7128, Realtek RT5659 and RT56156, Rockchip RK3036, TI PC3168A, and AMD ACP - Rename PCM1792a driver to be generic pcm179x HD-Audio - Use audio component for i915 HDMI/DP hotplug handling - On-demand binding with i915 driver - bdl_pos_adj parameter adjustment for Baytrail controllers - Enable power_save_node for CX20722; this shouldn't lead to regression, hopefully - Kabylake HDMI/DP codec support - Quirks for Lenovo E50-80, Dell Latitude E-series, and other Dell machines - A few code refactoring FireWire - Lots of code cleanup and refactoring - Integrate the support of SCS.1x devices into snd-oxfw driver; snd-scs1x driver is obsoleted USB-audio - Fix possible NULL dereference at disconnection - A regression fix for Native Instruments devices Misc - A few code cleanups of fm801 driver -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJWmmhNAAoJEGwxgFQ9KSmk/wsP/3eO+giAT9VRPa6qxR6VdT6I dZwTxcp4ZzUrgLxk9k5VYjqey6QL+1xWfl3Abrd+NzXDj1wo4KsDh2XCKG1btO9K UpIZf76Nzt7o91pzHbsU6mrjDeoVNqloZoGbg1utAmmegaXH3owd18p/ZHfE3sz2 BbaHmYW/R8lnaBgBhzqJB97+zRaLJmMWpWHfpHaIPjdfw8/V4j76jtPnpmv2hDZl BHXVHcQXjVGunFRzxdzBLuTC+FmhzUeTAbbAdOT4fEoOCv5MtZqYppNxdhj+b9l5 mrsXe5FBTNmrt9Z5TtfCuzgJPkzoDperFb0aKd7wI1jVMtLzkNCMlanHr9U6B6fr jSrs6l25xrpF1BBfRMfHjNudA5vng/XC5dtW00JofXSrIxtwPNUoDDiqJgw7xVm5 aVWK7KkQIjRbHdCQaeTymv70oHHKei92hbCrXUobXZ7wLeJMXNVPT25ttChWrgAI 7cu5h+K5PjReI/sJFTMPL4aHZ+jAn9quQl7vK8EXiL9E6G8lLiuBiVW6hjGd9At+ Z6UyGV+nCM6O3qZcyParMuLkNtWx9uT7Pcn8oTZAdKPngNhsf8+yl9qmsFkNLDC4 LKPx0+rdCjtMKn2du3krsHhG3EN9pLDrE6g5U3d6Cz83e69Y7fCuSjl31SjD91H0 bZDcM/ejYSbid3yKN4TL =Gvgb -----END PGP SIGNATURE----- Merge tag 'sound-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound Pull sound updates from Takashi Iwai: "We've had quite busy weeks in this cycle. Looking at ALSA core, the significant changes are a few fixes wrt timer and sequencer ioctls that have been revealed by fuzzer recently. Other than that, ASoC core got a few updates about DAI link handling, but these are rather straightforward refactoring. In drivers scene, ASoC received quite lots of new drivers in addition to bunch of updates for still ongoing Intel Skylake support and topology API. HD-audio gained a new HDMI/DP hotplug notification via component. FireWire got a pile of code refactoring/updates with SCS.1x driver integration. More highlights are shown below. [ NOTE: this contains also many commits for DRM. This is due to the pull of drm stable branch into sound tree, as the base of i915 audio component work for HD-audio. The highlights below don't contain these DRM changes, as these are supposed to be pulled via drm tree in anyway sooner or later. ] Core: - Handful fixes to harden ALSA timer and sequencer ioctls against races reported by syzkaller fuzzer - Irq description string can be unique to each card; only for HD-audio for now ASoC: - Conversion of the array of DAI links to a list for supporting dynamically adding and removing DAI links - Topology API enhancements to make everything more component based and being able to specify PCM links via topology - Some more fixes for the topology code, though it is still not final and ready for enabling in production; we really need to get to the point where that can be done - A pile of changes for Intel SkyLake drivers which hopefully deliver some useful initial functionality for systems with this chipset, though there is more work still to come - Lots of new features and cleanups for the Renesas drivers - ANC support for WM5110 - New drivers: Imagination Technologies IPs, Atmel class D speaker, Cirrus CS47L24 and WM1831, Dialog DA7128, Realtek RT5659 and RT56156, Rockchip RK3036, TI PC3168A, and AMD ACP - Rename PCM1792a driver to be generic pcm179x HD-Audio: - Use audio component for i915 HDMI/DP hotplug handling - On-demand binding with i915 driver - bdl_pos_adj parameter adjustment for Baytrail controllers - Enable power_save_node for CX20722; this shouldn't lead to regression, hopefully - Kabylake HDMI/DP codec support - Quirks for Lenovo E50-80, Dell Latitude E-series, and other Dell machines - A few code refactoring FireWire: - Lots of code cleanup and refactoring - Integrate the support of SCS.1x devices into snd-oxfw driver; snd-scs1x driver is obsoleted USB-audio: - Fix possible NULL dereference at disconnection - A regression fix for Native Instruments devices Misc: - A few code cleanups of fm801 driver" * tag 'sound-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (722 commits) ALSA: timer: Code cleanup ALSA: timer: Harden slave timer list handling ALSA: hda - Add fixup for Dell Latitidue E6540 ALSA: timer: Fix race among timer ioctls ALSA: hda - add codec support for Kabylake display audio codec ALSA: timer: Fix double unlink of active_list ALSA: usb-audio: Fix mixer ctl regression of Native Instrument devices ALSA: hda - fix the headset mic detection problem for a Dell laptop ALSA: hda - Fix white noise on Dell Latitude E5550 ALSA: hda_intel: add card number to irq description ALSA: seq: Fix race at timer setup and close ALSA: seq: Fix missing NULL check at remove_events ioctl ALSA: usb-audio: Avoid calling usb_autopm_put_interface() at disconnect ASoC: hdac_hdmi: remove unused hdac_hdmi_query_pin_connlist ASoC: AMD: Add missing include file ALSA: hda - Fixup inverted internal mic for Lenovo E50-80 ALSA: usb: Add native DSD support for Oppo HA-1 ASoC: Make aux_dev more like a generic component ASoC: bcm2835: cleanup includes by ordering them alphabetically ASoC: AMD: Manage ACP 2.x SRAM banks power ...
This commit is contained in:
commit
a016af2e70
|
@ -615,18 +615,6 @@ char *date;</synopsis>
|
|||
<function>drm_gem_object_init</function>. Storage for private GEM
|
||||
objects must be managed by drivers.
|
||||
</para>
|
||||
<para>
|
||||
Drivers that do not need to extend GEM objects with private information
|
||||
can call the <function>drm_gem_object_alloc</function> function to
|
||||
allocate and initialize a struct <structname>drm_gem_object</structname>
|
||||
instance. The GEM core will call the optional driver
|
||||
<methodname>gem_init_object</methodname> operation after initializing
|
||||
the GEM object with <function>drm_gem_object_init</function>.
|
||||
<synopsis>int (*gem_init_object) (struct drm_gem_object *obj);</synopsis>
|
||||
</para>
|
||||
<para>
|
||||
No alloc-and-init function exists for private GEM objects.
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3>
|
||||
<title>GEM Objects Lifetime</title>
|
||||
|
@ -635,10 +623,10 @@ char *date;</synopsis>
|
|||
acquired and release by <function>calling drm_gem_object_reference</function>
|
||||
and <function>drm_gem_object_unreference</function> respectively. The
|
||||
caller must hold the <structname>drm_device</structname>
|
||||
<structfield>struct_mutex</structfield> lock. As a convenience, GEM
|
||||
provides the <function>drm_gem_object_reference_unlocked</function> and
|
||||
<function>drm_gem_object_unreference_unlocked</function> functions that
|
||||
can be called without holding the lock.
|
||||
<structfield>struct_mutex</structfield> lock when calling
|
||||
<function>drm_gem_object_reference</function>. As a convenience, GEM
|
||||
provides <function>drm_gem_object_unreference_unlocked</function>
|
||||
functions that can be called without holding the lock.
|
||||
</para>
|
||||
<para>
|
||||
When the last reference to a GEM object is released the GEM core calls
|
||||
|
@ -649,15 +637,9 @@ char *date;</synopsis>
|
|||
</para>
|
||||
<para>
|
||||
<synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis>
|
||||
Drivers are responsible for freeing all GEM object resources, including
|
||||
the resources created by the GEM core. If an mmap offset has been
|
||||
created for the object (in which case
|
||||
<structname>drm_gem_object</structname>::<structfield>map_list</structfield>::<structfield>map</structfield>
|
||||
is not NULL) it must be freed by a call to
|
||||
<function>drm_gem_free_mmap_offset</function>. The shmfs backing store
|
||||
must be released by calling <function>drm_gem_object_release</function>
|
||||
(that function can safely be called if no shmfs backing store has been
|
||||
created).
|
||||
Drivers are responsible for freeing all GEM object resources. This includes
|
||||
the resources created by the GEM core, which need to be released with
|
||||
<function>drm_gem_object_release</function>.
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3>
|
||||
|
@ -740,17 +722,10 @@ char *date;</synopsis>
|
|||
DRM identifies the GEM object to be mapped by a fake offset passed
|
||||
through the mmap offset argument. Prior to being mapped, a GEM object
|
||||
must thus be associated with a fake offset. To do so, drivers must call
|
||||
<function>drm_gem_create_mmap_offset</function> on the object. The
|
||||
function allocates a fake offset range from a pool and stores the
|
||||
offset divided by PAGE_SIZE in
|
||||
<literal>obj->map_list.hash.key</literal>. Care must be taken not to
|
||||
call <function>drm_gem_create_mmap_offset</function> if a fake offset
|
||||
has already been allocated for the object. This can be tested by
|
||||
<literal>obj->map_list.map</literal> being non-NULL.
|
||||
<function>drm_gem_create_mmap_offset</function> on the object.
|
||||
</para>
|
||||
<para>
|
||||
Once allocated, the fake offset value
|
||||
(<literal>obj->map_list.hash.key << PAGE_SHIFT</literal>)
|
||||
must be passed to the application in a driver-specific way and can then
|
||||
be used as the mmap offset argument.
|
||||
</para>
|
||||
|
@ -836,10 +811,11 @@ char *date;</synopsis>
|
|||
abstracted from the client in libdrm.
|
||||
</para>
|
||||
</sect3>
|
||||
<sect3>
|
||||
<title>GEM Function Reference</title>
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>GEM Function Reference</title>
|
||||
!Edrivers/gpu/drm/drm_gem.c
|
||||
</sect3>
|
||||
!Iinclude/drm/drm_gem.h
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>VMA Offset Manager</title>
|
||||
|
@ -4201,17 +4177,21 @@ int num_ioctls;</synopsis>
|
|||
</sect2>
|
||||
</sect1>
|
||||
<sect1>
|
||||
<title>GuC-based Command Submission</title>
|
||||
<title>GuC</title>
|
||||
<sect2>
|
||||
<title>GuC</title>
|
||||
<title>GuC-specific firmware loader</title>
|
||||
!Pdrivers/gpu/drm/i915/intel_guc_loader.c GuC-specific firmware loader
|
||||
!Idrivers/gpu/drm/i915/intel_guc_loader.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>GuC Client</title>
|
||||
!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submissison
|
||||
<title>GuC-based command submission</title>
|
||||
!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submission
|
||||
!Idrivers/gpu/drm/i915/i915_guc_submission.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>GuC Firmware Layout</title>
|
||||
!Pdrivers/gpu/drm/i915/intel_guc_fwif.h GuC Firmware Layout
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<sect1>
|
||||
|
|
|
@ -7,6 +7,16 @@ Required properties:
|
|||
- compatible : "asahi-kasei,ak4613"
|
||||
- reg : The chip select number on the I2C bus
|
||||
|
||||
Optional properties:
|
||||
- asahi-kasei,in1-single-end : Boolean. Indicate input / output pins are single-ended.
|
||||
- asahi-kasei,in2-single-end rather than differential.
|
||||
- asahi-kasei,out1-single-end
|
||||
- asahi-kasei,out2-single-end
|
||||
- asahi-kasei,out3-single-end
|
||||
- asahi-kasei,out4-single-end
|
||||
- asahi-kasei,out5-single-end
|
||||
- asahi-kasei,out6-single-end
|
||||
|
||||
Example:
|
||||
|
||||
&i2c {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
* Atmel PDMIC driver under ALSA SoC architecture
|
||||
|
||||
Required properties:
|
||||
- compatible
|
||||
Should be "atmel,sama5d2-pdmic".
|
||||
- reg
|
||||
Should contain PDMIC registers location and length.
|
||||
- interrupts
|
||||
Should contain the IRQ line for the PDMIC.
|
||||
- dmas
|
||||
One DMA specifiers as described in atmel-dma.txt and dma.txt files.
|
||||
- dma-names
|
||||
Must be "rx".
|
||||
- clock-names
|
||||
Required elements:
|
||||
- "pclk" peripheral clock
|
||||
- "gclk" generated clock
|
||||
- clocks
|
||||
Must contain an entry for each required entry in clock-names.
|
||||
Please refer to clock-bindings.txt.
|
||||
- atmel,mic-min-freq
|
||||
The minimal frequency that the micphone supports.
|
||||
- atmel,mic-max-freq
|
||||
The maximal frequency that the micphone supports.
|
||||
|
||||
Optional properties:
|
||||
- pinctrl-names, pinctrl-0
|
||||
Please refer to pinctrl-bindings.txt.
|
||||
- atmel,model
|
||||
The user-visible name of this sound card.
|
||||
The default value is "PDMIC".
|
||||
- atmel,mic-offset
|
||||
The offset that should be added.
|
||||
The range is from -32768 to 32767.
|
||||
The default value is 0.
|
||||
|
||||
Example:
|
||||
pdmic@f8018000 {
|
||||
compatible = "atmel,sama5d2-pdmic";
|
||||
reg = <0xf8018000 0x124>;
|
||||
interrupts = <48 IRQ_TYPE_LEVEL_HIGH 7>;
|
||||
dmas = <&dma0
|
||||
(AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1)
|
||||
| AT91_XDMAC_DT_PERID(50))>;
|
||||
dma-names = "rx";
|
||||
clocks = <&pdmic_clk>, <&pdmic_gclk>;
|
||||
clock-names = "pclk", "gclk";
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_pdmic_default>;
|
||||
atmel,model = "PDMIC @ sama5d2_xplained";
|
||||
atmel,mic-min-freq = <1000000>;
|
||||
atmel,mic-max-freq = <3246000>;
|
||||
atmel,mic-offset = <0x0>;
|
||||
};
|
|
@ -0,0 +1,104 @@
|
|||
Dialog Semiconductor DA7218 Audio Codec bindings
|
||||
|
||||
DA7218 is an audio codec with HP detect feature.
|
||||
|
||||
======
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "dlg,da7217" or "dlg,da7218"
|
||||
- reg: Specifies the I2C slave address
|
||||
|
||||
- VDD-supply: VDD power supply for the device
|
||||
- VDDMIC-supply: VDDMIC power supply for the device
|
||||
- VDDIO-supply: VDDIO power supply for the device
|
||||
(See Documentation/devicetree/bindings/regulator/regulator.txt for further
|
||||
information relating to regulators)
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Specifies the phandle of the interrupt controller to which
|
||||
the IRQs from DA7218 are delivered to.
|
||||
- interrupts: IRQ line info for DA7218 chip.
|
||||
(See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
|
||||
further information relating to interrupt properties)
|
||||
- interrupt-names : Name associated with interrupt line. Should be "wakeup" if
|
||||
interrupt is to be used to wake system, otherwise "irq" should be used.
|
||||
- wakeup-source: Flag to indicate this device can wake system (suspend/resume).
|
||||
|
||||
- clocks : phandle and clock specifier for codec MCLK.
|
||||
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
|
||||
|
||||
- dlg,micbias1-lvl-millivolt : Voltage (mV) for Mic Bias 1
|
||||
[<1200>, <1600>, <1800>, <2000>, <2200>, <2400>, <2600>, <2800>, <3000>]
|
||||
- dlg,micbias2-lvl-millivolt : Voltage (mV) for Mic Bias 2
|
||||
[<1200>, <1600>, <1800>, <2000>, <2200>, <2400>, <2600>, <2800>, <3000>]
|
||||
- dlg,mic1-amp-in-sel : Mic1 input source type
|
||||
["diff", "se_p", "se_n"]
|
||||
- dlg,mic2-amp-in-sel : Mic2 input source type
|
||||
["diff", "se_p", "se_n"]
|
||||
- dlg,dmic1-data-sel : DMIC1 channel select based on clock edge.
|
||||
["lrise_rfall", "lfall_rrise"]
|
||||
- dlg,dmic1-samplephase : When to sample audio from DMIC1.
|
||||
["on_clkedge", "between_clkedge"]
|
||||
- dlg,dmic1-clkrate-hz : DMic1 clock frequency (Hz).
|
||||
[<1500000>, <3000000>]
|
||||
- dlg,dmic2-data-sel : DMic2 channel select based on clock edge.
|
||||
["lrise_rfall", "lfall_rrise"]
|
||||
- dlg,dmic2-samplephase : When to sample audio from DMic2.
|
||||
["on_clkedge", "between_clkedge"]
|
||||
- dlg,dmic2-clkrate-hz : DMic2 clock frequency (Hz).
|
||||
[<1500000>, <3000000>]
|
||||
- dlg,hp-diff-single-supply : Boolean flag, use single supply for HP
|
||||
(DA7217 only)
|
||||
|
||||
======
|
||||
|
||||
Optional Child node - 'da7218_hpldet' (DA7218 only):
|
||||
|
||||
Optional properties:
|
||||
- dlg,jack-rate-us : Time between jack detect measurements (us)
|
||||
[<5>, <10>, <20>, <40>, <80>, <160>, <320>, <640>]
|
||||
- dlg,jack-debounce : Number of debounce measurements taken for jack detect
|
||||
[<0>, <2>, <3>, <4>]
|
||||
- dlg,jack-threshold-pct : Threshold level for jack detection (% of VDD)
|
||||
[<84>, <88>, <92>, <96>]
|
||||
- dlg,comp-inv : Boolean flag, invert comparator output
|
||||
- dlg,hyst : Boolean flag, enable hysteresis
|
||||
- dlg,discharge : Boolean flag, auto discharge of Mic Bias on jack removal
|
||||
|
||||
======
|
||||
|
||||
Example:
|
||||
|
||||
codec: da7218@1a {
|
||||
compatible = "dlg,da7218";
|
||||
reg = <0x1a>;
|
||||
interrupt-parent = <&gpio6>;
|
||||
interrupts = <11 IRQ_TYPE_LEVEL_HIGH>;
|
||||
wakeup-source;
|
||||
|
||||
VDD-supply = <®_audio>;
|
||||
VDDMIC-supply = <®_audio>;
|
||||
VDDIO-supply = <®_audio>;
|
||||
|
||||
clocks = <&clks 201>;
|
||||
clock-names = "mclk";
|
||||
|
||||
dlg,micbias1-lvl-millivolt = <2600>;
|
||||
dlg,micbias2-lvl-millivolt = <2600>;
|
||||
dlg,mic1-amp-in-sel = "diff";
|
||||
dlg,mic2-amp-in-sel = "diff";
|
||||
|
||||
dlg,dmic1-data-sel = "lrise_rfall";
|
||||
dlg,dmic1-samplephase = "on_clkedge";
|
||||
dlg,dmic1-clkrate-hz = <3000000>;
|
||||
dlg,dmic2-data-sel = "lrise_rfall";
|
||||
dlg,dmic2-samplephase = "on_clkedge";
|
||||
dlg,dmic2-clkrate-hz = <3000000>;
|
||||
|
||||
da7218_hpldet {
|
||||
dlg,jack-rate-us = <40>;
|
||||
dlg,jack-debounce = <2>;
|
||||
dlg,jack-threshold-pct = <84>;
|
||||
dlg,hyst;
|
||||
};
|
||||
};
|
|
@ -28,13 +28,15 @@ Optional properties:
|
|||
- clocks : phandle and clock specifier for codec MCLK.
|
||||
- clock-names : Clock name string for 'clocks' attribute, should be "mclk".
|
||||
|
||||
- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine
|
||||
[<1050>, <1100>, <1200>, <1400>]
|
||||
- dlg,micbias-lvl : Voltage (mV) for Mic Bias
|
||||
[<1800>, <2000>, <2200>, <2400>, <2600>]
|
||||
[<1600>, <1800>, <2000>, <2200>, <2400>, <2600>]
|
||||
- dlg,mic-amp-in-sel : Mic input source type
|
||||
["diff", "se_p", "se_n"]
|
||||
|
||||
Deprecated properties:
|
||||
- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine
|
||||
(LDO unavailable in production HW so property no longer required).
|
||||
|
||||
======
|
||||
|
||||
Child node - 'da7219_aad':
|
||||
|
|
|
@ -25,6 +25,11 @@ Required properties:
|
|||
"mem" Peripheral access clock to access registers.
|
||||
"ipg" Peripheral clock to driver module.
|
||||
"asrck_<0-f>" Clock sources for input and output clock.
|
||||
"spba" The spba clock is required when ASRC is placed as a
|
||||
bus slave of the Shared Peripheral Bus and when two
|
||||
or more bus masters (CPU, DMA or DSP) try to access
|
||||
it. This property is optional depending on the SoC
|
||||
design.
|
||||
|
||||
- big-endian : If this property is absent, the little endian mode
|
||||
will be in use as default. Otherwise, the big endian
|
||||
|
|
|
@ -27,6 +27,11 @@ Required properties:
|
|||
derive HCK, SCK and FS.
|
||||
"fsys" The system clock derived from ahb clock used to
|
||||
derive HCK, SCK and FS.
|
||||
"spba" The spba clock is required when ESAI is placed as a
|
||||
bus slave of the Shared Peripheral Bus and when two
|
||||
or more bus masters (CPU, DMA or DSP) try to access
|
||||
it. This property is optional depending on the SoC
|
||||
design.
|
||||
|
||||
- fsl,fifo-depth : The number of elements in the transmit and receive
|
||||
FIFOs. This number is the maximum allowed value for
|
||||
|
|
|
@ -27,6 +27,11 @@ Required properties:
|
|||
Transceiver Clock Diagram" of SoC reference manual.
|
||||
It can also be referred to TxClk_Source bit of
|
||||
register SPDIF_STC.
|
||||
"spba" The spba clock is required when SPDIF is placed as a
|
||||
bus slave of the Shared Peripheral Bus and when two
|
||||
or more bus masters (CPU, DMA or DSP) try to access
|
||||
it. This property is optional depending on the SoC
|
||||
design.
|
||||
|
||||
- big-endian : If this property is absent, the native endian mode
|
||||
will be in use as default, or the big endian mode
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
Imagination Technologies I2S Input Controller
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible : Compatible list, must contain "img,i2s-in"
|
||||
|
||||
- #sound-dai-cells : Must be equal to 0
|
||||
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names
|
||||
|
||||
- clock-names : Must include the following entry:
|
||||
"sys" The system clock
|
||||
|
||||
- dmas: Contains an entry for each entry in dma-names.
|
||||
|
||||
- dma-names: Must include the following entry:
|
||||
"rx" Single DMA channel used by all active I2S channels
|
||||
|
||||
- img,i2s-channels : Number of I2S channels instantiated in the I2S in block
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- interrupts : Contains the I2S in interrupts. Depending on
|
||||
the configuration, there may be no interrupts, one interrupt,
|
||||
or an interrupt per I2S channel. For the case where there is
|
||||
one interrupt per channel, the interrupts should be listed
|
||||
in ascending channel order
|
||||
|
||||
- resets: Contains a phandle to the I2S in reset signal
|
||||
|
||||
- reset-names: Contains the reset signal name "rst"
|
||||
|
||||
Example:
|
||||
|
||||
i2s_in: i2s-in@18100800 {
|
||||
compatible = "img,i2s-in";
|
||||
reg = <0x18100800 0x200>;
|
||||
interrupts = <GIC_SHARED 7 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&mdc 30 0xffffffff 0>;
|
||||
dma-names = "rx";
|
||||
clocks = <&cr_periph SYS_CLK_I2S_IN>;
|
||||
clock-names = "sys";
|
||||
img,i2s-channels = <6>;
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
Imagination Technologies I2S Output Controller
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible : Compatible list, must contain "img,i2s-out"
|
||||
|
||||
- #sound-dai-cells : Must be equal to 0
|
||||
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names
|
||||
|
||||
- clock-names : Must include the following entries:
|
||||
"sys" The system clock
|
||||
"ref" The reference clock
|
||||
|
||||
- dmas: Contains an entry for each entry in dma-names.
|
||||
|
||||
- dma-names: Must include the following entry:
|
||||
"tx" Single DMA channel used by all active I2S channels
|
||||
|
||||
- img,i2s-channels : Number of I2S channels instantiated in the I2S out block
|
||||
|
||||
- resets: Contains a phandle to the I2S out reset signal
|
||||
|
||||
- reset-names: Contains the reset signal name "rst"
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- interrupts : Contains the I2S out interrupts. Depending on
|
||||
the configuration, there may be no interrupts, one interrupt,
|
||||
or an interrupt per I2S channel. For the case where there is
|
||||
one interrupt per channel, the interrupts should be listed
|
||||
in ascending channel order
|
||||
|
||||
Example:
|
||||
|
||||
i2s_out: i2s-out@18100A00 {
|
||||
compatible = "img,i2s-out";
|
||||
reg = <0x18100A00 0x200>;
|
||||
interrupts = <GIC_SHARED 13 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&mdc 23 0xffffffff 0>;
|
||||
dma-names = "tx";
|
||||
clocks = <&cr_periph SYS_CLK_I2S_OUT>,
|
||||
<&clk_core CLK_I2S>;
|
||||
clock-names = "sys", "ref";
|
||||
img,i2s-channels = <6>;
|
||||
resets = <&pistachio_reset PISTACHIO_RESET_I2S_OUT>;
|
||||
reset-names = "rst";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
Imagination Technologies Parallel Output Controller
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible : Compatible list, must contain "img,parallel-out".
|
||||
|
||||
- #sound-dai-cells : Must be equal to 0
|
||||
|
||||
- reg : Offset and length of the register set for the device.
|
||||
|
||||
- dmas: Contains an entry for each entry in dma-names.
|
||||
|
||||
- dma-names: Must include the following entry:
|
||||
"tx"
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"sys" The system clock
|
||||
"ref" The reference clock
|
||||
|
||||
- resets: Contains a phandle to the parallel out reset signal
|
||||
|
||||
- reset-names: Contains the reset signal name "rst"
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- interrupts : Contains the parallel out interrupt, if present
|
||||
|
||||
Example:
|
||||
|
||||
parallel_out: parallel-out@18100C00 {
|
||||
compatible = "img,parallel-out";
|
||||
reg = <0x18100C00 0x100>;
|
||||
interrupts = <GIC_SHARED 19 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&mdc 16 0xffffffff 0>;
|
||||
dma-names = "tx";
|
||||
clocks = <&cr_periph SYS_CLK_PAUD_OUT>,
|
||||
<&clk_core CLK_AUDIO_DAC>;
|
||||
clock-names = "sys", "ref";
|
||||
resets = <&pistachio_reset PISTACHIO_RESET_PRL_OUT>;
|
||||
reset-names = "rst";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,18 @@
|
|||
Pistachio internal DAC DT bindings
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "img,pistachio-internal-dac"
|
||||
|
||||
- img,cr-top : Must contain a phandle to the top level control syscon
|
||||
node which contains the internal dac control registers
|
||||
|
||||
- VDD-supply : Digital power supply regulator (+1.8V or +3.3V)
|
||||
|
||||
Examples:
|
||||
|
||||
internal_dac: internal-dac {
|
||||
compatible = "img,pistachio-internal-dac";
|
||||
img,cr-top = <&cr_top>;
|
||||
VDD-supply = <&supply3v3>;
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
Imagination Technologies SPDIF Input Controller
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible : Compatible list, must contain "img,spdif-in"
|
||||
|
||||
- #sound-dai-cells : Must be equal to 0
|
||||
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
- dmas: Contains an entry for each entry in dma-names.
|
||||
|
||||
- dma-names: Must include the following entry:
|
||||
"rx"
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"sys" The system clock
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- resets: Should contain a phandle to the spdif in reset signal, if any
|
||||
|
||||
- reset-names: Should contain the reset signal name "rst", if a
|
||||
reset phandle is given
|
||||
|
||||
- interrupts : Contains the spdif in interrupt, if present
|
||||
|
||||
Example:
|
||||
|
||||
spdif_in: spdif-in@18100E00 {
|
||||
compatible = "img,spdif-in";
|
||||
reg = <0x18100E00 0x100>;
|
||||
interrupts = <GIC_SHARED 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&mdc 15 0xffffffff 0>;
|
||||
dma-names = "rx";
|
||||
clocks = <&cr_periph SYS_CLK_SPDIF_IN>;
|
||||
clock-names = "sys";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
Imagination Technologies SPDIF Output Controller
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible : Compatible list, must contain "img,spdif-out"
|
||||
|
||||
- #sound-dai-cells : Must be equal to 0
|
||||
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
- dmas: Contains an entry for each entry in dma-names.
|
||||
|
||||
- dma-names: Must include the following entry:
|
||||
"tx"
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names.
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"sys" The system clock
|
||||
"ref" The reference clock
|
||||
|
||||
- resets: Contains a phandle to the spdif out reset signal
|
||||
|
||||
- reset-names: Contains the reset signal name "rst"
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- interrupts : Contains the parallel out interrupt, if present
|
||||
|
||||
Example:
|
||||
|
||||
spdif_out: spdif-out@18100D00 {
|
||||
compatible = "img,spdif-out";
|
||||
reg = <0x18100D00 0x100>;
|
||||
interrupts = <GIC_SHARED 21 IRQ_TYPE_LEVEL_HIGH>;
|
||||
dmas = <&mdc 14 0xffffffff 0>;
|
||||
dma-names = "tx";
|
||||
clocks = <&cr_periph SYS_CLK_SPDIF_OUT>,
|
||||
<&clk_core CLK_SPDIF>;
|
||||
clock-names = "sys", "ref";
|
||||
resets = <&pistachio_reset PISTACHIO_RESET_SPDIF_OUT>;
|
||||
reset-names = "rst";
|
||||
#sound-dai-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
Inno audio codec for RK3036
|
||||
|
||||
Inno audio codec is integrated inside RK3036 SoC.
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "rockchip,rk3036-codec".
|
||||
- reg : The registers of codec.
|
||||
- clock-names : Should be "acodec_pclk".
|
||||
- clocks : The clock of codec.
|
||||
- rockchip,grf : The phandle of grf device node.
|
||||
|
||||
Example:
|
||||
|
||||
acodec: acodec-ana@20030000 {
|
||||
compatible = "rk3036-codec";
|
||||
reg = <0x20030000 0x4000>;
|
||||
rockchip,grf = <&grf>;
|
||||
clock-names = "acodec_pclk";
|
||||
clocks = <&cru ACLK_VCODEC>;
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
Texas Instruments pcm1792a DT bindings
|
||||
Texas Instruments pcm179x DT bindings
|
||||
|
||||
This driver supports the SPI bus.
|
||||
|
|
@ -7,8 +7,11 @@ Required properties:
|
|||
"renesas,rcar_sound-gen3" if generation3
|
||||
Examples with soctypes are:
|
||||
- "renesas,rcar_sound-r8a7778" (R-Car M1A)
|
||||
- "renesas,rcar_sound-r8a7779" (R-Car H1)
|
||||
- "renesas,rcar_sound-r8a7790" (R-Car H2)
|
||||
- "renesas,rcar_sound-r8a7791" (R-Car M2-W)
|
||||
- "renesas,rcar_sound-r8a7793" (R-Car M2-N)
|
||||
- "renesas,rcar_sound-r8a7794" (R-Car E2)
|
||||
- "renesas,rcar_sound-r8a7795" (R-Car H3)
|
||||
- reg : Should contain the register physical address.
|
||||
required register is
|
||||
|
@ -34,6 +37,8 @@ Required properties:
|
|||
see below for detail.
|
||||
- #sound-dai-cells : it must be 0 if your system is using single DAI
|
||||
it must be 1 if your system is using multi DAI
|
||||
|
||||
Optional properties:
|
||||
- #clock-cells : it must be 0 if your system has audio_clkout
|
||||
it must be 1 if your system has audio_clkout0/1/2/3
|
||||
- clock-frequency : for all audio_clkout0/1/2/3
|
||||
|
@ -244,3 +249,80 @@ rcar_sound: sound@ec500000 {
|
|||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example: simple sound card
|
||||
|
||||
rsnd_ak4643: sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
simple-audio-card,format = "left_j";
|
||||
simple-audio-card,bitclock-master = <&sndcodec>;
|
||||
simple-audio-card,frame-master = <&sndcodec>;
|
||||
|
||||
sndcpu: simple-audio-card,cpu {
|
||||
sound-dai = <&rcar_sound>;
|
||||
};
|
||||
|
||||
sndcodec: simple-audio-card,codec {
|
||||
sound-dai = <&ak4643>;
|
||||
clocks = <&audio_clock>;
|
||||
};
|
||||
};
|
||||
|
||||
&rcar_sound {
|
||||
pinctrl-0 = <&sound_pins &sound_clk_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
/* Single DAI */
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
rcar_sound,dai {
|
||||
dai0 {
|
||||
playback = <&ssi0 &src2 &dvc0>;
|
||||
capture = <&ssi1 &src3 &dvc1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&ssi1 {
|
||||
shared-pin;
|
||||
};
|
||||
|
||||
Example: simple sound card for TDM
|
||||
|
||||
rsnd_tdm: sound {
|
||||
compatible = "simple-audio-card";
|
||||
|
||||
simple-audio-card,format = "left_j";
|
||||
simple-audio-card,bitclock-master = <&sndcodec>;
|
||||
simple-audio-card,frame-master = <&sndcodec>;
|
||||
|
||||
sndcpu: simple-audio-card,cpu {
|
||||
sound-dai = <&rcar_sound>;
|
||||
dai-tdm-slot-num = <6>;
|
||||
};
|
||||
|
||||
sndcodec: simple-audio-card,codec {
|
||||
sound-dai = <&xxx>;
|
||||
};
|
||||
};
|
||||
|
||||
Example: simple sound card for Multi channel
|
||||
|
||||
&rcar_sound {
|
||||
pinctrl-0 = <&sound_pins &sound_clk_pins>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
/* Single DAI */
|
||||
#sound-dai-cells = <0>;
|
||||
|
||||
status = "okay";
|
||||
|
||||
rcar_sound,dai {
|
||||
dai0 {
|
||||
playback = <&ssi0 &ssi1 &ssi2 &src0 &dvc0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -4,8 +4,8 @@ Renesas Sampling Rate Convert Sound Card specifies audio DAI connections of SoC
|
|||
|
||||
Required properties:
|
||||
|
||||
- compatible : "renesas,rsrc-card,<board>"
|
||||
Examples with soctypes are:
|
||||
- compatible : "renesas,rsrc-card{,<board>}"
|
||||
Examples with boards are:
|
||||
- "renesas,rsrc-card"
|
||||
- "renesas,rsrc-card,lager"
|
||||
- "renesas,rsrc-card,koelsch"
|
||||
|
|
|
@ -19,6 +19,7 @@ Required properties:
|
|||
- clock-names: should contain followings:
|
||||
- "i2s_hclk": clock for I2S BUS
|
||||
- "i2s_clk" : clock for I2S controller
|
||||
- rockchip,playback-channels: max playback channels, if not set, 8 channels default.
|
||||
- rockchip,capture-channels: max capture channels, if not set, 2 channels default.
|
||||
|
||||
Example for rk3288 I2S controller:
|
||||
|
@ -31,5 +32,6 @@ i2s@ff890000 {
|
|||
dma-names = "tx", "rx";
|
||||
clock-names = "i2s_hclk", "i2s_clk";
|
||||
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
|
||||
rockchip,playback-channels = <8>;
|
||||
rockchip,capture-channels = <2>;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
RT5616 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5616".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5616:
|
||||
|
||||
* IN1P
|
||||
* IN2P
|
||||
* IN2N
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* HPOL
|
||||
* HPOR
|
||||
|
||||
Example:
|
||||
|
||||
codec: rt5616@1b {
|
||||
compatible = "realtek,rt5616";
|
||||
reg = <0x1b>;
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
RT5651 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : "realtek,rt5651".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- realtek,in2-differential
|
||||
Boolean. Indicate MIC2 input are differential, rather than single-ended.
|
||||
|
||||
- realtek,dmic-en
|
||||
Boolean. true if dmic is used.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5651:
|
||||
|
||||
* DMIC L1
|
||||
* DMIC R1
|
||||
* IN1P
|
||||
* IN2P
|
||||
* IN2N
|
||||
* IN3P
|
||||
* HPOL
|
||||
* HPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* PDML
|
||||
* PDMR
|
||||
|
||||
Example:
|
||||
|
||||
codec: rt5651@1a {
|
||||
compatible = "realtek,rt5651";
|
||||
reg = <0x1a>;
|
||||
realtek,dmic-en = "true";
|
||||
realtek,in2-diff = "false";
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
RT5659/RT5658 audio CODEC
|
||||
|
||||
This device supports I2C only.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : One of "realtek,rt5659" or "realtek,rt5658".
|
||||
|
||||
- reg : The I2C address of the device.
|
||||
|
||||
- interrupts : The CODEC's interrupt output.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- realtek,in1-differential
|
||||
- realtek,in3-differential
|
||||
- realtek,in4-differential
|
||||
Boolean. Indicate MIC1/3/4 input are differential, rather than single-ended.
|
||||
|
||||
- realtek,dmic1-data-pin
|
||||
0: dmic1 is not used
|
||||
1: using IN2N pin as dmic1 data pin
|
||||
2: using GPIO5 pin as dmic1 data pin
|
||||
3: using GPIO9 pin as dmic1 data pin
|
||||
4: using GPIO11 pin as dmic1 data pin
|
||||
|
||||
- realtek,dmic2-data-pin
|
||||
0: dmic2 is not used
|
||||
1: using IN2P pin as dmic2 data pin
|
||||
2: using GPIO6 pin as dmic2 data pin
|
||||
3: using GPIO10 pin as dmic2 data pin
|
||||
4: using GPIO12 pin as dmic2 data pin
|
||||
|
||||
- realtek,jd-src
|
||||
0: No JD is used
|
||||
1: using JD3 as JD source
|
||||
|
||||
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
|
||||
- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
|
||||
|
||||
Pins on the device (for linking into audio routes) for RT5659/RT5658:
|
||||
|
||||
* DMIC L1
|
||||
* DMIC R1
|
||||
* DMIC L2
|
||||
* DMIC R2
|
||||
* IN1P
|
||||
* IN1N
|
||||
* IN2P
|
||||
* IN2N
|
||||
* IN3P
|
||||
* IN3N
|
||||
* IN4P
|
||||
* IN4N
|
||||
* HPOL
|
||||
* HPOR
|
||||
* SPOL
|
||||
* SPOR
|
||||
* LOUTL
|
||||
* LOUTR
|
||||
* MONOOUT
|
||||
* PDML
|
||||
* PDMR
|
||||
* SPDIF
|
||||
|
||||
Example:
|
||||
|
||||
rt5659 {
|
||||
compatible = "realtek,rt5659";
|
||||
reg = <0x1b>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>;
|
||||
realtek,ldo1-en-gpios =
|
||||
<&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>;
|
||||
};
|
|
@ -18,7 +18,7 @@ Required properties:
|
|||
Optional properties:
|
||||
|
||||
- realtek,pow-ldo2-gpio : The GPIO that controls the CODEC's POW_LDO2 pin.
|
||||
- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin.
|
||||
- realtek,reset-gpio : The GPIO that controls the CODEC's RESET pin. Active low.
|
||||
|
||||
- realtek,in1-differential
|
||||
- realtek,in2-differential
|
||||
|
|
|
@ -14,6 +14,9 @@ Required properties:
|
|||
- "apb": the parent APB clock for this controller
|
||||
- "codec": the parent module clock
|
||||
|
||||
Optional properties:
|
||||
- allwinner,pa-gpios: gpio to enable external amplifier
|
||||
|
||||
Example:
|
||||
codec: codec@01c22c00 {
|
||||
#sound-dai-cells = <0>;
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
Texas Instruments pcm3168a DT bindings
|
||||
|
||||
This driver supports both SPI and I2C bus access for this codec
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "ti,pcm3168a"
|
||||
|
||||
- clocks : Contains an entry for each entry in clock-names
|
||||
|
||||
- clock-names : Includes the following entries:
|
||||
"scki" The system clock
|
||||
|
||||
- VDD1-supply : Digital power supply regulator 1 (+3.3V)
|
||||
|
||||
- VDD2-supply : Digital power supply regulator 2 (+3.3V)
|
||||
|
||||
- VCCAD1-supply : ADC power supply regulator 1 (+5V)
|
||||
|
||||
- VCCAD2-supply : ADC power supply regulator 2 (+5V)
|
||||
|
||||
- VCCDA1-supply : DAC power supply regulator 1 (+5V)
|
||||
|
||||
- VCCDA2-supply : DAC power supply regulator 2 (+5V)
|
||||
|
||||
For required properties on SPI/I2C, consult SPI/I2C device tree documentation
|
||||
|
||||
Examples:
|
||||
|
||||
i2c0: i2c0@0 {
|
||||
|
||||
...
|
||||
|
||||
pcm3168a: audio-codec@44 {
|
||||
compatible = "ti,pcm3168a";
|
||||
reg = <0x44>;
|
||||
clocks = <&clk_core CLK_AUDIO>;
|
||||
clock-names = "scki";
|
||||
VDD1-supply = <&supply3v3>;
|
||||
VDD2-supply = <&supply3v3>;
|
||||
VCCAD1-supply = <&supply5v0>;
|
||||
VCCAD2-supply = <&supply5v0>;
|
||||
VCCDA1-supply = <&supply5v0>;
|
||||
VCCDA2-supply = <&supply5v0>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&dac_clk_pin>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
WM8974 audio CODEC
|
||||
|
||||
This device supports both I2C and SPI (configured with pin strapping
|
||||
on the board).
|
||||
|
||||
Required properties:
|
||||
- compatible: "wlf,wm8974"
|
||||
- reg: the I2C address or SPI chip select number of the device
|
||||
|
||||
Examples:
|
||||
|
||||
codec: wm8974@1a {
|
||||
compatible = "wlf,wm8974";
|
||||
reg = <0x1a>;
|
||||
};
|
|
@ -0,0 +1,49 @@
|
|||
The Imagination Technologies SPDIF Input controller contains the following
|
||||
controls:
|
||||
|
||||
name='IEC958 Capture Mask',index=0
|
||||
|
||||
This control returns a mask that shows which of the IEC958 status bits
|
||||
can be read using the 'IEC958 Capture Default' control.
|
||||
|
||||
name='IEC958 Capture Default',index=0
|
||||
|
||||
This control returns the status bits contained within the SPDIF stream that
|
||||
is being received. The 'IEC958 Capture Mask' shows which bits can be read
|
||||
from this control.
|
||||
|
||||
name='SPDIF In Multi Frequency Acquire',index=0
|
||||
name='SPDIF In Multi Frequency Acquire',index=1
|
||||
name='SPDIF In Multi Frequency Acquire',index=2
|
||||
name='SPDIF In Multi Frequency Acquire',index=3
|
||||
|
||||
This control is used to attempt acquisition of up to four different sample
|
||||
rates. The active rate can be obtained by reading the 'SPDIF In Lock Frequency'
|
||||
control.
|
||||
|
||||
When the value of this control is set to {0,0,0,0}, the rate given to hw_params
|
||||
will determine the single rate the block will capture. Else, the rate given to
|
||||
hw_params will be ignored, and the block will attempt capture for each of the
|
||||
four sample rates set here.
|
||||
|
||||
If less than four rates are required, the same rate can be specified more than
|
||||
once
|
||||
|
||||
name='SPDIF In Lock Frequency',index=0
|
||||
|
||||
This control returns the active capture rate, or 0 if a lock has not been
|
||||
acquired
|
||||
|
||||
name='SPDIF In Lock TRK',index=0
|
||||
|
||||
This control is used to modify the locking/jitter rejection characteristics
|
||||
of the block. Larger values increase the locking range, but reduce jitter
|
||||
rejection.
|
||||
|
||||
name='SPDIF In Lock Acquire Threshold',index=0
|
||||
|
||||
This control is used to change the threshold at which a lock is acquired.
|
||||
|
||||
name='SPDIF In Lock Release Threshold',index=0
|
||||
|
||||
This control is used to change the threshold at which a lock is released.
|
|
@ -54,12 +54,13 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_iis0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
static struct s3c_audio_pdata i2s0_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_playback = DMACH_I2S0_OUT,
|
||||
.dma_capture = DMACH_I2S0_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis0 = {
|
||||
|
@ -68,15 +69,20 @@ struct platform_device s3c64xx_device_iis0 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
|
||||
.resource = s3c64xx_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s0_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis0);
|
||||
|
||||
static struct resource s3c64xx_iis1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2s1_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_playback = DMACH_I2S1_OUT,
|
||||
.dma_capture = DMACH_I2S1_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis1 = {
|
||||
|
@ -85,19 +91,20 @@ struct platform_device s3c64xx_device_iis1 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
|
||||
.resource = s3c64xx_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s1_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis1);
|
||||
|
||||
static struct resource s3c64xx_iisv4_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv4_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_playback = DMACH_HSI_I2SV40_TX,
|
||||
.dma_capture = DMACH_HSI_I2SV40_RX,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN,
|
||||
|
@ -142,12 +149,13 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_pcm0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm0_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_capture = DMACH_PCM0_RX,
|
||||
.dma_playback = DMACH_PCM0_TX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm0 = {
|
||||
|
@ -163,12 +171,13 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0);
|
|||
|
||||
static struct resource s3c64xx_pcm1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm1_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_playback = DMACH_PCM1_TX,
|
||||
.dma_capture = DMACH_PCM1_RX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm1 = {
|
||||
|
@ -196,13 +205,15 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
|
||||
[3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
|
||||
[4] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata;
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.dma_playback = DMACH_AC97_PCMOUT,
|
||||
.dma_filter = pl08x_filter_id,
|
||||
.dma_capture = DMACH_AC97_PCMIN,
|
||||
.dma_capture_mic = DMACH_AC97_MICIN,
|
||||
};
|
||||
|
||||
static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
|
|
|
@ -14,38 +14,38 @@
|
|||
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
|
||||
|
||||
/* DMA0/SDMA0 */
|
||||
#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
|
||||
#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
|
||||
#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
|
||||
#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
|
||||
#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
|
||||
#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
|
||||
#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
|
||||
#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
|
||||
#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
|
||||
#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
|
||||
#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
|
||||
#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
|
||||
#define DMACH_UART0 "uart0_tx"
|
||||
#define DMACH_UART0_SRC2 "uart0_rx"
|
||||
#define DMACH_UART1 "uart1_tx"
|
||||
#define DMACH_UART1_SRC2 "uart1_rx"
|
||||
#define DMACH_UART2 "uart2_tx"
|
||||
#define DMACH_UART2_SRC2 "uart2_rx"
|
||||
#define DMACH_UART3 "uart3_tx"
|
||||
#define DMACH_UART3_SRC2 "uart3_rx"
|
||||
#define DMACH_PCM0_TX "pcm0_tx"
|
||||
#define DMACH_PCM0_RX "pcm0_rx"
|
||||
#define DMACH_I2S0_OUT "i2s0_tx"
|
||||
#define DMACH_I2S0_IN "i2s0_rx"
|
||||
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
|
||||
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
|
||||
#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
|
||||
#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
|
||||
#define DMACH_HSI_I2SV40_TX "i2s2_tx"
|
||||
#define DMACH_HSI_I2SV40_RX "i2s2_rx"
|
||||
|
||||
/* DMA1/SDMA1 */
|
||||
#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
|
||||
#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
|
||||
#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
|
||||
#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
|
||||
#define DMACH_PCM1_TX "pcm1_tx"
|
||||
#define DMACH_PCM1_RX "pcm1_rx"
|
||||
#define DMACH_I2S1_OUT "i2s1_tx"
|
||||
#define DMACH_I2S1_IN "i2s1_rx"
|
||||
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
|
||||
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
|
||||
#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
|
||||
#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
|
||||
#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
|
||||
#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
|
||||
#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
|
||||
#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
|
||||
#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
|
||||
#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
|
||||
#define DMACH_AC97_PCMOUT "ac97_out"
|
||||
#define DMACH_AC97_PCMIN "ac97_in"
|
||||
#define DMACH_AC97_MICIN "ac97_mic"
|
||||
#define DMACH_PWM "pwm"
|
||||
#define DMACH_IRDA "irda"
|
||||
#define DMACH_EXTERNAL "external"
|
||||
#define DMACH_SECURITY_RX "sec_rx"
|
||||
#define DMACH_SECURITY_TX "sec_tx"
|
||||
|
||||
enum dma_ch {
|
||||
DMACH_MAX = 32
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include <linux/platform_data/usb-ohci-s3c2410.h>
|
||||
#include <plat/usb-phy.h>
|
||||
#include <plat/regs-spi.h>
|
||||
#include <linux/platform_data/asoc-s3c.h>
|
||||
#include <linux/platform_data/spi-s3c64xx.h>
|
||||
|
||||
static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
||||
|
@ -74,9 +75,15 @@ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
|||
static struct resource s3c_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
|
||||
[2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
|
||||
[3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
|
||||
[4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
#ifdef CONFIG_S3C24XX_DMAC
|
||||
.dma_filter = s3c24xx_dma_filter,
|
||||
#endif
|
||||
.dma_playback = (void *)DMACH_PCM_OUT,
|
||||
.dma_capture = (void *)DMACH_PCM_IN,
|
||||
.dma_capture_mic = (void *)DMACH_MIC_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c_device_ac97 = {
|
||||
|
@ -87,6 +94,7 @@ struct platform_device s3c_device_ac97 = {
|
|||
.dev = {
|
||||
.dma_mask = &samsung_device_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s3c_ac97_pdata,
|
||||
}
|
||||
};
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
@ -566,6 +574,14 @@ static struct resource s3c_iis_resource[] = {
|
|||
[0] = DEFINE_RES_MEM(S3C24XX_PA_IIS, S3C24XX_SZ_IIS),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_iis_platdata = {
|
||||
#ifdef CONFIG_S3C24XX_DMAC
|
||||
.dma_filter = s3c24xx_dma_filter,
|
||||
#endif
|
||||
.dma_playback = (void *)DMACH_I2S_OUT,
|
||||
.dma_capture = (void *)DMACH_I2S_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c_device_iis = {
|
||||
.name = "s3c24xx-iis",
|
||||
.id = -1,
|
||||
|
@ -574,6 +590,7 @@ struct platform_device s3c_device_iis = {
|
|||
.dev = {
|
||||
.dma_mask = &samsung_device_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s3c_iis_platdata,
|
||||
}
|
||||
};
|
||||
#endif /* CONFIG_PLAT_S3C24XX */
|
||||
|
|
|
@ -55,6 +55,7 @@ enum sst_audio_device_id_mrfld {
|
|||
PIPE_MEDIA0_IN = 0x8F,
|
||||
PIPE_MEDIA1_IN = 0x90,
|
||||
PIPE_MEDIA2_IN = 0x91,
|
||||
PIPE_MEDIA3_IN = 0x9C,
|
||||
PIPE_RSVD = 0xFF,
|
||||
};
|
||||
|
||||
|
|
|
@ -547,6 +547,7 @@ static const struct pci_device_id intel_stolen_ids[] __initconst = {
|
|||
INTEL_CHV_IDS(&chv_stolen_funcs),
|
||||
INTEL_SKL_IDS(&gen9_stolen_funcs),
|
||||
INTEL_BXT_IDS(&gen9_stolen_funcs),
|
||||
INTEL_KBL_IDS(&gen9_stolen_funcs),
|
||||
};
|
||||
|
||||
static void __init intel_graphics_stolen(int num, int slot, int func)
|
||||
|
|
|
@ -444,7 +444,7 @@ config STM32_DMA
|
|||
here.
|
||||
|
||||
config S3C24XX_DMAC
|
||||
tristate "Samsung S3C24XX DMA support"
|
||||
bool "Samsung S3C24XX DMA support"
|
||||
depends on ARCH_S3C24XX
|
||||
select DMA_ENGINE
|
||||
select DMA_VIRTUAL_CHANNELS
|
||||
|
|
|
@ -518,7 +518,7 @@ static const struct drm_framebuffer_funcs amdgpu_fb_funcs = {
|
|||
int
|
||||
amdgpu_framebuffer_init(struct drm_device *dev,
|
||||
struct amdgpu_framebuffer *rfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
|
@ -535,7 +535,7 @@ amdgpu_framebuffer_init(struct drm_device *dev,
|
|||
static struct drm_framebuffer *
|
||||
amdgpu_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct amdgpu_framebuffer *amdgpu_fb;
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
struct amdgpu_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct amdgpu_framebuffer rfb;
|
||||
struct list_head fbdev_list;
|
||||
struct amdgpu_device *adev;
|
||||
};
|
||||
|
||||
|
|
|
@ -556,7 +556,7 @@ int amdgpu_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
|
|||
|
||||
int amdgpu_framebuffer_init(struct drm_device *dev,
|
||||
struct amdgpu_framebuffer *rfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
int amdgpufb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
|
|
|
@ -35,7 +35,7 @@ static const struct drm_framebuffer_funcs armada_fb_funcs = {
|
|||
};
|
||||
|
||||
struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
|
||||
const struct drm_mode_fb_cmd2 *mode, struct armada_gem_object *obj)
|
||||
{
|
||||
struct armada_framebuffer *dfb;
|
||||
uint8_t format, config;
|
||||
|
@ -101,7 +101,7 @@ struct armada_framebuffer *armada_framebuffer_create(struct drm_device *dev,
|
|||
}
|
||||
|
||||
static struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
|
||||
struct drm_file *dfile, struct drm_mode_fb_cmd2 *mode)
|
||||
struct drm_file *dfile, const struct drm_mode_fb_cmd2 *mode)
|
||||
{
|
||||
struct armada_gem_object *obj;
|
||||
struct armada_framebuffer *dfb;
|
||||
|
|
|
@ -19,6 +19,6 @@ struct armada_framebuffer {
|
|||
#define drm_fb_obj(fb) drm_fb_to_armada_fb(fb)->obj
|
||||
|
||||
struct armada_framebuffer *armada_framebuffer_create(struct drm_device *,
|
||||
struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
|
||||
const struct drm_mode_fb_cmd2 *, struct armada_gem_object *);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -256,7 +256,6 @@ struct ast_framebuffer {
|
|||
struct ast_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct ast_framebuffer afb;
|
||||
struct list_head fbdev_list;
|
||||
void *sysram;
|
||||
int size;
|
||||
struct ttm_bo_kmap_obj mapping;
|
||||
|
@ -309,7 +308,7 @@ extern void ast_mode_fini(struct drm_device *dev);
|
|||
|
||||
int ast_framebuffer_init(struct drm_device *dev,
|
||||
struct ast_framebuffer *ast_fb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
int ast_fbdev_init(struct drm_device *dev);
|
||||
|
|
|
@ -163,7 +163,7 @@ static struct fb_ops astfb_ops = {
|
|||
};
|
||||
|
||||
static int astfb_create_object(struct ast_fbdev *afbdev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
struct drm_device *dev = afbdev->helper.dev;
|
||||
|
|
|
@ -309,7 +309,7 @@ static const struct drm_framebuffer_funcs ast_fb_funcs = {
|
|||
|
||||
int ast_framebuffer_init(struct drm_device *dev,
|
||||
struct ast_framebuffer *ast_fb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
|
@ -327,7 +327,7 @@ int ast_framebuffer_init(struct drm_device *dev,
|
|||
static struct drm_framebuffer *
|
||||
ast_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct ast_framebuffer *ast_fb;
|
||||
|
|
|
@ -402,7 +402,7 @@ static irqreturn_t atmel_hlcdc_dc_irq_handler(int irq, void *data)
|
|||
}
|
||||
|
||||
static struct drm_framebuffer *atmel_hlcdc_fb_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
return drm_fb_cma_create(dev, file_priv, mode_cmd);
|
||||
}
|
||||
|
|
|
@ -149,7 +149,7 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
|
|||
|
||||
int bochs_framebuffer_init(struct drm_device *dev,
|
||||
struct bochs_framebuffer *gfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
|
||||
int bochs_bo_unpin(struct bochs_bo *bo);
|
||||
|
|
|
@ -34,7 +34,7 @@ static struct fb_ops bochsfb_ops = {
|
|||
};
|
||||
|
||||
static int bochsfb_create_object(struct bochs_device *bochs,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
struct drm_device *dev = bochs->dev;
|
||||
|
|
|
@ -484,7 +484,7 @@ static const struct drm_framebuffer_funcs bochs_fb_funcs = {
|
|||
|
||||
int bochs_framebuffer_init(struct drm_device *dev,
|
||||
struct bochs_framebuffer *gfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
|
@ -502,7 +502,7 @@ int bochs_framebuffer_init(struct drm_device *dev,
|
|||
static struct drm_framebuffer *
|
||||
bochs_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct bochs_framebuffer *bochs_fb;
|
||||
|
|
|
@ -153,7 +153,6 @@ struct cirrus_device {
|
|||
struct cirrus_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct cirrus_framebuffer gfb;
|
||||
struct list_head fbdev_list;
|
||||
void *sysram;
|
||||
int size;
|
||||
int x1, y1, x2, y2; /* dirty rect */
|
||||
|
@ -207,7 +206,7 @@ int cirrus_dumb_create(struct drm_file *file,
|
|||
|
||||
int cirrus_framebuffer_init(struct drm_device *dev,
|
||||
struct cirrus_framebuffer *gfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj);
|
||||
|
||||
bool cirrus_check_framebuffer(struct cirrus_device *cdev, int width, int height,
|
||||
|
|
|
@ -135,7 +135,7 @@ static struct fb_ops cirrusfb_ops = {
|
|||
};
|
||||
|
||||
static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
struct drm_device *dev = afbdev->helper.dev;
|
||||
|
|
|
@ -29,7 +29,7 @@ static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
|
|||
|
||||
int cirrus_framebuffer_init(struct drm_device *dev,
|
||||
struct cirrus_framebuffer *gfb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object *obj)
|
||||
{
|
||||
int ret;
|
||||
|
@ -47,7 +47,7 @@ int cirrus_framebuffer_init(struct drm_device *dev,
|
|||
static struct drm_framebuffer *
|
||||
cirrus_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct cirrus_device *cdev = dev->dev_private;
|
||||
struct drm_gem_object *obj;
|
||||
|
|
|
@ -316,8 +316,7 @@ int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
|||
if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
|
||||
return 0;
|
||||
|
||||
if (state->mode_blob)
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
state->mode_blob = NULL;
|
||||
|
||||
if (mode) {
|
||||
|
@ -363,8 +362,7 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
|||
if (blob == state->mode_blob)
|
||||
return 0;
|
||||
|
||||
if (state->mode_blob)
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
state->mode_blob = NULL;
|
||||
|
||||
if (blob) {
|
||||
|
@ -419,8 +417,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
|||
struct drm_property_blob *mode =
|
||||
drm_property_lookup_blob(dev, val);
|
||||
ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
|
||||
if (mode)
|
||||
drm_property_unreference_blob(mode);
|
||||
drm_property_unreference_blob(mode);
|
||||
return ret;
|
||||
}
|
||||
else if (crtc->funcs->atomic_set_property)
|
||||
|
@ -1191,12 +1188,7 @@ void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
|
|||
retry:
|
||||
drm_modeset_backoff(state->acquire_ctx);
|
||||
|
||||
ret = drm_modeset_lock(&state->dev->mode_config.connection_mutex,
|
||||
state->acquire_ctx);
|
||||
if (ret)
|
||||
goto retry;
|
||||
ret = drm_modeset_lock_all_crtcs(state->dev,
|
||||
state->acquire_ctx);
|
||||
ret = drm_modeset_lock_all_ctx(state->dev, state->acquire_ctx);
|
||||
if (ret)
|
||||
goto retry;
|
||||
}
|
||||
|
@ -1433,7 +1425,7 @@ static int atomic_set_prop(struct drm_atomic_state *state,
|
|||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers.
|
||||
* drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
|
||||
*
|
||||
* @dev: drm device to check.
|
||||
* @plane_mask: plane mask for planes that were updated.
|
||||
|
|
|
@ -80,6 +80,27 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
check_pending_encoder_assignment(struct drm_atomic_state *state,
|
||||
struct drm_encoder *new_encoder,
|
||||
struct drm_connector *new_connector)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int i;
|
||||
|
||||
for_each_connector_in_state(state, connector, conn_state, i) {
|
||||
if (conn_state->best_encoder != new_encoder)
|
||||
continue;
|
||||
|
||||
/* encoder already assigned and we're trying to re-steal it! */
|
||||
if (connector->state->best_encoder != conn_state->best_encoder)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct drm_crtc *
|
||||
get_current_crtc_for_encoder(struct drm_device *dev,
|
||||
struct drm_encoder *encoder)
|
||||
|
@ -229,6 +250,13 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!check_pending_encoder_assignment(state, new_encoder, connector)) {
|
||||
DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n",
|
||||
connector->base.id,
|
||||
connector->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
encoder_crtc = get_current_crtc_for_encoder(state->dev,
|
||||
new_encoder);
|
||||
|
||||
|
@ -1341,6 +1369,49 @@ drm_atomic_helper_commit_planes_on_crtc(struct drm_crtc_state *old_crtc_state)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_disable_planes_on_crtc - helper to disable CRTC's planes
|
||||
* @crtc: CRTC
|
||||
* @atomic: if set, synchronize with CRTC's atomic_begin/flush hooks
|
||||
*
|
||||
* Disables all planes associated with the given CRTC. This can be
|
||||
* used for instance in the CRTC helper disable callback to disable
|
||||
* all planes before shutting down the display pipeline.
|
||||
*
|
||||
* If the atomic-parameter is set the function calls the CRTC's
|
||||
* atomic_begin hook before and atomic_flush hook after disabling the
|
||||
* planes.
|
||||
*
|
||||
* It is a bug to call this function without having implemented the
|
||||
* ->atomic_disable() plane hook.
|
||||
*/
|
||||
void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc *crtc,
|
||||
bool atomic)
|
||||
{
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs =
|
||||
crtc->helper_private;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (atomic && crtc_funcs && crtc_funcs->atomic_begin)
|
||||
crtc_funcs->atomic_begin(crtc, NULL);
|
||||
|
||||
drm_for_each_plane(plane, crtc->dev) {
|
||||
const struct drm_plane_helper_funcs *plane_funcs =
|
||||
plane->helper_private;
|
||||
|
||||
if (plane->state->crtc != crtc || !plane_funcs)
|
||||
continue;
|
||||
|
||||
WARN_ON(!plane_funcs->atomic_disable);
|
||||
if (plane_funcs->atomic_disable)
|
||||
plane_funcs->atomic_disable(plane, NULL);
|
||||
}
|
||||
|
||||
if (atomic && crtc_funcs && crtc_funcs->atomic_flush)
|
||||
crtc_funcs->atomic_flush(crtc, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_cleanup_planes - cleanup plane resources after commit
|
||||
* @dev: DRM device
|
||||
|
@ -1485,12 +1556,12 @@ retry:
|
|||
drm_atomic_set_fb_for_plane(plane_state, fb);
|
||||
plane_state->crtc_x = crtc_x;
|
||||
plane_state->crtc_y = crtc_y;
|
||||
plane_state->crtc_h = crtc_h;
|
||||
plane_state->crtc_w = crtc_w;
|
||||
plane_state->crtc_h = crtc_h;
|
||||
plane_state->src_x = src_x;
|
||||
plane_state->src_y = src_y;
|
||||
plane_state->src_h = src_h;
|
||||
plane_state->src_w = src_w;
|
||||
plane_state->src_h = src_h;
|
||||
|
||||
if (plane == crtc->cursor)
|
||||
state->legacy_cursor_update = true;
|
||||
|
@ -1609,12 +1680,12 @@ int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
|
|||
drm_atomic_set_fb_for_plane(plane_state, NULL);
|
||||
plane_state->crtc_x = 0;
|
||||
plane_state->crtc_y = 0;
|
||||
plane_state->crtc_h = 0;
|
||||
plane_state->crtc_w = 0;
|
||||
plane_state->crtc_h = 0;
|
||||
plane_state->src_x = 0;
|
||||
plane_state->src_y = 0;
|
||||
plane_state->src_h = 0;
|
||||
plane_state->src_w = 0;
|
||||
plane_state->src_h = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1797,16 +1868,16 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set,
|
|||
drm_atomic_set_fb_for_plane(primary_state, set->fb);
|
||||
primary_state->crtc_x = 0;
|
||||
primary_state->crtc_y = 0;
|
||||
primary_state->crtc_h = vdisplay;
|
||||
primary_state->crtc_w = hdisplay;
|
||||
primary_state->crtc_h = vdisplay;
|
||||
primary_state->src_x = set->x << 16;
|
||||
primary_state->src_y = set->y << 16;
|
||||
if (primary_state->rotation & (BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_270))) {
|
||||
primary_state->src_h = hdisplay << 16;
|
||||
primary_state->src_w = vdisplay << 16;
|
||||
primary_state->src_h = hdisplay << 16;
|
||||
} else {
|
||||
primary_state->src_h = vdisplay << 16;
|
||||
primary_state->src_w = hdisplay << 16;
|
||||
primary_state->src_h = vdisplay << 16;
|
||||
}
|
||||
|
||||
commit:
|
||||
|
@ -1817,6 +1888,161 @@ commit:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_disable_all - disable all currently active outputs
|
||||
* @dev: DRM device
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Loops through all connectors, finding those that aren't turned off and then
|
||||
* turns them off by setting their DPMS mode to OFF and deactivating the CRTC
|
||||
* that they are connected to.
|
||||
*
|
||||
* This is used for example in suspend/resume to disable all currently active
|
||||
* functions when suspending.
|
||||
*
|
||||
* Note that if callers haven't already acquired all modeset locks this might
|
||||
* return -EDEADLK, which must be handled by calling drm_modeset_backoff().
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_suspend(), drm_atomic_helper_resume()
|
||||
*/
|
||||
int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_connector *conn;
|
||||
int err;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
drm_for_each_connector(conn, dev) {
|
||||
struct drm_crtc *crtc = conn->state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
if (!crtc || conn->dpms != DRM_MODE_DPMS_ON)
|
||||
continue;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state)) {
|
||||
err = PTR_ERR(crtc_state);
|
||||
goto free;
|
||||
}
|
||||
|
||||
crtc_state->active = false;
|
||||
}
|
||||
|
||||
err = drm_atomic_commit(state);
|
||||
|
||||
free:
|
||||
if (err < 0)
|
||||
drm_atomic_state_free(state);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_suspend - subsystem-level suspend helper
|
||||
* @dev: DRM device
|
||||
*
|
||||
* Duplicates the current atomic state, disables all active outputs and then
|
||||
* returns a pointer to the original atomic state to the caller. Drivers can
|
||||
* pass this pointer to the drm_atomic_helper_resume() helper upon resume to
|
||||
* restore the output configuration that was active at the time the system
|
||||
* entered suspend.
|
||||
*
|
||||
* Note that it is potentially unsafe to use this. The atomic state object
|
||||
* returned by this function is assumed to be persistent. Drivers must ensure
|
||||
* that this holds true. Before calling this function, drivers must make sure
|
||||
* to suspend fbdev emulation so that nothing can be using the device.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to a copy of the state before suspend on success or an ERR_PTR()-
|
||||
* encoded error code on failure. Drivers should store the returned atomic
|
||||
* state object and pass it to the drm_atomic_helper_resume() helper upon
|
||||
* resume.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_duplicate_state(), drm_atomic_helper_disable_all(),
|
||||
* drm_atomic_helper_resume()
|
||||
*/
|
||||
struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev)
|
||||
{
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
int err;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry:
|
||||
err = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (err < 0) {
|
||||
state = ERR_PTR(err);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
state = drm_atomic_helper_duplicate_state(dev, &ctx);
|
||||
if (IS_ERR(state))
|
||||
goto unlock;
|
||||
|
||||
err = drm_atomic_helper_disable_all(dev, &ctx);
|
||||
if (err < 0) {
|
||||
drm_atomic_state_free(state);
|
||||
state = ERR_PTR(err);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
unlock:
|
||||
if (PTR_ERR(state) == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
return state;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_suspend);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_resume - subsystem-level resume helper
|
||||
* @dev: DRM device
|
||||
* @state: atomic state to resume to
|
||||
*
|
||||
* Calls drm_mode_config_reset() to synchronize hardware and software states,
|
||||
* grabs all modeset locks and commits the atomic state object. This can be
|
||||
* used in conjunction with the drm_atomic_helper_suspend() helper to
|
||||
* implement suspend/resume for drivers that support atomic mode-setting.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_suspend()
|
||||
*/
|
||||
int drm_atomic_helper_resume(struct drm_device *dev,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int err;
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
drm_modeset_lock_all(dev);
|
||||
state->acquire_ctx = config->acquire_ctx;
|
||||
err = drm_atomic_commit(state);
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_resume);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_crtc_set_property - helper for crtc properties
|
||||
* @crtc: DRM crtc
|
||||
|
@ -2184,7 +2410,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
|
|||
*/
|
||||
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
if (crtc->state && crtc->state->mode_blob)
|
||||
if (crtc->state)
|
||||
drm_property_unreference_blob(crtc->state->mode_blob);
|
||||
kfree(crtc->state);
|
||||
crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
|
||||
|
@ -2252,8 +2478,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
|
|||
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
if (state->mode_blob)
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
|
||||
|
||||
|
@ -2430,7 +2655,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
|
|||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Makes a copy of the current atomic state by looping over all objects and
|
||||
* duplicating their respective states.
|
||||
* duplicating their respective states. This is used for example by suspend/
|
||||
* resume support code to save the state prior to suspend such that it can
|
||||
* be restored upon resume.
|
||||
*
|
||||
* Note that this treats atomic state as persistent between save and restore.
|
||||
* Drivers must make sure that this is possible and won't result in confusion
|
||||
|
@ -2442,6 +2669,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
|
|||
* Returns:
|
||||
* A pointer to the copy of the atomic state object on success or an
|
||||
* ERR_PTR()-encoded error code on failure.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_suspend(), drm_atomic_helper_resume()
|
||||
*/
|
||||
struct drm_atomic_state *
|
||||
drm_atomic_helper_duplicate_state(struct drm_device *dev,
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
static struct drm_framebuffer *
|
||||
internal_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *r,
|
||||
const struct drm_mode_fb_cmd2 *r,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/* Avoid boilerplate. I'm tired of typing. */
|
||||
|
@ -3235,7 +3235,7 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
|||
|
||||
static struct drm_framebuffer *
|
||||
internal_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *r,
|
||||
const struct drm_mode_fb_cmd2 *r,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
|
|
@ -818,7 +818,7 @@ EXPORT_SYMBOL(drm_helper_connector_dpms);
|
|||
* metadata fields.
|
||||
*/
|
||||
void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -855,6 +855,12 @@ EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
|
|||
* due to slight differences in allocating shared resources when the
|
||||
* configuration is restored in a different order than when userspace set it up)
|
||||
* need to use their own restore logic.
|
||||
*
|
||||
* This function is deprecated. New drivers should implement atomic mode-
|
||||
* setting and use the atomic suspend/resume helpers.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_suspend(), drm_atomic_helper_resume()
|
||||
*/
|
||||
void drm_helper_resume_force_mode(struct drm_device *dev)
|
||||
{
|
||||
|
|
|
@ -2545,6 +2545,33 @@ cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
|
|||
return clock;
|
||||
}
|
||||
|
||||
static u8 drm_match_cea_mode_clock_tolerance(const struct drm_display_mode *to_match,
|
||||
unsigned int clock_tolerance)
|
||||
{
|
||||
u8 mode;
|
||||
|
||||
if (!to_match->clock)
|
||||
return 0;
|
||||
|
||||
for (mode = 0; mode < ARRAY_SIZE(edid_cea_modes); mode++) {
|
||||
const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
|
||||
if (abs(to_match->clock - clock1) > clock_tolerance &&
|
||||
abs(to_match->clock - clock2) > clock_tolerance)
|
||||
continue;
|
||||
|
||||
if (drm_mode_equal_no_clocks(to_match, cea_mode))
|
||||
return mode + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_match_cea_mode - look for a CEA mode matching given mode
|
||||
* @to_match: display mode
|
||||
|
@ -2609,6 +2636,33 @@ hdmi_mode_alternate_clock(const struct drm_display_mode *hdmi_mode)
|
|||
return cea_mode_alternate_clock(hdmi_mode);
|
||||
}
|
||||
|
||||
static u8 drm_match_hdmi_mode_clock_tolerance(const struct drm_display_mode *to_match,
|
||||
unsigned int clock_tolerance)
|
||||
{
|
||||
u8 mode;
|
||||
|
||||
if (!to_match->clock)
|
||||
return 0;
|
||||
|
||||
for (mode = 0; mode < ARRAY_SIZE(edid_4k_modes); mode++) {
|
||||
const struct drm_display_mode *hdmi_mode = &edid_4k_modes[mode];
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
/* Make sure to also match alternate clocks */
|
||||
clock1 = hdmi_mode->clock;
|
||||
clock2 = hdmi_mode_alternate_clock(hdmi_mode);
|
||||
|
||||
if (abs(to_match->clock - clock1) > clock_tolerance &&
|
||||
abs(to_match->clock - clock2) > clock_tolerance)
|
||||
continue;
|
||||
|
||||
if (drm_mode_equal_no_clocks(to_match, hdmi_mode))
|
||||
return mode + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_match_hdmi_mode - look for a HDMI mode matching given mode
|
||||
* @to_match: display mode
|
||||
|
@ -3119,14 +3173,18 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
|||
u8 mode_idx;
|
||||
const char *type;
|
||||
|
||||
mode_idx = drm_match_cea_mode(mode) - 1;
|
||||
/*
|
||||
* allow 5kHz clock difference either way to account for
|
||||
* the 10kHz clock resolution limit of detailed timings.
|
||||
*/
|
||||
mode_idx = drm_match_cea_mode_clock_tolerance(mode, 5) - 1;
|
||||
if (mode_idx < ARRAY_SIZE(edid_cea_modes)) {
|
||||
type = "CEA";
|
||||
cea_mode = &edid_cea_modes[mode_idx];
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
} else {
|
||||
mode_idx = drm_match_hdmi_mode(mode) - 1;
|
||||
mode_idx = drm_match_hdmi_mode_clock_tolerance(mode, 5) - 1;
|
||||
if (mode_idx < ARRAY_SIZE(edid_4k_modes)) {
|
||||
type = "HDMI";
|
||||
cea_mode = &edid_4k_modes[mode_idx];
|
||||
|
|
|
@ -74,7 +74,7 @@ static struct drm_framebuffer_funcs drm_fb_cma_funcs = {
|
|||
};
|
||||
|
||||
static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj,
|
||||
const const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_cma_object **obj,
|
||||
unsigned int num_planes)
|
||||
{
|
||||
struct drm_fb_cma *fb_cma;
|
||||
|
@ -107,7 +107,7 @@ static struct drm_fb_cma *drm_fb_cma_alloc(struct drm_device *dev,
|
|||
* checked before calling this function.
|
||||
*/
|
||||
struct drm_framebuffer *drm_fb_cma_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct drm_fb_cma *fb_cma;
|
||||
struct drm_gem_cma_object *objs[4];
|
||||
|
|
|
@ -226,6 +226,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
|||
init_waitqueue_head(&priv->event_wait);
|
||||
priv->event_space = 4096; /* set aside 4k for event buffer */
|
||||
|
||||
mutex_init(&priv->event_read_lock);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_GEM))
|
||||
drm_gem_open(dev, priv);
|
||||
|
||||
|
@ -511,14 +513,28 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
{
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
ssize_t ret = 0;
|
||||
ssize_t ret;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, buffer, count))
|
||||
return -EFAULT;
|
||||
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
ret = mutex_lock_interruptible(&file_priv->event_read_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (;;) {
|
||||
if (list_empty(&file_priv->event_list)) {
|
||||
struct drm_pending_event *e = NULL;
|
||||
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
if (!list_empty(&file_priv->event_list)) {
|
||||
e = list_first_entry(&file_priv->event_list,
|
||||
struct drm_pending_event, link);
|
||||
file_priv->event_space += e->event->length;
|
||||
list_del(&e->link);
|
||||
}
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
|
||||
if (e == NULL) {
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
|
@ -527,36 +543,36 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
|
|||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
mutex_unlock(&file_priv->event_read_lock);
|
||||
ret = wait_event_interruptible(file_priv->event_wait,
|
||||
!list_empty(&file_priv->event_list));
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
ret = 0;
|
||||
if (ret >= 0)
|
||||
ret = mutex_lock_interruptible(&file_priv->event_read_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
struct drm_pending_event *e;
|
||||
unsigned length = e->event->length;
|
||||
|
||||
e = list_first_entry(&file_priv->event_list,
|
||||
struct drm_pending_event, link);
|
||||
if (e->event->length + ret > count)
|
||||
break;
|
||||
|
||||
if (__copy_to_user_inatomic(buffer + ret,
|
||||
e->event, e->event->length)) {
|
||||
if (ret == 0)
|
||||
ret = -EFAULT;
|
||||
if (length > count - ret) {
|
||||
put_back_event:
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
file_priv->event_space -= length;
|
||||
list_add(&e->link, &file_priv->event_list);
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
break;
|
||||
}
|
||||
|
||||
file_priv->event_space += e->event->length;
|
||||
ret += e->event->length;
|
||||
list_del(&e->link);
|
||||
if (copy_to_user(buffer + ret, e->event, length)) {
|
||||
if (ret == 0)
|
||||
ret = -EFAULT;
|
||||
goto put_back_event;
|
||||
}
|
||||
|
||||
ret += length;
|
||||
e->destroy(e);
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
mutex_unlock(&file_priv->event_read_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -244,8 +244,9 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj)
|
|||
* @filp: drm file-private structure to use for the handle look up
|
||||
* @handle: userspace handle to delete
|
||||
*
|
||||
* Removes the GEM handle from the @filp lookup table and if this is the last
|
||||
* handle also cleans up linked resources like GEM names.
|
||||
* Removes the GEM handle from the @filp lookup table which has been added with
|
||||
* drm_gem_handle_create(). If this is the last handle also cleans up linked
|
||||
* resources like GEM names.
|
||||
*/
|
||||
int
|
||||
drm_gem_handle_delete(struct drm_file *filp, u32 handle)
|
||||
|
@ -314,6 +315,10 @@ EXPORT_SYMBOL(drm_gem_dumb_destroy);
|
|||
* This expects the dev->object_name_lock to be held already and will drop it
|
||||
* before returning. Used to avoid races in establishing new handles when
|
||||
* importing an object from either an flink name or a dma-buf.
|
||||
*
|
||||
* Handles must be release again through drm_gem_handle_delete(). This is done
|
||||
* when userspace closes @file_priv for all attached handles, or through the
|
||||
* GEM_CLOSE ioctl for individual handles.
|
||||
*/
|
||||
int
|
||||
drm_gem_handle_create_tail(struct drm_file *file_priv,
|
||||
|
@ -541,7 +546,17 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_gem_put_pages);
|
||||
|
||||
/** Returns a reference to the object named by the handle. */
|
||||
/**
|
||||
* drm_gem_object_lookup - look up a GEM object from it's handle
|
||||
* @dev: DRM device
|
||||
* @filp: DRM file private date
|
||||
* @handle: userspace handle
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* A reference to the object named by the handle if such exists on @filp, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
drm_gem_object_lookup(struct drm_device *dev, struct drm_file *filp,
|
||||
u32 handle)
|
||||
|
@ -774,6 +789,13 @@ drm_gem_object_free(struct kref *kref)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_free);
|
||||
|
||||
/**
|
||||
* drm_gem_vm_open - vma->ops->open implementation for GEM
|
||||
* @vma: VM area structure
|
||||
*
|
||||
* This function implements the #vm_operations_struct open() callback for GEM
|
||||
* drivers. This must be used together with drm_gem_vm_close().
|
||||
*/
|
||||
void drm_gem_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
|
@ -782,6 +804,13 @@ void drm_gem_vm_open(struct vm_area_struct *vma)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_gem_vm_open);
|
||||
|
||||
/**
|
||||
* drm_gem_vm_close - vma->ops->close implementation for GEM
|
||||
* @vma: VM area structure
|
||||
*
|
||||
* This function implements the #vm_operations_struct close() callback for GEM
|
||||
* drivers. This must be used together with drm_gem_vm_open().
|
||||
*/
|
||||
void drm_gem_vm_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
|
|
|
@ -917,13 +917,30 @@ bool drm_mode_equal(const struct drm_display_mode *mode1, const struct drm_displ
|
|||
} else if (mode1->clock != mode2->clock)
|
||||
return false;
|
||||
|
||||
return drm_mode_equal_no_clocks(mode1, mode2);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_equal);
|
||||
|
||||
/**
|
||||
* drm_mode_equal_no_clocks - test modes for equality
|
||||
* @mode1: first mode
|
||||
* @mode2: second mode
|
||||
*
|
||||
* Check to see if @mode1 and @mode2 are equivalent, but
|
||||
* don't check the pixel clocks.
|
||||
*
|
||||
* Returns:
|
||||
* True if the modes are equal, false otherwise.
|
||||
*/
|
||||
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
|
||||
{
|
||||
if ((mode1->flags & DRM_MODE_FLAG_3D_MASK) !=
|
||||
(mode2->flags & DRM_MODE_FLAG_3D_MASK))
|
||||
return false;
|
||||
|
||||
return drm_mode_equal_no_clocks_no_stereo(mode1, mode2);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_equal);
|
||||
EXPORT_SYMBOL(drm_mode_equal_no_clocks);
|
||||
|
||||
/**
|
||||
* drm_mode_equal_no_clocks_no_stereo - test modes for equality
|
||||
|
@ -1230,7 +1247,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
|||
unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
|
||||
bool yres_specified = false, cvt = false, rb = false;
|
||||
bool interlace = false, margins = false, was_digit = false;
|
||||
int i;
|
||||
int i, err;
|
||||
enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
|
||||
|
||||
#ifdef CONFIG_FB
|
||||
|
@ -1250,7 +1267,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
|||
case '@':
|
||||
if (!refresh_specified && !bpp_specified &&
|
||||
!yres_specified && !cvt && !rb && was_digit) {
|
||||
refresh = simple_strtol(&name[i+1], NULL, 10);
|
||||
err = kstrtouint(&name[i + 1], 10, &refresh);
|
||||
if (err)
|
||||
return false;
|
||||
refresh_specified = true;
|
||||
was_digit = false;
|
||||
} else
|
||||
|
@ -1259,7 +1278,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
|||
case '-':
|
||||
if (!bpp_specified && !yres_specified && !cvt &&
|
||||
!rb && was_digit) {
|
||||
bpp = simple_strtol(&name[i+1], NULL, 10);
|
||||
err = kstrtouint(&name[i + 1], 10, &bpp);
|
||||
if (err)
|
||||
return false;
|
||||
bpp_specified = true;
|
||||
was_digit = false;
|
||||
} else
|
||||
|
@ -1267,7 +1288,9 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
|
|||
break;
|
||||
case 'x':
|
||||
if (!yres_specified && was_digit) {
|
||||
yres = simple_strtol(&name[i+1], NULL, 10);
|
||||
err = kstrtouint(&name[i + 1], 10, &yres);
|
||||
if (err)
|
||||
return false;
|
||||
yres_specified = true;
|
||||
was_digit = false;
|
||||
} else
|
||||
|
@ -1491,4 +1514,4 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
|
|||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,11 +57,18 @@
|
|||
|
||||
/**
|
||||
* drm_modeset_lock_all - take all modeset locks
|
||||
* @dev: drm device
|
||||
* @dev: DRM device
|
||||
*
|
||||
* This function takes all modeset locks, suitable where a more fine-grained
|
||||
* scheme isn't (yet) implemented. Locks must be dropped with
|
||||
* drm_modeset_unlock_all.
|
||||
* scheme isn't (yet) implemented. Locks must be dropped by calling the
|
||||
* drm_modeset_unlock_all() function.
|
||||
*
|
||||
* This function is deprecated. It allocates a lock acquisition context and
|
||||
* stores it in the DRM device's ->mode_config. This facilitate conversion of
|
||||
* existing code because it removes the need to manually deal with the
|
||||
* acquisition context, but it is also brittle because the context is global
|
||||
* and care must be taken not to nest calls. New code should use the
|
||||
* drm_modeset_lock_all_ctx() function and pass in the context explicitly.
|
||||
*/
|
||||
void drm_modeset_lock_all(struct drm_device *dev)
|
||||
{
|
||||
|
@ -78,39 +85,43 @@ void drm_modeset_lock_all(struct drm_device *dev)
|
|||
drm_modeset_acquire_init(ctx, 0);
|
||||
|
||||
retry:
|
||||
ret = drm_modeset_lock(&config->connection_mutex, ctx);
|
||||
if (ret)
|
||||
goto fail;
|
||||
ret = drm_modeset_lock_all_crtcs(dev, ctx);
|
||||
if (ret)
|
||||
goto fail;
|
||||
ret = drm_modeset_lock_all_ctx(dev, ctx);
|
||||
if (ret < 0) {
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_acquire_fini(ctx);
|
||||
kfree(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(config->acquire_ctx);
|
||||
|
||||
/* now we hold the locks, so now that it is safe, stash the
|
||||
* ctx for drm_modeset_unlock_all():
|
||||
/*
|
||||
* We hold the locks now, so it is safe to stash the acquisition
|
||||
* context for drm_modeset_unlock_all().
|
||||
*/
|
||||
config->acquire_ctx = ctx;
|
||||
|
||||
drm_warn_on_modeset_not_all_locked(dev);
|
||||
|
||||
return;
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
kfree(ctx);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_modeset_lock_all);
|
||||
|
||||
/**
|
||||
* drm_modeset_unlock_all - drop all modeset locks
|
||||
* @dev: device
|
||||
* @dev: DRM device
|
||||
*
|
||||
* This function drop all modeset locks taken by drm_modeset_lock_all.
|
||||
* This function drops all modeset locks taken by a previous call to the
|
||||
* drm_modeset_lock_all() function.
|
||||
*
|
||||
* This function is deprecated. It uses the lock acquisition context stored
|
||||
* in the DRM device's ->mode_config. This facilitates conversion of existing
|
||||
* code because it removes the need to manually deal with the acquisition
|
||||
* context, but it is also brittle because the context is global and care must
|
||||
* be taken not to nest calls. New code should pass the acquisition context
|
||||
* directly to the drm_modeset_drop_locks() function.
|
||||
*/
|
||||
void drm_modeset_unlock_all(struct drm_device *dev)
|
||||
{
|
||||
|
@ -431,14 +442,34 @@ void drm_modeset_unlock(struct drm_modeset_lock *lock)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_modeset_unlock);
|
||||
|
||||
/* In some legacy codepaths it's convenient to just grab all the crtc and plane
|
||||
* related locks. */
|
||||
int drm_modeset_lock_all_crtcs(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
/**
|
||||
* drm_modeset_lock_all_ctx - take all modeset locks
|
||||
* @dev: DRM device
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* This function takes all modeset locks, suitable where a more fine-grained
|
||||
* scheme isn't (yet) implemented.
|
||||
*
|
||||
* Unlike drm_modeset_lock_all(), it doesn't take the dev->mode_config.mutex
|
||||
* since that lock isn't required for modeset state changes. Callers which
|
||||
* need to grab that lock too need to do so outside of the acquire context
|
||||
* @ctx.
|
||||
*
|
||||
* Locks acquired with this function should be released by calling the
|
||||
* drm_modeset_drop_locks() function on @ctx.
|
||||
*
|
||||
* Returns: 0 on success or a negative error-code on failure.
|
||||
*/
|
||||
int drm_modeset_lock_all_ctx(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_plane *plane;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
ret = drm_modeset_lock(&crtc->mutex, ctx);
|
||||
|
@ -454,4 +485,4 @@ int drm_modeset_lock_all_crtcs(struct drm_device *dev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
|
||||
EXPORT_SYMBOL(drm_modeset_lock_all_ctx);
|
||||
|
|
|
@ -164,6 +164,8 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
|||
vscale = drm_rect_calc_vscale(src, dest, min_scale, max_scale);
|
||||
if (hscale < 0 || vscale < 0) {
|
||||
DRM_DEBUG_KMS("Invalid scaling of plane\n");
|
||||
drm_rect_debug_print("src: ", src, true);
|
||||
drm_rect_debug_print("dst: ", dest, false);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
|
@ -180,6 +182,8 @@ int drm_plane_helper_check_update(struct drm_plane *plane,
|
|||
|
||||
if (!can_position && !drm_rect_equals(dest, clip)) {
|
||||
DRM_DEBUG_KMS("Plane must cover entire CRTC\n");
|
||||
drm_rect_debug_print("dst: ", dest, false);
|
||||
drm_rect_debug_print("clip: ", clip, false);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
@ -147,6 +147,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||
list_for_each_entry(mode, &connector->modes, head)
|
||||
mode->status = MODE_UNVERIFIED;
|
||||
|
||||
old_status = connector->status;
|
||||
|
||||
if (connector->force) {
|
||||
if (connector->force == DRM_FORCE_ON ||
|
||||
connector->force == DRM_FORCE_ON_DIGITAL)
|
||||
|
@ -156,33 +158,32 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
|
|||
if (connector->funcs->force)
|
||||
connector->funcs->force(connector);
|
||||
} else {
|
||||
old_status = connector->status;
|
||||
|
||||
connector->status = connector->funcs->detect(connector, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Normally either the driver's hpd code or the poll loop should
|
||||
* pick up any changes and fire the hotplug event. But if
|
||||
* userspace sneaks in a probe, we might miss a change. Hence
|
||||
* check here, and if anything changed start the hotplug code.
|
||||
*/
|
||||
if (old_status != connector->status) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->status));
|
||||
|
||||
/*
|
||||
* Normally either the driver's hpd code or the poll loop should
|
||||
* pick up any changes and fire the hotplug event. But if
|
||||
* userspace sneaks in a probe, we might miss a change. Hence
|
||||
* check here, and if anything changed start the hotplug code.
|
||||
* The hotplug event code might call into the fb
|
||||
* helpers, and so expects that we do not hold any
|
||||
* locks. Fire up the poll struct instead, it will
|
||||
* disable itself again.
|
||||
*/
|
||||
if (old_status != connector->status) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
old_status, connector->status);
|
||||
|
||||
/*
|
||||
* The hotplug event code might call into the fb
|
||||
* helpers, and so expects that we do not hold any
|
||||
* locks. Fire up the poll struct instead, it will
|
||||
* disable itself again.
|
||||
*/
|
||||
dev->mode_config.delayed_event = true;
|
||||
if (dev->mode_config.poll_enabled)
|
||||
schedule_delayed_work(&dev->mode_config.output_poll_work,
|
||||
0);
|
||||
}
|
||||
dev->mode_config.delayed_event = true;
|
||||
if (dev->mode_config.poll_enabled)
|
||||
schedule_delayed_work(&dev->mode_config.output_poll_work,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Re-enable polling in case the global poll config changed. */
|
||||
|
|
|
@ -275,22 +275,23 @@ EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
|
|||
|
||||
/**
|
||||
* drm_rect_debug_print - print the rectangle information
|
||||
* @prefix: prefix string
|
||||
* @r: rectangle to print
|
||||
* @fixed_point: rectangle is in 16.16 fixed point format
|
||||
*/
|
||||
void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point)
|
||||
void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
|
||||
{
|
||||
int w = drm_rect_width(r);
|
||||
int h = drm_rect_height(r);
|
||||
|
||||
if (fixed_point)
|
||||
DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n",
|
||||
DRM_DEBUG_KMS("%s%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", prefix,
|
||||
w >> 16, ((w & 0xffff) * 15625) >> 10,
|
||||
h >> 16, ((h & 0xffff) * 15625) >> 10,
|
||||
r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10,
|
||||
r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10);
|
||||
else
|
||||
DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1);
|
||||
DRM_DEBUG_KMS("%s%dx%d%+d%+d\n", prefix, w, h, r->x1, r->y1);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_debug_print);
|
||||
|
||||
|
|
|
@ -167,47 +167,35 @@ static ssize_t status_store(struct device *device,
|
|||
{
|
||||
struct drm_connector *connector = to_drm_connector(device);
|
||||
struct drm_device *dev = connector->dev;
|
||||
enum drm_connector_status old_status;
|
||||
enum drm_connector_force old_force;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
old_status = connector->status;
|
||||
old_force = connector->force;
|
||||
|
||||
if (sysfs_streq(buf, "detect")) {
|
||||
if (sysfs_streq(buf, "detect"))
|
||||
connector->force = 0;
|
||||
connector->status = connector->funcs->detect(connector, true);
|
||||
} else if (sysfs_streq(buf, "on")) {
|
||||
else if (sysfs_streq(buf, "on"))
|
||||
connector->force = DRM_FORCE_ON;
|
||||
} else if (sysfs_streq(buf, "on-digital")) {
|
||||
else if (sysfs_streq(buf, "on-digital"))
|
||||
connector->force = DRM_FORCE_ON_DIGITAL;
|
||||
} else if (sysfs_streq(buf, "off")) {
|
||||
else if (sysfs_streq(buf, "off"))
|
||||
connector->force = DRM_FORCE_OFF;
|
||||
} else
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret == 0 && connector->force) {
|
||||
if (connector->force == DRM_FORCE_ON ||
|
||||
connector->force == DRM_FORCE_ON_DIGITAL)
|
||||
connector->status = connector_status_connected;
|
||||
else
|
||||
connector->status = connector_status_disconnected;
|
||||
if (connector->funcs->force)
|
||||
connector->funcs->force(connector);
|
||||
}
|
||||
|
||||
if (old_status != connector->status) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
|
||||
if (old_force != connector->force || !connector->force) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force updated from %d to %d or reprobing\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
old_status, connector->status);
|
||||
old_force, connector->force);
|
||||
|
||||
dev->mode_config.delayed_event = true;
|
||||
if (dev->mode_config.poll_enabled)
|
||||
schedule_delayed_work(&dev->mode_config.output_poll_work,
|
||||
0);
|
||||
connector->funcs->fill_modes(connector,
|
||||
dev->mode_config.max_width,
|
||||
dev->mode_config.max_height);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
@ -256,23 +244,29 @@ static ssize_t edid_show(struct file *filp, struct kobject *kobj,
|
|||
struct drm_connector *connector = to_drm_connector(connector_dev);
|
||||
unsigned char *edid;
|
||||
size_t size;
|
||||
ssize_t ret = 0;
|
||||
|
||||
mutex_lock(&connector->dev->mode_config.mutex);
|
||||
if (!connector->edid_blob_ptr)
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
edid = connector->edid_blob_ptr->data;
|
||||
size = connector->edid_blob_ptr->length;
|
||||
if (!edid)
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
if (off >= size)
|
||||
return 0;
|
||||
goto unlock;
|
||||
|
||||
if (off + count > size)
|
||||
count = size - off;
|
||||
memcpy(buf, edid + off, count);
|
||||
|
||||
return count;
|
||||
ret = count;
|
||||
unlock:
|
||||
mutex_unlock(&connector->dev->mode_config.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t modes_show(struct device *device,
|
||||
|
@ -283,10 +277,12 @@ static ssize_t modes_show(struct device *device,
|
|||
struct drm_display_mode *mode;
|
||||
int written = 0;
|
||||
|
||||
mutex_lock(&connector->dev->mode_config.mutex);
|
||||
list_for_each_entry(mode, &connector->modes, head) {
|
||||
written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
|
||||
mode->name);
|
||||
}
|
||||
mutex_unlock(&connector->dev->mode_config.mutex);
|
||||
|
||||
return written;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ static struct drm_framebuffer_funcs exynos_drm_fb_funcs = {
|
|||
|
||||
struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct exynos_drm_gem **exynos_gem,
|
||||
int count)
|
||||
{
|
||||
|
@ -154,7 +154,7 @@ err:
|
|||
|
||||
static struct drm_framebuffer *
|
||||
exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct exynos_drm_gem *exynos_gem[MAX_FB_BUFFER];
|
||||
struct drm_gem_object *obj;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
struct drm_framebuffer *
|
||||
exynos_drm_framebuffer_init(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct exynos_drm_gem **exynos_gem,
|
||||
int count);
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ static struct fb_ops psbfb_unaccel_ops = {
|
|||
*/
|
||||
static int psb_framebuffer_init(struct drm_device *dev,
|
||||
struct psb_framebuffer *fb,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct gtt_range *gt)
|
||||
{
|
||||
u32 bpp, depth;
|
||||
|
@ -284,7 +284,7 @@ static int psb_framebuffer_init(struct drm_device *dev,
|
|||
|
||||
static struct drm_framebuffer *psb_framebuffer_create
|
||||
(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct gtt_range *gt)
|
||||
{
|
||||
struct psb_framebuffer *fb;
|
||||
|
@ -406,8 +406,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
|||
|
||||
memset(dev_priv->vram_addr + backing->offset, 0, size);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
info = drm_fb_helper_alloc_fbi(&fbdev->psb_fb_helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
|
@ -463,17 +461,15 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
|||
dev_dbg(dev->dev, "allocated %dx%d fb\n",
|
||||
psbfb->base.width, psbfb->base.height);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
out_unref:
|
||||
if (backing->stolen)
|
||||
psb_gtt_free_range(dev, backing);
|
||||
else
|
||||
drm_gem_object_unreference(&backing->gem);
|
||||
drm_gem_object_unreference_unlocked(&backing->gem);
|
||||
|
||||
drm_fb_helper_release_fbi(&fbdev->psb_fb_helper);
|
||||
out_err1:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
psb_gtt_free_range(dev, backing);
|
||||
return ret;
|
||||
}
|
||||
|
@ -488,7 +484,7 @@ out_err1:
|
|||
*/
|
||||
static struct drm_framebuffer *psb_user_framebuffer_create
|
||||
(struct drm_device *dev, struct drm_file *filp,
|
||||
struct drm_mode_fb_cmd2 *cmd)
|
||||
const struct drm_mode_fb_cmd2 *cmd)
|
||||
{
|
||||
struct gtt_range *r;
|
||||
struct drm_gem_object *obj;
|
||||
|
@ -569,7 +565,7 @@ static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
|
|||
drm_framebuffer_cleanup(&psbfb->base);
|
||||
|
||||
if (psbfb->gtt)
|
||||
drm_gem_object_unreference(&psbfb->gtt->gem);
|
||||
drm_gem_object_unreference_unlocked(&psbfb->gtt->gem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -784,12 +780,8 @@ void psb_modeset_cleanup(struct drm_device *dev)
|
|||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
if (dev_priv->modeset) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
psb_fbdev_fini(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,15 +62,10 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
|
|||
int ret = 0;
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* GEM does all our handle to object mapping */
|
||||
obj = drm_gem_object_lookup(dev, file, handle);
|
||||
if (obj == NULL) {
|
||||
ret = -ENOENT;
|
||||
goto unlock;
|
||||
}
|
||||
/* What validation is needed here ? */
|
||||
if (obj == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
/* Make it mmapable */
|
||||
ret = drm_gem_create_mmap_offset(obj);
|
||||
|
@ -78,9 +73,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
|
|||
goto out;
|
||||
*offset = drm_vma_node_offset_addr(&obj->vma_node);
|
||||
out:
|
||||
drm_gem_object_unreference(obj);
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -130,7 +123,7 @@ int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size,
|
|||
return ret;
|
||||
}
|
||||
/* We have the initial and handle reference but need only one now */
|
||||
drm_gem_object_unreference(&r->gem);
|
||||
drm_gem_object_unreference_unlocked(&r->gem);
|
||||
*handlep = handle;
|
||||
return 0;
|
||||
}
|
||||
|
@ -189,7 +182,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
|
||||
/* Make sure we don't parallel update on a fault, nor move or remove
|
||||
something from beneath our feet */
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
mutex_lock(&dev_priv->mmap_mutex);
|
||||
|
||||
/* For now the mmap pins the object and it stays pinned. As things
|
||||
stand that will do us no harm */
|
||||
|
@ -215,7 +208,7 @@ int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||
ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
|
||||
|
||||
fail:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
mutex_unlock(&dev_priv->mmap_mutex);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
case -ERESTARTSYS:
|
||||
|
|
|
@ -349,8 +349,6 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
/* If we didn't get a handle then turn the cursor off */
|
||||
if (!handle) {
|
||||
temp = CURSOR_MODE_DISABLE;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
REG_WRITE(control, temp);
|
||||
REG_WRITE(base, 0);
|
||||
|
@ -362,11 +360,9 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
gt = container_of(gma_crtc->cursor_obj,
|
||||
struct gtt_range, gem);
|
||||
psb_gtt_unpin(gt);
|
||||
drm_gem_object_unreference(gma_crtc->cursor_obj);
|
||||
drm_gem_object_unreference_unlocked(gma_crtc->cursor_obj);
|
||||
gma_crtc->cursor_obj = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -376,7 +372,6 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
obj = drm_gem_object_lookup(dev, file_priv, handle);
|
||||
if (!obj) {
|
||||
ret = -ENOENT;
|
||||
|
@ -441,17 +436,15 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
if (gma_crtc->cursor_obj) {
|
||||
gt = container_of(gma_crtc->cursor_obj, struct gtt_range, gem);
|
||||
psb_gtt_unpin(gt);
|
||||
drm_gem_object_unreference(gma_crtc->cursor_obj);
|
||||
drm_gem_object_unreference_unlocked(gma_crtc->cursor_obj);
|
||||
}
|
||||
|
||||
gma_crtc->cursor_obj = obj;
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return ret;
|
||||
|
||||
unref_cursor:
|
||||
drm_gem_object_unreference(obj);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -425,6 +425,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
|
|||
|
||||
if (!resume) {
|
||||
mutex_init(&dev_priv->gtt_mutex);
|
||||
mutex_init(&dev_priv->mmap_mutex);
|
||||
psb_gtt_alloc(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -465,6 +465,8 @@ struct drm_psb_private {
|
|||
struct mutex gtt_mutex;
|
||||
struct resource *gtt_mem; /* Our PCI resource */
|
||||
|
||||
struct mutex mmap_mutex;
|
||||
|
||||
struct psb_mmu_driver *mmu;
|
||||
struct psb_mmu_pd *pf_pd;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ config DRM_I915
|
|||
# the shmem_readpage() which depends upon tmpfs
|
||||
select SHMEM
|
||||
select TMPFS
|
||||
select STOP_MACHINE
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL
|
||||
select DRM_MIPI_DSI
|
||||
|
|
|
@ -77,6 +77,7 @@ i915-y += dvo_ch7017.o \
|
|||
dvo_tfp410.o \
|
||||
intel_crt.o \
|
||||
intel_ddi.o \
|
||||
intel_dp_link_training.o \
|
||||
intel_dp_mst.o \
|
||||
intel_dp.o \
|
||||
intel_dsi.o \
|
||||
|
|
|
@ -32,7 +32,8 @@ struct intel_dvo_device {
|
|||
const char *name;
|
||||
int type;
|
||||
/* DVOA/B/C output register */
|
||||
u32 dvo_reg;
|
||||
i915_reg_t dvo_reg;
|
||||
i915_reg_t dvo_srcdim_reg;
|
||||
/* GPIO register used for i2c bus to control this device */
|
||||
u32 gpio;
|
||||
int slave_addr;
|
||||
|
|
|
@ -407,14 +407,14 @@ static const struct drm_i915_cmd_table hsw_blt_ring_cmds[] = {
|
|||
* LRI.
|
||||
*/
|
||||
struct drm_i915_reg_descriptor {
|
||||
u32 addr;
|
||||
i915_reg_t addr;
|
||||
u32 mask;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
/* Convenience macro for adding 32-bit registers. */
|
||||
#define REG32(address, ...) \
|
||||
{ .addr = address, __VA_ARGS__ }
|
||||
#define REG32(_reg, ...) \
|
||||
{ .addr = (_reg), __VA_ARGS__ }
|
||||
|
||||
/*
|
||||
* Convenience macro for adding 64-bit registers.
|
||||
|
@ -423,8 +423,13 @@ struct drm_i915_reg_descriptor {
|
|||
* access commands only allow 32-bit accesses. Hence, we have to include
|
||||
* entries for both halves of the 64-bit registers.
|
||||
*/
|
||||
#define REG64(addr) \
|
||||
REG32(addr), REG32(addr + sizeof(u32))
|
||||
#define REG64(_reg) \
|
||||
{ .addr = _reg }, \
|
||||
{ .addr = _reg ## _UDW }
|
||||
|
||||
#define REG64_IDX(_reg, idx) \
|
||||
{ .addr = _reg(idx) }, \
|
||||
{ .addr = _reg ## _UDW(idx) }
|
||||
|
||||
static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
|
||||
REG64(GPGPU_THREADS_DISPATCHED),
|
||||
|
@ -451,14 +456,14 @@ static const struct drm_i915_reg_descriptor gen7_render_regs[] = {
|
|||
REG32(GEN7_GPGPU_DISPATCHDIMX),
|
||||
REG32(GEN7_GPGPU_DISPATCHDIMY),
|
||||
REG32(GEN7_GPGPU_DISPATCHDIMZ),
|
||||
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(0)),
|
||||
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(1)),
|
||||
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(2)),
|
||||
REG64(GEN7_SO_NUM_PRIMS_WRITTEN(3)),
|
||||
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(0)),
|
||||
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(1)),
|
||||
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(2)),
|
||||
REG64(GEN7_SO_PRIM_STORAGE_NEEDED(3)),
|
||||
REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 0),
|
||||
REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 1),
|
||||
REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 2),
|
||||
REG64_IDX(GEN7_SO_NUM_PRIMS_WRITTEN, 3),
|
||||
REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 0),
|
||||
REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 1),
|
||||
REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 2),
|
||||
REG64_IDX(GEN7_SO_PRIM_STORAGE_NEEDED, 3),
|
||||
REG32(GEN7_SO_WRITE_OFFSET(0)),
|
||||
REG32(GEN7_SO_WRITE_OFFSET(1)),
|
||||
REG32(GEN7_SO_WRITE_OFFSET(2)),
|
||||
|
@ -592,7 +597,7 @@ static bool check_sorted(int ring_id,
|
|||
bool ret = true;
|
||||
|
||||
for (i = 0; i < reg_count; i++) {
|
||||
u32 curr = reg_table[i].addr;
|
||||
u32 curr = i915_mmio_reg_offset(reg_table[i].addr);
|
||||
|
||||
if (curr < previous) {
|
||||
DRM_ERROR("CMD: table not sorted ring=%d entry=%d reg=0x%08X prev=0x%08X\n",
|
||||
|
@ -847,7 +852,7 @@ find_reg(const struct drm_i915_reg_descriptor *table,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (table[i].addr == addr)
|
||||
if (i915_mmio_reg_offset(table[i].addr) == addr)
|
||||
return &table[i];
|
||||
}
|
||||
}
|
||||
|
@ -1023,7 +1028,7 @@ static bool check_cmd(const struct intel_engine_cs *ring,
|
|||
* to the register. Hence, limit OACONTROL writes to
|
||||
* only MI_LOAD_REGISTER_IMM commands.
|
||||
*/
|
||||
if (reg_addr == OACONTROL) {
|
||||
if (reg_addr == i915_mmio_reg_offset(OACONTROL)) {
|
||||
if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
|
||||
DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n");
|
||||
return false;
|
||||
|
|
|
@ -1252,18 +1252,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
|
|||
|
||||
max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 0 :
|
||||
rp_state_cap >> 16) & 0xff;
|
||||
max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
|
||||
max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
|
||||
GEN9_FREQ_SCALER : 1);
|
||||
seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
|
||||
intel_gpu_freq(dev_priv, max_freq));
|
||||
|
||||
max_freq = (rp_state_cap & 0xff00) >> 8;
|
||||
max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
|
||||
max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
|
||||
GEN9_FREQ_SCALER : 1);
|
||||
seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
|
||||
intel_gpu_freq(dev_priv, max_freq));
|
||||
|
||||
max_freq = (IS_BROXTON(dev) ? rp_state_cap >> 16 :
|
||||
rp_state_cap >> 0) & 0xff;
|
||||
max_freq *= (IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1);
|
||||
max_freq *= (IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
|
||||
GEN9_FREQ_SCALER : 1);
|
||||
seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
|
||||
intel_gpu_freq(dev_priv, max_freq));
|
||||
seq_printf(m, "Max overclocked frequency: %dMHz\n",
|
||||
|
@ -1523,7 +1526,7 @@ static int gen6_drpc_info(struct seq_file *m)
|
|||
seq_printf(m, "RC information accurate: %s\n", yesno(count < 51));
|
||||
}
|
||||
|
||||
gt_core_status = readl(dev_priv->regs + GEN6_GT_CORE_STATUS);
|
||||
gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS);
|
||||
trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true);
|
||||
|
||||
rpmodectl1 = I915_READ(GEN6_RP_CONTROL);
|
||||
|
@ -1640,7 +1643,7 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
|
|||
seq_puts(m, "FBC enabled\n");
|
||||
else
|
||||
seq_printf(m, "FBC disabled: %s\n",
|
||||
intel_no_fbc_reason_str(dev_priv->fbc.no_fbc_reason));
|
||||
dev_priv->fbc.no_fbc_reason);
|
||||
|
||||
if (INTEL_INFO(dev_priv)->gen >= 7)
|
||||
seq_printf(m, "Compressing: %s\n",
|
||||
|
@ -1801,7 +1804,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (IS_SKYLAKE(dev)) {
|
||||
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
|
||||
/* Convert GT frequency to 50 HZ units */
|
||||
min_gpu_freq =
|
||||
dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER;
|
||||
|
@ -1821,7 +1824,8 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused)
|
|||
&ia_freq);
|
||||
seq_printf(m, "%d\t\t%d\t\t\t\t%d\n",
|
||||
intel_gpu_freq(dev_priv, (gpu_freq *
|
||||
(IS_SKYLAKE(dev) ? GEN9_FREQ_SCALER : 1))),
|
||||
(IS_SKYLAKE(dev) || IS_KABYLAKE(dev) ?
|
||||
GEN9_FREQ_SCALER : 1))),
|
||||
((ia_freq >> 0) & 0xff) * 100,
|
||||
((ia_freq >> 8) & 0xff) * 100);
|
||||
}
|
||||
|
@ -1873,17 +1877,19 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
ifbdev = dev_priv->fbdev;
|
||||
fb = to_intel_framebuffer(ifbdev->helper.fb);
|
||||
if (ifbdev) {
|
||||
fb = to_intel_framebuffer(ifbdev->helper.fb);
|
||||
|
||||
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel,
|
||||
fb->base.modifier[0],
|
||||
atomic_read(&fb->base.refcount.refcount));
|
||||
describe_obj(m, fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
seq_printf(m, "fbcon size: %d x %d, depth %d, %d bpp, modifier 0x%llx, refcount %d, obj ",
|
||||
fb->base.width,
|
||||
fb->base.height,
|
||||
fb->base.depth,
|
||||
fb->base.bits_per_pixel,
|
||||
fb->base.modifier[0],
|
||||
atomic_read(&fb->base.refcount.refcount));
|
||||
describe_obj(m, fb->obj);
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
mutex_lock(&dev->mode_config.fb_lock);
|
||||
|
@ -2402,6 +2408,12 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
|
|||
guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
|
||||
seq_printf(m, "\tversion found: %d.%d\n",
|
||||
guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
|
||||
seq_printf(m, "\theader: offset is %d; size = %d\n",
|
||||
guc_fw->header_offset, guc_fw->header_size);
|
||||
seq_printf(m, "\tuCode: offset is %d; size = %d\n",
|
||||
guc_fw->ucode_offset, guc_fw->ucode_size);
|
||||
seq_printf(m, "\tRSA: offset is %d; size = %d\n",
|
||||
guc_fw->rsa_offset, guc_fw->rsa_size);
|
||||
|
||||
tmp = I915_READ(GUC_STATUS);
|
||||
|
||||
|
@ -2550,7 +2562,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
|||
yesno(work_busy(&dev_priv->psr.work.work)));
|
||||
|
||||
if (HAS_DDI(dev))
|
||||
enabled = I915_READ(EDP_PSR_CTL(dev)) & EDP_PSR_ENABLE;
|
||||
enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
|
||||
else {
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) &
|
||||
|
@ -2572,7 +2584,7 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
|
|||
|
||||
/* CHV PSR has no kind of performance counter */
|
||||
if (HAS_DDI(dev)) {
|
||||
psrperf = I915_READ(EDP_PSR_PERF_CNT(dev)) &
|
||||
psrperf = I915_READ(EDP_PSR_PERF_CNT) &
|
||||
EDP_PSR_PERF_CNT_MASK;
|
||||
|
||||
seq_printf(m, "Performance_Counter: %u\n", psrperf);
|
||||
|
@ -2696,24 +2708,16 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
|
|||
return "TRANSCODER_C";
|
||||
case POWER_DOMAIN_TRANSCODER_EDP:
|
||||
return "TRANSCODER_EDP";
|
||||
case POWER_DOMAIN_PORT_DDI_A_2_LANES:
|
||||
return "PORT_DDI_A_2_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_A_4_LANES:
|
||||
return "PORT_DDI_A_4_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_B_2_LANES:
|
||||
return "PORT_DDI_B_2_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_B_4_LANES:
|
||||
return "PORT_DDI_B_4_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_C_2_LANES:
|
||||
return "PORT_DDI_C_2_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_C_4_LANES:
|
||||
return "PORT_DDI_C_4_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_D_2_LANES:
|
||||
return "PORT_DDI_D_2_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_D_4_LANES:
|
||||
return "PORT_DDI_D_4_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_E_2_LANES:
|
||||
return "PORT_DDI_E_2_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_A_LANES:
|
||||
return "PORT_DDI_A_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_B_LANES:
|
||||
return "PORT_DDI_B_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_C_LANES:
|
||||
return "PORT_DDI_C_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_D_LANES:
|
||||
return "PORT_DDI_D_LANES";
|
||||
case POWER_DOMAIN_PORT_DDI_E_LANES:
|
||||
return "PORT_DDI_E_LANES";
|
||||
case POWER_DOMAIN_PORT_DSI:
|
||||
return "PORT_DSI";
|
||||
case POWER_DOMAIN_PORT_CRT:
|
||||
|
@ -2736,6 +2740,8 @@ static const char *power_domain_str(enum intel_display_power_domain domain)
|
|||
return "AUX_D";
|
||||
case POWER_DOMAIN_GMBUS:
|
||||
return "GMBUS";
|
||||
case POWER_DOMAIN_MODESET:
|
||||
return "MODESET";
|
||||
case POWER_DOMAIN_INIT:
|
||||
return "INIT";
|
||||
default:
|
||||
|
@ -2779,6 +2785,51 @@ static int i915_power_domain_info(struct seq_file *m, void *unused)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dmc_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_csr *csr;
|
||||
|
||||
if (!HAS_CSR(dev)) {
|
||||
seq_puts(m, "not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
csr = &dev_priv->csr;
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
seq_printf(m, "fw loaded: %s\n", yesno(csr->dmc_payload != NULL));
|
||||
seq_printf(m, "path: %s\n", csr->fw_path);
|
||||
|
||||
if (!csr->dmc_payload)
|
||||
goto out;
|
||||
|
||||
seq_printf(m, "version: %d.%d\n", CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version));
|
||||
|
||||
if (IS_SKYLAKE(dev) && csr->version >= CSR_VERSION(1, 6)) {
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
I915_READ(SKL_CSR_DC3_DC5_COUNT));
|
||||
seq_printf(m, "DC5 -> DC6 count: %d\n",
|
||||
I915_READ(SKL_CSR_DC5_DC6_COUNT));
|
||||
} else if (IS_BROXTON(dev) && csr->version >= CSR_VERSION(1, 4)) {
|
||||
seq_printf(m, "DC3 -> DC5 count: %d\n",
|
||||
I915_READ(BXT_CSR_DC3_DC5_COUNT));
|
||||
}
|
||||
|
||||
out:
|
||||
seq_printf(m, "program base: 0x%08x\n", I915_READ(CSR_PROGRAM(0)));
|
||||
seq_printf(m, "ssp base: 0x%08x\n", I915_READ(CSR_SSP_BASE));
|
||||
seq_printf(m, "htp: 0x%08x\n", I915_READ(CSR_HTP_SKL));
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_seq_print_mode(struct seq_file *m, int tabs,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
|
@ -2946,6 +2997,107 @@ static bool cursor_position(struct drm_device *dev, int pipe, int *x, int *y)
|
|||
return cursor_active(dev, pipe);
|
||||
}
|
||||
|
||||
static const char *plane_type(enum drm_plane_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case DRM_PLANE_TYPE_OVERLAY:
|
||||
return "OVL";
|
||||
case DRM_PLANE_TYPE_PRIMARY:
|
||||
return "PRI";
|
||||
case DRM_PLANE_TYPE_CURSOR:
|
||||
return "CUR";
|
||||
/*
|
||||
* Deliberately omitting default: to generate compiler warnings
|
||||
* when a new drm_plane_type gets added.
|
||||
*/
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
static const char *plane_rotation(unsigned int rotation)
|
||||
{
|
||||
static char buf[48];
|
||||
/*
|
||||
* According to doc only one DRM_ROTATE_ is allowed but this
|
||||
* will print them all to visualize if the values are misused
|
||||
*/
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s%s%s%s%s%s(0x%08x)",
|
||||
(rotation & BIT(DRM_ROTATE_0)) ? "0 " : "",
|
||||
(rotation & BIT(DRM_ROTATE_90)) ? "90 " : "",
|
||||
(rotation & BIT(DRM_ROTATE_180)) ? "180 " : "",
|
||||
(rotation & BIT(DRM_ROTATE_270)) ? "270 " : "",
|
||||
(rotation & BIT(DRM_REFLECT_X)) ? "FLIPX " : "",
|
||||
(rotation & BIT(DRM_REFLECT_Y)) ? "FLIPY " : "",
|
||||
rotation);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void intel_plane_info(struct seq_file *m, struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct intel_plane *intel_plane;
|
||||
|
||||
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
|
||||
struct drm_plane_state *state;
|
||||
struct drm_plane *plane = &intel_plane->base;
|
||||
|
||||
if (!plane->state) {
|
||||
seq_puts(m, "plane->state is NULL!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
state = plane->state;
|
||||
|
||||
seq_printf(m, "\t--Plane id %d: type=%s, crtc_pos=%4dx%4d, crtc_size=%4dx%4d, src_pos=%d.%04ux%d.%04u, src_size=%d.%04ux%d.%04u, format=%s, rotation=%s\n",
|
||||
plane->base.id,
|
||||
plane_type(intel_plane->base.type),
|
||||
state->crtc_x, state->crtc_y,
|
||||
state->crtc_w, state->crtc_h,
|
||||
(state->src_x >> 16),
|
||||
((state->src_x & 0xffff) * 15625) >> 10,
|
||||
(state->src_y >> 16),
|
||||
((state->src_y & 0xffff) * 15625) >> 10,
|
||||
(state->src_w >> 16),
|
||||
((state->src_w & 0xffff) * 15625) >> 10,
|
||||
(state->src_h >> 16),
|
||||
((state->src_h & 0xffff) * 15625) >> 10,
|
||||
state->fb ? drm_get_format_name(state->fb->pixel_format) : "N/A",
|
||||
plane_rotation(state->rotation));
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_scaler_info(struct seq_file *m, struct intel_crtc *intel_crtc)
|
||||
{
|
||||
struct intel_crtc_state *pipe_config;
|
||||
int num_scalers = intel_crtc->num_scalers;
|
||||
int i;
|
||||
|
||||
pipe_config = to_intel_crtc_state(intel_crtc->base.state);
|
||||
|
||||
/* Not all platformas have a scaler */
|
||||
if (num_scalers) {
|
||||
seq_printf(m, "\tnum_scalers=%d, scaler_users=%x scaler_id=%d",
|
||||
num_scalers,
|
||||
pipe_config->scaler_state.scaler_users,
|
||||
pipe_config->scaler_state.scaler_id);
|
||||
|
||||
for (i = 0; i < SKL_NUM_SCALERS; i++) {
|
||||
struct intel_scaler *sc =
|
||||
&pipe_config->scaler_state.scalers[i];
|
||||
|
||||
seq_printf(m, ", scalers[%d]: use=%s, mode=%x",
|
||||
i, yesno(sc->in_use), sc->mode);
|
||||
}
|
||||
seq_puts(m, "\n");
|
||||
} else {
|
||||
seq_puts(m, "\tNo scalers available on this platform\n");
|
||||
}
|
||||
}
|
||||
|
||||
static int i915_display_info(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
|
@ -2965,10 +3117,12 @@ static int i915_display_info(struct seq_file *m, void *unused)
|
|||
|
||||
pipe_config = to_intel_crtc_state(crtc->base.state);
|
||||
|
||||
seq_printf(m, "CRTC %d: pipe: %c, active=%s (size=%dx%d)\n",
|
||||
seq_printf(m, "CRTC %d: pipe: %c, active=%s, (size=%dx%d), dither=%s, bpp=%d\n",
|
||||
crtc->base.base.id, pipe_name(crtc->pipe),
|
||||
yesno(pipe_config->base.active),
|
||||
pipe_config->pipe_src_w, pipe_config->pipe_src_h);
|
||||
pipe_config->pipe_src_w, pipe_config->pipe_src_h,
|
||||
yesno(pipe_config->dither), pipe_config->pipe_bpp);
|
||||
|
||||
if (pipe_config->base.active) {
|
||||
intel_crtc_info(m, crtc);
|
||||
|
||||
|
@ -2978,6 +3132,8 @@ static int i915_display_info(struct seq_file *m, void *unused)
|
|||
x, y, crtc->base.cursor->state->crtc_w,
|
||||
crtc->base.cursor->state->crtc_h,
|
||||
crtc->cursor_addr, yesno(active));
|
||||
intel_scaler_info(m, crtc);
|
||||
intel_plane_info(m, crtc);
|
||||
}
|
||||
|
||||
seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s \n",
|
||||
|
@ -3112,7 +3268,8 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
|
|||
|
||||
seq_printf(m, "Workarounds applied: %d\n", dev_priv->workarounds.count);
|
||||
for (i = 0; i < dev_priv->workarounds.count; ++i) {
|
||||
u32 addr, mask, value, read;
|
||||
i915_reg_t addr;
|
||||
u32 mask, value, read;
|
||||
bool ok;
|
||||
|
||||
addr = dev_priv->workarounds.reg[i].addr;
|
||||
|
@ -3121,7 +3278,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused)
|
|||
read = I915_READ(addr);
|
||||
ok = (value & mask) == (read & mask);
|
||||
seq_printf(m, "0x%X: 0x%08X, mask: 0x%08X, read: 0x%08x, status: %s\n",
|
||||
addr, value, mask, read, ok ? "OK" : "FAIL");
|
||||
i915_mmio_reg_offset(addr), value, mask, read, ok ? "OK" : "FAIL");
|
||||
}
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
@ -5025,7 +5182,7 @@ static void gen9_sseu_device_status(struct drm_device *dev,
|
|||
|
||||
stat->slice_total++;
|
||||
|
||||
if (IS_SKYLAKE(dev))
|
||||
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
ss_cnt = INTEL_INFO(dev)->subslice_per_slice;
|
||||
|
||||
for (ss = 0; ss < ss_max; ss++) {
|
||||
|
@ -5238,6 +5395,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
|
|||
{"i915_energy_uJ", i915_energy_uJ, 0},
|
||||
{"i915_runtime_pm_status", i915_runtime_pm_status, 0},
|
||||
{"i915_power_domain_info", i915_power_domain_info, 0},
|
||||
{"i915_dmc_info", i915_dmc_info, 0},
|
||||
{"i915_display_info", i915_display_info, 0},
|
||||
{"i915_semaphore_status", i915_semaphore_status, 0},
|
||||
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/async.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
|
@ -338,7 +337,7 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_
|
|||
i915_resume_switcheroo(dev);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_ON;
|
||||
} else {
|
||||
pr_err("switched off\n");
|
||||
pr_info("switched off\n");
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
|
||||
i915_suspend_switcheroo(dev, pmm);
|
||||
dev->switch_power_state = DRM_SWITCH_POWER_OFF;
|
||||
|
@ -396,7 +395,9 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
if (ret)
|
||||
goto cleanup_vga_switcheroo;
|
||||
|
||||
intel_power_domains_init_hw(dev_priv);
|
||||
intel_power_domains_init_hw(dev_priv, false);
|
||||
|
||||
intel_csr_ucode_init(dev_priv);
|
||||
|
||||
ret = intel_irq_install(dev_priv);
|
||||
if (ret)
|
||||
|
@ -437,7 +438,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
|||
* scanning against hotplug events. Hence do this first and ignore the
|
||||
* tiny window where we will loose hotplug notifactions.
|
||||
*/
|
||||
async_schedule(intel_fbdev_initial_config, dev_priv);
|
||||
intel_fbdev_initial_config_async(dev);
|
||||
|
||||
drm_kms_helper_poll_init(dev);
|
||||
|
||||
|
@ -663,7 +664,8 @@ static void gen9_sseu_info_init(struct drm_device *dev)
|
|||
* supports EU power gating on devices with more than one EU
|
||||
* pair per subslice.
|
||||
*/
|
||||
info->has_slice_pg = (IS_SKYLAKE(dev) && (info->slice_total > 1));
|
||||
info->has_slice_pg = ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) &&
|
||||
(info->slice_total > 1));
|
||||
info->has_subslice_pg = (IS_BROXTON(dev) && (info->subslice_total > 1));
|
||||
info->has_eu_pg = (info->eu_per_subslice > 2);
|
||||
}
|
||||
|
@ -890,7 +892,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
spin_lock_init(&dev_priv->mmio_flip_lock);
|
||||
mutex_init(&dev_priv->sb_lock);
|
||||
mutex_init(&dev_priv->modeset_restore_lock);
|
||||
mutex_init(&dev_priv->csr_lock);
|
||||
mutex_init(&dev_priv->av_mutex);
|
||||
|
||||
intel_pm_setup(dev);
|
||||
|
@ -937,9 +938,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
intel_uncore_init(dev);
|
||||
|
||||
/* Load CSR Firmware for SKL */
|
||||
intel_csr_ucode_init(dev);
|
||||
|
||||
ret = i915_gem_gtt_init(dev);
|
||||
if (ret)
|
||||
goto out_freecsr;
|
||||
|
@ -1113,7 +1111,7 @@ out_mtrrfree:
|
|||
out_gtt:
|
||||
i915_global_gtt_cleanup(dev);
|
||||
out_freecsr:
|
||||
intel_csr_ucode_fini(dev);
|
||||
intel_csr_ucode_fini(dev_priv);
|
||||
intel_uncore_fini(dev);
|
||||
pci_iounmap(dev->pdev, dev_priv->regs);
|
||||
put_bridge:
|
||||
|
@ -1131,6 +1129,8 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
intel_fbdev_fini(dev);
|
||||
|
||||
i915_audio_component_cleanup(dev_priv);
|
||||
|
||||
ret = i915_gem_suspend(dev);
|
||||
|
@ -1153,8 +1153,6 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
|
||||
acpi_video_unregister();
|
||||
|
||||
intel_fbdev_fini(dev);
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
intel_modeset_cleanup(dev);
|
||||
|
@ -1196,7 +1194,7 @@ int i915_driver_unload(struct drm_device *dev)
|
|||
intel_fbc_cleanup_cfb(dev_priv);
|
||||
i915_gem_cleanup_stolen(dev);
|
||||
|
||||
intel_csr_ucode_fini(dev);
|
||||
intel_csr_ucode_fini(dev_priv);
|
||||
|
||||
intel_teardown_gmbus(dev);
|
||||
intel_teardown_mchbar(dev);
|
||||
|
@ -1264,8 +1262,6 @@ void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
|
|||
{
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
|
||||
if (file_priv && file_priv->bsd_ring)
|
||||
file_priv->bsd_ring = NULL;
|
||||
kfree(file_priv);
|
||||
}
|
||||
|
||||
|
|
|
@ -383,6 +383,7 @@ static const struct intel_device_info intel_skylake_gt3_info = {
|
|||
|
||||
static const struct intel_device_info intel_broxton_info = {
|
||||
.is_preliminary = 1,
|
||||
.is_broxton = 1,
|
||||
.gen = 9,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
|
||||
|
@ -394,50 +395,81 @@ static const struct intel_device_info intel_broxton_info = {
|
|||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_kabylake_info = {
|
||||
.is_preliminary = 1,
|
||||
.is_kabylake = 1,
|
||||
.gen = 9,
|
||||
.num_pipes = 3,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
|
||||
.has_llc = 1,
|
||||
.has_ddi = 1,
|
||||
.has_fpga_dbg = 1,
|
||||
.has_fbc = 1,
|
||||
GEN_DEFAULT_PIPEOFFSETS,
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_kabylake_gt3_info = {
|
||||
.is_preliminary = 1,
|
||||
.is_kabylake = 1,
|
||||
.gen = 9,
|
||||
.num_pipes = 3,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
|
||||
.has_llc = 1,
|
||||
.has_ddi = 1,
|
||||
.has_fpga_dbg = 1,
|
||||
.has_fbc = 1,
|
||||
GEN_DEFAULT_PIPEOFFSETS,
|
||||
IVB_CURSOR_OFFSETS,
|
||||
};
|
||||
|
||||
/*
|
||||
* Make sure any device matches here are from most specific to most
|
||||
* general. For example, since the Quanta match is based on the subsystem
|
||||
* and subvendor IDs, we need it to come before the more general IVB
|
||||
* PCI ID matches, otherwise we'll use the wrong info struct above.
|
||||
*/
|
||||
#define INTEL_PCI_IDS \
|
||||
INTEL_I830_IDS(&intel_i830_info), \
|
||||
INTEL_I845G_IDS(&intel_845g_info), \
|
||||
INTEL_I85X_IDS(&intel_i85x_info), \
|
||||
INTEL_I865G_IDS(&intel_i865g_info), \
|
||||
INTEL_I915G_IDS(&intel_i915g_info), \
|
||||
INTEL_I915GM_IDS(&intel_i915gm_info), \
|
||||
INTEL_I945G_IDS(&intel_i945g_info), \
|
||||
INTEL_I945GM_IDS(&intel_i945gm_info), \
|
||||
INTEL_I965G_IDS(&intel_i965g_info), \
|
||||
INTEL_G33_IDS(&intel_g33_info), \
|
||||
INTEL_I965GM_IDS(&intel_i965gm_info), \
|
||||
INTEL_GM45_IDS(&intel_gm45_info), \
|
||||
INTEL_G45_IDS(&intel_g45_info), \
|
||||
INTEL_PINEVIEW_IDS(&intel_pineview_info), \
|
||||
INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info), \
|
||||
INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info), \
|
||||
INTEL_SNB_D_IDS(&intel_sandybridge_d_info), \
|
||||
INTEL_SNB_M_IDS(&intel_sandybridge_m_info), \
|
||||
INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */ \
|
||||
INTEL_IVB_M_IDS(&intel_ivybridge_m_info), \
|
||||
INTEL_IVB_D_IDS(&intel_ivybridge_d_info), \
|
||||
INTEL_HSW_D_IDS(&intel_haswell_d_info), \
|
||||
INTEL_HSW_M_IDS(&intel_haswell_m_info), \
|
||||
INTEL_VLV_M_IDS(&intel_valleyview_m_info), \
|
||||
INTEL_VLV_D_IDS(&intel_valleyview_d_info), \
|
||||
INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info), \
|
||||
INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info), \
|
||||
INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info), \
|
||||
INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info), \
|
||||
INTEL_CHV_IDS(&intel_cherryview_info), \
|
||||
INTEL_SKL_GT1_IDS(&intel_skylake_info), \
|
||||
INTEL_SKL_GT2_IDS(&intel_skylake_info), \
|
||||
INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info), \
|
||||
INTEL_BXT_IDS(&intel_broxton_info)
|
||||
|
||||
static const struct pci_device_id pciidlist[] = { /* aka */
|
||||
INTEL_PCI_IDS,
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
INTEL_I830_IDS(&intel_i830_info),
|
||||
INTEL_I845G_IDS(&intel_845g_info),
|
||||
INTEL_I85X_IDS(&intel_i85x_info),
|
||||
INTEL_I865G_IDS(&intel_i865g_info),
|
||||
INTEL_I915G_IDS(&intel_i915g_info),
|
||||
INTEL_I915GM_IDS(&intel_i915gm_info),
|
||||
INTEL_I945G_IDS(&intel_i945g_info),
|
||||
INTEL_I945GM_IDS(&intel_i945gm_info),
|
||||
INTEL_I965G_IDS(&intel_i965g_info),
|
||||
INTEL_G33_IDS(&intel_g33_info),
|
||||
INTEL_I965GM_IDS(&intel_i965gm_info),
|
||||
INTEL_GM45_IDS(&intel_gm45_info),
|
||||
INTEL_G45_IDS(&intel_g45_info),
|
||||
INTEL_PINEVIEW_IDS(&intel_pineview_info),
|
||||
INTEL_IRONLAKE_D_IDS(&intel_ironlake_d_info),
|
||||
INTEL_IRONLAKE_M_IDS(&intel_ironlake_m_info),
|
||||
INTEL_SNB_D_IDS(&intel_sandybridge_d_info),
|
||||
INTEL_SNB_M_IDS(&intel_sandybridge_m_info),
|
||||
INTEL_IVB_Q_IDS(&intel_ivybridge_q_info), /* must be first IVB */
|
||||
INTEL_IVB_M_IDS(&intel_ivybridge_m_info),
|
||||
INTEL_IVB_D_IDS(&intel_ivybridge_d_info),
|
||||
INTEL_HSW_D_IDS(&intel_haswell_d_info),
|
||||
INTEL_HSW_M_IDS(&intel_haswell_m_info),
|
||||
INTEL_VLV_M_IDS(&intel_valleyview_m_info),
|
||||
INTEL_VLV_D_IDS(&intel_valleyview_d_info),
|
||||
INTEL_BDW_GT12M_IDS(&intel_broadwell_m_info),
|
||||
INTEL_BDW_GT12D_IDS(&intel_broadwell_d_info),
|
||||
INTEL_BDW_GT3M_IDS(&intel_broadwell_gt3m_info),
|
||||
INTEL_BDW_GT3D_IDS(&intel_broadwell_gt3d_info),
|
||||
INTEL_CHV_IDS(&intel_cherryview_info),
|
||||
INTEL_SKL_GT1_IDS(&intel_skylake_info),
|
||||
INTEL_SKL_GT2_IDS(&intel_skylake_info),
|
||||
INTEL_SKL_GT3_IDS(&intel_skylake_gt3_info),
|
||||
INTEL_BXT_IDS(&intel_broxton_info),
|
||||
INTEL_KBL_GT1_IDS(&intel_kabylake_info),
|
||||
INTEL_KBL_GT2_IDS(&intel_kabylake_info),
|
||||
INTEL_KBL_GT3_IDS(&intel_kabylake_gt3_info),
|
||||
INTEL_KBL_GT4_IDS(&intel_kabylake_gt3_info),
|
||||
{0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -463,7 +495,7 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev)
|
|||
} else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
|
||||
ret = PCH_LPT;
|
||||
DRM_DEBUG_KMS("Assuming LynxPoint PCH\n");
|
||||
} else if (IS_SKYLAKE(dev)) {
|
||||
} else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
|
||||
ret = PCH_SPT;
|
||||
DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n");
|
||||
}
|
||||
|
@ -526,11 +558,13 @@ void intel_detect_pch(struct drm_device *dev)
|
|||
} else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_SPT;
|
||||
DRM_DEBUG_KMS("Found SunrisePoint PCH\n");
|
||||
WARN_ON(!IS_SKYLAKE(dev));
|
||||
WARN_ON(!IS_SKYLAKE(dev) &&
|
||||
!IS_KABYLAKE(dev));
|
||||
} else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_SPT;
|
||||
DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n");
|
||||
WARN_ON(!IS_SKYLAKE(dev));
|
||||
WARN_ON(!IS_SKYLAKE(dev) &&
|
||||
!IS_KABYLAKE(dev));
|
||||
} else if (id == INTEL_PCH_P2X_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = intel_virt_detect_pch(dev);
|
||||
} else
|
||||
|
@ -570,26 +604,6 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
|
|||
return true;
|
||||
}
|
||||
|
||||
void i915_firmware_load_error_print(const char *fw_path, int err)
|
||||
{
|
||||
DRM_ERROR("failed to load firmware %s (%d)\n", fw_path, err);
|
||||
|
||||
/*
|
||||
* If the reason is not known assume -ENOENT since that's the most
|
||||
* usual failure mode.
|
||||
*/
|
||||
if (!err)
|
||||
err = -ENOENT;
|
||||
|
||||
if (!(IS_BUILTIN(CONFIG_DRM_I915) && err == -ENOENT))
|
||||
return;
|
||||
|
||||
DRM_ERROR(
|
||||
"The driver is built-in, so to load the firmware you need to\n"
|
||||
"include it either in the kernel (see CONFIG_EXTRA_FIRMWARE) or\n"
|
||||
"in your initrd/initramfs image.\n");
|
||||
}
|
||||
|
||||
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
@ -608,7 +622,6 @@ static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
|
|||
static int intel_suspend_complete(struct drm_i915_private *dev_priv);
|
||||
static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
|
||||
bool rpm_resume);
|
||||
static int skl_resume_prepare(struct drm_i915_private *dev_priv);
|
||||
static int bxt_resume_prepare(struct drm_i915_private *dev_priv);
|
||||
|
||||
|
||||
|
@ -679,6 +692,9 @@ static int i915_drm_suspend(struct drm_device *dev)
|
|||
|
||||
intel_display_set_init_power(dev_priv, false);
|
||||
|
||||
if (HAS_CSR(dev_priv))
|
||||
flush_work(&dev_priv->csr.work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -687,10 +703,13 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
|||
struct drm_i915_private *dev_priv = drm_dev->dev_private;
|
||||
int ret;
|
||||
|
||||
intel_power_domains_suspend(dev_priv);
|
||||
|
||||
ret = intel_suspend_complete(dev_priv);
|
||||
|
||||
if (ret) {
|
||||
DRM_ERROR("Suspend complete failed: %d\n", ret);
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -838,13 +857,11 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
|||
|
||||
if (IS_BROXTON(dev))
|
||||
ret = bxt_resume_prepare(dev_priv);
|
||||
else if (IS_SKYLAKE(dev_priv))
|
||||
ret = skl_resume_prepare(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
|
||||
intel_uncore_sanitize(dev);
|
||||
intel_power_domains_init_hw(dev_priv);
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1051,15 +1068,6 @@ static int i915_pm_resume(struct device *dev)
|
|||
return i915_drm_resume(drm_dev);
|
||||
}
|
||||
|
||||
static int skl_suspend_complete(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/* Enabling DC6 is not a hard requirement to enter runtime D3 */
|
||||
|
||||
skl_uninit_cdclk(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hsw_suspend_complete(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
hsw_enable_pc8(dev_priv);
|
||||
|
@ -1099,16 +1107,6 @@ static int bxt_resume_prepare(struct drm_i915_private *dev_priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int skl_resume_prepare(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
skl_init_cdclk(dev_priv);
|
||||
intel_csr_load_program(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save all Gunit registers that may be lost after a D3 and a subsequent
|
||||
* S0i[R123] transition. The list of registers needing a save/restore is
|
||||
|
@ -1572,8 +1570,6 @@ static int intel_runtime_resume(struct device *device)
|
|||
|
||||
if (IS_BROXTON(dev))
|
||||
ret = bxt_resume_prepare(dev_priv);
|
||||
else if (IS_SKYLAKE(dev))
|
||||
ret = skl_resume_prepare(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
|
@ -1616,8 +1612,6 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
|
|||
|
||||
if (IS_BROXTON(dev_priv))
|
||||
ret = bxt_suspend_complete(dev_priv);
|
||||
else if (IS_SKYLAKE(dev_priv))
|
||||
ret = skl_suspend_complete(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
ret = hsw_suspend_complete(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20151010"
|
||||
#define DRIVER_DATE "20151120"
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
|
@ -180,15 +180,11 @@ enum intel_display_power_domain {
|
|||
POWER_DOMAIN_TRANSCODER_B,
|
||||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_EDP,
|
||||
POWER_DOMAIN_PORT_DDI_A_2_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_A_4_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_B_2_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_B_4_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_C_2_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_C_4_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_D_2_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_D_4_LANES,
|
||||
POWER_DOMAIN_PORT_DDI_E_2_LANES,
|
||||
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_DSI,
|
||||
POWER_DOMAIN_PORT_CRT,
|
||||
POWER_DOMAIN_PORT_OTHER,
|
||||
|
@ -200,6 +196,7 @@ enum intel_display_power_domain {
|
|||
POWER_DOMAIN_AUX_C,
|
||||
POWER_DOMAIN_AUX_D,
|
||||
POWER_DOMAIN_GMBUS,
|
||||
POWER_DOMAIN_MODESET,
|
||||
POWER_DOMAIN_INIT,
|
||||
|
||||
POWER_DOMAIN_NUM,
|
||||
|
@ -289,7 +286,7 @@ struct i915_hotplug {
|
|||
list_for_each_entry(intel_plane, \
|
||||
&(dev)->mode_config.plane_list, \
|
||||
base.head) \
|
||||
if ((intel_plane)->pipe == (intel_crtc)->pipe)
|
||||
for_each_if ((intel_plane)->pipe == (intel_crtc)->pipe)
|
||||
|
||||
#define for_each_intel_crtc(dev, intel_crtc) \
|
||||
list_for_each_entry(intel_crtc, &dev->mode_config.crtc_list, base.head)
|
||||
|
@ -306,15 +303,15 @@ struct i915_hotplug {
|
|||
|
||||
#define for_each_encoder_on_crtc(dev, __crtc, intel_encoder) \
|
||||
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
|
||||
if ((intel_encoder)->base.crtc == (__crtc))
|
||||
for_each_if ((intel_encoder)->base.crtc == (__crtc))
|
||||
|
||||
#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
|
||||
list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
|
||||
if ((intel_connector)->base.encoder == (__encoder))
|
||||
for_each_if ((intel_connector)->base.encoder == (__encoder))
|
||||
|
||||
#define for_each_power_domain(domain, mask) \
|
||||
for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \
|
||||
if ((1 << (domain)) & (mask))
|
||||
for_each_if ((1 << (domain)) & (mask))
|
||||
|
||||
struct drm_i915_private;
|
||||
struct i915_mm_struct;
|
||||
|
@ -631,11 +628,9 @@ struct drm_i915_display_funcs {
|
|||
int target, int refclk,
|
||||
struct dpll *match_clock,
|
||||
struct dpll *best_clock);
|
||||
int (*compute_pipe_wm)(struct intel_crtc *crtc,
|
||||
struct drm_atomic_state *state);
|
||||
void (*update_wm)(struct drm_crtc *crtc);
|
||||
void (*update_sprite_wm)(struct drm_plane *plane,
|
||||
struct drm_crtc *crtc,
|
||||
uint32_t sprite_width, uint32_t sprite_height,
|
||||
int pixel_size, bool enable, bool scaled);
|
||||
int (*modeset_calc_cdclk)(struct drm_atomic_state *state);
|
||||
void (*modeset_commit_cdclk)(struct drm_atomic_state *state);
|
||||
/* Returns the active state of the crtc, and if the crtc is active,
|
||||
|
@ -693,18 +688,18 @@ struct intel_uncore_funcs {
|
|||
void (*force_wake_put)(struct drm_i915_private *dev_priv,
|
||||
enum forcewake_domains domains);
|
||||
|
||||
uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
|
||||
uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
|
||||
uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
|
||||
uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, off_t offset, bool trace);
|
||||
uint8_t (*mmio_readb)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
|
||||
uint16_t (*mmio_readw)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
|
||||
uint32_t (*mmio_readl)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
|
||||
uint64_t (*mmio_readq)(struct drm_i915_private *dev_priv, i915_reg_t r, bool trace);
|
||||
|
||||
void (*mmio_writeb)(struct drm_i915_private *dev_priv, off_t offset,
|
||||
void (*mmio_writeb)(struct drm_i915_private *dev_priv, i915_reg_t r,
|
||||
uint8_t val, bool trace);
|
||||
void (*mmio_writew)(struct drm_i915_private *dev_priv, off_t offset,
|
||||
void (*mmio_writew)(struct drm_i915_private *dev_priv, i915_reg_t r,
|
||||
uint16_t val, bool trace);
|
||||
void (*mmio_writel)(struct drm_i915_private *dev_priv, off_t offset,
|
||||
void (*mmio_writel)(struct drm_i915_private *dev_priv, i915_reg_t r,
|
||||
uint32_t val, bool trace);
|
||||
void (*mmio_writeq)(struct drm_i915_private *dev_priv, off_t offset,
|
||||
void (*mmio_writeq)(struct drm_i915_private *dev_priv, i915_reg_t r,
|
||||
uint64_t val, bool trace);
|
||||
};
|
||||
|
||||
|
@ -721,11 +716,11 @@ struct intel_uncore {
|
|||
enum forcewake_domain_id id;
|
||||
unsigned wake_count;
|
||||
struct timer_list timer;
|
||||
u32 reg_set;
|
||||
i915_reg_t reg_set;
|
||||
u32 val_set;
|
||||
u32 val_clear;
|
||||
u32 reg_ack;
|
||||
u32 reg_post;
|
||||
i915_reg_t reg_ack;
|
||||
i915_reg_t reg_post;
|
||||
u32 val_reset;
|
||||
} fw_domain[FW_DOMAIN_ID_COUNT];
|
||||
};
|
||||
|
@ -735,25 +730,24 @@ struct intel_uncore {
|
|||
for ((i__) = 0, (domain__) = &(dev_priv__)->uncore.fw_domain[0]; \
|
||||
(i__) < FW_DOMAIN_ID_COUNT; \
|
||||
(i__)++, (domain__) = &(dev_priv__)->uncore.fw_domain[i__]) \
|
||||
if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
|
||||
for_each_if (((mask__) & (dev_priv__)->uncore.fw_domains) & (1 << (i__)))
|
||||
|
||||
#define for_each_fw_domain(domain__, dev_priv__, i__) \
|
||||
for_each_fw_domain_mask(domain__, FORCEWAKE_ALL, dev_priv__, i__)
|
||||
|
||||
enum csr_state {
|
||||
FW_UNINITIALIZED = 0,
|
||||
FW_LOADED,
|
||||
FW_FAILED
|
||||
};
|
||||
#define CSR_VERSION(major, minor) ((major) << 16 | (minor))
|
||||
#define CSR_VERSION_MAJOR(version) ((version) >> 16)
|
||||
#define CSR_VERSION_MINOR(version) ((version) & 0xffff)
|
||||
|
||||
struct intel_csr {
|
||||
struct work_struct work;
|
||||
const char *fw_path;
|
||||
uint32_t *dmc_payload;
|
||||
uint32_t dmc_fw_size;
|
||||
uint32_t version;
|
||||
uint32_t mmio_count;
|
||||
uint32_t mmioaddr[8];
|
||||
i915_reg_t mmioaddr[8];
|
||||
uint32_t mmiodata[8];
|
||||
enum csr_state state;
|
||||
};
|
||||
|
||||
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
|
||||
|
@ -771,6 +765,8 @@ struct intel_csr {
|
|||
func(is_valleyview) sep \
|
||||
func(is_haswell) sep \
|
||||
func(is_skylake) sep \
|
||||
func(is_broxton) sep \
|
||||
func(is_kabylake) sep \
|
||||
func(is_preliminary) sep \
|
||||
func(has_fbc) sep \
|
||||
func(has_pipe_cxsr) sep \
|
||||
|
@ -929,24 +925,7 @@ struct i915_fbc {
|
|||
struct drm_framebuffer *fb;
|
||||
} *fbc_work;
|
||||
|
||||
enum no_fbc_reason {
|
||||
FBC_OK, /* FBC is enabled */
|
||||
FBC_UNSUPPORTED, /* FBC is not supported by this chipset */
|
||||
FBC_NO_OUTPUT, /* no outputs enabled to compress */
|
||||
FBC_STOLEN_TOO_SMALL, /* not enough space for buffers */
|
||||
FBC_UNSUPPORTED_MODE, /* interlace or doublescanned mode */
|
||||
FBC_MODE_TOO_LARGE, /* mode too large for compression */
|
||||
FBC_BAD_PLANE, /* fbc not supported on plane */
|
||||
FBC_NOT_TILED, /* buffer not tiled */
|
||||
FBC_MULTIPLE_PIPES, /* more than one pipe active */
|
||||
FBC_MODULE_PARAM,
|
||||
FBC_CHIP_DEFAULT, /* disabled by default on this chip */
|
||||
FBC_ROTATION, /* rotation is not supported */
|
||||
FBC_IN_DBG_MASTER, /* kernel debugger is active */
|
||||
FBC_BAD_STRIDE, /* stride is not supported */
|
||||
FBC_PIXEL_RATE, /* pixel rate is too big */
|
||||
FBC_PIXEL_FORMAT /* pixel format is invalid */
|
||||
} no_fbc_reason;
|
||||
const char *no_fbc_reason;
|
||||
|
||||
bool (*fbc_enabled)(struct drm_i915_private *dev_priv);
|
||||
void (*enable_fbc)(struct intel_crtc *crtc);
|
||||
|
@ -1020,7 +999,7 @@ struct intel_gmbus {
|
|||
struct i2c_adapter adapter;
|
||||
u32 force_bit;
|
||||
u32 reg0;
|
||||
u32 gpio_reg;
|
||||
i915_reg_t gpio_reg;
|
||||
struct i2c_algo_bit_data bit_algo;
|
||||
struct drm_i915_private *dev_priv;
|
||||
};
|
||||
|
@ -1669,7 +1648,7 @@ struct i915_frontbuffer_tracking {
|
|||
};
|
||||
|
||||
struct i915_wa_reg {
|
||||
u32 addr;
|
||||
i915_reg_t addr;
|
||||
u32 value;
|
||||
/* bitmask representing WA bits */
|
||||
u32 mask;
|
||||
|
@ -1698,6 +1677,13 @@ struct i915_execbuffer_params {
|
|||
struct drm_i915_gem_request *request;
|
||||
};
|
||||
|
||||
/* used in computing the new watermarks state */
|
||||
struct intel_wm_config {
|
||||
unsigned int num_pipes_active;
|
||||
bool sprites_enabled;
|
||||
bool sprites_scaled;
|
||||
};
|
||||
|
||||
struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
struct kmem_cache *objects;
|
||||
|
@ -1718,9 +1704,6 @@ struct drm_i915_private {
|
|||
|
||||
struct intel_csr csr;
|
||||
|
||||
/* Display CSR-related protection */
|
||||
struct mutex csr_lock;
|
||||
|
||||
struct intel_gmbus gmbus[GMBUS_NUM_PINS];
|
||||
|
||||
/** gmbus_mutex protects against concurrent usage of the single hw gmbus
|
||||
|
@ -1735,6 +1718,8 @@ struct drm_i915_private {
|
|||
/* MMIO base address for MIPI regs */
|
||||
uint32_t mipi_mmio_base;
|
||||
|
||||
uint32_t psr_mmio_base;
|
||||
|
||||
wait_queue_head_t gmbus_wait_queue;
|
||||
|
||||
struct pci_dev *bridge_dev;
|
||||
|
@ -1922,6 +1907,9 @@ struct drm_i915_private {
|
|||
*/
|
||||
uint16_t skl_latency[8];
|
||||
|
||||
/* Committed wm config */
|
||||
struct intel_wm_config config;
|
||||
|
||||
/*
|
||||
* The skl_wm_values structure is a bit too big for stack
|
||||
* allocation, so we keep the staging struct where we store
|
||||
|
@ -1956,6 +1944,8 @@ struct drm_i915_private {
|
|||
/* perform PHY state sanity checks? */
|
||||
bool chv_phy_assert[2];
|
||||
|
||||
struct intel_encoder *dig_port_map[I915_MAX_PORTS];
|
||||
|
||||
/*
|
||||
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
|
||||
* will be rejected. Instead look for a better place.
|
||||
|
@ -1980,7 +1970,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc)
|
|||
/* Iterate over initialised rings */
|
||||
#define for_each_ring(ring__, dev_priv__, i__) \
|
||||
for ((i__) = 0; (i__) < I915_NUM_RINGS; (i__)++) \
|
||||
if (((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__)))
|
||||
for_each_if ((((ring__) = &(dev_priv__)->ring[(i__)]), intel_ring_initialized((ring__))))
|
||||
|
||||
enum hdmi_force_audio {
|
||||
HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */
|
||||
|
@ -2445,6 +2435,15 @@ struct drm_i915_cmd_table {
|
|||
#define INTEL_DEVID(p) (INTEL_INFO(p)->device_id)
|
||||
#define INTEL_REVID(p) (__I915__(p)->dev->pdev->revision)
|
||||
|
||||
#define REVID_FOREVER 0xff
|
||||
/*
|
||||
* Return true if revision is in range [since,until] inclusive.
|
||||
*
|
||||
* Use 0 for open-ended since, and REVID_FOREVER for open-ended until.
|
||||
*/
|
||||
#define IS_REVID(p, since, until) \
|
||||
(INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until))
|
||||
|
||||
#define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577)
|
||||
#define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562)
|
||||
#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x)
|
||||
|
@ -2471,7 +2470,8 @@ struct drm_i915_cmd_table {
|
|||
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
|
||||
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake)
|
||||
#define IS_BROXTON(dev) (!INTEL_INFO(dev)->is_skylake && IS_GEN9(dev))
|
||||
#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton)
|
||||
#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake)
|
||||
#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile)
|
||||
#define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \
|
||||
(INTEL_DEVID(dev) & 0xFF00) == 0x0C00)
|
||||
|
@ -2506,16 +2506,21 @@ struct drm_i915_cmd_table {
|
|||
|
||||
#define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary)
|
||||
|
||||
#define SKL_REVID_A0 (0x0)
|
||||
#define SKL_REVID_B0 (0x1)
|
||||
#define SKL_REVID_C0 (0x2)
|
||||
#define SKL_REVID_D0 (0x3)
|
||||
#define SKL_REVID_E0 (0x4)
|
||||
#define SKL_REVID_F0 (0x5)
|
||||
#define SKL_REVID_A0 0x0
|
||||
#define SKL_REVID_B0 0x1
|
||||
#define SKL_REVID_C0 0x2
|
||||
#define SKL_REVID_D0 0x3
|
||||
#define SKL_REVID_E0 0x4
|
||||
#define SKL_REVID_F0 0x5
|
||||
|
||||
#define BXT_REVID_A0 (0x0)
|
||||
#define BXT_REVID_B0 (0x3)
|
||||
#define BXT_REVID_C0 (0x9)
|
||||
#define IS_SKL_REVID(p, since, until) (IS_SKYLAKE(p) && IS_REVID(p, since, until))
|
||||
|
||||
#define BXT_REVID_A0 0x0
|
||||
#define BXT_REVID_A1 0x1
|
||||
#define BXT_REVID_B0 0x3
|
||||
#define BXT_REVID_C0 0x9
|
||||
|
||||
#define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until))
|
||||
|
||||
/*
|
||||
* The genX designation typically refers to the render engine, so render
|
||||
|
@ -2587,10 +2592,10 @@ struct drm_i915_cmd_table {
|
|||
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
|
||||
#define HAS_PSR(dev) (IS_HASWELL(dev) || IS_BROADWELL(dev) || \
|
||||
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev) || \
|
||||
IS_SKYLAKE(dev))
|
||||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \
|
||||
IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
|
||||
IS_SKYLAKE(dev))
|
||||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
|
||||
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
|
||||
|
||||
|
@ -2650,6 +2655,7 @@ struct i915_params {
|
|||
int panel_use_ssc;
|
||||
int vbt_sdvo_panel_type;
|
||||
int enable_rc6;
|
||||
int enable_dc;
|
||||
int enable_fbc;
|
||||
int enable_ppgtt;
|
||||
int enable_execlists;
|
||||
|
@ -2698,7 +2704,6 @@ extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
|
|||
extern unsigned long i915_gfx_val(struct drm_i915_private *dev_priv);
|
||||
extern void i915_update_gfx_val(struct drm_i915_private *dev_priv);
|
||||
int vlv_force_gfx_clock(struct drm_i915_private *dev_priv, bool on);
|
||||
void i915_firmware_load_error_print(const char *fw_path, int err);
|
||||
|
||||
/* intel_hotplug.c */
|
||||
void intel_hpd_irq_handler(struct drm_device *dev, u32 pin_mask, u32 long_mask);
|
||||
|
@ -3008,8 +3013,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write);
|
|||
int __must_check
|
||||
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
|
||||
u32 alignment,
|
||||
struct intel_engine_cs *pipelined,
|
||||
struct drm_i915_gem_request **pipelined_request,
|
||||
const struct i915_ggtt_view *view);
|
||||
void i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
|
||||
const struct i915_ggtt_view *view);
|
||||
|
@ -3364,7 +3367,6 @@ extern void intel_set_rps(struct drm_device *dev, u8 val);
|
|||
extern void intel_set_memory_cxsr(struct drm_i915_private *dev_priv,
|
||||
bool enable);
|
||||
extern void intel_detect_pch(struct drm_device *dev);
|
||||
extern int intel_trans_dp_port_sel(struct drm_crtc *crtc);
|
||||
extern int intel_enable_rc6(const struct drm_device *dev);
|
||||
|
||||
extern bool i915_semaphore_is_enabled(struct drm_device *dev);
|
||||
|
@ -3447,6 +3449,32 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
|||
#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg)
|
||||
#define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg)
|
||||
|
||||
#define __raw_read(x, s) \
|
||||
static inline uint##x##_t __raw_i915_read##x(struct drm_i915_private *dev_priv, \
|
||||
i915_reg_t reg) \
|
||||
{ \
|
||||
return read##s(dev_priv->regs + i915_mmio_reg_offset(reg)); \
|
||||
}
|
||||
|
||||
#define __raw_write(x, s) \
|
||||
static inline void __raw_i915_write##x(struct drm_i915_private *dev_priv, \
|
||||
i915_reg_t reg, uint##x##_t val) \
|
||||
{ \
|
||||
write##s(val, dev_priv->regs + i915_mmio_reg_offset(reg)); \
|
||||
}
|
||||
__raw_read(8, b)
|
||||
__raw_read(16, w)
|
||||
__raw_read(32, l)
|
||||
__raw_read(64, q)
|
||||
|
||||
__raw_write(8, b)
|
||||
__raw_write(16, w)
|
||||
__raw_write(32, l)
|
||||
__raw_write(64, q)
|
||||
|
||||
#undef __raw_read
|
||||
#undef __raw_write
|
||||
|
||||
/* These are untraced mmio-accessors that are only valid to be used inside
|
||||
* criticial sections inside IRQ handlers where forcewake is explicitly
|
||||
* controlled.
|
||||
|
@ -3454,8 +3482,8 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
|||
* Note: Should only be used between intel_uncore_forcewake_irqlock() and
|
||||
* intel_uncore_forcewake_irqunlock().
|
||||
*/
|
||||
#define I915_READ_FW(reg__) readl(dev_priv->regs + (reg__))
|
||||
#define I915_WRITE_FW(reg__, val__) writel(val__, dev_priv->regs + (reg__))
|
||||
#define I915_READ_FW(reg__) __raw_i915_read32(dev_priv, (reg__))
|
||||
#define I915_WRITE_FW(reg__, val__) __raw_i915_write32(dev_priv, (reg__), (val__))
|
||||
#define POSTING_READ_FW(reg__) (void)I915_READ_FW(reg__)
|
||||
|
||||
/* "Broadcast RGB" property */
|
||||
|
@ -3463,7 +3491,7 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val);
|
|||
#define INTEL_BROADCAST_RGB_FULL 1
|
||||
#define INTEL_BROADCAST_RGB_LIMITED 2
|
||||
|
||||
static inline uint32_t i915_vgacntrl_reg(struct drm_device *dev)
|
||||
static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
|
||||
{
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
return VLV_VGACNTRL;
|
||||
|
|
|
@ -2797,6 +2797,8 @@ static void i915_gem_reset_ring_status(struct drm_i915_private *dev_priv,
|
|||
static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
||||
struct intel_engine_cs *ring)
|
||||
{
|
||||
struct intel_ringbuffer *buffer;
|
||||
|
||||
while (!list_empty(&ring->active_list)) {
|
||||
struct drm_i915_gem_object *obj;
|
||||
|
||||
|
@ -2812,18 +2814,23 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
|||
* are the ones that keep the context and ringbuffer backing objects
|
||||
* pinned in place.
|
||||
*/
|
||||
while (!list_empty(&ring->execlist_queue)) {
|
||||
struct drm_i915_gem_request *submit_req;
|
||||
|
||||
submit_req = list_first_entry(&ring->execlist_queue,
|
||||
struct drm_i915_gem_request,
|
||||
execlist_link);
|
||||
list_del(&submit_req->execlist_link);
|
||||
if (i915.enable_execlists) {
|
||||
spin_lock_irq(&ring->execlist_lock);
|
||||
while (!list_empty(&ring->execlist_queue)) {
|
||||
struct drm_i915_gem_request *submit_req;
|
||||
|
||||
if (submit_req->ctx != ring->default_context)
|
||||
intel_lr_context_unpin(submit_req);
|
||||
submit_req = list_first_entry(&ring->execlist_queue,
|
||||
struct drm_i915_gem_request,
|
||||
execlist_link);
|
||||
list_del(&submit_req->execlist_link);
|
||||
|
||||
i915_gem_request_unreference(submit_req);
|
||||
if (submit_req->ctx != ring->default_context)
|
||||
intel_lr_context_unpin(submit_req);
|
||||
|
||||
i915_gem_request_unreference(submit_req);
|
||||
}
|
||||
spin_unlock_irq(&ring->execlist_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2842,6 +2849,18 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
|||
|
||||
i915_gem_request_retire(request);
|
||||
}
|
||||
|
||||
/* Having flushed all requests from all queues, we know that all
|
||||
* ringbuffers must now be empty. However, since we do not reclaim
|
||||
* all space when retiring the request (to prevent HEADs colliding
|
||||
* with rapid ringbuffer wraparound) the amount of available space
|
||||
* upon reset is less than when we start. Do one more pass over
|
||||
* all the ringbuffers to reset last_retired_head.
|
||||
*/
|
||||
list_for_each_entry(buffer, &ring->buffers, link) {
|
||||
buffer->last_retired_head = buffer->tail;
|
||||
intel_ring_update_space(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void i915_gem_reset(struct drm_device *dev)
|
||||
|
@ -3886,7 +3905,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|||
* cacheline, whereas normally such cachelines would get
|
||||
* invalidated.
|
||||
*/
|
||||
if (IS_BROXTON(dev) && INTEL_REVID(dev) < BXT_REVID_B0)
|
||||
if (IS_BXT_REVID(dev, 0, BXT_REVID_A1))
|
||||
return -ENODEV;
|
||||
|
||||
level = I915_CACHE_LLC;
|
||||
|
@ -3929,17 +3948,11 @@ rpm_put:
|
|||
int
|
||||
i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
|
||||
u32 alignment,
|
||||
struct intel_engine_cs *pipelined,
|
||||
struct drm_i915_gem_request **pipelined_request,
|
||||
const struct i915_ggtt_view *view)
|
||||
{
|
||||
u32 old_read_domains, old_write_domain;
|
||||
int ret;
|
||||
|
||||
ret = i915_gem_object_sync(obj, pipelined, pipelined_request);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Mark the pin_display early so that we account for the
|
||||
* display coherency whilst setting up the cache domains.
|
||||
*/
|
||||
|
@ -4541,10 +4554,8 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
|
|||
{
|
||||
struct i915_vma *vma;
|
||||
list_for_each_entry(vma, &obj->vma_list, vma_link) {
|
||||
if (i915_is_ggtt(vma->vm) &&
|
||||
vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
|
||||
continue;
|
||||
if (vma->vm == vm)
|
||||
if (vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL &&
|
||||
vma->vm == vm)
|
||||
return vma;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -4633,7 +4644,6 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
|
|||
struct intel_engine_cs *ring = req->ring;
|
||||
struct drm_device *dev = ring->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 reg_base = GEN7_L3LOG_BASE + (slice * 0x200);
|
||||
u32 *remap_info = dev_priv->l3_parity.remap_info[slice];
|
||||
int i, ret;
|
||||
|
||||
|
@ -4649,10 +4659,10 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
|
|||
* here because no other code should access these registers other than
|
||||
* at initialization time.
|
||||
*/
|
||||
for (i = 0; i < GEN7_L3LOG_SIZE; i += 4) {
|
||||
for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) {
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, reg_base + i);
|
||||
intel_ring_emit(ring, remap_info[i/4]);
|
||||
intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
|
||||
intel_ring_emit(ring, remap_info[i]);
|
||||
}
|
||||
|
||||
intel_ring_advance(ring);
|
||||
|
@ -4820,18 +4830,9 @@ i915_gem_init_hw(struct drm_device *dev)
|
|||
if (HAS_GUC_UCODE(dev)) {
|
||||
ret = intel_guc_ucode_load(dev);
|
||||
if (ret) {
|
||||
/*
|
||||
* If we got an error and GuC submission is enabled, map
|
||||
* the error to -EIO so the GPU will be declared wedged.
|
||||
* OTOH, if we didn't intend to use the GuC anyway, just
|
||||
* discard the error and carry on.
|
||||
*/
|
||||
DRM_ERROR("Failed to initialize GuC, error %d%s\n", ret,
|
||||
i915.enable_guc_submission ? "" :
|
||||
" (ignored)");
|
||||
ret = i915.enable_guc_submission ? -EIO : 0;
|
||||
if (ret)
|
||||
goto out;
|
||||
DRM_ERROR("Failed to initialize GuC, error %d\n", ret);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -554,7 +554,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
|
|||
if (signaller == ring)
|
||||
continue;
|
||||
|
||||
intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
|
||||
intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
|
||||
intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
|
|||
if (signaller == ring)
|
||||
continue;
|
||||
|
||||
intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base));
|
||||
intel_ring_emit_reg(ring, RING_PSMI_CTL(signaller->mmio_base));
|
||||
intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE));
|
||||
}
|
||||
}
|
||||
|
@ -923,6 +923,14 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
|
|||
case I915_CONTEXT_PARAM_NO_ZEROMAP:
|
||||
args->value = ctx->flags & CONTEXT_NO_ZEROMAP;
|
||||
break;
|
||||
case I915_CONTEXT_PARAM_GTT_SIZE:
|
||||
if (ctx->ppgtt)
|
||||
args->value = ctx->ppgtt->base.total;
|
||||
else if (to_i915(dev)->mm.aliasing_ppgtt)
|
||||
args->value = to_i915(dev)->mm.aliasing_ppgtt->base.total;
|
||||
else
|
||||
args->value = to_i915(dev)->gtt.base.total;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
|
|
@ -1114,7 +1114,7 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
|
|||
|
||||
for (i = 0; i < 4; i++) {
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i));
|
||||
intel_ring_emit_reg(ring, GEN7_SO_WRITE_OFFSET(i));
|
||||
intel_ring_emit(ring, 0);
|
||||
}
|
||||
|
||||
|
@ -1241,7 +1241,7 @@ i915_gem_ringbuffer_submission(struct i915_execbuffer_params *params,
|
|||
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, INSTPM);
|
||||
intel_ring_emit_reg(ring, INSTPM);
|
||||
intel_ring_emit(ring, instp_mask << 16 | instp_mode);
|
||||
intel_ring_advance(ring);
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
|
|||
struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int fence_reg_lo, fence_reg_hi;
|
||||
i915_reg_t fence_reg_lo, fence_reg_hi;
|
||||
int fence_pitch_shift;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/stop_machine.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/i915_drm.h>
|
||||
#include "i915_drv.h"
|
||||
|
@ -104,9 +105,11 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
|||
{
|
||||
bool has_aliasing_ppgtt;
|
||||
bool has_full_ppgtt;
|
||||
bool has_full_48bit_ppgtt;
|
||||
|
||||
has_aliasing_ppgtt = INTEL_INFO(dev)->gen >= 6;
|
||||
has_full_ppgtt = INTEL_INFO(dev)->gen >= 7;
|
||||
has_full_48bit_ppgtt = IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9;
|
||||
|
||||
if (intel_vgpu_active(dev))
|
||||
has_full_ppgtt = false; /* emulation is too hard */
|
||||
|
@ -125,6 +128,9 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
|||
if (enable_ppgtt == 2 && has_full_ppgtt)
|
||||
return 2;
|
||||
|
||||
if (enable_ppgtt == 3 && has_full_48bit_ppgtt)
|
||||
return 3;
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU
|
||||
/* Disable ppgtt on SNB if VT-d is on. */
|
||||
if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) {
|
||||
|
@ -141,7 +147,7 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
|||
}
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 8 && i915.enable_execlists)
|
||||
return 2;
|
||||
return has_full_48bit_ppgtt ? 3 : 2;
|
||||
else
|
||||
return has_aliasing_ppgtt ? 1 : 0;
|
||||
}
|
||||
|
@ -661,10 +667,10 @@ static int gen8_write_pdp(struct drm_i915_gem_request *req,
|
|||
return ret;
|
||||
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, GEN8_RING_PDP_UDW(ring, entry));
|
||||
intel_ring_emit_reg(ring, GEN8_RING_PDP_UDW(ring, entry));
|
||||
intel_ring_emit(ring, upper_32_bits(addr));
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
|
||||
intel_ring_emit(ring, GEN8_RING_PDP_LDW(ring, entry));
|
||||
intel_ring_emit_reg(ring, GEN8_RING_PDP_LDW(ring, entry));
|
||||
intel_ring_emit(ring, lower_32_bits(addr));
|
||||
intel_ring_advance(ring);
|
||||
|
||||
|
@ -904,14 +910,13 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
|
|||
enum vgt_g2v_type msg;
|
||||
struct drm_device *dev = ppgtt->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned int offset = vgtif_reg(pdp0_lo);
|
||||
int i;
|
||||
|
||||
if (USES_FULL_48BIT_PPGTT(dev)) {
|
||||
u64 daddr = px_dma(&ppgtt->pml4);
|
||||
|
||||
I915_WRITE(offset, lower_32_bits(daddr));
|
||||
I915_WRITE(offset + 4, upper_32_bits(daddr));
|
||||
I915_WRITE(vgtif_reg(pdp[0].lo), lower_32_bits(daddr));
|
||||
I915_WRITE(vgtif_reg(pdp[0].hi), upper_32_bits(daddr));
|
||||
|
||||
msg = (create ? VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE :
|
||||
VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY);
|
||||
|
@ -919,10 +924,8 @@ static int gen8_ppgtt_notify_vgt(struct i915_hw_ppgtt *ppgtt, bool create)
|
|||
for (i = 0; i < GEN8_LEGACY_PDPES; i++) {
|
||||
u64 daddr = i915_page_dir_dma_addr(ppgtt, i);
|
||||
|
||||
I915_WRITE(offset, lower_32_bits(daddr));
|
||||
I915_WRITE(offset + 4, upper_32_bits(daddr));
|
||||
|
||||
offset += 8;
|
||||
I915_WRITE(vgtif_reg(pdp[i].lo), lower_32_bits(daddr));
|
||||
I915_WRITE(vgtif_reg(pdp[i].hi), upper_32_bits(daddr));
|
||||
}
|
||||
|
||||
msg = (create ? VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE :
|
||||
|
@ -1662,9 +1665,9 @@ static int hsw_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
|||
return ret;
|
||||
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
|
||||
intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
|
||||
intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
|
||||
intel_ring_emit(ring, PP_DIR_DCLV_2G);
|
||||
intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
|
||||
intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
|
||||
intel_ring_emit(ring, get_pd_offset(ppgtt));
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_advance(ring);
|
||||
|
@ -1699,9 +1702,9 @@ static int gen7_mm_switch(struct i915_hw_ppgtt *ppgtt,
|
|||
return ret;
|
||||
|
||||
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(2));
|
||||
intel_ring_emit(ring, RING_PP_DIR_DCLV(ring));
|
||||
intel_ring_emit_reg(ring, RING_PP_DIR_DCLV(ring));
|
||||
intel_ring_emit(ring, PP_DIR_DCLV_2G);
|
||||
intel_ring_emit(ring, RING_PP_DIR_BASE(ring));
|
||||
intel_ring_emit_reg(ring, RING_PP_DIR_BASE(ring));
|
||||
intel_ring_emit(ring, get_pd_offset(ppgtt));
|
||||
intel_ring_emit(ring, MI_NOOP);
|
||||
intel_ring_advance(ring);
|
||||
|
@ -2528,6 +2531,26 @@ static int ggtt_bind_vma(struct i915_vma *vma,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct ggtt_bind_vma__cb {
|
||||
struct i915_vma *vma;
|
||||
enum i915_cache_level cache_level;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
static int ggtt_bind_vma__cb(void *_arg)
|
||||
{
|
||||
struct ggtt_bind_vma__cb *arg = _arg;
|
||||
return ggtt_bind_vma(arg->vma, arg->cache_level, arg->flags);
|
||||
}
|
||||
|
||||
static int ggtt_bind_vma__BKL(struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 flags)
|
||||
{
|
||||
struct ggtt_bind_vma__cb arg = { vma, cache_level, flags };
|
||||
return stop_machine(ggtt_bind_vma__cb, &arg, NULL);
|
||||
}
|
||||
|
||||
static int aliasing_gtt_bind_vma(struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 flags)
|
||||
|
@ -2996,6 +3019,9 @@ static int gen8_gmch_probe(struct drm_device *dev,
|
|||
dev_priv->gtt.base.bind_vma = ggtt_bind_vma;
|
||||
dev_priv->gtt.base.unbind_vma = ggtt_unbind_vma;
|
||||
|
||||
if (IS_CHERRYVIEW(dev))
|
||||
dev_priv->gtt.base.bind_vma = ggtt_bind_vma__BKL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3303,7 +3329,7 @@ static struct sg_table *
|
|||
intel_rotate_fb_obj_pages(struct i915_ggtt_view *ggtt_view,
|
||||
struct drm_i915_gem_object *obj)
|
||||
{
|
||||
struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
|
||||
struct intel_rotation_info *rot_info = &ggtt_view->params.rotation_info;
|
||||
unsigned int size_pages = rot_info->size >> PAGE_SHIFT;
|
||||
unsigned int size_pages_uv;
|
||||
struct sg_page_iter sg_iter;
|
||||
|
@ -3535,7 +3561,7 @@ i915_ggtt_view_size(struct drm_i915_gem_object *obj,
|
|||
if (view->type == I915_GGTT_VIEW_NORMAL) {
|
||||
return obj->base.size;
|
||||
} else if (view->type == I915_GGTT_VIEW_ROTATED) {
|
||||
return view->rotation_info.size;
|
||||
return view->params.rotation_info.size;
|
||||
} else if (view->type == I915_GGTT_VIEW_PARTIAL) {
|
||||
return view->params.partial.size << PAGE_SHIFT;
|
||||
} else {
|
||||
|
|
|
@ -156,13 +156,10 @@ struct i915_ggtt_view {
|
|||
u64 offset;
|
||||
unsigned int size;
|
||||
} partial;
|
||||
struct intel_rotation_info rotation_info;
|
||||
} params;
|
||||
|
||||
struct sg_table *pages;
|
||||
|
||||
union {
|
||||
struct intel_rotation_info rotation_info;
|
||||
};
|
||||
};
|
||||
|
||||
extern const struct i915_ggtt_view i915_ggtt_view_normal;
|
||||
|
@ -556,7 +553,7 @@ i915_ggtt_view_equal(const struct i915_ggtt_view *a,
|
|||
|
||||
if (a->type != b->type)
|
||||
return false;
|
||||
if (a->type == I915_GGTT_VIEW_PARTIAL)
|
||||
if (a->type != I915_GGTT_VIEW_NORMAL)
|
||||
return !memcmp(&a->params, &b->params, sizeof(a->params));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -433,7 +433,8 @@ int i915_gem_init_stolen(struct drm_device *dev)
|
|||
&reserved_size);
|
||||
break;
|
||||
default:
|
||||
if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv))
|
||||
if (IS_BROADWELL(dev_priv) ||
|
||||
IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev))
|
||||
bdw_get_stolen_reserved(dev_priv, &reserved_base,
|
||||
&reserved_size);
|
||||
else
|
||||
|
|
|
@ -176,6 +176,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (obj->pin_display || obj->framebuffer_references) {
|
||||
ret = -EBUSY;
|
||||
|
@ -269,6 +271,8 @@ err:
|
|||
drm_gem_object_unreference(&obj->base);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -366,6 +366,17 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
|
|||
err_printf(m, "Suspend count: %u\n", error->suspend_count);
|
||||
err_printf(m, "PCI ID: 0x%04x\n", dev->pdev->device);
|
||||
err_printf(m, "IOMMU enabled?: %d\n", error->iommu);
|
||||
|
||||
if (HAS_CSR(dev)) {
|
||||
struct intel_csr *csr = &dev_priv->csr;
|
||||
|
||||
err_printf(m, "DMC loaded: %s\n",
|
||||
yesno(csr->dmc_payload != NULL));
|
||||
err_printf(m, "DMC fw version: %d.%d\n",
|
||||
CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version));
|
||||
}
|
||||
|
||||
err_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
err_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
if (INTEL_INFO(dev)->gen >= 8) {
|
||||
|
@ -862,7 +873,7 @@ static void i915_record_ring_state(struct drm_device *dev,
|
|||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
|
||||
ering->rc_psmi = I915_READ(RING_PSMI_CTL(ring->mmio_base));
|
||||
ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
|
||||
if (INTEL_INFO(dev)->gen >= 8)
|
||||
gen8_record_semaphore_state(dev_priv, error, ring, ering);
|
||||
|
@ -899,7 +910,7 @@ static void i915_record_ring_state(struct drm_device *dev,
|
|||
ering->ctl = I915_READ_CTL(ring);
|
||||
|
||||
if (I915_NEED_GFX_HWS(dev)) {
|
||||
int mmio;
|
||||
i915_reg_t mmio;
|
||||
|
||||
if (IS_GEN7(dev)) {
|
||||
switch (ring->id) {
|
||||
|
@ -1071,6 +1082,25 @@ static void i915_gem_record_rings(struct drm_device *dev,
|
|||
list_for_each_entry(request, &ring->request_list, list) {
|
||||
struct drm_i915_error_request *erq;
|
||||
|
||||
if (count >= error->ring[i].num_requests) {
|
||||
/*
|
||||
* If the ring request list was changed in
|
||||
* between the point where the error request
|
||||
* list was created and dimensioned and this
|
||||
* point then just exit early to avoid crashes.
|
||||
*
|
||||
* We don't need to communicate that the
|
||||
* request list changed state during error
|
||||
* state capture and that the error state is
|
||||
* slightly incorrect as a consequence since we
|
||||
* are typically only interested in the request
|
||||
* list state at the point of error state
|
||||
* capture, not in any changes happening during
|
||||
* the capture.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
erq = &error->ring[i].requests[count++];
|
||||
erq->seqno = request->seqno;
|
||||
erq->jiffies = request->emitted_jiffies;
|
||||
|
@ -1181,7 +1211,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
|
|||
if (IS_VALLEYVIEW(dev)) {
|
||||
error->gtier[0] = I915_READ(GTIER);
|
||||
error->ier = I915_READ(VLV_IER);
|
||||
error->forcewake = I915_READ(FORCEWAKE_VLV);
|
||||
error->forcewake = I915_READ_FW(FORCEWAKE_VLV);
|
||||
}
|
||||
|
||||
if (IS_GEN7(dev))
|
||||
|
@ -1193,14 +1223,14 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv,
|
|||
}
|
||||
|
||||
if (IS_GEN6(dev)) {
|
||||
error->forcewake = I915_READ(FORCEWAKE);
|
||||
error->forcewake = I915_READ_FW(FORCEWAKE);
|
||||
error->gab_ctl = I915_READ(GAB_CTL);
|
||||
error->gfx_mode = I915_READ(GFX_MODE);
|
||||
}
|
||||
|
||||
/* 2: Registers which belong to multiple generations */
|
||||
if (INTEL_INFO(dev)->gen >= 7)
|
||||
error->forcewake = I915_READ(FORCEWAKE_MT);
|
||||
error->forcewake = I915_READ_FW(FORCEWAKE_MT);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
error->derrmr = I915_READ(DERRMR);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
/* Definitions of GuC H/W registers, bits, etc */
|
||||
|
||||
#define GUC_STATUS 0xc000
|
||||
#define GUC_STATUS _MMIO(0xc000)
|
||||
#define GS_BOOTROM_SHIFT 1
|
||||
#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT)
|
||||
#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT)
|
||||
|
@ -39,40 +39,41 @@
|
|||
#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT)
|
||||
#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)
|
||||
|
||||
#define SOFT_SCRATCH(n) (0xc180 + ((n) * 4))
|
||||
#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4)
|
||||
|
||||
#define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
|
||||
#define DMA_ADDR_0_LOW 0xc300
|
||||
#define DMA_ADDR_0_HIGH 0xc304
|
||||
#define DMA_ADDR_1_LOW 0xc308
|
||||
#define DMA_ADDR_1_HIGH 0xc30c
|
||||
#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4)
|
||||
#define UOS_RSA_SCRATCH_MAX_COUNT 64
|
||||
#define DMA_ADDR_0_LOW _MMIO(0xc300)
|
||||
#define DMA_ADDR_0_HIGH _MMIO(0xc304)
|
||||
#define DMA_ADDR_1_LOW _MMIO(0xc308)
|
||||
#define DMA_ADDR_1_HIGH _MMIO(0xc30c)
|
||||
#define DMA_ADDRESS_SPACE_WOPCM (7 << 16)
|
||||
#define DMA_ADDRESS_SPACE_GTT (8 << 16)
|
||||
#define DMA_COPY_SIZE 0xc310
|
||||
#define DMA_CTRL 0xc314
|
||||
#define DMA_COPY_SIZE _MMIO(0xc310)
|
||||
#define DMA_CTRL _MMIO(0xc314)
|
||||
#define UOS_MOVE (1<<4)
|
||||
#define START_DMA (1<<0)
|
||||
#define DMA_GUC_WOPCM_OFFSET 0xc340
|
||||
#define DMA_GUC_WOPCM_OFFSET _MMIO(0xc340)
|
||||
#define GUC_WOPCM_OFFSET_VALUE 0x80000 /* 512KB */
|
||||
#define GUC_MAX_IDLE_COUNT 0xC3E4
|
||||
#define GUC_MAX_IDLE_COUNT _MMIO(0xC3E4)
|
||||
|
||||
#define GUC_WOPCM_SIZE 0xc050
|
||||
#define GUC_WOPCM_SIZE _MMIO(0xc050)
|
||||
#define GUC_WOPCM_SIZE_VALUE (0x80 << 12) /* 512KB */
|
||||
|
||||
/* GuC addresses below GUC_WOPCM_TOP don't map through the GTT */
|
||||
#define GUC_WOPCM_TOP (GUC_WOPCM_SIZE_VALUE)
|
||||
|
||||
#define GEN8_GT_PM_CONFIG 0x138140
|
||||
#define GEN9LP_GT_PM_CONFIG 0x138140
|
||||
#define GEN9_GT_PM_CONFIG 0x13816c
|
||||
#define GEN8_GT_PM_CONFIG _MMIO(0x138140)
|
||||
#define GEN9LP_GT_PM_CONFIG _MMIO(0x138140)
|
||||
#define GEN9_GT_PM_CONFIG _MMIO(0x13816c)
|
||||
#define GT_DOORBELL_ENABLE (1<<0)
|
||||
|
||||
#define GEN8_GTCR 0x4274
|
||||
#define GEN8_GTCR _MMIO(0x4274)
|
||||
#define GEN8_GTCR_INVALIDATE (1<<0)
|
||||
|
||||
#define GUC_ARAT_C6DIS 0xA178
|
||||
#define GUC_ARAT_C6DIS _MMIO(0xA178)
|
||||
|
||||
#define GUC_SHIM_CONTROL 0xc064
|
||||
#define GUC_SHIM_CONTROL _MMIO(0xc064)
|
||||
#define GUC_DISABLE_SRAM_INIT_TO_ZEROES (1<<0)
|
||||
#define GUC_ENABLE_READ_CACHE_LOGIC (1<<1)
|
||||
#define GUC_ENABLE_MIA_CACHING (1<<2)
|
||||
|
@ -89,21 +90,21 @@
|
|||
GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA | \
|
||||
GUC_ENABLE_MIA_CLOCK_GATING)
|
||||
|
||||
#define HOST2GUC_INTERRUPT 0xc4c8
|
||||
#define HOST2GUC_INTERRUPT _MMIO(0xc4c8)
|
||||
#define HOST2GUC_TRIGGER (1<<0)
|
||||
|
||||
#define DRBMISC1 0x1984
|
||||
#define DOORBELL_ENABLE (1<<0)
|
||||
|
||||
#define GEN8_DRBREGL(x) (0x1000 + (x) * 8)
|
||||
#define GEN8_DRBREGL(x) _MMIO(0x1000 + (x) * 8)
|
||||
#define GEN8_DRB_VALID (1<<0)
|
||||
#define GEN8_DRBREGU(x) (GEN8_DRBREGL(x) + 4)
|
||||
#define GEN8_DRBREGU(x) _MMIO(0x1000 + (x) * 8 + 4)
|
||||
|
||||
#define DE_GUCRMR 0x44054
|
||||
#define DE_GUCRMR _MMIO(0x44054)
|
||||
|
||||
#define GUC_BCS_RCS_IER 0xC550
|
||||
#define GUC_VCS2_VCS1_IER 0xC554
|
||||
#define GUC_WD_VECS_IER 0xC558
|
||||
#define GUC_PM_P24C_IER 0xC55C
|
||||
#define GUC_BCS_RCS_IER _MMIO(0xC550)
|
||||
#define GUC_VCS2_VCS1_IER _MMIO(0xC554)
|
||||
#define GUC_WD_VECS_IER _MMIO(0xC558)
|
||||
#define GUC_PM_P24C_IER _MMIO(0xC55C)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "intel_guc.h"
|
||||
|
||||
/**
|
||||
* DOC: GuC Client
|
||||
* DOC: GuC-based command submission
|
||||
*
|
||||
* i915_guc_client:
|
||||
* We use the term client to avoid confusion with contexts. A i915_guc_client is
|
||||
|
@ -161,9 +161,9 @@ static int host2guc_sample_forcewake(struct intel_guc *guc,
|
|||
data[0] = HOST2GUC_ACTION_SAMPLE_FORCEWAKE;
|
||||
/* WaRsDisableCoarsePowerGating:skl,bxt */
|
||||
if (!intel_enable_rc6(dev_priv->dev) ||
|
||||
(IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
|
||||
(IS_SKL_GT3(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)) ||
|
||||
(IS_SKL_GT4(dev) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
|
||||
IS_BXT_REVID(dev, 0, BXT_REVID_A1) ||
|
||||
(IS_SKL_GT3(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)) ||
|
||||
(IS_SKL_GT4(dev) && IS_SKL_REVID(dev, 0, SKL_REVID_E0)))
|
||||
data[1] = 0;
|
||||
else
|
||||
/* bit 0 and 1 are for Render and Media domain separately */
|
||||
|
@ -258,7 +258,7 @@ static void guc_disable_doorbell(struct intel_guc *guc,
|
|||
struct drm_i915_private *dev_priv = guc_to_i915(guc);
|
||||
struct guc_doorbell_info *doorbell;
|
||||
void *base;
|
||||
int drbreg = GEN8_DRBREGL(client->doorbell_id);
|
||||
i915_reg_t drbreg = GEN8_DRBREGL(client->doorbell_id);
|
||||
int value;
|
||||
|
||||
base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
|
||||
|
@ -588,8 +588,7 @@ static void lr_context_update(struct drm_i915_gem_request *rq)
|
|||
/**
|
||||
* i915_guc_submit() - Submit commands through GuC
|
||||
* @client: the guc client where commands will go through
|
||||
* @ctx: LRC where commands come from
|
||||
* @ring: HW engine that will excute the commands
|
||||
* @rq: request associated with the commands
|
||||
*
|
||||
* Return: 0 if succeed
|
||||
*/
|
||||
|
@ -731,7 +730,8 @@ static void guc_client_free(struct drm_device *dev,
|
|||
* The kernel client to replace ExecList submission is created with
|
||||
* NORMAL priority. Priority of a client for scheduler can be HIGH,
|
||||
* while a preemption context can use CRITICAL.
|
||||
* @ctx the context to own the client (we use the default render context)
|
||||
* @ctx: the context that owns the client (we use the default render
|
||||
* context)
|
||||
*
|
||||
* Return: An i915_guc_client object if success.
|
||||
*/
|
||||
|
|
|
@ -139,7 +139,8 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = {
|
|||
/*
|
||||
* We should clear IMR at preinstall/uninstall, and just check at postinstall.
|
||||
*/
|
||||
static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
|
||||
static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv,
|
||||
i915_reg_t reg)
|
||||
{
|
||||
u32 val = I915_READ(reg);
|
||||
|
||||
|
@ -147,7 +148,7 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, u32 reg)
|
|||
return;
|
||||
|
||||
WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n",
|
||||
reg, val);
|
||||
i915_mmio_reg_offset(reg), val);
|
||||
I915_WRITE(reg, 0xffffffff);
|
||||
POSTING_READ(reg);
|
||||
I915_WRITE(reg, 0xffffffff);
|
||||
|
@ -283,17 +284,17 @@ void gen5_disable_gt_irq(struct drm_i915_private *dev_priv, uint32_t mask)
|
|||
ilk_update_gt_irq(dev_priv, mask, 0);
|
||||
}
|
||||
|
||||
static u32 gen6_pm_iir(struct drm_i915_private *dev_priv)
|
||||
static i915_reg_t gen6_pm_iir(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IIR(2) : GEN6_PMIIR;
|
||||
}
|
||||
|
||||
static u32 gen6_pm_imr(struct drm_i915_private *dev_priv)
|
||||
static i915_reg_t gen6_pm_imr(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IMR(2) : GEN6_PMIMR;
|
||||
}
|
||||
|
||||
static u32 gen6_pm_ier(struct drm_i915_private *dev_priv)
|
||||
static i915_reg_t gen6_pm_ier(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
return INTEL_INFO(dev_priv)->gen >= 8 ? GEN8_GT_IER(2) : GEN6_PMIER;
|
||||
}
|
||||
|
@ -350,7 +351,7 @@ void gen6_disable_pm_irq(struct drm_i915_private *dev_priv, uint32_t mask)
|
|||
void gen6_reset_rps_interrupts(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
uint32_t reg = gen6_pm_iir(dev_priv);
|
||||
i915_reg_t reg = gen6_pm_iir(dev_priv);
|
||||
|
||||
spin_lock_irq(&dev_priv->irq_lock);
|
||||
I915_WRITE(reg, dev_priv->pm_rps_events);
|
||||
|
@ -477,7 +478,7 @@ static void
|
|||
__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
u32 enable_mask, u32 status_mask)
|
||||
{
|
||||
u32 reg = PIPESTAT(pipe);
|
||||
i915_reg_t reg = PIPESTAT(pipe);
|
||||
u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
@ -504,7 +505,7 @@ static void
|
|||
__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe,
|
||||
u32 enable_mask, u32 status_mask)
|
||||
{
|
||||
u32 reg = PIPESTAT(pipe);
|
||||
i915_reg_t reg = PIPESTAT(pipe);
|
||||
u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK;
|
||||
|
||||
assert_spin_locked(&dev_priv->irq_lock);
|
||||
|
@ -665,8 +666,7 @@ static u32 i8xx_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
|
|||
static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned long high_frame;
|
||||
unsigned long low_frame;
|
||||
i915_reg_t high_frame, low_frame;
|
||||
u32 high1, high2, low, pixel, vbl_start, hsync_start, htotal;
|
||||
struct intel_crtc *intel_crtc =
|
||||
to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
||||
|
@ -717,9 +717,7 @@ static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
|
|||
return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
|
||||
}
|
||||
|
||||
/* raw reads, only for fast reads of display block, no need for forcewake etc. */
|
||||
#define __raw_i915_read32(dev_priv__, reg__) readl((dev_priv__)->regs + (reg__))
|
||||
|
||||
/* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */
|
||||
static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->base.dev;
|
||||
|
@ -733,9 +731,9 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
|
|||
vtotal /= 2;
|
||||
|
||||
if (IS_GEN2(dev))
|
||||
position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
|
||||
position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
|
||||
else
|
||||
position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
|
||||
position = I915_READ_FW(PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
|
||||
|
||||
/*
|
||||
* On HSW, the DSL reg (0x70000) appears to return 0 if we
|
||||
|
@ -827,7 +825,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
|
|||
* We can split this into vertical and horizontal
|
||||
* scanout position.
|
||||
*/
|
||||
position = (__raw_i915_read32(dev_priv, PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
|
||||
position = (I915_READ_FW(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT;
|
||||
|
||||
/* convert to pixel counts */
|
||||
vbl_start *= htotal;
|
||||
|
@ -1188,7 +1186,7 @@ static void ivybridge_parity_work(struct work_struct *work)
|
|||
POSTING_READ(GEN7_MISCCPCTL);
|
||||
|
||||
while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
|
||||
u32 reg;
|
||||
i915_reg_t reg;
|
||||
|
||||
slice--;
|
||||
if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev)))
|
||||
|
@ -1196,7 +1194,7 @@ static void ivybridge_parity_work(struct work_struct *work)
|
|||
|
||||
dev_priv->l3_parity.which_slice &= ~(1<<slice);
|
||||
|
||||
reg = GEN7_L3CDERRST1 + (slice * 0x200);
|
||||
reg = GEN7_L3CDERRST1(slice);
|
||||
|
||||
error_status = I915_READ(reg);
|
||||
row = GEN7_PARITY_ERROR_ROW(error_status);
|
||||
|
@ -1290,70 +1288,69 @@ static void snb_gt_irq_handler(struct drm_device *dev,
|
|||
ivybridge_parity_error_irq_handler(dev, gt_iir);
|
||||
}
|
||||
|
||||
static __always_inline void
|
||||
gen8_cs_irq_handler(struct intel_engine_cs *ring, u32 iir, int test_shift)
|
||||
{
|
||||
if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
|
||||
notify_ring(ring);
|
||||
if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
|
||||
intel_lrc_irq_handler(ring);
|
||||
}
|
||||
|
||||
static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
|
||||
u32 master_ctl)
|
||||
{
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
|
||||
if (master_ctl & (GEN8_GT_RCS_IRQ | GEN8_GT_BCS_IRQ)) {
|
||||
u32 tmp = I915_READ_FW(GEN8_GT_IIR(0));
|
||||
if (tmp) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(0), tmp);
|
||||
u32 iir = I915_READ_FW(GEN8_GT_IIR(0));
|
||||
if (iir) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(0), iir);
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
|
||||
intel_lrc_irq_handler(&dev_priv->ring[RCS]);
|
||||
if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_RCS_IRQ_SHIFT))
|
||||
notify_ring(&dev_priv->ring[RCS]);
|
||||
gen8_cs_irq_handler(&dev_priv->ring[RCS],
|
||||
iir, GEN8_RCS_IRQ_SHIFT);
|
||||
|
||||
if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
|
||||
intel_lrc_irq_handler(&dev_priv->ring[BCS]);
|
||||
if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_BCS_IRQ_SHIFT))
|
||||
notify_ring(&dev_priv->ring[BCS]);
|
||||
gen8_cs_irq_handler(&dev_priv->ring[BCS],
|
||||
iir, GEN8_BCS_IRQ_SHIFT);
|
||||
} else
|
||||
DRM_ERROR("The master control interrupt lied (GT0)!\n");
|
||||
}
|
||||
|
||||
if (master_ctl & (GEN8_GT_VCS1_IRQ | GEN8_GT_VCS2_IRQ)) {
|
||||
u32 tmp = I915_READ_FW(GEN8_GT_IIR(1));
|
||||
if (tmp) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(1), tmp);
|
||||
u32 iir = I915_READ_FW(GEN8_GT_IIR(1));
|
||||
if (iir) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(1), iir);
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
|
||||
intel_lrc_irq_handler(&dev_priv->ring[VCS]);
|
||||
if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS1_IRQ_SHIFT))
|
||||
notify_ring(&dev_priv->ring[VCS]);
|
||||
gen8_cs_irq_handler(&dev_priv->ring[VCS],
|
||||
iir, GEN8_VCS1_IRQ_SHIFT);
|
||||
|
||||
if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
|
||||
intel_lrc_irq_handler(&dev_priv->ring[VCS2]);
|
||||
if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT))
|
||||
notify_ring(&dev_priv->ring[VCS2]);
|
||||
gen8_cs_irq_handler(&dev_priv->ring[VCS2],
|
||||
iir, GEN8_VCS2_IRQ_SHIFT);
|
||||
} else
|
||||
DRM_ERROR("The master control interrupt lied (GT1)!\n");
|
||||
}
|
||||
|
||||
if (master_ctl & GEN8_GT_VECS_IRQ) {
|
||||
u32 tmp = I915_READ_FW(GEN8_GT_IIR(3));
|
||||
if (tmp) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(3), tmp);
|
||||
u32 iir = I915_READ_FW(GEN8_GT_IIR(3));
|
||||
if (iir) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(3), iir);
|
||||
ret = IRQ_HANDLED;
|
||||
|
||||
if (tmp & (GT_CONTEXT_SWITCH_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
|
||||
intel_lrc_irq_handler(&dev_priv->ring[VECS]);
|
||||
if (tmp & (GT_RENDER_USER_INTERRUPT << GEN8_VECS_IRQ_SHIFT))
|
||||
notify_ring(&dev_priv->ring[VECS]);
|
||||
gen8_cs_irq_handler(&dev_priv->ring[VECS],
|
||||
iir, GEN8_VECS_IRQ_SHIFT);
|
||||
} else
|
||||
DRM_ERROR("The master control interrupt lied (GT3)!\n");
|
||||
}
|
||||
|
||||
if (master_ctl & GEN8_GT_PM_IRQ) {
|
||||
u32 tmp = I915_READ_FW(GEN8_GT_IIR(2));
|
||||
if (tmp & dev_priv->pm_rps_events) {
|
||||
u32 iir = I915_READ_FW(GEN8_GT_IIR(2));
|
||||
if (iir & dev_priv->pm_rps_events) {
|
||||
I915_WRITE_FW(GEN8_GT_IIR(2),
|
||||
tmp & dev_priv->pm_rps_events);
|
||||
iir & dev_priv->pm_rps_events);
|
||||
ret = IRQ_HANDLED;
|
||||
gen6_rps_irq_handler(dev_priv, tmp);
|
||||
gen6_rps_irq_handler(dev_priv, iir);
|
||||
} else
|
||||
DRM_ERROR("The master control interrupt lied (PM)!\n");
|
||||
}
|
||||
|
@ -1625,7 +1622,7 @@ static void valleyview_pipestat_irq_handler(struct drm_device *dev, u32 iir)
|
|||
|
||||
spin_lock(&dev_priv->irq_lock);
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
int reg;
|
||||
i915_reg_t reg;
|
||||
u32 mask, iir_bit = 0;
|
||||
|
||||
/*
|
||||
|
@ -2354,9 +2351,13 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
|
|||
spt_irq_handler(dev, pch_iir);
|
||||
else
|
||||
cpt_irq_handler(dev, pch_iir);
|
||||
} else
|
||||
DRM_ERROR("The master control interrupt lied (SDE)!\n");
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Like on previous PCH there seems to be something
|
||||
* fishy going on with forwarding PCH interrupts.
|
||||
*/
|
||||
DRM_DEBUG_DRIVER("The master control interrupt lied (SDE)!\n");
|
||||
}
|
||||
}
|
||||
|
||||
I915_WRITE_FW(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL);
|
||||
|
@ -3869,7 +3870,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
|||
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
int reg = PIPESTAT(pipe);
|
||||
i915_reg_t reg = PIPESTAT(pipe);
|
||||
pipe_stats[pipe] = I915_READ(reg);
|
||||
|
||||
/*
|
||||
|
@ -4050,7 +4051,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
int reg = PIPESTAT(pipe);
|
||||
i915_reg_t reg = PIPESTAT(pipe);
|
||||
pipe_stats[pipe] = I915_READ(reg);
|
||||
|
||||
/* Clear the PIPE*STAT regs before the IIR */
|
||||
|
@ -4272,7 +4273,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||
DRM_DEBUG("Command parser error, iir 0x%08x\n", iir);
|
||||
|
||||
for_each_pipe(dev_priv, pipe) {
|
||||
int reg = PIPESTAT(pipe);
|
||||
i915_reg_t reg = PIPESTAT(pipe);
|
||||
pipe_stats[pipe] = I915_READ(reg);
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,6 +32,7 @@ struct i915_params i915 __read_mostly = {
|
|||
.panel_use_ssc = -1,
|
||||
.vbt_sdvo_panel_type = -1,
|
||||
.enable_rc6 = -1,
|
||||
.enable_dc = -1,
|
||||
.enable_fbc = -1,
|
||||
.enable_execlists = -1,
|
||||
.enable_hangcheck = true,
|
||||
|
@ -80,6 +81,11 @@ MODULE_PARM_DESC(enable_rc6,
|
|||
"For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. "
|
||||
"default: -1 (use per-chip default)");
|
||||
|
||||
module_param_named_unsafe(enable_dc, i915.enable_dc, int, 0400);
|
||||
MODULE_PARM_DESC(enable_dc,
|
||||
"Enable power-saving display C-states. "
|
||||
"(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)");
|
||||
|
||||
module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600);
|
||||
MODULE_PARM_DESC(enable_fbc,
|
||||
"Enable frame buffer compression for power savings "
|
||||
|
@ -112,7 +118,7 @@ MODULE_PARM_DESC(enable_hangcheck,
|
|||
module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400);
|
||||
MODULE_PARM_DESC(enable_ppgtt,
|
||||
"Override PPGTT usage. "
|
||||
"(-1=auto [default], 0=disabled, 1=aliasing, 2=full)");
|
||||
"(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)");
|
||||
|
||||
module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400);
|
||||
MODULE_PARM_DESC(enable_execlists,
|
||||
|
@ -126,7 +132,7 @@ module_param_named_unsafe(preliminary_hw_support, i915.preliminary_hw_support, i
|
|||
MODULE_PARM_DESC(preliminary_hw_support,
|
||||
"Enable preliminary hardware support.");
|
||||
|
||||
module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0600);
|
||||
module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400);
|
||||
MODULE_PARM_DESC(disable_power_well,
|
||||
"Disable display power wells when possible "
|
||||
"(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -35,7 +35,8 @@
|
|||
#define dev_to_drm_minor(d) dev_get_drvdata((d))
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static u32 calc_residency(struct drm_device *dev, const u32 reg)
|
||||
static u32 calc_residency(struct drm_device *dev,
|
||||
i915_reg_t reg)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u64 raw_time; /* 32b value may overflow during fixed point math */
|
||||
|
|
|
@ -664,7 +664,7 @@ TRACE_EVENT(i915_flip_complete,
|
|||
);
|
||||
|
||||
TRACE_EVENT_CONDITION(i915_reg_rw,
|
||||
TP_PROTO(bool write, u32 reg, u64 val, int len, bool trace),
|
||||
TP_PROTO(bool write, i915_reg_t reg, u64 val, int len, bool trace),
|
||||
|
||||
TP_ARGS(write, reg, val, len, trace),
|
||||
|
||||
|
@ -679,7 +679,7 @@ TRACE_EVENT_CONDITION(i915_reg_rw,
|
|||
|
||||
TP_fast_assign(
|
||||
__entry->val = (u64)val;
|
||||
__entry->reg = reg;
|
||||
__entry->reg = i915_mmio_reg_offset(reg);
|
||||
__entry->write = write;
|
||||
__entry->len = len;
|
||||
),
|
||||
|
|
|
@ -69,13 +69,13 @@ void i915_check_vgpu(struct drm_device *dev)
|
|||
if (!IS_HASWELL(dev))
|
||||
return;
|
||||
|
||||
magic = readq(dev_priv->regs + vgtif_reg(magic));
|
||||
magic = __raw_i915_read64(dev_priv, vgtif_reg(magic));
|
||||
if (magic != VGT_MAGIC)
|
||||
return;
|
||||
|
||||
version = INTEL_VGT_IF_VERSION_ENCODE(
|
||||
readw(dev_priv->regs + vgtif_reg(version_major)),
|
||||
readw(dev_priv->regs + vgtif_reg(version_minor)));
|
||||
__raw_i915_read16(dev_priv, vgtif_reg(version_major)),
|
||||
__raw_i915_read16(dev_priv, vgtif_reg(version_minor)));
|
||||
if (version != INTEL_VGT_IF_VERSION) {
|
||||
DRM_INFO("VGT interface version mismatch!\n");
|
||||
return;
|
||||
|
|
|
@ -92,14 +92,10 @@ struct vgt_if {
|
|||
uint32_t g2v_notify;
|
||||
uint32_t rsv6[7];
|
||||
|
||||
uint32_t pdp0_lo;
|
||||
uint32_t pdp0_hi;
|
||||
uint32_t pdp1_lo;
|
||||
uint32_t pdp1_hi;
|
||||
uint32_t pdp2_lo;
|
||||
uint32_t pdp2_hi;
|
||||
uint32_t pdp3_lo;
|
||||
uint32_t pdp3_hi;
|
||||
struct {
|
||||
uint32_t lo;
|
||||
uint32_t hi;
|
||||
} pdp[4];
|
||||
|
||||
uint32_t execlist_context_descriptor_lo;
|
||||
uint32_t execlist_context_descriptor_hi;
|
||||
|
@ -108,7 +104,7 @@ struct vgt_if {
|
|||
} __packed;
|
||||
|
||||
#define vgtif_reg(x) \
|
||||
(VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x)
|
||||
_MMIO((VGT_PVINFO_PAGE + (long)&((struct vgt_if *)NULL)->x))
|
||||
|
||||
/* vGPU display status to be used by the host side */
|
||||
#define VGT_DRV_DISPLAY_NOT_READY 0
|
||||
|
|
|
@ -94,6 +94,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
|
|||
__drm_atomic_helper_crtc_duplicate_state(crtc, &crtc_state->base);
|
||||
|
||||
crtc_state->update_pipe = false;
|
||||
crtc_state->disable_lp_wm = false;
|
||||
|
||||
return &crtc_state->base;
|
||||
}
|
||||
|
@ -205,8 +206,6 @@ int intel_atomic_setup_scalers(struct drm_device *dev,
|
|||
* but since this plane is unchanged just do the
|
||||
* minimum required validation.
|
||||
*/
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
|
||||
intel_crtc->atomic.wait_for_flips = true;
|
||||
crtc_state->base.planes_changed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,7 @@ intel_plane_duplicate_state(struct drm_plane *plane)
|
|||
state = &intel_state->base;
|
||||
|
||||
__drm_atomic_helper_plane_duplicate_state(plane, state);
|
||||
intel_state->wait_req = NULL;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
@ -100,6 +101,7 @@ void
|
|||
intel_plane_destroy_state(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
WARN_ON(state && to_intel_plane_state(state)->wait_req);
|
||||
drm_atomic_helper_plane_destroy_state(plane, state);
|
||||
}
|
||||
|
||||
|
|
|
@ -161,9 +161,9 @@ static bool audio_rate_need_prog(struct intel_crtc *crtc,
|
|||
}
|
||||
|
||||
static bool intel_eld_uptodate(struct drm_connector *connector,
|
||||
int reg_eldv, uint32_t bits_eldv,
|
||||
int reg_elda, uint32_t bits_elda,
|
||||
int reg_edid)
|
||||
i915_reg_t reg_eldv, uint32_t bits_eldv,
|
||||
i915_reg_t reg_elda, uint32_t bits_elda,
|
||||
i915_reg_t reg_edid)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
uint8_t *eld = connector->eld;
|
||||
|
@ -364,8 +364,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder)
|
|||
enum port port = intel_dig_port->port;
|
||||
enum pipe pipe = intel_crtc->pipe;
|
||||
uint32_t tmp, eldv;
|
||||
int aud_config;
|
||||
int aud_cntrl_st2;
|
||||
i915_reg_t aud_config, aud_cntrl_st2;
|
||||
|
||||
DRM_DEBUG_KMS("Disable audio codec on port %c, pipe %c\n",
|
||||
port_name(port), pipe_name(pipe));
|
||||
|
@ -416,10 +415,7 @@ static void ilk_audio_codec_enable(struct drm_connector *connector,
|
|||
uint32_t eldv;
|
||||
uint32_t tmp;
|
||||
int len, i;
|
||||
int hdmiw_hdmiedid;
|
||||
int aud_config;
|
||||
int aud_cntl_st;
|
||||
int aud_cntrl_st2;
|
||||
i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
|
||||
|
||||
DRM_DEBUG_KMS("Enable audio codec on port %c, pipe %c, %u bytes ELD\n",
|
||||
port_name(port), pipe_name(pipe), drm_eld_size(eld));
|
||||
|
@ -525,6 +521,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder)
|
|||
dev_priv->display.audio_codec_enable(connector, intel_encoder,
|
||||
adjusted_mode);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_dig_port->audio_connector = connector;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
|
||||
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
|
||||
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
|
||||
}
|
||||
|
@ -548,6 +548,10 @@ void intel_audio_codec_disable(struct intel_encoder *intel_encoder)
|
|||
if (dev_priv->display.audio_codec_disable)
|
||||
dev_priv->display.audio_codec_disable(intel_encoder);
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_dig_port->audio_connector = NULL;
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
|
||||
if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
|
||||
acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port);
|
||||
}
|
||||
|
@ -591,7 +595,7 @@ static void i915_audio_component_codec_wake_override(struct device *dev,
|
|||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
u32 tmp;
|
||||
|
||||
if (!IS_SKYLAKE(dev_priv))
|
||||
if (!IS_SKYLAKE(dev_priv) && !IS_KABYLAKE(dev_priv))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -632,44 +636,40 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
int port, int rate)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
struct drm_device *drm_dev = dev_priv->dev;
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
struct intel_crtc *crtc;
|
||||
struct drm_display_mode *mode;
|
||||
struct i915_audio_component *acomp = dev_priv->audio_component;
|
||||
enum pipe pipe = -1;
|
||||
enum pipe pipe = INVALID_PIPE;
|
||||
u32 tmp;
|
||||
int n;
|
||||
int err = 0;
|
||||
|
||||
/* HSW, BDW SKL need this fix */
|
||||
/* HSW, BDW, SKL, KBL need this fix */
|
||||
if (!IS_SKYLAKE(dev_priv) &&
|
||||
!IS_BROADWELL(dev_priv) &&
|
||||
!IS_HASWELL(dev_priv))
|
||||
!IS_KABYLAKE(dev_priv) &&
|
||||
!IS_BROADWELL(dev_priv) &&
|
||||
!IS_HASWELL(dev_priv))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
/* 1. get the pipe */
|
||||
for_each_intel_encoder(drm_dev, intel_encoder) {
|
||||
if (intel_encoder->type != INTEL_OUTPUT_HDMI)
|
||||
continue;
|
||||
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
||||
if (port == intel_dig_port->port) {
|
||||
crtc = to_intel_crtc(intel_encoder->base.crtc);
|
||||
if (!crtc) {
|
||||
DRM_DEBUG_KMS("%s: crtc is NULL\n", __func__);
|
||||
continue;
|
||||
}
|
||||
pipe = crtc->pipe;
|
||||
break;
|
||||
}
|
||||
intel_encoder = dev_priv->dig_port_map[port];
|
||||
/* intel_encoder might be NULL for DP MST */
|
||||
if (!intel_encoder || !intel_encoder->base.crtc ||
|
||||
intel_encoder->type != INTEL_OUTPUT_HDMI) {
|
||||
DRM_DEBUG_KMS("no valid port %c\n", port_name(port));
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
crtc = to_intel_crtc(intel_encoder->base.crtc);
|
||||
pipe = crtc->pipe;
|
||||
if (pipe == INVALID_PIPE) {
|
||||
DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port));
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return -ENODEV;
|
||||
err = -ENODEV;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("pipe %c connects port %c\n",
|
||||
pipe_name(pipe), port_name(port));
|
||||
mode = &crtc->config->base.adjusted_mode;
|
||||
|
@ -682,8 +682,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
n = audio_config_get_n(mode, rate);
|
||||
|
@ -693,8 +692,7 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = I915_READ(HSW_AUD_CFG(pipe));
|
||||
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* 3. set the N/CTS/M */
|
||||
|
@ -702,8 +700,37 @@ static int i915_audio_component_sync_audio_rate(struct device *dev,
|
|||
tmp = audio_config_setup_n_reg(n, tmp);
|
||||
I915_WRITE(HSW_AUD_CFG(pipe), tmp);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int i915_audio_component_get_eld(struct device *dev, int port,
|
||||
bool *enabled,
|
||||
unsigned char *buf, int max_bytes)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev_to_i915(dev);
|
||||
struct intel_encoder *intel_encoder;
|
||||
struct intel_digital_port *intel_dig_port;
|
||||
const u8 *eld;
|
||||
int ret = -EINVAL;
|
||||
|
||||
mutex_lock(&dev_priv->av_mutex);
|
||||
intel_encoder = dev_priv->dig_port_map[port];
|
||||
/* intel_encoder might be NULL for DP MST */
|
||||
if (intel_encoder) {
|
||||
ret = 0;
|
||||
intel_dig_port = enc_to_dig_port(&intel_encoder->base);
|
||||
*enabled = intel_dig_port->audio_connector != NULL;
|
||||
if (*enabled) {
|
||||
eld = intel_dig_port->audio_connector->eld;
|
||||
ret = drm_eld_size(eld);
|
||||
memcpy(buf, eld, min(max_bytes, ret));
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->av_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct i915_audio_component_ops i915_audio_component_ops = {
|
||||
|
@ -713,6 +740,7 @@ static const struct i915_audio_component_ops i915_audio_component_ops = {
|
|||
.codec_wake_override = i915_audio_component_codec_wake_override,
|
||||
.get_cdclk_freq = i915_audio_component_get_cdclk_freq,
|
||||
.sync_audio_rate = i915_audio_component_sync_audio_rate,
|
||||
.get_eld = i915_audio_component_get_eld,
|
||||
};
|
||||
|
||||
static int i915_audio_component_bind(struct device *i915_dev,
|
||||
|
|
|
@ -50,7 +50,7 @@ struct intel_crt {
|
|||
* encoder's enable/disable callbacks */
|
||||
struct intel_connector *connector;
|
||||
bool force_hotplug_required;
|
||||
u32 adpa_reg;
|
||||
i915_reg_t adpa_reg;
|
||||
};
|
||||
|
||||
static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
|
||||
|
@ -480,12 +480,8 @@ intel_crt_load_detect(struct intel_crt *crt)
|
|||
uint32_t vsample;
|
||||
uint32_t vblank, vblank_start, vblank_end;
|
||||
uint32_t dsl;
|
||||
uint32_t bclrpat_reg;
|
||||
uint32_t vtotal_reg;
|
||||
uint32_t vblank_reg;
|
||||
uint32_t vsync_reg;
|
||||
uint32_t pipeconf_reg;
|
||||
uint32_t pipe_dsl_reg;
|
||||
i915_reg_t bclrpat_reg, vtotal_reg,
|
||||
vblank_reg, vsync_reg, pipeconf_reg, pipe_dsl_reg;
|
||||
uint8_t st00;
|
||||
enum drm_connector_status status;
|
||||
|
||||
|
@ -518,7 +514,7 @@ intel_crt_load_detect(struct intel_crt *crt)
|
|||
/* Wait for next Vblank to substitue
|
||||
* border color for Color info */
|
||||
intel_wait_for_vblank(dev, pipe);
|
||||
st00 = I915_READ8(VGA_MSR_WRITE);
|
||||
st00 = I915_READ8(_VGA_MSR_WRITE);
|
||||
status = ((st00 & (1 << 4)) != 0) ?
|
||||
connector_status_connected :
|
||||
connector_status_disconnected;
|
||||
|
@ -563,7 +559,7 @@ intel_crt_load_detect(struct intel_crt *crt)
|
|||
do {
|
||||
count++;
|
||||
/* Read the ST00 VGA status register */
|
||||
st00 = I915_READ8(VGA_MSR_WRITE);
|
||||
st00 = I915_READ8(_VGA_MSR_WRITE);
|
||||
if (st00 & (1 << 4))
|
||||
detect++;
|
||||
} while ((I915_READ(pipe_dsl_reg) == dsl));
|
||||
|
|
|
@ -47,21 +47,10 @@
|
|||
MODULE_FIRMWARE(I915_CSR_SKL);
|
||||
MODULE_FIRMWARE(I915_CSR_BXT);
|
||||
|
||||
/*
|
||||
* SKL CSR registers for DC5 and DC6
|
||||
*/
|
||||
#define CSR_PROGRAM(i) (0x80000 + (i) * 4)
|
||||
#define CSR_SSP_BASE_ADDR_GEN9 0x00002FC0
|
||||
#define CSR_HTP_ADDR_SKL 0x00500034
|
||||
#define CSR_SSP_BASE 0x8F074
|
||||
#define CSR_HTP_SKL 0x8F004
|
||||
#define CSR_LAST_WRITE 0x8F034
|
||||
#define CSR_LAST_WRITE_VALUE 0xc003b400
|
||||
/* MMIO address range for CSR program (0x80000 - 0x82FFF) */
|
||||
#define SKL_CSR_VERSION_REQUIRED CSR_VERSION(1, 23)
|
||||
|
||||
#define CSR_MAX_FW_SIZE 0x2FFF
|
||||
#define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF
|
||||
#define CSR_MMIO_START_RANGE 0x80000
|
||||
#define CSR_MMIO_END_RANGE 0x8FFFF
|
||||
|
||||
struct intel_css_header {
|
||||
/* 0x09 for DMC */
|
||||
|
@ -178,166 +167,134 @@ struct stepping_info {
|
|||
};
|
||||
|
||||
static const struct stepping_info skl_stepping_info[] = {
|
||||
{'A', '0'}, {'B', '0'}, {'C', '0'},
|
||||
{'D', '0'}, {'E', '0'}, {'F', '0'},
|
||||
{'G', '0'}, {'H', '0'}, {'I', '0'}
|
||||
{'A', '0'}, {'B', '0'}, {'C', '0'},
|
||||
{'D', '0'}, {'E', '0'}, {'F', '0'},
|
||||
{'G', '0'}, {'H', '0'}, {'I', '0'}
|
||||
};
|
||||
|
||||
static struct stepping_info bxt_stepping_info[] = {
|
||||
static const struct stepping_info bxt_stepping_info[] = {
|
||||
{'A', '0'}, {'A', '1'}, {'A', '2'},
|
||||
{'B', '0'}, {'B', '1'}, {'B', '2'}
|
||||
};
|
||||
|
||||
static char intel_get_stepping(struct drm_device *dev)
|
||||
static const struct stepping_info *intel_get_stepping_info(struct drm_device *dev)
|
||||
{
|
||||
if (IS_SKYLAKE(dev) && (dev->pdev->revision <
|
||||
ARRAY_SIZE(skl_stepping_info)))
|
||||
return skl_stepping_info[dev->pdev->revision].stepping;
|
||||
else if (IS_BROXTON(dev) && (dev->pdev->revision <
|
||||
ARRAY_SIZE(bxt_stepping_info)))
|
||||
return bxt_stepping_info[dev->pdev->revision].stepping;
|
||||
else
|
||||
return -ENODATA;
|
||||
}
|
||||
const struct stepping_info *si;
|
||||
unsigned int size;
|
||||
|
||||
static char intel_get_substepping(struct drm_device *dev)
|
||||
{
|
||||
if (IS_SKYLAKE(dev) && (dev->pdev->revision <
|
||||
ARRAY_SIZE(skl_stepping_info)))
|
||||
return skl_stepping_info[dev->pdev->revision].substepping;
|
||||
else if (IS_BROXTON(dev) && (dev->pdev->revision <
|
||||
ARRAY_SIZE(bxt_stepping_info)))
|
||||
return bxt_stepping_info[dev->pdev->revision].substepping;
|
||||
else
|
||||
return -ENODATA;
|
||||
}
|
||||
if (IS_SKYLAKE(dev)) {
|
||||
size = ARRAY_SIZE(skl_stepping_info);
|
||||
si = skl_stepping_info;
|
||||
} else if (IS_BROXTON(dev)) {
|
||||
size = ARRAY_SIZE(bxt_stepping_info);
|
||||
si = bxt_stepping_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_csr_load_status_get() - to get firmware loading status.
|
||||
* @dev_priv: i915 device.
|
||||
*
|
||||
* This function helps to get the firmware loading status.
|
||||
*
|
||||
* Return: Firmware loading status.
|
||||
*/
|
||||
enum csr_state intel_csr_load_status_get(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
enum csr_state state;
|
||||
if (INTEL_REVID(dev) < size)
|
||||
return si + INTEL_REVID(dev);
|
||||
|
||||
mutex_lock(&dev_priv->csr_lock);
|
||||
state = dev_priv->csr.state;
|
||||
mutex_unlock(&dev_priv->csr_lock);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_csr_load_status_set() - help to set firmware loading status.
|
||||
* @dev_priv: i915 device.
|
||||
* @state: enumeration of firmware loading status.
|
||||
*
|
||||
* Set the firmware loading status.
|
||||
*/
|
||||
void intel_csr_load_status_set(struct drm_i915_private *dev_priv,
|
||||
enum csr_state state)
|
||||
{
|
||||
mutex_lock(&dev_priv->csr_lock);
|
||||
dev_priv->csr.state = state;
|
||||
mutex_unlock(&dev_priv->csr_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_csr_load_program() - write the firmware from memory to register.
|
||||
* @dev: drm device.
|
||||
* @dev_priv: i915 drm device.
|
||||
*
|
||||
* CSR firmware is read from a .bin file and kept in internal memory one time.
|
||||
* Everytime display comes back from low power state this function is called to
|
||||
* copy the firmware from internal memory to registers.
|
||||
*/
|
||||
void intel_csr_load_program(struct drm_device *dev)
|
||||
void intel_csr_load_program(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 *payload = dev_priv->csr.dmc_payload;
|
||||
uint32_t i, fw_size;
|
||||
|
||||
if (!IS_GEN9(dev)) {
|
||||
if (!IS_GEN9(dev_priv)) {
|
||||
DRM_ERROR("No CSR support available for this platform\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Firmware gets lost on S3/S4, but not when entering system
|
||||
* standby or suspend-to-idle (which is just like forced runtime pm).
|
||||
* Unfortunately the ACPI subsystem doesn't yet give us a way to
|
||||
* differentiate this, hence figure it out with this hack.
|
||||
*/
|
||||
if (I915_READ(CSR_PROGRAM(0)))
|
||||
if (!dev_priv->csr.dmc_payload) {
|
||||
DRM_ERROR("Tried to program CSR with empty payload\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&dev_priv->csr_lock);
|
||||
fw_size = dev_priv->csr.dmc_fw_size;
|
||||
for (i = 0; i < fw_size; i++)
|
||||
I915_WRITE(CSR_PROGRAM(i), payload[i]);
|
||||
|
||||
for (i = 0; i < dev_priv->csr.mmio_count; i++) {
|
||||
I915_WRITE(dev_priv->csr.mmioaddr[i],
|
||||
dev_priv->csr.mmiodata[i]);
|
||||
dev_priv->csr.mmiodata[i]);
|
||||
}
|
||||
|
||||
dev_priv->csr.state = FW_LOADED;
|
||||
mutex_unlock(&dev_priv->csr_lock);
|
||||
}
|
||||
|
||||
static void finish_csr_load(const struct firmware *fw, void *context)
|
||||
static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv,
|
||||
const struct firmware *fw)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = context;
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct intel_css_header *css_header;
|
||||
struct intel_package_header *package_header;
|
||||
struct intel_dmc_header *dmc_header;
|
||||
struct intel_csr *csr = &dev_priv->csr;
|
||||
char stepping = intel_get_stepping(dev);
|
||||
char substepping = intel_get_substepping(dev);
|
||||
const struct stepping_info *stepping_info = intel_get_stepping_info(dev);
|
||||
char stepping, substepping;
|
||||
uint32_t dmc_offset = CSR_DEFAULT_FW_OFFSET, readcount = 0, nbytes;
|
||||
uint32_t i;
|
||||
uint32_t *dmc_payload;
|
||||
bool fw_loaded = false;
|
||||
|
||||
if (!fw) {
|
||||
i915_firmware_load_error_print(csr->fw_path, 0);
|
||||
goto out;
|
||||
}
|
||||
if (!fw)
|
||||
return NULL;
|
||||
|
||||
if ((stepping == -ENODATA) || (substepping == -ENODATA)) {
|
||||
if (!stepping_info) {
|
||||
DRM_ERROR("Unknown stepping info, firmware loading failed\n");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stepping = stepping_info->stepping;
|
||||
substepping = stepping_info->substepping;
|
||||
|
||||
/* Extract CSS Header information*/
|
||||
css_header = (struct intel_css_header *)fw->data;
|
||||
if (sizeof(struct intel_css_header) !=
|
||||
(css_header->header_len * 4)) {
|
||||
(css_header->header_len * 4)) {
|
||||
DRM_ERROR("Firmware has wrong CSS header length %u bytes\n",
|
||||
(css_header->header_len * 4));
|
||||
goto out;
|
||||
(css_header->header_len * 4));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
csr->version = css_header->version;
|
||||
|
||||
if (IS_SKYLAKE(dev) && csr->version < SKL_CSR_VERSION_REQUIRED) {
|
||||
DRM_INFO("Refusing to load old Skylake DMC firmware v%u.%u,"
|
||||
" please upgrade to v%u.%u or later"
|
||||
" [https://01.org/linuxgraphics/intel-linux-graphics-firmwares].\n",
|
||||
CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version),
|
||||
CSR_VERSION_MAJOR(SKL_CSR_VERSION_REQUIRED),
|
||||
CSR_VERSION_MINOR(SKL_CSR_VERSION_REQUIRED));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
readcount += sizeof(struct intel_css_header);
|
||||
|
||||
/* Extract Package Header information*/
|
||||
package_header = (struct intel_package_header *)
|
||||
&fw->data[readcount];
|
||||
&fw->data[readcount];
|
||||
if (sizeof(struct intel_package_header) !=
|
||||
(package_header->header_len * 4)) {
|
||||
(package_header->header_len * 4)) {
|
||||
DRM_ERROR("Firmware has wrong package header length %u bytes\n",
|
||||
(package_header->header_len * 4));
|
||||
goto out;
|
||||
(package_header->header_len * 4));
|
||||
return NULL;
|
||||
}
|
||||
readcount += sizeof(struct intel_package_header);
|
||||
|
||||
/* Search for dmc_offset to find firware binary. */
|
||||
for (i = 0; i < package_header->num_entries; i++) {
|
||||
if (package_header->fw_info[i].substepping == '*' &&
|
||||
stepping == package_header->fw_info[i].stepping) {
|
||||
stepping == package_header->fw_info[i].stepping) {
|
||||
dmc_offset = package_header->fw_info[i].offset;
|
||||
break;
|
||||
} else if (stepping == package_header->fw_info[i].stepping &&
|
||||
|
@ -345,12 +302,12 @@ static void finish_csr_load(const struct firmware *fw, void *context)
|
|||
dmc_offset = package_header->fw_info[i].offset;
|
||||
break;
|
||||
} else if (package_header->fw_info[i].stepping == '*' &&
|
||||
package_header->fw_info[i].substepping == '*')
|
||||
package_header->fw_info[i].substepping == '*')
|
||||
dmc_offset = package_header->fw_info[i].offset;
|
||||
}
|
||||
if (dmc_offset == CSR_DEFAULT_FW_OFFSET) {
|
||||
DRM_ERROR("Firmware not supported for %c stepping\n", stepping);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
readcount += dmc_offset;
|
||||
|
||||
|
@ -358,26 +315,26 @@ static void finish_csr_load(const struct firmware *fw, void *context)
|
|||
dmc_header = (struct intel_dmc_header *)&fw->data[readcount];
|
||||
if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) {
|
||||
DRM_ERROR("Firmware has wrong dmc header length %u bytes\n",
|
||||
(dmc_header->header_len));
|
||||
goto out;
|
||||
(dmc_header->header_len));
|
||||
return NULL;
|
||||
}
|
||||
readcount += sizeof(struct intel_dmc_header);
|
||||
|
||||
/* Cache the dmc header info. */
|
||||
if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) {
|
||||
DRM_ERROR("Firmware has wrong mmio count %u\n",
|
||||
dmc_header->mmio_count);
|
||||
goto out;
|
||||
dmc_header->mmio_count);
|
||||
return NULL;
|
||||
}
|
||||
csr->mmio_count = dmc_header->mmio_count;
|
||||
for (i = 0; i < dmc_header->mmio_count; i++) {
|
||||
if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE ||
|
||||
dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
|
||||
dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) {
|
||||
DRM_ERROR(" Firmware has wrong mmio address 0x%x\n",
|
||||
dmc_header->mmioaddr[i]);
|
||||
goto out;
|
||||
dmc_header->mmioaddr[i]);
|
||||
return NULL;
|
||||
}
|
||||
csr->mmioaddr[i] = dmc_header->mmioaddr[i];
|
||||
csr->mmioaddr[i] = _MMIO(dmc_header->mmioaddr[i]);
|
||||
csr->mmiodata[i] = dmc_header->mmiodata[i];
|
||||
}
|
||||
|
||||
|
@ -385,56 +342,80 @@ static void finish_csr_load(const struct firmware *fw, void *context)
|
|||
nbytes = dmc_header->fw_size * 4;
|
||||
if (nbytes > CSR_MAX_FW_SIZE) {
|
||||
DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes);
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
csr->dmc_fw_size = dmc_header->fw_size;
|
||||
|
||||
csr->dmc_payload = kmalloc(nbytes, GFP_KERNEL);
|
||||
if (!csr->dmc_payload) {
|
||||
dmc_payload = kmalloc(nbytes, GFP_KERNEL);
|
||||
if (!dmc_payload) {
|
||||
DRM_ERROR("Memory allocation failed for dmc payload\n");
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dmc_payload = csr->dmc_payload;
|
||||
memcpy(dmc_payload, &fw->data[readcount], nbytes);
|
||||
|
||||
/* load csr program during system boot, as needed for DC states */
|
||||
intel_csr_load_program(dev);
|
||||
fw_loaded = true;
|
||||
return dmc_payload;
|
||||
}
|
||||
|
||||
static void csr_load_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *dev_priv;
|
||||
struct intel_csr *csr;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
dev_priv = container_of(work, typeof(*dev_priv), csr.work);
|
||||
csr = &dev_priv->csr;
|
||||
|
||||
ret = request_firmware(&fw, dev_priv->csr.fw_path,
|
||||
&dev_priv->dev->pdev->dev);
|
||||
if (!fw)
|
||||
goto out;
|
||||
|
||||
dev_priv->csr.dmc_payload = parse_csr_fw(dev_priv, fw);
|
||||
if (!dev_priv->csr.dmc_payload)
|
||||
goto out;
|
||||
|
||||
/* load csr program during system boot, as needed for DC states */
|
||||
intel_csr_load_program(dev_priv);
|
||||
|
||||
DRM_DEBUG_KMS("Finished loading %s\n", dev_priv->csr.fw_path);
|
||||
out:
|
||||
if (fw_loaded)
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
else
|
||||
intel_csr_load_status_set(dev_priv, FW_FAILED);
|
||||
if (dev_priv->csr.dmc_payload) {
|
||||
intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
DRM_INFO("Finished loading %s (v%u.%u)\n",
|
||||
dev_priv->csr.fw_path,
|
||||
CSR_VERSION_MAJOR(csr->version),
|
||||
CSR_VERSION_MINOR(csr->version));
|
||||
} else {
|
||||
DRM_ERROR("Failed to load DMC firmware, disabling rpm\n");
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_csr_ucode_init() - initialize the firmware loading.
|
||||
* @dev: drm device.
|
||||
* @dev_priv: i915 drm device.
|
||||
*
|
||||
* This function is called at the time of loading the display driver to read
|
||||
* firmware from a .bin file and copied into a internal memory.
|
||||
*/
|
||||
void intel_csr_ucode_init(struct drm_device *dev)
|
||||
void intel_csr_ucode_init(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_csr *csr = &dev_priv->csr;
|
||||
int ret;
|
||||
|
||||
if (!HAS_CSR(dev))
|
||||
INIT_WORK(&dev_priv->csr.work, csr_load_work_fn);
|
||||
|
||||
if (!HAS_CSR(dev_priv))
|
||||
return;
|
||||
|
||||
if (IS_SKYLAKE(dev))
|
||||
if (IS_SKYLAKE(dev_priv))
|
||||
csr->fw_path = I915_CSR_SKL;
|
||||
else if (IS_BROXTON(dev_priv))
|
||||
csr->fw_path = I915_CSR_BXT;
|
||||
else {
|
||||
DRM_ERROR("Unexpected: no known CSR firmware for platform\n");
|
||||
intel_csr_load_status_set(dev_priv, FW_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -444,43 +425,24 @@ void intel_csr_ucode_init(struct drm_device *dev)
|
|||
* Obtain a runtime pm reference, until CSR is loaded,
|
||||
* to avoid entering runtime-suspend.
|
||||
*/
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
/* CSR supported for platform, load firmware */
|
||||
ret = request_firmware_nowait(THIS_MODULE, true, csr->fw_path,
|
||||
&dev_priv->dev->pdev->dev,
|
||||
GFP_KERNEL, dev_priv,
|
||||
finish_csr_load);
|
||||
if (ret) {
|
||||
i915_firmware_load_error_print(csr->fw_path, ret);
|
||||
intel_csr_load_status_set(dev_priv, FW_FAILED);
|
||||
}
|
||||
schedule_work(&dev_priv->csr.work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_csr_ucode_fini() - unload the CSR firmware.
|
||||
* @dev: drm device.
|
||||
* @dev_priv: i915 drm device.
|
||||
*
|
||||
* Firmmware unloading includes freeing the internal momory and reset the
|
||||
* firmware loading status.
|
||||
*/
|
||||
void intel_csr_ucode_fini(struct drm_device *dev)
|
||||
void intel_csr_ucode_fini(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!HAS_CSR(dev))
|
||||
if (!HAS_CSR(dev_priv))
|
||||
return;
|
||||
|
||||
intel_csr_load_status_set(dev_priv, FW_FAILED);
|
||||
flush_work(&dev_priv->csr.work);
|
||||
|
||||
kfree(dev_priv->csr.dmc_payload);
|
||||
}
|
||||
|
||||
void assert_csr_loaded(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
WARN_ONCE(intel_csr_load_status_get(dev_priv) != FW_LOADED,
|
||||
"CSR is not loaded.\n");
|
||||
WARN_ONCE(!I915_READ(CSR_PROGRAM(0)),
|
||||
"CSR program storage start is NULL\n");
|
||||
WARN_ONCE(!I915_READ(CSR_SSP_BASE), "CSR SSP Base Not fine\n");
|
||||
WARN_ONCE(!I915_READ(CSR_HTP_SKL), "CSR HTP Not fine\n");
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue