mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-02-05 23:55:23 +07:00
Merge remote-tracking branch 'airlied/drm-next' into drm-nouveau-next
This commit is contained in:
commit
06d5a24f08
@ -126,6 +126,8 @@ X!Edrivers/base/interface.c
|
||||
</sect1>
|
||||
<sect1><title>Device Drivers DMA Management</title>
|
||||
!Edrivers/base/dma-buf.c
|
||||
!Edrivers/base/reservation.c
|
||||
!Iinclude/linux/reservation.h
|
||||
!Edrivers/base/dma-coherent.c
|
||||
!Edrivers/base/dma-mapping.c
|
||||
</sect1>
|
||||
|
@ -186,11 +186,12 @@
|
||||
<varlistentry>
|
||||
<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
|
||||
<listitem><para>
|
||||
DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler. The
|
||||
DRM core will automatically register an interrupt handler when the
|
||||
flag is set. DRIVER_IRQ_SHARED indicates whether the device &
|
||||
handler support shared IRQs (note that this is required of PCI
|
||||
drivers).
|
||||
DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler
|
||||
managed by the DRM Core. The core will support simple IRQ handler
|
||||
installation when the flag is set. The installation process is
|
||||
described in <xref linkend="drm-irq-registration"/>.</para>
|
||||
<para>DRIVER_IRQ_SHARED indicates whether the device & handler
|
||||
support shared IRQs (note that this is required of PCI drivers).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@ -344,50 +345,71 @@ char *date;</synopsis>
|
||||
The DRM core tries to facilitate IRQ handler registration and
|
||||
unregistration by providing <function>drm_irq_install</function> and
|
||||
<function>drm_irq_uninstall</function> functions. Those functions only
|
||||
support a single interrupt per device.
|
||||
</para>
|
||||
<!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
|
||||
<para>
|
||||
Both functions get the device IRQ by calling
|
||||
<function>drm_dev_to_irq</function>. This inline function will call a
|
||||
bus-specific operation to retrieve the IRQ number. For platform devices,
|
||||
<function>platform_get_irq</function>(..., 0) is used to retrieve the
|
||||
IRQ number.
|
||||
</para>
|
||||
<para>
|
||||
<function>drm_irq_install</function> starts by calling the
|
||||
<methodname>irq_preinstall</methodname> driver operation. The operation
|
||||
is optional and must make sure that the interrupt will not get fired by
|
||||
clearing all pending interrupt flags or disabling the interrupt.
|
||||
</para>
|
||||
<para>
|
||||
The IRQ will then be requested by a call to
|
||||
<function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
|
||||
feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
|
||||
requested.
|
||||
</para>
|
||||
<para>
|
||||
The IRQ handler function must be provided as the mandatory irq_handler
|
||||
driver operation. It will get passed directly to
|
||||
<function>request_irq</function> and thus has the same prototype as all
|
||||
IRQ handlers. It will get called with a pointer to the DRM device as the
|
||||
second argument.
|
||||
</para>
|
||||
<para>
|
||||
Finally the function calls the optional
|
||||
<methodname>irq_postinstall</methodname> driver operation. The operation
|
||||
usually enables interrupts (excluding the vblank interrupt, which is
|
||||
enabled separately), but drivers may choose to enable/disable interrupts
|
||||
at a different time.
|
||||
</para>
|
||||
<para>
|
||||
<function>drm_irq_uninstall</function> is similarly used to uninstall an
|
||||
IRQ handler. It starts by waking up all processes waiting on a vblank
|
||||
interrupt to make sure they don't hang, and then calls the optional
|
||||
<methodname>irq_uninstall</methodname> driver operation. The operation
|
||||
must disable all hardware interrupts. Finally the function frees the IRQ
|
||||
by calling <function>free_irq</function>.
|
||||
support a single interrupt per device, devices that use more than one
|
||||
IRQs need to be handled manually.
|
||||
</para>
|
||||
<sect4>
|
||||
<title>Managed IRQ Registration</title>
|
||||
<para>
|
||||
Both the <function>drm_irq_install</function> and
|
||||
<function>drm_irq_uninstall</function> functions get the device IRQ by
|
||||
calling <function>drm_dev_to_irq</function>. This inline function will
|
||||
call a bus-specific operation to retrieve the IRQ number. For platform
|
||||
devices, <function>platform_get_irq</function>(..., 0) is used to
|
||||
retrieve the IRQ number.
|
||||
</para>
|
||||
<para>
|
||||
<function>drm_irq_install</function> starts by calling the
|
||||
<methodname>irq_preinstall</methodname> driver operation. The operation
|
||||
is optional and must make sure that the interrupt will not get fired by
|
||||
clearing all pending interrupt flags or disabling the interrupt.
|
||||
</para>
|
||||
<para>
|
||||
The IRQ will then be requested by a call to
|
||||
<function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
|
||||
feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
|
||||
requested.
|
||||
</para>
|
||||
<para>
|
||||
The IRQ handler function must be provided as the mandatory irq_handler
|
||||
driver operation. It will get passed directly to
|
||||
<function>request_irq</function> and thus has the same prototype as all
|
||||
IRQ handlers. It will get called with a pointer to the DRM device as the
|
||||
second argument.
|
||||
</para>
|
||||
<para>
|
||||
Finally the function calls the optional
|
||||
<methodname>irq_postinstall</methodname> driver operation. The operation
|
||||
usually enables interrupts (excluding the vblank interrupt, which is
|
||||
enabled separately), but drivers may choose to enable/disable interrupts
|
||||
at a different time.
|
||||
</para>
|
||||
<para>
|
||||
<function>drm_irq_uninstall</function> is similarly used to uninstall an
|
||||
IRQ handler. It starts by waking up all processes waiting on a vblank
|
||||
interrupt to make sure they don't hang, and then calls the optional
|
||||
<methodname>irq_uninstall</methodname> driver operation. The operation
|
||||
must disable all hardware interrupts. Finally the function frees the IRQ
|
||||
by calling <function>free_irq</function>.
|
||||
</para>
|
||||
</sect4>
|
||||
<sect4>
|
||||
<title>Manual IRQ Registration</title>
|
||||
<para>
|
||||
Drivers that require multiple interrupt handlers can't use the managed
|
||||
IRQ registration functions. In that case IRQs must be registered and
|
||||
unregistered manually (usually with the <function>request_irq</function>
|
||||
and <function>free_irq</function> functions, or their devm_* equivalent).
|
||||
</para>
|
||||
<para>
|
||||
When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ
|
||||
driver feature flag, and must not provide the
|
||||
<methodname>irq_handler</methodname> driver operation. They must set the
|
||||
<structname>drm_device</structname> <structfield>irq_enabled</structfield>
|
||||
field to 1 upon registration of the IRQs, and clear it to 0 after
|
||||
unregistering the IRQs.
|
||||
</para>
|
||||
</sect4>
|
||||
</sect3>
|
||||
<sect3>
|
||||
<title>Memory Manager Initialization</title>
|
||||
@ -1213,6 +1235,15 @@ int max_width, max_height;</synopsis>
|
||||
<sect4>
|
||||
<title>Miscellaneous</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<synopsis>void (*set_property)(struct drm_crtc *crtc,
|
||||
struct drm_property *property, uint64_t value);</synopsis>
|
||||
<para>
|
||||
Set the value of the given CRTC property to
|
||||
<parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
|
||||
for more information about properties.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<synopsis>void (*gamma_set)(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b,
|
||||
uint32_t start, uint32_t size);</synopsis>
|
||||
@ -1363,6 +1394,15 @@ int max_width, max_height;</synopsis>
|
||||
<xref linkend="drm-kms-init"/>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<synopsis>void (*set_property)(struct drm_plane *plane,
|
||||
struct drm_property *property, uint64_t value);</synopsis>
|
||||
<para>
|
||||
Set the value of the given plane property to
|
||||
<parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
|
||||
for more information about properties.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</sect3>
|
||||
</sect2>
|
||||
@ -1571,6 +1611,15 @@ int max_width, max_height;</synopsis>
|
||||
<sect4>
|
||||
<title>Miscellaneous</title>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<synopsis>void (*set_property)(struct drm_connector *connector,
|
||||
struct drm_property *property, uint64_t value);</synopsis>
|
||||
<para>
|
||||
Set the value of the given connector property to
|
||||
<parameter>value</parameter>. See <xref linkend="drm-kms-properties"/>
|
||||
for more information about properties.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<synopsis>void (*destroy)(struct drm_connector *connector);</synopsis>
|
||||
<para>
|
||||
@ -1846,10 +1895,6 @@ void intel_crt_init(struct drm_device *dev)
|
||||
<synopsis>bool (*mode_fixup)(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);</synopsis>
|
||||
<note><para>
|
||||
FIXME: The mode argument be const, but the i915 driver modifies
|
||||
mode->clock in <function>intel_dp_mode_fixup</function>.
|
||||
</para></note>
|
||||
<para>
|
||||
Let encoders adjust the requested mode or reject it completely. This
|
||||
operation returns true if the mode is accepted (possibly after being
|
||||
@ -2161,6 +2206,128 @@ void intel_crt_init(struct drm_device *dev)
|
||||
<title>EDID Helper Functions Reference</title>
|
||||
!Edrivers/gpu/drm/drm_edid.c
|
||||
</sect2>
|
||||
<sect2>
|
||||
<title>Rectangle Utilities Reference</title>
|
||||
!Pinclude/drm/drm_rect.h rect utils
|
||||
!Iinclude/drm/drm_rect.h
|
||||
!Edrivers/gpu/drm/drm_rect.c
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<!-- Internals: kms properties -->
|
||||
|
||||
<sect1 id="drm-kms-properties">
|
||||
<title>KMS Properties</title>
|
||||
<para>
|
||||
Drivers may need to expose additional parameters to applications than
|
||||
those described in the previous sections. KMS supports attaching
|
||||
properties to CRTCs, connectors and planes and offers a userspace API to
|
||||
list, get and set the property values.
|
||||
</para>
|
||||
<para>
|
||||
Properties are identified by a name that uniquely defines the property
|
||||
purpose, and store an associated value. For all property types except blob
|
||||
properties the value is a 64-bit unsigned integer.
|
||||
</para>
|
||||
<para>
|
||||
KMS differentiates between properties and property instances. Drivers
|
||||
first create properties and then create and associate individual instances
|
||||
of those properties to objects. A property can be instantiated multiple
|
||||
times and associated with different objects. Values are stored in property
|
||||
instances, and all other property information are stored in the propery
|
||||
and shared between all instances of the property.
|
||||
</para>
|
||||
<para>
|
||||
Every property is created with a type that influences how the KMS core
|
||||
handles the property. Supported property types are
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>DRM_MODE_PROP_RANGE</term>
|
||||
<listitem><para>Range properties report their minimum and maximum
|
||||
admissible values. The KMS core verifies that values set by
|
||||
application fit in that range.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>DRM_MODE_PROP_ENUM</term>
|
||||
<listitem><para>Enumerated properties take a numerical value that
|
||||
ranges from 0 to the number of enumerated values defined by the
|
||||
property minus one, and associate a free-formed string name to each
|
||||
value. Applications can retrieve the list of defined value-name pairs
|
||||
and use the numerical value to get and set property instance values.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>DRM_MODE_PROP_BITMASK</term>
|
||||
<listitem><para>Bitmask properties are enumeration properties that
|
||||
additionally restrict all enumerated values to the 0..63 range.
|
||||
Bitmask property instance values combine one or more of the
|
||||
enumerated bits defined by the property.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>DRM_MODE_PROP_BLOB</term>
|
||||
<listitem><para>Blob properties store a binary blob without any format
|
||||
restriction. The binary blobs are created as KMS standalone objects,
|
||||
and blob property instance values store the ID of their associated
|
||||
blob object.</para>
|
||||
<para>Blob properties are only used for the connector EDID property
|
||||
and cannot be created by drivers.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
To create a property drivers call one of the following functions depending
|
||||
on the property type. All property creation functions take property flags
|
||||
and name, as well as type-specific arguments.
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<synopsis>struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
uint64_t min, uint64_t max);</synopsis>
|
||||
<para>Create a range property with the given minimum and maximum
|
||||
values.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<synopsis>struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
|
||||
const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_values);</synopsis>
|
||||
<para>Create an enumerated property. The <parameter>props</parameter>
|
||||
argument points to an array of <parameter>num_values</parameter>
|
||||
value-name pairs.</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<synopsis>struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
|
||||
int flags, const char *name,
|
||||
const struct drm_prop_enum_list *props,
|
||||
int num_values);</synopsis>
|
||||
<para>Create a bitmask property. The <parameter>props</parameter>
|
||||
argument points to an array of <parameter>num_values</parameter>
|
||||
value-name pairs.</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Properties can additionally be created as immutable, in which case they
|
||||
will be read-only for applications but can be modified by the driver. To
|
||||
create an immutable property drivers must set the DRM_MODE_PROP_IMMUTABLE
|
||||
flag at property creation time.
|
||||
</para>
|
||||
<para>
|
||||
When no array of value-name pairs is readily available at property
|
||||
creation time for enumerated or range properties, drivers can create
|
||||
the property using the <function>drm_property_create</function> function
|
||||
and manually add enumeration value-name pairs by calling the
|
||||
<function>drm_property_add_enum</function> function. Care must be taken to
|
||||
properly specify the property type through the <parameter>flags</parameter>
|
||||
argument.
|
||||
</para>
|
||||
<para>
|
||||
After creating properties drivers can attach property instances to CRTC,
|
||||
connector and plane objects by calling the
|
||||
<function>drm_object_attach_property</function>. The function takes a
|
||||
pointer to the target object, a pointer to the previously created property
|
||||
and an initial instance value.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<!-- Internals: vertical blanking -->
|
||||
|
@ -10,6 +10,14 @@ Recommended properties:
|
||||
services interrupts for this device.
|
||||
- ti,hwmods: Name of the hwmod associated to the LCDC
|
||||
|
||||
Optional properties:
|
||||
- max-bandwidth: The maximum pixels per second that the memory
|
||||
interface / lcd controller combination can sustain
|
||||
- max-width: The maximum horizontal pixel width supported by
|
||||
the lcd controller.
|
||||
- max-pixelclock: The maximum pixel clock that can be supported
|
||||
by the lcd controller in KHz.
|
||||
|
||||
Example:
|
||||
|
||||
fb: fb@4830e000 {
|
||||
|
@ -34,6 +34,7 @@ optional properties:
|
||||
- ignored = ignored
|
||||
- interlaced (bool): boolean to enable interlaced mode
|
||||
- doublescan (bool): boolean to enable doublescan mode
|
||||
- doubleclk (bool): boolean to enable doubleclock mode
|
||||
|
||||
All the optional properties that are not bool follow the following logic:
|
||||
<1>: high active
|
||||
|
@ -1,7 +1,10 @@
|
||||
Device-Tree bindings for drm hdmi driver
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be "samsung,exynos5-hdmi".
|
||||
- compatible: value should be one among the following:
|
||||
1) "samsung,exynos5-hdmi" <DEPRECATED>
|
||||
2) "samsung,exynos4210-hdmi"
|
||||
3) "samsung,exynos4212-hdmi"
|
||||
- reg: physical base address of the hdmi and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt number to the cpu.
|
||||
@ -15,7 +18,7 @@ Required properties:
|
||||
Example:
|
||||
|
||||
hdmi {
|
||||
compatible = "samsung,exynos5-hdmi";
|
||||
compatible = "samsung,exynos4212-hdmi";
|
||||
reg = <0x14530000 0x100000>;
|
||||
interrupts = <0 95 0>;
|
||||
hpd-gpio = <&gpx3 7 0xf 1 3>;
|
||||
|
@ -1,12 +1,15 @@
|
||||
Device-Tree bindings for hdmiddc driver
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be "samsung,exynos5-hdmiddc".
|
||||
- compatible: value should be one of the following
|
||||
1) "samsung,exynos5-hdmiddc" <DEPRECATED>
|
||||
2) "samsung,exynos4210-hdmiddc"
|
||||
|
||||
- reg: I2C address of the hdmiddc device.
|
||||
|
||||
Example:
|
||||
|
||||
hdmiddc {
|
||||
compatible = "samsung,exynos5-hdmiddc";
|
||||
compatible = "samsung,exynos4210-hdmiddc";
|
||||
reg = <0x50>;
|
||||
};
|
||||
|
@ -1,12 +1,15 @@
|
||||
Device-Tree bindings for hdmiphy driver
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be "samsung,exynos5-hdmiphy".
|
||||
- compatible: value should be one of the following:
|
||||
1) "samsung,exynos5-hdmiphy" <DEPRECATED>
|
||||
2) "samsung,exynos4210-hdmiphy".
|
||||
3) "samsung,exynos4212-hdmiphy".
|
||||
- reg: I2C address of the hdmiphy device.
|
||||
|
||||
Example:
|
||||
|
||||
hdmiphy {
|
||||
compatible = "samsung,exynos5-hdmiphy";
|
||||
compatible = "samsung,exynos4210-hdmiphy";
|
||||
reg = <0x38>;
|
||||
};
|
||||
|
@ -1,7 +1,12 @@
|
||||
Device-Tree bindings for mixer driver
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be "samsung,exynos5-mixer".
|
||||
- compatible: value should be one of the following:
|
||||
1) "samsung,exynos5-mixer" <DEPRECATED>
|
||||
2) "samsung,exynos4210-mixer"
|
||||
3) "samsung,exynos5250-mixer"
|
||||
4) "samsung,exynos5420-mixer"
|
||||
|
||||
- reg: physical base address of the mixer and length of memory mapped
|
||||
region.
|
||||
- interrupts: interrupt number to the cpu.
|
||||
@ -9,7 +14,7 @@ Required properties:
|
||||
Example:
|
||||
|
||||
mixer {
|
||||
compatible = "samsung,exynos5-mixer";
|
||||
compatible = "samsung,exynos5250-mixer";
|
||||
reg = <0x14450000 0x10000>;
|
||||
interrupts = <0 94 0>;
|
||||
};
|
||||
|
@ -81,17 +81,11 @@ pmipal Use the protected mode interface for palette changes.
|
||||
|
||||
mtrr:n Setup memory type range registers for the framebuffer
|
||||
where n:
|
||||
0 - disabled (equivalent to nomtrr) (default)
|
||||
1 - uncachable
|
||||
2 - write-back
|
||||
3 - write-combining
|
||||
4 - write-through
|
||||
0 - disabled (equivalent to nomtrr)
|
||||
3 - write-combining (default)
|
||||
|
||||
If you see the following in dmesg, choose the type that matches
|
||||
the old one. In this example, use "mtrr:2".
|
||||
...
|
||||
mtrr: type mismatch for e0000000,8000000 old: write-back new: write-combining
|
||||
...
|
||||
Values other than 0 and 3 will result in a warning and will be
|
||||
treated just like 3.
|
||||
|
||||
nomtrr Do not use memory type range registers.
|
||||
|
||||
|
344
Documentation/ww-mutex-design.txt
Normal file
344
Documentation/ww-mutex-design.txt
Normal file
@ -0,0 +1,344 @@
|
||||
Wait/Wound Deadlock-Proof Mutex Design
|
||||
======================================
|
||||
|
||||
Please read mutex-design.txt first, as it applies to wait/wound mutexes too.
|
||||
|
||||
Motivation for WW-Mutexes
|
||||
-------------------------
|
||||
|
||||
GPU's do operations that commonly involve many buffers. Those buffers
|
||||
can be shared across contexts/processes, exist in different memory
|
||||
domains (for example VRAM vs system memory), and so on. And with
|
||||
PRIME / dmabuf, they can even be shared across devices. So there are
|
||||
a handful of situations where the driver needs to wait for buffers to
|
||||
become ready. If you think about this in terms of waiting on a buffer
|
||||
mutex for it to become available, this presents a problem because
|
||||
there is no way to guarantee that buffers appear in a execbuf/batch in
|
||||
the same order in all contexts. That is directly under control of
|
||||
userspace, and a result of the sequence of GL calls that an application
|
||||
makes. Which results in the potential for deadlock. The problem gets
|
||||
more complex when you consider that the kernel may need to migrate the
|
||||
buffer(s) into VRAM before the GPU operates on the buffer(s), which
|
||||
may in turn require evicting some other buffers (and you don't want to
|
||||
evict other buffers which are already queued up to the GPU), but for a
|
||||
simplified understanding of the problem you can ignore this.
|
||||
|
||||
The algorithm that the TTM graphics subsystem came up with for dealing with
|
||||
this problem is quite simple. For each group of buffers (execbuf) that need
|
||||
to be locked, the caller would be assigned a unique reservation id/ticket,
|
||||
from a global counter. In case of deadlock while locking all the buffers
|
||||
associated with a execbuf, the one with the lowest reservation ticket (i.e.
|
||||
the oldest task) wins, and the one with the higher reservation id (i.e. the
|
||||
younger task) unlocks all of the buffers that it has already locked, and then
|
||||
tries again.
|
||||
|
||||
In the RDBMS literature this deadlock handling approach is called wait/wound:
|
||||
The older tasks waits until it can acquire the contended lock. The younger tasks
|
||||
needs to back off and drop all the locks it is currently holding, i.e. the
|
||||
younger task is wounded.
|
||||
|
||||
Concepts
|
||||
--------
|
||||
|
||||
Compared to normal mutexes two additional concepts/objects show up in the lock
|
||||
interface for w/w mutexes:
|
||||
|
||||
Acquire context: To ensure eventual forward progress it is important the a task
|
||||
trying to acquire locks doesn't grab a new reservation id, but keeps the one it
|
||||
acquired when starting the lock acquisition. This ticket is stored in the
|
||||
acquire context. Furthermore the acquire context keeps track of debugging state
|
||||
to catch w/w mutex interface abuse.
|
||||
|
||||
W/w class: In contrast to normal mutexes the lock class needs to be explicit for
|
||||
w/w mutexes, since it is required to initialize the acquire context.
|
||||
|
||||
Furthermore there are three different class of w/w lock acquire functions:
|
||||
|
||||
* Normal lock acquisition with a context, using ww_mutex_lock.
|
||||
|
||||
* Slowpath lock acquisition on the contending lock, used by the wounded task
|
||||
after having dropped all already acquired locks. These functions have the
|
||||
_slow postfix.
|
||||
|
||||
From a simple semantics point-of-view the _slow functions are not strictly
|
||||
required, since simply calling the normal ww_mutex_lock functions on the
|
||||
contending lock (after having dropped all other already acquired locks) will
|
||||
work correctly. After all if no other ww mutex has been acquired yet there's
|
||||
no deadlock potential and hence the ww_mutex_lock call will block and not
|
||||
prematurely return -EDEADLK. The advantage of the _slow functions is in
|
||||
interface safety:
|
||||
- ww_mutex_lock has a __must_check int return type, whereas ww_mutex_lock_slow
|
||||
has a void return type. Note that since ww mutex code needs loops/retries
|
||||
anyway the __must_check doesn't result in spurious warnings, even though the
|
||||
very first lock operation can never fail.
|
||||
- When full debugging is enabled ww_mutex_lock_slow checks that all acquired
|
||||
ww mutex have been released (preventing deadlocks) and makes sure that we
|
||||
block on the contending lock (preventing spinning through the -EDEADLK
|
||||
slowpath until the contended lock can be acquired).
|
||||
|
||||
* Functions to only acquire a single w/w mutex, which results in the exact same
|
||||
semantics as a normal mutex. This is done by calling ww_mutex_lock with a NULL
|
||||
context.
|
||||
|
||||
Again this is not strictly required. But often you only want to acquire a
|
||||
single lock in which case it's pointless to set up an acquire context (and so
|
||||
better to avoid grabbing a deadlock avoidance ticket).
|
||||
|
||||
Of course, all the usual variants for handling wake-ups due to signals are also
|
||||
provided.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Three different ways to acquire locks within the same w/w class. Common
|
||||
definitions for methods #1 and #2:
|
||||
|
||||
static DEFINE_WW_CLASS(ww_class);
|
||||
|
||||
struct obj {
|
||||
struct ww_mutex lock;
|
||||
/* obj data */
|
||||
};
|
||||
|
||||
struct obj_entry {
|
||||
struct list_head head;
|
||||
struct obj *obj;
|
||||
};
|
||||
|
||||
Method 1, using a list in execbuf->buffers that's not allowed to be reordered.
|
||||
This is useful if a list of required objects is already tracked somewhere.
|
||||
Furthermore the lock helper can use propagate the -EALREADY return code back to
|
||||
the caller as a signal that an object is twice on the list. This is useful if
|
||||
the list is constructed from userspace input and the ABI requires userspace to
|
||||
not have duplicate entries (e.g. for a gpu commandbuffer submission ioctl).
|
||||
|
||||
int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
struct obj *res_obj = NULL;
|
||||
struct obj_entry *contended_entry = NULL;
|
||||
struct obj_entry *entry;
|
||||
|
||||
ww_acquire_init(ctx, &ww_class);
|
||||
|
||||
retry:
|
||||
list_for_each_entry (entry, list, head) {
|
||||
if (entry->obj == res_obj) {
|
||||
res_obj = NULL;
|
||||
continue;
|
||||
}
|
||||
ret = ww_mutex_lock(&entry->obj->lock, ctx);
|
||||
if (ret < 0) {
|
||||
contended_entry = entry;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ww_acquire_done(ctx);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
list_for_each_entry_continue_reverse (entry, list, head)
|
||||
ww_mutex_unlock(&entry->obj->lock);
|
||||
|
||||
if (res_obj)
|
||||
ww_mutex_unlock(&res_obj->lock);
|
||||
|
||||
if (ret == -EDEADLK) {
|
||||
/* we lost out in a seqno race, lock and retry.. */
|
||||
ww_mutex_lock_slow(&contended_entry->obj->lock, ctx);
|
||||
res_obj = contended_entry->obj;
|
||||
goto retry;
|
||||
}
|
||||
ww_acquire_fini(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Method 2, using a list in execbuf->buffers that can be reordered. Same semantics
|
||||
of duplicate entry detection using -EALREADY as method 1 above. But the
|
||||
list-reordering allows for a bit more idiomatic code.
|
||||
|
||||
int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
struct obj_entry *entry, *entry2;
|
||||
|
||||
ww_acquire_init(ctx, &ww_class);
|
||||
|
||||
list_for_each_entry (entry, list, head) {
|
||||
ret = ww_mutex_lock(&entry->obj->lock, ctx);
|
||||
if (ret < 0) {
|
||||
entry2 = entry;
|
||||
|
||||
list_for_each_entry_continue_reverse (entry2, list, head)
|
||||
ww_mutex_unlock(&entry2->obj->lock);
|
||||
|
||||
if (ret != -EDEADLK) {
|
||||
ww_acquire_fini(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* we lost out in a seqno race, lock and retry.. */
|
||||
ww_mutex_lock_slow(&entry->obj->lock, ctx);
|
||||
|
||||
/*
|
||||
* Move buf to head of the list, this will point
|
||||
* buf->next to the first unlocked entry,
|
||||
* restarting the for loop.
|
||||
*/
|
||||
list_del(&entry->head);
|
||||
list_add(&entry->head, list);
|
||||
}
|
||||
}
|
||||
|
||||
ww_acquire_done(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Unlocking works the same way for both methods #1 and #2:
|
||||
|
||||
void unlock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
struct obj_entry *entry;
|
||||
|
||||
list_for_each_entry (entry, list, head)
|
||||
ww_mutex_unlock(&entry->obj->lock);
|
||||
|
||||
ww_acquire_fini(ctx);
|
||||
}
|
||||
|
||||
Method 3 is useful if the list of objects is constructed ad-hoc and not upfront,
|
||||
e.g. when adjusting edges in a graph where each node has its own ww_mutex lock,
|
||||
and edges can only be changed when holding the locks of all involved nodes. w/w
|
||||
mutexes are a natural fit for such a case for two reasons:
|
||||
- They can handle lock-acquisition in any order which allows us to start walking
|
||||
a graph from a starting point and then iteratively discovering new edges and
|
||||
locking down the nodes those edges connect to.
|
||||
- Due to the -EALREADY return code signalling that a given objects is already
|
||||
held there's no need for additional book-keeping to break cycles in the graph
|
||||
or keep track off which looks are already held (when using more than one node
|
||||
as a starting point).
|
||||
|
||||
Note that this approach differs in two important ways from the above methods:
|
||||
- Since the list of objects is dynamically constructed (and might very well be
|
||||
different when retrying due to hitting the -EDEADLK wound condition) there's
|
||||
no need to keep any object on a persistent list when it's not locked. We can
|
||||
therefore move the list_head into the object itself.
|
||||
- On the other hand the dynamic object list construction also means that the -EALREADY return
|
||||
code can't be propagated.
|
||||
|
||||
Note also that methods #1 and #2 and method #3 can be combined, e.g. to first lock a
|
||||
list of starting nodes (passed in from userspace) using one of the above
|
||||
methods. And then lock any additional objects affected by the operations using
|
||||
method #3 below. The backoff/retry procedure will be a bit more involved, since
|
||||
when the dynamic locking step hits -EDEADLK we also need to unlock all the
|
||||
objects acquired with the fixed list. But the w/w mutex debug checks will catch
|
||||
any interface misuse for these cases.
|
||||
|
||||
Also, method 3 can't fail the lock acquisition step since it doesn't return
|
||||
-EALREADY. Of course this would be different when using the _interruptible
|
||||
variants, but that's outside of the scope of these examples here.
|
||||
|
||||
struct obj {
|
||||
struct ww_mutex ww_mutex;
|
||||
struct list_head locked_list;
|
||||
};
|
||||
|
||||
static DEFINE_WW_CLASS(ww_class);
|
||||
|
||||
void __unlock_objs(struct list_head *list)
|
||||
{
|
||||
struct obj *entry, *temp;
|
||||
|
||||
list_for_each_entry_safe (entry, temp, list, locked_list) {
|
||||
/* need to do that before unlocking, since only the current lock holder is
|
||||
allowed to use object */
|
||||
list_del(&entry->locked_list);
|
||||
ww_mutex_unlock(entry->ww_mutex)
|
||||
}
|
||||
}
|
||||
|
||||
void lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
struct obj *obj;
|
||||
|
||||
ww_acquire_init(ctx, &ww_class);
|
||||
|
||||
retry:
|
||||
/* re-init loop start state */
|
||||
loop {
|
||||
/* magic code which walks over a graph and decides which objects
|
||||
* to lock */
|
||||
|
||||
ret = ww_mutex_lock(obj->ww_mutex, ctx);
|
||||
if (ret == -EALREADY) {
|
||||
/* we have that one already, get to the next object */
|
||||
continue;
|
||||
}
|
||||
if (ret == -EDEADLK) {
|
||||
__unlock_objs(list);
|
||||
|
||||
ww_mutex_lock_slow(obj, ctx);
|
||||
list_add(&entry->locked_list, list);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
/* locked a new object, add it to the list */
|
||||
list_add_tail(&entry->locked_list, list);
|
||||
}
|
||||
|
||||
ww_acquire_done(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unlock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
|
||||
{
|
||||
__unlock_objs(list);
|
||||
ww_acquire_fini(ctx);
|
||||
}
|
||||
|
||||
Method 4: Only lock one single objects. In that case deadlock detection and
|
||||
prevention is obviously overkill, since with grabbing just one lock you can't
|
||||
produce a deadlock within just one class. To simplify this case the w/w mutex
|
||||
api can be used with a NULL context.
|
||||
|
||||
Implementation Details
|
||||
----------------------
|
||||
|
||||
Design:
|
||||
ww_mutex currently encapsulates a struct mutex, this means no extra overhead for
|
||||
normal mutex locks, which are far more common. As such there is only a small
|
||||
increase in code size if wait/wound mutexes are not used.
|
||||
|
||||
In general, not much contention is expected. The locks are typically used to
|
||||
serialize access to resources for devices. The only way to make wakeups
|
||||
smarter would be at the cost of adding a field to struct mutex_waiter. This
|
||||
would add overhead to all cases where normal mutexes are used, and
|
||||
ww_mutexes are generally less performance sensitive.
|
||||
|
||||
Lockdep:
|
||||
Special care has been taken to warn for as many cases of api abuse
|
||||
as possible. Some common api abuses will be caught with
|
||||
CONFIG_DEBUG_MUTEXES, but CONFIG_PROVE_LOCKING is recommended.
|
||||
|
||||
Some of the errors which will be warned about:
|
||||
- Forgetting to call ww_acquire_fini or ww_acquire_init.
|
||||
- Attempting to lock more mutexes after ww_acquire_done.
|
||||
- Attempting to lock the wrong mutex after -EDEADLK and
|
||||
unlocking all mutexes.
|
||||
- Attempting to lock the right mutex after -EDEADLK,
|
||||
before unlocking all mutexes.
|
||||
|
||||
- Calling ww_mutex_lock_slow before -EDEADLK was returned.
|
||||
|
||||
- Unlocking mutexes with the wrong unlock function.
|
||||
- Calling one of the ww_acquire_* twice on the same context.
|
||||
- Using a different ww_class for the mutex than for the ww_acquire_ctx.
|
||||
- Normal lockdep errors that can result in deadlocks.
|
||||
|
||||
Some of the lockdep errors that can result in deadlocks:
|
||||
- Calling ww_acquire_init to initialize a second ww_acquire_ctx before
|
||||
having called ww_acquire_fini on the first.
|
||||
- 'normal' deadlocks that can occur.
|
||||
|
||||
FIXME: Update this section once we have the TASK_DEADLOCK task state flag magic
|
||||
implemented.
|
@ -2697,12 +2697,14 @@ F: include/drm/exynos*
|
||||
F: include/uapi/drm/exynos*
|
||||
|
||||
DRM DRIVERS FOR NVIDIA TEGRA
|
||||
M: Thierry Reding <thierry.reding@avionic-design.de>
|
||||
M: Thierry Reding <thierry.reding@gmail.com>
|
||||
M: Terje Bergström <tbergstrom@nvidia.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: linux-tegra@vger.kernel.org
|
||||
T: git git://gitorious.org/thierryreding/linux.git
|
||||
T: git git://anongit.freedesktop.org/tegra/linux.git
|
||||
S: Maintained
|
||||
F: drivers/gpu/drm/tegra/
|
||||
F: drivers/gpu/host1x/
|
||||
F: include/uapi/drm/tegra_drm.h
|
||||
F: Documentation/devicetree/bindings/gpu/nvidia,tegra20-host1x.txt
|
||||
|
||||
DSBR100 USB FM RADIO DRIVER
|
||||
|
@ -190,7 +190,7 @@ i2c@12C80000 {
|
||||
samsung,i2c-max-bus-freq = <66000>;
|
||||
|
||||
hdmiddc@50 {
|
||||
compatible = "samsung,exynos5-hdmiddc";
|
||||
compatible = "samsung,exynos4210-hdmiddc";
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
||||
@ -224,7 +224,7 @@ i2c@12CE0000 {
|
||||
samsung,i2c-max-bus-freq = <378000>;
|
||||
|
||||
hdmiphy@38 {
|
||||
compatible = "samsung,exynos5-hdmiphy";
|
||||
compatible = "samsung,exynos4212-hdmiphy";
|
||||
reg = <0x38>;
|
||||
};
|
||||
};
|
||||
|
@ -72,7 +72,7 @@ i2c@12C80000 {
|
||||
samsung,i2c-max-bus-freq = <66000>;
|
||||
|
||||
hdmiddc@50 {
|
||||
compatible = "samsung,exynos5-hdmiddc";
|
||||
compatible = "samsung,exynos4210-hdmiddc";
|
||||
reg = <0x50>;
|
||||
};
|
||||
};
|
||||
@ -102,7 +102,7 @@ i2c@12CE0000 {
|
||||
samsung,i2c-max-bus-freq = <66000>;
|
||||
|
||||
hdmiphy@38 {
|
||||
compatible = "samsung,exynos5-hdmiphy";
|
||||
compatible = "samsung,exynos4212-hdmiphy";
|
||||
reg = <0x38>;
|
||||
};
|
||||
};
|
||||
|
@ -601,7 +601,7 @@ gsc_3: gsc@0x13e30000 {
|
||||
};
|
||||
|
||||
hdmi {
|
||||
compatible = "samsung,exynos5-hdmi";
|
||||
compatible = "samsung,exynos4212-hdmi";
|
||||
reg = <0x14530000 0x70000>;
|
||||
interrupts = <0 95 0>;
|
||||
clocks = <&clock 333>, <&clock 136>, <&clock 137>,
|
||||
@ -611,7 +611,7 @@ hdmi {
|
||||
};
|
||||
|
||||
mixer {
|
||||
compatible = "samsung,exynos5-mixer";
|
||||
compatible = "samsung,exynos5250-mixer";
|
||||
reg = <0x14450000 0x10000>;
|
||||
interrupts = <0 94 0>;
|
||||
};
|
||||
|
@ -29,17 +29,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
||||
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
|
||||
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
|
||||
* or anything the slow path function returns.
|
||||
* Change the count from 1 to a value lower than 1. This function returns 0
|
||||
* if the fastpath succeeds, or -1 otherwise.
|
||||
*/
|
||||
static inline int
|
||||
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||
__mutex_fastpath_lock_retval(atomic_t *count)
|
||||
{
|
||||
if (unlikely(ia64_fetchadd4_acq(count, -1) != 1))
|
||||
return fail_fn(count);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -82,17 +82,15 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
||||
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
|
||||
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
|
||||
* or anything the slow path function returns.
|
||||
* Change the count from 1 to a value lower than 1. This function returns 0
|
||||
* if the fastpath succeeds, or -1 otherwise.
|
||||
*/
|
||||
static inline int
|
||||
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||
__mutex_fastpath_lock_retval(atomic_t *count)
|
||||
{
|
||||
if (unlikely(__mutex_dec_return_lock(count) < 0))
|
||||
return fail_fn(count);
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -97,22 +97,14 @@ static int fsl_indirect_read_config(struct pci_bus *bus, unsigned int devfn,
|
||||
return indirect_read_config(bus, devfn, offset, len, val);
|
||||
}
|
||||
|
||||
static struct pci_ops fsl_indirect_pci_ops =
|
||||
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
|
||||
|
||||
static struct pci_ops fsl_indirect_pcie_ops =
|
||||
{
|
||||
.read = fsl_indirect_read_config,
|
||||
.write = indirect_write_config,
|
||||
};
|
||||
|
||||
static void __init fsl_setup_indirect_pci(struct pci_controller* hose,
|
||||
resource_size_t cfg_addr,
|
||||
resource_size_t cfg_data, u32 flags)
|
||||
{
|
||||
setup_indirect_pci(hose, cfg_addr, cfg_data, flags);
|
||||
hose->ops = &fsl_indirect_pci_ops;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
|
||||
|
||||
#define MAX_PHYS_ADDR_BITS 40
|
||||
static u64 pci64_dma_offset = 1ull << MAX_PHYS_ADDR_BITS;
|
||||
|
||||
@ -504,13 +496,15 @@ int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
|
||||
if (!hose->private_data)
|
||||
goto no_bridge;
|
||||
|
||||
fsl_setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
|
||||
PPC_INDIRECT_TYPE_BIG_ENDIAN);
|
||||
setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
|
||||
PPC_INDIRECT_TYPE_BIG_ENDIAN);
|
||||
|
||||
if (in_be32(&pci->block_rev1) < PCIE_IP_REV_3_0)
|
||||
hose->indirect_type |= PPC_INDIRECT_TYPE_FSL_CFG_REG_LINK;
|
||||
|
||||
if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
|
||||
/* use fsl_indirect_read_config for PCIe */
|
||||
hose->ops = &fsl_indirect_pcie_ops;
|
||||
/* For PCIE read HEADER_TYPE to identify controler mode */
|
||||
early_read_config_byte(hose, 0, 0, PCI_HEADER_TYPE, &hdr_type);
|
||||
if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE)
|
||||
@ -814,8 +808,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
|
||||
if (ret)
|
||||
goto err0;
|
||||
} else {
|
||||
fsl_setup_indirect_pci(hose, rsrc_cfg.start,
|
||||
rsrc_cfg.start + 4, 0);
|
||||
setup_indirect_pci(hose, rsrc_cfg.start,
|
||||
rsrc_cfg.start + 4, 0);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
|
||||
|
@ -50,9 +50,10 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||
{
|
||||
struct dma_map_ops *dma_ops = get_dma_ops(dev);
|
||||
|
||||
debug_dma_mapping_error(dev, dma_addr);
|
||||
if (dma_ops->mapping_error)
|
||||
return dma_ops->mapping_error(dev, dma_addr);
|
||||
return (dma_addr == 0UL);
|
||||
return (dma_addr == DMA_ERROR_CODE);
|
||||
}
|
||||
|
||||
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
|
||||
|
@ -754,9 +754,9 @@ static struct bin_attribute sys_reipl_fcp_scp_data_attr = {
|
||||
.write = reipl_fcp_scpdata_write,
|
||||
};
|
||||
|
||||
DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%016llx\n",
|
||||
DEFINE_IPL_ATTR_RW(reipl_fcp, wwpn, "0x%016llx\n", "%llx\n",
|
||||
reipl_block_fcp->ipl_info.fcp.wwpn);
|
||||
DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%016llx\n",
|
||||
DEFINE_IPL_ATTR_RW(reipl_fcp, lun, "0x%016llx\n", "%llx\n",
|
||||
reipl_block_fcp->ipl_info.fcp.lun);
|
||||
DEFINE_IPL_ATTR_RW(reipl_fcp, bootprog, "%lld\n", "%lld\n",
|
||||
reipl_block_fcp->ipl_info.fcp.bootprog);
|
||||
@ -1323,9 +1323,9 @@ static struct shutdown_action __refdata reipl_action = {
|
||||
|
||||
/* FCP dump device attributes */
|
||||
|
||||
DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%016llx\n",
|
||||
DEFINE_IPL_ATTR_RW(dump_fcp, wwpn, "0x%016llx\n", "%llx\n",
|
||||
dump_block_fcp->ipl_info.fcp.wwpn);
|
||||
DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%016llx\n",
|
||||
DEFINE_IPL_ATTR_RW(dump_fcp, lun, "0x%016llx\n", "%llx\n",
|
||||
dump_block_fcp->ipl_info.fcp.lun);
|
||||
DEFINE_IPL_ATTR_RW(dump_fcp, bootprog, "%lld\n", "%lld\n",
|
||||
dump_block_fcp->ipl_info.fcp.bootprog);
|
||||
|
@ -312,6 +312,7 @@ void measurement_alert_subclass_unregister(void)
|
||||
}
|
||||
EXPORT_SYMBOL(measurement_alert_subclass_unregister);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void synchronize_irq(unsigned int irq)
|
||||
{
|
||||
/*
|
||||
@ -320,6 +321,7 @@ void synchronize_irq(unsigned int irq)
|
||||
*/
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(synchronize_irq);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
|
||||
|
@ -123,7 +123,8 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr,
|
||||
continue;
|
||||
} else if ((addr <= chunk->addr) &&
|
||||
(addr + size >= chunk->addr + chunk->size)) {
|
||||
memset(chunk, 0 , sizeof(*chunk));
|
||||
memmove(chunk, chunk + 1, (MEMORY_CHUNKS-i-1) * sizeof(*chunk));
|
||||
memset(&mem_chunk[MEMORY_CHUNKS-1], 0, sizeof(*chunk));
|
||||
} else if (addr + size < chunk->addr + chunk->size) {
|
||||
chunk->size = chunk->addr + chunk->size - addr - size;
|
||||
chunk->addr = addr + size;
|
||||
|
@ -37,7 +37,7 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
||||
}
|
||||
|
||||
static inline int
|
||||
__mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||
__mutex_fastpath_lock_retval(atomic_t *count)
|
||||
{
|
||||
int __done, __res;
|
||||
|
||||
@ -51,7 +51,7 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
||||
: "t");
|
||||
|
||||
if (unlikely(!__done || __res != 0))
|
||||
__res = fail_fn(count);
|
||||
__res = -1;
|
||||
|
||||
return __res;
|
||||
}
|
||||
|
@ -345,4 +345,11 @@ extern bool xen_biovec_phys_mergeable(const struct bio_vec *vec1,
|
||||
|
||||
#define IO_SPACE_LIMIT 0xffff
|
||||
|
||||
#ifdef CONFIG_MTRR
|
||||
extern int __must_check arch_phys_wc_add(unsigned long base,
|
||||
unsigned long size);
|
||||
extern void arch_phys_wc_del(int handle);
|
||||
#define arch_phys_wc_add arch_phys_wc_add
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_X86_IO_H */
|
||||
|
@ -26,7 +26,10 @@
|
||||
#include <uapi/asm/mtrr.h>
|
||||
|
||||
|
||||
/* The following functions are for use by other drivers */
|
||||
/*
|
||||
* The following functions are for use by other drivers that cannot use
|
||||
* arch_phys_wc_add and arch_phys_wc_del.
|
||||
*/
|
||||
# ifdef CONFIG_MTRR
|
||||
extern u8 mtrr_type_lookup(u64 addr, u64 end);
|
||||
extern void mtrr_save_fixed_ranges(void *);
|
||||
@ -45,6 +48,7 @@ extern void mtrr_aps_init(void);
|
||||
extern void mtrr_bp_restore(void);
|
||||
extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
|
||||
extern int amd_special_default_mtrr(void);
|
||||
extern int phys_wc_to_mtrr_index(int handle);
|
||||
# else
|
||||
static inline u8 mtrr_type_lookup(u64 addr, u64 end)
|
||||
{
|
||||
@ -80,6 +84,10 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
|
||||
static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
|
||||
{
|
||||
}
|
||||
static inline int phys_wc_to_mtrr_index(int handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define mtrr_ap_init() do {} while (0)
|
||||
#define mtrr_bp_init() do {} while (0)
|
||||
|
@ -42,17 +42,14 @@ do { \
|
||||
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if it
|
||||
* wasn't 1 originally. This function returns 0 if the fastpath succeeds,
|
||||
* or anything the slow path function returns
|
||||
* Change the count from 1 to a value lower than 1. This function returns 0
|
||||
* if the fastpath succeeds, or -1 otherwise.
|
||||
*/
|
||||
static inline int __mutex_fastpath_lock_retval(atomic_t *count,
|
||||
int (*fail_fn)(atomic_t *))
|
||||
static inline int __mutex_fastpath_lock_retval(atomic_t *count)
|
||||
{
|
||||
if (unlikely(atomic_dec_return(count) < 0))
|
||||
return fail_fn(count);
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,17 +37,14 @@ do { \
|
||||
* __mutex_fastpath_lock_retval - try to take the lock by moving the count
|
||||
* from 1 to a 0 value
|
||||
* @count: pointer of type atomic_t
|
||||
* @fail_fn: function to call if the original value was not 1
|
||||
*
|
||||
* Change the count from 1 to a value lower than 1, and call <fail_fn> if
|
||||
* it wasn't 1 originally. This function returns 0 if the fastpath succeeds,
|
||||
* or anything the slow path function returns
|
||||
* Change the count from 1 to a value lower than 1. This function returns 0
|
||||
* if the fastpath succeeds, or -1 otherwise.
|
||||
*/
|
||||
static inline int __mutex_fastpath_lock_retval(atomic_t *count,
|
||||
int (*fail_fn)(atomic_t *))
|
||||
static inline int __mutex_fastpath_lock_retval(atomic_t *count)
|
||||
{
|
||||
if (unlikely(atomic_dec_return(count) < 0))
|
||||
return fail_fn(count);
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,9 +51,13 @@
|
||||
#include <asm/e820.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/msr.h>
|
||||
#include <asm/pat.h>
|
||||
|
||||
#include "mtrr.h"
|
||||
|
||||
/* arch_phys_wc_add returns an MTRR register index plus this offset. */
|
||||
#define MTRR_TO_PHYS_WC_OFFSET 1000
|
||||
|
||||
u32 num_var_ranges;
|
||||
|
||||
unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
|
||||
@ -524,6 +528,73 @@ int mtrr_del(int reg, unsigned long base, unsigned long size)
|
||||
}
|
||||
EXPORT_SYMBOL(mtrr_del);
|
||||
|
||||
/**
|
||||
* arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable
|
||||
* @base: Physical base address
|
||||
* @size: Size of region
|
||||
*
|
||||
* If PAT is available, this does nothing. If PAT is unavailable, it
|
||||
* attempts to add a WC MTRR covering size bytes starting at base and
|
||||
* logs an error if this fails.
|
||||
*
|
||||
* Drivers must store the return value to pass to mtrr_del_wc_if_needed,
|
||||
* but drivers should not try to interpret that return value.
|
||||
*/
|
||||
int arch_phys_wc_add(unsigned long base, unsigned long size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (pat_enabled)
|
||||
return 0; /* Success! (We don't need to do anything.) */
|
||||
|
||||
ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true);
|
||||
if (ret < 0) {
|
||||
pr_warn("Failed to add WC MTRR for [%p-%p]; performance may suffer.",
|
||||
(void *)base, (void *)(base + size - 1));
|
||||
return ret;
|
||||
}
|
||||
return ret + MTRR_TO_PHYS_WC_OFFSET;
|
||||
}
|
||||
EXPORT_SYMBOL(arch_phys_wc_add);
|
||||
|
||||
/*
|
||||
* arch_phys_wc_del - undoes arch_phys_wc_add
|
||||
* @handle: Return value from arch_phys_wc_add
|
||||
*
|
||||
* This cleans up after mtrr_add_wc_if_needed.
|
||||
*
|
||||
* The API guarantees that mtrr_del_wc_if_needed(error code) and
|
||||
* mtrr_del_wc_if_needed(0) do nothing.
|
||||
*/
|
||||
void arch_phys_wc_del(int handle)
|
||||
{
|
||||
if (handle >= 1) {
|
||||
WARN_ON(handle < MTRR_TO_PHYS_WC_OFFSET);
|
||||
mtrr_del(handle - MTRR_TO_PHYS_WC_OFFSET, 0, 0);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(arch_phys_wc_del);
|
||||
|
||||
/*
|
||||
* phys_wc_to_mtrr_index - translates arch_phys_wc_add's return value
|
||||
* @handle: Return value from arch_phys_wc_add
|
||||
*
|
||||
* This will turn the return value from arch_phys_wc_add into an mtrr
|
||||
* index suitable for debugging.
|
||||
*
|
||||
* Note: There is no legitimate use for this function, except possibly
|
||||
* in printk line. Alas there is an illegitimate use in some ancient
|
||||
* drm ioctls.
|
||||
*/
|
||||
int phys_wc_to_mtrr_index(int handle)
|
||||
{
|
||||
if (handle < MTRR_TO_PHYS_WC_OFFSET)
|
||||
return -1;
|
||||
else
|
||||
return handle - MTRR_TO_PHYS_WC_OFFSET;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phys_wc_to_mtrr_index);
|
||||
|
||||
/*
|
||||
* HACK ALERT!
|
||||
* These should be called implicitly, but we can't yet until all the initcall
|
||||
|
@ -10,7 +10,7 @@ obj-$(CONFIG_CMA) += dma-contiguous.o
|
||||
obj-y += power/
|
||||
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
|
||||
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
|
||||
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o
|
||||
obj-$(CONFIG_DMA_SHARED_BUFFER) += dma-buf.o reservation.o
|
||||
obj-$(CONFIG_ISA) += isa.o
|
||||
obj-$(CONFIG_FW_LOADER) += firmware_class.o
|
||||
obj-$(CONFIG_NUMA) += node.o
|
||||
|
39
drivers/base/reservation.c
Normal file
39
drivers/base/reservation.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2012-2013 Canonical Ltd
|
||||
*
|
||||
* Based on bo.c which bears the following copyright notice,
|
||||
* but is dual licensed:
|
||||
*
|
||||
* Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
/*
|
||||
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
|
||||
*/
|
||||
|
||||
#include <linux/reservation.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
DEFINE_WW_CLASS(reservation_ww_class);
|
||||
EXPORT_SYMBOL(reservation_ww_class);
|
@ -236,14 +236,14 @@ static int ati_configure(void)
|
||||
static int agp_ati_suspend(struct pci_dev *dev, pm_message_t state)
|
||||
{
|
||||
pci_save_state(dev);
|
||||
pci_set_power_state(dev, 3);
|
||||
pci_set_power_state(dev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int agp_ati_resume(struct pci_dev *dev)
|
||||
{
|
||||
pci_set_power_state(dev, 0);
|
||||
pci_set_power_state(dev, PCI_D0);
|
||||
pci_restore_state(dev);
|
||||
|
||||
return ati_configure();
|
||||
|
@ -603,7 +603,8 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
vma->vm_ops = kerninfo.vm_ops;
|
||||
} else if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
(kerninfo.aper_base + offset) >> PAGE_SHIFT,
|
||||
size, vma->vm_page_prot)) {
|
||||
size,
|
||||
pgprot_writecombine(vma->vm_page_prot))) {
|
||||
goto out_again;
|
||||
}
|
||||
mutex_unlock(&(agp_fe.agp_mutex));
|
||||
@ -618,8 +619,9 @@ static int agp_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
if (kerninfo.vm_ops) {
|
||||
vma->vm_ops = kerninfo.vm_ops;
|
||||
} else if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
kerninfo.aper_base >> PAGE_SHIFT,
|
||||
size, vma->vm_page_prot)) {
|
||||
kerninfo.aper_base >> PAGE_SHIFT,
|
||||
size,
|
||||
pgprot_writecombine(vma->vm_page_prot))) {
|
||||
goto out_again;
|
||||
}
|
||||
mutex_unlock(&(agp_fe.agp_mutex));
|
||||
|
@ -399,8 +399,8 @@ static void agp_nvidia_remove(struct pci_dev *pdev)
|
||||
#ifdef CONFIG_PM
|
||||
static int agp_nvidia_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
pci_save_state (pdev);
|
||||
pci_set_power_state (pdev, 3);
|
||||
pci_save_state(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -408,7 +408,7 @@ static int agp_nvidia_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int agp_nvidia_resume(struct pci_dev *pdev)
|
||||
{
|
||||
/* set power state 0 and restore PCI space */
|
||||
pci_set_power_state (pdev, 0);
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
|
||||
/* reconfigure AGP hardware again */
|
||||
|
@ -139,6 +139,7 @@ config DRM_I915
|
||||
select BACKLIGHT_CLASS_DEVICE if ACPI
|
||||
select VIDEO_OUTPUT_CONTROL if ACPI
|
||||
select INPUT if ACPI
|
||||
select THERMAL if ACPI
|
||||
select ACPI_VIDEO if ACPI
|
||||
select ACPI_BUTTON if ACPI
|
||||
help
|
||||
@ -213,6 +214,8 @@ source "drivers/gpu/drm/mgag200/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/cirrus/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/rcar-du/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/shmobile/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/omapdrm/Kconfig"
|
||||
|
@ -12,7 +12,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
|
||||
drm_platform.o drm_sysfs.o drm_hashtab.o drm_mm.o \
|
||||
drm_crtc.o drm_modes.o drm_edid.o \
|
||||
drm_info.o drm_debugfs.o drm_encoder_slave.o \
|
||||
drm_trace_points.o drm_global.o drm_prime.o
|
||||
drm_trace_points.o drm_global.o drm_prime.o \
|
||||
drm_rect.o
|
||||
|
||||
drm-$(CONFIG_COMPAT) += drm_ioc32.o
|
||||
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
|
||||
@ -48,6 +49,7 @@ obj-$(CONFIG_DRM_EXYNOS) +=exynos/
|
||||
obj-$(CONFIG_DRM_GMA500) += gma500/
|
||||
obj-$(CONFIG_DRM_UDL) += udl/
|
||||
obj-$(CONFIG_DRM_AST) += ast/
|
||||
obj-$(CONFIG_DRM_RCAR_DU) += rcar-du/
|
||||
obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/
|
||||
obj-$(CONFIG_DRM_OMAP) += omapdrm/
|
||||
obj-$(CONFIG_DRM_TILCDC) += tilcdc/
|
||||
|
@ -348,8 +348,24 @@ int ast_gem_create(struct drm_device *dev,
|
||||
int ast_bo_pin(struct ast_bo *bo, u32 pl_flag, u64 *gpu_addr);
|
||||
int ast_bo_unpin(struct ast_bo *bo);
|
||||
|
||||
int ast_bo_reserve(struct ast_bo *bo, bool no_wait);
|
||||
void ast_bo_unreserve(struct ast_bo *bo);
|
||||
static inline int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS && ret != -EBUSY)
|
||||
DRM_ERROR("reserve failed %p\n", bo);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ast_bo_unreserve(struct ast_bo *bo)
|
||||
{
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
}
|
||||
|
||||
void ast_ttm_placement(struct ast_bo *bo, int domain);
|
||||
int ast_bo_push_sysram(struct ast_bo *bo);
|
||||
int ast_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
|
@ -51,7 +51,7 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
|
||||
struct ast_bo *bo;
|
||||
int src_offset, dst_offset;
|
||||
int bpp = (afbdev->afb.base.bits_per_pixel + 7)/8;
|
||||
int ret;
|
||||
int ret = -EBUSY;
|
||||
bool unmap = false;
|
||||
bool store_for_later = false;
|
||||
int x2, y2;
|
||||
@ -65,7 +65,8 @@ static void ast_dirty_update(struct ast_fbdev *afbdev,
|
||||
* then the BO is being moved and we should
|
||||
* store up the damage until later.
|
||||
*/
|
||||
ret = ast_bo_reserve(bo, true);
|
||||
if (!in_interrupt())
|
||||
ret = ast_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
if (ret != -EBUSY)
|
||||
return;
|
||||
|
@ -271,26 +271,19 @@ int ast_mm_init(struct ast_private *ast)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ast->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0),
|
||||
DRM_MTRR_WC);
|
||||
ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_mm_fini(struct ast_private *ast)
|
||||
{
|
||||
struct drm_device *dev = ast->dev;
|
||||
ttm_bo_device_release(&ast->ttm.bdev);
|
||||
|
||||
ast_ttm_global_release(ast);
|
||||
|
||||
if (ast->fb_mtrr >= 0) {
|
||||
drm_mtrr_del(ast->fb_mtrr,
|
||||
pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
|
||||
ast->fb_mtrr = -1;
|
||||
}
|
||||
arch_phys_wc_del(ast->fb_mtrr);
|
||||
}
|
||||
|
||||
void ast_ttm_placement(struct ast_bo *bo, int domain)
|
||||
@ -310,24 +303,6 @@ void ast_ttm_placement(struct ast_bo *bo, int domain)
|
||||
bo->placement.num_busy_placement = c;
|
||||
}
|
||||
|
||||
int ast_bo_reserve(struct ast_bo *bo, bool no_wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS && ret != -EBUSY)
|
||||
DRM_ERROR("reserve failed %p\n", bo);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ast_bo_unreserve(struct ast_bo *bo)
|
||||
{
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
}
|
||||
|
||||
int ast_bo_create(struct drm_device *dev, int size, int align,
|
||||
uint32_t flags, struct ast_bo **pastbo)
|
||||
{
|
||||
|
@ -240,8 +240,25 @@ void cirrus_ttm_placement(struct cirrus_bo *bo, int domain);
|
||||
int cirrus_bo_create(struct drm_device *dev, int size, int align,
|
||||
uint32_t flags, struct cirrus_bo **pcirrusbo);
|
||||
int cirrus_mmap(struct file *filp, struct vm_area_struct *vma);
|
||||
int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait);
|
||||
void cirrus_bo_unreserve(struct cirrus_bo *bo);
|
||||
|
||||
static inline int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS && ret != -EBUSY)
|
||||
DRM_ERROR("reserve failed %p\n", bo);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void cirrus_bo_unreserve(struct cirrus_bo *bo)
|
||||
{
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
}
|
||||
|
||||
int cirrus_bo_push_sysram(struct cirrus_bo *bo);
|
||||
int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr);
|
||||
#endif /* __CIRRUS_DRV_H__ */
|
||||
|
@ -25,7 +25,7 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
|
||||
struct cirrus_bo *bo;
|
||||
int src_offset, dst_offset;
|
||||
int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;
|
||||
int ret;
|
||||
int ret = -EBUSY;
|
||||
bool unmap = false;
|
||||
bool store_for_later = false;
|
||||
int x2, y2;
|
||||
@ -39,7 +39,8 @@ static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
|
||||
* then the BO is being moved and we should
|
||||
* store up the damage until later.
|
||||
*/
|
||||
ret = cirrus_bo_reserve(bo, true);
|
||||
if (!in_interrupt())
|
||||
ret = cirrus_bo_reserve(bo, true);
|
||||
if (ret) {
|
||||
if (ret != -EBUSY)
|
||||
return;
|
||||
|
@ -271,9 +271,8 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
|
||||
return ret;
|
||||
}
|
||||
|
||||
cirrus->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0),
|
||||
DRM_MTRR_WC);
|
||||
cirrus->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0));
|
||||
|
||||
cirrus->mm_inited = true;
|
||||
return 0;
|
||||
@ -281,8 +280,6 @@ int cirrus_mm_init(struct cirrus_device *cirrus)
|
||||
|
||||
void cirrus_mm_fini(struct cirrus_device *cirrus)
|
||||
{
|
||||
struct drm_device *dev = cirrus->dev;
|
||||
|
||||
if (!cirrus->mm_inited)
|
||||
return;
|
||||
|
||||
@ -290,12 +287,8 @@ void cirrus_mm_fini(struct cirrus_device *cirrus)
|
||||
|
||||
cirrus_ttm_global_release(cirrus);
|
||||
|
||||
if (cirrus->fb_mtrr >= 0) {
|
||||
drm_mtrr_del(cirrus->fb_mtrr,
|
||||
pci_resource_start(dev->pdev, 0),
|
||||
pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
|
||||
cirrus->fb_mtrr = -1;
|
||||
}
|
||||
arch_phys_wc_del(cirrus->fb_mtrr);
|
||||
cirrus->fb_mtrr = 0;
|
||||
}
|
||||
|
||||
void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
|
||||
@ -315,24 +308,6 @@ void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
|
||||
bo->placement.num_busy_placement = c;
|
||||
}
|
||||
|
||||
int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
|
||||
if (ret) {
|
||||
if (ret != -ERESTARTSYS && ret != -EBUSY)
|
||||
DRM_ERROR("reserve failed %p\n", bo);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cirrus_bo_unreserve(struct cirrus_bo *bo)
|
||||
{
|
||||
ttm_bo_unreserve(&bo->bo);
|
||||
}
|
||||
|
||||
int cirrus_bo_create(struct drm_device *dev, int size, int align,
|
||||
uint32_t flags, struct cirrus_bo **pcirrusbo)
|
||||
{
|
||||
|
@ -210,12 +210,16 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
|
||||
if (drm_core_has_MTRR(dev)) {
|
||||
if (map->type == _DRM_FRAME_BUFFER ||
|
||||
(map->flags & _DRM_WRITE_COMBINING)) {
|
||||
map->mtrr = mtrr_add(map->offset, map->size,
|
||||
MTRR_TYPE_WRCOMB, 1);
|
||||
map->mtrr =
|
||||
arch_phys_wc_add(map->offset, map->size);
|
||||
}
|
||||
}
|
||||
if (map->type == _DRM_REGISTERS) {
|
||||
map->handle = ioremap(map->offset, map->size);
|
||||
if (map->flags & _DRM_WRITE_COMBINING)
|
||||
map->handle = ioremap_wc(map->offset,
|
||||
map->size);
|
||||
else
|
||||
map->handle = ioremap(map->offset, map->size);
|
||||
if (!map->handle) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
@ -410,6 +414,15 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
/* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */
|
||||
map->handle = (void *)(unsigned long)maplist->user_token;
|
||||
|
||||
/*
|
||||
* It appears that there are no users of this value whatsoever --
|
||||
* drmAddMap just discards it. Let's not encourage its use.
|
||||
* (Keeping drm_addmap_core's returned mtrr value would be wrong --
|
||||
* it's not a real mtrr index anymore.)
|
||||
*/
|
||||
map->mtrr = -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -451,11 +464,8 @@ int drm_rmmap_locked(struct drm_device *dev, struct drm_local_map *map)
|
||||
iounmap(map->handle);
|
||||
/* FALLTHROUGH */
|
||||
case _DRM_FRAME_BUFFER:
|
||||
if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
|
||||
int retcode;
|
||||
retcode = mtrr_del(map->mtrr, map->offset, map->size);
|
||||
DRM_DEBUG("mtrr_del=%d\n", retcode);
|
||||
}
|
||||
if (drm_core_has_MTRR(dev))
|
||||
arch_phys_wc_del(map->mtrr);
|
||||
break;
|
||||
case _DRM_SHM:
|
||||
vfree(map->handle);
|
||||
|
@ -29,6 +29,7 @@
|
||||
* Dave Airlie <airlied@linux.ie>
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
@ -91,7 +92,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
|
||||
|
||||
/* Avoid boilerplate. I'm tired of typing. */
|
||||
#define DRM_ENUM_NAME_FN(fnname, list) \
|
||||
char *fnname(int val) \
|
||||
const char *fnname(int val) \
|
||||
{ \
|
||||
int i; \
|
||||
for (i = 0; i < ARRAY_SIZE(list); i++) { \
|
||||
@ -104,7 +105,7 @@ EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
|
||||
/*
|
||||
* Global properties
|
||||
*/
|
||||
static struct drm_prop_enum_list drm_dpms_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_dpms_enum_list[] =
|
||||
{ { DRM_MODE_DPMS_ON, "On" },
|
||||
{ DRM_MODE_DPMS_STANDBY, "Standby" },
|
||||
{ DRM_MODE_DPMS_SUSPEND, "Suspend" },
|
||||
@ -116,7 +117,7 @@ DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
|
||||
/*
|
||||
* Optional properties
|
||||
*/
|
||||
static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SCALE_NONE, "None" },
|
||||
{ DRM_MODE_SCALE_FULLSCREEN, "Full" },
|
||||
@ -124,7 +125,7 @@ static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
|
||||
{ DRM_MODE_SCALE_ASPECT, "Full aspect" },
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_DITHERING_OFF, "Off" },
|
||||
{ DRM_MODE_DITHERING_ON, "On" },
|
||||
@ -134,7 +135,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
|
||||
/*
|
||||
* Non-global properties, but "required" for certain connectors.
|
||||
*/
|
||||
static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
|
||||
@ -143,7 +144,7 @@ static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
|
||||
|
||||
DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
|
||||
|
||||
static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
|
||||
@ -153,7 +154,7 @@ static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
|
||||
DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
|
||||
drm_dvi_i_subconnector_enum_list)
|
||||
|
||||
static struct drm_prop_enum_list drm_tv_select_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_tv_select_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
|
||||
@ -164,7 +165,7 @@ static struct drm_prop_enum_list drm_tv_select_enum_list[] =
|
||||
|
||||
DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
|
||||
|
||||
static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
|
||||
{
|
||||
{ DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
|
||||
{ DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
|
||||
@ -176,7 +177,7 @@ static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
|
||||
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
|
||||
drm_tv_subconnector_enum_list)
|
||||
|
||||
static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
|
||||
static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
|
||||
{ DRM_MODE_DIRTY_OFF, "Off" },
|
||||
{ DRM_MODE_DIRTY_ON, "On" },
|
||||
{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
|
||||
@ -184,7 +185,7 @@ static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
|
||||
|
||||
struct drm_conn_prop_enum_list {
|
||||
int type;
|
||||
char *name;
|
||||
const char *name;
|
||||
int count;
|
||||
};
|
||||
|
||||
@ -210,7 +211,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
|
||||
{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
|
||||
};
|
||||
|
||||
static struct drm_prop_enum_list drm_encoder_enum_list[] =
|
||||
static const struct drm_prop_enum_list drm_encoder_enum_list[] =
|
||||
{ { DRM_MODE_ENCODER_NONE, "None" },
|
||||
{ DRM_MODE_ENCODER_DAC, "DAC" },
|
||||
{ DRM_MODE_ENCODER_TMDS, "TMDS" },
|
||||
@ -219,7 +220,7 @@ static struct drm_prop_enum_list drm_encoder_enum_list[] =
|
||||
{ DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
|
||||
};
|
||||
|
||||
char *drm_get_encoder_name(struct drm_encoder *encoder)
|
||||
const char *drm_get_encoder_name(const struct drm_encoder *encoder)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
@ -230,7 +231,7 @@ char *drm_get_encoder_name(struct drm_encoder *encoder)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_encoder_name);
|
||||
|
||||
char *drm_get_connector_name(struct drm_connector *connector)
|
||||
const char *drm_get_connector_name(const struct drm_connector *connector)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
@ -241,7 +242,7 @@ char *drm_get_connector_name(struct drm_connector *connector)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_connector_name);
|
||||
|
||||
char *drm_get_connector_status_name(enum drm_connector_status status)
|
||||
const char *drm_get_connector_status_name(enum drm_connector_status status)
|
||||
{
|
||||
if (status == connector_status_connected)
|
||||
return "connected";
|
||||
@ -252,6 +253,28 @@ char *drm_get_connector_status_name(enum drm_connector_status status)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_connector_status_name);
|
||||
|
||||
static char printable_char(int c)
|
||||
{
|
||||
return isascii(c) && isprint(c) ? c : '?';
|
||||
}
|
||||
|
||||
const char *drm_get_format_name(uint32_t format)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%c%c%c%c %s-endian (0x%08x)",
|
||||
printable_char(format & 0xff),
|
||||
printable_char((format >> 8) & 0xff),
|
||||
printable_char((format >> 16) & 0xff),
|
||||
printable_char((format >> 24) & 0x7f),
|
||||
format & DRM_FORMAT_BIG_ENDIAN ? "big" : "little",
|
||||
format);
|
||||
|
||||
return buf;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_format_name);
|
||||
|
||||
/**
|
||||
* drm_mode_object_get - allocate a new modeset identifier
|
||||
* @dev: DRM device
|
||||
@ -569,16 +592,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
|
||||
}
|
||||
|
||||
list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
|
||||
if (plane->fb == fb) {
|
||||
/* should turn off the crtc */
|
||||
ret = plane->funcs->disable_plane(plane);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to disable plane with busy fb\n");
|
||||
/* disconnect the plane from the fb and crtc: */
|
||||
__drm_framebuffer_unreference(plane->fb);
|
||||
plane->fb = NULL;
|
||||
plane->crtc = NULL;
|
||||
}
|
||||
if (plane->fb == fb)
|
||||
drm_plane_force_disable(plane);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
@ -593,7 +608,7 @@ EXPORT_SYMBOL(drm_framebuffer_remove);
|
||||
* @crtc: CRTC object to init
|
||||
* @funcs: callbacks for the new CRTC
|
||||
*
|
||||
* Inits a new object created as base part of an driver crtc object.
|
||||
* Inits a new object created as base part of a driver crtc object.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure.
|
||||
@ -628,11 +643,12 @@ int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
EXPORT_SYMBOL(drm_crtc_init);
|
||||
|
||||
/**
|
||||
* drm_crtc_cleanup - Cleans up the core crtc usage.
|
||||
* drm_crtc_cleanup - Clean up the core crtc usage
|
||||
* @crtc: CRTC to cleanup
|
||||
*
|
||||
* Cleanup @crtc. Removes from drm modesetting space
|
||||
* does NOT free object, caller does that.
|
||||
* This function cleans up @crtc and removes it from the DRM mode setting
|
||||
* core. Note that the function does *not* free the crtc structure itself,
|
||||
* this is the responsibility of the caller.
|
||||
*/
|
||||
void drm_crtc_cleanup(struct drm_crtc *crtc)
|
||||
{
|
||||
@ -657,7 +673,7 @@ EXPORT_SYMBOL(drm_crtc_cleanup);
|
||||
void drm_mode_probed_add(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
list_add(&mode->head, &connector->probed_modes);
|
||||
list_add_tail(&mode->head, &connector->probed_modes);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_probed_add);
|
||||
|
||||
@ -803,6 +819,21 @@ void drm_encoder_cleanup(struct drm_encoder *encoder)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_encoder_cleanup);
|
||||
|
||||
/**
|
||||
* drm_plane_init - Initialise a new plane object
|
||||
* @dev: DRM device
|
||||
* @plane: plane object to init
|
||||
* @possible_crtcs: bitmask of possible CRTCs
|
||||
* @funcs: callbacks for the new plane
|
||||
* @formats: array of supported formats (%DRM_FORMAT_*)
|
||||
* @format_count: number of elements in @formats
|
||||
* @priv: plane is private (hidden from userspace)?
|
||||
*
|
||||
* Inits a new object created as base part of a driver plane object.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
unsigned long possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
@ -851,6 +882,14 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_init);
|
||||
|
||||
/**
|
||||
* drm_plane_cleanup - Clean up the core plane usage
|
||||
* @plane: plane to cleanup
|
||||
*
|
||||
* This function cleans up @plane and removes it from the DRM mode setting
|
||||
* core. Note that the function does *not* free the plane structure itself,
|
||||
* this is the responsibility of the caller.
|
||||
*/
|
||||
void drm_plane_cleanup(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
@ -867,6 +906,32 @@ void drm_plane_cleanup(struct drm_plane *plane)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_cleanup);
|
||||
|
||||
/**
|
||||
* drm_plane_force_disable - Forcibly disable a plane
|
||||
* @plane: plane to disable
|
||||
*
|
||||
* Forces the plane to be disabled.
|
||||
*
|
||||
* Used when the plane's current framebuffer is destroyed,
|
||||
* and when restoring fbdev mode.
|
||||
*/
|
||||
void drm_plane_force_disable(struct drm_plane *plane)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!plane->fb)
|
||||
return;
|
||||
|
||||
ret = plane->funcs->disable_plane(plane);
|
||||
if (ret)
|
||||
DRM_ERROR("failed to disable plane with busy fb\n");
|
||||
/* disconnect the plane from the fb and crtc: */
|
||||
__drm_framebuffer_unreference(plane->fb);
|
||||
plane->fb = NULL;
|
||||
plane->crtc = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_force_disable);
|
||||
|
||||
/**
|
||||
* drm_mode_create - create a new display mode
|
||||
* @dev: DRM device
|
||||
@ -1740,7 +1805,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
|
||||
|
||||
plane_resp->plane_id = plane->base.id;
|
||||
plane_resp->possible_crtcs = plane->possible_crtcs;
|
||||
plane_resp->gamma_size = plane->gamma_size;
|
||||
plane_resp->gamma_size = 0;
|
||||
|
||||
/*
|
||||
* This ioctl is called twice, once to determine how much space is
|
||||
@ -1834,7 +1899,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||
if (fb->pixel_format == plane->format_types[i])
|
||||
break;
|
||||
if (i == plane->format_count) {
|
||||
DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s\n",
|
||||
drm_get_format_name(fb->pixel_format));
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1906,18 +1972,31 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
|
||||
int drm_mode_set_config_internal(struct drm_mode_set *set)
|
||||
{
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
struct drm_framebuffer *fb, *old_fb;
|
||||
struct drm_framebuffer *fb;
|
||||
struct drm_crtc *tmp;
|
||||
int ret;
|
||||
|
||||
old_fb = crtc->fb;
|
||||
/*
|
||||
* NOTE: ->set_config can also disable other crtcs (if we steal all
|
||||
* connectors from it), hence we need to refcount the fbs across all
|
||||
* crtcs. Atomic modeset will have saner semantics ...
|
||||
*/
|
||||
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
|
||||
tmp->old_fb = tmp->fb;
|
||||
|
||||
fb = set->fb;
|
||||
|
||||
ret = crtc->funcs->set_config(set);
|
||||
if (ret == 0) {
|
||||
if (old_fb)
|
||||
drm_framebuffer_unreference(old_fb);
|
||||
if (fb)
|
||||
drm_framebuffer_reference(fb);
|
||||
/* crtc->fb must be updated by ->set_config, enforces this. */
|
||||
WARN_ON(fb != crtc->fb);
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
|
||||
if (tmp->fb)
|
||||
drm_framebuffer_reference(tmp->fb);
|
||||
if (tmp->old_fb)
|
||||
drm_framebuffer_unreference(tmp->old_fb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -2099,10 +2178,10 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
static int drm_mode_cursor_common(struct drm_device *dev,
|
||||
struct drm_mode_cursor2 *req,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_cursor *req = data;
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
@ -2122,13 +2201,17 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
|
||||
mutex_lock(&crtc->mutex);
|
||||
if (req->flags & DRM_MODE_CURSOR_BO) {
|
||||
if (!crtc->funcs->cursor_set) {
|
||||
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
}
|
||||
/* Turns off the cursor if handle is 0 */
|
||||
ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
|
||||
req->width, req->height);
|
||||
if (crtc->funcs->cursor_set2)
|
||||
ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
|
||||
req->width, req->height, req->hot_x, req->hot_y);
|
||||
else
|
||||
ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
|
||||
req->width, req->height);
|
||||
}
|
||||
|
||||
if (req->flags & DRM_MODE_CURSOR_MOVE) {
|
||||
@ -2143,6 +2226,25 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
mutex_unlock(&crtc->mutex);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
int drm_mode_cursor_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_cursor *req = data;
|
||||
struct drm_mode_cursor2 new_req;
|
||||
|
||||
memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
|
||||
new_req.hot_x = new_req.hot_y = 0;
|
||||
|
||||
return drm_mode_cursor_common(dev, &new_req, file_priv);
|
||||
}
|
||||
|
||||
int drm_mode_cursor2_ioctl(struct drm_device *dev,
|
||||
void *data, struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_mode_cursor2 *req = data;
|
||||
return drm_mode_cursor_common(dev, req, file_priv);
|
||||
}
|
||||
|
||||
/* Original addfb only supported RGB formats, so figure out which one */
|
||||
@ -2312,7 +2414,8 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
||||
|
||||
ret = format_check(r);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
|
||||
DRM_DEBUG_KMS("bad framebuffer format %s\n",
|
||||
drm_get_format_name(r->pixel_format));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -189,13 +189,14 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
|
||||
if (list_empty(&connector->modes))
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(mode, &connector->modes, head)
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
drm_mode_sort(&connector->modes);
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
|
||||
drm_get_connector_name(connector));
|
||||
list_for_each_entry(mode, &connector->modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||
drm_mode_debug_printmodeline(mode);
|
||||
}
|
||||
@ -564,14 +565,13 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
|
||||
DRM_DEBUG_KMS("\n");
|
||||
|
||||
if (!set)
|
||||
return -EINVAL;
|
||||
BUG_ON(!set);
|
||||
BUG_ON(!set->crtc);
|
||||
BUG_ON(!set->crtc->helper_private);
|
||||
|
||||
if (!set->crtc)
|
||||
return -EINVAL;
|
||||
|
||||
if (!set->crtc->helper_private)
|
||||
return -EINVAL;
|
||||
/* Enforce sane interface api - has been abused by the fb helper. */
|
||||
BUG_ON(!set->mode && set->fb);
|
||||
BUG_ON(set->fb && set->num_connectors == 0);
|
||||
|
||||
crtc_funcs = set->crtc->helper_private;
|
||||
|
||||
@ -645,11 +645,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
mode_changed = true;
|
||||
} else if (set->fb == NULL) {
|
||||
mode_changed = true;
|
||||
} else if (set->fb->depth != set->crtc->fb->depth) {
|
||||
mode_changed = true;
|
||||
} else if (set->fb->bits_per_pixel !=
|
||||
set->crtc->fb->bits_per_pixel) {
|
||||
mode_changed = true;
|
||||
} else if (set->fb->pixel_format !=
|
||||
set->crtc->fb->pixel_format) {
|
||||
mode_changed = true;
|
||||
@ -759,12 +754,6 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
|
||||
for (i = 0; i < set->num_connectors; i++) {
|
||||
DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
|
||||
drm_get_connector_name(set->connectors[i]));
|
||||
set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
|
||||
}
|
||||
}
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
} else if (fb_changed) {
|
||||
@ -782,6 +771,22 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* crtc set_config helpers implicit set the crtc and all connected
|
||||
* encoders to DPMS on for a full mode set. But for just an fb update it
|
||||
* doesn't do that. To not confuse userspace, do an explicit DPMS_ON
|
||||
* unconditionally. This will also ensure driver internal dpms state is
|
||||
* consistent again.
|
||||
*/
|
||||
if (set->crtc->enabled) {
|
||||
DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
|
||||
for (i = 0; i < set->num_connectors; i++) {
|
||||
DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
|
||||
drm_get_connector_name(set->connectors[i]));
|
||||
set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(save_connectors);
|
||||
kfree(save_encoders);
|
||||
kfree(save_crtcs);
|
||||
|
@ -166,6 +166,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
|
||||
};
|
||||
|
||||
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
|
||||
|
@ -968,6 +968,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
|
||||
u8 csum = 0;
|
||||
struct edid *edid = (struct edid *)raw_edid;
|
||||
|
||||
if (WARN_ON(!raw_edid))
|
||||
return false;
|
||||
|
||||
if (edid_fixup > 8 || edid_fixup < 0)
|
||||
edid_fixup = 6;
|
||||
|
||||
@ -1010,15 +1013,15 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid)
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
bad:
|
||||
if (raw_edid && print_bad_edid) {
|
||||
if (print_bad_edid) {
|
||||
printk(KERN_ERR "Raw EDID:\n");
|
||||
print_hex_dump(KERN_ERR, " \t", DUMP_PREFIX_NONE, 16, 1,
|
||||
raw_edid, EDID_LENGTH, false);
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_edid_block_valid);
|
||||
|
||||
@ -1706,11 +1709,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
|
||||
return NULL;
|
||||
|
||||
if (pt->misc & DRM_EDID_PT_STEREO) {
|
||||
printk(KERN_WARNING "stereo mode not supported\n");
|
||||
DRM_DEBUG_KMS("stereo mode not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
|
||||
printk(KERN_WARNING "composite sync not supported\n");
|
||||
DRM_DEBUG_KMS("composite sync not supported\n");
|
||||
}
|
||||
|
||||
/* it is incorrect if hsync/vsync width is zero */
|
||||
@ -2321,6 +2324,31 @@ u8 *drm_find_cea_extension(struct edid *edid)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_find_cea_extension);
|
||||
|
||||
/*
|
||||
* Calculate the alternate clock for the CEA mode
|
||||
* (60Hz vs. 59.94Hz etc.)
|
||||
*/
|
||||
static unsigned int
|
||||
cea_mode_alternate_clock(const struct drm_display_mode *cea_mode)
|
||||
{
|
||||
unsigned int clock = cea_mode->clock;
|
||||
|
||||
if (cea_mode->vrefresh % 6 != 0)
|
||||
return clock;
|
||||
|
||||
/*
|
||||
* edid_cea_modes contains the 59.94Hz
|
||||
* variant for 240 and 480 line modes,
|
||||
* and the 60Hz variant otherwise.
|
||||
*/
|
||||
if (cea_mode->vdisplay == 240 || cea_mode->vdisplay == 480)
|
||||
clock = clock * 1001 / 1000;
|
||||
else
|
||||
clock = DIV_ROUND_UP(clock * 1000, 1001);
|
||||
|
||||
return clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_match_cea_mode - look for a CEA mode matching given mode
|
||||
* @to_match: display mode
|
||||
@ -2339,21 +2367,9 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
|
||||
const struct drm_display_mode *cea_mode = &edid_cea_modes[mode];
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
clock1 = clock2 = cea_mode->clock;
|
||||
|
||||
/* Check both 60Hz and 59.94Hz */
|
||||
if (cea_mode->vrefresh % 6 == 0) {
|
||||
/*
|
||||
* edid_cea_modes contains the 59.94Hz
|
||||
* variant for 240 and 480 line modes,
|
||||
* and the 60Hz variant otherwise.
|
||||
*/
|
||||
if (cea_mode->vdisplay == 240 ||
|
||||
cea_mode->vdisplay == 480)
|
||||
clock1 = clock1 * 1001 / 1000;
|
||||
else
|
||||
clock2 = DIV_ROUND_UP(clock2 * 1000, 1001);
|
||||
}
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
|
||||
if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
|
||||
KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
|
||||
@ -2364,6 +2380,66 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_match_cea_mode);
|
||||
|
||||
static int
|
||||
add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode, *tmp;
|
||||
LIST_HEAD(list);
|
||||
int modes = 0;
|
||||
|
||||
/* Don't add CEA modes if the CEA extension block is missing */
|
||||
if (!drm_find_cea_extension(edid))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Go through all probed modes and create a new mode
|
||||
* with the alternate clock for certain CEA modes.
|
||||
*/
|
||||
list_for_each_entry(mode, &connector->probed_modes, head) {
|
||||
const struct drm_display_mode *cea_mode;
|
||||
struct drm_display_mode *newmode;
|
||||
u8 cea_mode_idx = drm_match_cea_mode(mode) - 1;
|
||||
unsigned int clock1, clock2;
|
||||
|
||||
if (cea_mode_idx >= ARRAY_SIZE(edid_cea_modes))
|
||||
continue;
|
||||
|
||||
cea_mode = &edid_cea_modes[cea_mode_idx];
|
||||
|
||||
clock1 = cea_mode->clock;
|
||||
clock2 = cea_mode_alternate_clock(cea_mode);
|
||||
|
||||
if (clock1 == clock2)
|
||||
continue;
|
||||
|
||||
if (mode->clock != clock1 && mode->clock != clock2)
|
||||
continue;
|
||||
|
||||
newmode = drm_mode_duplicate(dev, cea_mode);
|
||||
if (!newmode)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The current mode could be either variant. Make
|
||||
* sure to pick the "other" clock for the new mode.
|
||||
*/
|
||||
if (mode->clock != clock1)
|
||||
newmode->clock = clock1;
|
||||
else
|
||||
newmode->clock = clock2;
|
||||
|
||||
list_add_tail(&newmode->head, &list);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(mode, tmp, &list, head) {
|
||||
list_del(&mode->head);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
modes++;
|
||||
}
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
static int
|
||||
do_cea_modes (struct drm_connector *connector, u8 *db, u8 len)
|
||||
@ -2946,6 +3022,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
||||
if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
|
||||
num_modes += add_inferred_modes(connector, edid);
|
||||
num_modes += add_cea_modes(connector, edid);
|
||||
num_modes += add_alternate_cea_modes(connector, edid);
|
||||
|
||||
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
|
||||
edid_fixup_preferred(connector, quirks);
|
||||
|
@ -186,12 +186,11 @@ static u8 *edid_load(struct drm_connector *connector, char *name,
|
||||
goto relfw_out;
|
||||
}
|
||||
|
||||
edid = kmalloc(fwsize, GFP_KERNEL);
|
||||
edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
|
||||
if (edid == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto relfw_out;
|
||||
}
|
||||
memcpy(edid, fwdata, fwsize);
|
||||
|
||||
if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
|
||||
connector->bad_edid_counter++;
|
||||
|
@ -168,6 +168,9 @@ static void drm_fb_helper_save_lut_atomic(struct drm_crtc *crtc, struct drm_fb_h
|
||||
uint16_t *r_base, *g_base, *b_base;
|
||||
int i;
|
||||
|
||||
if (helper->funcs->gamma_get == NULL)
|
||||
return;
|
||||
|
||||
r_base = crtc->gamma_store;
|
||||
g_base = r_base + crtc->gamma_size;
|
||||
b_base = g_base + crtc->gamma_size;
|
||||
@ -284,13 +287,27 @@ EXPORT_SYMBOL(drm_fb_helper_debug_leave);
|
||||
*/
|
||||
bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_plane *plane;
|
||||
bool error = false;
|
||||
int i, ret;
|
||||
int i;
|
||||
|
||||
drm_warn_on_modeset_not_all_locked(fb_helper->dev);
|
||||
drm_warn_on_modeset_not_all_locked(dev);
|
||||
|
||||
list_for_each_entry(plane, &dev->mode_config.plane_list, head)
|
||||
drm_plane_force_disable(plane);
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
struct drm_crtc *crtc = mode_set->crtc;
|
||||
int ret;
|
||||
|
||||
if (crtc->funcs->cursor_set) {
|
||||
ret = crtc->funcs->cursor_set(crtc, NULL, 0, 0, 0);
|
||||
if (ret)
|
||||
error = true;
|
||||
}
|
||||
|
||||
ret = drm_mode_set_config_internal(mode_set);
|
||||
if (ret)
|
||||
error = true;
|
||||
@ -583,6 +600,14 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The driver really shouldn't advertise pseudo/directcolor
|
||||
* visuals if it can't deal with the palette.
|
||||
*/
|
||||
if (WARN_ON(!fb_helper->funcs->gamma_set ||
|
||||
!fb_helper->funcs->gamma_get))
|
||||
return -EINVAL;
|
||||
|
||||
pindex = regno;
|
||||
|
||||
if (fb->bits_per_pixel == 16) {
|
||||
@ -626,12 +651,19 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_crtc_helper_funcs *crtc_funcs;
|
||||
u16 *red, *green, *blue, *transp;
|
||||
struct drm_crtc *crtc;
|
||||
int i, j, rc = 0;
|
||||
int start;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
if (!drm_fb_helper_is_bound(fb_helper)) {
|
||||
drm_modeset_unlock_all(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
crtc = fb_helper->crtc_info[i].mode_set.crtc;
|
||||
crtc_funcs = crtc->helper_private;
|
||||
@ -654,10 +686,13 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
||||
|
||||
rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
|
||||
if (rc)
|
||||
return rc;
|
||||
goto out;
|
||||
}
|
||||
crtc_funcs->load_lut(crtc);
|
||||
if (crtc_funcs->load_lut)
|
||||
crtc_funcs->load_lut(crtc);
|
||||
}
|
||||
out:
|
||||
drm_modeset_unlock_all(dev);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_setcmap);
|
||||
|
@ -271,6 +271,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
priv->uid = current_euid();
|
||||
priv->pid = get_pid(task_pid(current));
|
||||
priv->minor = idr_find(&drm_minors_idr, minor_id);
|
||||
if (!priv->minor) {
|
||||
ret = -ENODEV;
|
||||
goto out_put_pid;
|
||||
}
|
||||
|
||||
priv->ioctl_count = 0;
|
||||
/* for compatibility root is always authenticated */
|
||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
||||
@ -292,7 +297,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
if (dev->driver->open) {
|
||||
ret = dev->driver->open(dev, priv);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
goto out_prime_destroy;
|
||||
}
|
||||
|
||||
|
||||
@ -304,7 +309,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
if (!priv->minor->master) {
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
ret = -ENOMEM;
|
||||
goto out_free;
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
priv->is_master = 1;
|
||||
@ -322,7 +327,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
drm_master_put(&priv->minor->master);
|
||||
drm_master_put(&priv->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
goto out_free;
|
||||
goto out_close;
|
||||
}
|
||||
}
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
@ -333,7 +338,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
drm_master_put(&priv->minor->master);
|
||||
drm_master_put(&priv->master);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
goto out_free;
|
||||
goto out_close;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@ -367,7 +372,17 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
out_free:
|
||||
|
||||
out_close:
|
||||
if (dev->driver->postclose)
|
||||
dev->driver->postclose(dev, priv);
|
||||
out_prime_destroy:
|
||||
if (drm_core_check_feature(dev, DRIVER_PRIME))
|
||||
drm_prime_destroy_file_private(&priv->prime);
|
||||
if (dev->driver->driver_features & DRIVER_GEM)
|
||||
drm_gem_release(dev, priv);
|
||||
out_put_pid:
|
||||
put_pid(priv->pid);
|
||||
kfree(priv);
|
||||
filp->private_data = NULL;
|
||||
return ret;
|
||||
|
@ -108,12 +108,8 @@ drm_gem_init(struct drm_device *dev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
|
||||
DRM_FILE_PAGE_OFFSET_SIZE)) {
|
||||
drm_ht_remove(&mm->offset_hash);
|
||||
kfree(mm);
|
||||
return -ENOMEM;
|
||||
}
|
||||
drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
|
||||
DRM_FILE_PAGE_OFFSET_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -453,25 +449,21 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
|
||||
spin_lock(&dev->object_name_lock);
|
||||
if (!obj->name) {
|
||||
ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT);
|
||||
obj->name = ret;
|
||||
args->name = (uint64_t) obj->name;
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
idr_preload_end();
|
||||
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
ret = 0;
|
||||
|
||||
obj->name = ret;
|
||||
|
||||
/* Allocate a reference for the name table. */
|
||||
drm_gem_object_reference(obj);
|
||||
} else {
|
||||
args->name = (uint64_t) obj->name;
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
idr_preload_end();
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
args->name = (uint64_t) obj->name;
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
spin_unlock(&dev->object_name_lock);
|
||||
idr_preload_end();
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
return ret;
|
||||
}
|
||||
@ -644,6 +636,59 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_vm_close);
|
||||
|
||||
/**
|
||||
* drm_gem_mmap_obj - memory map a GEM object
|
||||
* @obj: the GEM object to map
|
||||
* @obj_size: the object size to be mapped, in bytes
|
||||
* @vma: VMA for the area to be mapped
|
||||
*
|
||||
* Set up the VMA to prepare mapping of the GEM object using the gem_vm_ops
|
||||
* provided by the driver. Depending on their requirements, drivers can either
|
||||
* provide a fault handler in their gem_vm_ops (in which case any accesses to
|
||||
* the object will be trapped, to perform migration, GTT binding, surface
|
||||
* register allocation, or performance monitoring), or mmap the buffer memory
|
||||
* synchronously after calling drm_gem_mmap_obj.
|
||||
*
|
||||
* This function is mainly intended to implement the DMABUF mmap operation, when
|
||||
* the GEM object is not looked up based on its fake offset. To implement the
|
||||
* DRM mmap operation, drivers should use the drm_gem_mmap() function.
|
||||
*
|
||||
* NOTE: This function has to be protected with dev->struct_mutex
|
||||
*
|
||||
* Return 0 or success or -EINVAL if the object size is smaller than the VMA
|
||||
* size, or if no gem_vm_ops are provided.
|
||||
*/
|
||||
int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
lockdep_assert_held(&dev->struct_mutex);
|
||||
|
||||
/* Check for valid size. */
|
||||
if (obj_size < vma->vm_end - vma->vm_start)
|
||||
return -EINVAL;
|
||||
|
||||
if (!dev->driver->gem_vm_ops)
|
||||
return -EINVAL;
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
|
||||
vma->vm_ops = dev->driver->gem_vm_ops;
|
||||
vma->vm_private_data = obj;
|
||||
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
|
||||
|
||||
/* Take a ref for this mapping of the object, so that the fault
|
||||
* handler can dereference the mmap offset's pointer to the object.
|
||||
* This reference is cleaned up by the corresponding vm_close
|
||||
* (which should happen whether the vma was created by this call, or
|
||||
* by a vm_open due to mremap or partial unmap or whatever).
|
||||
*/
|
||||
drm_gem_object_reference(obj);
|
||||
|
||||
drm_vm_open_locked(dev, vma);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_mmap_obj);
|
||||
|
||||
/**
|
||||
* drm_gem_mmap - memory map routine for GEM objects
|
||||
@ -653,11 +698,9 @@ EXPORT_SYMBOL(drm_gem_vm_close);
|
||||
* If a driver supports GEM object mapping, mmap calls on the DRM file
|
||||
* descriptor will end up here.
|
||||
*
|
||||
* If we find the object based on the offset passed in (vma->vm_pgoff will
|
||||
* Look up the GEM object based on the offset passed in (vma->vm_pgoff will
|
||||
* contain the fake offset we created when the GTT map ioctl was called on
|
||||
* the object), we set up the driver fault handler so that any accesses
|
||||
* to the object can be trapped, to perform migration, GTT binding, surface
|
||||
* register allocation, or performance monitoring.
|
||||
* the object) and map it with a call to drm_gem_mmap_obj().
|
||||
*/
|
||||
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
@ -665,7 +708,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
struct drm_device *dev = priv->minor->dev;
|
||||
struct drm_gem_mm *mm = dev->mm_private;
|
||||
struct drm_local_map *map = NULL;
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_hash_item *hash;
|
||||
int ret = 0;
|
||||
|
||||
@ -686,32 +728,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* Check for valid size. */
|
||||
if (map->size < vma->vm_end - vma->vm_start) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
obj = map->handle;
|
||||
if (!obj->dev->driver->gem_vm_ops) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
|
||||
vma->vm_ops = obj->dev->driver->gem_vm_ops;
|
||||
vma->vm_private_data = map->handle;
|
||||
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
|
||||
|
||||
/* Take a ref for this mapping of the object, so that the fault
|
||||
* handler can dereference the mmap offset's pointer to the object.
|
||||
* This reference is cleaned up by the corresponding vm_close
|
||||
* (which should happen whether the vma was created by this call, or
|
||||
* by a vm_open due to mremap or partial unmap or whatever).
|
||||
*/
|
||||
drm_gem_object_reference(obj);
|
||||
|
||||
drm_vm_open_locked(dev, vma);
|
||||
ret = drm_gem_mmap_obj(map->handle, map->size, vma);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
@ -32,11 +33,44 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
|
||||
return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
static void drm_gem_cma_buf_destroy(struct drm_device *drm,
|
||||
struct drm_gem_cma_object *cma_obj)
|
||||
/*
|
||||
* __drm_gem_cma_create - Create a GEM CMA object without allocating memory
|
||||
* @drm: The drm device
|
||||
* @size: The GEM object size
|
||||
*
|
||||
* This function creates and initializes a GEM CMA object of the given size, but
|
||||
* doesn't allocate any memory to back the object.
|
||||
*
|
||||
* Return a struct drm_gem_cma_object* on success or ERR_PTR values on failure.
|
||||
*/
|
||||
static struct drm_gem_cma_object *
|
||||
__drm_gem_cma_create(struct drm_device *drm, unsigned int size)
|
||||
{
|
||||
dma_free_writecombine(drm->dev, cma_obj->base.size, cma_obj->vaddr,
|
||||
cma_obj->paddr);
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret;
|
||||
|
||||
cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
|
||||
if (!cma_obj)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
gem_obj = &cma_obj->base;
|
||||
|
||||
ret = drm_gem_object_init(drm, gem_obj, size);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
ret = drm_gem_create_mmap_offset(gem_obj);
|
||||
if (ret) {
|
||||
drm_gem_object_release(gem_obj);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return cma_obj;
|
||||
|
||||
error:
|
||||
kfree(cma_obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -49,44 +83,42 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
||||
unsigned int size)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
struct sg_table *sgt = NULL;
|
||||
int ret;
|
||||
|
||||
size = round_up(size, PAGE_SIZE);
|
||||
|
||||
cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
|
||||
if (!cma_obj)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
cma_obj = __drm_gem_cma_create(drm, size);
|
||||
if (IS_ERR(cma_obj))
|
||||
return cma_obj;
|
||||
|
||||
cma_obj->vaddr = dma_alloc_writecombine(drm->dev, size,
|
||||
&cma_obj->paddr, GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!cma_obj->vaddr) {
|
||||
dev_err(drm->dev, "failed to allocate buffer with size %d\n", size);
|
||||
dev_err(drm->dev, "failed to allocate buffer with size %d\n",
|
||||
size);
|
||||
ret = -ENOMEM;
|
||||
goto err_dma_alloc;
|
||||
goto error;
|
||||
}
|
||||
|
||||
gem_obj = &cma_obj->base;
|
||||
sgt = kzalloc(sizeof(*cma_obj->sgt), GFP_KERNEL);
|
||||
if (sgt == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = drm_gem_object_init(drm, gem_obj, size);
|
||||
if (ret)
|
||||
goto err_obj_init;
|
||||
ret = dma_get_sgtable(drm->dev, sgt, cma_obj->vaddr,
|
||||
cma_obj->paddr, size);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = drm_gem_create_mmap_offset(gem_obj);
|
||||
if (ret)
|
||||
goto err_create_mmap_offset;
|
||||
cma_obj->sgt = sgt;
|
||||
|
||||
return cma_obj;
|
||||
|
||||
err_create_mmap_offset:
|
||||
drm_gem_object_release(gem_obj);
|
||||
|
||||
err_obj_init:
|
||||
drm_gem_cma_buf_destroy(drm, cma_obj);
|
||||
|
||||
err_dma_alloc:
|
||||
kfree(cma_obj);
|
||||
|
||||
error:
|
||||
kfree(sgt);
|
||||
drm_gem_cma_free_object(&cma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
|
||||
@ -143,11 +175,20 @@ void drm_gem_cma_free_object(struct drm_gem_object *gem_obj)
|
||||
if (gem_obj->map_list.map)
|
||||
drm_gem_free_mmap_offset(gem_obj);
|
||||
|
||||
drm_gem_object_release(gem_obj);
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(gem_obj);
|
||||
|
||||
drm_gem_cma_buf_destroy(gem_obj->dev, cma_obj);
|
||||
if (cma_obj->vaddr) {
|
||||
dma_free_writecombine(gem_obj->dev->dev, cma_obj->base.size,
|
||||
cma_obj->vaddr, cma_obj->paddr);
|
||||
if (cma_obj->sgt) {
|
||||
sg_free_table(cma_obj->sgt);
|
||||
kfree(cma_obj->sgt);
|
||||
}
|
||||
} else if (gem_obj->import_attach) {
|
||||
drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
|
||||
}
|
||||
|
||||
drm_gem_object_release(gem_obj);
|
||||
|
||||
kfree(cma_obj);
|
||||
}
|
||||
@ -174,10 +215,7 @@ int drm_gem_cma_dumb_create(struct drm_file *file_priv,
|
||||
|
||||
cma_obj = drm_gem_cma_create_with_handle(file_priv, dev,
|
||||
args->size, &args->handle);
|
||||
if (IS_ERR(cma_obj))
|
||||
return PTR_ERR(cma_obj);
|
||||
|
||||
return 0;
|
||||
return PTR_RET(cma_obj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
|
||||
|
||||
@ -215,13 +253,26 @@ const struct vm_operations_struct drm_gem_cma_vm_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
|
||||
|
||||
static int drm_gem_cma_mmap_obj(struct drm_gem_cma_object *cma_obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_gem_cma_mmap - (struct file_operation)->mmap callback function
|
||||
*/
|
||||
int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *gem_obj;
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret;
|
||||
|
||||
ret = drm_gem_mmap(filp, vma);
|
||||
@ -231,12 +282,7 @@ int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
gem_obj = vma->vm_private_data;
|
||||
cma_obj = to_drm_gem_cma_obj(gem_obj);
|
||||
|
||||
ret = remap_pfn_range(vma, vma->vm_start, cma_obj->paddr >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
return ret;
|
||||
return drm_gem_cma_mmap_obj(cma_obj, vma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
|
||||
|
||||
@ -270,3 +316,289 @@ void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_describe);
|
||||
#endif
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* DMA-BUF
|
||||
*/
|
||||
|
||||
struct drm_gem_cma_dmabuf_attachment {
|
||||
struct sg_table sgt;
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
static int drm_gem_cma_dmabuf_attach(struct dma_buf *dmabuf, struct device *dev,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_cma_dmabuf_attachment *cma_attach;
|
||||
|
||||
cma_attach = kzalloc(sizeof(*cma_attach), GFP_KERNEL);
|
||||
if (!cma_attach)
|
||||
return -ENOMEM;
|
||||
|
||||
cma_attach->dir = DMA_NONE;
|
||||
attach->priv = cma_attach;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_gem_cma_dmabuf_detach(struct dma_buf *dmabuf,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_gem_cma_dmabuf_attachment *cma_attach = attach->priv;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (cma_attach == NULL)
|
||||
return;
|
||||
|
||||
sgt = &cma_attach->sgt;
|
||||
|
||||
if (cma_attach->dir != DMA_NONE)
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
|
||||
cma_attach->dir);
|
||||
|
||||
sg_free_table(sgt);
|
||||
kfree(cma_attach);
|
||||
attach->priv = NULL;
|
||||
}
|
||||
|
||||
static struct sg_table *
|
||||
drm_gem_cma_dmabuf_map(struct dma_buf_attachment *attach,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct drm_gem_cma_dmabuf_attachment *cma_attach = attach->priv;
|
||||
struct drm_gem_cma_object *cma_obj = attach->dmabuf->priv;
|
||||
struct drm_device *drm = cma_obj->base.dev;
|
||||
struct scatterlist *rd, *wr;
|
||||
struct sg_table *sgt;
|
||||
unsigned int i;
|
||||
int nents, ret;
|
||||
|
||||
DRM_DEBUG_PRIME("\n");
|
||||
|
||||
if (WARN_ON(dir == DMA_NONE))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Return the cached mapping when possible. */
|
||||
if (cma_attach->dir == dir)
|
||||
return &cma_attach->sgt;
|
||||
|
||||
/* Two mappings with different directions for the same attachment are
|
||||
* not allowed.
|
||||
*/
|
||||
if (WARN_ON(cma_attach->dir != DMA_NONE))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
sgt = &cma_attach->sgt;
|
||||
|
||||
ret = sg_alloc_table(sgt, cma_obj->sgt->orig_nents, GFP_KERNEL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to alloc sgt.\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
mutex_lock(&drm->struct_mutex);
|
||||
|
||||
rd = cma_obj->sgt->sgl;
|
||||
wr = sgt->sgl;
|
||||
for (i = 0; i < sgt->orig_nents; ++i) {
|
||||
sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
|
||||
rd = sg_next(rd);
|
||||
wr = sg_next(wr);
|
||||
}
|
||||
|
||||
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
|
||||
if (!nents) {
|
||||
DRM_ERROR("failed to map sgl with iommu.\n");
|
||||
sg_free_table(sgt);
|
||||
sgt = ERR_PTR(-EIO);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cma_attach->dir = dir;
|
||||
attach->priv = cma_attach;
|
||||
|
||||
DRM_DEBUG_PRIME("buffer size = %zu\n", cma_obj->base.size);
|
||||
|
||||
done:
|
||||
mutex_unlock(&drm->struct_mutex);
|
||||
return sgt;
|
||||
}
|
||||
|
||||
static void drm_gem_cma_dmabuf_unmap(struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
/* Nothing to do. */
|
||||
}
|
||||
|
||||
static void drm_gem_cma_dmabuf_release(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = dmabuf->priv;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* drm_gem_cma_dmabuf_release() call means that file object's
|
||||
* f_count is 0 and it calls drm_gem_object_handle_unreference()
|
||||
* to drop the references that these values had been increased
|
||||
* at drm_prime_handle_to_fd()
|
||||
*/
|
||||
if (cma_obj->base.export_dma_buf == dmabuf) {
|
||||
cma_obj->base.export_dma_buf = NULL;
|
||||
|
||||
/*
|
||||
* drop this gem object refcount to release allocated buffer
|
||||
* and resources.
|
||||
*/
|
||||
drm_gem_object_unreference_unlocked(&cma_obj->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void *drm_gem_cma_dmabuf_kmap_atomic(struct dma_buf *dmabuf,
|
||||
unsigned long page_num)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void drm_gem_cma_dmabuf_kunmap_atomic(struct dma_buf *dmabuf,
|
||||
unsigned long page_num, void *addr)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void *drm_gem_cma_dmabuf_kmap(struct dma_buf *dmabuf,
|
||||
unsigned long page_num)
|
||||
{
|
||||
/* TODO */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void drm_gem_cma_dmabuf_kunmap(struct dma_buf *dmabuf,
|
||||
unsigned long page_num, void *addr)
|
||||
{
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static int drm_gem_cma_dmabuf_mmap(struct dma_buf *dmabuf,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = dmabuf->priv;
|
||||
struct drm_gem_object *gem_obj = &cma_obj->base;
|
||||
struct drm_device *dev = gem_obj->dev;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
ret = drm_gem_mmap_obj(gem_obj, gem_obj->size, vma);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return drm_gem_cma_mmap_obj(cma_obj, vma);
|
||||
}
|
||||
|
||||
static void *drm_gem_cma_dmabuf_vmap(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = dmabuf->priv;
|
||||
|
||||
return cma_obj->vaddr;
|
||||
}
|
||||
|
||||
static struct dma_buf_ops drm_gem_cma_dmabuf_ops = {
|
||||
.attach = drm_gem_cma_dmabuf_attach,
|
||||
.detach = drm_gem_cma_dmabuf_detach,
|
||||
.map_dma_buf = drm_gem_cma_dmabuf_map,
|
||||
.unmap_dma_buf = drm_gem_cma_dmabuf_unmap,
|
||||
.kmap = drm_gem_cma_dmabuf_kmap,
|
||||
.kmap_atomic = drm_gem_cma_dmabuf_kmap_atomic,
|
||||
.kunmap = drm_gem_cma_dmabuf_kunmap,
|
||||
.kunmap_atomic = drm_gem_cma_dmabuf_kunmap_atomic,
|
||||
.mmap = drm_gem_cma_dmabuf_mmap,
|
||||
.vmap = drm_gem_cma_dmabuf_vmap,
|
||||
.release = drm_gem_cma_dmabuf_release,
|
||||
};
|
||||
|
||||
struct dma_buf *drm_gem_cma_dmabuf_export(struct drm_device *drm,
|
||||
struct drm_gem_object *obj, int flags)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
|
||||
|
||||
return dma_buf_export(cma_obj, &drm_gem_cma_dmabuf_ops,
|
||||
cma_obj->base.size, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_dmabuf_export);
|
||||
|
||||
struct drm_gem_object *drm_gem_cma_dmabuf_import(struct drm_device *drm,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct dma_buf_attachment *attach;
|
||||
struct sg_table *sgt;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/* is this one of own objects? */
|
||||
if (dma_buf->ops == &drm_gem_cma_dmabuf_ops) {
|
||||
struct drm_gem_object *obj;
|
||||
|
||||
cma_obj = dma_buf->priv;
|
||||
obj = &cma_obj->base;
|
||||
|
||||
/* is it from our device? */
|
||||
if (obj->dev == drm) {
|
||||
/*
|
||||
* Importing dmabuf exported from out own gem increases
|
||||
* refcount on gem itself instead of f_count of dmabuf.
|
||||
*/
|
||||
drm_gem_object_reference(obj);
|
||||
dma_buf_put(dma_buf);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a CMA GEM buffer. */
|
||||
cma_obj = __drm_gem_cma_create(drm, dma_buf->size);
|
||||
if (IS_ERR(cma_obj))
|
||||
return ERR_PTR(PTR_ERR(cma_obj));
|
||||
|
||||
/* Attach to the buffer and map it. Make sure the mapping is contiguous
|
||||
* on the device memory bus, as that's all we support.
|
||||
*/
|
||||
attach = dma_buf_attach(dma_buf, drm->dev);
|
||||
if (IS_ERR(attach)) {
|
||||
ret = -EINVAL;
|
||||
goto error_gem_free;
|
||||
}
|
||||
|
||||
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR_OR_NULL(sgt)) {
|
||||
ret = sgt ? PTR_ERR(sgt) : -ENOMEM;
|
||||
goto error_buf_detach;
|
||||
}
|
||||
|
||||
if (sgt->nents != 1) {
|
||||
ret = -EINVAL;
|
||||
goto error_buf_unmap;
|
||||
}
|
||||
|
||||
cma_obj->base.import_attach = attach;
|
||||
cma_obj->paddr = sg_dma_address(sgt->sgl);
|
||||
cma_obj->sgt = sgt;
|
||||
|
||||
DRM_DEBUG_PRIME("dma_addr = 0x%x, size = %zu\n", cma_obj->paddr,
|
||||
dma_buf->size);
|
||||
|
||||
return &cma_obj->base;
|
||||
|
||||
error_buf_unmap:
|
||||
dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
|
||||
error_buf_detach:
|
||||
dma_buf_detach(dma_buf, attach);
|
||||
error_gem_free:
|
||||
drm_gem_cma_free_object(&cma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_dmabuf_import);
|
||||
|
@ -38,6 +38,9 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
#ifdef CONFIG_X86
|
||||
#include <asm/mtrr.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Get the bus id.
|
||||
@ -181,7 +184,17 @@ int drm_getmap(struct drm_device *dev, void *data,
|
||||
map->type = r_list->map->type;
|
||||
map->flags = r_list->map->flags;
|
||||
map->handle = (void *)(unsigned long) r_list->user_token;
|
||||
map->mtrr = r_list->map->mtrr;
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
/*
|
||||
* There appears to be exactly one user of the mtrr index: dritest.
|
||||
* It's easy enough to keep it working on non-PAT systems.
|
||||
*/
|
||||
map->mtrr = phys_wc_to_mtrr_index(r_list->map->mtrr);
|
||||
#else
|
||||
map->mtrr = -1;
|
||||
#endif
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -669,7 +669,7 @@ int drm_mm_clean(struct drm_mm * mm)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_clean);
|
||||
|
||||
int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
|
||||
void drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
|
||||
{
|
||||
INIT_LIST_HEAD(&mm->hole_stack);
|
||||
INIT_LIST_HEAD(&mm->unused_nodes);
|
||||
@ -690,8 +690,6 @@ int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
|
||||
list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
|
||||
|
||||
mm->color_adjust = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_init);
|
||||
|
||||
@ -699,8 +697,8 @@ void drm_mm_takedown(struct drm_mm * mm)
|
||||
{
|
||||
struct drm_mm_node *entry, *next;
|
||||
|
||||
if (!list_empty(&mm->head_node.node_list)) {
|
||||
DRM_ERROR("Memory manager not clean. Delaying takedown\n");
|
||||
if (WARN(!list_empty(&mm->head_node.node_list),
|
||||
"Memory manager not clean. Delaying takedown\n")) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -716,36 +714,37 @@ void drm_mm_takedown(struct drm_mm * mm)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mm_takedown);
|
||||
|
||||
static unsigned long drm_mm_debug_hole(struct drm_mm_node *entry,
|
||||
const char *prefix)
|
||||
{
|
||||
unsigned long hole_start, hole_end, hole_size;
|
||||
|
||||
if (entry->hole_follows) {
|
||||
hole_start = drm_mm_hole_node_start(entry);
|
||||
hole_end = drm_mm_hole_node_end(entry);
|
||||
hole_size = hole_end - hole_start;
|
||||
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
|
||||
prefix, hole_start, hole_end,
|
||||
hole_size);
|
||||
return hole_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
|
||||
{
|
||||
struct drm_mm_node *entry;
|
||||
unsigned long total_used = 0, total_free = 0, total = 0;
|
||||
unsigned long hole_start, hole_end, hole_size;
|
||||
|
||||
hole_start = drm_mm_hole_node_start(&mm->head_node);
|
||||
hole_end = drm_mm_hole_node_end(&mm->head_node);
|
||||
hole_size = hole_end - hole_start;
|
||||
if (hole_size)
|
||||
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
|
||||
prefix, hole_start, hole_end,
|
||||
hole_size);
|
||||
total_free += hole_size;
|
||||
total_free += drm_mm_debug_hole(&mm->head_node, prefix);
|
||||
|
||||
drm_mm_for_each_node(entry, mm) {
|
||||
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
|
||||
prefix, entry->start, entry->start + entry->size,
|
||||
entry->size);
|
||||
total_used += entry->size;
|
||||
|
||||
if (entry->hole_follows) {
|
||||
hole_start = drm_mm_hole_node_start(entry);
|
||||
hole_end = drm_mm_hole_node_end(entry);
|
||||
hole_size = hole_end - hole_start;
|
||||
printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
|
||||
prefix, hole_start, hole_end,
|
||||
hole_size);
|
||||
total_free += hole_size;
|
||||
}
|
||||
total_free += drm_mm_debug_hole(entry, prefix);
|
||||
}
|
||||
total = total_free + total_used;
|
||||
|
||||
|
@ -535,6 +535,8 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
|
||||
dmode->flags |= DRM_MODE_FLAG_INTERLACE;
|
||||
if (vm->flags & DISPLAY_FLAGS_DOUBLESCAN)
|
||||
dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
|
||||
if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
|
||||
dmode->flags |= DRM_MODE_FLAG_DBLCLK;
|
||||
drm_mode_set_name(dmode);
|
||||
|
||||
return 0;
|
||||
@ -787,16 +789,17 @@ EXPORT_SYMBOL(drm_mode_set_crtcinfo);
|
||||
* LOCKING:
|
||||
* None.
|
||||
*
|
||||
* Copy an existing mode into another mode, preserving the object id
|
||||
* of the destination mode.
|
||||
* Copy an existing mode into another mode, preserving the object id and
|
||||
* list head of the destination mode.
|
||||
*/
|
||||
void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src)
|
||||
{
|
||||
int id = dst->base.id;
|
||||
struct list_head head = dst->head;
|
||||
|
||||
*dst = *src;
|
||||
dst->base.id = id;
|
||||
INIT_LIST_HEAD(&dst->head);
|
||||
dst->head = head;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_copy);
|
||||
|
||||
@ -1017,6 +1020,11 @@ static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head
|
||||
diff = b->hdisplay * b->vdisplay - a->hdisplay * a->vdisplay;
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
diff = b->vrefresh - a->vrefresh;
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
diff = b->clock - a->clock;
|
||||
return diff;
|
||||
}
|
||||
|
@ -278,10 +278,10 @@ static int drm_pci_agp_init(struct drm_device *dev)
|
||||
}
|
||||
if (drm_core_has_MTRR(dev)) {
|
||||
if (dev->agp)
|
||||
dev->agp->agp_mtrr =
|
||||
mtrr_add(dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size *
|
||||
1024 * 1024, MTRR_TYPE_WRCOMB, 1);
|
||||
dev->agp->agp_mtrr = arch_phys_wc_add(
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size *
|
||||
1024 * 1024);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -62,20 +62,124 @@ struct drm_prime_member {
|
||||
struct dma_buf *dma_buf;
|
||||
uint32_t handle;
|
||||
};
|
||||
static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
|
||||
|
||||
struct drm_prime_attachment {
|
||||
struct sg_table *sgt;
|
||||
enum dma_data_direction dir;
|
||||
};
|
||||
|
||||
static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
|
||||
member = kmalloc(sizeof(*member), GFP_KERNEL);
|
||||
if (!member)
|
||||
return -ENOMEM;
|
||||
|
||||
get_dma_buf(dma_buf);
|
||||
member->dma_buf = dma_buf;
|
||||
member->handle = handle;
|
||||
list_add(&member->entry, &prime_fpriv->head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_gem_map_attach(struct dma_buf *dma_buf,
|
||||
struct device *target_dev,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_prime_attachment *prime_attach;
|
||||
struct drm_gem_object *obj = dma_buf->priv;
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
prime_attach = kzalloc(sizeof(*prime_attach), GFP_KERNEL);
|
||||
if (!prime_attach)
|
||||
return -ENOMEM;
|
||||
|
||||
prime_attach->dir = DMA_NONE;
|
||||
attach->priv = prime_attach;
|
||||
|
||||
if (!dev->driver->gem_prime_pin)
|
||||
return 0;
|
||||
|
||||
return dev->driver->gem_prime_pin(obj);
|
||||
}
|
||||
|
||||
static void drm_gem_map_detach(struct dma_buf *dma_buf,
|
||||
struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct drm_prime_attachment *prime_attach = attach->priv;
|
||||
struct drm_gem_object *obj = dma_buf->priv;
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (dev->driver->gem_prime_unpin)
|
||||
dev->driver->gem_prime_unpin(obj);
|
||||
|
||||
if (!prime_attach)
|
||||
return;
|
||||
|
||||
sgt = prime_attach->sgt;
|
||||
|
||||
if (prime_attach->dir != DMA_NONE)
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents,
|
||||
prime_attach->dir);
|
||||
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
kfree(prime_attach);
|
||||
attach->priv = NULL;
|
||||
}
|
||||
|
||||
static void drm_prime_remove_buf_handle_locked(
|
||||
struct drm_prime_file_private *prime_fpriv,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
struct drm_prime_member *member, *safe;
|
||||
|
||||
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
|
||||
if (member->dma_buf == dma_buf) {
|
||||
dma_buf_put(dma_buf);
|
||||
list_del(&member->entry);
|
||||
kfree(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
|
||||
enum dma_data_direction dir)
|
||||
{
|
||||
struct drm_prime_attachment *prime_attach = attach->priv;
|
||||
struct drm_gem_object *obj = attach->dmabuf->priv;
|
||||
struct sg_table *sgt;
|
||||
|
||||
if (WARN_ON(dir == DMA_NONE || !prime_attach))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* return the cached mapping when possible */
|
||||
if (prime_attach->dir == dir)
|
||||
return prime_attach->sgt;
|
||||
|
||||
/*
|
||||
* two mappings with different directions for the same attachment are
|
||||
* not allowed
|
||||
*/
|
||||
if (WARN_ON(prime_attach->dir != DMA_NONE))
|
||||
return ERR_PTR(-EBUSY);
|
||||
|
||||
mutex_lock(&obj->dev->struct_mutex);
|
||||
|
||||
sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
|
||||
|
||||
if (!IS_ERR_OR_NULL(sgt))
|
||||
dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
if (!IS_ERR(sgt)) {
|
||||
if (!dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir)) {
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
sgt = ERR_PTR(-ENOMEM);
|
||||
} else {
|
||||
prime_attach->sgt = sgt;
|
||||
prime_attach->dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&obj->dev->struct_mutex);
|
||||
return sgt;
|
||||
@ -84,9 +188,7 @@ static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
|
||||
static void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt, enum dma_data_direction dir)
|
||||
{
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
/* nothing to be done here */
|
||||
}
|
||||
|
||||
static void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
|
||||
@ -146,6 +248,8 @@ static int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf,
|
||||
}
|
||||
|
||||
static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
|
||||
.attach = drm_gem_map_attach,
|
||||
.detach = drm_gem_map_detach,
|
||||
.map_dma_buf = drm_gem_map_dma_buf,
|
||||
.unmap_dma_buf = drm_gem_unmap_dma_buf,
|
||||
.release = drm_gem_dmabuf_release,
|
||||
@ -185,11 +289,6 @@ static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = {
|
||||
struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
|
||||
struct drm_gem_object *obj, int flags)
|
||||
{
|
||||
if (dev->driver->gem_prime_pin) {
|
||||
int ret = dev->driver->gem_prime_pin(obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
return dma_buf_export(obj, &drm_gem_prime_dmabuf_ops, obj->size, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_prime_export);
|
||||
@ -235,15 +334,34 @@ int drm_gem_prime_handle_to_fd(struct drm_device *dev,
|
||||
ret = drm_prime_add_buf_handle(&file_priv->prime,
|
||||
obj->export_dma_buf, handle);
|
||||
if (ret)
|
||||
goto out;
|
||||
goto fail_put_dmabuf;
|
||||
|
||||
*prime_fd = dma_buf_fd(buf, flags);
|
||||
ret = dma_buf_fd(buf, flags);
|
||||
if (ret < 0)
|
||||
goto fail_rm_handle;
|
||||
|
||||
*prime_fd = ret;
|
||||
mutex_unlock(&file_priv->prime.lock);
|
||||
return 0;
|
||||
|
||||
out_have_obj:
|
||||
get_dma_buf(dmabuf);
|
||||
*prime_fd = dma_buf_fd(dmabuf, flags);
|
||||
ret = dma_buf_fd(dmabuf, flags);
|
||||
if (ret < 0) {
|
||||
dma_buf_put(dmabuf);
|
||||
} else {
|
||||
*prime_fd = ret;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
goto out;
|
||||
|
||||
fail_rm_handle:
|
||||
drm_prime_remove_buf_handle_locked(&file_priv->prime, buf);
|
||||
fail_put_dmabuf:
|
||||
/* clear NOT to be checked when releasing dma_buf */
|
||||
obj->export_dma_buf = NULL;
|
||||
dma_buf_put(buf);
|
||||
out:
|
||||
drm_gem_object_unreference_unlocked(obj);
|
||||
mutex_unlock(&file_priv->prime.lock);
|
||||
@ -276,7 +394,7 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
||||
|
||||
attach = dma_buf_attach(dma_buf, dev->dev);
|
||||
if (IS_ERR(attach))
|
||||
return ERR_PTR(PTR_ERR(attach));
|
||||
return ERR_CAST(attach);
|
||||
|
||||
get_dma_buf(dma_buf);
|
||||
|
||||
@ -412,8 +530,10 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
|
||||
int ret;
|
||||
|
||||
sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
|
||||
if (!sg)
|
||||
if (!sg) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0,
|
||||
nr_pages << PAGE_SHIFT, GFP_KERNEL);
|
||||
@ -423,7 +543,7 @@ struct sg_table *drm_prime_pages_to_sg(struct page **pages, int nr_pages)
|
||||
return sg;
|
||||
out:
|
||||
kfree(sg);
|
||||
return NULL;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_prime_pages_to_sg);
|
||||
|
||||
@ -492,21 +612,6 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_prime_destroy_file_private);
|
||||
|
||||
static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
|
||||
member = kmalloc(sizeof(*member), GFP_KERNEL);
|
||||
if (!member)
|
||||
return -ENOMEM;
|
||||
|
||||
get_dma_buf(dma_buf);
|
||||
member->dma_buf = dma_buf;
|
||||
member->handle = handle;
|
||||
list_add(&member->entry, &prime_fpriv->head);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
@ -523,16 +628,8 @@ EXPORT_SYMBOL(drm_prime_lookup_buf_handle);
|
||||
|
||||
void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf)
|
||||
{
|
||||
struct drm_prime_member *member, *safe;
|
||||
|
||||
mutex_lock(&prime_fpriv->lock);
|
||||
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
|
||||
if (member->dma_buf == dma_buf) {
|
||||
dma_buf_put(dma_buf);
|
||||
list_del(&member->entry);
|
||||
kfree(member);
|
||||
}
|
||||
}
|
||||
drm_prime_remove_buf_handle_locked(prime_fpriv, dma_buf);
|
||||
mutex_unlock(&prime_fpriv->lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_prime_remove_buf_handle);
|
||||
|
295
drivers/gpu/drm/drm_rect.c
Normal file
295
drivers/gpu/drm/drm_rect.c
Normal file
@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
/**
|
||||
* drm_rect_intersect - intersect two rectangles
|
||||
* @r1: first rectangle
|
||||
* @r2: second rectangle
|
||||
*
|
||||
* Calculate the intersection of rectangles @r1 and @r2.
|
||||
* @r1 will be overwritten with the intersection.
|
||||
*
|
||||
* RETURNS:
|
||||
* %true if rectangle @r1 is still visible after the operation,
|
||||
* %false otherwise.
|
||||
*/
|
||||
bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
|
||||
{
|
||||
r1->x1 = max(r1->x1, r2->x1);
|
||||
r1->y1 = max(r1->y1, r2->y1);
|
||||
r1->x2 = min(r1->x2, r2->x2);
|
||||
r1->y2 = min(r1->y2, r2->y2);
|
||||
|
||||
return drm_rect_visible(r1);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_intersect);
|
||||
|
||||
/**
|
||||
* drm_rect_clip_scaled - perform a scaled clip operation
|
||||
* @src: source window rectangle
|
||||
* @dst: destination window rectangle
|
||||
* @clip: clip rectangle
|
||||
* @hscale: horizontal scaling factor
|
||||
* @vscale: vertical scaling factor
|
||||
*
|
||||
* Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
|
||||
* same amounts multiplied by @hscale and @vscale.
|
||||
*
|
||||
* RETURNS:
|
||||
* %true if rectangle @dst is still visible after being clipped,
|
||||
* %false otherwise
|
||||
*/
|
||||
bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
|
||||
const struct drm_rect *clip,
|
||||
int hscale, int vscale)
|
||||
{
|
||||
int diff;
|
||||
|
||||
diff = clip->x1 - dst->x1;
|
||||
if (diff > 0) {
|
||||
int64_t tmp = src->x1 + (int64_t) diff * hscale;
|
||||
src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
||||
}
|
||||
diff = clip->y1 - dst->y1;
|
||||
if (diff > 0) {
|
||||
int64_t tmp = src->y1 + (int64_t) diff * vscale;
|
||||
src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
||||
}
|
||||
diff = dst->x2 - clip->x2;
|
||||
if (diff > 0) {
|
||||
int64_t tmp = src->x2 - (int64_t) diff * hscale;
|
||||
src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
||||
}
|
||||
diff = dst->y2 - clip->y2;
|
||||
if (diff > 0) {
|
||||
int64_t tmp = src->y2 - (int64_t) diff * vscale;
|
||||
src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
||||
}
|
||||
|
||||
return drm_rect_intersect(dst, clip);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_clip_scaled);
|
||||
|
||||
static int drm_calc_scale(int src, int dst)
|
||||
{
|
||||
int scale = 0;
|
||||
|
||||
if (src < 0 || dst < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (dst == 0)
|
||||
return 0;
|
||||
|
||||
scale = src / dst;
|
||||
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_rect_calc_hscale - calculate the horizontal scaling factor
|
||||
* @src: source window rectangle
|
||||
* @dst: destination window rectangle
|
||||
* @min_hscale: minimum allowed horizontal scaling factor
|
||||
* @max_hscale: maximum allowed horizontal scaling factor
|
||||
*
|
||||
* Calculate the horizontal scaling factor as
|
||||
* (@src width) / (@dst width).
|
||||
*
|
||||
* RETURNS:
|
||||
* The horizontal scaling factor, or errno of out of limits.
|
||||
*/
|
||||
int drm_rect_calc_hscale(const struct drm_rect *src,
|
||||
const struct drm_rect *dst,
|
||||
int min_hscale, int max_hscale)
|
||||
{
|
||||
int src_w = drm_rect_width(src);
|
||||
int dst_w = drm_rect_width(dst);
|
||||
int hscale = drm_calc_scale(src_w, dst_w);
|
||||
|
||||
if (hscale < 0 || dst_w == 0)
|
||||
return hscale;
|
||||
|
||||
if (hscale < min_hscale || hscale > max_hscale)
|
||||
return -ERANGE;
|
||||
|
||||
return hscale;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_calc_hscale);
|
||||
|
||||
/**
|
||||
* drm_rect_calc_vscale - calculate the vertical scaling factor
|
||||
* @src: source window rectangle
|
||||
* @dst: destination window rectangle
|
||||
* @min_vscale: minimum allowed vertical scaling factor
|
||||
* @max_vscale: maximum allowed vertical scaling factor
|
||||
*
|
||||
* Calculate the vertical scaling factor as
|
||||
* (@src height) / (@dst height).
|
||||
*
|
||||
* RETURNS:
|
||||
* The vertical scaling factor, or errno of out of limits.
|
||||
*/
|
||||
int drm_rect_calc_vscale(const struct drm_rect *src,
|
||||
const struct drm_rect *dst,
|
||||
int min_vscale, int max_vscale)
|
||||
{
|
||||
int src_h = drm_rect_height(src);
|
||||
int dst_h = drm_rect_height(dst);
|
||||
int vscale = drm_calc_scale(src_h, dst_h);
|
||||
|
||||
if (vscale < 0 || dst_h == 0)
|
||||
return vscale;
|
||||
|
||||
if (vscale < min_vscale || vscale > max_vscale)
|
||||
return -ERANGE;
|
||||
|
||||
return vscale;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_calc_vscale);
|
||||
|
||||
/**
|
||||
* drm_calc_hscale_relaxed - calculate the horizontal scaling factor
|
||||
* @src: source window rectangle
|
||||
* @dst: destination window rectangle
|
||||
* @min_hscale: minimum allowed horizontal scaling factor
|
||||
* @max_hscale: maximum allowed horizontal scaling factor
|
||||
*
|
||||
* Calculate the horizontal scaling factor as
|
||||
* (@src width) / (@dst width).
|
||||
*
|
||||
* If the calculated scaling factor is below @min_vscale,
|
||||
* decrease the height of rectangle @dst to compensate.
|
||||
*
|
||||
* If the calculated scaling factor is above @max_vscale,
|
||||
* decrease the height of rectangle @src to compensate.
|
||||
*
|
||||
* RETURNS:
|
||||
* The horizontal scaling factor.
|
||||
*/
|
||||
int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
|
||||
struct drm_rect *dst,
|
||||
int min_hscale, int max_hscale)
|
||||
{
|
||||
int src_w = drm_rect_width(src);
|
||||
int dst_w = drm_rect_width(dst);
|
||||
int hscale = drm_calc_scale(src_w, dst_w);
|
||||
|
||||
if (hscale < 0 || dst_w == 0)
|
||||
return hscale;
|
||||
|
||||
if (hscale < min_hscale) {
|
||||
int max_dst_w = src_w / min_hscale;
|
||||
|
||||
drm_rect_adjust_size(dst, max_dst_w - dst_w, 0);
|
||||
|
||||
return min_hscale;
|
||||
}
|
||||
|
||||
if (hscale > max_hscale) {
|
||||
int max_src_w = dst_w * max_hscale;
|
||||
|
||||
drm_rect_adjust_size(src, max_src_w - src_w, 0);
|
||||
|
||||
return max_hscale;
|
||||
}
|
||||
|
||||
return hscale;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed);
|
||||
|
||||
/**
|
||||
* drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor
|
||||
* @src: source window rectangle
|
||||
* @dst: destination window rectangle
|
||||
* @min_vscale: minimum allowed vertical scaling factor
|
||||
* @max_vscale: maximum allowed vertical scaling factor
|
||||
*
|
||||
* Calculate the vertical scaling factor as
|
||||
* (@src height) / (@dst height).
|
||||
*
|
||||
* If the calculated scaling factor is below @min_vscale,
|
||||
* decrease the height of rectangle @dst to compensate.
|
||||
*
|
||||
* If the calculated scaling factor is above @max_vscale,
|
||||
* decrease the height of rectangle @src to compensate.
|
||||
*
|
||||
* RETURNS:
|
||||
* The vertical scaling factor.
|
||||
*/
|
||||
int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
|
||||
struct drm_rect *dst,
|
||||
int min_vscale, int max_vscale)
|
||||
{
|
||||
int src_h = drm_rect_height(src);
|
||||
int dst_h = drm_rect_height(dst);
|
||||
int vscale = drm_calc_scale(src_h, dst_h);
|
||||
|
||||
if (vscale < 0 || dst_h == 0)
|
||||
return vscale;
|
||||
|
||||
if (vscale < min_vscale) {
|
||||
int max_dst_h = src_h / min_vscale;
|
||||
|
||||
drm_rect_adjust_size(dst, 0, max_dst_h - dst_h);
|
||||
|
||||
return min_vscale;
|
||||
}
|
||||
|
||||
if (vscale > max_vscale) {
|
||||
int max_src_h = dst_h * max_vscale;
|
||||
|
||||
drm_rect_adjust_size(src, 0, max_src_h - src_h);
|
||||
|
||||
return max_vscale;
|
||||
}
|
||||
|
||||
return vscale;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
|
||||
|
||||
/**
|
||||
* drm_rect_debug_print - print the rectangle information
|
||||
* @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)
|
||||
{
|
||||
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",
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_rect_debug_print);
|
@ -203,7 +203,7 @@ EXPORT_SYMBOL(drm_master_put);
|
||||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (file_priv->is_master)
|
||||
return 0;
|
||||
@ -229,7 +229,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
@ -451,14 +451,8 @@ void drm_put_dev(struct drm_device *dev)
|
||||
|
||||
drm_lastclose(dev);
|
||||
|
||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
|
||||
dev->agp && dev->agp->agp_mtrr >= 0) {
|
||||
int retval;
|
||||
retval = mtrr_del(dev->agp->agp_mtrr,
|
||||
dev->agp->agp_info.aper_base,
|
||||
dev->agp->agp_info.aper_size * 1024 * 1024);
|
||||
DRM_DEBUG("mtrr_del=%d\n", retval);
|
||||
}
|
||||
if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) && dev->agp)
|
||||
arch_phys_wc_del(dev->agp->agp_mtrr);
|
||||
|
||||
if (dev->driver->unload)
|
||||
dev->driver->unload(dev);
|
||||
|
@ -30,14 +30,14 @@ static struct device_type drm_sysfs_device_minor = {
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_class_suspend - DRM class suspend hook
|
||||
* __drm_class_suspend - internal DRM class suspend routine
|
||||
* @dev: Linux device to suspend
|
||||
* @state: power state to enter
|
||||
*
|
||||
* Just figures out what the actual struct drm_device associated with
|
||||
* @dev is and calls its suspend hook, if present.
|
||||
*/
|
||||
static int drm_class_suspend(struct device *dev, pm_message_t state)
|
||||
static int __drm_class_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
if (dev->type == &drm_sysfs_device_minor) {
|
||||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
@ -51,6 +51,26 @@ static int drm_class_suspend(struct device *dev, pm_message_t state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_class_suspend - internal DRM class suspend hook. Simply calls
|
||||
* __drm_class_suspend() with the correct pm state.
|
||||
* @dev: Linux device to suspend
|
||||
*/
|
||||
static int drm_class_suspend(struct device *dev)
|
||||
{
|
||||
return __drm_class_suspend(dev, PMSG_SUSPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_class_freeze - internal DRM class freeze hook. Simply calls
|
||||
* __drm_class_suspend() with the correct pm state.
|
||||
* @dev: Linux device to freeze
|
||||
*/
|
||||
static int drm_class_freeze(struct device *dev)
|
||||
{
|
||||
return __drm_class_suspend(dev, PMSG_FREEZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_class_resume - DRM class resume hook
|
||||
* @dev: Linux device to resume
|
||||
@ -72,6 +92,12 @@ static int drm_class_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops drm_class_dev_pm_ops = {
|
||||
.suspend = drm_class_suspend,
|
||||
.resume = drm_class_resume,
|
||||
.freeze = drm_class_freeze,
|
||||
};
|
||||
|
||||
static char *drm_devnode(struct device *dev, umode_t *mode)
|
||||
{
|
||||
return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
|
||||
@ -106,8 +132,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
class->suspend = drm_class_suspend;
|
||||
class->resume = drm_class_resume;
|
||||
class->pm = &drm_class_dev_pm_ops;
|
||||
|
||||
err = class_create_file(class, &class_attr_version.attr);
|
||||
if (err)
|
||||
|
@ -21,7 +21,7 @@ TRACE_EVENT(drm_vblank_event,
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq)
|
||||
TP_printk("crtc=%d, seq=%u", __entry->crtc, __entry->seq)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drm_vblank_event_queued,
|
||||
@ -37,7 +37,7 @@ TRACE_EVENT(drm_vblank_event_queued,
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
|
||||
TP_printk("pid=%d, crtc=%d, seq=%u", __entry->pid, __entry->crtc, \
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
@ -54,7 +54,7 @@ TRACE_EVENT(drm_vblank_event_delivered,
|
||||
__entry->crtc = crtc;
|
||||
__entry->seq = seq;
|
||||
),
|
||||
TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
|
||||
TP_printk("pid=%d, crtc=%d, seq=%u", __entry->pid, __entry->crtc, \
|
||||
__entry->seq)
|
||||
);
|
||||
|
||||
|
@ -43,18 +43,19 @@
|
||||
static void drm_vm_open(struct vm_area_struct *vma);
|
||||
static void drm_vm_close(struct vm_area_struct *vma);
|
||||
|
||||
static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
|
||||
static pgprot_t drm_io_prot(struct drm_local_map *map,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (boot_cpu_data.x86 > 3 && map_type != _DRM_AGP) {
|
||||
pgprot_val(tmp) |= _PAGE_PCD;
|
||||
pgprot_val(tmp) &= ~_PAGE_PWT;
|
||||
}
|
||||
if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING))
|
||||
tmp = pgprot_noncached(tmp);
|
||||
else
|
||||
tmp = pgprot_writecombine(tmp);
|
||||
#elif defined(__powerpc__)
|
||||
pgprot_val(tmp) |= _PAGE_NO_CACHE;
|
||||
if (map_type == _DRM_REGISTERS)
|
||||
if (map->type == _DRM_REGISTERS)
|
||||
pgprot_val(tmp) |= _PAGE_GUARDED;
|
||||
#elif defined(__ia64__)
|
||||
if (efi_range_is_wc(vma->vm_start, vma->vm_end -
|
||||
@ -250,13 +251,8 @@ static void drm_vm_shm_close(struct vm_area_struct *vma)
|
||||
switch (map->type) {
|
||||
case _DRM_REGISTERS:
|
||||
case _DRM_FRAME_BUFFER:
|
||||
if (drm_core_has_MTRR(dev) && map->mtrr >= 0) {
|
||||
int retcode;
|
||||
retcode = mtrr_del(map->mtrr,
|
||||
map->offset,
|
||||
map->size);
|
||||
DRM_DEBUG("mtrr_del = %d\n", retcode);
|
||||
}
|
||||
if (drm_core_has_MTRR(dev))
|
||||
arch_phys_wc_del(map->mtrr);
|
||||
iounmap(map->handle);
|
||||
break;
|
||||
case _DRM_SHM:
|
||||
@ -617,8 +613,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
|
||||
case _DRM_FRAME_BUFFER:
|
||||
case _DRM_REGISTERS:
|
||||
offset = drm_core_get_reg_ofs(dev);
|
||||
vma->vm_flags |= VM_IO; /* not in core dump */
|
||||
vma->vm_page_prot = drm_io_prot(map->type, vma);
|
||||
vma->vm_page_prot = drm_io_prot(map, vma);
|
||||
if (io_remap_pfn_range(vma, vma->vm_start,
|
||||
(map->offset + offset) >> PAGE_SHIFT,
|
||||
vma->vm_end - vma->vm_start,
|
||||
|
@ -52,6 +52,8 @@ static struct i2c_device_id ddc_idtable[] = {
|
||||
static struct of_device_id hdmiddc_match_types[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5-hdmiddc",
|
||||
}, {
|
||||
.compatible = "samsung,exynos4210-hdmiddc",
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
|
@ -24,8 +24,6 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
||||
enum dma_attr attr;
|
||||
unsigned int nr_pages;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (buf->dma_addr) {
|
||||
DRM_DEBUG_KMS("already allocated.\n");
|
||||
return 0;
|
||||
@ -119,8 +117,6 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
||||
static void lowlevel_buffer_deallocate(struct drm_device *dev,
|
||||
unsigned int flags, struct exynos_drm_gem_buf *buf)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s.\n", __FILE__);
|
||||
|
||||
if (!buf->dma_addr) {
|
||||
DRM_DEBUG_KMS("dma_addr is invalid.\n");
|
||||
return;
|
||||
@ -151,7 +147,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
|
||||
{
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
|
||||
DRM_DEBUG_KMS("%s.\n", __FILE__);
|
||||
DRM_DEBUG_KMS("desired size = 0x%x\n", size);
|
||||
|
||||
buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||
@ -167,8 +162,6 @@ struct exynos_drm_gem_buf *exynos_drm_init_buf(struct drm_device *dev,
|
||||
void exynos_drm_fini_buf(struct drm_device *dev,
|
||||
struct exynos_drm_gem_buf *buffer)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s.\n", __FILE__);
|
||||
|
||||
if (!buffer) {
|
||||
DRM_DEBUG_KMS("buffer is null.\n");
|
||||
return;
|
||||
|
@ -34,7 +34,6 @@ convert_to_display_mode(struct drm_display_mode *mode,
|
||||
struct exynos_drm_panel_info *panel)
|
||||
{
|
||||
struct fb_videomode *timing = &panel->timing;
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
mode->clock = timing->pixclock / 1000;
|
||||
mode->vrefresh = timing->refresh;
|
||||
@ -58,37 +57,6 @@ convert_to_display_mode(struct drm_display_mode *mode,
|
||||
mode->flags |= DRM_MODE_FLAG_DBLSCAN;
|
||||
}
|
||||
|
||||
/* convert drm_display_mode to exynos_video_timings */
|
||||
static inline void
|
||||
convert_to_video_timing(struct fb_videomode *timing,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
memset(timing, 0, sizeof(*timing));
|
||||
|
||||
timing->pixclock = mode->clock * 1000;
|
||||
timing->refresh = drm_mode_vrefresh(mode);
|
||||
|
||||
timing->xres = mode->hdisplay;
|
||||
timing->right_margin = mode->hsync_start - mode->hdisplay;
|
||||
timing->hsync_len = mode->hsync_end - mode->hsync_start;
|
||||
timing->left_margin = mode->htotal - mode->hsync_end;
|
||||
|
||||
timing->yres = mode->vdisplay;
|
||||
timing->lower_margin = mode->vsync_start - mode->vdisplay;
|
||||
timing->vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
timing->upper_margin = mode->vtotal - mode->vsync_end;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
timing->vmode = FB_VMODE_INTERLACED;
|
||||
else
|
||||
timing->vmode = FB_VMODE_NONINTERLACED;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
timing->vmode |= FB_VMODE_DOUBLE;
|
||||
}
|
||||
|
||||
static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct exynos_drm_connector *exynos_connector =
|
||||
@ -99,8 +67,6 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
|
||||
unsigned int count = 0;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!display_ops) {
|
||||
DRM_DEBUG_KMS("display_ops is null.\n");
|
||||
return 0;
|
||||
@ -168,15 +134,12 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
|
||||
to_exynos_connector(connector);
|
||||
struct exynos_drm_manager *manager = exynos_connector->manager;
|
||||
struct exynos_drm_display_ops *display_ops = manager->display_ops;
|
||||
struct fb_videomode timing;
|
||||
int ret = MODE_BAD;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
convert_to_video_timing(&timing, mode);
|
||||
|
||||
if (display_ops && display_ops->check_timing)
|
||||
if (!display_ops->check_timing(manager->dev, (void *)&timing))
|
||||
if (display_ops && display_ops->check_mode)
|
||||
if (!display_ops->check_mode(manager->dev, mode))
|
||||
ret = MODE_OK;
|
||||
|
||||
return ret;
|
||||
@ -190,8 +153,6 @@ struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
|
||||
struct drm_mode_object *obj;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
|
||||
DRM_MODE_OBJECT_ENCODER);
|
||||
if (!obj) {
|
||||
@ -234,8 +195,6 @@ void exynos_drm_display_power(struct drm_connector *connector, int mode)
|
||||
static void exynos_drm_connector_dpms(struct drm_connector *connector,
|
||||
int mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* in case that drm_crtc_helper_set_mode() is called,
|
||||
* encoder/crtc->funcs->dpms() will be just returned
|
||||
@ -282,8 +241,6 @@ exynos_drm_connector_detect(struct drm_connector *connector, bool force)
|
||||
manager->display_ops;
|
||||
enum drm_connector_status status = connector_status_disconnected;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (display_ops && display_ops->is_connected) {
|
||||
if (display_ops->is_connected(manager->dev))
|
||||
status = connector_status_connected;
|
||||
@ -299,8 +256,6 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
|
||||
struct exynos_drm_connector *exynos_connector =
|
||||
to_exynos_connector(connector);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(exynos_connector);
|
||||
@ -322,8 +277,6 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
|
||||
int type;
|
||||
int err;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_connector = kzalloc(sizeof(*exynos_connector), GFP_KERNEL);
|
||||
if (!exynos_connector) {
|
||||
DRM_ERROR("failed to allocate connector\n");
|
||||
|
@ -27,8 +27,6 @@ static int exynos_drm_create_enc_conn(struct drm_device *dev,
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
subdrv->manager->dev = subdrv->dev;
|
||||
|
||||
/* create and initialize a encoder for this sub driver. */
|
||||
@ -102,8 +100,6 @@ static int exynos_drm_subdrv_probe(struct drm_device *dev,
|
||||
static void exynos_drm_subdrv_remove(struct drm_device *dev,
|
||||
struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (subdrv->remove)
|
||||
subdrv->remove(dev, subdrv->dev);
|
||||
}
|
||||
@ -114,8 +110,6 @@ int exynos_drm_device_register(struct drm_device *dev)
|
||||
unsigned int fine_cnt = 0;
|
||||
int err;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
@ -158,8 +152,6 @@ int exynos_drm_device_unregister(struct drm_device *dev)
|
||||
{
|
||||
struct exynos_drm_subdrv *subdrv;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (!dev) {
|
||||
WARN(1, "Unexpected drm device unregister!\n");
|
||||
return -EINVAL;
|
||||
@ -176,8 +168,6 @@ EXPORT_SYMBOL_GPL(exynos_drm_device_unregister);
|
||||
|
||||
int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (!subdrv)
|
||||
return -EINVAL;
|
||||
|
||||
@ -189,8 +179,6 @@ EXPORT_SYMBOL_GPL(exynos_drm_subdrv_register);
|
||||
|
||||
int exynos_drm_subdrv_unregister(struct exynos_drm_subdrv *subdrv)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (!subdrv)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -76,8 +76,6 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
|
||||
static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* drm framework doesn't check NULL. */
|
||||
}
|
||||
|
||||
@ -85,8 +83,6 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
exynos_plane_commit(exynos_crtc->plane);
|
||||
exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
|
||||
@ -97,8 +93,6 @@ exynos_drm_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* drm framework doesn't check NULL */
|
||||
return true;
|
||||
}
|
||||
@ -115,8 +109,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
int pipe = exynos_crtc->pipe;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* copy the mode data adjusted by mode_fixup() into crtc->mode
|
||||
* so that hardware can be seet to proper mode.
|
||||
@ -139,7 +131,7 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
static int exynos_drm_crtc_mode_set_commit(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
||||
@ -148,8 +140,6 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
unsigned int crtc_h;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* when framebuffer changing is requested, crtc's dpms should be on */
|
||||
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
|
||||
DRM_ERROR("failed framebuffer changing request.\n");
|
||||
@ -169,18 +159,16 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void exynos_drm_crtc_load_lut(struct drm_crtc *crtc)
|
||||
static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
/* drm framework doesn't check NULL */
|
||||
return exynos_drm_crtc_mode_set_commit(crtc, x, y, old_fb);
|
||||
}
|
||||
|
||||
static void exynos_drm_crtc_disable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_OFF);
|
||||
exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
@ -192,7 +180,6 @@ static struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = {
|
||||
.mode_fixup = exynos_drm_crtc_mode_fixup,
|
||||
.mode_set = exynos_drm_crtc_mode_set,
|
||||
.mode_set_base = exynos_drm_crtc_mode_set_base,
|
||||
.load_lut = exynos_drm_crtc_load_lut,
|
||||
.disable = exynos_drm_crtc_disable,
|
||||
};
|
||||
|
||||
@ -206,8 +193,6 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *old_fb = crtc->fb;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* when the page flip is requested, crtc's dpms should be on */
|
||||
if (exynos_crtc->dpms > DRM_MODE_DPMS_ON) {
|
||||
DRM_ERROR("failed page flip request.\n");
|
||||
@ -237,7 +222,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
|
||||
spin_unlock_irq(&dev->event_lock);
|
||||
|
||||
crtc->fb = fb;
|
||||
ret = exynos_drm_crtc_mode_set_base(crtc, crtc->x, crtc->y,
|
||||
ret = exynos_drm_crtc_mode_set_commit(crtc, crtc->x, crtc->y,
|
||||
NULL);
|
||||
if (ret) {
|
||||
crtc->fb = old_fb;
|
||||
@ -260,8 +245,6 @@ static void exynos_drm_crtc_destroy(struct drm_crtc *crtc)
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
||||
struct exynos_drm_private *private = crtc->dev->dev_private;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
private->crtc[exynos_crtc->pipe] = NULL;
|
||||
|
||||
drm_crtc_cleanup(crtc);
|
||||
@ -276,8 +259,6 @@ static int exynos_drm_crtc_set_property(struct drm_crtc *crtc,
|
||||
struct exynos_drm_private *dev_priv = dev->dev_private;
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (property == dev_priv->crtc_mode_property) {
|
||||
enum exynos_crtc_mode mode = val;
|
||||
|
||||
@ -322,8 +303,6 @@ static void exynos_drm_crtc_attach_mode_property(struct drm_crtc *crtc)
|
||||
struct exynos_drm_private *dev_priv = dev->dev_private;
|
||||
struct drm_property *prop;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
prop = dev_priv->crtc_mode_property;
|
||||
if (!prop) {
|
||||
prop = drm_property_create_enum(dev, 0, "mode", mode_names,
|
||||
@ -343,8 +322,6 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr)
|
||||
struct exynos_drm_private *private = dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL);
|
||||
if (!exynos_crtc) {
|
||||
DRM_ERROR("failed to allocate exynos crtc\n");
|
||||
@ -379,8 +356,6 @@ int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc)
|
||||
struct exynos_drm_crtc *exynos_crtc =
|
||||
to_exynos_crtc(private->crtc[crtc]);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
|
||||
return -EPERM;
|
||||
|
||||
@ -396,8 +371,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc)
|
||||
struct exynos_drm_crtc *exynos_crtc =
|
||||
to_exynos_crtc(private->crtc[crtc]);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (exynos_crtc->dpms != DRM_MODE_DPMS_ON)
|
||||
return;
|
||||
|
||||
@ -413,8 +386,6 @@ void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc)
|
||||
struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc);
|
||||
unsigned long flags;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list,
|
||||
|
@ -71,8 +71,6 @@ static struct sg_table *
|
||||
unsigned int i;
|
||||
int nents, ret;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/* just return current sgt if already requested. */
|
||||
if (exynos_attach->dir == dir && exynos_attach->is_mapped)
|
||||
return &exynos_attach->sgt;
|
||||
@ -133,8 +131,6 @@ static void exynos_dmabuf_release(struct dma_buf *dmabuf)
|
||||
{
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* exynos_dmabuf_release() call means that file object's
|
||||
* f_count is 0 and it calls drm_gem_object_handle_unreference()
|
||||
@ -219,8 +215,6 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_PRIME("%s\n", __FILE__);
|
||||
|
||||
/* is this one of own objects? */
|
||||
if (dma_buf->ops == &exynos_dmabuf_ops) {
|
||||
struct drm_gem_object *obj;
|
||||
|
@ -46,8 +46,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
int ret;
|
||||
int nr;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
private = kzalloc(sizeof(struct exynos_drm_private), GFP_KERNEL);
|
||||
if (!private) {
|
||||
DRM_ERROR("failed to allocate private\n");
|
||||
@ -140,8 +138,6 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
static int exynos_drm_unload(struct drm_device *dev)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_fbdev_fini(dev);
|
||||
exynos_drm_device_unregister(dev);
|
||||
drm_vblank_cleanup(dev);
|
||||
@ -160,8 +156,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_exynos_file_private *file_priv;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
|
||||
if (!file_priv)
|
||||
return -ENOMEM;
|
||||
@ -178,8 +172,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
|
||||
struct drm_pending_vblank_event *e, *t;
|
||||
unsigned long flags;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
/* release events of current file */
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
list_for_each_entry_safe(e, t, &private->pageflip_event_list,
|
||||
@ -196,8 +188,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
|
||||
|
||||
static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
if (!file->driver_priv)
|
||||
return;
|
||||
|
||||
@ -207,8 +197,6 @@ static void exynos_drm_postclose(struct drm_device *dev, struct drm_file *file)
|
||||
|
||||
static void exynos_drm_lastclose(struct drm_device *dev)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_fbdev_restore_mode(dev);
|
||||
}
|
||||
|
||||
@ -292,8 +280,6 @@ static struct drm_driver exynos_drm_driver = {
|
||||
|
||||
static int exynos_drm_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
|
||||
exynos_drm_driver.num_ioctls = DRM_ARRAY_SIZE(exynos_ioctls);
|
||||
|
||||
@ -302,8 +288,6 @@ static int exynos_drm_platform_probe(struct platform_device *pdev)
|
||||
|
||||
static int exynos_drm_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
drm_platform_exit(&exynos_drm_driver, pdev);
|
||||
|
||||
return 0;
|
||||
@ -322,8 +306,6 @@ static int __init exynos_drm_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
#ifdef CONFIG_DRM_EXYNOS_FIMD
|
||||
ret = platform_driver_register(&fimd_driver);
|
||||
if (ret < 0)
|
||||
@ -455,8 +437,6 @@ static int __init exynos_drm_init(void)
|
||||
|
||||
static void __exit exynos_drm_exit(void)
|
||||
{
|
||||
DRM_DEBUG_DRIVER("%s\n", __FILE__);
|
||||
|
||||
platform_device_unregister(exynos_drm_pdev);
|
||||
|
||||
platform_driver_unregister(&exynos_drm_platform_driver);
|
||||
|
@ -142,7 +142,7 @@ struct exynos_drm_overlay {
|
||||
* @is_connected: check for that display is connected or not.
|
||||
* @get_edid: get edid modes from display driver.
|
||||
* @get_panel: get panel object from display driver.
|
||||
* @check_timing: check if timing is valid or not.
|
||||
* @check_mode: check if mode is valid or not.
|
||||
* @power_on: display device on or off.
|
||||
*/
|
||||
struct exynos_drm_display_ops {
|
||||
@ -151,7 +151,7 @@ struct exynos_drm_display_ops {
|
||||
struct edid *(*get_edid)(struct device *dev,
|
||||
struct drm_connector *connector);
|
||||
void *(*get_panel)(struct device *dev);
|
||||
int (*check_timing)(struct device *dev, void *timing);
|
||||
int (*check_mode)(struct device *dev, struct drm_display_mode *mode);
|
||||
int (*power_on)(struct device *dev, int mode);
|
||||
};
|
||||
|
||||
|
@ -61,7 +61,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
|
||||
|
||||
DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
|
||||
DRM_DEBUG_KMS("encoder dpms: %d\n", mode);
|
||||
|
||||
if (exynos_encoder->dpms == mode) {
|
||||
DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
|
||||
@ -104,8 +104,6 @@ exynos_drm_encoder_mode_fixup(struct drm_encoder *encoder,
|
||||
struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder == encoder)
|
||||
if (manager_ops && manager_ops->mode_fixup)
|
||||
@ -155,8 +153,6 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct exynos_drm_manager *manager;
|
||||
struct exynos_drm_manager_ops *manager_ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
if (connector->encoder == encoder) {
|
||||
struct exynos_drm_encoder *exynos_encoder;
|
||||
@ -189,8 +185,6 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
|
||||
|
||||
static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* drm framework doesn't check NULL. */
|
||||
}
|
||||
|
||||
@ -200,8 +194,6 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
|
||||
struct exynos_drm_manager *manager = exynos_encoder->manager;
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops && manager_ops->commit)
|
||||
manager_ops->commit(manager->dev);
|
||||
|
||||
@ -274,8 +266,6 @@ static void exynos_drm_encoder_destroy(struct drm_encoder *encoder)
|
||||
struct exynos_drm_encoder *exynos_encoder =
|
||||
to_exynos_encoder(encoder);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_encoder->manager->pipe = -1;
|
||||
|
||||
drm_encoder_cleanup(encoder);
|
||||
@ -315,8 +305,6 @@ void exynos_drm_encoder_setup(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
|
||||
encoder->possible_clones = exynos_drm_encoder_clones(encoder);
|
||||
}
|
||||
@ -329,8 +317,6 @@ exynos_drm_encoder_create(struct drm_device *dev,
|
||||
struct drm_encoder *encoder;
|
||||
struct exynos_drm_encoder *exynos_encoder;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!manager || !possible_crtcs)
|
||||
return NULL;
|
||||
|
||||
@ -427,8 +413,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
|
||||
struct exynos_drm_manager_ops *manager_ops = manager->ops;
|
||||
int mode = *(int *)data;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (manager_ops && manager_ops->dpms)
|
||||
manager_ops->dpms(manager->dev, mode);
|
||||
|
||||
@ -449,8 +433,6 @@ void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data)
|
||||
to_exynos_encoder(encoder)->manager;
|
||||
int pipe = *(int *)data;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* when crtc is detached from encoder, this pipe is used
|
||||
* to select manager operation
|
||||
@ -465,8 +447,6 @@ void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data)
|
||||
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
|
||||
struct exynos_drm_overlay *overlay = data;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (overlay_ops && overlay_ops->mode_set)
|
||||
overlay_ops->mode_set(manager->dev, overlay);
|
||||
}
|
||||
@ -478,8 +458,6 @@ void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data)
|
||||
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
|
||||
int zpos = DEFAULT_ZPOS;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (data)
|
||||
zpos = *(int *)data;
|
||||
|
||||
@ -494,8 +472,6 @@ void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data)
|
||||
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
|
||||
int zpos = DEFAULT_ZPOS;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (data)
|
||||
zpos = *(int *)data;
|
||||
|
||||
@ -510,8 +486,6 @@ void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data)
|
||||
struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
|
||||
int zpos = DEFAULT_ZPOS;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (data)
|
||||
zpos = *(int *)data;
|
||||
|
||||
|
@ -70,8 +70,6 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
|
||||
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
|
||||
unsigned int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* make sure that overlay data are updated before relesing fb. */
|
||||
exynos_drm_encoder_complete_scanout(fb);
|
||||
|
||||
@ -97,8 +95,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb,
|
||||
{
|
||||
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* This fb should have only one gem object. */
|
||||
if (WARN_ON(exynos_fb->buf_cnt != 1))
|
||||
return -EINVAL;
|
||||
@ -112,8 +108,6 @@ static int exynos_drm_fb_dirty(struct drm_framebuffer *fb,
|
||||
unsigned color, struct drm_clip_rect *clips,
|
||||
unsigned num_clips)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
@ -225,8 +219,6 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv,
|
||||
struct exynos_drm_fb *exynos_fb;
|
||||
int i, ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL);
|
||||
if (!exynos_fb) {
|
||||
DRM_ERROR("failed to allocate exynos drm framebuffer\n");
|
||||
@ -293,8 +285,6 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
|
||||
struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
|
||||
struct exynos_drm_gem_buf *buffer;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (index >= MAX_FB_BUFFER)
|
||||
return NULL;
|
||||
|
||||
|
@ -43,8 +43,6 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
|
||||
unsigned long vm_size;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
|
||||
|
||||
vm_size = vma->vm_end - vma->vm_start;
|
||||
@ -84,8 +82,6 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
|
||||
unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
|
||||
unsigned long offset;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
|
||||
|
||||
@ -148,8 +144,6 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
|
||||
unsigned long size;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
|
||||
sizes->surface_width, sizes->surface_height,
|
||||
sizes->surface_bpp);
|
||||
@ -238,8 +232,6 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
|
||||
unsigned int num_crtc;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector)
|
||||
return 0;
|
||||
|
||||
|
@ -175,8 +175,6 @@ static void fimc_sw_reset(struct fimc_context *ctx)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* stop dma operation */
|
||||
cfg = fimc_read(EXYNOS_CISTATUS);
|
||||
if (EXYNOS_CISTATUS_GET_ENVID_STATUS(cfg)) {
|
||||
@ -210,8 +208,6 @@ static void fimc_sw_reset(struct fimc_context *ctx)
|
||||
|
||||
static int fimc_set_camblk_fimd0_wb(struct fimc_context *ctx)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
return regmap_update_bits(ctx->sysreg, SYSREG_CAMERA_BLK,
|
||||
SYSREG_FIMD0WB_DEST_MASK,
|
||||
ctx->id << SYSREG_FIMD0WB_DEST_SHIFT);
|
||||
@ -221,7 +217,7 @@ static void fimc_set_type_ctrl(struct fimc_context *ctx, enum fimc_wb wb)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:wb[%d]\n", __func__, wb);
|
||||
DRM_DEBUG_KMS("wb[%d]\n", wb);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
cfg &= ~(EXYNOS_CIGCTRL_TESTPATTERN_MASK |
|
||||
@ -257,10 +253,10 @@ static void fimc_set_polarity(struct fimc_context *ctx,
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:inv_pclk[%d]inv_vsync[%d]\n",
|
||||
__func__, pol->inv_pclk, pol->inv_vsync);
|
||||
DRM_DEBUG_KMS("%s:inv_href[%d]inv_hsync[%d]\n",
|
||||
__func__, pol->inv_href, pol->inv_hsync);
|
||||
DRM_DEBUG_KMS("inv_pclk[%d]inv_vsync[%d]\n",
|
||||
pol->inv_pclk, pol->inv_vsync);
|
||||
DRM_DEBUG_KMS("inv_href[%d]inv_hsync[%d]\n",
|
||||
pol->inv_href, pol->inv_hsync);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
cfg &= ~(EXYNOS_CIGCTRL_INVPOLPCLK | EXYNOS_CIGCTRL_INVPOLVSYNC |
|
||||
@ -282,7 +278,7 @@ static void fimc_handle_jpeg(struct fimc_context *ctx, bool enable)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
|
||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
if (enable)
|
||||
@ -298,7 +294,7 @@ static void fimc_handle_irq(struct fimc_context *ctx, bool enable,
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
|
||||
enable, overflow, level);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
@ -319,8 +315,6 @@ static void fimc_clear_irq(struct fimc_context *ctx)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
cfg |= EXYNOS_CIGCTRL_IRQ_CLR;
|
||||
fimc_write(cfg, EXYNOS_CIGCTRL);
|
||||
@ -335,7 +329,7 @@ static bool fimc_check_ovf(struct fimc_context *ctx)
|
||||
flag = EXYNOS_CISTATUS_OVFIY | EXYNOS_CISTATUS_OVFICB |
|
||||
EXYNOS_CISTATUS_OVFICR;
|
||||
|
||||
DRM_DEBUG_KMS("%s:flag[0x%x]\n", __func__, flag);
|
||||
DRM_DEBUG_KMS("flag[0x%x]\n", flag);
|
||||
|
||||
if (status & flag) {
|
||||
cfg = fimc_read(EXYNOS_CIWDOFST);
|
||||
@ -364,7 +358,7 @@ static bool fimc_check_frame_end(struct fimc_context *ctx)
|
||||
|
||||
cfg = fimc_read(EXYNOS_CISTATUS);
|
||||
|
||||
DRM_DEBUG_KMS("%s:cfg[0x%x]\n", __func__, cfg);
|
||||
DRM_DEBUG_KMS("cfg[0x%x]\n", cfg);
|
||||
|
||||
if (!(cfg & EXYNOS_CISTATUS_FRAMEEND))
|
||||
return false;
|
||||
@ -380,15 +374,13 @@ static int fimc_get_buf_id(struct fimc_context *ctx)
|
||||
u32 cfg;
|
||||
int frame_cnt, buf_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CISTATUS2);
|
||||
frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg);
|
||||
|
||||
if (frame_cnt == 0)
|
||||
frame_cnt = EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg);
|
||||
|
||||
DRM_DEBUG_KMS("%s:present[%d]before[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("present[%d]before[%d]\n",
|
||||
EXYNOS_CISTATUS2_GET_FRAMECOUNT_PRESENT(cfg),
|
||||
EXYNOS_CISTATUS2_GET_FRAMECOUNT_BEFORE(cfg));
|
||||
|
||||
@ -398,7 +390,7 @@ static int fimc_get_buf_id(struct fimc_context *ctx)
|
||||
}
|
||||
|
||||
buf_id = frame_cnt - 1;
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
|
||||
DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
|
||||
|
||||
return buf_id;
|
||||
}
|
||||
@ -407,7 +399,7 @@ static void fimc_handle_lastend(struct fimc_context *ctx, bool enable)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
|
||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIOCTRL);
|
||||
if (enable)
|
||||
@ -424,7 +416,7 @@ static int fimc_src_set_fmt_order(struct fimc_context *ctx, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
/* RGB */
|
||||
cfg = fimc_read(EXYNOS_CISCCTRL);
|
||||
@ -497,7 +489,7 @@ static int fimc_src_set_fmt(struct device *dev, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
cfg = fimc_read(EXYNOS_MSCTRL);
|
||||
cfg &= ~EXYNOS_MSCTRL_INFORMAT_RGB;
|
||||
@ -557,8 +549,7 @@ static int fimc_src_set_transf(struct device *dev,
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg1, cfg2;
|
||||
|
||||
DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
|
||||
degree, flip);
|
||||
DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
|
||||
|
||||
cfg1 = fimc_read(EXYNOS_MSCTRL);
|
||||
cfg1 &= ~(EXYNOS_MSCTRL_FLIP_X_MIRROR |
|
||||
@ -621,10 +612,9 @@ static int fimc_set_window(struct fimc_context *ctx,
|
||||
v1 = pos->y;
|
||||
v2 = sz->vsize - pos->h - pos->y;
|
||||
|
||||
DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
|
||||
__func__, pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("%s:h1[%d]h2[%d]v1[%d]v2[%d]\n", __func__,
|
||||
h1, h2, v1, v2);
|
||||
DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]hsize[%d]vsize[%d]\n",
|
||||
pos->x, pos->y, pos->w, pos->h, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("h1[%d]h2[%d]v1[%d]v2[%d]\n", h1, h2, v1, v2);
|
||||
|
||||
/*
|
||||
* set window offset 1, 2 size
|
||||
@ -653,8 +643,8 @@ static int fimc_src_set_size(struct device *dev, int swap,
|
||||
struct drm_exynos_sz img_sz = *sz;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
|
||||
__func__, swap, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
|
||||
swap, sz->hsize, sz->vsize);
|
||||
|
||||
/* original size */
|
||||
cfg = (EXYNOS_ORGISIZE_HORIZONTAL(img_sz.hsize) |
|
||||
@ -662,8 +652,7 @@ static int fimc_src_set_size(struct device *dev, int swap,
|
||||
|
||||
fimc_write(cfg, EXYNOS_ORGISIZE);
|
||||
|
||||
DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n", __func__,
|
||||
pos->x, pos->y, pos->w, pos->h);
|
||||
DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
|
||||
|
||||
if (swap) {
|
||||
img_pos.w = pos->h;
|
||||
@ -720,7 +709,7 @@ static int fimc_src_set_addr(struct device *dev,
|
||||
|
||||
property = &c_node->property;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
|
||||
property->prop_id, buf_id, buf_type);
|
||||
|
||||
if (buf_id > FIMC_MAX_SRC) {
|
||||
@ -772,7 +761,7 @@ static int fimc_dst_set_fmt_order(struct fimc_context *ctx, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
/* RGB */
|
||||
cfg = fimc_read(EXYNOS_CISCCTRL);
|
||||
@ -851,7 +840,7 @@ static int fimc_dst_set_fmt(struct device *dev, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CIEXTEN);
|
||||
|
||||
@ -919,8 +908,7 @@ static int fimc_dst_set_transf(struct device *dev,
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
|
||||
degree, flip);
|
||||
DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CITRGFMT);
|
||||
cfg &= ~EXYNOS_CITRGFMT_FLIP_MASK;
|
||||
@ -970,7 +958,7 @@ static int fimc_dst_set_transf(struct device *dev,
|
||||
|
||||
static int fimc_get_ratio_shift(u32 src, u32 dst, u32 *ratio, u32 *shift)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
|
||||
DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst);
|
||||
|
||||
if (src >= dst * 64) {
|
||||
DRM_ERROR("failed to make ratio and shift.\n");
|
||||
@ -1039,20 +1027,20 @@ static int fimc_set_prescaler(struct fimc_context *ctx, struct fimc_scaler *sc,
|
||||
|
||||
pre_dst_width = src_w / pre_hratio;
|
||||
pre_dst_height = src_h / pre_vratio;
|
||||
DRM_DEBUG_KMS("%s:pre_dst_width[%d]pre_dst_height[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("pre_dst_width[%d]pre_dst_height[%d]\n",
|
||||
pre_dst_width, pre_dst_height);
|
||||
DRM_DEBUG_KMS("%s:pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
|
||||
__func__, pre_hratio, hfactor, pre_vratio, vfactor);
|
||||
DRM_DEBUG_KMS("pre_hratio[%d]hfactor[%d]pre_vratio[%d]vfactor[%d]\n",
|
||||
pre_hratio, hfactor, pre_vratio, vfactor);
|
||||
|
||||
sc->hratio = (src_w << 14) / (dst_w << hfactor);
|
||||
sc->vratio = (src_h << 14) / (dst_h << vfactor);
|
||||
sc->up_h = (dst_w >= src_w) ? true : false;
|
||||
sc->up_v = (dst_h >= src_h) ? true : false;
|
||||
DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
|
||||
__func__, sc->hratio, sc->vratio, sc->up_h, sc->up_v);
|
||||
DRM_DEBUG_KMS("hratio[%d]vratio[%d]up_h[%d]up_v[%d]\n",
|
||||
sc->hratio, sc->vratio, sc->up_h, sc->up_v);
|
||||
|
||||
shfactor = FIMC_SHFACTOR - (hfactor + vfactor);
|
||||
DRM_DEBUG_KMS("%s:shfactor[%d]\n", __func__, shfactor);
|
||||
DRM_DEBUG_KMS("shfactor[%d]\n", shfactor);
|
||||
|
||||
cfg = (EXYNOS_CISCPRERATIO_SHFACTOR(shfactor) |
|
||||
EXYNOS_CISCPRERATIO_PREHORRATIO(pre_hratio) |
|
||||
@ -1070,10 +1058,10 @@ static void fimc_set_scaler(struct fimc_context *ctx, struct fimc_scaler *sc)
|
||||
{
|
||||
u32 cfg, cfg_ext;
|
||||
|
||||
DRM_DEBUG_KMS("%s:range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
|
||||
__func__, sc->range, sc->bypass, sc->up_h, sc->up_v);
|
||||
DRM_DEBUG_KMS("%s:hratio[%d]vratio[%d]\n",
|
||||
__func__, sc->hratio, sc->vratio);
|
||||
DRM_DEBUG_KMS("range[%d]bypass[%d]up_h[%d]up_v[%d]\n",
|
||||
sc->range, sc->bypass, sc->up_h, sc->up_v);
|
||||
DRM_DEBUG_KMS("hratio[%d]vratio[%d]\n",
|
||||
sc->hratio, sc->vratio);
|
||||
|
||||
cfg = fimc_read(EXYNOS_CISCCTRL);
|
||||
cfg &= ~(EXYNOS_CISCCTRL_SCALERBYPASS |
|
||||
@ -1113,8 +1101,8 @@ static int fimc_dst_set_size(struct device *dev, int swap,
|
||||
struct drm_exynos_sz img_sz = *sz;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:swap[%d]hsize[%d]vsize[%d]\n",
|
||||
__func__, swap, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("swap[%d]hsize[%d]vsize[%d]\n",
|
||||
swap, sz->hsize, sz->vsize);
|
||||
|
||||
/* original size */
|
||||
cfg = (EXYNOS_ORGOSIZE_HORIZONTAL(img_sz.hsize) |
|
||||
@ -1122,8 +1110,7 @@ static int fimc_dst_set_size(struct device *dev, int swap,
|
||||
|
||||
fimc_write(cfg, EXYNOS_ORGOSIZE);
|
||||
|
||||
DRM_DEBUG_KMS("%s:x[%d]y[%d]w[%d]h[%d]\n",
|
||||
__func__, pos->x, pos->y, pos->w, pos->h);
|
||||
DRM_DEBUG_KMS("x[%d]y[%d]w[%d]h[%d]\n", pos->x, pos->y, pos->w, pos->h);
|
||||
|
||||
/* CSC ITU */
|
||||
cfg = fimc_read(EXYNOS_CIGCTRL);
|
||||
@ -1180,7 +1167,7 @@ static int fimc_dst_get_buf_seq(struct fimc_context *ctx)
|
||||
if (cfg & (mask << i))
|
||||
buf_num++;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
|
||||
DRM_DEBUG_KMS("buf_num[%d]\n", buf_num);
|
||||
|
||||
return buf_num;
|
||||
}
|
||||
@ -1194,8 +1181,7 @@ static int fimc_dst_set_buf_seq(struct fimc_context *ctx, u32 buf_id,
|
||||
u32 mask = 0x00000001 << buf_id;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
|
||||
buf_id, buf_type);
|
||||
DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
@ -1252,7 +1238,7 @@ static int fimc_dst_set_addr(struct device *dev,
|
||||
|
||||
property = &c_node->property;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
|
||||
property->prop_id, buf_id, buf_type);
|
||||
|
||||
if (buf_id > FIMC_MAX_DST) {
|
||||
@ -1302,7 +1288,7 @@ static struct exynos_drm_ipp_ops fimc_dst_ops = {
|
||||
|
||||
static int fimc_clk_ctrl(struct fimc_context *ctx, bool enable)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
|
||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||
|
||||
if (enable) {
|
||||
clk_prepare_enable(ctx->clocks[FIMC_CLK_GATE]);
|
||||
@ -1326,7 +1312,7 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
|
||||
c_node->event_work;
|
||||
int buf_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fimc id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("fimc id[%d]\n", ctx->id);
|
||||
|
||||
fimc_clear_irq(ctx);
|
||||
if (fimc_check_ovf(ctx))
|
||||
@ -1339,7 +1325,7 @@ static irqreturn_t fimc_irq_handler(int irq, void *dev_id)
|
||||
if (buf_id < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, buf_id);
|
||||
DRM_DEBUG_KMS("buf_id[%d]\n", buf_id);
|
||||
|
||||
if (fimc_dst_set_buf_seq(ctx, buf_id, IPP_BUF_DEQUEUE) < 0) {
|
||||
DRM_ERROR("failed to dequeue.\n");
|
||||
@ -1357,8 +1343,6 @@ static int fimc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
|
||||
{
|
||||
struct drm_exynos_ipp_prop_list *prop_list;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
|
||||
if (!prop_list) {
|
||||
DRM_ERROR("failed to alloc property list.\n");
|
||||
@ -1402,7 +1386,7 @@ static inline bool fimc_check_drm_flip(enum drm_exynos_flip flip)
|
||||
case EXYNOS_DRM_FLIP_BOTH:
|
||||
return true;
|
||||
default:
|
||||
DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid flip\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1419,8 +1403,6 @@ static int fimc_ippdrv_check_property(struct device *dev,
|
||||
bool swap;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
for_each_ipp_ops(i) {
|
||||
if ((i == EXYNOS_DRM_OPS_SRC) &&
|
||||
(property->cmd == IPP_CMD_WB))
|
||||
@ -1526,8 +1508,6 @@ static void fimc_clear_addr(struct fimc_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s:\n", __func__);
|
||||
|
||||
for (i = 0; i < FIMC_MAX_SRC; i++) {
|
||||
fimc_write(0, EXYNOS_CIIYSA(i));
|
||||
fimc_write(0, EXYNOS_CIICBSA(i));
|
||||
@ -1545,8 +1525,6 @@ static int fimc_ippdrv_reset(struct device *dev)
|
||||
{
|
||||
struct fimc_context *ctx = get_fimc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* reset h/w block */
|
||||
fimc_sw_reset(ctx);
|
||||
|
||||
@ -1570,7 +1548,7 @@ static int fimc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
|
||||
int ret, i;
|
||||
u32 cfg0, cfg1;
|
||||
|
||||
DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
|
||||
DRM_DEBUG_KMS("cmd[%d]\n", cmd);
|
||||
|
||||
if (!c_node) {
|
||||
DRM_ERROR("failed to get c_node.\n");
|
||||
@ -1679,7 +1657,7 @@ static void fimc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
|
||||
struct drm_exynos_ipp_set_wb set_wb = {0, 0};
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
|
||||
DRM_DEBUG_KMS("cmd[%d]\n", cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case IPP_CMD_M2M:
|
||||
@ -1869,8 +1847,7 @@ static int fimc_probe(struct platform_device *pdev)
|
||||
goto err_put_clk;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
|
||||
(int)ippdrv);
|
||||
DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
|
||||
|
||||
mutex_init(&ctx->lock);
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
@ -1917,7 +1894,7 @@ static int fimc_suspend(struct device *dev)
|
||||
{
|
||||
struct fimc_context *ctx = get_fimc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
@ -1929,7 +1906,7 @@ static int fimc_resume(struct device *dev)
|
||||
{
|
||||
struct fimc_context *ctx = get_fimc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return fimc_clk_ctrl(ctx, true);
|
||||
@ -1943,7 +1920,7 @@ static int fimc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct fimc_context *ctx = get_fimc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
return fimc_clk_ctrl(ctx, false);
|
||||
}
|
||||
@ -1952,7 +1929,7 @@ static int fimc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct fimc_context *ctx = get_fimc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
return fimc_clk_ctrl(ctx, true);
|
||||
}
|
||||
|
@ -63,14 +63,24 @@
|
||||
|
||||
struct fimd_driver_data {
|
||||
unsigned int timing_base;
|
||||
|
||||
unsigned int has_shadowcon:1;
|
||||
unsigned int has_clksel:1;
|
||||
};
|
||||
|
||||
static struct fimd_driver_data s3c64xx_fimd_driver_data = {
|
||||
.timing_base = 0x0,
|
||||
.has_clksel = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos4_fimd_driver_data = {
|
||||
.timing_base = 0x0,
|
||||
.has_shadowcon = 1,
|
||||
};
|
||||
|
||||
static struct fimd_driver_data exynos5_fimd_driver_data = {
|
||||
.timing_base = 0x20000,
|
||||
.has_shadowcon = 1,
|
||||
};
|
||||
|
||||
struct fimd_win_data {
|
||||
@ -107,10 +117,13 @@ struct fimd_context {
|
||||
atomic_t wait_vsync_event;
|
||||
|
||||
struct exynos_drm_panel_info *panel;
|
||||
struct fimd_driver_data *driver_data;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id fimd_driver_dt_match[] = {
|
||||
{ .compatible = "samsung,s3c6400-fimd",
|
||||
.data = &s3c64xx_fimd_driver_data },
|
||||
{ .compatible = "samsung,exynos4210-fimd",
|
||||
.data = &exynos4_fimd_driver_data },
|
||||
{ .compatible = "samsung,exynos5250-fimd",
|
||||
@ -137,8 +150,6 @@ static inline struct fimd_driver_data *drm_fimd_get_driver_data(
|
||||
|
||||
static bool fimd_display_is_connected(struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
|
||||
return true;
|
||||
@ -148,15 +159,11 @@ static void *fimd_get_panel(struct device *dev)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return ctx->panel;
|
||||
}
|
||||
|
||||
static int fimd_check_timing(struct device *dev, void *timing)
|
||||
static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
|
||||
return 0;
|
||||
@ -164,8 +171,6 @@ static int fimd_check_timing(struct device *dev, void *timing)
|
||||
|
||||
static int fimd_display_power_on(struct device *dev, int mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
@ -175,7 +180,7 @@ static struct exynos_drm_display_ops fimd_display_ops = {
|
||||
.type = EXYNOS_DISPLAY_TYPE_LCD,
|
||||
.is_connected = fimd_display_is_connected,
|
||||
.get_panel = fimd_get_panel,
|
||||
.check_timing = fimd_check_timing,
|
||||
.check_mode = fimd_check_mode,
|
||||
.power_on = fimd_display_power_on,
|
||||
};
|
||||
|
||||
@ -183,7 +188,7 @@ static void fimd_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
|
||||
DRM_DEBUG_KMS("%d\n", mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
@ -221,8 +226,6 @@ static void fimd_apply(struct device *subdrv_dev)
|
||||
struct fimd_win_data *win_data;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
for (i = 0; i < WINDOWS_NR; i++) {
|
||||
win_data = &ctx->win_data[i];
|
||||
if (win_data->enabled && (ovl_ops && ovl_ops->commit))
|
||||
@ -239,15 +242,12 @@ static void fimd_commit(struct device *dev)
|
||||
struct exynos_drm_panel_info *panel = ctx->panel;
|
||||
struct fb_videomode *timing = &panel->timing;
|
||||
struct fimd_driver_data *driver_data;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
u32 val;
|
||||
|
||||
driver_data = drm_fimd_get_driver_data(pdev);
|
||||
driver_data = ctx->driver_data;
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* setup polarity values from machine code. */
|
||||
writel(ctx->vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
|
||||
|
||||
@ -274,6 +274,11 @@ static void fimd_commit(struct device *dev)
|
||||
val = ctx->vidcon0;
|
||||
val &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
|
||||
|
||||
if (ctx->driver_data->has_clksel) {
|
||||
val &= ~VIDCON0_CLKSEL_MASK;
|
||||
val |= VIDCON0_CLKSEL_LCD;
|
||||
}
|
||||
|
||||
if (ctx->clkdiv > 1)
|
||||
val |= VIDCON0_CLKVAL_F(ctx->clkdiv - 1) | VIDCON0_CLKDIR;
|
||||
else
|
||||
@ -292,8 +297,6 @@ static int fimd_enable_vblank(struct device *dev)
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
u32 val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return -EPERM;
|
||||
|
||||
@ -319,8 +322,6 @@ static void fimd_disable_vblank(struct device *dev)
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
u32 val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
@ -370,8 +371,6 @@ static void fimd_win_mode_set(struct device *dev,
|
||||
int win;
|
||||
unsigned long offset;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!overlay) {
|
||||
dev_err(dev, "overlay is NULL\n");
|
||||
return;
|
||||
@ -381,7 +380,7 @@ static void fimd_win_mode_set(struct device *dev,
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
offset = overlay->fb_x * (overlay->bpp >> 3);
|
||||
@ -418,8 +417,6 @@ static void fimd_win_set_pixfmt(struct device *dev, unsigned int win)
|
||||
struct fimd_win_data *win_data = &ctx->win_data[win];
|
||||
unsigned long val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
val = WINCONx_ENWIN;
|
||||
|
||||
switch (win_data->bpp) {
|
||||
@ -478,8 +475,6 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win)
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
unsigned int keycon0 = 0, keycon1 = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
keycon0 = ~(WxKEYCON0_KEYBL_EN | WxKEYCON0_KEYEN_F |
|
||||
WxKEYCON0_DIRCON) | WxKEYCON0_COMPKEY(0);
|
||||
|
||||
@ -489,6 +484,33 @@ static void fimd_win_set_colkey(struct device *dev, unsigned int win)
|
||||
writel(keycon1, ctx->regs + WKEYCON1_BASE(win));
|
||||
}
|
||||
|
||||
/**
|
||||
* shadow_protect_win() - disable updating values from shadow registers at vsync
|
||||
*
|
||||
* @win: window to protect registers for
|
||||
* @protect: 1 to protect (disable updates)
|
||||
*/
|
||||
static void fimd_shadow_protect_win(struct fimd_context *ctx,
|
||||
int win, bool protect)
|
||||
{
|
||||
u32 reg, bits, val;
|
||||
|
||||
if (ctx->driver_data->has_shadowcon) {
|
||||
reg = SHADOWCON;
|
||||
bits = SHADOWCON_WINx_PROTECT(win);
|
||||
} else {
|
||||
reg = PRTCON;
|
||||
bits = PRTCON_PROTECT;
|
||||
}
|
||||
|
||||
val = readl(ctx->regs + reg);
|
||||
if (protect)
|
||||
val |= bits;
|
||||
else
|
||||
val &= ~bits;
|
||||
writel(val, ctx->regs + reg);
|
||||
}
|
||||
|
||||
static void fimd_win_commit(struct device *dev, int zpos)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
@ -498,21 +520,19 @@ static void fimd_win_commit(struct device *dev, int zpos)
|
||||
unsigned int last_x;
|
||||
unsigned int last_y;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
|
||||
/*
|
||||
* SHADOWCON register is used for enabling timing.
|
||||
* SHADOWCON/PRTCON register is used for enabling timing.
|
||||
*
|
||||
* for example, once only width value of a register is set,
|
||||
* if the dma is started then fimd hardware could malfunction so
|
||||
@ -522,9 +542,7 @@ static void fimd_win_commit(struct device *dev, int zpos)
|
||||
*/
|
||||
|
||||
/* protect windows */
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val |= SHADOWCON_WINx_PROTECT(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
fimd_shadow_protect_win(ctx, win, true);
|
||||
|
||||
/* buffer start address */
|
||||
val = (unsigned long)win_data->dma_addr;
|
||||
@ -602,10 +620,13 @@ static void fimd_win_commit(struct device *dev, int zpos)
|
||||
writel(val, ctx->regs + WINCON(win));
|
||||
|
||||
/* Enable DMA channel and unprotect windows */
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val |= SHADOWCON_CHx_ENABLE(win);
|
||||
val &= ~SHADOWCON_WINx_PROTECT(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
fimd_shadow_protect_win(ctx, win, false);
|
||||
|
||||
if (ctx->driver_data->has_shadowcon) {
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val |= SHADOWCON_CHx_ENABLE(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
}
|
||||
|
||||
win_data->enabled = true;
|
||||
}
|
||||
@ -617,12 +638,10 @@ static void fimd_win_disable(struct device *dev, int zpos)
|
||||
int win = zpos;
|
||||
u32 val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
@ -634,9 +653,7 @@ static void fimd_win_disable(struct device *dev, int zpos)
|
||||
}
|
||||
|
||||
/* protect windows */
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val |= SHADOWCON_WINx_PROTECT(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
fimd_shadow_protect_win(ctx, win, true);
|
||||
|
||||
/* wincon */
|
||||
val = readl(ctx->regs + WINCON(win));
|
||||
@ -644,10 +661,13 @@ static void fimd_win_disable(struct device *dev, int zpos)
|
||||
writel(val, ctx->regs + WINCON(win));
|
||||
|
||||
/* unprotect windows */
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val &= ~SHADOWCON_CHx_ENABLE(win);
|
||||
val &= ~SHADOWCON_WINx_PROTECT(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
if (ctx->driver_data->has_shadowcon) {
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val &= ~SHADOWCON_CHx_ENABLE(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
}
|
||||
|
||||
fimd_shadow_protect_win(ctx, win, false);
|
||||
|
||||
win_data->enabled = false;
|
||||
}
|
||||
@ -697,8 +717,6 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
|
||||
|
||||
static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* enable drm irq mode.
|
||||
* - with irq_enabled = 1, we can use the vblank feature.
|
||||
@ -725,8 +743,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
|
||||
static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* detach this sub driver from iommu mapping if supported. */
|
||||
if (is_drm_iommu_supported(drm_dev))
|
||||
drm_iommu_detach_device(drm_dev, dev);
|
||||
@ -741,8 +757,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx,
|
||||
u32 best_framerate = 0;
|
||||
u32 framerate;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
retrace = timing->left_margin + timing->hsync_len +
|
||||
timing->right_margin + timing->xres;
|
||||
retrace *= timing->upper_margin + timing->vsync_len +
|
||||
@ -777,10 +791,6 @@ static int fimd_calc_clkdiv(struct fimd_context *ctx,
|
||||
|
||||
static void fimd_clear_win(struct fimd_context *ctx, int win)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
writel(0, ctx->regs + WINCON(win));
|
||||
writel(0, ctx->regs + VIDOSD_A(win));
|
||||
writel(0, ctx->regs + VIDOSD_B(win));
|
||||
@ -789,15 +799,11 @@ static void fimd_clear_win(struct fimd_context *ctx, int win)
|
||||
if (win == 1 || win == 2)
|
||||
writel(0, ctx->regs + VIDOSD_D(win));
|
||||
|
||||
val = readl(ctx->regs + SHADOWCON);
|
||||
val &= ~SHADOWCON_WINx_PROTECT(win);
|
||||
writel(val, ctx->regs + SHADOWCON);
|
||||
fimd_shadow_protect_win(ctx, win, false);
|
||||
}
|
||||
|
||||
static int fimd_clock(struct fimd_context *ctx, bool enable)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (enable) {
|
||||
int ret;
|
||||
|
||||
@ -883,8 +889,6 @@ static int fimd_probe(struct platform_device *pdev)
|
||||
int win;
|
||||
int ret = -EINVAL;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (dev->of_node) {
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
@ -949,6 +953,7 @@ static int fimd_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ctx->driver_data = drm_fimd_get_driver_data(pdev);
|
||||
ctx->vidcon0 = pdata->vidcon0;
|
||||
ctx->vidcon1 = pdata->vidcon1;
|
||||
ctx->default_win = pdata->default_win;
|
||||
@ -989,8 +994,6 @@ static int fimd_remove(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct fimd_context *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_subdrv_unregister(&ctx->subdrv);
|
||||
|
||||
if (ctx->suspended)
|
||||
@ -1055,8 +1058,6 @@ static int fimd_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return fimd_activate(ctx, false);
|
||||
}
|
||||
|
||||
@ -1064,14 +1065,15 @@ static int fimd_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct fimd_context *ctx = get_fimd_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return fimd_activate(ctx, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct platform_device_id fimd_driver_ids[] = {
|
||||
{
|
||||
.name = "s3c64xx-fb",
|
||||
.driver_data = (unsigned long)&s3c64xx_fimd_driver_data,
|
||||
}, {
|
||||
.name = "exynos4-fb",
|
||||
.driver_data = (unsigned long)&exynos4_fimd_driver_data,
|
||||
}, {
|
||||
|
@ -132,8 +132,6 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj)
|
||||
struct drm_gem_object *obj;
|
||||
struct exynos_drm_gem_buf *buf;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
obj = &exynos_gem_obj->base;
|
||||
buf = exynos_gem_obj->buffer;
|
||||
|
||||
@ -227,7 +225,6 @@ struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
|
||||
}
|
||||
|
||||
size = roundup_gem_size(size, flags);
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ret = check_gem_flags(flags);
|
||||
if (ret)
|
||||
@ -268,8 +265,6 @@ int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
|
||||
if (IS_ERR(exynos_gem_obj))
|
||||
return PTR_ERR(exynos_gem_obj);
|
||||
@ -331,8 +326,6 @@ int exynos_drm_gem_map_offset_ioctl(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct drm_exynos_gem_map_off *args = data;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
DRM_DEBUG_KMS("handle = 0x%x, offset = 0x%lx\n",
|
||||
args->handle, (unsigned long)args->offset);
|
||||
|
||||
@ -371,8 +364,6 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
|
||||
unsigned long vm_size;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
|
||||
vma->vm_private_data = obj;
|
||||
vma->vm_ops = drm_dev->driver->gem_vm_ops;
|
||||
@ -429,9 +420,7 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
{
|
||||
struct drm_exynos_gem_mmap *args = data;
|
||||
struct drm_gem_object *obj;
|
||||
unsigned int addr;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
unsigned long addr;
|
||||
|
||||
if (!(dev->driver->driver_features & DRIVER_GEM)) {
|
||||
DRM_ERROR("does not support GEM.\n");
|
||||
@ -473,14 +462,14 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
drm_gem_object_unreference(obj);
|
||||
|
||||
if (IS_ERR((void *)addr)) {
|
||||
if (IS_ERR_VALUE(addr)) {
|
||||
/* check filp->f_op, filp->private_data are restored */
|
||||
if (file_priv->filp->f_op == &exynos_drm_gem_fops) {
|
||||
file_priv->filp->f_op = fops_get(dev->driver->fops);
|
||||
file_priv->filp->private_data = file_priv;
|
||||
}
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
return PTR_ERR((void *)addr);
|
||||
return (int)addr;
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@ -643,8 +632,6 @@ void exynos_gem_unmap_sgt_from_dma(struct drm_device *drm_dev,
|
||||
|
||||
int exynos_drm_gem_init_object(struct drm_gem_object *obj)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -653,8 +640,6 @@ void exynos_drm_gem_free_object(struct drm_gem_object *obj)
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
struct exynos_drm_gem_buf *buf;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_gem_obj = to_exynos_gem_obj(obj);
|
||||
buf = exynos_gem_obj->buffer;
|
||||
|
||||
@ -671,8 +656,6 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
|
||||
struct exynos_drm_gem_obj *exynos_gem_obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* alocate memory to be used for framebuffer.
|
||||
* - this callback would be called by user application
|
||||
@ -704,8 +687,6 @@ int exynos_drm_gem_dumb_map_offset(struct drm_file *file_priv,
|
||||
struct drm_gem_object *obj;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/*
|
||||
@ -743,8 +724,6 @@ int exynos_drm_gem_dumb_destroy(struct drm_file *file_priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* obj->refcount and obj->handle_count are decreased and
|
||||
* if both them are 0 then exynos_drm_gem_free_object()
|
||||
@ -788,8 +767,6 @@ int exynos_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* set vm_area_struct. */
|
||||
ret = drm_gem_mmap(filp, vma);
|
||||
if (ret < 0) {
|
||||
|
@ -400,8 +400,6 @@ static int gsc_sw_reset(struct gsc_context *ctx)
|
||||
u32 cfg;
|
||||
int count = GSC_RESET_TIMEOUT;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* s/w reset */
|
||||
cfg = (GSC_SW_RESET_SRESET);
|
||||
gsc_write(cfg, GSC_SW_RESET);
|
||||
@ -441,8 +439,6 @@ static void gsc_set_gscblk_fimd_wb(struct gsc_context *ctx, bool enable)
|
||||
{
|
||||
u32 gscblk_cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
gscblk_cfg = readl(SYSREG_GSCBLK_CFG1);
|
||||
|
||||
if (enable)
|
||||
@ -460,7 +456,7 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:enable[%d]overflow[%d]level[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("enable[%d]overflow[%d]level[%d]\n",
|
||||
enable, overflow, done);
|
||||
|
||||
cfg = gsc_read(GSC_IRQ);
|
||||
@ -491,7 +487,7 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
cfg = gsc_read(GSC_IN_CON);
|
||||
cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
|
||||
@ -567,8 +563,7 @@ static int gsc_src_set_transf(struct device *dev,
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
|
||||
degree, flip);
|
||||
DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
|
||||
|
||||
cfg = gsc_read(GSC_IN_CON);
|
||||
cfg &= ~GSC_IN_ROT_MASK;
|
||||
@ -616,8 +611,8 @@ static int gsc_src_set_size(struct device *dev, int swap,
|
||||
struct gsc_scaler *sc = &ctx->sc;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
|
||||
__func__, swap, pos->x, pos->y, pos->w, pos->h);
|
||||
DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
|
||||
swap, pos->x, pos->y, pos->w, pos->h);
|
||||
|
||||
if (swap) {
|
||||
img_pos.w = pos->h;
|
||||
@ -634,8 +629,7 @@ static int gsc_src_set_size(struct device *dev, int swap,
|
||||
GSC_CROPPED_HEIGHT(img_pos.h));
|
||||
gsc_write(cfg, GSC_CROPPED_SIZE);
|
||||
|
||||
DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
|
||||
__func__, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize);
|
||||
|
||||
/* original size */
|
||||
cfg = gsc_read(GSC_SRCIMG_SIZE);
|
||||
@ -650,8 +644,7 @@ static int gsc_src_set_size(struct device *dev, int swap,
|
||||
cfg = gsc_read(GSC_IN_CON);
|
||||
cfg &= ~GSC_IN_RGB_TYPE_MASK;
|
||||
|
||||
DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
|
||||
__func__, pos->w, sc->range);
|
||||
DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range);
|
||||
|
||||
if (pos->w >= GSC_WIDTH_ITU_709)
|
||||
if (sc->range)
|
||||
@ -677,8 +670,7 @@ static int gsc_src_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
|
||||
u32 cfg;
|
||||
u32 mask = 0x00000001 << buf_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
|
||||
buf_id, buf_type);
|
||||
DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
|
||||
|
||||
/* mask register set */
|
||||
cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
|
||||
@ -721,7 +713,7 @@ static int gsc_src_set_addr(struct device *dev,
|
||||
|
||||
property = &c_node->property;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
|
||||
property->prop_id, buf_id, buf_type);
|
||||
|
||||
if (buf_id > GSC_MAX_SRC) {
|
||||
@ -765,7 +757,7 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt)
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:fmt[0x%x]\n", __func__, fmt);
|
||||
DRM_DEBUG_KMS("fmt[0x%x]\n", fmt);
|
||||
|
||||
cfg = gsc_read(GSC_OUT_CON);
|
||||
cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
|
||||
@ -838,8 +830,7 @@ static int gsc_dst_set_transf(struct device *dev,
|
||||
struct exynos_drm_ippdrv *ippdrv = &ctx->ippdrv;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:degree[%d]flip[0x%x]\n", __func__,
|
||||
degree, flip);
|
||||
DRM_DEBUG_KMS("degree[%d]flip[0x%x]\n", degree, flip);
|
||||
|
||||
cfg = gsc_read(GSC_IN_CON);
|
||||
cfg &= ~GSC_IN_ROT_MASK;
|
||||
@ -881,7 +872,7 @@ static int gsc_dst_set_transf(struct device *dev,
|
||||
|
||||
static int gsc_get_ratio_shift(u32 src, u32 dst, u32 *ratio)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s:src[%d]dst[%d]\n", __func__, src, dst);
|
||||
DRM_DEBUG_KMS("src[%d]dst[%d]\n", src, dst);
|
||||
|
||||
if (src >= dst * 8) {
|
||||
DRM_ERROR("failed to make ratio and shift.\n");
|
||||
@ -944,20 +935,19 @@ static int gsc_set_prescaler(struct gsc_context *ctx, struct gsc_scaler *sc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:pre_hratio[%d]pre_vratio[%d]\n",
|
||||
__func__, sc->pre_hratio, sc->pre_vratio);
|
||||
DRM_DEBUG_KMS("pre_hratio[%d]pre_vratio[%d]\n",
|
||||
sc->pre_hratio, sc->pre_vratio);
|
||||
|
||||
sc->main_hratio = (src_w << 16) / dst_w;
|
||||
sc->main_vratio = (src_h << 16) / dst_h;
|
||||
|
||||
DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
|
||||
__func__, sc->main_hratio, sc->main_vratio);
|
||||
DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n",
|
||||
sc->main_hratio, sc->main_vratio);
|
||||
|
||||
gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio,
|
||||
&sc->pre_shfactor);
|
||||
|
||||
DRM_DEBUG_KMS("%s:pre_shfactor[%d]\n", __func__,
|
||||
sc->pre_shfactor);
|
||||
DRM_DEBUG_KMS("pre_shfactor[%d]\n", sc->pre_shfactor);
|
||||
|
||||
cfg = (GSC_PRESC_SHFACTOR(sc->pre_shfactor) |
|
||||
GSC_PRESC_H_RATIO(sc->pre_hratio) |
|
||||
@ -1023,8 +1013,8 @@ static void gsc_set_scaler(struct gsc_context *ctx, struct gsc_scaler *sc)
|
||||
{
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:main_hratio[%ld]main_vratio[%ld]\n",
|
||||
__func__, sc->main_hratio, sc->main_vratio);
|
||||
DRM_DEBUG_KMS("main_hratio[%ld]main_vratio[%ld]\n",
|
||||
sc->main_hratio, sc->main_vratio);
|
||||
|
||||
gsc_set_h_coef(ctx, sc->main_hratio);
|
||||
cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
|
||||
@ -1043,8 +1033,8 @@ static int gsc_dst_set_size(struct device *dev, int swap,
|
||||
struct gsc_scaler *sc = &ctx->sc;
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
|
||||
__func__, swap, pos->x, pos->y, pos->w, pos->h);
|
||||
DRM_DEBUG_KMS("swap[%d]x[%d]y[%d]w[%d]h[%d]\n",
|
||||
swap, pos->x, pos->y, pos->w, pos->h);
|
||||
|
||||
if (swap) {
|
||||
img_pos.w = pos->h;
|
||||
@ -1060,8 +1050,7 @@ static int gsc_dst_set_size(struct device *dev, int swap,
|
||||
cfg = (GSC_SCALED_WIDTH(img_pos.w) | GSC_SCALED_HEIGHT(img_pos.h));
|
||||
gsc_write(cfg, GSC_SCALED_SIZE);
|
||||
|
||||
DRM_DEBUG_KMS("%s:hsize[%d]vsize[%d]\n",
|
||||
__func__, sz->hsize, sz->vsize);
|
||||
DRM_DEBUG_KMS("hsize[%d]vsize[%d]\n", sz->hsize, sz->vsize);
|
||||
|
||||
/* original size */
|
||||
cfg = gsc_read(GSC_DSTIMG_SIZE);
|
||||
@ -1074,8 +1063,7 @@ static int gsc_dst_set_size(struct device *dev, int swap,
|
||||
cfg = gsc_read(GSC_OUT_CON);
|
||||
cfg &= ~GSC_OUT_RGB_TYPE_MASK;
|
||||
|
||||
DRM_DEBUG_KMS("%s:width[%d]range[%d]\n",
|
||||
__func__, pos->w, sc->range);
|
||||
DRM_DEBUG_KMS("width[%d]range[%d]\n", pos->w, sc->range);
|
||||
|
||||
if (pos->w >= GSC_WIDTH_ITU_709)
|
||||
if (sc->range)
|
||||
@ -1104,7 +1092,7 @@ static int gsc_dst_get_buf_seq(struct gsc_context *ctx)
|
||||
if (cfg & (mask << i))
|
||||
buf_num--;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_num[%d]\n", __func__, buf_num);
|
||||
DRM_DEBUG_KMS("buf_num[%d]\n", buf_num);
|
||||
|
||||
return buf_num;
|
||||
}
|
||||
@ -1118,8 +1106,7 @@ static int gsc_dst_set_buf_seq(struct gsc_context *ctx, u32 buf_id,
|
||||
u32 mask = 0x00000001 << buf_id;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]buf_type[%d]\n", __func__,
|
||||
buf_id, buf_type);
|
||||
DRM_DEBUG_KMS("buf_id[%d]buf_type[%d]\n", buf_id, buf_type);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
@ -1177,7 +1164,7 @@ static int gsc_dst_set_addr(struct device *dev,
|
||||
|
||||
property = &c_node->property;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]buf_type[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]buf_type[%d]\n",
|
||||
property->prop_id, buf_id, buf_type);
|
||||
|
||||
if (buf_id > GSC_MAX_DST) {
|
||||
@ -1217,7 +1204,7 @@ static struct exynos_drm_ipp_ops gsc_dst_ops = {
|
||||
|
||||
static int gsc_clk_ctrl(struct gsc_context *ctx, bool enable)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
|
||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||
|
||||
if (enable) {
|
||||
clk_enable(ctx->gsc_clk);
|
||||
@ -1236,7 +1223,7 @@ static int gsc_get_src_buf_index(struct gsc_context *ctx)
|
||||
u32 buf_id = GSC_MAX_SRC;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
|
||||
|
||||
cfg = gsc_read(GSC_IN_BASE_ADDR_Y_MASK);
|
||||
curr_index = GSC_IN_CURR_GET_INDEX(cfg);
|
||||
@ -1259,7 +1246,7 @@ static int gsc_get_src_buf_index(struct gsc_context *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
|
||||
DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg,
|
||||
curr_index, buf_id);
|
||||
|
||||
return buf_id;
|
||||
@ -1271,7 +1258,7 @@ static int gsc_get_dst_buf_index(struct gsc_context *ctx)
|
||||
u32 buf_id = GSC_MAX_DST;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
|
||||
|
||||
cfg = gsc_read(GSC_OUT_BASE_ADDR_Y_MASK);
|
||||
curr_index = GSC_OUT_CURR_GET_INDEX(cfg);
|
||||
@ -1294,7 +1281,7 @@ static int gsc_get_dst_buf_index(struct gsc_context *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:cfg[0x%x]curr_index[%d]buf_id[%d]\n", __func__, cfg,
|
||||
DRM_DEBUG_KMS("cfg[0x%x]curr_index[%d]buf_id[%d]\n", cfg,
|
||||
curr_index, buf_id);
|
||||
|
||||
return buf_id;
|
||||
@ -1310,7 +1297,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
|
||||
u32 status;
|
||||
int buf_id[EXYNOS_DRM_OPS_MAX];
|
||||
|
||||
DRM_DEBUG_KMS("%s:gsc id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("gsc id[%d]\n", ctx->id);
|
||||
|
||||
status = gsc_read(GSC_IRQ);
|
||||
if (status & GSC_IRQ_STATUS_OR_IRQ) {
|
||||
@ -1331,7 +1318,7 @@ static irqreturn_t gsc_irq_handler(int irq, void *dev_id)
|
||||
if (buf_id[EXYNOS_DRM_OPS_DST] < 0)
|
||||
return IRQ_HANDLED;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id_src[%d]buf_id_dst[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("buf_id_src[%d]buf_id_dst[%d]\n",
|
||||
buf_id[EXYNOS_DRM_OPS_SRC], buf_id[EXYNOS_DRM_OPS_DST]);
|
||||
|
||||
event_work->ippdrv = ippdrv;
|
||||
@ -1350,8 +1337,6 @@ static int gsc_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
|
||||
{
|
||||
struct drm_exynos_ipp_prop_list *prop_list;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
|
||||
if (!prop_list) {
|
||||
DRM_ERROR("failed to alloc property list.\n");
|
||||
@ -1394,7 +1379,7 @@ static inline bool gsc_check_drm_flip(enum drm_exynos_flip flip)
|
||||
case EXYNOS_DRM_FLIP_BOTH:
|
||||
return true;
|
||||
default:
|
||||
DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid flip\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1411,8 +1396,6 @@ static int gsc_ippdrv_check_property(struct device *dev,
|
||||
bool swap;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
for_each_ipp_ops(i) {
|
||||
if ((i == EXYNOS_DRM_OPS_SRC) &&
|
||||
(property->cmd == IPP_CMD_WB))
|
||||
@ -1521,8 +1504,6 @@ static int gsc_ippdrv_reset(struct device *dev)
|
||||
struct gsc_scaler *sc = &ctx->sc;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* reset h/w block */
|
||||
ret = gsc_sw_reset(ctx);
|
||||
if (ret < 0) {
|
||||
@ -1549,7 +1530,7 @@ static int gsc_ippdrv_start(struct device *dev, enum drm_exynos_ipp_cmd cmd)
|
||||
u32 cfg;
|
||||
int ret, i;
|
||||
|
||||
DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
|
||||
DRM_DEBUG_KMS("cmd[%d]\n", cmd);
|
||||
|
||||
if (!c_node) {
|
||||
DRM_ERROR("failed to get c_node.\n");
|
||||
@ -1643,7 +1624,7 @@ static void gsc_ippdrv_stop(struct device *dev, enum drm_exynos_ipp_cmd cmd)
|
||||
struct drm_exynos_ipp_set_wb set_wb = {0, 0};
|
||||
u32 cfg;
|
||||
|
||||
DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, cmd);
|
||||
DRM_DEBUG_KMS("cmd[%d]\n", cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case IPP_CMD_M2M:
|
||||
@ -1728,8 +1709,7 @@ static int gsc_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]ippdrv[0x%x]\n", __func__, ctx->id,
|
||||
(int)ippdrv);
|
||||
DRM_DEBUG_KMS("id[%d]ippdrv[0x%x]\n", ctx->id, (int)ippdrv);
|
||||
|
||||
mutex_init(&ctx->lock);
|
||||
platform_set_drvdata(pdev, ctx);
|
||||
@ -1772,7 +1752,7 @@ static int gsc_suspend(struct device *dev)
|
||||
{
|
||||
struct gsc_context *ctx = get_gsc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
@ -1784,7 +1764,7 @@ static int gsc_resume(struct device *dev)
|
||||
{
|
||||
struct gsc_context *ctx = get_gsc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return gsc_clk_ctrl(ctx, true);
|
||||
@ -1798,7 +1778,7 @@ static int gsc_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct gsc_context *ctx = get_gsc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
return gsc_clk_ctrl(ctx, false);
|
||||
}
|
||||
@ -1807,7 +1787,7 @@ static int gsc_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct gsc_context *ctx = get_gsc_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __FILE__, ctx->id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", ctx->id);
|
||||
|
||||
return gsc_clk_ctrl(ctx, true);
|
||||
}
|
||||
|
@ -88,16 +88,12 @@ void exynos_mixer_drv_attach(struct exynos_drm_hdmi_context *ctx)
|
||||
|
||||
void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ops)
|
||||
hdmi_ops = ops;
|
||||
}
|
||||
|
||||
void exynos_mixer_ops_register(struct exynos_mixer_ops *ops)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ops)
|
||||
mixer_ops = ops;
|
||||
}
|
||||
@ -106,8 +102,6 @@ static bool drm_hdmi_is_connected(struct device *dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->is_connected)
|
||||
return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx);
|
||||
|
||||
@ -119,34 +113,31 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->get_edid)
|
||||
return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int drm_hdmi_check_timing(struct device *dev, void *timing)
|
||||
static int drm_hdmi_check_mode(struct device *dev,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* Both, mixer and hdmi should be able to handle the requested mode.
|
||||
* If any of the two fails, return mode as BAD.
|
||||
*/
|
||||
|
||||
if (mixer_ops && mixer_ops->check_timing)
|
||||
ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);
|
||||
if (mixer_ops && mixer_ops->check_mode)
|
||||
ret = mixer_ops->check_mode(ctx->mixer_ctx->ctx, mode);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (hdmi_ops && hdmi_ops->check_timing)
|
||||
return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
|
||||
if (hdmi_ops && hdmi_ops->check_mode)
|
||||
return hdmi_ops->check_mode(ctx->hdmi_ctx->ctx, mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -155,8 +146,6 @@ static int drm_hdmi_power_on(struct device *dev, int mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->power_on)
|
||||
return hdmi_ops->power_on(ctx->hdmi_ctx->ctx, mode);
|
||||
|
||||
@ -167,7 +156,7 @@ static struct exynos_drm_display_ops drm_hdmi_display_ops = {
|
||||
.type = EXYNOS_DISPLAY_TYPE_HDMI,
|
||||
.is_connected = drm_hdmi_is_connected,
|
||||
.get_edid = drm_hdmi_get_edid,
|
||||
.check_timing = drm_hdmi_check_timing,
|
||||
.check_mode = drm_hdmi_check_mode,
|
||||
.power_on = drm_hdmi_power_on,
|
||||
};
|
||||
|
||||
@ -177,8 +166,6 @@ static int drm_hdmi_enable_vblank(struct device *subdrv_dev)
|
||||
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
|
||||
struct exynos_drm_manager *manager = subdrv->manager;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (mixer_ops && mixer_ops->enable_vblank)
|
||||
return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx,
|
||||
manager->pipe);
|
||||
@ -190,8 +177,6 @@ static void drm_hdmi_disable_vblank(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (mixer_ops && mixer_ops->disable_vblank)
|
||||
return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx);
|
||||
}
|
||||
@ -200,8 +185,6 @@ static void drm_hdmi_wait_for_vblank(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (mixer_ops && mixer_ops->wait_for_vblank)
|
||||
mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx);
|
||||
}
|
||||
@ -214,11 +197,9 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
|
||||
struct drm_display_mode *m;
|
||||
int mode_ok;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
drm_mode_set_crtcinfo(adjusted_mode, 0);
|
||||
|
||||
mode_ok = drm_hdmi_check_timing(subdrv_dev, adjusted_mode);
|
||||
mode_ok = drm_hdmi_check_mode(subdrv_dev, adjusted_mode);
|
||||
|
||||
/* just return if user desired mode exists. */
|
||||
if (mode_ok == 0)
|
||||
@ -229,7 +210,7 @@ static void drm_hdmi_mode_fixup(struct device *subdrv_dev,
|
||||
* to adjusted_mode.
|
||||
*/
|
||||
list_for_each_entry(m, &connector->modes, head) {
|
||||
mode_ok = drm_hdmi_check_timing(subdrv_dev, m);
|
||||
mode_ok = drm_hdmi_check_mode(subdrv_dev, m);
|
||||
|
||||
if (mode_ok == 0) {
|
||||
struct drm_mode_object base;
|
||||
@ -256,8 +237,6 @@ static void drm_hdmi_mode_set(struct device *subdrv_dev, void *mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->mode_set)
|
||||
hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode);
|
||||
}
|
||||
@ -267,8 +246,6 @@ static void drm_hdmi_get_max_resol(struct device *subdrv_dev,
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->get_max_resol)
|
||||
hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height);
|
||||
}
|
||||
@ -277,8 +254,6 @@ static void drm_hdmi_commit(struct device *subdrv_dev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (hdmi_ops && hdmi_ops->commit)
|
||||
hdmi_ops->commit(ctx->hdmi_ctx->ctx);
|
||||
}
|
||||
@ -287,8 +262,6 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (mixer_ops && mixer_ops->dpms)
|
||||
mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
|
||||
|
||||
@ -301,8 +274,6 @@ static void drm_hdmi_apply(struct device *subdrv_dev)
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
for (i = 0; i < MIXER_WIN_NR; i++) {
|
||||
if (!ctx->enabled[i])
|
||||
continue;
|
||||
@ -331,8 +302,6 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
|
||||
{
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (mixer_ops && mixer_ops->win_mode_set)
|
||||
mixer_ops->win_mode_set(ctx->mixer_ctx->ctx, overlay);
|
||||
}
|
||||
@ -342,9 +311,7 @@ static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win < 0 || win > MIXER_WIN_NR) {
|
||||
if (win < 0 || win >= MIXER_WIN_NR) {
|
||||
DRM_ERROR("mixer window[%d] is wrong\n", win);
|
||||
return;
|
||||
}
|
||||
@ -360,9 +327,7 @@ static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
|
||||
struct drm_hdmi_context *ctx = to_context(subdrv_dev);
|
||||
int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win < 0 || win > MIXER_WIN_NR) {
|
||||
if (win < 0 || win >= MIXER_WIN_NR) {
|
||||
DRM_ERROR("mixer window[%d] is wrong\n", win);
|
||||
return;
|
||||
}
|
||||
@ -392,8 +357,6 @@ static int hdmi_subdrv_probe(struct drm_device *drm_dev,
|
||||
struct exynos_drm_subdrv *subdrv = to_subdrv(dev);
|
||||
struct drm_hdmi_context *ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!hdmi_ctx) {
|
||||
DRM_ERROR("hdmi context not initialized.\n");
|
||||
return -EFAULT;
|
||||
@ -440,8 +403,6 @@ static int exynos_drm_hdmi_probe(struct platform_device *pdev)
|
||||
struct exynos_drm_subdrv *subdrv;
|
||||
struct drm_hdmi_context *ctx;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx) {
|
||||
DRM_LOG_KMS("failed to alloc common hdmi context.\n");
|
||||
@ -466,8 +427,6 @@ static int exynos_drm_hdmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_subdrv_unregister(&ctx->subdrv);
|
||||
|
||||
return 0;
|
||||
|
@ -32,11 +32,11 @@ struct exynos_hdmi_ops {
|
||||
bool (*is_connected)(void *ctx);
|
||||
struct edid *(*get_edid)(void *ctx,
|
||||
struct drm_connector *connector);
|
||||
int (*check_timing)(void *ctx, struct fb_videomode *timing);
|
||||
int (*check_mode)(void *ctx, struct drm_display_mode *mode);
|
||||
int (*power_on)(void *ctx, int mode);
|
||||
|
||||
/* manager */
|
||||
void (*mode_set)(void *ctx, void *mode);
|
||||
void (*mode_set)(void *ctx, struct drm_display_mode *mode);
|
||||
void (*get_max_resol)(void *ctx, unsigned int *width,
|
||||
unsigned int *height);
|
||||
void (*commit)(void *ctx);
|
||||
@ -57,7 +57,7 @@ struct exynos_mixer_ops {
|
||||
void (*win_disable)(void *ctx, int zpos);
|
||||
|
||||
/* display */
|
||||
int (*check_timing)(void *ctx, struct fb_videomode *timing);
|
||||
int (*check_mode)(void *ctx, struct drm_display_mode *mode);
|
||||
};
|
||||
|
||||
void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
|
||||
|
@ -131,8 +131,6 @@ void exynos_platform_device_ipp_unregister(void)
|
||||
|
||||
int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!ippdrv)
|
||||
return -EINVAL;
|
||||
|
||||
@ -145,8 +143,6 @@ int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
|
||||
|
||||
int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!ippdrv)
|
||||
return -EINVAL;
|
||||
|
||||
@ -162,8 +158,6 @@ static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj,
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* do the allocation under our mutexlock */
|
||||
mutex_lock(lock);
|
||||
ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
|
||||
@ -179,7 +173,7 @@ static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
|
||||
{
|
||||
void *obj;
|
||||
|
||||
DRM_DEBUG_KMS("%s:id[%d]\n", __func__, id);
|
||||
DRM_DEBUG_KMS("id[%d]\n", id);
|
||||
|
||||
mutex_lock(lock);
|
||||
|
||||
@ -216,7 +210,7 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
|
||||
struct exynos_drm_ippdrv *ippdrv;
|
||||
u32 ipp_id = property->ipp_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, ipp_id);
|
||||
DRM_DEBUG_KMS("ipp_id[%d]\n", ipp_id);
|
||||
|
||||
if (ipp_id) {
|
||||
/* find ipp driver using idr */
|
||||
@ -257,14 +251,13 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
|
||||
*/
|
||||
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
|
||||
if (ipp_check_dedicated(ippdrv, property->cmd)) {
|
||||
DRM_DEBUG_KMS("%s:used device.\n", __func__);
|
||||
DRM_DEBUG_KMS("used device.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ippdrv->check_property &&
|
||||
ippdrv->check_property(ippdrv->dev, property)) {
|
||||
DRM_DEBUG_KMS("%s:not support property.\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("not support property.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -283,10 +276,10 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
|
||||
struct drm_exynos_ipp_cmd_node *c_node;
|
||||
int count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", prop_id);
|
||||
|
||||
if (list_empty(&exynos_drm_ippdrv_list)) {
|
||||
DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("ippdrv_list is empty.\n");
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
@ -296,8 +289,7 @@ static struct exynos_drm_ippdrv *ipp_find_drv_by_handle(u32 prop_id)
|
||||
* e.g PAUSE state, queue buf, command contro.
|
||||
*/
|
||||
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
|
||||
DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n", __func__,
|
||||
count++, (int)ippdrv);
|
||||
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", count++, (int)ippdrv);
|
||||
|
||||
if (!list_empty(&ippdrv->cmd_list)) {
|
||||
list_for_each_entry(c_node, &ippdrv->cmd_list, list)
|
||||
@ -320,8 +312,6 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
|
||||
struct exynos_drm_ippdrv *ippdrv;
|
||||
int count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!ctx) {
|
||||
DRM_ERROR("invalid context.\n");
|
||||
return -EINVAL;
|
||||
@ -332,7 +322,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:ipp_id[%d]\n", __func__, prop_list->ipp_id);
|
||||
DRM_DEBUG_KMS("ipp_id[%d]\n", prop_list->ipp_id);
|
||||
|
||||
if (!prop_list->ipp_id) {
|
||||
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list)
|
||||
@ -371,11 +361,11 @@ static void ipp_print_property(struct drm_exynos_ipp_property *property,
|
||||
struct drm_exynos_pos *pos = &config->pos;
|
||||
struct drm_exynos_sz *sz = &config->sz;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]ops[%s]fmt[0x%x]\n",
|
||||
__func__, property->prop_id, idx ? "dst" : "src", config->fmt);
|
||||
DRM_DEBUG_KMS("prop_id[%d]ops[%s]fmt[0x%x]\n",
|
||||
property->prop_id, idx ? "dst" : "src", config->fmt);
|
||||
|
||||
DRM_DEBUG_KMS("%s:pos[%d %d %d %d]sz[%d %d]f[%d]r[%d]\n",
|
||||
__func__, pos->x, pos->y, pos->w, pos->h,
|
||||
DRM_DEBUG_KMS("pos[%d %d %d %d]sz[%d %d]f[%d]r[%d]\n",
|
||||
pos->x, pos->y, pos->w, pos->h,
|
||||
sz->hsize, sz->vsize, config->flip, config->degree);
|
||||
}
|
||||
|
||||
@ -385,7 +375,7 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
|
||||
struct drm_exynos_ipp_cmd_node *c_node;
|
||||
u32 prop_id = property->prop_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", prop_id);
|
||||
|
||||
ippdrv = ipp_find_drv_by_handle(prop_id);
|
||||
if (IS_ERR(ippdrv)) {
|
||||
@ -401,8 +391,8 @@ static int ipp_find_and_set_property(struct drm_exynos_ipp_property *property)
|
||||
list_for_each_entry(c_node, &ippdrv->cmd_list, list) {
|
||||
if ((c_node->property.prop_id == prop_id) &&
|
||||
(c_node->state == IPP_STATE_STOP)) {
|
||||
DRM_DEBUG_KMS("%s:found cmd[%d]ippdrv[0x%x]\n",
|
||||
__func__, property->cmd, (int)ippdrv);
|
||||
DRM_DEBUG_KMS("found cmd[%d]ippdrv[0x%x]\n",
|
||||
property->cmd, (int)ippdrv);
|
||||
|
||||
c_node->property = *property;
|
||||
return 0;
|
||||
@ -418,8 +408,6 @@ static struct drm_exynos_ipp_cmd_work *ipp_create_cmd_work(void)
|
||||
{
|
||||
struct drm_exynos_ipp_cmd_work *cmd_work;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
cmd_work = kzalloc(sizeof(*cmd_work), GFP_KERNEL);
|
||||
if (!cmd_work) {
|
||||
DRM_ERROR("failed to alloc cmd_work.\n");
|
||||
@ -435,8 +423,6 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
|
||||
{
|
||||
struct drm_exynos_ipp_event_work *event_work;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
event_work = kzalloc(sizeof(*event_work), GFP_KERNEL);
|
||||
if (!event_work) {
|
||||
DRM_ERROR("failed to alloc event_work.\n");
|
||||
@ -460,8 +446,6 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
|
||||
struct drm_exynos_ipp_cmd_node *c_node;
|
||||
int ret, i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!ctx) {
|
||||
DRM_ERROR("invalid context.\n");
|
||||
return -EINVAL;
|
||||
@ -486,7 +470,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
|
||||
* instead of allocation.
|
||||
*/
|
||||
if (property->prop_id) {
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
|
||||
return ipp_find_and_set_property(property);
|
||||
}
|
||||
|
||||
@ -512,8 +496,8 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
|
||||
goto err_clear;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
|
||||
__func__, property->prop_id, property->cmd, (int)ippdrv);
|
||||
DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
|
||||
property->prop_id, property->cmd, (int)ippdrv);
|
||||
|
||||
/* stored property information and ippdrv in private data */
|
||||
c_node->priv = priv;
|
||||
@ -569,8 +553,6 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
|
||||
|
||||
static void ipp_clean_cmd_node(struct drm_exynos_ipp_cmd_node *c_node)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* delete list */
|
||||
list_del(&c_node->list);
|
||||
|
||||
@ -593,8 +575,6 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
|
||||
struct list_head *head;
|
||||
int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, };
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
mutex_lock(&c_node->mem_lock);
|
||||
|
||||
for_each_ipp_ops(i) {
|
||||
@ -602,20 +582,19 @@ static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
|
||||
head = &c_node->mem_list[i];
|
||||
|
||||
if (list_empty(head)) {
|
||||
DRM_DEBUG_KMS("%s:%s memory empty.\n", __func__,
|
||||
i ? "dst" : "src");
|
||||
DRM_DEBUG_KMS("%s memory empty.\n", i ? "dst" : "src");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* find memory node entry */
|
||||
list_for_each_entry(m_node, head, list) {
|
||||
DRM_DEBUG_KMS("%s:%s,count[%d]m_node[0x%x]\n", __func__,
|
||||
DRM_DEBUG_KMS("%s,count[%d]m_node[0x%x]\n",
|
||||
i ? "dst" : "src", count[i], (int)m_node);
|
||||
count[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:min[%d]max[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("min[%d]max[%d]\n",
|
||||
min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
|
||||
max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
|
||||
|
||||
@ -644,15 +623,14 @@ static struct drm_exynos_ipp_mem_node
|
||||
struct list_head *head;
|
||||
int count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__, qbuf->buf_id);
|
||||
DRM_DEBUG_KMS("buf_id[%d]\n", qbuf->buf_id);
|
||||
|
||||
/* source/destination memory list */
|
||||
head = &c_node->mem_list[qbuf->ops_id];
|
||||
|
||||
/* find memory node from memory list */
|
||||
list_for_each_entry(m_node, head, list) {
|
||||
DRM_DEBUG_KMS("%s:count[%d]m_node[0x%x]\n",
|
||||
__func__, count++, (int)m_node);
|
||||
DRM_DEBUG_KMS("count[%d]m_node[0x%x]\n", count++, (int)m_node);
|
||||
|
||||
/* compare buffer id */
|
||||
if (m_node->buf_id == qbuf->buf_id)
|
||||
@ -669,7 +647,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
|
||||
struct exynos_drm_ipp_ops *ops = NULL;
|
||||
int ret = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
|
||||
DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
|
||||
|
||||
if (!m_node) {
|
||||
DRM_ERROR("invalid queue node.\n");
|
||||
@ -678,7 +656,7 @@ static int ipp_set_mem_node(struct exynos_drm_ippdrv *ippdrv,
|
||||
|
||||
mutex_lock(&c_node->mem_lock);
|
||||
|
||||
DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
|
||||
DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
|
||||
|
||||
/* get operations callback */
|
||||
ops = ippdrv->ops[m_node->ops_id];
|
||||
@ -714,8 +692,6 @@ static struct drm_exynos_ipp_mem_node
|
||||
void *addr;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
mutex_lock(&c_node->mem_lock);
|
||||
|
||||
m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
|
||||
@ -732,14 +708,11 @@ static struct drm_exynos_ipp_mem_node
|
||||
m_node->prop_id = qbuf->prop_id;
|
||||
m_node->buf_id = qbuf->buf_id;
|
||||
|
||||
DRM_DEBUG_KMS("%s:m_node[0x%x]ops_id[%d]\n", __func__,
|
||||
(int)m_node, qbuf->ops_id);
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]buf_id[%d]\n", __func__,
|
||||
qbuf->prop_id, m_node->buf_id);
|
||||
DRM_DEBUG_KMS("m_node[0x%x]ops_id[%d]\n", (int)m_node, qbuf->ops_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]buf_id[%d]\n", qbuf->prop_id, m_node->buf_id);
|
||||
|
||||
for_each_ipp_planar(i) {
|
||||
DRM_DEBUG_KMS("%s:i[%d]handle[0x%x]\n", __func__,
|
||||
i, qbuf->handle[i]);
|
||||
DRM_DEBUG_KMS("i[%d]handle[0x%x]\n", i, qbuf->handle[i]);
|
||||
|
||||
/* get dma address by handle */
|
||||
if (qbuf->handle[i]) {
|
||||
@ -752,9 +725,8 @@ static struct drm_exynos_ipp_mem_node
|
||||
|
||||
buf_info.handles[i] = qbuf->handle[i];
|
||||
buf_info.base[i] = *(dma_addr_t *) addr;
|
||||
DRM_DEBUG_KMS("%s:i[%d]base[0x%x]hd[0x%x]\n",
|
||||
__func__, i, buf_info.base[i],
|
||||
(int)buf_info.handles[i]);
|
||||
DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%x]\n",
|
||||
i, buf_info.base[i], (int)buf_info.handles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -778,7 +750,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
|
||||
{
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s:node[0x%x]\n", __func__, (int)m_node);
|
||||
DRM_DEBUG_KMS("node[0x%x]\n", (int)m_node);
|
||||
|
||||
if (!m_node) {
|
||||
DRM_ERROR("invalid dequeue node.\n");
|
||||
@ -792,7 +764,7 @@ static int ipp_put_mem_node(struct drm_device *drm_dev,
|
||||
|
||||
mutex_lock(&c_node->mem_lock);
|
||||
|
||||
DRM_DEBUG_KMS("%s:ops_id[%d]\n", __func__, m_node->ops_id);
|
||||
DRM_DEBUG_KMS("ops_id[%d]\n", m_node->ops_id);
|
||||
|
||||
/* put gem buffer */
|
||||
for_each_ipp_planar(i) {
|
||||
@ -824,8 +796,7 @@ static int ipp_get_event(struct drm_device *drm_dev,
|
||||
struct drm_exynos_ipp_send_event *e;
|
||||
unsigned long flags;
|
||||
|
||||
DRM_DEBUG_KMS("%s:ops_id[%d]buf_id[%d]\n", __func__,
|
||||
qbuf->ops_id, qbuf->buf_id);
|
||||
DRM_DEBUG_KMS("ops_id[%d]buf_id[%d]\n", qbuf->ops_id, qbuf->buf_id);
|
||||
|
||||
e = kzalloc(sizeof(*e), GFP_KERNEL);
|
||||
|
||||
@ -857,16 +828,13 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node,
|
||||
struct drm_exynos_ipp_send_event *e, *te;
|
||||
int count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (list_empty(&c_node->event_list)) {
|
||||
DRM_DEBUG_KMS("%s:event_list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("event_list is empty.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(e, te, &c_node->event_list, base.link) {
|
||||
DRM_DEBUG_KMS("%s:count[%d]e[0x%x]\n",
|
||||
__func__, count++, (int)e);
|
||||
DRM_DEBUG_KMS("count[%d]e[0x%x]\n", count++, (int)e);
|
||||
|
||||
/*
|
||||
* quf == NULL condition means all event deletion.
|
||||
@ -912,8 +880,6 @@ static int ipp_queue_buf_with_run(struct device *dev,
|
||||
struct exynos_drm_ipp_ops *ops;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
ippdrv = ipp_find_drv_by_handle(qbuf->prop_id);
|
||||
if (IS_ERR(ippdrv)) {
|
||||
DRM_ERROR("failed to get ipp driver.\n");
|
||||
@ -929,12 +895,12 @@ static int ipp_queue_buf_with_run(struct device *dev,
|
||||
property = &c_node->property;
|
||||
|
||||
if (c_node->state != IPP_STATE_START) {
|
||||
DRM_DEBUG_KMS("%s:bypass for invalid state.\n" , __func__);
|
||||
DRM_DEBUG_KMS("bypass for invalid state.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ipp_check_mem_list(c_node)) {
|
||||
DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
|
||||
DRM_DEBUG_KMS("empty memory.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -964,8 +930,6 @@ static void ipp_clean_queue_buf(struct drm_device *drm_dev,
|
||||
{
|
||||
struct drm_exynos_ipp_mem_node *m_node, *tm_node;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!list_empty(&c_node->mem_list[qbuf->ops_id])) {
|
||||
/* delete list */
|
||||
list_for_each_entry_safe(m_node, tm_node,
|
||||
@ -989,8 +953,6 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
|
||||
struct drm_exynos_ipp_mem_node *m_node;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!qbuf) {
|
||||
DRM_ERROR("invalid buf parameter.\n");
|
||||
return -EINVAL;
|
||||
@ -1001,8 +963,8 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]ops_id[%s]buf_id[%d]buf_type[%d]\n",
|
||||
__func__, qbuf->prop_id, qbuf->ops_id ? "dst" : "src",
|
||||
DRM_DEBUG_KMS("prop_id[%d]ops_id[%s]buf_id[%d]buf_type[%d]\n",
|
||||
qbuf->prop_id, qbuf->ops_id ? "dst" : "src",
|
||||
qbuf->buf_id, qbuf->buf_type);
|
||||
|
||||
/* find command node */
|
||||
@ -1075,8 +1037,6 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
|
||||
static bool exynos_drm_ipp_check_valid(struct device *dev,
|
||||
enum drm_exynos_ipp_ctrl ctrl, enum drm_exynos_ipp_state state)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (ctrl != IPP_CTRL_PLAY) {
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
DRM_ERROR("pm:runtime_suspended.\n");
|
||||
@ -1104,7 +1064,6 @@ static bool exynos_drm_ipp_check_valid(struct device *dev,
|
||||
default:
|
||||
DRM_ERROR("invalid state.\n");
|
||||
goto err_status;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1126,8 +1085,6 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
|
||||
struct drm_exynos_ipp_cmd_work *cmd_work;
|
||||
struct drm_exynos_ipp_cmd_node *c_node;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!ctx) {
|
||||
DRM_ERROR("invalid context.\n");
|
||||
return -EINVAL;
|
||||
@ -1138,7 +1095,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:ctrl[%d]prop_id[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("ctrl[%d]prop_id[%d]\n",
|
||||
cmd_ctrl->ctrl, cmd_ctrl->prop_id);
|
||||
|
||||
ippdrv = ipp_find_drv_by_handle(cmd_ctrl->prop_id);
|
||||
@ -1213,7 +1170,7 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:done ctrl[%d]prop_id[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("done ctrl[%d]prop_id[%d]\n",
|
||||
cmd_ctrl->ctrl, cmd_ctrl->prop_id);
|
||||
|
||||
return 0;
|
||||
@ -1249,7 +1206,7 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
|
||||
|
||||
/* reset h/w block */
|
||||
if (ippdrv->reset &&
|
||||
@ -1310,13 +1267,13 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
|
||||
struct list_head *head;
|
||||
int ret, i;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
|
||||
|
||||
/* store command info in ippdrv */
|
||||
ippdrv->c_node = c_node;
|
||||
|
||||
if (!ipp_check_mem_list(c_node)) {
|
||||
DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
|
||||
DRM_DEBUG_KMS("empty memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -1343,8 +1300,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:m_node[0x%x]\n",
|
||||
__func__, (int)m_node);
|
||||
DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
|
||||
|
||||
ret = ipp_set_mem_node(ippdrv, c_node, m_node);
|
||||
if (ret) {
|
||||
@ -1382,7 +1338,7 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:cmd[%d]\n", __func__, property->cmd);
|
||||
DRM_DEBUG_KMS("cmd[%d]\n", property->cmd);
|
||||
|
||||
/* start operations */
|
||||
if (ippdrv->start) {
|
||||
@ -1405,7 +1361,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
|
||||
struct list_head *head;
|
||||
int ret = 0, i;
|
||||
|
||||
DRM_DEBUG_KMS("%s:prop_id[%d]\n", __func__, property->prop_id);
|
||||
DRM_DEBUG_KMS("prop_id[%d]\n", property->prop_id);
|
||||
|
||||
/* put event */
|
||||
ipp_put_event(c_node, NULL);
|
||||
@ -1418,8 +1374,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
|
||||
head = &c_node->mem_list[i];
|
||||
|
||||
if (list_empty(head)) {
|
||||
DRM_DEBUG_KMS("%s:mem_list is empty.\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("mem_list is empty.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1439,7 +1394,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
|
||||
head = &c_node->mem_list[EXYNOS_DRM_OPS_DST];
|
||||
|
||||
if (list_empty(head)) {
|
||||
DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("mem_list is empty.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1456,7 +1411,7 @@ static int ipp_stop_property(struct drm_device *drm_dev,
|
||||
head = &c_node->mem_list[EXYNOS_DRM_OPS_SRC];
|
||||
|
||||
if (list_empty(head)) {
|
||||
DRM_DEBUG_KMS("%s:mem_list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("mem_list is empty.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1491,8 +1446,6 @@ void ipp_sched_cmd(struct work_struct *work)
|
||||
struct drm_exynos_ipp_property *property;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
ippdrv = cmd_work->ippdrv;
|
||||
if (!ippdrv) {
|
||||
DRM_ERROR("invalid ippdrv list.\n");
|
||||
@ -1550,7 +1503,7 @@ void ipp_sched_cmd(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:ctrl[%d] done.\n", __func__, cmd_work->ctrl);
|
||||
DRM_DEBUG_KMS("ctrl[%d] done.\n", cmd_work->ctrl);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&c_node->cmd_lock);
|
||||
@ -1571,8 +1524,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
|
||||
int ret, i;
|
||||
|
||||
for_each_ipp_ops(i)
|
||||
DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
|
||||
i ? "dst" : "src", buf_id[i]);
|
||||
DRM_DEBUG_KMS("%s buf_id[%d]\n", i ? "dst" : "src", buf_id[i]);
|
||||
|
||||
if (!drm_dev) {
|
||||
DRM_ERROR("failed to get drm_dev.\n");
|
||||
@ -1585,12 +1537,12 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
|
||||
}
|
||||
|
||||
if (list_empty(&c_node->event_list)) {
|
||||
DRM_DEBUG_KMS("%s:event list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("event list is empty.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ipp_check_mem_list(c_node)) {
|
||||
DRM_DEBUG_KMS("%s:empty memory.\n", __func__);
|
||||
DRM_DEBUG_KMS("empty memory.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1609,7 +1561,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
|
||||
}
|
||||
|
||||
tbuf_id[i] = m_node->buf_id;
|
||||
DRM_DEBUG_KMS("%s:%s buf_id[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("%s buf_id[%d]\n",
|
||||
i ? "dst" : "src", tbuf_id[i]);
|
||||
|
||||
ret = ipp_put_mem_node(drm_dev, c_node, m_node);
|
||||
@ -1677,8 +1629,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
|
||||
}
|
||||
|
||||
do_gettimeofday(&now);
|
||||
DRM_DEBUG_KMS("%s:tv_sec[%ld]tv_usec[%ld]\n"
|
||||
, __func__, now.tv_sec, now.tv_usec);
|
||||
DRM_DEBUG_KMS("tv_sec[%ld]tv_usec[%ld]\n", now.tv_sec, now.tv_usec);
|
||||
e->event.tv_sec = now.tv_sec;
|
||||
e->event.tv_usec = now.tv_usec;
|
||||
e->event.prop_id = property->prop_id;
|
||||
@ -1692,7 +1643,7 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
|
||||
wake_up_interruptible(&e->base.file_priv->event_wait);
|
||||
spin_unlock_irqrestore(&drm_dev->event_lock, flags);
|
||||
|
||||
DRM_DEBUG_KMS("%s:done cmd[%d]prop_id[%d]buf_id[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("done cmd[%d]prop_id[%d]buf_id[%d]\n",
|
||||
property->cmd, property->prop_id, tbuf_id[EXYNOS_DRM_OPS_DST]);
|
||||
|
||||
return 0;
|
||||
@ -1711,8 +1662,7 @@ void ipp_sched_event(struct work_struct *work)
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:buf_id[%d]\n", __func__,
|
||||
event_work->buf_id[EXYNOS_DRM_OPS_DST]);
|
||||
DRM_DEBUG_KMS("buf_id[%d]\n", event_work->buf_id[EXYNOS_DRM_OPS_DST]);
|
||||
|
||||
ippdrv = event_work->ippdrv;
|
||||
if (!ippdrv) {
|
||||
@ -1733,8 +1683,8 @@ void ipp_sched_event(struct work_struct *work)
|
||||
* or going out operations.
|
||||
*/
|
||||
if (c_node->state != IPP_STATE_START) {
|
||||
DRM_DEBUG_KMS("%s:bypass state[%d]prop_id[%d]\n",
|
||||
__func__, c_node->state, c_node->property.prop_id);
|
||||
DRM_DEBUG_KMS("bypass state[%d]prop_id[%d]\n",
|
||||
c_node->state, c_node->property.prop_id);
|
||||
goto err_completion;
|
||||
}
|
||||
|
||||
@ -1759,8 +1709,6 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
struct exynos_drm_ippdrv *ippdrv;
|
||||
int ret, count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* get ipp driver entry */
|
||||
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
|
||||
ippdrv->drm_dev = drm_dev;
|
||||
@ -1772,7 +1720,7 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
goto err_idr;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]ipp_id[%d]\n", __func__,
|
||||
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
|
||||
count++, (int)ippdrv, ippdrv->ipp_id);
|
||||
|
||||
if (ippdrv->ipp_id == 0) {
|
||||
@ -1816,8 +1764,6 @@ static void ipp_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
struct exynos_drm_ippdrv *ippdrv;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* get ipp driver entry */
|
||||
list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
|
||||
if (is_drm_iommu_supported(drm_dev))
|
||||
@ -1834,8 +1780,6 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
|
||||
struct drm_exynos_file_private *file_priv = file->driver_priv;
|
||||
struct exynos_drm_ipp_private *priv;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
DRM_ERROR("failed to allocate priv.\n");
|
||||
@ -1846,7 +1790,7 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
|
||||
|
||||
INIT_LIST_HEAD(&priv->event_list);
|
||||
|
||||
DRM_DEBUG_KMS("%s:done priv[0x%x]\n", __func__, (int)priv);
|
||||
DRM_DEBUG_KMS("done priv[0x%x]\n", (int)priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1860,10 +1804,10 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
|
||||
struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
|
||||
int count = 0;
|
||||
|
||||
DRM_DEBUG_KMS("%s:for priv[0x%x]\n", __func__, (int)priv);
|
||||
DRM_DEBUG_KMS("for priv[0x%x]\n", (int)priv);
|
||||
|
||||
if (list_empty(&exynos_drm_ippdrv_list)) {
|
||||
DRM_DEBUG_KMS("%s:ippdrv_list is empty.\n", __func__);
|
||||
DRM_DEBUG_KMS("ippdrv_list is empty.\n");
|
||||
goto err_clear;
|
||||
}
|
||||
|
||||
@ -1873,8 +1817,8 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
|
||||
|
||||
list_for_each_entry_safe(c_node, tc_node,
|
||||
&ippdrv->cmd_list, list) {
|
||||
DRM_DEBUG_KMS("%s:count[%d]ippdrv[0x%x]\n",
|
||||
__func__, count++, (int)ippdrv);
|
||||
DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
|
||||
count++, (int)ippdrv);
|
||||
|
||||
if (c_node->priv == priv) {
|
||||
/*
|
||||
@ -1913,8 +1857,6 @@ static int ipp_probe(struct platform_device *pdev)
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
mutex_init(&ctx->ipp_lock);
|
||||
mutex_init(&ctx->prop_lock);
|
||||
|
||||
@ -1978,8 +1920,6 @@ static int ipp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ipp_context *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
/* unregister sub driver */
|
||||
exynos_drm_subdrv_unregister(&ctx->subdrv);
|
||||
|
||||
@ -1999,7 +1939,7 @@ static int ipp_remove(struct platform_device *pdev)
|
||||
|
||||
static int ipp_power_ctrl(struct ipp_context *ctx, bool enable)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s:enable[%d]\n", __func__, enable);
|
||||
DRM_DEBUG_KMS("enable[%d]\n", enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2009,8 +1949,6 @@ static int ipp_suspend(struct device *dev)
|
||||
{
|
||||
struct ipp_context *ctx = get_ipp_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
@ -2021,8 +1959,6 @@ static int ipp_resume(struct device *dev)
|
||||
{
|
||||
struct ipp_context *ctx = get_ipp_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return ipp_power_ctrl(ctx, true);
|
||||
|
||||
@ -2035,8 +1971,6 @@ static int ipp_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct ipp_context *ctx = get_ipp_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
return ipp_power_ctrl(ctx, false);
|
||||
}
|
||||
|
||||
@ -2044,8 +1978,6 @@ static int ipp_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct ipp_context *ctx = get_ipp_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
return ipp_power_ctrl(ctx, true);
|
||||
}
|
||||
#endif
|
||||
|
@ -81,8 +81,6 @@ int exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
int nr;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
nr = exynos_drm_fb_get_buf_cnt(fb);
|
||||
for (i = 0; i < nr; i++) {
|
||||
struct exynos_drm_gem_buf *buffer = exynos_drm_fb_buffer(fb, i);
|
||||
@ -159,8 +157,6 @@ void exynos_plane_dpms(struct drm_plane *plane, int mode)
|
||||
struct exynos_plane *exynos_plane = to_exynos_plane(plane);
|
||||
struct exynos_drm_overlay *overlay = &exynos_plane->overlay;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (mode == DRM_MODE_DPMS_ON) {
|
||||
if (exynos_plane->enabled)
|
||||
return;
|
||||
@ -189,8 +185,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
{
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
ret = exynos_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y,
|
||||
crtc_w, crtc_h, src_x >> 16, src_y >> 16,
|
||||
src_w >> 16, src_h >> 16);
|
||||
@ -207,8 +201,6 @@ exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
|
||||
static int exynos_disable_plane(struct drm_plane *plane)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
exynos_plane_dpms(plane, DRM_MODE_DPMS_OFF);
|
||||
|
||||
return 0;
|
||||
@ -218,8 +210,6 @@ static void exynos_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
struct exynos_plane *exynos_plane = to_exynos_plane(plane);
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
exynos_disable_plane(plane);
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(exynos_plane);
|
||||
@ -233,8 +223,6 @@ static int exynos_plane_set_property(struct drm_plane *plane,
|
||||
struct exynos_plane *exynos_plane = to_exynos_plane(plane);
|
||||
struct exynos_drm_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (property == dev_priv->plane_zpos_property) {
|
||||
exynos_plane->overlay.zpos = val;
|
||||
return 0;
|
||||
@ -256,8 +244,6 @@ static void exynos_plane_attach_zpos_property(struct drm_plane *plane)
|
||||
struct exynos_drm_private *dev_priv = dev->dev_private;
|
||||
struct drm_property *prop;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
prop = dev_priv->plane_zpos_property;
|
||||
if (!prop) {
|
||||
prop = drm_property_create_range(dev, 0, "zpos", 0,
|
||||
@ -277,8 +263,6 @@ struct drm_plane *exynos_plane_init(struct drm_device *dev,
|
||||
struct exynos_plane *exynos_plane;
|
||||
int err;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
exynos_plane = kzalloc(sizeof(struct exynos_plane), GFP_KERNEL);
|
||||
if (!exynos_plane) {
|
||||
DRM_ERROR("failed to allocate plane\n");
|
||||
|
@ -244,7 +244,7 @@ static int rotator_src_set_size(struct device *dev, int swap,
|
||||
/* Get format */
|
||||
fmt = rotator_reg_get_fmt(rot);
|
||||
if (!rotator_check_reg_fmt(fmt)) {
|
||||
DRM_ERROR("%s:invalid format.\n", __func__);
|
||||
DRM_ERROR("invalid format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -287,7 +287,7 @@ static int rotator_src_set_addr(struct device *dev,
|
||||
/* Get format */
|
||||
fmt = rotator_reg_get_fmt(rot);
|
||||
if (!rotator_check_reg_fmt(fmt)) {
|
||||
DRM_ERROR("%s:invalid format.\n", __func__);
|
||||
DRM_ERROR("invalid format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -381,7 +381,7 @@ static int rotator_dst_set_size(struct device *dev, int swap,
|
||||
/* Get format */
|
||||
fmt = rotator_reg_get_fmt(rot);
|
||||
if (!rotator_check_reg_fmt(fmt)) {
|
||||
DRM_ERROR("%s:invalid format.\n", __func__);
|
||||
DRM_ERROR("invalid format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -422,7 +422,7 @@ static int rotator_dst_set_addr(struct device *dev,
|
||||
/* Get format */
|
||||
fmt = rotator_reg_get_fmt(rot);
|
||||
if (!rotator_check_reg_fmt(fmt)) {
|
||||
DRM_ERROR("%s:invalid format.\n", __func__);
|
||||
DRM_ERROR("invalid format.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -471,8 +471,6 @@ static int rotator_init_prop_list(struct exynos_drm_ippdrv *ippdrv)
|
||||
{
|
||||
struct drm_exynos_ipp_prop_list *prop_list;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
prop_list = devm_kzalloc(ippdrv->dev, sizeof(*prop_list), GFP_KERNEL);
|
||||
if (!prop_list) {
|
||||
DRM_ERROR("failed to alloc property list.\n");
|
||||
@ -502,7 +500,7 @@ static inline bool rotator_check_drm_fmt(u32 fmt)
|
||||
case DRM_FORMAT_NV12:
|
||||
return true;
|
||||
default:
|
||||
DRM_DEBUG_KMS("%s:not support format\n", __func__);
|
||||
DRM_DEBUG_KMS("not support format\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -516,7 +514,7 @@ static inline bool rotator_check_drm_flip(enum drm_exynos_flip flip)
|
||||
case EXYNOS_DRM_FLIP_BOTH:
|
||||
return true;
|
||||
default:
|
||||
DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid flip\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -536,19 +534,18 @@ static int rotator_ippdrv_check_property(struct device *dev,
|
||||
|
||||
/* Check format configuration */
|
||||
if (src_config->fmt != dst_config->fmt) {
|
||||
DRM_DEBUG_KMS("%s:not support csc feature\n", __func__);
|
||||
DRM_DEBUG_KMS("not support csc feature\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rotator_check_drm_fmt(dst_config->fmt)) {
|
||||
DRM_DEBUG_KMS("%s:invalid format\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check transform configuration */
|
||||
if (src_config->degree != EXYNOS_DRM_DEGREE_0) {
|
||||
DRM_DEBUG_KMS("%s:not support source-side rotation\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("not support source-side rotation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -561,51 +558,47 @@ static int rotator_ippdrv_check_property(struct device *dev,
|
||||
/* No problem */
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("%s:invalid degree\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid degree\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (src_config->flip != EXYNOS_DRM_FLIP_NONE) {
|
||||
DRM_DEBUG_KMS("%s:not support source-side flip\n", __func__);
|
||||
DRM_DEBUG_KMS("not support source-side flip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!rotator_check_drm_flip(dst_config->flip)) {
|
||||
DRM_DEBUG_KMS("%s:invalid flip\n", __func__);
|
||||
DRM_DEBUG_KMS("invalid flip\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check size configuration */
|
||||
if ((src_pos->x + src_pos->w > src_sz->hsize) ||
|
||||
(src_pos->y + src_pos->h > src_sz->vsize)) {
|
||||
DRM_DEBUG_KMS("%s:out of source buffer bound\n", __func__);
|
||||
DRM_DEBUG_KMS("out of source buffer bound\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (swap) {
|
||||
if ((dst_pos->x + dst_pos->h > dst_sz->vsize) ||
|
||||
(dst_pos->y + dst_pos->w > dst_sz->hsize)) {
|
||||
DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("out of destination buffer bound\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((src_pos->w != dst_pos->h) || (src_pos->h != dst_pos->w)) {
|
||||
DRM_DEBUG_KMS("%s:not support scale feature\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("not support scale feature\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if ((dst_pos->x + dst_pos->w > dst_sz->hsize) ||
|
||||
(dst_pos->y + dst_pos->h > dst_sz->vsize)) {
|
||||
DRM_DEBUG_KMS("%s:out of destination buffer bound\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("out of destination buffer bound\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((src_pos->w != dst_pos->w) || (src_pos->h != dst_pos->h)) {
|
||||
DRM_DEBUG_KMS("%s:not support scale feature\n",
|
||||
__func__);
|
||||
DRM_DEBUG_KMS("not support scale feature\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
@ -693,7 +686,7 @@ static int rotator_probe(struct platform_device *pdev)
|
||||
goto err_ippdrv_register;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("%s:ippdrv[0x%x]\n", __func__, (int)ippdrv);
|
||||
DRM_DEBUG_KMS("ippdrv[0x%x]\n", (int)ippdrv);
|
||||
|
||||
platform_set_drvdata(pdev, rot);
|
||||
|
||||
@ -752,8 +745,6 @@ static struct platform_device_id rotator_driver_ids[] = {
|
||||
|
||||
static int rotator_clk_crtl(struct rot_context *rot, bool enable)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (enable) {
|
||||
clk_enable(rot->clock);
|
||||
rot->suspended = false;
|
||||
@ -771,8 +762,6 @@ static int rotator_suspend(struct device *dev)
|
||||
{
|
||||
struct rot_context *rot = dev_get_drvdata(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (pm_runtime_suspended(dev))
|
||||
return 0;
|
||||
|
||||
@ -783,8 +772,6 @@ static int rotator_resume(struct device *dev)
|
||||
{
|
||||
struct rot_context *rot = dev_get_drvdata(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
if (!pm_runtime_suspended(dev))
|
||||
return rotator_clk_crtl(rot, true);
|
||||
|
||||
@ -797,8 +784,6 @@ static int rotator_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct rot_context *rot = dev_get_drvdata(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
return rotator_clk_crtl(rot, false);
|
||||
}
|
||||
|
||||
@ -806,8 +791,6 @@ static int rotator_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct rot_context *rot = dev_get_drvdata(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __func__);
|
||||
|
||||
return rotator_clk_crtl(rot, true);
|
||||
}
|
||||
#endif
|
||||
|
@ -89,8 +89,6 @@ static bool vidi_display_is_connected(struct device *dev)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* connection request would come from user side
|
||||
* to do hotplug through specific ioctl.
|
||||
@ -105,8 +103,6 @@ static struct edid *vidi_get_edid(struct device *dev,
|
||||
struct edid *edid;
|
||||
int edid_len;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* the edid data comes from user side and it would be set
|
||||
* to ctx->raw_edid through specific ioctl.
|
||||
@ -128,17 +124,13 @@ static struct edid *vidi_get_edid(struct device *dev,
|
||||
|
||||
static void *vidi_get_panel(struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int vidi_check_timing(struct device *dev, void *timing)
|
||||
static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
|
||||
return 0;
|
||||
@ -146,8 +138,6 @@ static int vidi_check_timing(struct device *dev, void *timing)
|
||||
|
||||
static int vidi_display_power_on(struct device *dev, int mode)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
@ -158,7 +148,7 @@ static struct exynos_drm_display_ops vidi_display_ops = {
|
||||
.is_connected = vidi_display_is_connected,
|
||||
.get_edid = vidi_get_edid,
|
||||
.get_panel = vidi_get_panel,
|
||||
.check_timing = vidi_check_timing,
|
||||
.check_mode = vidi_check_mode,
|
||||
.power_on = vidi_display_power_on,
|
||||
};
|
||||
|
||||
@ -166,7 +156,7 @@ static void vidi_dpms(struct device *subdrv_dev, int mode)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(subdrv_dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s, %d\n", __FILE__, mode);
|
||||
DRM_DEBUG_KMS("%d\n", mode);
|
||||
|
||||
mutex_lock(&ctx->lock);
|
||||
|
||||
@ -196,8 +186,6 @@ static void vidi_apply(struct device *subdrv_dev)
|
||||
struct vidi_win_data *win_data;
|
||||
int i;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
for (i = 0; i < WINDOWS_NR; i++) {
|
||||
win_data = &ctx->win_data[i];
|
||||
if (win_data->enabled && (ovl_ops && ovl_ops->commit))
|
||||
@ -212,8 +200,6 @@ static void vidi_commit(struct device *dev)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
}
|
||||
@ -222,8 +208,6 @@ static int vidi_enable_vblank(struct device *dev)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return -EPERM;
|
||||
|
||||
@ -246,8 +230,6 @@ static void vidi_disable_vblank(struct device *dev)
|
||||
{
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
@ -271,8 +253,6 @@ static void vidi_win_mode_set(struct device *dev,
|
||||
int win;
|
||||
unsigned long offset;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!overlay) {
|
||||
dev_err(dev, "overlay is NULL\n");
|
||||
return;
|
||||
@ -282,7 +262,7 @@ static void vidi_win_mode_set(struct device *dev,
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
offset = overlay->fb_x * (overlay->bpp >> 3);
|
||||
@ -324,15 +304,13 @@ static void vidi_win_commit(struct device *dev, int zpos)
|
||||
struct vidi_win_data *win_data;
|
||||
int win = zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (ctx->suspended)
|
||||
return;
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
@ -351,12 +329,10 @@ static void vidi_win_disable(struct device *dev, int zpos)
|
||||
struct vidi_win_data *win_data;
|
||||
int win = zpos;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = ctx->default_win;
|
||||
|
||||
if (win < 0 || win > WINDOWS_NR)
|
||||
if (win < 0 || win >= WINDOWS_NR)
|
||||
return;
|
||||
|
||||
win_data = &ctx->win_data[win];
|
||||
@ -407,8 +383,6 @@ static void vidi_fake_vblank_handler(struct work_struct *work)
|
||||
|
||||
static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/*
|
||||
* enable drm irq mode.
|
||||
* - with irq_enabled = 1, we can use the vblank feature.
|
||||
@ -431,8 +405,6 @@ static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
|
||||
|
||||
static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev)
|
||||
{
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
/* TODO. */
|
||||
}
|
||||
|
||||
@ -441,8 +413,6 @@ static int vidi_power_on(struct vidi_context *ctx, bool enable)
|
||||
struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
|
||||
struct device *dev = subdrv->dev;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (enable != false && enable != true)
|
||||
return -EINVAL;
|
||||
|
||||
@ -483,8 +453,6 @@ static int vidi_store_connection(struct device *dev,
|
||||
struct vidi_context *ctx = get_vidi_context(dev);
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ret = kstrtoint(buf, 0, &ctx->connected);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -522,8 +490,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
|
||||
struct drm_exynos_vidi_connection *vidi = data;
|
||||
int edid_len;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
if (!vidi) {
|
||||
DRM_DEBUG_KMS("user data for vidi is null.\n");
|
||||
return -EINVAL;
|
||||
@ -592,8 +558,6 @@ static int vidi_probe(struct platform_device *pdev)
|
||||
struct exynos_drm_subdrv *subdrv;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
|
||||
if (!ctx)
|
||||
return -ENOMEM;
|
||||
@ -625,8 +589,6 @@ static int vidi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vidi_context *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||
|
||||
exynos_drm_subdrv_unregister(&ctx->subdrv);
|
||||
|
||||
if (ctx->raw_edid != (struct edid *)fake_edid_info) {
|
||||
|
@ -83,6 +83,7 @@ struct hdmi_resources {
|
||||
struct clk *sclk_pixel;
|
||||
struct clk *sclk_hdmiphy;
|
||||
struct clk *hdmiphy;
|
||||
struct clk *mout_hdmi;
|
||||
struct regulator_bulk_data *regul_bulk;
|
||||
int regul_count;
|
||||
};
|
||||
@ -689,8 +690,6 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata,
|
||||
u32 mod;
|
||||
u32 vic;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mod = hdmi_reg_read(hdata, HDMI_MODE_SEL);
|
||||
if (hdata->dvi_mode) {
|
||||
hdmi_reg_writeb(hdata, HDMI_VSI_CON,
|
||||
@ -755,8 +754,6 @@ static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
|
||||
struct edid *raw_edid;
|
||||
struct hdmi_context *hdata = ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (!hdata->ddc_port)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
@ -777,8 +774,6 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
|
||||
const struct hdmiphy_config *confs;
|
||||
int count, i;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (hdata->type == HDMI_TYPE13) {
|
||||
confs = hdmiphy_v13_configs;
|
||||
count = ARRAY_SIZE(hdmiphy_v13_configs);
|
||||
@ -796,18 +791,17 @@ static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
|
||||
static int hdmi_check_mode(void *ctx, struct drm_display_mode *mode)
|
||||
{
|
||||
struct hdmi_context *hdata = ctx;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
|
||||
mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
|
||||
false, mode->clock * 1000);
|
||||
|
||||
DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
|
||||
timing->yres, timing->refresh,
|
||||
timing->vmode);
|
||||
|
||||
ret = hdmi_find_phy_conf(hdata, timing->pixclock);
|
||||
ret = hdmi_find_phy_conf(hdata, mode->clock * 1000);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return 0;
|
||||
@ -1042,7 +1036,7 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
|
||||
static void hdmi_v13_mode_apply(struct hdmi_context *hdata)
|
||||
{
|
||||
const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v13_conf.tg;
|
||||
const struct hdmi_v13_core_regs *core =
|
||||
@ -1118,9 +1112,9 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
|
||||
hdmi_regs_dump(hdata, "timing apply");
|
||||
}
|
||||
|
||||
clk_disable(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
|
||||
clk_enable(hdata->res.sclk_hdmi);
|
||||
clk_disable_unprepare(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
|
||||
clk_prepare_enable(hdata->res.sclk_hdmi);
|
||||
|
||||
/* enable HDMI and timing generator */
|
||||
hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
|
||||
@ -1131,7 +1125,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
|
||||
hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
|
||||
}
|
||||
|
||||
static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
|
||||
static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
|
||||
{
|
||||
const struct hdmi_tg_regs *tg = &hdata->mode_conf.conf.v14_conf.tg;
|
||||
const struct hdmi_v14_core_regs *core =
|
||||
@ -1285,9 +1279,9 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
|
||||
hdmi_regs_dump(hdata, "timing apply");
|
||||
}
|
||||
|
||||
clk_disable(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
|
||||
clk_enable(hdata->res.sclk_hdmi);
|
||||
clk_disable_unprepare(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_hdmiphy);
|
||||
clk_prepare_enable(hdata->res.sclk_hdmi);
|
||||
|
||||
/* enable HDMI and timing generator */
|
||||
hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
|
||||
@ -1298,12 +1292,12 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
|
||||
hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
|
||||
}
|
||||
|
||||
static void hdmi_timing_apply(struct hdmi_context *hdata)
|
||||
static void hdmi_mode_apply(struct hdmi_context *hdata)
|
||||
{
|
||||
if (hdata->type == HDMI_TYPE13)
|
||||
hdmi_v13_timing_apply(hdata);
|
||||
hdmi_v13_mode_apply(hdata);
|
||||
else
|
||||
hdmi_v14_timing_apply(hdata);
|
||||
hdmi_v14_mode_apply(hdata);
|
||||
}
|
||||
|
||||
static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||
@ -1311,9 +1305,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||
u8 buffer[2];
|
||||
u32 reg;
|
||||
|
||||
clk_disable(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
|
||||
clk_enable(hdata->res.sclk_hdmi);
|
||||
clk_disable_unprepare(hdata->res.sclk_hdmi);
|
||||
clk_set_parent(hdata->res.mout_hdmi, hdata->res.sclk_pixel);
|
||||
clk_prepare_enable(hdata->res.sclk_hdmi);
|
||||
|
||||
/* operation mode */
|
||||
buffer[0] = 0x1f;
|
||||
@ -1336,8 +1330,6 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||
|
||||
static void hdmiphy_poweron(struct hdmi_context *hdata)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (hdata->type == HDMI_TYPE14)
|
||||
hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, 0,
|
||||
HDMI_PHY_POWER_OFF_EN);
|
||||
@ -1345,8 +1337,6 @@ static void hdmiphy_poweron(struct hdmi_context *hdata)
|
||||
|
||||
static void hdmiphy_poweroff(struct hdmi_context *hdata)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (hdata->type == HDMI_TYPE14)
|
||||
hdmi_reg_writemask(hdata, HDMI_PHY_CON_0, ~0,
|
||||
HDMI_PHY_POWER_OFF_EN);
|
||||
@ -1410,8 +1400,6 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
||||
|
||||
static void hdmi_conf_apply(struct hdmi_context *hdata)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
hdmiphy_conf_reset(hdata);
|
||||
hdmiphy_conf_apply(hdata);
|
||||
|
||||
@ -1423,7 +1411,7 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
|
||||
hdmi_audio_init(hdata);
|
||||
|
||||
/* setting core registers */
|
||||
hdmi_timing_apply(hdata);
|
||||
hdmi_mode_apply(hdata);
|
||||
hdmi_audio_control(hdata, true);
|
||||
|
||||
hdmi_regs_dump(hdata, "start");
|
||||
@ -1569,8 +1557,7 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
|
||||
(m->vsync_start - m->vdisplay) / 2);
|
||||
hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2);
|
||||
hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2);
|
||||
hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal +
|
||||
((m->vsync_end - m->vsync_start) * 4) + 5) / 2);
|
||||
hdmi_set_reg(core->v_blank_f0, 2, m->vtotal - m->vdisplay / 2);
|
||||
hdmi_set_reg(core->v_blank_f1, 2, m->vtotal);
|
||||
hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7);
|
||||
hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2);
|
||||
@ -1580,7 +1567,10 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
|
||||
(m->htotal / 2) + (m->hsync_start - m->hdisplay));
|
||||
hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2);
|
||||
hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2);
|
||||
hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/
|
||||
hdmi_set_reg(tg->vact_st2, 2, m->vtotal - m->vdisplay / 2);
|
||||
hdmi_set_reg(tg->vsync2, 2, (m->vtotal / 2) + 1);
|
||||
hdmi_set_reg(tg->vsync_bot_hdmi, 2, (m->vtotal / 2) + 1);
|
||||
hdmi_set_reg(tg->field_bot_hdmi, 2, (m->vtotal / 2) + 1);
|
||||
hdmi_set_reg(tg->vact_st3, 2, 0x0);
|
||||
hdmi_set_reg(tg->vact_st4, 2, 0x0);
|
||||
} else {
|
||||
@ -1602,6 +1592,9 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
|
||||
hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */
|
||||
hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */
|
||||
hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */
|
||||
hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
|
||||
}
|
||||
|
||||
/* Following values & calculations are same irrespective of mode type */
|
||||
@ -1633,22 +1626,19 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
|
||||
hdmi_set_reg(tg->hact_sz, 2, m->hdisplay);
|
||||
hdmi_set_reg(tg->v_fsz, 2, m->vtotal);
|
||||
hdmi_set_reg(tg->vsync, 2, 0x1);
|
||||
hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */
|
||||
hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */
|
||||
hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */
|
||||
hdmi_set_reg(tg->tg_3d, 1, 0x0);
|
||||
}
|
||||
|
||||
static void hdmi_mode_set(void *ctx, void *mode)
|
||||
static void hdmi_mode_set(void *ctx, struct drm_display_mode *mode)
|
||||
{
|
||||
struct hdmi_context *hdata = ctx;
|
||||
struct drm_display_mode *m = mode;
|
||||
|
||||
DRM_DEBUG_KMS("[%s]: xres=%d, yres=%d, refresh=%d, intl=%s\n",
|
||||
__func__, m->hdisplay, m->vdisplay,
|
||||
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n",
|
||||
m->hdisplay, m->vdisplay,
|
||||
m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ?
|
||||
"INTERLACED" : "PROGERESSIVE");
|
||||
|
||||
@ -1661,8 +1651,6 @@ static void hdmi_mode_set(void *ctx, void *mode)
|
||||
static void hdmi_get_max_resol(void *ctx, unsigned int *width,
|
||||
unsigned int *height)
|
||||
{
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
*width = MAX_WIDTH;
|
||||
*height = MAX_HEIGHT;
|
||||
}
|
||||
@ -1671,8 +1659,6 @@ static void hdmi_commit(void *ctx)
|
||||
{
|
||||
struct hdmi_context *hdata = ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
if (!hdata->powered) {
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
@ -1687,8 +1673,6 @@ static void hdmi_poweron(struct hdmi_context *hdata)
|
||||
{
|
||||
struct hdmi_resources *res = &hdata->res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
if (hdata->powered) {
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
@ -1699,10 +1683,12 @@ static void hdmi_poweron(struct hdmi_context *hdata)
|
||||
|
||||
mutex_unlock(&hdata->hdmi_mutex);
|
||||
|
||||
regulator_bulk_enable(res->regul_count, res->regul_bulk);
|
||||
clk_enable(res->hdmiphy);
|
||||
clk_enable(res->hdmi);
|
||||
clk_enable(res->sclk_hdmi);
|
||||
if (regulator_bulk_enable(res->regul_count, res->regul_bulk))
|
||||
DRM_DEBUG_KMS("failed to enable regulator bulk\n");
|
||||
|
||||
clk_prepare_enable(res->hdmiphy);
|
||||
clk_prepare_enable(res->hdmi);
|
||||
clk_prepare_enable(res->sclk_hdmi);
|
||||
|
||||
hdmiphy_poweron(hdata);
|
||||
}
|
||||
@ -1711,8 +1697,6 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
|
||||
{
|
||||
struct hdmi_resources *res = &hdata->res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
if (!hdata->powered)
|
||||
goto out;
|
||||
@ -1725,9 +1709,9 @@ static void hdmi_poweroff(struct hdmi_context *hdata)
|
||||
hdmiphy_conf_reset(hdata);
|
||||
hdmiphy_poweroff(hdata);
|
||||
|
||||
clk_disable(res->sclk_hdmi);
|
||||
clk_disable(res->hdmi);
|
||||
clk_disable(res->hdmiphy);
|
||||
clk_disable_unprepare(res->sclk_hdmi);
|
||||
clk_disable_unprepare(res->hdmi);
|
||||
clk_disable_unprepare(res->hdmiphy);
|
||||
regulator_bulk_disable(res->regul_count, res->regul_bulk);
|
||||
|
||||
mutex_lock(&hdata->hdmi_mutex);
|
||||
@ -1742,7 +1726,7 @@ static void hdmi_dpms(void *ctx, int mode)
|
||||
{
|
||||
struct hdmi_context *hdata = ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s mode %d\n", __LINE__, __func__, mode);
|
||||
DRM_DEBUG_KMS("mode %d\n", mode);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
@ -1765,7 +1749,7 @@ static struct exynos_hdmi_ops hdmi_ops = {
|
||||
/* display */
|
||||
.is_connected = hdmi_is_connected,
|
||||
.get_edid = hdmi_get_edid,
|
||||
.check_timing = hdmi_check_timing,
|
||||
.check_mode = hdmi_check_mode,
|
||||
|
||||
/* manager */
|
||||
.mode_set = hdmi_mode_set,
|
||||
@ -1831,8 +1815,13 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
|
||||
DRM_ERROR("failed to get clock 'hdmiphy'\n");
|
||||
goto fail;
|
||||
}
|
||||
res->mout_hdmi = devm_clk_get(dev, "mout_hdmi");
|
||||
if (IS_ERR(res->mout_hdmi)) {
|
||||
DRM_ERROR("failed to get clock 'mout_hdmi'\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
|
||||
clk_set_parent(res->mout_hdmi, res->sclk_pixel);
|
||||
|
||||
res->regul_bulk = devm_kzalloc(dev, ARRAY_SIZE(supply) *
|
||||
sizeof(res->regul_bulk[0]), GFP_KERNEL);
|
||||
@ -1877,7 +1866,6 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct s5p_hdmi_platform_data *pd;
|
||||
enum of_gpio_flags flags;
|
||||
u32 value;
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
@ -1891,7 +1879,7 @@ static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
|
||||
goto err_data;
|
||||
}
|
||||
|
||||
pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
|
||||
pd->hpd_gpio = of_get_named_gpio(np, "hpd-gpio", 0);
|
||||
|
||||
return pd;
|
||||
|
||||
@ -1929,6 +1917,9 @@ static struct of_device_id hdmi_match_types[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5-hdmi",
|
||||
.data = (void *)HDMI_TYPE14,
|
||||
}, {
|
||||
.compatible = "samsung,exynos4212-hdmi",
|
||||
.data = (void *)HDMI_TYPE14,
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
@ -1944,8 +1935,6 @@ static int hdmi_probe(struct platform_device *pdev)
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_KMS("[%d]\n", __LINE__);
|
||||
|
||||
if (dev->of_node) {
|
||||
pdata = drm_hdmi_dt_parse_pdata(dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
@ -2071,8 +2060,6 @@ static int hdmi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
/* hdmiphy i2c driver */
|
||||
@ -2089,8 +2076,6 @@ static int hdmi_suspend(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
disable_irq(hdata->irq);
|
||||
|
||||
hdata->hpd = false;
|
||||
@ -2098,7 +2083,7 @@ static int hdmi_suspend(struct device *dev)
|
||||
drm_helper_hpd_irq_event(ctx->drm_dev);
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
|
||||
DRM_DEBUG_KMS("Already suspended\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2112,14 +2097,12 @@ static int hdmi_resume(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
hdata->hpd = gpio_get_value(hdata->hpd_gpio);
|
||||
|
||||
enable_irq(hdata->irq);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
|
||||
DRM_DEBUG_KMS("Already resumed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2134,7 +2117,6 @@ static int hdmi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
hdmi_poweroff(hdata);
|
||||
|
||||
@ -2145,7 +2127,6 @@ static int hdmi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
|
||||
struct hdmi_context *hdata = ctx->ctx;
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
hdmi_poweron(hdata);
|
||||
|
||||
|
@ -50,6 +50,10 @@ static const struct i2c_device_id hdmiphy_id[] = {
|
||||
static struct of_device_id hdmiphy_match_types[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5-hdmiphy",
|
||||
}, {
|
||||
.compatible = "samsung,exynos4210-hdmiphy",
|
||||
}, {
|
||||
.compatible = "samsung,exynos4212-hdmiphy",
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ struct mixer_resources {
|
||||
enum mixer_version_id {
|
||||
MXR_VER_0_0_0_16,
|
||||
MXR_VER_16_0_33_0,
|
||||
MXR_VER_128_0_0_184,
|
||||
};
|
||||
|
||||
struct mixer_context {
|
||||
@ -283,17 +284,19 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height)
|
||||
val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE :
|
||||
MXR_CFG_SCAN_PROGRASSIVE);
|
||||
|
||||
/* choosing between porper HD and SD mode */
|
||||
if (height <= 480)
|
||||
val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
|
||||
else if (height <= 576)
|
||||
val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
|
||||
else if (height <= 720)
|
||||
val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
|
||||
else if (height <= 1080)
|
||||
val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
|
||||
else
|
||||
val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
|
||||
if (ctx->mxr_ver != MXR_VER_128_0_0_184) {
|
||||
/* choosing between proper HD and SD mode */
|
||||
if (height <= 480)
|
||||
val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
|
||||
else if (height <= 576)
|
||||
val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
|
||||
else if (height <= 720)
|
||||
val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
|
||||
else if (height <= 1080)
|
||||
val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
|
||||
else
|
||||
val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
|
||||
}
|
||||
|
||||
mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK);
|
||||
}
|
||||
@ -557,6 +560,14 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
|
||||
/* setup geometry */
|
||||
mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), win_data->fb_width);
|
||||
|
||||
/* setup display size */
|
||||
if (ctx->mxr_ver == MXR_VER_128_0_0_184 &&
|
||||
win == MIXER_DEFAULT_WIN) {
|
||||
val = MXR_MXR_RES_HEIGHT(win_data->fb_height);
|
||||
val |= MXR_MXR_RES_WIDTH(win_data->fb_width);
|
||||
mixer_reg_write(res, MXR_RESOLUTION, val);
|
||||
}
|
||||
|
||||
val = MXR_GRP_WH_WIDTH(win_data->crtc_width);
|
||||
val |= MXR_GRP_WH_HEIGHT(win_data->crtc_height);
|
||||
val |= MXR_GRP_WH_H_SCALE(x_ratio);
|
||||
@ -581,7 +592,8 @@ static void mixer_graph_buffer(struct mixer_context *ctx, int win)
|
||||
mixer_cfg_layer(ctx, win, true);
|
||||
|
||||
/* layer update mandatory for mixer 16.0.33.0 */
|
||||
if (ctx->mxr_ver == MXR_VER_16_0_33_0)
|
||||
if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
|
||||
ctx->mxr_ver == MXR_VER_128_0_0_184)
|
||||
mixer_layer_update(ctx);
|
||||
|
||||
mixer_run(ctx);
|
||||
@ -696,8 +708,6 @@ static int mixer_enable_vblank(void *ctx, int pipe)
|
||||
struct mixer_context *mixer_ctx = ctx;
|
||||
struct mixer_resources *res = &mixer_ctx->mixer_res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mixer_ctx->pipe = pipe;
|
||||
|
||||
/* enable vsync interrupt */
|
||||
@ -712,8 +722,6 @@ static void mixer_disable_vblank(void *ctx)
|
||||
struct mixer_context *mixer_ctx = ctx;
|
||||
struct mixer_resources *res = &mixer_ctx->mixer_res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
/* disable vsync interrupt */
|
||||
mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
|
||||
}
|
||||
@ -725,8 +733,6 @@ static void mixer_win_mode_set(void *ctx,
|
||||
struct hdmi_win_data *win_data;
|
||||
int win;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (!overlay) {
|
||||
DRM_ERROR("overlay is NULL\n");
|
||||
return;
|
||||
@ -742,7 +748,7 @@ static void mixer_win_mode_set(void *ctx,
|
||||
if (win == DEFAULT_ZPOS)
|
||||
win = MIXER_DEFAULT_WIN;
|
||||
|
||||
if (win < 0 || win > MIXER_WIN_NR) {
|
||||
if (win < 0 || win >= MIXER_WIN_NR) {
|
||||
DRM_ERROR("mixer window[%d] is wrong\n", win);
|
||||
return;
|
||||
}
|
||||
@ -776,7 +782,7 @@ static void mixer_win_commit(void *ctx, int win)
|
||||
{
|
||||
struct mixer_context *mixer_ctx = ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
|
||||
DRM_DEBUG_KMS("win: %d\n", win);
|
||||
|
||||
mutex_lock(&mixer_ctx->mixer_mutex);
|
||||
if (!mixer_ctx->powered) {
|
||||
@ -799,7 +805,7 @@ static void mixer_win_disable(void *ctx, int win)
|
||||
struct mixer_resources *res = &mixer_ctx->mixer_res;
|
||||
unsigned long flags;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
|
||||
DRM_DEBUG_KMS("win: %d\n", win);
|
||||
|
||||
mutex_lock(&mixer_ctx->mixer_mutex);
|
||||
if (!mixer_ctx->powered) {
|
||||
@ -820,17 +826,21 @@ static void mixer_win_disable(void *ctx, int win)
|
||||
mixer_ctx->win_data[win].enabled = false;
|
||||
}
|
||||
|
||||
static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
|
||||
static int mixer_check_mode(void *ctx, struct drm_display_mode *mode)
|
||||
{
|
||||
struct mixer_context *mixer_ctx = ctx;
|
||||
u32 w, h;
|
||||
|
||||
w = timing->xres;
|
||||
h = timing->yres;
|
||||
w = mode->hdisplay;
|
||||
h = mode->vdisplay;
|
||||
|
||||
DRM_DEBUG_KMS("%s : xres=%d, yres=%d, refresh=%d, intl=%d\n",
|
||||
__func__, timing->xres, timing->yres,
|
||||
timing->refresh, (timing->vmode &
|
||||
FB_VMODE_INTERLACED) ? true : false);
|
||||
DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
|
||||
mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);
|
||||
|
||||
if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16 ||
|
||||
mixer_ctx->mxr_ver == MXR_VER_128_0_0_184)
|
||||
return 0;
|
||||
|
||||
if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
|
||||
(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
|
||||
@ -891,8 +901,6 @@ static void mixer_poweron(struct mixer_context *ctx)
|
||||
{
|
||||
struct mixer_resources *res = &ctx->mixer_res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&ctx->mixer_mutex);
|
||||
if (ctx->powered) {
|
||||
mutex_unlock(&ctx->mixer_mutex);
|
||||
@ -901,10 +909,10 @@ static void mixer_poweron(struct mixer_context *ctx)
|
||||
ctx->powered = true;
|
||||
mutex_unlock(&ctx->mixer_mutex);
|
||||
|
||||
clk_enable(res->mixer);
|
||||
clk_prepare_enable(res->mixer);
|
||||
if (ctx->vp_enabled) {
|
||||
clk_enable(res->vp);
|
||||
clk_enable(res->sclk_mixer);
|
||||
clk_prepare_enable(res->vp);
|
||||
clk_prepare_enable(res->sclk_mixer);
|
||||
}
|
||||
|
||||
mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
|
||||
@ -917,8 +925,6 @@ static void mixer_poweroff(struct mixer_context *ctx)
|
||||
{
|
||||
struct mixer_resources *res = &ctx->mixer_res;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mutex_lock(&ctx->mixer_mutex);
|
||||
if (!ctx->powered)
|
||||
goto out;
|
||||
@ -928,10 +934,10 @@ static void mixer_poweroff(struct mixer_context *ctx)
|
||||
|
||||
ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
|
||||
|
||||
clk_disable(res->mixer);
|
||||
clk_disable_unprepare(res->mixer);
|
||||
if (ctx->vp_enabled) {
|
||||
clk_disable(res->vp);
|
||||
clk_disable(res->sclk_mixer);
|
||||
clk_disable_unprepare(res->vp);
|
||||
clk_disable_unprepare(res->sclk_mixer);
|
||||
}
|
||||
|
||||
mutex_lock(&ctx->mixer_mutex);
|
||||
@ -945,8 +951,6 @@ static void mixer_dpms(void *ctx, int mode)
|
||||
{
|
||||
struct mixer_context *mixer_ctx = ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
if (pm_runtime_suspended(mixer_ctx->dev))
|
||||
@ -978,7 +982,7 @@ static struct exynos_mixer_ops mixer_ops = {
|
||||
.win_disable = mixer_win_disable,
|
||||
|
||||
/* display */
|
||||
.check_timing = mixer_check_timing,
|
||||
.check_mode = mixer_check_mode,
|
||||
};
|
||||
|
||||
static irqreturn_t mixer_irq_handler(int irq, void *arg)
|
||||
@ -1128,12 +1132,17 @@ static int vp_resources_init(struct exynos_drm_hdmi_context *ctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mixer_drv_data exynos5_mxr_drv_data = {
|
||||
static struct mixer_drv_data exynos5420_mxr_drv_data = {
|
||||
.version = MXR_VER_128_0_0_184,
|
||||
.is_vp_enabled = 0,
|
||||
};
|
||||
|
||||
static struct mixer_drv_data exynos5250_mxr_drv_data = {
|
||||
.version = MXR_VER_16_0_33_0,
|
||||
.is_vp_enabled = 0,
|
||||
};
|
||||
|
||||
static struct mixer_drv_data exynos4_mxr_drv_data = {
|
||||
static struct mixer_drv_data exynos4210_mxr_drv_data = {
|
||||
.version = MXR_VER_0_0_0_16,
|
||||
.is_vp_enabled = 1,
|
||||
};
|
||||
@ -1141,10 +1150,10 @@ static struct mixer_drv_data exynos4_mxr_drv_data = {
|
||||
static struct platform_device_id mixer_driver_types[] = {
|
||||
{
|
||||
.name = "s5p-mixer",
|
||||
.driver_data = (unsigned long)&exynos4_mxr_drv_data,
|
||||
.driver_data = (unsigned long)&exynos4210_mxr_drv_data,
|
||||
}, {
|
||||
.name = "exynos5-mixer",
|
||||
.driver_data = (unsigned long)&exynos5_mxr_drv_data,
|
||||
.driver_data = (unsigned long)&exynos5250_mxr_drv_data,
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
@ -1153,7 +1162,13 @@ static struct platform_device_id mixer_driver_types[] = {
|
||||
static struct of_device_id mixer_match_types[] = {
|
||||
{
|
||||
.compatible = "samsung,exynos5-mixer",
|
||||
.data = &exynos5_mxr_drv_data,
|
||||
.data = &exynos5250_mxr_drv_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5250-mixer",
|
||||
.data = &exynos5250_mxr_drv_data,
|
||||
}, {
|
||||
.compatible = "samsung,exynos5420-mixer",
|
||||
.data = &exynos5420_mxr_drv_data,
|
||||
}, {
|
||||
/* end node */
|
||||
}
|
||||
@ -1186,8 +1201,7 @@ static int mixer_probe(struct platform_device *pdev)
|
||||
|
||||
if (dev->of_node) {
|
||||
const struct of_device_id *match;
|
||||
match = of_match_node(of_match_ptr(mixer_match_types),
|
||||
dev->of_node);
|
||||
match = of_match_node(mixer_match_types, dev->of_node);
|
||||
drv = (struct mixer_drv_data *)match->data;
|
||||
} else {
|
||||
drv = (struct mixer_drv_data *)
|
||||
@ -1251,10 +1265,8 @@ static int mixer_suspend(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
|
||||
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("%s : Already suspended\n", __func__);
|
||||
DRM_DEBUG_KMS("Already suspended\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1268,10 +1280,8 @@ static int mixer_resume(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
|
||||
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
if (!pm_runtime_suspended(dev)) {
|
||||
DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
|
||||
DRM_DEBUG_KMS("Already resumed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1287,8 +1297,6 @@ static int mixer_runtime_suspend(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
|
||||
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mixer_poweroff(ctx);
|
||||
|
||||
return 0;
|
||||
@ -1299,8 +1307,6 @@ static int mixer_runtime_resume(struct device *dev)
|
||||
struct exynos_drm_hdmi_context *drm_hdmi_ctx = get_mixer_context(dev);
|
||||
struct mixer_context *ctx = drm_hdmi_ctx->ctx;
|
||||
|
||||
DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
|
||||
|
||||
mixer_poweron(ctx);
|
||||
|
||||
return 0;
|
||||
|
@ -44,6 +44,9 @@
|
||||
#define MXR_CM_COEFF_Y 0x0080
|
||||
#define MXR_CM_COEFF_CB 0x0084
|
||||
#define MXR_CM_COEFF_CR 0x0088
|
||||
#define MXR_MO 0x0304
|
||||
#define MXR_RESOLUTION 0x0310
|
||||
|
||||
#define MXR_GRAPHIC0_BASE_S 0x2024
|
||||
#define MXR_GRAPHIC1_BASE_S 0x2044
|
||||
|
||||
@ -119,6 +122,10 @@
|
||||
#define MXR_GRP_WH_WIDTH(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_GRP_WH_HEIGHT(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
||||
/* bits for MXR_RESOLUTION */
|
||||
#define MXR_MXR_RES_HEIGHT(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_MXR_RES_WIDTH(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
||||
/* bits for MXR_GRAPHICn_SXY */
|
||||
#define MXR_GRP_SXY_SX(x) MXR_MASK_VAL(x, 26, 16)
|
||||
#define MXR_GRP_SXY_SY(x) MXR_MASK_VAL(x, 10, 0)
|
||||
|
@ -36,6 +36,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
|
||||
intel_overlay.o \
|
||||
intel_sprite.o \
|
||||
intel_opregion.o \
|
||||
intel_sideband.o \
|
||||
dvo_ch7xxx.o \
|
||||
dvo_ch7017.o \
|
||||
dvo_ivch.o \
|
||||
|
@ -32,12 +32,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#define CH7xxx_REG_DID 0x4b
|
||||
|
||||
#define CH7011_VID 0x83 /* 7010 as well */
|
||||
#define CH7010B_VID 0x05
|
||||
#define CH7009A_VID 0x84
|
||||
#define CH7009B_VID 0x85
|
||||
#define CH7301_VID 0x95
|
||||
|
||||
#define CH7xxx_VID 0x84
|
||||
#define CH7xxx_DID 0x17
|
||||
#define CH7010_DID 0x16
|
||||
|
||||
#define CH7xxx_NUM_REGS 0x4c
|
||||
|
||||
@ -87,11 +89,20 @@ static struct ch7xxx_id_struct {
|
||||
char *name;
|
||||
} ch7xxx_ids[] = {
|
||||
{ CH7011_VID, "CH7011" },
|
||||
{ CH7010B_VID, "CH7010B" },
|
||||
{ CH7009A_VID, "CH7009A" },
|
||||
{ CH7009B_VID, "CH7009B" },
|
||||
{ CH7301_VID, "CH7301" },
|
||||
};
|
||||
|
||||
static struct ch7xxx_did_struct {
|
||||
uint8_t did;
|
||||
char *name;
|
||||
} ch7xxx_dids[] = {
|
||||
{ CH7xxx_DID, "CH7XXX" },
|
||||
{ CH7010_DID, "CH7010B" },
|
||||
};
|
||||
|
||||
struct ch7xxx_priv {
|
||||
bool quiet;
|
||||
};
|
||||
@ -108,6 +119,18 @@ static char *ch7xxx_get_id(uint8_t vid)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *ch7xxx_get_did(uint8_t did)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ch7xxx_dids); i++) {
|
||||
if (ch7xxx_dids[i].did == did)
|
||||
return ch7xxx_dids[i].name;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Reads an 8 bit register */
|
||||
static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch)
|
||||
{
|
||||
@ -179,7 +202,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
|
||||
/* this will detect the CH7xxx chip on the specified i2c bus */
|
||||
struct ch7xxx_priv *ch7xxx;
|
||||
uint8_t vendor, device;
|
||||
char *name;
|
||||
char *name, *devid;
|
||||
|
||||
ch7xxx = kzalloc(sizeof(struct ch7xxx_priv), GFP_KERNEL);
|
||||
if (ch7xxx == NULL)
|
||||
@ -204,7 +227,8 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo,
|
||||
if (!ch7xxx_readb(dvo, CH7xxx_REG_DID, &device))
|
||||
goto out;
|
||||
|
||||
if (device != CH7xxx_DID) {
|
||||
devid = ch7xxx_get_did(device);
|
||||
if (!devid) {
|
||||
DRM_DEBUG_KMS("ch7xxx not detected; got 0x%02x from %s "
|
||||
"slave %d.\n",
|
||||
vendor, adapter->name, dvo->slave_addr);
|
||||
|
@ -61,11 +61,11 @@ static int i915_capabilities(struct seq_file *m, void *data)
|
||||
|
||||
seq_printf(m, "gen: %d\n", info->gen);
|
||||
seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev));
|
||||
#define DEV_INFO_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
|
||||
#define DEV_INFO_SEP ;
|
||||
DEV_INFO_FLAGS;
|
||||
#undef DEV_INFO_FLAG
|
||||
#undef DEV_INFO_SEP
|
||||
#define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x))
|
||||
#define SEP_SEMICOLON ;
|
||||
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON);
|
||||
#undef PRINT_FLAG
|
||||
#undef SEP_SEMICOLON
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -196,6 +196,32 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
struct file_stats {
|
||||
int count;
|
||||
size_t total, active, inactive, unbound;
|
||||
};
|
||||
|
||||
static int per_file_stats(int id, void *ptr, void *data)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = ptr;
|
||||
struct file_stats *stats = data;
|
||||
|
||||
stats->count++;
|
||||
stats->total += obj->base.size;
|
||||
|
||||
if (obj->gtt_space) {
|
||||
if (!list_empty(&obj->ring_list))
|
||||
stats->active += obj->base.size;
|
||||
else
|
||||
stats->inactive += obj->base.size;
|
||||
} else {
|
||||
if (!list_empty(&obj->global_list))
|
||||
stats->unbound += obj->base.size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
@ -204,6 +230,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
u32 count, mappable_count, purgeable_count;
|
||||
size_t size, mappable_size, purgeable_size;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_file *file;
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
@ -215,7 +242,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
dev_priv->mm.object_memory);
|
||||
|
||||
size = count = mappable_size = mappable_count = 0;
|
||||
count_objects(&dev_priv->mm.bound_list, gtt_list);
|
||||
count_objects(&dev_priv->mm.bound_list, global_list);
|
||||
seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n",
|
||||
count, mappable_count, size, mappable_size);
|
||||
|
||||
@ -230,7 +257,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
count, mappable_count, size, mappable_size);
|
||||
|
||||
size = count = purgeable_size = purgeable_count = 0;
|
||||
list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
|
||||
size += obj->base.size, ++count;
|
||||
if (obj->madv == I915_MADV_DONTNEED)
|
||||
purgeable_size += obj->base.size, ++purgeable_count;
|
||||
@ -238,7 +265,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
seq_printf(m, "%u unbound objects, %zu bytes\n", count, size);
|
||||
|
||||
size = count = mappable_size = mappable_count = 0;
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
|
||||
if (obj->fault_mappable) {
|
||||
size += obj->gtt_space->size;
|
||||
++count;
|
||||
@ -263,6 +290,21 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
|
||||
dev_priv->gtt.total,
|
||||
dev_priv->gtt.mappable_end - dev_priv->gtt.start);
|
||||
|
||||
seq_printf(m, "\n");
|
||||
list_for_each_entry_reverse(file, &dev->filelist, lhead) {
|
||||
struct file_stats stats;
|
||||
|
||||
memset(&stats, 0, sizeof(stats));
|
||||
idr_for_each(&file->object_idr, per_file_stats, &stats);
|
||||
seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n",
|
||||
get_pid_task(file->pid, PIDTYPE_PID)->comm,
|
||||
stats.count,
|
||||
stats.total,
|
||||
stats.active,
|
||||
stats.inactive,
|
||||
stats.unbound);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
return 0;
|
||||
@ -283,7 +325,7 @@ static int i915_gem_gtt_info(struct seq_file *m, void* data)
|
||||
return ret;
|
||||
|
||||
total_obj_size = total_gtt_size = count = 0;
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
|
||||
if (list == PINNED_LIST && obj->pin_count == 0)
|
||||
continue;
|
||||
|
||||
@ -570,6 +612,7 @@ static const char *ring_str(int ring)
|
||||
case RCS: return "render";
|
||||
case VCS: return "bsd";
|
||||
case BCS: return "blt";
|
||||
case VECS: return "vebox";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@ -604,73 +647,187 @@ static const char *purgeable_flag(int purgeable)
|
||||
return purgeable ? " purgeable" : "";
|
||||
}
|
||||
|
||||
static void print_error_buffers(struct seq_file *m,
|
||||
static bool __i915_error_ok(struct drm_i915_error_state_buf *e)
|
||||
{
|
||||
|
||||
if (!e->err && WARN(e->bytes > (e->size - 1), "overflow")) {
|
||||
e->err = -ENOSPC;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e->bytes == e->size - 1 || e->err)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __i915_error_seek(struct drm_i915_error_state_buf *e,
|
||||
unsigned len)
|
||||
{
|
||||
if (e->pos + len <= e->start) {
|
||||
e->pos += len;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* First vsnprintf needs to fit in its entirety for memmove */
|
||||
if (len >= e->size) {
|
||||
e->err = -EIO;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void __i915_error_advance(struct drm_i915_error_state_buf *e,
|
||||
unsigned len)
|
||||
{
|
||||
/* If this is first printf in this window, adjust it so that
|
||||
* start position matches start of the buffer
|
||||
*/
|
||||
|
||||
if (e->pos < e->start) {
|
||||
const size_t off = e->start - e->pos;
|
||||
|
||||
/* Should not happen but be paranoid */
|
||||
if (off > len || e->bytes) {
|
||||
e->err = -EIO;
|
||||
return;
|
||||
}
|
||||
|
||||
memmove(e->buf, e->buf + off, len - off);
|
||||
e->bytes = len - off;
|
||||
e->pos = e->start;
|
||||
return;
|
||||
}
|
||||
|
||||
e->bytes += len;
|
||||
e->pos += len;
|
||||
}
|
||||
|
||||
static void i915_error_vprintf(struct drm_i915_error_state_buf *e,
|
||||
const char *f, va_list args)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if (!__i915_error_ok(e))
|
||||
return;
|
||||
|
||||
/* Seek the first printf which is hits start position */
|
||||
if (e->pos < e->start) {
|
||||
len = vsnprintf(NULL, 0, f, args);
|
||||
if (!__i915_error_seek(e, len))
|
||||
return;
|
||||
}
|
||||
|
||||
len = vsnprintf(e->buf + e->bytes, e->size - e->bytes, f, args);
|
||||
if (len >= e->size - e->bytes)
|
||||
len = e->size - e->bytes - 1;
|
||||
|
||||
__i915_error_advance(e, len);
|
||||
}
|
||||
|
||||
static void i915_error_puts(struct drm_i915_error_state_buf *e,
|
||||
const char *str)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
if (!__i915_error_ok(e))
|
||||
return;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
/* Seek the first printf which is hits start position */
|
||||
if (e->pos < e->start) {
|
||||
if (!__i915_error_seek(e, len))
|
||||
return;
|
||||
}
|
||||
|
||||
if (len >= e->size - e->bytes)
|
||||
len = e->size - e->bytes - 1;
|
||||
memcpy(e->buf + e->bytes, str, len);
|
||||
|
||||
__i915_error_advance(e, len);
|
||||
}
|
||||
|
||||
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, f);
|
||||
i915_error_vprintf(e, f, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
#define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__)
|
||||
#define err_puts(e, s) i915_error_puts(e, s)
|
||||
|
||||
static void print_error_buffers(struct drm_i915_error_state_buf *m,
|
||||
const char *name,
|
||||
struct drm_i915_error_buffer *err,
|
||||
int count)
|
||||
{
|
||||
seq_printf(m, "%s [%d]:\n", name, count);
|
||||
err_printf(m, "%s [%d]:\n", name, count);
|
||||
|
||||
while (count--) {
|
||||
seq_printf(m, " %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",
|
||||
err_printf(m, " %08x %8u %02x %02x %x %x",
|
||||
err->gtt_offset,
|
||||
err->size,
|
||||
err->read_domains,
|
||||
err->write_domain,
|
||||
err->rseqno, err->wseqno,
|
||||
pin_flag(err->pinned),
|
||||
tiling_flag(err->tiling),
|
||||
dirty_flag(err->dirty),
|
||||
purgeable_flag(err->purgeable),
|
||||
err->ring != -1 ? " " : "",
|
||||
ring_str(err->ring),
|
||||
cache_level_str(err->cache_level));
|
||||
err->rseqno, err->wseqno);
|
||||
err_puts(m, pin_flag(err->pinned));
|
||||
err_puts(m, tiling_flag(err->tiling));
|
||||
err_puts(m, dirty_flag(err->dirty));
|
||||
err_puts(m, purgeable_flag(err->purgeable));
|
||||
err_puts(m, err->ring != -1 ? " " : "");
|
||||
err_puts(m, ring_str(err->ring));
|
||||
err_puts(m, cache_level_str(err->cache_level));
|
||||
|
||||
if (err->name)
|
||||
seq_printf(m, " (name: %d)", err->name);
|
||||
err_printf(m, " (name: %d)", err->name);
|
||||
if (err->fence_reg != I915_FENCE_REG_NONE)
|
||||
seq_printf(m, " (fence: %d)", err->fence_reg);
|
||||
err_printf(m, " (fence: %d)", err->fence_reg);
|
||||
|
||||
seq_printf(m, "\n");
|
||||
err_puts(m, "\n");
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_ring_error_state(struct seq_file *m,
|
||||
static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
|
||||
struct drm_device *dev,
|
||||
struct drm_i915_error_state *error,
|
||||
unsigned ring)
|
||||
{
|
||||
BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */
|
||||
seq_printf(m, "%s command stream:\n", ring_str(ring));
|
||||
seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
|
||||
seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
|
||||
seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]);
|
||||
seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]);
|
||||
seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
||||
seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||
seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]);
|
||||
err_printf(m, "%s command stream:\n", ring_str(ring));
|
||||
err_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
|
||||
err_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
|
||||
err_printf(m, " CTL: 0x%08x\n", error->ctl[ring]);
|
||||
err_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]);
|
||||
err_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
||||
err_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||
err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]);
|
||||
if (ring == RCS && INTEL_INFO(dev)->gen >= 4)
|
||||
seq_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr);
|
||||
err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4)
|
||||
seq_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]);
|
||||
seq_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
|
||||
seq_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
|
||||
err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]);
|
||||
err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]);
|
||||
err_printf(m, " FADDR: 0x%08x\n", error->faddr[ring]);
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
seq_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
|
||||
seq_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
|
||||
seq_printf(m, " SYNC_0: 0x%08x [last synced 0x%08x]\n",
|
||||
err_printf(m, " RC PSMI: 0x%08x\n", error->rc_psmi[ring]);
|
||||
err_printf(m, " FAULT_REG: 0x%08x\n", error->fault_reg[ring]);
|
||||
err_printf(m, " SYNC_0: 0x%08x [last synced 0x%08x]\n",
|
||||
error->semaphore_mboxes[ring][0],
|
||||
error->semaphore_seqno[ring][0]);
|
||||
seq_printf(m, " SYNC_1: 0x%08x [last synced 0x%08x]\n",
|
||||
err_printf(m, " SYNC_1: 0x%08x [last synced 0x%08x]\n",
|
||||
error->semaphore_mboxes[ring][1],
|
||||
error->semaphore_seqno[ring][1]);
|
||||
}
|
||||
seq_printf(m, " seqno: 0x%08x\n", error->seqno[ring]);
|
||||
seq_printf(m, " waiting: %s\n", yesno(error->waiting[ring]));
|
||||
seq_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
|
||||
seq_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
|
||||
err_printf(m, " seqno: 0x%08x\n", error->seqno[ring]);
|
||||
err_printf(m, " waiting: %s\n", yesno(error->waiting[ring]));
|
||||
err_printf(m, " ring->head: 0x%08x\n", error->cpu_ring_head[ring]);
|
||||
err_printf(m, " ring->tail: 0x%08x\n", error->cpu_ring_tail[ring]);
|
||||
}
|
||||
|
||||
struct i915_error_state_file_priv {
|
||||
@ -678,9 +835,11 @@ struct i915_error_state_file_priv {
|
||||
struct drm_i915_error_state *error;
|
||||
};
|
||||
|
||||
static int i915_error_state(struct seq_file *m, void *unused)
|
||||
|
||||
static int i915_error_state(struct i915_error_state_file_priv *error_priv,
|
||||
struct drm_i915_error_state_buf *m)
|
||||
|
||||
{
|
||||
struct i915_error_state_file_priv *error_priv = m->private;
|
||||
struct drm_device *dev = error_priv->dev;
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
struct drm_i915_error_state *error = error_priv->error;
|
||||
@ -688,34 +847,35 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||
int i, j, page, offset, elt;
|
||||
|
||||
if (!error) {
|
||||
seq_printf(m, "no error state collected\n");
|
||||
err_printf(m, "no error state collected\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
||||
err_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
|
||||
error->time.tv_usec);
|
||||
seq_printf(m, "Kernel: " UTS_RELEASE "\n");
|
||||
seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
||||
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
seq_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
seq_printf(m, "CCID: 0x%08x\n", error->ccid);
|
||||
err_printf(m, "Kernel: " UTS_RELEASE "\n");
|
||||
err_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
|
||||
err_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
err_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
err_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
err_printf(m, "CCID: 0x%08x\n", error->ccid);
|
||||
|
||||
for (i = 0; i < dev_priv->num_fence_regs; i++)
|
||||
seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
|
||||
err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++)
|
||||
seq_printf(m, " INSTDONE_%d: 0x%08x\n", i, error->extra_instdone[i]);
|
||||
err_printf(m, " INSTDONE_%d: 0x%08x\n", i,
|
||||
error->extra_instdone[i]);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
seq_printf(m, "ERROR: 0x%08x\n", error->error);
|
||||
seq_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
|
||||
err_printf(m, "ERROR: 0x%08x\n", error->error);
|
||||
err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg);
|
||||
}
|
||||
|
||||
if (INTEL_INFO(dev)->gen == 7)
|
||||
seq_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
|
||||
err_printf(m, "ERR_INT: 0x%08x\n", error->err_int);
|
||||
|
||||
for_each_ring(ring, dev_priv, i)
|
||||
i915_ring_error_state(m, dev, error, i);
|
||||
@ -734,24 +894,25 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||
struct drm_i915_error_object *obj;
|
||||
|
||||
if ((obj = error->ring[i].batchbuffer)) {
|
||||
seq_printf(m, "%s --- gtt_offset = 0x%08x\n",
|
||||
err_printf(m, "%s --- gtt_offset = 0x%08x\n",
|
||||
dev_priv->ring[i].name,
|
||||
obj->gtt_offset);
|
||||
offset = 0;
|
||||
for (page = 0; page < obj->page_count; page++) {
|
||||
for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
||||
seq_printf(m, "%08x : %08x\n", offset, obj->pages[page][elt]);
|
||||
err_printf(m, "%08x : %08x\n", offset,
|
||||
obj->pages[page][elt]);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error->ring[i].num_requests) {
|
||||
seq_printf(m, "%s --- %d requests\n",
|
||||
err_printf(m, "%s --- %d requests\n",
|
||||
dev_priv->ring[i].name,
|
||||
error->ring[i].num_requests);
|
||||
for (j = 0; j < error->ring[i].num_requests; j++) {
|
||||
seq_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n",
|
||||
err_printf(m, " seqno 0x%08x, emitted %ld, tail 0x%08x\n",
|
||||
error->ring[i].requests[j].seqno,
|
||||
error->ring[i].requests[j].jiffies,
|
||||
error->ring[i].requests[j].tail);
|
||||
@ -759,13 +920,13 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||
}
|
||||
|
||||
if ((obj = error->ring[i].ringbuffer)) {
|
||||
seq_printf(m, "%s --- ringbuffer = 0x%08x\n",
|
||||
err_printf(m, "%s --- ringbuffer = 0x%08x\n",
|
||||
dev_priv->ring[i].name,
|
||||
obj->gtt_offset);
|
||||
offset = 0;
|
||||
for (page = 0; page < obj->page_count; page++) {
|
||||
for (elt = 0; elt < PAGE_SIZE/4; elt++) {
|
||||
seq_printf(m, "%08x : %08x\n",
|
||||
err_printf(m, "%08x : %08x\n",
|
||||
offset,
|
||||
obj->pages[page][elt]);
|
||||
offset += 4;
|
||||
@ -775,12 +936,12 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
||||
|
||||
obj = error->ring[i].ctx;
|
||||
if (obj) {
|
||||
seq_printf(m, "%s --- HW Context = 0x%08x\n",
|
||||
err_printf(m, "%s --- HW Context = 0x%08x\n",
|
||||
dev_priv->ring[i].name,
|
||||
obj->gtt_offset);
|
||||
offset = 0;
|
||||
for (elt = 0; elt < PAGE_SIZE/16; elt += 4) {
|
||||
seq_printf(m, "[%04x] %08x %08x %08x %08x\n",
|
||||
err_printf(m, "[%04x] %08x %08x %08x %08x\n",
|
||||
offset,
|
||||
obj->pages[0][elt],
|
||||
obj->pages[0][elt+1],
|
||||
@ -806,8 +967,7 @@ i915_error_state_write(struct file *filp,
|
||||
size_t cnt,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct seq_file *m = filp->private_data;
|
||||
struct i915_error_state_file_priv *error_priv = m->private;
|
||||
struct i915_error_state_file_priv *error_priv = filp->private_data;
|
||||
struct drm_device *dev = error_priv->dev;
|
||||
int ret;
|
||||
|
||||
@ -842,25 +1002,81 @@ static int i915_error_state_open(struct inode *inode, struct file *file)
|
||||
kref_get(&error_priv->error->ref);
|
||||
spin_unlock_irqrestore(&dev_priv->gpu_error.lock, flags);
|
||||
|
||||
return single_open(file, i915_error_state, error_priv);
|
||||
file->private_data = error_priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_error_state_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct seq_file *m = file->private_data;
|
||||
struct i915_error_state_file_priv *error_priv = m->private;
|
||||
struct i915_error_state_file_priv *error_priv = file->private_data;
|
||||
|
||||
if (error_priv->error)
|
||||
kref_put(&error_priv->error->ref, i915_error_state_free);
|
||||
kfree(error_priv);
|
||||
|
||||
return single_release(inode, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t i915_error_state_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *pos)
|
||||
{
|
||||
struct i915_error_state_file_priv *error_priv = file->private_data;
|
||||
struct drm_i915_error_state_buf error_str;
|
||||
loff_t tmp_pos = 0;
|
||||
ssize_t ret_count = 0;
|
||||
int ret = 0;
|
||||
|
||||
memset(&error_str, 0, sizeof(error_str));
|
||||
|
||||
/* We need to have enough room to store any i915_error_state printf
|
||||
* so that we can move it to start position.
|
||||
*/
|
||||
error_str.size = count + 1 > PAGE_SIZE ? count + 1 : PAGE_SIZE;
|
||||
error_str.buf = kmalloc(error_str.size,
|
||||
GFP_TEMPORARY | __GFP_NORETRY | __GFP_NOWARN);
|
||||
|
||||
if (error_str.buf == NULL) {
|
||||
error_str.size = PAGE_SIZE;
|
||||
error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
|
||||
}
|
||||
|
||||
if (error_str.buf == NULL) {
|
||||
error_str.size = 128;
|
||||
error_str.buf = kmalloc(error_str.size, GFP_TEMPORARY);
|
||||
}
|
||||
|
||||
if (error_str.buf == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
error_str.start = *pos;
|
||||
|
||||
ret = i915_error_state(error_priv, &error_str);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (error_str.bytes == 0 && error_str.err) {
|
||||
ret = error_str.err;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_count = simple_read_from_buffer(userbuf, count, &tmp_pos,
|
||||
error_str.buf,
|
||||
error_str.bytes);
|
||||
|
||||
if (ret_count < 0)
|
||||
ret = ret_count;
|
||||
else
|
||||
*pos = error_str.start + ret_count;
|
||||
out:
|
||||
kfree(error_str.buf);
|
||||
return ret ?: ret_count;
|
||||
}
|
||||
|
||||
static const struct file_operations i915_error_state_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = i915_error_state_open,
|
||||
.read = seq_read,
|
||||
.read = i915_error_state_read,
|
||||
.write = i915_error_state_write,
|
||||
.llseek = default_llseek,
|
||||
.release = i915_error_state_release,
|
||||
@ -941,7 +1157,7 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
||||
MEMSTAT_VID_SHIFT);
|
||||
seq_printf(m, "Current P-state: %d\n",
|
||||
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
|
||||
} else if (IS_GEN6(dev) || IS_GEN7(dev)) {
|
||||
} else if ((IS_GEN6(dev) || IS_GEN7(dev)) && !IS_VALLEYVIEW(dev)) {
|
||||
u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
|
||||
u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
|
||||
u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
@ -1009,6 +1225,26 @@ static int i915_cur_delayinfo(struct seq_file *m, void *unused)
|
||||
|
||||
seq_printf(m, "Max overclocked frequency: %dMHz\n",
|
||||
dev_priv->rps.hw_max * GT_FREQUENCY_MULTIPLIER);
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
u32 freq_sts, val;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
|
||||
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
|
||||
|
||||
val = vlv_punit_read(dev_priv, PUNIT_FUSE_BUS1);
|
||||
seq_printf(m, "max GPU freq: %d MHz\n",
|
||||
vlv_gpu_freq(dev_priv->mem_freq, val));
|
||||
|
||||
val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_LFM);
|
||||
seq_printf(m, "min GPU freq: %d MHz\n",
|
||||
vlv_gpu_freq(dev_priv->mem_freq, val));
|
||||
|
||||
seq_printf(m, "current GPU freq: %d MHz\n",
|
||||
vlv_gpu_freq(dev_priv->mem_freq,
|
||||
(freq_sts >> 8) & 0xff));
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
} else {
|
||||
seq_printf(m, "no P-state info available\n");
|
||||
}
|
||||
@ -1290,6 +1526,25 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_ips_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!HAS_IPS(dev)) {
|
||||
seq_puts(m, "not supported\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (I915_READ(IPS_CTL) & IPS_ENABLE)
|
||||
seq_puts(m, "enabled\n");
|
||||
else
|
||||
seq_puts(m, "disabled\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
@ -1642,27 +1897,27 @@ static int i915_dpio_info(struct seq_file *m, void *data)
|
||||
seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL));
|
||||
|
||||
seq_printf(m, "DPIO_DIV_A: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_DIV_A));
|
||||
vlv_dpio_read(dev_priv, _DPIO_DIV_A));
|
||||
seq_printf(m, "DPIO_DIV_B: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_DIV_B));
|
||||
vlv_dpio_read(dev_priv, _DPIO_DIV_B));
|
||||
|
||||
seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_REFSFR_A));
|
||||
vlv_dpio_read(dev_priv, _DPIO_REFSFR_A));
|
||||
seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_REFSFR_B));
|
||||
vlv_dpio_read(dev_priv, _DPIO_REFSFR_B));
|
||||
|
||||
seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
|
||||
vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_A));
|
||||
seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
|
||||
vlv_dpio_read(dev_priv, _DPIO_CORE_CLK_B));
|
||||
|
||||
seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A));
|
||||
seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B));
|
||||
seq_printf(m, "DPIO_LPF_COEFF_A: 0x%08x\n",
|
||||
vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_A));
|
||||
seq_printf(m, "DPIO_LPF_COEFF_B: 0x%08x\n",
|
||||
vlv_dpio_read(dev_priv, _DPIO_LPF_COEFF_B));
|
||||
|
||||
seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",
|
||||
intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
|
||||
vlv_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE));
|
||||
|
||||
mutex_unlock(&dev_priv->dpio_lock);
|
||||
|
||||
@ -1780,7 +2035,8 @@ i915_drop_caches_set(void *data, u64 val)
|
||||
}
|
||||
|
||||
if (val & DROP_UNBOUND) {
|
||||
list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
|
||||
list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
|
||||
global_list)
|
||||
if (obj->pages_pin_count == 0) {
|
||||
ret = i915_gem_object_put_pages(obj);
|
||||
if (ret)
|
||||
@ -1812,7 +2068,11 @@ i915_max_freq_get(void *data, u64 *val)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
*val = vlv_gpu_freq(dev_priv->mem_freq,
|
||||
dev_priv->rps.max_delay);
|
||||
else
|
||||
*val = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return 0;
|
||||
@ -1837,9 +2097,16 @@ i915_max_freq_set(void *data, u64 val)
|
||||
/*
|
||||
* Turbo will still be enabled, but won't go above the set value.
|
||||
*/
|
||||
do_div(val, GT_FREQUENCY_MULTIPLIER);
|
||||
dev_priv->rps.max_delay = val;
|
||||
gen6_set_rps(dev, val);
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
val = vlv_freq_opcode(dev_priv->mem_freq, val);
|
||||
dev_priv->rps.max_delay = val;
|
||||
gen6_set_rps(dev, val);
|
||||
} else {
|
||||
do_div(val, GT_FREQUENCY_MULTIPLIER);
|
||||
dev_priv->rps.max_delay = val;
|
||||
gen6_set_rps(dev, val);
|
||||
}
|
||||
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return 0;
|
||||
@ -1863,7 +2130,11 @@ i915_min_freq_get(void *data, u64 *val)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
*val = vlv_gpu_freq(dev_priv->mem_freq,
|
||||
dev_priv->rps.min_delay);
|
||||
else
|
||||
*val = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return 0;
|
||||
@ -1888,9 +2159,15 @@ i915_min_freq_set(void *data, u64 val)
|
||||
/*
|
||||
* Turbo will still be enabled, but won't go below the set value.
|
||||
*/
|
||||
do_div(val, GT_FREQUENCY_MULTIPLIER);
|
||||
dev_priv->rps.min_delay = val;
|
||||
gen6_set_rps(dev, val);
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
val = vlv_freq_opcode(dev_priv->mem_freq, val);
|
||||
dev_priv->rps.min_delay = val;
|
||||
valleyview_set_rps(dev, val);
|
||||
} else {
|
||||
do_div(val, GT_FREQUENCY_MULTIPLIER);
|
||||
dev_priv->rps.min_delay = val;
|
||||
gen6_set_rps(dev, val);
|
||||
}
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return 0;
|
||||
@ -2057,6 +2334,7 @@ static struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_gem_hws", i915_hws_info, 0, (void *)RCS},
|
||||
{"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS},
|
||||
{"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS},
|
||||
{"i915_gem_hws_vebox", i915_hws_info, 0, (void *)VECS},
|
||||
{"i915_rstdby_delays", i915_rstdby_delays, 0},
|
||||
{"i915_cur_delayinfo", i915_cur_delayinfo, 0},
|
||||
{"i915_delayfreq_table", i915_delayfreq_table, 0},
|
||||
@ -2066,6 +2344,7 @@ static struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_ring_freq_table", i915_ring_freq_table, 0},
|
||||
{"i915_gfxec", i915_gfxec, 0},
|
||||
{"i915_fbc_status", i915_fbc_status, 0},
|
||||
{"i915_ips_status", i915_ips_status, 0},
|
||||
{"i915_sr_status", i915_sr_status, 0},
|
||||
{"i915_opregion", i915_opregion, 0},
|
||||
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <linux/vga_switcheroo.h>
|
||||
#include <linux/slab.h>
|
||||
#include <acpi/video.h>
|
||||
#include <asm/pat.h>
|
||||
|
||||
#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS])
|
||||
|
||||
@ -956,6 +955,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_BLT:
|
||||
value = intel_ring_initialized(&dev_priv->ring[BCS]);
|
||||
break;
|
||||
case I915_PARAM_HAS_VEBOX:
|
||||
value = intel_ring_initialized(&dev_priv->ring[VECS]);
|
||||
break;
|
||||
case I915_PARAM_HAS_RELAXED_FENCING:
|
||||
value = 1;
|
||||
break;
|
||||
@ -999,8 +1001,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
value = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_DRIVER("Unknown parameter %d\n",
|
||||
param->param);
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1359,8 +1360,10 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
cleanup_gem:
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_cleanup_ringbuffer(dev);
|
||||
i915_gem_context_fini(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
i915_gem_cleanup_aliasing_ppgtt(dev);
|
||||
drm_mm_takedown(&dev_priv->mm.gtt_space);
|
||||
cleanup_irq:
|
||||
drm_irq_uninstall(dev);
|
||||
cleanup_gem_stolen:
|
||||
@ -1397,29 +1400,6 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master)
|
||||
master->driver_priv = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base,
|
||||
unsigned long size)
|
||||
{
|
||||
dev_priv->mm.gtt_mtrr = -1;
|
||||
|
||||
#if defined(CONFIG_X86_PAT)
|
||||
if (cpu_has_pat)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Set up a WC MTRR for non-PAT systems. This is more common than
|
||||
* one would think, because the kernel disables PAT on first
|
||||
* generation Core chips because WC PAT gets overridden by a UC
|
||||
* MTRR if present. Even if a UC MTRR isn't present.
|
||||
*/
|
||||
dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1);
|
||||
if (dev_priv->mm.gtt_mtrr < 0) {
|
||||
DRM_INFO("MTRR allocation failed. Graphics "
|
||||
"performance may suffer.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct apertures_struct *ap;
|
||||
@ -1431,7 +1411,7 @@ static void i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
|
||||
return;
|
||||
|
||||
ap->ranges[0].base = dev_priv->gtt.mappable_base;
|
||||
ap->ranges[0].size = dev_priv->gtt.mappable_end - dev_priv->gtt.start;
|
||||
ap->ranges[0].size = dev_priv->gtt.mappable_end;
|
||||
|
||||
primary =
|
||||
pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
|
||||
@ -1445,15 +1425,19 @@ static void i915_dump_device_info(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
const struct intel_device_info *info = dev_priv->info;
|
||||
|
||||
#define DEV_INFO_FLAG(name) info->name ? #name "," : ""
|
||||
#define DEV_INFO_SEP ,
|
||||
#define PRINT_S(name) "%s"
|
||||
#define SEP_EMPTY
|
||||
#define PRINT_FLAG(name) info->name ? #name "," : ""
|
||||
#define SEP_COMMA ,
|
||||
DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x flags="
|
||||
"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
|
||||
DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY),
|
||||
info->gen,
|
||||
dev_priv->dev->pdev->device,
|
||||
DEV_INFO_FLAGS);
|
||||
#undef DEV_INFO_FLAG
|
||||
#undef DEV_INFO_SEP
|
||||
DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA));
|
||||
#undef PRINT_S
|
||||
#undef SEP_EMPTY
|
||||
#undef PRINT_FLAG
|
||||
#undef SEP_COMMA
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1468,7 +1452,7 @@ static void intel_early_sanitize_regs(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (IS_HASWELL(dev))
|
||||
if (HAS_FPGA_DBG_UNCLAIMED(dev))
|
||||
I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
|
||||
}
|
||||
|
||||
@ -1574,8 +1558,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
goto out_rmmap;
|
||||
}
|
||||
|
||||
i915_mtrr_setup(dev_priv, dev_priv->gtt.mappable_base,
|
||||
aperture_size);
|
||||
dev_priv->mm.gtt_mtrr = arch_phys_wc_add(dev_priv->gtt.mappable_base,
|
||||
aperture_size);
|
||||
|
||||
/* The i915 workqueue is primarily used for batched retirement of
|
||||
* requests (and thus managing bo) once the task has been completed
|
||||
@ -1629,6 +1613,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
spin_lock_init(&dev_priv->irq_lock);
|
||||
spin_lock_init(&dev_priv->gpu_error.lock);
|
||||
spin_lock_init(&dev_priv->rps.lock);
|
||||
spin_lock_init(&dev_priv->backlight.lock);
|
||||
mutex_init(&dev_priv->dpio_lock);
|
||||
|
||||
mutex_init(&dev_priv->rps.hw_lock);
|
||||
@ -1647,6 +1632,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
/* Start out suspended */
|
||||
dev_priv->mm.suspended = 1;
|
||||
|
||||
if (HAS_POWER_WELL(dev))
|
||||
i915_init_power_well(dev);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
ret = i915_load_modeset_init(dev);
|
||||
if (ret < 0) {
|
||||
@ -1679,12 +1667,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
intel_teardown_mchbar(dev);
|
||||
destroy_workqueue(dev_priv->wq);
|
||||
out_mtrrfree:
|
||||
if (dev_priv->mm.gtt_mtrr >= 0) {
|
||||
mtrr_del(dev_priv->mm.gtt_mtrr,
|
||||
dev_priv->gtt.mappable_base,
|
||||
aperture_size);
|
||||
dev_priv->mm.gtt_mtrr = -1;
|
||||
}
|
||||
arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
|
||||
io_mapping_free(dev_priv->gtt.mappable);
|
||||
dev_priv->gtt.gtt_remove(dev);
|
||||
out_rmmap:
|
||||
@ -1703,6 +1686,9 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
|
||||
intel_gpu_ips_teardown();
|
||||
|
||||
if (HAS_POWER_WELL(dev))
|
||||
i915_remove_power_well(dev);
|
||||
|
||||
i915_teardown_sysfs(dev);
|
||||
|
||||
if (dev_priv->mm.inactive_shrinker.shrink)
|
||||
@ -1719,12 +1705,7 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
cancel_delayed_work_sync(&dev_priv->mm.retire_work);
|
||||
|
||||
io_mapping_free(dev_priv->gtt.mappable);
|
||||
if (dev_priv->mm.gtt_mtrr >= 0) {
|
||||
mtrr_del(dev_priv->mm.gtt_mtrr,
|
||||
dev_priv->gtt.mappable_base,
|
||||
dev_priv->gtt.mappable_end);
|
||||
dev_priv->mm.gtt_mtrr = -1;
|
||||
}
|
||||
arch_phys_wc_del(dev_priv->mm.gtt_mtrr);
|
||||
|
||||
acpi_video_unregister();
|
||||
|
||||
@ -1737,10 +1718,10 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
* free the memory space allocated for the child device
|
||||
* config parsed from VBT
|
||||
*/
|
||||
if (dev_priv->child_dev && dev_priv->child_dev_num) {
|
||||
kfree(dev_priv->child_dev);
|
||||
dev_priv->child_dev = NULL;
|
||||
dev_priv->child_dev_num = 0;
|
||||
if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) {
|
||||
kfree(dev_priv->vbt.child_dev);
|
||||
dev_priv->vbt.child_dev = NULL;
|
||||
dev_priv->vbt.child_dev_num = 0;
|
||||
}
|
||||
|
||||
vga_switcheroo_unregister_client(dev->pdev);
|
||||
@ -1773,6 +1754,7 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
i915_free_hws(dev);
|
||||
}
|
||||
|
||||
drm_mm_takedown(&dev_priv->mm.gtt_space);
|
||||
if (dev_priv->regs != NULL)
|
||||
pci_iounmap(dev->pdev, dev_priv->regs);
|
||||
|
||||
@ -1782,6 +1764,8 @@ int i915_driver_unload(struct drm_device *dev)
|
||||
destroy_workqueue(dev_priv->wq);
|
||||
pm_qos_remove_request(&dev_priv->pm_qos);
|
||||
|
||||
dev_priv->gtt.gtt_remove(dev);
|
||||
|
||||
if (dev_priv->slab)
|
||||
kmem_cache_destroy(dev_priv->slab);
|
||||
|
||||
@ -1796,7 +1780,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)
|
||||
struct drm_i915_file_private *file_priv;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
|
||||
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
|
||||
if (!file_priv)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -128,6 +128,10 @@ module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
|
||||
MODULE_PARM_DESC(disable_power_well,
|
||||
"Disable the power well when possible (default: false)");
|
||||
|
||||
int i915_enable_ips __read_mostly = 1;
|
||||
module_param_named(enable_ips, i915_enable_ips, int, 0600);
|
||||
MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)");
|
||||
|
||||
static struct drm_driver driver;
|
||||
extern int intel_agp_enabled;
|
||||
|
||||
@ -280,6 +284,7 @@ static const struct intel_device_info intel_ivybridge_m_info = {
|
||||
GEN7_FEATURES,
|
||||
.is_ivybridge = 1,
|
||||
.is_mobile = 1,
|
||||
.has_fbc = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_ivybridge_q_info = {
|
||||
@ -308,12 +313,19 @@ static const struct intel_device_info intel_valleyview_d_info = {
|
||||
static const struct intel_device_info intel_haswell_d_info = {
|
||||
GEN7_FEATURES,
|
||||
.is_haswell = 1,
|
||||
.has_ddi = 1,
|
||||
.has_fpga_dbg = 1,
|
||||
.has_vebox_ring = 1,
|
||||
};
|
||||
|
||||
static const struct intel_device_info intel_haswell_m_info = {
|
||||
GEN7_FEATURES,
|
||||
.is_haswell = 1,
|
||||
.is_mobile = 1,
|
||||
.has_ddi = 1,
|
||||
.has_fpga_dbg = 1,
|
||||
.has_fbc = 1,
|
||||
.has_vebox_ring = 1,
|
||||
};
|
||||
|
||||
static const struct pci_device_id pciidlist[] = { /* aka */
|
||||
@ -445,7 +457,6 @@ void intel_detect_pch(struct drm_device *dev)
|
||||
*/
|
||||
if (INTEL_INFO(dev)->num_pipes == 0) {
|
||||
dev_priv->pch_type = PCH_NOP;
|
||||
dev_priv->num_pch_pll = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -454,9 +465,15 @@ void intel_detect_pch(struct drm_device *dev)
|
||||
* make graphics device passthrough work easy for VMM, that only
|
||||
* need to expose ISA bridge to let driver know the real hardware
|
||||
* underneath. This is a requirement from virtualization team.
|
||||
*
|
||||
* In some virtualized environments (e.g. XEN), there is irrelevant
|
||||
* ISA bridge in the system. To work reliably, we should scan trhough
|
||||
* all the ISA bridge devices and check for the first match, instead
|
||||
* of only checking the first one.
|
||||
*/
|
||||
pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
|
||||
if (pch) {
|
||||
while (pch) {
|
||||
struct pci_dev *curr = pch;
|
||||
if (pch->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
unsigned short id;
|
||||
id = pch->device & INTEL_PCH_DEVICE_ID_MASK;
|
||||
@ -464,37 +481,39 @@ void intel_detect_pch(struct drm_device *dev)
|
||||
|
||||
if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_IBX;
|
||||
dev_priv->num_pch_pll = 2;
|
||||
DRM_DEBUG_KMS("Found Ibex Peak PCH\n");
|
||||
WARN_ON(!IS_GEN5(dev));
|
||||
} else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_CPT;
|
||||
dev_priv->num_pch_pll = 2;
|
||||
DRM_DEBUG_KMS("Found CougarPoint PCH\n");
|
||||
WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
|
||||
} else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) {
|
||||
/* PantherPoint is CPT compatible */
|
||||
dev_priv->pch_type = PCH_CPT;
|
||||
dev_priv->num_pch_pll = 2;
|
||||
DRM_DEBUG_KMS("Found PatherPoint PCH\n");
|
||||
WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev)));
|
||||
} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_LPT;
|
||||
dev_priv->num_pch_pll = 0;
|
||||
DRM_DEBUG_KMS("Found LynxPoint PCH\n");
|
||||
WARN_ON(!IS_HASWELL(dev));
|
||||
WARN_ON(IS_ULT(dev));
|
||||
} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {
|
||||
dev_priv->pch_type = PCH_LPT;
|
||||
dev_priv->num_pch_pll = 0;
|
||||
DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");
|
||||
WARN_ON(!IS_HASWELL(dev));
|
||||
WARN_ON(!IS_ULT(dev));
|
||||
} else {
|
||||
goto check_next;
|
||||
}
|
||||
BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);
|
||||
pci_dev_put(pch);
|
||||
break;
|
||||
}
|
||||
pci_dev_put(pch);
|
||||
check_next:
|
||||
pch = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, curr);
|
||||
pci_dev_put(curr);
|
||||
}
|
||||
if (!pch)
|
||||
DRM_DEBUG_KMS("No PCH found?\n");
|
||||
}
|
||||
|
||||
bool i915_semaphore_is_enabled(struct drm_device *dev)
|
||||
@ -549,6 +568,8 @@ static int i915_drm_freeze(struct drm_device *dev)
|
||||
*/
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
dev_priv->display.crtc_disable(crtc);
|
||||
|
||||
intel_modeset_suspend_hw(dev);
|
||||
}
|
||||
|
||||
i915_save_state(dev);
|
||||
@ -556,7 +577,7 @@ static int i915_drm_freeze(struct drm_device *dev)
|
||||
intel_opregion_fini(dev);
|
||||
|
||||
console_lock();
|
||||
intel_fbdev_set_suspend(dev, 1);
|
||||
intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED);
|
||||
console_unlock();
|
||||
|
||||
return 0;
|
||||
@ -600,7 +621,7 @@ void intel_console_resume(struct work_struct *work)
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
|
||||
console_lock();
|
||||
intel_fbdev_set_suspend(dev, 0);
|
||||
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
@ -669,7 +690,7 @@ static int __i915_drm_thaw(struct drm_device *dev)
|
||||
* path of resume if possible.
|
||||
*/
|
||||
if (console_trylock()) {
|
||||
intel_fbdev_set_suspend(dev, 0);
|
||||
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING);
|
||||
console_unlock();
|
||||
} else {
|
||||
schedule_work(&dev_priv->console_resume_work);
|
||||
@ -855,37 +876,14 @@ static int gen6_do_reset(struct drm_device *dev)
|
||||
|
||||
int intel_gpu_reset(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret = -ENODEV;
|
||||
|
||||
switch (INTEL_INFO(dev)->gen) {
|
||||
case 7:
|
||||
case 6:
|
||||
ret = gen6_do_reset(dev);
|
||||
break;
|
||||
case 5:
|
||||
ret = ironlake_do_reset(dev);
|
||||
break;
|
||||
case 4:
|
||||
ret = i965_do_reset(dev);
|
||||
break;
|
||||
case 2:
|
||||
ret = i8xx_do_reset(dev);
|
||||
break;
|
||||
case 6: return gen6_do_reset(dev);
|
||||
case 5: return ironlake_do_reset(dev);
|
||||
case 4: return i965_do_reset(dev);
|
||||
case 2: return i8xx_do_reset(dev);
|
||||
default: return -ENODEV;
|
||||
}
|
||||
|
||||
/* Also reset the gpu hangman. */
|
||||
if (dev_priv->gpu_error.stop_rings) {
|
||||
DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
|
||||
dev_priv->gpu_error.stop_rings = 0;
|
||||
if (ret == -ENODEV) {
|
||||
DRM_ERROR("Reset not implemented, but ignoring "
|
||||
"error for simulated gpu hangs\n");
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -906,6 +904,7 @@ int intel_gpu_reset(struct drm_device *dev)
|
||||
int i915_reset(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
bool simulated;
|
||||
int ret;
|
||||
|
||||
if (!i915_try_reset)
|
||||
@ -915,13 +914,26 @@ int i915_reset(struct drm_device *dev)
|
||||
|
||||
i915_gem_reset(dev);
|
||||
|
||||
ret = -ENODEV;
|
||||
if (get_seconds() - dev_priv->gpu_error.last_reset < 5)
|
||||
simulated = dev_priv->gpu_error.stop_rings != 0;
|
||||
|
||||
if (!simulated && get_seconds() - dev_priv->gpu_error.last_reset < 5) {
|
||||
DRM_ERROR("GPU hanging too fast, declaring wedged!\n");
|
||||
else
|
||||
ret = -ENODEV;
|
||||
} else {
|
||||
ret = intel_gpu_reset(dev);
|
||||
|
||||
dev_priv->gpu_error.last_reset = get_seconds();
|
||||
/* Also reset the gpu hangman. */
|
||||
if (simulated) {
|
||||
DRM_INFO("Simulated gpu hang, resetting stop_rings\n");
|
||||
dev_priv->gpu_error.stop_rings = 0;
|
||||
if (ret == -ENODEV) {
|
||||
DRM_ERROR("Reset not implemented, but ignoring "
|
||||
"error for simulated gpu hangs\n");
|
||||
ret = 0;
|
||||
}
|
||||
} else
|
||||
dev_priv->gpu_error.last_reset = get_seconds();
|
||||
}
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to reset chip.\n");
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@ -984,12 +996,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
struct intel_device_info *intel_info =
|
||||
(struct intel_device_info *) ent->driver_data;
|
||||
|
||||
if (intel_info->is_valleyview)
|
||||
if(!i915_preliminary_hw_support) {
|
||||
DRM_ERROR("Preliminary hardware support disabled\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Only bind to function 0 of the device. Early generations
|
||||
* used function 1 as a placeholder for multi-head. This causes
|
||||
* us confusion instead, especially on the systems where both
|
||||
@ -1218,16 +1224,16 @@ MODULE_LICENSE("GPL and additional rights");
|
||||
static void
|
||||
ilk_dummy_write(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
/* WaIssueDummyWriteToWakeupFromRC6: Issue a dummy write to wake up the
|
||||
* chip from rc6 before touching it for real. MI_MODE is masked, hence
|
||||
* harmless to write 0 into. */
|
||||
/* WaIssueDummyWriteToWakeupFromRC6:ilk Issue a dummy write to wake up
|
||||
* the chip from rc6 before touching it for real. MI_MODE is masked,
|
||||
* hence harmless to write 0 into. */
|
||||
I915_WRITE_NOTRACE(MI_MODE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
|
||||
{
|
||||
if (IS_HASWELL(dev_priv->dev) &&
|
||||
if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
|
||||
(I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
|
||||
DRM_ERROR("Unknown unclaimed register before writing to %x\n",
|
||||
reg);
|
||||
@ -1238,7 +1244,7 @@ hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
|
||||
static void
|
||||
hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
|
||||
{
|
||||
if (IS_HASWELL(dev_priv->dev) &&
|
||||
if (HAS_FPGA_DBG_UNCLAIMED(dev_priv->dev) &&
|
||||
(I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) {
|
||||
DRM_ERROR("Unclaimed write to %x\n", reg);
|
||||
I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
|
||||
|
@ -76,6 +76,8 @@ enum plane {
|
||||
};
|
||||
#define plane_name(p) ((p) + 'A')
|
||||
|
||||
#define sprite_name(p, s) ((p) * dev_priv->num_plane + (s) + 'A')
|
||||
|
||||
enum port {
|
||||
PORT_A = 0,
|
||||
PORT_B,
|
||||
@ -86,6 +88,24 @@ enum port {
|
||||
};
|
||||
#define port_name(p) ((p) + 'A')
|
||||
|
||||
enum intel_display_power_domain {
|
||||
POWER_DOMAIN_PIPE_A,
|
||||
POWER_DOMAIN_PIPE_B,
|
||||
POWER_DOMAIN_PIPE_C,
|
||||
POWER_DOMAIN_PIPE_A_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_B_PANEL_FITTER,
|
||||
POWER_DOMAIN_PIPE_C_PANEL_FITTER,
|
||||
POWER_DOMAIN_TRANSCODER_A,
|
||||
POWER_DOMAIN_TRANSCODER_B,
|
||||
POWER_DOMAIN_TRANSCODER_C,
|
||||
POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF,
|
||||
};
|
||||
|
||||
#define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A)
|
||||
#define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \
|
||||
((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER)
|
||||
#define POWER_DOMAIN_TRANSCODER(tran) ((tran) + POWER_DOMAIN_TRANSCODER_A)
|
||||
|
||||
enum hpd_pin {
|
||||
HPD_NONE = 0,
|
||||
HPD_PORT_A = HPD_NONE, /* PORT_A is internal */
|
||||
@ -112,15 +132,38 @@ enum hpd_pin {
|
||||
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
|
||||
if ((intel_encoder)->base.crtc == (__crtc))
|
||||
|
||||
struct intel_pch_pll {
|
||||
struct drm_i915_private;
|
||||
|
||||
enum intel_dpll_id {
|
||||
DPLL_ID_PRIVATE = -1, /* non-shared dpll in use */
|
||||
/* real shared dpll ids must be >= 0 */
|
||||
DPLL_ID_PCH_PLL_A,
|
||||
DPLL_ID_PCH_PLL_B,
|
||||
};
|
||||
#define I915_NUM_PLLS 2
|
||||
|
||||
struct intel_dpll_hw_state {
|
||||
uint32_t dpll;
|
||||
uint32_t fp0;
|
||||
uint32_t fp1;
|
||||
};
|
||||
|
||||
struct intel_shared_dpll {
|
||||
int refcount; /* count of number of CRTCs sharing this PLL */
|
||||
int active; /* count of number of active CRTCs (i.e. DPMS on) */
|
||||
bool on; /* is the PLL actually active? Disabled during modeset */
|
||||
int pll_reg;
|
||||
int fp0_reg;
|
||||
int fp1_reg;
|
||||
const char *name;
|
||||
/* should match the index in the dev_priv->shared_dplls array */
|
||||
enum intel_dpll_id id;
|
||||
struct intel_dpll_hw_state hw_state;
|
||||
void (*enable)(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll);
|
||||
void (*disable)(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll);
|
||||
bool (*get_hw_state)(struct drm_i915_private *dev_priv,
|
||||
struct intel_shared_dpll *pll,
|
||||
struct intel_dpll_hw_state *hw_state);
|
||||
};
|
||||
#define I915_NUM_PLLS 2
|
||||
|
||||
/* Used by dp and fdi links */
|
||||
struct intel_link_m_n {
|
||||
@ -175,7 +218,6 @@ struct opregion_header;
|
||||
struct opregion_acpi;
|
||||
struct opregion_swsci;
|
||||
struct opregion_asle;
|
||||
struct drm_i915_private;
|
||||
|
||||
struct intel_opregion {
|
||||
struct opregion_header __iomem *header;
|
||||
@ -286,6 +328,8 @@ struct drm_i915_error_state {
|
||||
|
||||
struct intel_crtc_config;
|
||||
struct intel_crtc;
|
||||
struct intel_limit;
|
||||
struct dpll;
|
||||
|
||||
struct drm_i915_display_funcs {
|
||||
bool (*fbc_enabled)(struct drm_device *dev);
|
||||
@ -293,11 +337,28 @@ struct drm_i915_display_funcs {
|
||||
void (*disable_fbc)(struct drm_device *dev);
|
||||
int (*get_display_clock_speed)(struct drm_device *dev);
|
||||
int (*get_fifo_size)(struct drm_device *dev, int plane);
|
||||
/**
|
||||
* find_dpll() - Find the best values for the PLL
|
||||
* @limit: limits for the PLL
|
||||
* @crtc: current CRTC
|
||||
* @target: target frequency in kHz
|
||||
* @refclk: reference clock frequency in kHz
|
||||
* @match_clock: if provided, @best_clock P divider must
|
||||
* match the P divider from @match_clock
|
||||
* used for LVDS downclocking
|
||||
* @best_clock: best PLL values found
|
||||
*
|
||||
* Returns true on success, false on failure.
|
||||
*/
|
||||
bool (*find_dpll)(const struct intel_limit *limit,
|
||||
struct drm_crtc *crtc,
|
||||
int target, int refclk,
|
||||
struct dpll *match_clock,
|
||||
struct dpll *best_clock);
|
||||
void (*update_wm)(struct drm_device *dev);
|
||||
void (*update_sprite_wm)(struct drm_device *dev, int pipe,
|
||||
uint32_t sprite_width, int pixel_size);
|
||||
void (*update_linetime_wm)(struct drm_device *dev, int pipe,
|
||||
struct drm_display_mode *mode);
|
||||
uint32_t sprite_width, int pixel_size,
|
||||
bool enable);
|
||||
void (*modeset_global_resources)(struct drm_device *dev);
|
||||
/* Returns the active state of the crtc, and if the crtc is active,
|
||||
* fills out the pipe-config with the hw state. */
|
||||
@ -331,68 +392,56 @@ struct drm_i915_gt_funcs {
|
||||
void (*force_wake_put)(struct drm_i915_private *dev_priv);
|
||||
};
|
||||
|
||||
#define DEV_INFO_FLAGS \
|
||||
DEV_INFO_FLAG(is_mobile) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_i85x) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_i915g) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_i945gm) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_g33) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(need_gfx_hws) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_g4x) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_pineview) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_broadwater) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_crestline) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_ivybridge) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_valleyview) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(is_haswell) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_force_wake) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_fbc) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_pipe_cxsr) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_hotplug) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(cursor_needs_physical) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_overlay) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(overlay_needs_physical) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(supports_tv) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_bsd_ring) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_blt_ring) DEV_INFO_SEP \
|
||||
DEV_INFO_FLAG(has_llc)
|
||||
#define DEV_INFO_FOR_EACH_FLAG(func, sep) \
|
||||
func(is_mobile) sep \
|
||||
func(is_i85x) sep \
|
||||
func(is_i915g) sep \
|
||||
func(is_i945gm) sep \
|
||||
func(is_g33) sep \
|
||||
func(need_gfx_hws) sep \
|
||||
func(is_g4x) sep \
|
||||
func(is_pineview) sep \
|
||||
func(is_broadwater) sep \
|
||||
func(is_crestline) sep \
|
||||
func(is_ivybridge) sep \
|
||||
func(is_valleyview) sep \
|
||||
func(is_haswell) sep \
|
||||
func(has_force_wake) sep \
|
||||
func(has_fbc) sep \
|
||||
func(has_pipe_cxsr) sep \
|
||||
func(has_hotplug) sep \
|
||||
func(cursor_needs_physical) sep \
|
||||
func(has_overlay) sep \
|
||||
func(overlay_needs_physical) sep \
|
||||
func(supports_tv) sep \
|
||||
func(has_bsd_ring) sep \
|
||||
func(has_blt_ring) sep \
|
||||
func(has_vebox_ring) sep \
|
||||
func(has_llc) sep \
|
||||
func(has_ddi) sep \
|
||||
func(has_fpga_dbg)
|
||||
|
||||
#define DEFINE_FLAG(name) u8 name:1
|
||||
#define SEP_SEMICOLON ;
|
||||
|
||||
struct intel_device_info {
|
||||
u32 display_mmio_offset;
|
||||
u8 num_pipes:3;
|
||||
u8 gen;
|
||||
u8 is_mobile:1;
|
||||
u8 is_i85x:1;
|
||||
u8 is_i915g:1;
|
||||
u8 is_i945gm:1;
|
||||
u8 is_g33:1;
|
||||
u8 need_gfx_hws:1;
|
||||
u8 is_g4x:1;
|
||||
u8 is_pineview:1;
|
||||
u8 is_broadwater:1;
|
||||
u8 is_crestline:1;
|
||||
u8 is_ivybridge:1;
|
||||
u8 is_valleyview:1;
|
||||
u8 has_force_wake:1;
|
||||
u8 is_haswell:1;
|
||||
u8 has_fbc:1;
|
||||
u8 has_pipe_cxsr:1;
|
||||
u8 has_hotplug:1;
|
||||
u8 cursor_needs_physical:1;
|
||||
u8 has_overlay:1;
|
||||
u8 overlay_needs_physical:1;
|
||||
u8 supports_tv:1;
|
||||
u8 has_bsd_ring:1;
|
||||
u8 has_blt_ring:1;
|
||||
u8 has_llc:1;
|
||||
DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON);
|
||||
};
|
||||
|
||||
#undef DEFINE_FLAG
|
||||
#undef SEP_SEMICOLON
|
||||
|
||||
enum i915_cache_level {
|
||||
I915_CACHE_NONE = 0,
|
||||
I915_CACHE_LLC,
|
||||
I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */
|
||||
};
|
||||
|
||||
typedef uint32_t gen6_gtt_pte_t;
|
||||
|
||||
/* The Graphics Translation Table is the way in which GEN hardware translates a
|
||||
* Graphics Virtual Address into a Physical Address. In addition to the normal
|
||||
* collateral associated with any va->pa translations GEN hardware also has a
|
||||
@ -428,6 +477,9 @@ struct i915_gtt {
|
||||
struct sg_table *st,
|
||||
unsigned int pg_start,
|
||||
enum i915_cache_level cache_level);
|
||||
gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level);
|
||||
};
|
||||
#define gtt_total_entries(gtt) ((gtt).total >> PAGE_SHIFT)
|
||||
|
||||
@ -449,19 +501,31 @@ struct i915_hw_ppgtt {
|
||||
struct sg_table *st,
|
||||
unsigned int pg_start,
|
||||
enum i915_cache_level cache_level);
|
||||
gen6_gtt_pte_t (*pte_encode)(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level);
|
||||
int (*enable)(struct drm_device *dev);
|
||||
void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
|
||||
};
|
||||
|
||||
struct i915_ctx_hang_stats {
|
||||
/* This context had batch pending when hang was declared */
|
||||
unsigned batch_pending;
|
||||
|
||||
/* This context had batch active when hang was declared */
|
||||
unsigned batch_active;
|
||||
};
|
||||
|
||||
/* This must match up with the value previously used for execbuf2.rsvd1. */
|
||||
#define DEFAULT_CONTEXT_ID 0
|
||||
struct i915_hw_context {
|
||||
struct kref ref;
|
||||
int id;
|
||||
bool is_initialized;
|
||||
struct drm_i915_file_private *file_priv;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_ctx_hang_stats hang_stats;
|
||||
};
|
||||
|
||||
enum no_fbc_reason {
|
||||
@ -658,6 +722,7 @@ struct i915_suspend_saved_registers {
|
||||
|
||||
struct intel_gen6_power_mgmt {
|
||||
struct work_struct work;
|
||||
struct delayed_work vlv_work;
|
||||
u32 pm_iir;
|
||||
/* lock - irqsave spinlock that protectects the work_struct and
|
||||
* pm_iir. */
|
||||
@ -668,6 +733,7 @@ struct intel_gen6_power_mgmt {
|
||||
u8 cur_delay;
|
||||
u8 min_delay;
|
||||
u8 max_delay;
|
||||
u8 rpe_delay;
|
||||
u8 hw_max;
|
||||
|
||||
struct delayed_work delayed_resume_work;
|
||||
@ -704,6 +770,15 @@ struct intel_ilk_power_mgmt {
|
||||
struct drm_i915_gem_object *renderctx;
|
||||
};
|
||||
|
||||
/* Power well structure for haswell */
|
||||
struct i915_power_well {
|
||||
struct drm_device *device;
|
||||
spinlock_t lock;
|
||||
/* power well enable/disable usage count */
|
||||
int count;
|
||||
int i915_request;
|
||||
};
|
||||
|
||||
struct i915_dri1_state {
|
||||
unsigned allow_batchbuffer : 1;
|
||||
u32 __iomem *gfx_hws_cpu_addr;
|
||||
@ -812,14 +887,20 @@ struct i915_gem_mm {
|
||||
u32 object_count;
|
||||
};
|
||||
|
||||
struct drm_i915_error_state_buf {
|
||||
unsigned bytes;
|
||||
unsigned size;
|
||||
int err;
|
||||
u8 *buf;
|
||||
loff_t start;
|
||||
loff_t pos;
|
||||
};
|
||||
|
||||
struct i915_gpu_error {
|
||||
/* For hangcheck timer */
|
||||
#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */
|
||||
#define DRM_I915_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)
|
||||
struct timer_list hangcheck_timer;
|
||||
int hangcheck_count;
|
||||
uint32_t last_acthd[I915_NUM_RINGS];
|
||||
uint32_t prev_instdone[I915_NUM_INSTDONE_REG];
|
||||
|
||||
/* For reset and error_state handling. */
|
||||
spinlock_t lock;
|
||||
@ -875,6 +956,37 @@ enum modeset_restore {
|
||||
MODESET_SUSPENDED,
|
||||
};
|
||||
|
||||
struct intel_vbt_data {
|
||||
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
|
||||
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
|
||||
|
||||
/* Feature bits */
|
||||
unsigned int int_tv_support:1;
|
||||
unsigned int lvds_dither:1;
|
||||
unsigned int lvds_vbt:1;
|
||||
unsigned int int_crt_support:1;
|
||||
unsigned int lvds_use_ssc:1;
|
||||
unsigned int display_clock_mode:1;
|
||||
unsigned int fdi_rx_polarity_inverted:1;
|
||||
int lvds_ssc_freq;
|
||||
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
|
||||
|
||||
/* eDP */
|
||||
int edp_rate;
|
||||
int edp_lanes;
|
||||
int edp_preemphasis;
|
||||
int edp_vswing;
|
||||
bool edp_initialized;
|
||||
bool edp_support;
|
||||
int edp_bpp;
|
||||
struct edp_power_seq edp_pps;
|
||||
|
||||
int crt_ddc_pin;
|
||||
|
||||
int child_dev_num;
|
||||
struct child_device_config *child_dev;
|
||||
};
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
struct drm_device *dev;
|
||||
struct kmem_cache *slab;
|
||||
@ -941,9 +1053,9 @@ typedef struct drm_i915_private {
|
||||
HPD_MARK_DISABLED = 2
|
||||
} hpd_mark;
|
||||
} hpd_stats[HPD_NUM_PINS];
|
||||
u32 hpd_event_bits;
|
||||
struct timer_list hotplug_reenable_timer;
|
||||
|
||||
int num_pch_pll;
|
||||
int num_plane;
|
||||
|
||||
unsigned long cfb_size;
|
||||
@ -953,6 +1065,7 @@ typedef struct drm_i915_private {
|
||||
struct intel_fbc_work *fbc_work;
|
||||
|
||||
struct intel_opregion opregion;
|
||||
struct intel_vbt_data vbt;
|
||||
|
||||
/* overlay */
|
||||
struct intel_overlay *overlay;
|
||||
@ -962,37 +1075,15 @@ typedef struct drm_i915_private {
|
||||
struct {
|
||||
int level;
|
||||
bool enabled;
|
||||
spinlock_t lock; /* bl registers and the above bl fields */
|
||||
struct backlight_device *device;
|
||||
} backlight;
|
||||
|
||||
/* LVDS info */
|
||||
struct drm_display_mode *lfp_lvds_vbt_mode; /* if any */
|
||||
struct drm_display_mode *sdvo_lvds_vbt_mode; /* if any */
|
||||
|
||||
/* Feature bits from the VBIOS */
|
||||
unsigned int int_tv_support:1;
|
||||
unsigned int lvds_dither:1;
|
||||
unsigned int lvds_vbt:1;
|
||||
unsigned int int_crt_support:1;
|
||||
unsigned int lvds_use_ssc:1;
|
||||
unsigned int display_clock_mode:1;
|
||||
unsigned int fdi_rx_polarity_inverted:1;
|
||||
int lvds_ssc_freq;
|
||||
unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */
|
||||
struct {
|
||||
int rate;
|
||||
int lanes;
|
||||
int preemphasis;
|
||||
int vswing;
|
||||
|
||||
bool initialized;
|
||||
bool support;
|
||||
int bpp;
|
||||
struct edp_power_seq pps;
|
||||
} edp;
|
||||
bool no_aux_handshake;
|
||||
|
||||
int crt_ddc_pin;
|
||||
struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
|
||||
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
|
||||
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
|
||||
@ -1020,16 +1111,13 @@ typedef struct drm_i915_private {
|
||||
/* Kernel Modesetting */
|
||||
|
||||
struct sdvo_device_mapping sdvo_mappings[2];
|
||||
/* indicate whether the LVDS_BORDER should be enabled or not */
|
||||
unsigned int lvds_border_bits;
|
||||
/* Panel fitter placement and size for Ironlake+ */
|
||||
u32 pch_pf_pos, pch_pf_size;
|
||||
|
||||
struct drm_crtc *plane_to_crtc_mapping[3];
|
||||
struct drm_crtc *pipe_to_crtc_mapping[3];
|
||||
wait_queue_head_t pending_flip_queue;
|
||||
|
||||
struct intel_pch_pll pch_plls[I915_NUM_PLLS];
|
||||
int num_shared_dpll;
|
||||
struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
|
||||
struct intel_ddi_plls ddi_plls;
|
||||
|
||||
/* Reclocking support */
|
||||
@ -1038,8 +1126,6 @@ typedef struct drm_i915_private {
|
||||
/* indicates the reduced downclock for LVDS*/
|
||||
int lvds_downclock;
|
||||
u16 orig_clock;
|
||||
int child_dev_num;
|
||||
struct child_device_config *child_dev;
|
||||
|
||||
bool mchbar_need_disable;
|
||||
|
||||
@ -1052,6 +1138,9 @@ typedef struct drm_i915_private {
|
||||
* mchdev_lock in intel_pm.c */
|
||||
struct intel_ilk_power_mgmt ips;
|
||||
|
||||
/* Haswell power well */
|
||||
struct i915_power_well power_well;
|
||||
|
||||
enum no_fbc_reason no_fbc_reason;
|
||||
|
||||
struct drm_mm_node *compressed_fb;
|
||||
@ -1059,6 +1148,8 @@ typedef struct drm_i915_private {
|
||||
|
||||
struct i915_gpu_error gpu_error;
|
||||
|
||||
struct drm_i915_gem_object *vlv_pctx;
|
||||
|
||||
/* list of fbdev register on this device */
|
||||
struct intel_fbdev *fbdev;
|
||||
|
||||
@ -1124,7 +1215,7 @@ struct drm_i915_gem_object {
|
||||
struct drm_mm_node *gtt_space;
|
||||
/** Stolen memory for this object, instead of being backed by shmem. */
|
||||
struct drm_mm_node *stolen;
|
||||
struct list_head gtt_list;
|
||||
struct list_head global_list;
|
||||
|
||||
/** This object's place on the active/inactive lists */
|
||||
struct list_head ring_list;
|
||||
@ -1271,9 +1362,18 @@ struct drm_i915_gem_request {
|
||||
/** GEM sequence number associated with this request. */
|
||||
uint32_t seqno;
|
||||
|
||||
/** Postion in the ringbuffer of the end of the request */
|
||||
/** Position in the ringbuffer of the start of the request */
|
||||
u32 head;
|
||||
|
||||
/** Position in the ringbuffer of the end of the request */
|
||||
u32 tail;
|
||||
|
||||
/** Context related to this request */
|
||||
struct i915_hw_context *ctx;
|
||||
|
||||
/** Batch buffer related to this request if any */
|
||||
struct drm_i915_gem_object *batch_obj;
|
||||
|
||||
/** Time at which this request was emitted, in jiffies. */
|
||||
unsigned long emitted_jiffies;
|
||||
|
||||
@ -1291,6 +1391,8 @@ struct drm_i915_file_private {
|
||||
struct list_head request_list;
|
||||
} mm;
|
||||
struct idr context_idr;
|
||||
|
||||
struct i915_ctx_hang_stats hang_stats;
|
||||
};
|
||||
|
||||
#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info)
|
||||
@ -1341,6 +1443,7 @@ struct drm_i915_file_private {
|
||||
|
||||
#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring)
|
||||
#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring)
|
||||
#define HAS_VEBOX(dev) (INTEL_INFO(dev)->has_vebox_ring)
|
||||
#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc)
|
||||
#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws)
|
||||
|
||||
@ -1371,10 +1474,13 @@ struct drm_i915_file_private {
|
||||
#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)
|
||||
#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc)
|
||||
|
||||
#define HAS_IPS(dev) (IS_ULT(dev))
|
||||
|
||||
#define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)
|
||||
|
||||
#define HAS_DDI(dev) (IS_HASWELL(dev))
|
||||
#define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi)
|
||||
#define HAS_POWER_WELL(dev) (IS_HASWELL(dev))
|
||||
#define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg)
|
||||
|
||||
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
||||
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
||||
@ -1435,6 +1541,7 @@ extern bool i915_enable_hangcheck __read_mostly;
|
||||
extern int i915_enable_ppgtt __read_mostly;
|
||||
extern unsigned int i915_preliminary_hw_support __read_mostly;
|
||||
extern int i915_disable_power_well __read_mostly;
|
||||
extern int i915_enable_ips __read_mostly;
|
||||
|
||||
extern int i915_suspend(struct drm_device *dev, pm_message_t state);
|
||||
extern int i915_resume(struct drm_device *dev);
|
||||
@ -1486,8 +1593,6 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
|
||||
void
|
||||
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);
|
||||
|
||||
void intel_enable_asle(struct drm_device *dev);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern void i915_destroy_error_state(struct drm_device *dev);
|
||||
#else
|
||||
@ -1626,6 +1731,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
if (obj->fence_reg != I915_FENCE_REG_NONE) {
|
||||
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
||||
WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count <= 0);
|
||||
dev_priv->fence_regs[obj->fence_reg].pin_count--;
|
||||
}
|
||||
}
|
||||
@ -1658,9 +1764,12 @@ void i915_gem_init_swizzling(struct drm_device *dev);
|
||||
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
|
||||
int __must_check i915_gpu_idle(struct drm_device *dev);
|
||||
int __must_check i915_gem_idle(struct drm_device *dev);
|
||||
int i915_add_request(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
u32 *seqno);
|
||||
int __i915_add_request(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
struct drm_i915_gem_object *batch_obj,
|
||||
u32 *seqno);
|
||||
#define i915_add_request(ring, seqno) \
|
||||
__i915_add_request(ring, NULL, NULL, seqno)
|
||||
int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
|
||||
uint32_t seqno);
|
||||
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
|
||||
@ -1703,6 +1812,21 @@ void i915_gem_context_fini(struct drm_device *dev);
|
||||
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
|
||||
int i915_switch_context(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file, int to_id);
|
||||
void i915_gem_context_free(struct kref *ctx_ref);
|
||||
static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
|
||||
{
|
||||
kref_get(&ctx->ref);
|
||||
}
|
||||
|
||||
static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
|
||||
{
|
||||
kref_put(&ctx->ref, i915_gem_context_free);
|
||||
}
|
||||
|
||||
struct i915_ctx_hang_stats * __must_check
|
||||
i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
u32 id);
|
||||
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file);
|
||||
int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
@ -1784,6 +1908,8 @@ void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
|
||||
/* i915_debugfs.c */
|
||||
int i915_debugfs_init(struct drm_minor *minor);
|
||||
void i915_debugfs_cleanup(struct drm_minor *minor);
|
||||
__printf(2, 3)
|
||||
void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...);
|
||||
|
||||
/* i915_suspend.c */
|
||||
extern int i915_save_state(struct drm_device *dev);
|
||||
@ -1800,7 +1926,7 @@ void i915_teardown_sysfs(struct drm_device *dev_priv);
|
||||
/* intel_i2c.c */
|
||||
extern int intel_setup_gmbus(struct drm_device *dev);
|
||||
extern void intel_teardown_gmbus(struct drm_device *dev);
|
||||
extern inline bool intel_gmbus_is_port_valid(unsigned port)
|
||||
static inline bool intel_gmbus_is_port_valid(unsigned port)
|
||||
{
|
||||
return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD);
|
||||
}
|
||||
@ -1809,7 +1935,7 @@ extern struct i2c_adapter *intel_gmbus_get_adapter(
|
||||
struct drm_i915_private *dev_priv, unsigned port);
|
||||
extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);
|
||||
extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);
|
||||
extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
{
|
||||
return container_of(adapter, struct intel_gmbus, adapter)->force_bit;
|
||||
}
|
||||
@ -1821,14 +1947,10 @@ extern int intel_opregion_setup(struct drm_device *dev);
|
||||
extern void intel_opregion_init(struct drm_device *dev);
|
||||
extern void intel_opregion_fini(struct drm_device *dev);
|
||||
extern void intel_opregion_asle_intr(struct drm_device *dev);
|
||||
extern void intel_opregion_gse_intr(struct drm_device *dev);
|
||||
extern void intel_opregion_enable_asle(struct drm_device *dev);
|
||||
#else
|
||||
static inline void intel_opregion_init(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_gse_intr(struct drm_device *dev) { return; }
|
||||
static inline void intel_opregion_enable_asle(struct drm_device *dev) { return; }
|
||||
#endif
|
||||
|
||||
/* intel_acpi.c */
|
||||
@ -1842,6 +1964,7 @@ static inline void intel_unregister_dsm_handler(void) { return; }
|
||||
|
||||
/* modesetting */
|
||||
extern void intel_modeset_init_hw(struct drm_device *dev);
|
||||
extern void intel_modeset_suspend_hw(struct drm_device *dev);
|
||||
extern void intel_modeset_init(struct drm_device *dev);
|
||||
extern void intel_modeset_gem_init(struct drm_device *dev);
|
||||
extern void intel_modeset_cleanup(struct drm_device *dev);
|
||||
@ -1854,6 +1977,9 @@ extern void intel_disable_fbc(struct drm_device *dev);
|
||||
extern bool ironlake_set_drps(struct drm_device *dev, u8 val);
|
||||
extern void intel_init_pch_refclk(struct drm_device *dev);
|
||||
extern void gen6_set_rps(struct drm_device *dev, u8 val);
|
||||
extern void valleyview_set_rps(struct drm_device *dev, u8 val);
|
||||
extern int valleyview_rps_max_freq(struct drm_i915_private *dev_priv);
|
||||
extern int valleyview_rps_min_freq(struct drm_i915_private *dev_priv);
|
||||
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);
|
||||
@ -1865,10 +1991,11 @@ int i915_reg_read_ioctl(struct drm_device *dev, void *data,
|
||||
/* overlay */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev);
|
||||
extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error);
|
||||
extern void intel_overlay_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
struct intel_overlay_error_state *error);
|
||||
|
||||
extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev);
|
||||
extern void intel_display_print_error_state(struct seq_file *m,
|
||||
extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e,
|
||||
struct drm_device *dev,
|
||||
struct intel_display_error_state *error);
|
||||
#endif
|
||||
@ -1883,8 +2010,20 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv);
|
||||
|
||||
int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u8 mbox, u32 *val);
|
||||
int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u8 mbox, u32 val);
|
||||
int valleyview_punit_read(struct drm_i915_private *dev_priv, u8 addr, u32 *val);
|
||||
int valleyview_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
|
||||
|
||||
/* intel_sideband.c */
|
||||
u32 vlv_punit_read(struct drm_i915_private *dev_priv, u8 addr);
|
||||
void vlv_punit_write(struct drm_i915_private *dev_priv, u8 addr, u32 val);
|
||||
u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr);
|
||||
u32 vlv_dpio_read(struct drm_i915_private *dev_priv, int reg);
|
||||
void vlv_dpio_write(struct drm_i915_private *dev_priv, int reg, u32 val);
|
||||
u32 intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,
|
||||
enum intel_sbi_destination destination);
|
||||
void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,
|
||||
enum intel_sbi_destination destination);
|
||||
|
||||
int vlv_gpu_freq(int ddr_freq, int val);
|
||||
int vlv_freq_opcode(int ddr_freq, int val);
|
||||
|
||||
#define __i915_read(x, y) \
|
||||
u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg);
|
||||
|
@ -176,7 +176,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
|
||||
|
||||
pinned = 0;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
|
||||
if (obj->pin_count)
|
||||
pinned += obj->gtt_space->size;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@ -956,7 +956,7 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
|
||||
|
||||
ret = 0;
|
||||
if (seqno == ring->outstanding_lazy_request)
|
||||
ret = i915_add_request(ring, NULL, NULL);
|
||||
ret = i915_add_request(ring, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1087,6 +1087,25 @@ i915_wait_seqno(struct intel_ring_buffer *ring, uint32_t seqno)
|
||||
interruptible, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_object_wait_rendering__tail(struct drm_i915_gem_object *obj,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
i915_gem_retire_requests_ring(ring);
|
||||
|
||||
/* Manually manage the write flush as we may have not yet
|
||||
* retired the buffer.
|
||||
*
|
||||
* Note that the last_write_seqno is always the earlier of
|
||||
* the two (read/write) seqno, so if we haved successfully waited,
|
||||
* we know we have passed the last write.
|
||||
*/
|
||||
obj->last_write_seqno = 0;
|
||||
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that all rendering to the object has completed and the object is
|
||||
* safe to unbind from the GTT or access from the CPU.
|
||||
@ -1107,18 +1126,7 @@ i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i915_gem_retire_requests_ring(ring);
|
||||
|
||||
/* Manually manage the write flush as we may have not yet
|
||||
* retired the buffer.
|
||||
*/
|
||||
if (obj->last_write_seqno &&
|
||||
i915_seqno_passed(seqno, obj->last_write_seqno)) {
|
||||
obj->last_write_seqno = 0;
|
||||
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return i915_gem_object_wait_rendering__tail(obj, ring);
|
||||
}
|
||||
|
||||
/* A nonblocking variant of the above wait. This is a highly dangerous routine
|
||||
@ -1154,19 +1162,10 @@ i915_gem_object_wait_rendering__nonblocking(struct drm_i915_gem_object *obj,
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
ret = __wait_seqno(ring, seqno, reset_counter, true, NULL);
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
i915_gem_retire_requests_ring(ring);
|
||||
|
||||
/* Manually manage the write flush as we may have not yet
|
||||
* retired the buffer.
|
||||
*/
|
||||
if (obj->last_write_seqno &&
|
||||
i915_seqno_passed(seqno, obj->last_write_seqno)) {
|
||||
obj->last_write_seqno = 0;
|
||||
obj->base.write_domain &= ~I915_GEM_GPU_DOMAINS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return i915_gem_object_wait_rendering__tail(obj, ring);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1676,7 +1675,7 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
|
||||
/* ->put_pages might need to allocate memory for the bit17 swizzle
|
||||
* array, hence protect them from being reaped by removing them from gtt
|
||||
* lists early. */
|
||||
list_del(&obj->gtt_list);
|
||||
list_del(&obj->global_list);
|
||||
|
||||
ops->put_pages(obj);
|
||||
obj->pages = NULL;
|
||||
@ -1696,7 +1695,7 @@ __i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
|
||||
|
||||
list_for_each_entry_safe(obj, next,
|
||||
&dev_priv->mm.unbound_list,
|
||||
gtt_list) {
|
||||
global_list) {
|
||||
if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
|
||||
i915_gem_object_put_pages(obj) == 0) {
|
||||
count += obj->base.size >> PAGE_SHIFT;
|
||||
@ -1733,7 +1732,8 @@ i915_gem_shrink_all(struct drm_i915_private *dev_priv)
|
||||
|
||||
i915_gem_evict_everything(dev_priv->dev);
|
||||
|
||||
list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list, gtt_list)
|
||||
list_for_each_entry_safe(obj, next, &dev_priv->mm.unbound_list,
|
||||
global_list)
|
||||
i915_gem_object_put_pages(obj);
|
||||
}
|
||||
|
||||
@ -1801,7 +1801,14 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
|
||||
gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
|
||||
gfp &= ~(__GFP_IO | __GFP_WAIT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (swiotlb_nr_tbl()) {
|
||||
st->nents++;
|
||||
sg_set_page(sg, page, PAGE_SIZE, 0);
|
||||
sg = sg_next(sg);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!i || page_to_pfn(page) != last_pfn + 1) {
|
||||
if (i)
|
||||
sg = sg_next(sg);
|
||||
@ -1812,8 +1819,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
|
||||
}
|
||||
last_pfn = page_to_pfn(page);
|
||||
}
|
||||
|
||||
sg_mark_end(sg);
|
||||
#ifdef CONFIG_SWIOTLB
|
||||
if (!swiotlb_nr_tbl())
|
||||
#endif
|
||||
sg_mark_end(sg);
|
||||
obj->pages = st;
|
||||
|
||||
if (i915_gem_object_needs_bit17_swizzle(obj))
|
||||
@ -1858,7 +1867,7 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
list_add_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
|
||||
list_add_tail(&obj->global_list, &dev_priv->mm.unbound_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1996,17 +2005,18 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
i915_add_request(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
u32 *out_seqno)
|
||||
int __i915_add_request(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
struct drm_i915_gem_object *obj,
|
||||
u32 *out_seqno)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = ring->dev->dev_private;
|
||||
struct drm_i915_gem_request *request;
|
||||
u32 request_ring_position;
|
||||
u32 request_ring_position, request_start;
|
||||
int was_empty;
|
||||
int ret;
|
||||
|
||||
request_start = intel_ring_get_tail(ring);
|
||||
/*
|
||||
* Emit any outstanding flushes - execbuf can fail to emit the flush
|
||||
* after having emitted the batchbuffer command. Hence we need to fix
|
||||
@ -2038,7 +2048,21 @@ i915_add_request(struct intel_ring_buffer *ring,
|
||||
|
||||
request->seqno = intel_ring_get_seqno(ring);
|
||||
request->ring = ring;
|
||||
request->head = request_start;
|
||||
request->tail = request_ring_position;
|
||||
request->ctx = ring->last_context;
|
||||
request->batch_obj = obj;
|
||||
|
||||
/* Whilst this request exists, batch_obj will be on the
|
||||
* active_list, and so will hold the active reference. Only when this
|
||||
* request is retired will the the batch_obj be moved onto the
|
||||
* inactive_list and lose its active reference. Hence we do not need
|
||||
* to explicitly hold another reference here.
|
||||
*/
|
||||
|
||||
if (request->ctx)
|
||||
i915_gem_context_reference(request->ctx);
|
||||
|
||||
request->emitted_jiffies = jiffies;
|
||||
was_empty = list_empty(&ring->request_list);
|
||||
list_add_tail(&request->list, &ring->request_list);
|
||||
@ -2091,9 +2115,114 @@ i915_gem_request_remove_from_client(struct drm_i915_gem_request *request)
|
||||
spin_unlock(&file_priv->mm.lock);
|
||||
}
|
||||
|
||||
static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
|
||||
{
|
||||
if (acthd >= obj->gtt_offset &&
|
||||
acthd < obj->gtt_offset + obj->base.size)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool i915_head_inside_request(const u32 acthd_unmasked,
|
||||
const u32 request_start,
|
||||
const u32 request_end)
|
||||
{
|
||||
const u32 acthd = acthd_unmasked & HEAD_ADDR;
|
||||
|
||||
if (request_start < request_end) {
|
||||
if (acthd >= request_start && acthd < request_end)
|
||||
return true;
|
||||
} else if (request_start > request_end) {
|
||||
if (acthd >= request_start || acthd < request_end)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool i915_request_guilty(struct drm_i915_gem_request *request,
|
||||
const u32 acthd, bool *inside)
|
||||
{
|
||||
/* There is a possibility that unmasked head address
|
||||
* pointing inside the ring, matches the batch_obj address range.
|
||||
* However this is extremely unlikely.
|
||||
*/
|
||||
|
||||
if (request->batch_obj) {
|
||||
if (i915_head_inside_object(acthd, request->batch_obj)) {
|
||||
*inside = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (i915_head_inside_request(acthd, request->head, request->tail)) {
|
||||
*inside = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void i915_set_reset_status(struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_request *request,
|
||||
u32 acthd)
|
||||
{
|
||||
struct i915_ctx_hang_stats *hs = NULL;
|
||||
bool inside, guilty;
|
||||
|
||||
/* Innocent until proven guilty */
|
||||
guilty = false;
|
||||
|
||||
if (ring->hangcheck.action != wait &&
|
||||
i915_request_guilty(request, acthd, &inside)) {
|
||||
DRM_ERROR("%s hung %s bo (0x%x ctx %d) at 0x%x\n",
|
||||
ring->name,
|
||||
inside ? "inside" : "flushing",
|
||||
request->batch_obj ?
|
||||
request->batch_obj->gtt_offset : 0,
|
||||
request->ctx ? request->ctx->id : 0,
|
||||
acthd);
|
||||
|
||||
guilty = true;
|
||||
}
|
||||
|
||||
/* If contexts are disabled or this is the default context, use
|
||||
* file_priv->reset_state
|
||||
*/
|
||||
if (request->ctx && request->ctx->id != DEFAULT_CONTEXT_ID)
|
||||
hs = &request->ctx->hang_stats;
|
||||
else if (request->file_priv)
|
||||
hs = &request->file_priv->hang_stats;
|
||||
|
||||
if (hs) {
|
||||
if (guilty)
|
||||
hs->batch_active++;
|
||||
else
|
||||
hs->batch_pending++;
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_gem_free_request(struct drm_i915_gem_request *request)
|
||||
{
|
||||
list_del(&request->list);
|
||||
i915_gem_request_remove_from_client(request);
|
||||
|
||||
if (request->ctx)
|
||||
i915_gem_context_unreference(request->ctx);
|
||||
|
||||
kfree(request);
|
||||
}
|
||||
|
||||
static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
|
||||
struct intel_ring_buffer *ring)
|
||||
{
|
||||
u32 completed_seqno;
|
||||
u32 acthd;
|
||||
|
||||
acthd = intel_ring_get_active_head(ring);
|
||||
completed_seqno = ring->get_seqno(ring, false);
|
||||
|
||||
while (!list_empty(&ring->request_list)) {
|
||||
struct drm_i915_gem_request *request;
|
||||
|
||||
@ -2101,9 +2230,10 @@ static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
|
||||
struct drm_i915_gem_request,
|
||||
list);
|
||||
|
||||
list_del(&request->list);
|
||||
i915_gem_request_remove_from_client(request);
|
||||
kfree(request);
|
||||
if (request->seqno > completed_seqno)
|
||||
i915_set_reset_status(ring, request, acthd);
|
||||
|
||||
i915_gem_free_request(request);
|
||||
}
|
||||
|
||||
while (!list_empty(&ring->active_list)) {
|
||||
@ -2195,9 +2325,7 @@ i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
|
||||
*/
|
||||
ring->last_retired_head = request->tail;
|
||||
|
||||
list_del(&request->list);
|
||||
i915_gem_request_remove_from_client(request);
|
||||
kfree(request);
|
||||
i915_gem_free_request(request);
|
||||
}
|
||||
|
||||
/* Move any buffers on the active list that are no longer referenced
|
||||
@ -2264,7 +2392,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
|
||||
idle = true;
|
||||
for_each_ring(ring, dev_priv, i) {
|
||||
if (ring->gpu_caches_dirty)
|
||||
i915_add_request(ring, NULL, NULL);
|
||||
i915_add_request(ring, NULL);
|
||||
|
||||
idle &= list_empty(&ring->request_list);
|
||||
}
|
||||
@ -2496,9 +2624,10 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)
|
||||
obj->has_aliasing_ppgtt_mapping = 0;
|
||||
}
|
||||
i915_gem_gtt_finish_object(obj);
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
list_del(&obj->mm_list);
|
||||
list_move_tail(&obj->gtt_list, &dev_priv->mm.unbound_list);
|
||||
list_move_tail(&obj->global_list, &dev_priv->mm.unbound_list);
|
||||
/* Avoid an unnecessary call to unbind on rebind. */
|
||||
obj->map_and_fenceable = true;
|
||||
|
||||
@ -2678,18 +2807,33 @@ static inline int fence_number(struct drm_i915_private *dev_priv,
|
||||
return fence - dev_priv->fence_regs;
|
||||
}
|
||||
|
||||
struct write_fence {
|
||||
struct drm_device *dev;
|
||||
struct drm_i915_gem_object *obj;
|
||||
int fence;
|
||||
};
|
||||
|
||||
static void i915_gem_write_fence__ipi(void *data)
|
||||
{
|
||||
struct write_fence *args = data;
|
||||
|
||||
/* Required for SNB+ with LLC */
|
||||
wbinvd();
|
||||
|
||||
/* Required for VLV */
|
||||
i915_gem_write_fence(args->dev, args->fence, args->obj);
|
||||
}
|
||||
|
||||
static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
|
||||
struct drm_i915_fence_reg *fence,
|
||||
bool enable)
|
||||
{
|
||||
struct drm_device *dev = obj->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int fence_reg = fence_number(dev_priv, fence);
|
||||
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
|
||||
struct write_fence args = {
|
||||
.dev = obj->base.dev,
|
||||
.fence = fence_number(dev_priv, fence),
|
||||
.obj = enable ? obj : NULL,
|
||||
};
|
||||
|
||||
/* In order to fully serialize access to the fenced region and
|
||||
* the update to the fence register we need to take extreme
|
||||
@ -2700,13 +2844,19 @@ static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
|
||||
* SNB+ we need to take a step further and emit an explicit wbinvd()
|
||||
* on each processor in order to manually flush all memory
|
||||
* transactions before updating the fence register.
|
||||
*
|
||||
* However, Valleyview complicates matter. There the wbinvd is
|
||||
* insufficient and unlike SNB/IVB requires the serialising
|
||||
* register write. (Note that that register write by itself is
|
||||
* conversely not sufficient for SNB+.) To compromise, we do both.
|
||||
*/
|
||||
if (HAS_LLC(obj->base.dev))
|
||||
on_each_cpu(i915_gem_write_fence__ipi, NULL, 1);
|
||||
i915_gem_write_fence(dev, fence_reg, enable ? obj : NULL);
|
||||
if (INTEL_INFO(args.dev)->gen >= 6)
|
||||
on_each_cpu(i915_gem_write_fence__ipi, &args, 1);
|
||||
else
|
||||
i915_gem_write_fence(args.dev, args.fence, args.obj);
|
||||
|
||||
if (enable) {
|
||||
obj->fence_reg = fence_reg;
|
||||
obj->fence_reg = args.fence;
|
||||
fence->obj = obj;
|
||||
list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
|
||||
} else {
|
||||
@ -2885,7 +3035,7 @@ static void i915_gem_verify_gtt(struct drm_device *dev)
|
||||
struct drm_i915_gem_object *obj;
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.gtt_list, global_list) {
|
||||
if (obj->gtt_space == NULL) {
|
||||
printk(KERN_ERR "object found on GTT list with no space reserved\n");
|
||||
err++;
|
||||
@ -2932,6 +3082,8 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
|
||||
struct drm_mm_node *node;
|
||||
u32 size, fence_size, fence_alignment, unfenced_alignment;
|
||||
bool mappable, fenceable;
|
||||
size_t gtt_max = map_and_fenceable ?
|
||||
dev_priv->gtt.mappable_end : dev_priv->gtt.total;
|
||||
int ret;
|
||||
|
||||
fence_size = i915_gem_get_gtt_size(dev,
|
||||
@ -2958,9 +3110,11 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
|
||||
/* If the object is bigger than the entire aperture, reject it early
|
||||
* before evicting everything in a vain attempt to find space.
|
||||
*/
|
||||
if (obj->base.size >
|
||||
(map_and_fenceable ? dev_priv->gtt.mappable_end : dev_priv->gtt.total)) {
|
||||
DRM_ERROR("Attempting to bind an object larger than the aperture\n");
|
||||
if (obj->base.size > gtt_max) {
|
||||
DRM_ERROR("Attempting to bind an object larger than the aperture: object=%zd > %s aperture=%zu\n",
|
||||
obj->base.size,
|
||||
map_and_fenceable ? "mappable" : "total",
|
||||
gtt_max);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
@ -2976,14 +3130,10 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
search_free:
|
||||
if (map_and_fenceable)
|
||||
ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
|
||||
size, alignment, obj->cache_level,
|
||||
0, dev_priv->gtt.mappable_end);
|
||||
else
|
||||
ret = drm_mm_insert_node_generic(&dev_priv->mm.gtt_space, node,
|
||||
size, alignment, obj->cache_level);
|
||||
search_free:
|
||||
ret = drm_mm_insert_node_in_range_generic(&dev_priv->mm.gtt_space, node,
|
||||
size, alignment,
|
||||
obj->cache_level, 0, gtt_max);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_something(dev, size, alignment,
|
||||
obj->cache_level,
|
||||
@ -3009,7 +3159,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
|
||||
return ret;
|
||||
}
|
||||
|
||||
list_move_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
|
||||
list_move_tail(&obj->global_list, &dev_priv->mm.bound_list);
|
||||
list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
|
||||
|
||||
obj->gtt_space = node;
|
||||
@ -3024,7 +3174,6 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
trace_i915_gem_object_bind(obj, map_and_fenceable);
|
||||
i915_gem_verify_gtt(dev);
|
||||
return 0;
|
||||
@ -3724,7 +3873,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
|
||||
const struct drm_i915_gem_object_ops *ops)
|
||||
{
|
||||
INIT_LIST_HEAD(&obj->mm_list);
|
||||
INIT_LIST_HEAD(&obj->gtt_list);
|
||||
INIT_LIST_HEAD(&obj->global_list);
|
||||
INIT_LIST_HEAD(&obj->ring_list);
|
||||
INIT_LIST_HEAD(&obj->exec_list);
|
||||
|
||||
@ -3824,7 +3973,13 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
|
||||
dev_priv->mm.interruptible = was_interruptible;
|
||||
}
|
||||
|
||||
obj->pages_pin_count = 0;
|
||||
/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
|
||||
* before progressing. */
|
||||
if (obj->stolen)
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
if (WARN_ON(obj->pages_pin_count))
|
||||
obj->pages_pin_count = 0;
|
||||
i915_gem_object_put_pages(obj);
|
||||
i915_gem_object_free_mmap_offset(obj);
|
||||
i915_gem_object_release_stolen(obj);
|
||||
@ -3977,12 +4132,21 @@ static int i915_gem_init_rings(struct drm_device *dev)
|
||||
goto cleanup_bsd_ring;
|
||||
}
|
||||
|
||||
if (HAS_VEBOX(dev)) {
|
||||
ret = intel_init_vebox_ring_buffer(dev);
|
||||
if (ret)
|
||||
goto cleanup_blt_ring;
|
||||
}
|
||||
|
||||
|
||||
ret = i915_gem_set_seqno(dev, ((u32)~0 - 0x1000));
|
||||
if (ret)
|
||||
goto cleanup_blt_ring;
|
||||
goto cleanup_vebox_ring;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_vebox_ring:
|
||||
intel_cleanup_ring_buffer(&dev_priv->ring[VECS]);
|
||||
cleanup_blt_ring:
|
||||
intel_cleanup_ring_buffer(&dev_priv->ring[BCS]);
|
||||
cleanup_bsd_ring:
|
||||
@ -4456,10 +4620,10 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc)
|
||||
}
|
||||
|
||||
cnt = 0;
|
||||
list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
|
||||
list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
|
||||
if (obj->pages_pin_count == 0)
|
||||
cnt += obj->base.size >> PAGE_SHIFT;
|
||||
list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
|
||||
list_for_each_entry(obj, &dev_priv->mm.inactive_list, global_list)
|
||||
if (obj->pin_count == 0 && obj->pages_pin_count == 0)
|
||||
cnt += obj->base.size >> PAGE_SHIFT;
|
||||
|
||||
|
@ -113,7 +113,7 @@ static int get_context_size(struct drm_device *dev)
|
||||
case 7:
|
||||
reg = I915_READ(GEN7_CXT_SIZE);
|
||||
if (IS_HASWELL(dev))
|
||||
ret = HSW_CXT_TOTAL_SIZE(reg) * 64;
|
||||
ret = HSW_CXT_TOTAL_SIZE;
|
||||
else
|
||||
ret = GEN7_CXT_TOTAL_SIZE(reg) * 64;
|
||||
break;
|
||||
@ -124,10 +124,10 @@ static int get_context_size(struct drm_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void do_destroy(struct i915_hw_context *ctx)
|
||||
void i915_gem_context_free(struct kref *ctx_ref)
|
||||
{
|
||||
if (ctx->file_priv)
|
||||
idr_remove(&ctx->file_priv->context_idr, ctx->id);
|
||||
struct i915_hw_context *ctx = container_of(ctx_ref,
|
||||
typeof(*ctx), ref);
|
||||
|
||||
drm_gem_object_unreference(&ctx->obj->base);
|
||||
kfree(ctx);
|
||||
@ -145,6 +145,7 @@ create_hw_context(struct drm_device *dev,
|
||||
if (ctx == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
kref_init(&ctx->ref);
|
||||
ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
|
||||
if (ctx->obj == NULL) {
|
||||
kfree(ctx);
|
||||
@ -155,7 +156,8 @@ create_hw_context(struct drm_device *dev,
|
||||
if (INTEL_INFO(dev)->gen >= 7) {
|
||||
ret = i915_gem_object_set_cache_level(ctx->obj,
|
||||
I915_CACHE_LLC_MLC);
|
||||
if (ret)
|
||||
/* Failure shouldn't ever happen this early */
|
||||
if (WARN_ON(ret))
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
@ -169,18 +171,18 @@ create_hw_context(struct drm_device *dev,
|
||||
if (file_priv == NULL)
|
||||
return ctx;
|
||||
|
||||
ctx->file_priv = file_priv;
|
||||
|
||||
ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID + 1, 0,
|
||||
GFP_KERNEL);
|
||||
if (ret < 0)
|
||||
goto err_out;
|
||||
|
||||
ctx->file_priv = file_priv;
|
||||
ctx->id = ret;
|
||||
|
||||
return ctx;
|
||||
|
||||
err_out:
|
||||
do_destroy(ctx);
|
||||
i915_gem_context_unreference(ctx);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@ -213,12 +215,16 @@ static int create_default_context(struct drm_i915_private *dev_priv)
|
||||
*/
|
||||
dev_priv->ring[RCS].default_context = ctx;
|
||||
ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false, false);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
|
||||
goto err_destroy;
|
||||
}
|
||||
|
||||
ret = do_switch(ctx);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Switch failed %d\n", ret);
|
||||
goto err_unpin;
|
||||
}
|
||||
|
||||
DRM_DEBUG_DRIVER("Default HW context loaded\n");
|
||||
return 0;
|
||||
@ -226,7 +232,7 @@ static int create_default_context(struct drm_i915_private *dev_priv)
|
||||
err_unpin:
|
||||
i915_gem_object_unpin(ctx->obj);
|
||||
err_destroy:
|
||||
do_destroy(ctx);
|
||||
i915_gem_context_unreference(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -236,6 +242,7 @@ void i915_gem_context_init(struct drm_device *dev)
|
||||
|
||||
if (!HAS_HW_CONTEXTS(dev)) {
|
||||
dev_priv->hw_contexts_disabled = true;
|
||||
DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -248,11 +255,13 @@ void i915_gem_context_init(struct drm_device *dev)
|
||||
|
||||
if (dev_priv->hw_context_size > (1<<20)) {
|
||||
dev_priv->hw_contexts_disabled = true;
|
||||
DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (create_default_context(dev_priv)) {
|
||||
dev_priv->hw_contexts_disabled = true;
|
||||
DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -262,6 +271,7 @@ void i915_gem_context_init(struct drm_device *dev)
|
||||
void i915_gem_context_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
|
||||
|
||||
if (dev_priv->hw_contexts_disabled)
|
||||
return;
|
||||
@ -271,9 +281,16 @@ void i915_gem_context_fini(struct drm_device *dev)
|
||||
* other code, leading to spurious errors. */
|
||||
intel_gpu_reset(dev);
|
||||
|
||||
i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj);
|
||||
i915_gem_object_unpin(dctx->obj);
|
||||
|
||||
do_destroy(dev_priv->ring[RCS].default_context);
|
||||
/* When default context is created and switched to, base object refcount
|
||||
* will be 2 (+1 from object creation and +1 from do_switch()).
|
||||
* i915_gem_context_fini() will be called after gpu_idle() has switched
|
||||
* to default context. So we need to unreference the base object once
|
||||
* to offset the do_switch part, so that i915_gem_context_unreference()
|
||||
* can then free the base object correctly. */
|
||||
drm_gem_object_unreference(&dctx->obj->base);
|
||||
i915_gem_context_unreference(dctx);
|
||||
}
|
||||
|
||||
static int context_idr_cleanup(int id, void *p, void *data)
|
||||
@ -282,11 +299,38 @@ static int context_idr_cleanup(int id, void *p, void *data)
|
||||
|
||||
BUG_ON(id == DEFAULT_CONTEXT_ID);
|
||||
|
||||
do_destroy(ctx);
|
||||
|
||||
i915_gem_context_unreference(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct i915_ctx_hang_stats *
|
||||
i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
|
||||
struct drm_file *file,
|
||||
u32 id)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = ring->dev->dev_private;
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
struct i915_hw_context *to;
|
||||
|
||||
if (dev_priv->hw_contexts_disabled)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (ring->id != RCS)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (file == NULL)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (id == DEFAULT_CONTEXT_ID)
|
||||
return &file_priv->hang_stats;
|
||||
|
||||
to = i915_gem_context_get(file->driver_priv, id);
|
||||
if (to == NULL)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
return &to->hang_stats;
|
||||
}
|
||||
|
||||
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
|
||||
{
|
||||
struct drm_i915_file_private *file_priv = file->driver_priv;
|
||||
@ -325,6 +369,7 @@ mi_set_context(struct intel_ring_buffer *ring,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw */
|
||||
if (IS_GEN7(ring->dev))
|
||||
intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE);
|
||||
else
|
||||
@ -353,13 +398,13 @@ mi_set_context(struct intel_ring_buffer *ring,
|
||||
static int do_switch(struct i915_hw_context *to)
|
||||
{
|
||||
struct intel_ring_buffer *ring = to->ring;
|
||||
struct drm_i915_gem_object *from_obj = ring->last_context_obj;
|
||||
struct i915_hw_context *from = ring->last_context;
|
||||
u32 hw_flags = 0;
|
||||
int ret;
|
||||
|
||||
BUG_ON(from_obj != NULL && from_obj->pin_count == 0);
|
||||
BUG_ON(from != NULL && from->obj != NULL && from->obj->pin_count == 0);
|
||||
|
||||
if (from_obj == to->obj)
|
||||
if (from == to)
|
||||
return 0;
|
||||
|
||||
ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false);
|
||||
@ -382,7 +427,7 @@ static int do_switch(struct i915_hw_context *to)
|
||||
|
||||
if (!to->is_initialized || is_default_context(to))
|
||||
hw_flags |= MI_RESTORE_INHIBIT;
|
||||
else if (WARN_ON_ONCE(from_obj == to->obj)) /* not yet expected */
|
||||
else if (WARN_ON_ONCE(from == to)) /* not yet expected */
|
||||
hw_flags |= MI_FORCE_RESTORE;
|
||||
|
||||
ret = mi_set_context(ring, to, hw_flags);
|
||||
@ -397,9 +442,9 @@ static int do_switch(struct i915_hw_context *to)
|
||||
* is a bit suboptimal because the retiring can occur simply after the
|
||||
* MI_SET_CONTEXT instead of when the next seqno has completed.
|
||||
*/
|
||||
if (from_obj != NULL) {
|
||||
from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
|
||||
i915_gem_object_move_to_active(from_obj, ring);
|
||||
if (from != NULL) {
|
||||
from->obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
|
||||
i915_gem_object_move_to_active(from->obj, ring);
|
||||
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
|
||||
* whole damn pipeline, we don't need to explicitly mark the
|
||||
* object dirty. The only exception is that the context must be
|
||||
@ -407,15 +452,26 @@ static int do_switch(struct i915_hw_context *to)
|
||||
* able to defer doing this until we know the object would be
|
||||
* swapped, but there is no way to do that yet.
|
||||
*/
|
||||
from_obj->dirty = 1;
|
||||
BUG_ON(from_obj->ring != ring);
|
||||
i915_gem_object_unpin(from_obj);
|
||||
from->obj->dirty = 1;
|
||||
BUG_ON(from->obj->ring != ring);
|
||||
|
||||
drm_gem_object_unreference(&from_obj->base);
|
||||
ret = i915_add_request(ring, NULL);
|
||||
if (ret) {
|
||||
/* Too late, we've already scheduled a context switch.
|
||||
* Try to undo the change so that the hw state is
|
||||
* consistent with out tracking. In case of emergency,
|
||||
* scream.
|
||||
*/
|
||||
WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT));
|
||||
return ret;
|
||||
}
|
||||
|
||||
i915_gem_object_unpin(from->obj);
|
||||
i915_gem_context_unreference(from);
|
||||
}
|
||||
|
||||
drm_gem_object_reference(&to->obj->base);
|
||||
ring->last_context_obj = to->obj;
|
||||
i915_gem_context_reference(to);
|
||||
ring->last_context = to;
|
||||
to->is_initialized = true;
|
||||
|
||||
return 0;
|
||||
@ -444,6 +500,8 @@ int i915_switch_context(struct intel_ring_buffer *ring,
|
||||
if (dev_priv->hw_contexts_disabled)
|
||||
return 0;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
|
||||
|
||||
if (ring != &dev_priv->ring[RCS])
|
||||
return 0;
|
||||
|
||||
@ -512,8 +570,8 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
do_destroy(ctx);
|
||||
|
||||
idr_remove(&ctx->file_priv->context_idr, ctx->id);
|
||||
i915_gem_context_unreference(ctx);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
|
||||
|
@ -786,7 +786,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
|
||||
obj->dirty = 1;
|
||||
obj->last_write_seqno = intel_ring_get_seqno(ring);
|
||||
if (obj->pin_count) /* check for potential scanout */
|
||||
intel_mark_fb_busy(obj);
|
||||
intel_mark_fb_busy(obj, ring);
|
||||
}
|
||||
|
||||
trace_i915_gem_object_change_domain(obj, old_read, old_write);
|
||||
@ -796,13 +796,14 @@ i915_gem_execbuffer_move_to_active(struct list_head *objects,
|
||||
static void
|
||||
i915_gem_execbuffer_retire_commands(struct drm_device *dev,
|
||||
struct drm_file *file,
|
||||
struct intel_ring_buffer *ring)
|
||||
struct intel_ring_buffer *ring,
|
||||
struct drm_i915_gem_object *obj)
|
||||
{
|
||||
/* Unconditionally force add_request to emit a full flush. */
|
||||
ring->gpu_caches_dirty = true;
|
||||
|
||||
/* Add a breadcrumb for the completion of the batch buffer */
|
||||
(void)i915_add_request(ring, file, NULL);
|
||||
(void)__i915_add_request(ring, file, obj, NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -885,6 +886,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
case I915_EXEC_VEBOX:
|
||||
ring = &dev_priv->ring[VECS];
|
||||
if (ctx_id != 0) {
|
||||
DRM_DEBUG("Ring %s doesn't support contexts\n",
|
||||
ring->name);
|
||||
return -EPERM;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DRM_DEBUG("execbuf with unknown ring: %d\n",
|
||||
(int)(args->flags & I915_EXEC_RING_MASK));
|
||||
@ -1074,7 +1084,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
|
||||
trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
|
||||
|
||||
i915_gem_execbuffer_move_to_active(&eb->objects, ring);
|
||||
i915_gem_execbuffer_retire_commands(dev, file, ring);
|
||||
i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
|
||||
|
||||
err:
|
||||
eb_destroy(eb);
|
||||
|
@ -28,8 +28,6 @@
|
||||
#include "i915_trace.h"
|
||||
#include "intel_drv.h"
|
||||
|
||||
typedef uint32_t gen6_gtt_pte_t;
|
||||
|
||||
/* PPGTT stuff */
|
||||
#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0))
|
||||
|
||||
@ -44,29 +42,22 @@ typedef uint32_t gen6_gtt_pte_t;
|
||||
#define GEN6_PTE_CACHE_LLC_MLC (3 << 1)
|
||||
#define GEN6_PTE_ADDR_ENCODE(addr) GEN6_GTT_ADDR_ENCODE(addr)
|
||||
|
||||
static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
static gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
{
|
||||
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
|
||||
switch (level) {
|
||||
case I915_CACHE_LLC_MLC:
|
||||
/* Haswell doesn't set L3 this way */
|
||||
if (IS_HASWELL(dev))
|
||||
pte |= GEN6_PTE_CACHE_LLC;
|
||||
else
|
||||
pte |= GEN6_PTE_CACHE_LLC_MLC;
|
||||
pte |= GEN6_PTE_CACHE_LLC_MLC;
|
||||
break;
|
||||
case I915_CACHE_LLC:
|
||||
pte |= GEN6_PTE_CACHE_LLC;
|
||||
break;
|
||||
case I915_CACHE_NONE:
|
||||
if (IS_HASWELL(dev))
|
||||
pte |= HSW_PTE_UNCACHED;
|
||||
else
|
||||
pte |= GEN6_PTE_UNCACHED;
|
||||
pte |= GEN6_PTE_UNCACHED;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
@ -75,16 +66,48 @@ static inline gen6_gtt_pte_t gen6_pte_encode(struct drm_device *dev,
|
||||
return pte;
|
||||
}
|
||||
|
||||
static int gen6_ppgtt_enable(struct drm_device *dev)
|
||||
#define BYT_PTE_WRITEABLE (1 << 1)
|
||||
#define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2)
|
||||
|
||||
static gen6_gtt_pte_t byt_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t pd_offset;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
|
||||
/* Mark the page as writeable. Other platforms don't have a
|
||||
* setting for read-only/writable, so this matches that behavior.
|
||||
*/
|
||||
pte |= BYT_PTE_WRITEABLE;
|
||||
|
||||
if (level != I915_CACHE_NONE)
|
||||
pte |= BYT_PTE_SNOOPED_BY_CPU_CACHES;
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
static gen6_gtt_pte_t hsw_pte_encode(struct drm_device *dev,
|
||||
dma_addr_t addr,
|
||||
enum i915_cache_level level)
|
||||
{
|
||||
gen6_gtt_pte_t pte = GEN6_PTE_VALID;
|
||||
pte |= GEN6_PTE_ADDR_ENCODE(addr);
|
||||
|
||||
if (level != I915_CACHE_NONE)
|
||||
pte |= GEN6_PTE_CACHE_LLC;
|
||||
|
||||
return pte;
|
||||
}
|
||||
|
||||
static void gen6_write_pdes(struct i915_hw_ppgtt *ppgtt)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = ppgtt->dev->dev_private;
|
||||
gen6_gtt_pte_t __iomem *pd_addr;
|
||||
uint32_t pd_entry;
|
||||
int i;
|
||||
|
||||
WARN_ON(ppgtt->pd_offset & 0x3f);
|
||||
pd_addr = (gen6_gtt_pte_t __iomem*)dev_priv->gtt.gsm +
|
||||
ppgtt->pd_offset / sizeof(gen6_gtt_pte_t);
|
||||
for (i = 0; i < ppgtt->num_pd_entries; i++) {
|
||||
@ -97,6 +120,19 @@ static int gen6_ppgtt_enable(struct drm_device *dev)
|
||||
writel(pd_entry, pd_addr + i);
|
||||
}
|
||||
readl(pd_addr);
|
||||
}
|
||||
|
||||
static int gen6_ppgtt_enable(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t pd_offset;
|
||||
struct intel_ring_buffer *ring;
|
||||
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
|
||||
int i;
|
||||
|
||||
BUG_ON(ppgtt->pd_offset & 0x3f);
|
||||
|
||||
gen6_write_pdes(ppgtt);
|
||||
|
||||
pd_offset = ppgtt->pd_offset;
|
||||
pd_offset /= 64; /* in cachelines, */
|
||||
@ -154,9 +190,9 @@ static void gen6_ppgtt_clear_range(struct i915_hw_ppgtt *ppgtt,
|
||||
unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES;
|
||||
unsigned last_pte, i;
|
||||
|
||||
scratch_pte = gen6_pte_encode(ppgtt->dev,
|
||||
ppgtt->scratch_page_dma_addr,
|
||||
I915_CACHE_LLC);
|
||||
scratch_pte = ppgtt->pte_encode(ppgtt->dev,
|
||||
ppgtt->scratch_page_dma_addr,
|
||||
I915_CACHE_LLC);
|
||||
|
||||
while (num_entries) {
|
||||
last_pte = first_pte + num_entries;
|
||||
@ -191,8 +227,8 @@ static void gen6_ppgtt_insert_entries(struct i915_hw_ppgtt *ppgtt,
|
||||
dma_addr_t page_addr;
|
||||
|
||||
page_addr = sg_page_iter_dma_address(&sg_iter);
|
||||
pt_vaddr[act_pte] = gen6_pte_encode(ppgtt->dev, page_addr,
|
||||
cache_level);
|
||||
pt_vaddr[act_pte] = ppgtt->pte_encode(ppgtt->dev, page_addr,
|
||||
cache_level);
|
||||
if (++act_pte == I915_PPGTT_PT_ENTRIES) {
|
||||
kunmap_atomic(pt_vaddr);
|
||||
act_pt++;
|
||||
@ -233,8 +269,15 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
|
||||
/* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
|
||||
* entries. For aliasing ppgtt support we just steal them at the end for
|
||||
* now. */
|
||||
first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
|
||||
first_pd_entry_in_global_pt = gtt_total_entries(dev_priv->gtt);
|
||||
|
||||
if (IS_HASWELL(dev)) {
|
||||
ppgtt->pte_encode = hsw_pte_encode;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
ppgtt->pte_encode = byt_pte_encode;
|
||||
} else {
|
||||
ppgtt->pte_encode = gen6_pte_encode;
|
||||
}
|
||||
ppgtt->num_pd_entries = I915_PPGTT_PD_ENTRIES;
|
||||
ppgtt->enable = gen6_ppgtt_enable;
|
||||
ppgtt->clear_range = gen6_ppgtt_clear_range;
|
||||
@ -396,7 +439,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
|
||||
dev_priv->gtt.gtt_clear_range(dev, dev_priv->gtt.start / PAGE_SIZE,
|
||||
dev_priv->gtt.total / PAGE_SIZE);
|
||||
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
|
||||
i915_gem_clflush_object(obj);
|
||||
i915_gem_gtt_bind_object(obj, obj->cache_level);
|
||||
}
|
||||
@ -437,7 +480,8 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_page_iter_dma_address(&sg_iter);
|
||||
iowrite32(gen6_pte_encode(dev, addr, level), >t_entries[i]);
|
||||
iowrite32(dev_priv->gtt.pte_encode(dev, addr, level),
|
||||
>t_entries[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -449,7 +493,7 @@ static void gen6_ggtt_insert_entries(struct drm_device *dev,
|
||||
*/
|
||||
if (i != 0)
|
||||
WARN_ON(readl(>t_entries[i-1])
|
||||
!= gen6_pte_encode(dev, addr, level));
|
||||
!= dev_priv->gtt.pte_encode(dev, addr, level));
|
||||
|
||||
/* This next bit makes the above posting read even more important. We
|
||||
* want to flush the TLBs only after we're certain all the PTE updates
|
||||
@ -474,8 +518,9 @@ static void gen6_ggtt_clear_range(struct drm_device *dev,
|
||||
first_entry, num_entries, max_entries))
|
||||
num_entries = max_entries;
|
||||
|
||||
scratch_pte = gen6_pte_encode(dev, dev_priv->gtt.scratch_page_dma,
|
||||
I915_CACHE_LLC);
|
||||
scratch_pte = dev_priv->gtt.pte_encode(dev,
|
||||
dev_priv->gtt.scratch_page_dma,
|
||||
I915_CACHE_LLC);
|
||||
for (i = 0; i < num_entries; i++)
|
||||
iowrite32(scratch_pte, >t_base[i]);
|
||||
readl(gtt_base);
|
||||
@ -586,7 +631,7 @@ void i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust;
|
||||
|
||||
/* Mark any preallocated objects as occupied */
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) {
|
||||
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
|
||||
DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n",
|
||||
obj->gtt_offset, obj->base.size);
|
||||
|
||||
@ -809,6 +854,13 @@ int i915_gem_gtt_init(struct drm_device *dev)
|
||||
} else {
|
||||
dev_priv->gtt.gtt_probe = gen6_gmch_probe;
|
||||
dev_priv->gtt.gtt_remove = gen6_gmch_remove;
|
||||
if (IS_HASWELL(dev)) {
|
||||
dev_priv->gtt.pte_encode = hsw_pte_encode;
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
dev_priv->gtt.pte_encode = byt_pte_encode;
|
||||
} else {
|
||||
dev_priv->gtt.pte_encode = gen6_pte_encode;
|
||||
}
|
||||
}
|
||||
|
||||
ret = dev_priv->gtt.gtt_probe(dev, &dev_priv->gtt.total,
|
||||
|
@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
|
||||
* its value of TOLUD.
|
||||
*/
|
||||
base = 0;
|
||||
if (INTEL_INFO(dev)->gen >= 6) {
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
pci_read_config_dword(dev->pdev, 0x5c, &base);
|
||||
base &= ~((1<<20) - 1);
|
||||
} else if (INTEL_INFO(dev)->gen >= 6) {
|
||||
/* Read Base Data of Stolen Memory Register (BDSM) directly.
|
||||
* Note that there is also a MCHBAR miror at 0x1080c0 or
|
||||
* we could use device 2:0x5c instead.
|
||||
@ -136,6 +139,7 @@ static int i915_setup_compression(struct drm_device *dev, int size)
|
||||
err_fb:
|
||||
drm_mm_put_block(compressed_fb);
|
||||
err:
|
||||
pr_info_once("drm: not enough stolen space for compressed buffer (need %d more bytes), disabling. Hint: you may be able to increase stolen memory size in the BIOS to avoid this.\n", size);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@ -143,7 +147,7 @@ int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->mm.stolen_base == 0)
|
||||
if (!drm_mm_initialized(&dev_priv->mm.stolen))
|
||||
return -ENODEV;
|
||||
|
||||
if (size < dev_priv->cfb_size)
|
||||
@ -175,6 +179,9 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (!drm_mm_initialized(&dev_priv->mm.stolen))
|
||||
return;
|
||||
|
||||
i915_gem_stolen_cleanup_compression(dev);
|
||||
drm_mm_takedown(&dev_priv->mm.stolen);
|
||||
}
|
||||
@ -182,6 +189,7 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
|
||||
int i915_gem_init_stolen(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int bios_reserved = 0;
|
||||
|
||||
dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
|
||||
if (dev_priv->mm.stolen_base == 0)
|
||||
@ -190,8 +198,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
|
||||
DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
|
||||
dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
bios_reserved = 1024*1024; /* top 1M on VLV/BYT */
|
||||
|
||||
/* Basic memrange allocator for stolen space */
|
||||
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size);
|
||||
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
|
||||
bios_reserved);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -270,7 +282,7 @@ _i915_gem_object_create_stolen(struct drm_device *dev,
|
||||
goto cleanup;
|
||||
|
||||
obj->has_dma_mapping = true;
|
||||
obj->pages_pin_count = 1;
|
||||
i915_gem_object_pin_pages(obj);
|
||||
obj->stolen = stolen;
|
||||
|
||||
obj->base.write_domain = I915_GEM_DOMAIN_GTT;
|
||||
@ -291,7 +303,7 @@ i915_gem_object_create_stolen(struct drm_device *dev, u32 size)
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_mm_node *stolen;
|
||||
|
||||
if (dev_priv->mm.stolen_base == 0)
|
||||
if (!drm_mm_initialized(&dev_priv->mm.stolen))
|
||||
return NULL;
|
||||
|
||||
DRM_DEBUG_KMS("creating stolen object: size=%x\n", size);
|
||||
@ -322,7 +334,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct drm_mm_node *stolen;
|
||||
|
||||
if (dev_priv->mm.stolen_base == 0)
|
||||
if (!drm_mm_initialized(&dev_priv->mm.stolen))
|
||||
return NULL;
|
||||
|
||||
DRM_DEBUG_KMS("creating preallocated stolen object: stolen_offset=%x, gtt_offset=%x, size=%x\n",
|
||||
@ -330,7 +342,6 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
|
||||
/* KISS and expect everything to be page-aligned */
|
||||
BUG_ON(stolen_offset & 4095);
|
||||
BUG_ON(gtt_offset & 4095);
|
||||
BUG_ON(size & 4095);
|
||||
|
||||
if (WARN_ON(size == 0))
|
||||
@ -351,6 +362,10 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Some objects just need physical mem from stolen space */
|
||||
if (gtt_offset == -1)
|
||||
return obj;
|
||||
|
||||
/* To simplify the initialisation sequence between KMS and GTT,
|
||||
* we allow construction of the stolen object prior to
|
||||
* setting up the GTT space. The actual reservation will occur
|
||||
@ -371,7 +386,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
obj->gtt_offset = gtt_offset;
|
||||
obj->has_global_gtt_mapping = 1;
|
||||
|
||||
list_add_tail(&obj->gtt_list, &dev_priv->mm.bound_list);
|
||||
list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);
|
||||
list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list);
|
||||
|
||||
return obj;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -192,6 +192,7 @@ static void i915_restore_vga(struct drm_device *dev)
|
||||
static void i915_save_display(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
unsigned long flags;
|
||||
|
||||
/* Display arbitration control */
|
||||
if (INTEL_INFO(dev)->gen <= 4)
|
||||
@ -202,6 +203,8 @@ static void i915_save_display(struct drm_device *dev)
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_save_display_reg(dev);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
||||
|
||||
/* LVDS state */
|
||||
if (HAS_PCH_SPLIT(dev)) {
|
||||
dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
|
||||
@ -222,6 +225,8 @@ static void i915_save_display(struct drm_device *dev)
|
||||
dev_priv->regfile.saveLVDS = I915_READ(LVDS);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
||||
|
||||
if (!IS_I830(dev) && !IS_845G(dev) && !HAS_PCH_SPLIT(dev))
|
||||
dev_priv->regfile.savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
|
||||
|
||||
@ -257,6 +262,7 @@ static void i915_restore_display(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 mask = 0xffffffff;
|
||||
unsigned long flags;
|
||||
|
||||
/* Display arbitration */
|
||||
if (INTEL_INFO(dev)->gen <= 4)
|
||||
@ -265,6 +271,8 @@ static void i915_restore_display(struct drm_device *dev)
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
i915_restore_display_reg(dev);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->backlight.lock, flags);
|
||||
|
||||
/* LVDS state */
|
||||
if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
|
||||
I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2);
|
||||
@ -304,6 +312,8 @@ static void i915_restore_display(struct drm_device *dev)
|
||||
I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->backlight.lock, flags);
|
||||
|
||||
/* only restore FBC info on the platform that supports FBC*/
|
||||
intel_disable_fbc(dev);
|
||||
if (I915_HAS_FBC(dev)) {
|
||||
|
@ -212,7 +212,13 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev,
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
if (IS_VALLEYVIEW(dev_priv->dev)) {
|
||||
u32 freq;
|
||||
freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
ret = vlv_gpu_freq(dev_priv->mem_freq, (freq >> 8) & 0xff);
|
||||
} else {
|
||||
ret = dev_priv->rps.cur_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
}
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
@ -226,7 +232,10 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.max_delay);
|
||||
else
|
||||
ret = dev_priv->rps.max_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
@ -246,16 +255,25 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val /= GT_FREQUENCY_MULTIPLIER;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
non_oc_max = (rp_state_cap & 0xff);
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
if (IS_VALLEYVIEW(dev_priv->dev)) {
|
||||
val = vlv_freq_opcode(dev_priv->mem_freq, val);
|
||||
|
||||
if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) {
|
||||
hw_max = valleyview_rps_max_freq(dev_priv);
|
||||
hw_min = valleyview_rps_min_freq(dev_priv);
|
||||
non_oc_max = hw_max;
|
||||
} else {
|
||||
val /= GT_FREQUENCY_MULTIPLIER;
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
non_oc_max = (rp_state_cap & 0xff);
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
}
|
||||
|
||||
if (val < hw_min || val > hw_max ||
|
||||
val < dev_priv->rps.min_delay) {
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -264,8 +282,12 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev,
|
||||
DRM_DEBUG("User requested overclocking to %d\n",
|
||||
val * GT_FREQUENCY_MULTIPLIER);
|
||||
|
||||
if (dev_priv->rps.cur_delay > val)
|
||||
gen6_set_rps(dev_priv->dev, val);
|
||||
if (dev_priv->rps.cur_delay > val) {
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
valleyview_set_rps(dev_priv->dev, val);
|
||||
else
|
||||
gen6_set_rps(dev_priv->dev, val);
|
||||
}
|
||||
|
||||
dev_priv->rps.max_delay = val;
|
||||
|
||||
@ -282,7 +304,10 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
if (IS_VALLEYVIEW(dev_priv->dev))
|
||||
ret = vlv_gpu_freq(dev_priv->mem_freq, dev_priv->rps.min_delay);
|
||||
else
|
||||
ret = dev_priv->rps.min_delay * GT_FREQUENCY_MULTIPLIER;
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ret);
|
||||
@ -302,21 +327,32 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
val /= GT_FREQUENCY_MULTIPLIER;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
val = vlv_freq_opcode(dev_priv->mem_freq, val);
|
||||
|
||||
hw_max = valleyview_rps_max_freq(dev_priv);
|
||||
hw_min = valleyview_rps_min_freq(dev_priv);
|
||||
} else {
|
||||
val /= GT_FREQUENCY_MULTIPLIER;
|
||||
|
||||
rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
|
||||
hw_max = dev_priv->rps.hw_max;
|
||||
hw_min = ((rp_state_cap & 0xff0000) >> 16);
|
||||
}
|
||||
|
||||
if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) {
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev_priv->rps.cur_delay < val)
|
||||
gen6_set_rps(dev_priv->dev, val);
|
||||
if (dev_priv->rps.cur_delay < val) {
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
valleyview_set_rps(dev, val);
|
||||
else
|
||||
gen6_set_rps(dev_priv->dev, val);
|
||||
}
|
||||
|
||||
dev_priv->rps.min_delay = val;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user