Merge tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc into drm-next
drm-misc for 4.12: Core: - Removed some fb subsampling dimension checks from core (Ville) - Some MST slot cleanup (Dhinakaran) - Extracted drm_debugfs.h & drm_ioctl.h from drmP.h (Daniel) - Added drm_atomic_helper_shutdown() to compliment suspend/resume counterparts (Daniel) - Pipe context through legacy modeset to remove legacy_backoff nasties (Daniel) - Cleanups around vblank as well as allowing lockless counter reads (Chris W.) - VGA Switcheroo added to MAINTAINERS with Lukas Wunner as reviewer (Lukas) Drivers: - Enhancements to rockchip driver probe (Jeffy) and dsi (Chris Z.) - Thunderbolt external GPU awareness added (Lukas) * tag 'drm-misc-next-2017-03-31' of git://anongit.freedesktop.org/git/drm-misc: (63 commits) apple-gmux: Don't switch external DP port on 2011+ MacBook Pros drm/nouveau: Don't register Thunderbolt eGPU with vga_switcheroo drm/amdgpu: Don't register Thunderbolt eGPU with vga_switcheroo drm/radeon: Don't register Thunderbolt eGPU with vga_switcheroo PCI: Recognize Thunderbolt devices MAINTAINERS: Add Lukas Wunner as reviewer for vga_switcheroo drm: Fix locking gotcha in page_flip ioctl drm: Clarify the role of plane_state argument to drm_simple update(). drm: Clear e after kfree in drm_mode_page_flip_ioctl drm: Convert cmpxchg(bool) back to a two step operation drm/bridge: ti-tfp410: support hpd via gpio drm: use .hword to represent 16-bit numbers Revert unrelated part of "drm: simplify the locking in the GETCRTC ioctl" drm: Fixup failure paths in drm_atomic_helper_set_config drm: Peek at the current counter/timestamp for vblank queries drm: Refactor vblank sequence number comparison drm: vblank cannot be enabled if dev->irq_enabled is false drm: Mark up accesses of vblank->enabled outside of its spinlock drm: Make the decision to keep vblank irq enabled earlier drm/atomic-helper: Remove the backoff hack from set_config ...
This commit is contained in:
commit
320d8c3d38
|
@ -59,9 +59,9 @@
|
|||
/* Fixed header pattern */
|
||||
header: .byte 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00
|
||||
|
||||
mfg_id: .word swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3))
|
||||
mfg_id: .hword swap16(mfgname2id(MFG_LNX1, MFG_LNX2, MFG_LNX3))
|
||||
|
||||
prod_code: .word 0
|
||||
prod_code: .hword 0
|
||||
|
||||
/* Serial number. 32 bits, little endian. */
|
||||
serial_number: .long SERIAL
|
||||
|
@ -177,7 +177,7 @@ std_vres: .byte (XY_RATIO<<6)+VFREQ-60
|
|||
|
||||
descriptor1:
|
||||
/* Pixel clock in 10 kHz units. (0.-655.35 MHz, little-endian) */
|
||||
clock: .word CLOCK/10
|
||||
clock: .hword CLOCK/10
|
||||
|
||||
/* Horizontal active pixels 8 lsbits (0-4095) */
|
||||
x_act_lsb: .byte XPIX&0xff
|
||||
|
|
|
@ -10,7 +10,7 @@ Required properties:
|
|||
- interrupts: Represent the controller's interrupt to the CPU(s).
|
||||
- clocks, clock-names: Phandles to the controller's pll reference
|
||||
clock(ref) and APB clock(pclk). For RK3399, a phy config clock
|
||||
(phy_cfg) is additional required. As described in [1].
|
||||
(phy_cfg) and a grf clock(grf) are required. As described in [1].
|
||||
- rockchip,grf: this soc should set GRF regs to mux vopl/vopb.
|
||||
- ports: contain a port node with endpoint definitions as defined in [2].
|
||||
For vopb,set the reg = <0> and set the reg = <1> for vopl.
|
||||
|
|
|
@ -207,6 +207,18 @@ Display CRC Support
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
|
||||
:doc: CRC ABI
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
|
||||
:export:
|
||||
|
||||
Debugfs Support
|
||||
---------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_debugfs.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
|
||||
:export:
|
||||
|
||||
VBlank event handling
|
||||
=====================
|
||||
|
||||
|
|
|
@ -60,3 +60,28 @@ checkpatch or sparse. We welcome such contributions.
|
|||
|
||||
Anyone looking to kick it up a notch can find a list of janitorial tasks on
|
||||
the :ref:`TODO list <todo>`.
|
||||
|
||||
Contribution Process
|
||||
====================
|
||||
|
||||
Mostly the DRM subsystem works like any other kernel subsystem, see :ref:`the
|
||||
main process guidelines and documentation <process_index>` for how things work.
|
||||
Here we just document some of the specialities of the GPU subsystem.
|
||||
|
||||
Feature Merge Deadlines
|
||||
-----------------------
|
||||
|
||||
All feature work must be in the linux-next tree by the -rc6 release of the
|
||||
current release cycle, otherwise they must be postponed and can't reach the next
|
||||
merge window. All patches must have landed in the drm-next tree by latest -rc7,
|
||||
but if your branch is not in linux-next then this must have happened by -rc6
|
||||
already.
|
||||
|
||||
After that point only bugfixes (like after the upstream merge window has closed
|
||||
with the -rc1 release) are allowed. No new platform enabling or new drivers are
|
||||
allowed.
|
||||
|
||||
This means that there's a blackout-period of about one month where feature work
|
||||
can't be merged. The recommended way to deal with that is having a -next tree
|
||||
that's always open, but making sure to not feed it into linux-next during the
|
||||
blackout period. As an example, drm-misc works like that.
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions
|
||||
,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon."
|
||||
,Connector,“EDID”,BLOB | IMMUTABLE,0,Connector,Contains id of edid blob ptr object.
|
||||
,,“DPMS”,ENUM,"{ “On”, “Standby”, “Suspend”, “Off” }",Connector,Contains DPMS operation mode value.
|
||||
,,“PATH”,BLOB | IMMUTABLE,0,Connector,Contains topology path to a connector.
|
||||
,,“TILE”,BLOB | IMMUTABLE,0,Connector,Contains tiling information for a connector.
|
||||
,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Connector,CRTC that connector is attached to (atomic)
|
||||
,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
|
||||
,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
|
||||
,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
|
||||
|
|
|
|
@ -99,6 +99,30 @@ events for atomic commits correctly. But fixing these bugs is good anyway.
|
|||
|
||||
Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
Better manual-upload support for atomic
|
||||
---------------------------------------
|
||||
|
||||
This would be especially useful for tinydrm:
|
||||
|
||||
- Add a struct drm_rect dirty_clip to drm_crtc_state. When duplicating the
|
||||
crtc state, clear that to the max values, x/y = 0 and w/h = MAX_INT, in
|
||||
__drm_atomic_helper_crtc_duplicate_state().
|
||||
|
||||
- Move tinydrm_merge_clips into drm_framebuffer.c, dropping the tinydrm_
|
||||
prefix ofc and using drm_fb_. drm_framebuffer.c makes sense since this
|
||||
is a function useful to implement the fb->dirty function.
|
||||
|
||||
- Create a new drm_fb_dirty function which does essentially what e.g.
|
||||
mipi_dbi_fb_dirty does. You can use e.g. drm_atomic_helper_update_plane as the
|
||||
template. But instead of doing a simple full-screen plane update, this new
|
||||
helper also sets crtc_state->dirty_clip to the right coordinates. And of
|
||||
course it needs to check whether the fb is actually active (and maybe where),
|
||||
so there's some book-keeping involved. There's also some good fun involved in
|
||||
scaling things appropriately. For that case we might simply give up and
|
||||
declare the entire area covered by the plane as dirty.
|
||||
|
||||
Contact: Noralf Trønnes, Daniel Vetter
|
||||
|
||||
Fallout from atomic KMS
|
||||
-----------------------
|
||||
|
||||
|
@ -272,6 +296,32 @@ This is a really varied tasks with lots of little bits and pieces:
|
|||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Clean up the debugfs support
|
||||
----------------------------
|
||||
|
||||
There's a bunch of issues with it:
|
||||
|
||||
- The drm_info_list ->show() function doesn't even bother to cast to the drm
|
||||
structure for you. This is lazy.
|
||||
|
||||
- We probably want to have some support for debugfs files on crtc/connectors and
|
||||
maybe other kms objects directly in core. There's even drm_print support in
|
||||
the funcs for these objects to dump kms state, so it's all there. And then the
|
||||
->show() functions should obviously give you a pointer to the right object.
|
||||
|
||||
- The drm_info_list stuff is centered on drm_minor instead of drm_device. For
|
||||
anything we want to print drm_device (or maybe drm_file) is the right thing.
|
||||
|
||||
- The drm_driver->debugfs_init hooks we have is just an artifact of the old
|
||||
midlayered load sequence. DRM debugfs should work more like sysfs, where you
|
||||
can create properties/files for an object anytime you want, and the core
|
||||
takes care of publishing/unpuplishing all the files at register/unregister
|
||||
time. Drivers shouldn't need to worry about these technicalities, and fixing
|
||||
this (together with the drm_minor->drm_device move) would allow us to remove
|
||||
debugfs_init.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Better Testing
|
||||
==============
|
||||
|
||||
|
@ -310,6 +360,52 @@ Contact: Daniel Vetter
|
|||
Driver Specific
|
||||
===============
|
||||
|
||||
tinydrm
|
||||
-------
|
||||
|
||||
Tinydrm is the helper driver for really simple fb drivers. The goal is to make
|
||||
those drivers as simple as possible, so lots of room for refactoring:
|
||||
|
||||
- backlight helpers, probably best to put them into a new drm_backlight.c.
|
||||
This is because drivers/video is de-facto unmaintained. We could also
|
||||
move drivers/video/backlight to drivers/gpu/backlight and take it all
|
||||
over within drm-misc, but that's more work.
|
||||
|
||||
- spi helpers, probably best put into spi core/helper code. Thierry said
|
||||
the spi maintainer is fast&reactive, so shouldn't be a big issue.
|
||||
|
||||
- extract the mipi-dbi helper (well, the non-tinydrm specific parts at
|
||||
least) into a separate helper, like we have for mipi-dsi already. Or follow
|
||||
one of the ideas for having a shared dsi/dbi helper, abstracting away the
|
||||
transport details more.
|
||||
|
||||
- tinydrm_lastclose could be drm_fb_helper_lastclose. Only thing we need
|
||||
for that is to store the drm_fb_helper pointer somewhere in
|
||||
drm_device->mode_config. And then we could roll that out to all the
|
||||
drivers.
|
||||
|
||||
- tinydrm_gem_cma_prime_import_sg_table should probably go into the cma
|
||||
helpers, as a _vmapped variant (since not every driver needs the vmap).
|
||||
And tinydrm_gem_cma_free_object could the be merged into
|
||||
drm_gem_cma_free_object().
|
||||
|
||||
- tinydrm_fb_create we could move into drm_simple_pipe, only need to add
|
||||
the fb_create hook to drm_simple_pipe_funcs, which would again simplify a
|
||||
bunch of things (since it gives you a one-stop vfunc for simple drivers).
|
||||
|
||||
- Quick aside: The unregister devm stuff is kinda getting the lifetimes of
|
||||
a drm_device wrong. Doesn't matter, since everyone else gets it wrong
|
||||
too :-)
|
||||
|
||||
- With the fbdev pointer in dev->mode_config we could also make
|
||||
suspend/resume helpers entirely generic, at least if we add a
|
||||
dev->mode_config.suspend_state. We could even provide a generic pm_ops
|
||||
structure with those.
|
||||
|
||||
- also rework the drm_framebuffer_funcs->dirty hook wire-up, see above.
|
||||
|
||||
Contact: Noralf Trønnes, Daniel Vetter
|
||||
|
||||
Outside DRM
|
||||
===========
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
\renewcommand\thesection*
|
||||
\renewcommand\thesubsection*
|
||||
|
||||
.. _process_index:
|
||||
|
||||
Working with the kernel development community
|
||||
=============================================
|
||||
|
|
10
MAINTAINERS
10
MAINTAINERS
|
@ -4145,6 +4145,7 @@ F: Documentation/devicetree/bindings/video/
|
|||
F: Documentation/gpu/
|
||||
F: include/drm/
|
||||
F: include/uapi/drm/
|
||||
F: include/linux/vga*
|
||||
|
||||
DRM DRIVERS AND MISC GPU PATCHES
|
||||
M: Daniel Vetter <daniel.vetter@intel.com>
|
||||
|
@ -4158,6 +4159,7 @@ F: drivers/gpu/vga/
|
|||
F: drivers/gpu/drm/*
|
||||
F: include/drm/drm*
|
||||
F: include/uapi/drm/drm*
|
||||
F: include/linux/vga*
|
||||
|
||||
DRM DRIVER FOR AST SERVER GRAPHICS CHIPS
|
||||
M: Dave Airlie <airlied@redhat.com>
|
||||
|
@ -13257,6 +13259,14 @@ L: kvm@vger.kernel.org
|
|||
S: Maintained
|
||||
F: drivers/vfio/platform/
|
||||
|
||||
VGA_SWITCHEROO
|
||||
R: Lukas Wunner <lukas@wunner.de>
|
||||
S: Maintained
|
||||
F: Documentation/gpu/vga-switcheroo.rst
|
||||
F: drivers/gpu/vga/vga_switcheroo.c
|
||||
F: include/linux/vga_switcheroo.h
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
|
||||
VIDEOBUF2 FRAMEWORK
|
||||
M: Pawel Osciak <pawel@osciak.com>
|
||||
M: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
|
|
|
@ -1929,7 +1929,9 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
runtime = true;
|
||||
if (amdgpu_device_is_px(ddev))
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(adev->pdev, &amdgpu_switcheroo_ops, runtime);
|
||||
if (!pci_is_thunderbolt_attached(adev->pdev))
|
||||
vga_switcheroo_register_client(adev->pdev,
|
||||
&amdgpu_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
vga_switcheroo_init_domain_pm_ops(adev->dev, &adev->vga_pm_domain);
|
||||
|
||||
|
@ -2084,7 +2086,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
|||
amdgpu_atombios_fini(adev);
|
||||
kfree(adev->bios);
|
||||
adev->bios = NULL;
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
if (!pci_is_thunderbolt_attached(adev->pdev))
|
||||
vga_switcheroo_unregister_client(adev->pdev);
|
||||
if (adev->flags & AMD_IS_PX)
|
||||
vga_switcheroo_fini_domain_pm_ops(adev->dev);
|
||||
vga_client_register(adev->pdev, NULL, NULL, NULL);
|
||||
|
|
|
@ -311,7 +311,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags,
|
||||
uint32_t target)
|
||||
uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct amdgpu_bo *new_abo;
|
||||
struct amdgpu_flip_work *work;
|
||||
|
@ -332,7 +333,8 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_crtc_set_config(struct drm_mode_set *set)
|
||||
int amdgpu_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct amdgpu_device *adev;
|
||||
|
@ -349,7 +351,7 @@ int amdgpu_crtc_set_config(struct drm_mode_set *set)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = drm_crtc_helper_set_config(set);
|
||||
ret = drm_crtc_helper_set_config(set, ctx);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
if (crtc->enabled)
|
||||
|
|
|
@ -103,7 +103,8 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
|||
amdgpu_has_atpx() &&
|
||||
(amdgpu_is_atpx_hybrid() ||
|
||||
amdgpu_has_atpx_dgpu_power_cntl()) &&
|
||||
((flags & AMD_IS_APU) == 0))
|
||||
((flags & AMD_IS_APU) == 0) &&
|
||||
!pci_is_thunderbolt_attached(dev->pdev))
|
||||
flags |= AMD_IS_PX;
|
||||
|
||||
/* amdgpu_device_init should report only fatal error
|
||||
|
|
|
@ -590,11 +590,13 @@ int amdgpu_align_pitch(struct amdgpu_device *adev, int width, int bpp, bool tile
|
|||
/* amdgpu_display.c */
|
||||
void amdgpu_print_display_setup(struct drm_device *dev);
|
||||
int amdgpu_modeset_create_props(struct amdgpu_device *adev);
|
||||
int amdgpu_crtc_set_config(struct drm_mode_set *set);
|
||||
int amdgpu_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags, uint32_t target);
|
||||
uint32_t page_flip_flags, uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
|
||||
struct amdgpu_bo *new_abo);
|
||||
int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
|
||||
|
|
|
@ -1027,7 +1027,8 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
|
|||
* and a mode_set.
|
||||
*/
|
||||
static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags)
|
||||
struct drm_framebuffer *fb, struct drm_pending_vblank_event *event, uint32_t page_flip_flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
|
||||
struct armada_frame_work *work;
|
||||
|
|
|
@ -94,7 +94,8 @@ static int
|
|||
armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
|
||||
uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
|
||||
struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
|
||||
|
@ -257,7 +258,8 @@ armada_ovl_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int armada_ovl_plane_disable(struct drm_plane *plane)
|
||||
static int armada_ovl_plane_disable(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct armada_ovl_plane *dplane = drm_to_armada_ovl_plane(plane);
|
||||
struct drm_framebuffer *fb;
|
||||
|
|
|
@ -192,6 +192,8 @@ void bochs_fbdev_fini(struct bochs_device *bochs)
|
|||
if (bochs->fb.initialized)
|
||||
bochs_fbdev_destroy(bochs);
|
||||
|
||||
drm_fb_helper_fini(&bochs->fb.helper);
|
||||
if (bochs->fb.helper.fbdev)
|
||||
drm_fb_helper_fini(&bochs->fb.helper);
|
||||
|
||||
bochs->fb.initialized = false;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ static void bochs_crtc_commit(struct drm_crtc *crtc)
|
|||
static int bochs_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags)
|
||||
uint32_t page_flip_flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct bochs_device *bochs =
|
||||
container_of(crtc, struct bochs_device, crtc);
|
||||
|
|
|
@ -1916,7 +1916,7 @@ static irqreturn_t dw_hdmi_irq(int irq, void *dev_id)
|
|||
if (intr_stat &
|
||||
(HDMI_IH_PHY_STAT0_RX_SENSE | HDMI_IH_PHY_STAT0_HPD)) {
|
||||
mutex_lock(&hdmi->mutex);
|
||||
if (!hdmi->disabled && !hdmi->force) {
|
||||
if (!hdmi->force) {
|
||||
/*
|
||||
* If the RX sense status indicates we're disconnected,
|
||||
* clear the software rxsense status.
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -18,11 +22,15 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
#define HOTPLUG_DEBOUNCE_MS 1100
|
||||
|
||||
struct tfp410 {
|
||||
struct drm_bridge bridge;
|
||||
struct drm_connector connector;
|
||||
|
||||
struct i2c_adapter *ddc;
|
||||
struct gpio_desc *hpd;
|
||||
struct delayed_work hpd_work;
|
||||
|
||||
struct device *dev;
|
||||
};
|
||||
|
@ -76,6 +84,13 @@ tfp410_connector_detect(struct drm_connector *connector, bool force)
|
|||
{
|
||||
struct tfp410 *dvi = drm_connector_to_tfp410(connector);
|
||||
|
||||
if (dvi->hpd) {
|
||||
if (gpiod_get_value_cansleep(dvi->hpd))
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
}
|
||||
|
||||
if (dvi->ddc) {
|
||||
if (drm_probe_ddc(dvi->ddc))
|
||||
return connector_status_connected;
|
||||
|
@ -106,6 +121,9 @@ static int tfp410_attach(struct drm_bridge *bridge)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (dvi->hpd)
|
||||
dvi->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
|
||||
drm_connector_helper_add(&dvi->connector,
|
||||
&tfp410_con_helper_funcs);
|
||||
ret = drm_connector_init(bridge->dev, &dvi->connector,
|
||||
|
@ -125,7 +143,27 @@ static const struct drm_bridge_funcs tfp410_bridge_funcs = {
|
|||
.attach = tfp410_attach,
|
||||
};
|
||||
|
||||
static int tfp410_get_connector_ddc(struct tfp410 *dvi)
|
||||
static void tfp410_hpd_work_func(struct work_struct *work)
|
||||
{
|
||||
struct tfp410 *dvi;
|
||||
|
||||
dvi = container_of(work, struct tfp410, hpd_work.work);
|
||||
|
||||
if (dvi->bridge.dev)
|
||||
drm_helper_hpd_irq_event(dvi->bridge.dev);
|
||||
}
|
||||
|
||||
static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg)
|
||||
{
|
||||
struct tfp410 *dvi = arg;
|
||||
|
||||
mod_delayed_work(system_wq, &dvi->hpd_work,
|
||||
msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tfp410_get_connector_properties(struct tfp410 *dvi)
|
||||
{
|
||||
struct device_node *ep = NULL, *connector_node = NULL;
|
||||
struct device_node *ddc_phandle = NULL;
|
||||
|
@ -140,6 +178,17 @@ static int tfp410_get_connector_ddc(struct tfp410 *dvi)
|
|||
if (!connector_node)
|
||||
goto fail;
|
||||
|
||||
dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode,
|
||||
"hpd-gpios", 0, GPIOD_IN, "hpd");
|
||||
if (IS_ERR(dvi->hpd)) {
|
||||
ret = PTR_ERR(dvi->hpd);
|
||||
dvi->hpd = NULL;
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ddc_phandle = of_parse_phandle(connector_node, "ddc-i2c-bus", 0);
|
||||
if (!ddc_phandle)
|
||||
goto fail;
|
||||
|
@ -176,10 +225,23 @@ static int tfp410_init(struct device *dev)
|
|||
dvi->bridge.of_node = dev->of_node;
|
||||
dvi->dev = dev;
|
||||
|
||||
ret = tfp410_get_connector_ddc(dvi);
|
||||
ret = tfp410_get_connector_properties(dvi);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (dvi->hpd) {
|
||||
INIT_DELAYED_WORK(&dvi->hpd_work, tfp410_hpd_work_func);
|
||||
|
||||
ret = devm_request_threaded_irq(dev, gpiod_to_irq(dvi->hpd),
|
||||
NULL, tfp410_hpd_irq_thread, IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"hdmi-hpd", dvi);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to register hpd interrupt\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ret = drm_bridge_add(&dvi->bridge);
|
||||
if (ret) {
|
||||
dev_err(dev, "drm_bridge_add() failed: %d\n", ret);
|
||||
|
@ -189,6 +251,8 @@ static int tfp410_init(struct device *dev)
|
|||
return 0;
|
||||
fail:
|
||||
i2c_put_adapter(dvi->ddc);
|
||||
if (dvi->hpd)
|
||||
gpiod_put(dvi->hpd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -196,10 +260,14 @@ static int tfp410_fini(struct device *dev)
|
|||
{
|
||||
struct tfp410 *dvi = dev_get_drvdata(dev);
|
||||
|
||||
cancel_delayed_work_sync(&dvi->hpd_work);
|
||||
|
||||
drm_bridge_remove(&dvi->bridge);
|
||||
|
||||
if (dvi->ddc)
|
||||
i2c_put_adapter(dvi->ddc);
|
||||
if (dvi->hpd)
|
||||
gpiod_put(dvi->hpd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2077,6 +2077,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
|
|||
* @src_y: y offset of @fb for panning
|
||||
* @src_w: width of source rectangle in @fb
|
||||
* @src_h: height of source rectangle in @fb
|
||||
* @ctx: lock acquire context
|
||||
*
|
||||
* Provides a default plane update handler using the atomic driver interface.
|
||||
*
|
||||
|
@ -2089,7 +2090,8 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_plane_state *plane_state;
|
||||
|
@ -2099,8 +2101,7 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
retry:
|
||||
state->acquire_ctx = ctx;
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state)) {
|
||||
ret = PTR_ERR(plane_state);
|
||||
|
@ -2125,59 +2126,33 @@ retry:
|
|||
|
||||
ret = drm_atomic_commit(state);
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
plane->old_fb = plane->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_update_plane);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_disable_plane - Helper for primary plane disable using * atomic
|
||||
* @plane: plane to disable
|
||||
* @ctx: lock acquire context
|
||||
*
|
||||
* Provides a default plane disable handler using the atomic driver interface.
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
int drm_atomic_helper_disable_plane(struct drm_plane *plane)
|
||||
int drm_atomic_helper_disable_plane(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_plane_state *plane_state;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* FIXME: Without plane->crtc set we can't get at the implicit legacy
|
||||
* acquire context. The real fix will be to wire the acquire ctx through
|
||||
* everywhere we need it, but meanwhile prevent chaos by just skipping
|
||||
* this noop. The critical case is the cursor ioctls which a) only grab
|
||||
* crtc/cursor-plane locks (so we need the crtc to get at the right
|
||||
* acquire context) and b) can try to disable the plane multiple times.
|
||||
*/
|
||||
if (!plane->crtc)
|
||||
return 0;
|
||||
|
||||
state = drm_atomic_state_alloc(plane->dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(plane->crtc);
|
||||
retry:
|
||||
state->acquire_ctx = ctx;
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state)) {
|
||||
ret = PTR_ERR(plane_state);
|
||||
|
@ -2193,24 +2168,8 @@ retry:
|
|||
|
||||
ret = drm_atomic_commit(state);
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
plane->old_fb = plane->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
|
||||
|
||||
|
@ -2306,6 +2265,7 @@ static int update_output_state(struct drm_atomic_state *state,
|
|||
/**
|
||||
* drm_atomic_helper_set_config - set a new config from userspace
|
||||
* @set: mode set configuration
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Provides a default crtc set_config handler using the atomic driver interface.
|
||||
*
|
||||
|
@ -2318,7 +2278,8 @@ static int update_output_state(struct drm_atomic_state *state,
|
|||
* Returns:
|
||||
* Returns 0 on success, negative errno numbers on failure.
|
||||
*/
|
||||
int drm_atomic_helper_set_config(struct drm_mode_set *set)
|
||||
int drm_atomic_helper_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
|
@ -2329,32 +2290,16 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
|
|||
return -ENOMEM;
|
||||
|
||||
state->legacy_set_config = true;
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
retry:
|
||||
state->acquire_ctx = ctx;
|
||||
ret = __drm_atomic_helper_set_config(set, state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
fail:
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
crtc->primary->old_fb = crtc->primary->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_set_config);
|
||||
|
||||
|
@ -2443,7 +2388,8 @@ commit:
|
|||
* that they are connected to.
|
||||
*
|
||||
* This is used for example in suspend/resume to disable all currently active
|
||||
* functions when suspending.
|
||||
* functions when suspending. If you just want to shut down everything at e.g.
|
||||
* driver unload, look at drm_atomic_helper_shutdown().
|
||||
*
|
||||
* Note that if callers haven't already acquired all modeset locks this might
|
||||
* return -EDEADLK, which must be handled by calling drm_modeset_backoff().
|
||||
|
@ -2452,7 +2398,8 @@ commit:
|
|||
* 0 on success or a negative error code on failure.
|
||||
*
|
||||
* See also:
|
||||
* drm_atomic_helper_suspend(), drm_atomic_helper_resume()
|
||||
* drm_atomic_helper_suspend(), drm_atomic_helper_resume() and
|
||||
* drm_atomic_helper_shutdown().
|
||||
*/
|
||||
int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
|
@ -2516,6 +2463,42 @@ free:
|
|||
|
||||
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_shutdown - shutdown all CRTC
|
||||
* @dev: DRM device
|
||||
*
|
||||
* This shuts down all CRTC, which is useful for driver unloading. Shutdown on
|
||||
* suspend should instead be handled with drm_atomic_helper_suspend(), since
|
||||
* that also takes a snapshot of the modeset state to be restored on resume.
|
||||
*
|
||||
* This is just a convenience wrapper around drm_atomic_helper_disable_all(),
|
||||
* and it is the atomic version of drm_crtc_force_disable_all().
|
||||
*/
|
||||
void drm_atomic_helper_shutdown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
while (1) {
|
||||
ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (!ret)
|
||||
ret = drm_atomic_helper_disable_all(dev, &ctx);
|
||||
|
||||
if (ret != -EDEADLK)
|
||||
break;
|
||||
|
||||
drm_modeset_backoff(&ctx);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_shutdown);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_suspend - subsystem-level suspend helper
|
||||
* @dev: DRM device
|
||||
|
@ -2862,6 +2845,7 @@ static int page_flip_common(
|
|||
* @fb: DRM framebuffer
|
||||
* @event: optional DRM event to signal upon completion
|
||||
* @flags: flip flags for non-vblank sync'ed updates
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Provides a default &drm_crtc_funcs.page_flip implementation
|
||||
* using the atomic driver interface.
|
||||
|
@ -2875,7 +2859,8 @@ static int page_flip_common(
|
|||
int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
struct drm_atomic_state *state;
|
||||
|
@ -2885,34 +2870,16 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
retry:
|
||||
ret = page_flip_common(state, crtc, fb, event, flags);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_nonblocking_commit(state);
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
plane->old_fb = plane->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_page_flip);
|
||||
|
||||
|
@ -2923,6 +2890,7 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip);
|
|||
* @event: optional DRM event to signal upon completion
|
||||
* @flags: flip flags for non-vblank sync'ed updates
|
||||
* @target: specifying the target vblank period when the flip to take effect
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Provides a default &drm_crtc_funcs.page_flip_target implementation.
|
||||
* Similar to drm_atomic_helper_page_flip() with extra parameter to specify
|
||||
|
@ -2936,7 +2904,8 @@ int drm_atomic_helper_page_flip_target(
|
|||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags,
|
||||
uint32_t target)
|
||||
uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
struct drm_atomic_state *state;
|
||||
|
@ -2947,9 +2916,8 @@ int drm_atomic_helper_page_flip_target(
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
retry:
|
||||
ret = page_flip_common(state, crtc, fb, event, flags);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
@ -2962,26 +2930,9 @@ retry:
|
|||
crtc_state->target_vblank = target;
|
||||
|
||||
ret = drm_atomic_nonblocking_commit(state);
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
/*
|
||||
* Someone might have exchanged the framebuffer while we dropped locks
|
||||
* in the backoff code. We need to fix up the fb refcount tracking the
|
||||
* core does for us.
|
||||
*/
|
||||
plane->old_fb = plane->fb;
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
|
||||
|
||||
|
|
|
@ -94,6 +94,8 @@ EXPORT_SYMBOL(drm_crtc_from_index);
|
|||
* drm_crtc_force_disable - Forcibly turn off a CRTC
|
||||
* @crtc: CRTC to turn off
|
||||
*
|
||||
* Note: This should only be used by non-atomic legacy drivers.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
|
@ -103,6 +105,8 @@ int drm_crtc_force_disable(struct drm_crtc *crtc)
|
|||
.crtc = crtc,
|
||||
};
|
||||
|
||||
WARN_ON(drm_drv_uses_atomic_modeset(crtc->dev));
|
||||
|
||||
return drm_mode_set_config_internal(&set);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_force_disable);
|
||||
|
@ -114,6 +118,9 @@ EXPORT_SYMBOL(drm_crtc_force_disable);
|
|||
* Drivers may want to call this on unload to ensure that all displays are
|
||||
* unlit and the GPU is in a consistent, low power state. Takes modeset locks.
|
||||
*
|
||||
* Note: This should only be used by non-atomic legacy drivers. For an atomic
|
||||
* version look at drm_atomic_helper_shutdown().
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
|
@ -399,9 +406,9 @@ int drm_mode_getcrtc(struct drm_device *dev,
|
|||
if (!crtc)
|
||||
return -ENOENT;
|
||||
|
||||
drm_modeset_lock_crtc(crtc, crtc->primary);
|
||||
crtc_resp->gamma_size = crtc->gamma_size;
|
||||
|
||||
drm_modeset_lock(&crtc->primary->mutex, NULL);
|
||||
if (crtc->primary->state && crtc->primary->state->fb)
|
||||
crtc_resp->fb_id = crtc->primary->state->fb->base.id;
|
||||
else if (!crtc->primary->state && crtc->primary->fb)
|
||||
|
@ -409,9 +416,14 @@ int drm_mode_getcrtc(struct drm_device *dev,
|
|||
else
|
||||
crtc_resp->fb_id = 0;
|
||||
|
||||
if (crtc->state) {
|
||||
if (crtc->primary->state) {
|
||||
crtc_resp->x = crtc->primary->state->src_x >> 16;
|
||||
crtc_resp->y = crtc->primary->state->src_y >> 16;
|
||||
}
|
||||
drm_modeset_unlock(&crtc->primary->mutex);
|
||||
|
||||
drm_modeset_lock(&crtc->mutex, NULL);
|
||||
if (crtc->state) {
|
||||
if (crtc->state->enable) {
|
||||
drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode);
|
||||
crtc_resp->mode_valid = 1;
|
||||
|
@ -430,23 +442,13 @@ int drm_mode_getcrtc(struct drm_device *dev,
|
|||
crtc_resp->mode_valid = 0;
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_crtc(crtc);
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
|
||||
* @set: modeset config to set
|
||||
*
|
||||
* This is a little helper to wrap internal calls to the
|
||||
* &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
|
||||
* correct refcounting dance.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_set_config_internal(struct drm_mode_set *set)
|
||||
static int __drm_mode_set_config_internal(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_crtc *crtc = set->crtc;
|
||||
struct drm_framebuffer *fb;
|
||||
|
@ -463,7 +465,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
|
|||
|
||||
fb = set->fb;
|
||||
|
||||
ret = crtc->funcs->set_config(set);
|
||||
ret = crtc->funcs->set_config(set, ctx);
|
||||
if (ret == 0) {
|
||||
crtc->primary->crtc = crtc;
|
||||
crtc->primary->fb = fb;
|
||||
|
@ -479,6 +481,25 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
|
|||
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* drm_mode_set_config_internal - helper to call &drm_mode_config_funcs.set_config
|
||||
* @set: modeset config to set
|
||||
*
|
||||
* This is a little helper to wrap internal calls to the
|
||||
* &drm_mode_config_funcs.set_config driver interface. The only thing it adds is
|
||||
* correct refcounting dance.
|
||||
*
|
||||
* This should only be used by non-atomic legacy drivers.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_set_config_internal(struct drm_mode_set *set)
|
||||
{
|
||||
WARN_ON(drm_drv_uses_atomic_modeset(set->crtc->dev));
|
||||
|
||||
return __drm_mode_set_config_internal(set, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_set_config_internal);
|
||||
|
||||
/**
|
||||
|
@ -534,6 +555,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
struct drm_display_mode *mode = NULL;
|
||||
struct drm_mode_set set;
|
||||
uint32_t __user *set_connectors_ptr;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -547,15 +569,18 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
|
||||
return -ERANGE;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
crtc = drm_crtc_find(dev, crtc_req->crtc_id);
|
||||
if (!crtc) {
|
||||
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
return -ENOENT;
|
||||
}
|
||||
DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
retry:
|
||||
ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
if (crtc_req->mode_valid) {
|
||||
/* If we have a mode we need a framebuffer. */
|
||||
/* If we pass -1, set the mode with the currently bound fb */
|
||||
|
@ -676,7 +701,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
set.connectors = connector_set;
|
||||
set.num_connectors = crtc_req->count_connectors;
|
||||
set.fb = fb;
|
||||
ret = drm_mode_set_config_internal(&set);
|
||||
ret = __drm_mode_set_config_internal(&set, &ctx);
|
||||
|
||||
out:
|
||||
if (fb)
|
||||
|
@ -690,7 +715,13 @@ out:
|
|||
}
|
||||
kfree(connector_set);
|
||||
drm_mode_destroy(dev, mode);
|
||||
drm_modeset_unlock_all(dev);
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -476,6 +476,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
|
|||
/**
|
||||
* drm_crtc_helper_set_config - set a new config from userspace
|
||||
* @set: mode set configuration
|
||||
* @ctx: lock acquire context, not used here
|
||||
*
|
||||
* The drm_crtc_helper_set_config() helper function implements the of
|
||||
* &drm_crtc_funcs.set_config callback for drivers using the legacy CRTC
|
||||
|
@ -510,7 +511,8 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
|
|||
* Returns:
|
||||
* Returns 0 on success, negative errno numbers on failure.
|
||||
*/
|
||||
int drm_crtc_helper_set_config(struct drm_mode_set *set)
|
||||
int drm_crtc_helper_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct drm_crtc **save_encoder_crtcs, *new_crtc;
|
||||
|
|
|
@ -1,10 +1,3 @@
|
|||
/**
|
||||
* \file drm_debugfs.c
|
||||
* debugfs support for DRM
|
||||
*
|
||||
* \author Ben Gamari <bgamari@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Created: Sun Dec 21 13:08:50 2008 by bgamari@gmail.com
|
||||
*
|
||||
|
@ -34,9 +27,12 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
@ -72,16 +68,15 @@ static const struct file_operations drm_debugfs_fops = {
|
|||
|
||||
|
||||
/**
|
||||
* Initialize a given set of debugfs files for a device
|
||||
*
|
||||
* \param files The array of files to create
|
||||
* \param count The number of files given
|
||||
* \param root DRI debugfs dir entry.
|
||||
* \param minor device minor number
|
||||
* \return Zero on success, non-zero on failure
|
||||
* drm_debugfs_create_files - Initialize a given set of debugfs files for DRM
|
||||
* minor
|
||||
* @files: The array of files to create
|
||||
* @count: The number of files given
|
||||
* @root: DRI debugfs dir entry.
|
||||
* @minor: device minor number
|
||||
*
|
||||
* Create a given set of debugfs files represented by an array of
|
||||
* &drm_info_list in the given root directory. These files will be removed
|
||||
* &struct drm_info_list in the given root directory. These files will be removed
|
||||
* automatically on drm_debugfs_cleanup().
|
||||
*/
|
||||
int drm_debugfs_create_files(const struct drm_info_list *files, int count,
|
||||
|
@ -130,17 +125,6 @@ fail:
|
|||
}
|
||||
EXPORT_SYMBOL(drm_debugfs_create_files);
|
||||
|
||||
/**
|
||||
* Initialize the DRI debugfs filesystem for a device
|
||||
*
|
||||
* \param dev DRM device
|
||||
* \param minor device minor number
|
||||
* \param root DRI debugfs dir entry.
|
||||
*
|
||||
* Create the DRI debugfs root entry "/sys/kernel/debug/dri", the device debugfs root entry
|
||||
* "/sys/kernel/debug/dri/%minor%/", and each entry in debugfs_list as
|
||||
* "/sys/kernel/debug/dri/%minor%/%name%".
|
||||
*/
|
||||
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
||||
struct dentry *root)
|
||||
{
|
||||
|
@ -186,16 +170,6 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a list of debugfs files
|
||||
*
|
||||
* \param files The list of files
|
||||
* \param count The number of files
|
||||
* \param minor The minor of which we should remove the files
|
||||
* \return always zero.
|
||||
*
|
||||
* Remove all debugfs entries created by debugfs_init().
|
||||
*/
|
||||
int drm_debugfs_remove_files(const struct drm_info_list *files, int count,
|
||||
struct drm_minor *minor)
|
||||
{
|
||||
|
@ -232,14 +206,6 @@ static void drm_debugfs_remove_all_files(struct drm_minor *minor)
|
|||
mutex_unlock(&minor->debugfs_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup the debugfs filesystem resources.
|
||||
*
|
||||
* \param minor device minor number.
|
||||
* \return always zero.
|
||||
*
|
||||
* Remove all debugfs entries created by debugfs_init().
|
||||
*/
|
||||
int drm_debugfs_cleanup(struct drm_minor *minor)
|
||||
{
|
||||
if (!minor->debugfs_root)
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
* DOC: CRC ABI
|
||||
*
|
||||
* DRM device drivers can provide to userspace CRC information of each frame as
|
||||
* it reached a given hardware component (a "source").
|
||||
* it reached a given hardware component (a CRC sampling "source").
|
||||
*
|
||||
* Userspace can control generation of CRCs in a given CRTC by writing to the
|
||||
* file dri/0/crtc-N/crc/control in debugfs, with N being the index of the CRTC.
|
||||
|
@ -57,6 +57,11 @@
|
|||
* rely on being able to generate matching CRC values for the frame contents that
|
||||
* it submits. In this general case, the maximum userspace can do is to compare
|
||||
* the reported CRCs of frames that should have the same contents.
|
||||
*
|
||||
* On the driver side the implementation effort is minimal, drivers only need to
|
||||
* implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically
|
||||
* set up if that vfunc is set. CRC samples need to be captured in the driver by
|
||||
* calling drm_crtc_add_crc_entry().
|
||||
*/
|
||||
|
||||
static int crc_control_show(struct seq_file *m, void *data)
|
||||
|
@ -280,16 +285,6 @@ static const struct file_operations drm_crtc_crc_data_fops = {
|
|||
.release = crtc_crc_release,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_debugfs_crtc_crc_add - Add files to debugfs for capture of frame CRCs
|
||||
* @crtc: CRTC to whom the frames will belong
|
||||
*
|
||||
* Adds files to debugfs directory that allows userspace to control the
|
||||
* generation of frame CRCs and to read them.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_debugfs_crtc_crc_add(struct drm_crtc *crtc)
|
||||
{
|
||||
struct dentry *crc_ent, *ent;
|
||||
|
|
|
@ -2042,10 +2042,6 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
mgr->total_pbn = 2560;
|
||||
mgr->total_slots = DIV_ROUND_UP(mgr->total_pbn, mgr->pbn_div);
|
||||
mgr->avail_slots = mgr->total_slots;
|
||||
|
||||
/* add initial branch device at LCT 1 */
|
||||
mstb = drm_dp_add_mst_branch_device(1, NULL);
|
||||
if (mstb == NULL) {
|
||||
|
@ -2475,26 +2471,25 @@ int drm_dp_find_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr,
|
|||
|
||||
num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
|
||||
|
||||
if (num_slots > mgr->avail_slots)
|
||||
/* max. time slots - one slot for MTP header */
|
||||
if (num_slots > 63)
|
||||
return -ENOSPC;
|
||||
return num_slots;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_find_vcpi_slots);
|
||||
|
||||
static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_vcpi *vcpi, int pbn)
|
||||
struct drm_dp_vcpi *vcpi, int pbn, int slots)
|
||||
{
|
||||
int num_slots;
|
||||
int ret;
|
||||
|
||||
num_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
|
||||
|
||||
if (num_slots > mgr->avail_slots)
|
||||
/* max. time slots - one slot for MTP header */
|
||||
if (slots > 63)
|
||||
return -ENOSPC;
|
||||
|
||||
vcpi->pbn = pbn;
|
||||
vcpi->aligned_pbn = num_slots * mgr->pbn_div;
|
||||
vcpi->num_slots = num_slots;
|
||||
vcpi->aligned_pbn = slots * mgr->pbn_div;
|
||||
vcpi->num_slots = slots;
|
||||
|
||||
ret = drm_dp_mst_assign_payload_id(mgr, vcpi);
|
||||
if (ret < 0)
|
||||
|
@ -2509,7 +2504,8 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr,
|
|||
* @pbn: payload bandwidth number to request
|
||||
* @slots: returned number of slots for this PBN.
|
||||
*/
|
||||
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots)
|
||||
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port, int pbn, int slots)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -2517,22 +2513,25 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp
|
|||
if (!port)
|
||||
return false;
|
||||
|
||||
if (slots < 0)
|
||||
return false;
|
||||
|
||||
if (port->vcpi.vcpi > 0) {
|
||||
DRM_DEBUG_KMS("payload: vcpi %d already allocated for pbn %d - requested pbn %d\n", port->vcpi.vcpi, port->vcpi.pbn, pbn);
|
||||
if (pbn == port->vcpi.pbn) {
|
||||
*slots = port->vcpi.num_slots;
|
||||
drm_dp_put_port(port);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn);
|
||||
ret = drm_dp_init_vcpi(mgr, &port->vcpi, pbn, slots);
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("failed to init vcpi %d %d %d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), mgr->avail_slots, ret);
|
||||
DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n",
|
||||
DIV_ROUND_UP(pbn, mgr->pbn_div), ret);
|
||||
goto out;
|
||||
}
|
||||
DRM_DEBUG_KMS("initing vcpi for %d %d\n", pbn, port->vcpi.num_slots);
|
||||
*slots = port->vcpi.num_slots;
|
||||
DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n",
|
||||
pbn, port->vcpi.num_slots);
|
||||
|
||||
drm_dp_put_port(port);
|
||||
return true;
|
||||
|
|
|
@ -177,7 +177,7 @@ struct drm_framebuffer *drm_fb_cma_create_with_funcs(struct drm_device *dev,
|
|||
int ret;
|
||||
int i;
|
||||
|
||||
info = drm_format_info(mode_cmd->pixel_format);
|
||||
info = drm_get_format_info(dev, mode_cmd);
|
||||
if (!info)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
|
|
@ -206,6 +206,31 @@ const struct drm_format_info *drm_format_info(u32 format)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_format_info);
|
||||
|
||||
/**
|
||||
* drm_get_format_info - query information for a given framebuffer configuration
|
||||
* @dev: DRM device
|
||||
* @mode_cmd: metadata from the userspace fb creation request
|
||||
*
|
||||
* Returns:
|
||||
* The instance of struct drm_format_info that describes the pixel format, or
|
||||
* NULL if the format is unsupported.
|
||||
*/
|
||||
const struct drm_format_info *
|
||||
drm_get_format_info(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
const struct drm_format_info *info = NULL;
|
||||
|
||||
if (dev->mode_config.funcs->get_format_info)
|
||||
info = dev->mode_config.funcs->get_format_info(mode_cmd);
|
||||
|
||||
if (!info)
|
||||
info = drm_format_info(mode_cmd->pixel_format);
|
||||
|
||||
return info;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_format_info);
|
||||
|
||||
/**
|
||||
* drm_format_num_planes - get the number of planes for format
|
||||
* @format: pixel format (DRM_FORMAT_*)
|
||||
|
|
|
@ -126,11 +126,31 @@ int drm_mode_addfb(struct drm_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
||||
static int fb_plane_width(int width,
|
||||
const struct drm_format_info *format, int plane)
|
||||
{
|
||||
if (plane == 0)
|
||||
return width;
|
||||
|
||||
return DIV_ROUND_UP(width, format->hsub);
|
||||
}
|
||||
|
||||
static int fb_plane_height(int height,
|
||||
const struct drm_format_info *format, int plane)
|
||||
{
|
||||
if (plane == 0)
|
||||
return height;
|
||||
|
||||
return DIV_ROUND_UP(height, format->vsub);
|
||||
}
|
||||
|
||||
static int framebuffer_check(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *r)
|
||||
{
|
||||
const struct drm_format_info *info;
|
||||
int i;
|
||||
|
||||
/* check if the format is supported at all */
|
||||
info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
|
||||
if (!info) {
|
||||
struct drm_format_name_buf format_name;
|
||||
|
@ -140,19 +160,22 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->width == 0 || r->width % info->hsub) {
|
||||
/* now let the driver pick its own format info */
|
||||
info = drm_get_format_info(dev, r);
|
||||
|
||||
if (r->width == 0) {
|
||||
DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (r->height == 0 || r->height % info->vsub) {
|
||||
if (r->height == 0) {
|
||||
DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < info->num_planes; i++) {
|
||||
unsigned int width = r->width / (i != 0 ? info->hsub : 1);
|
||||
unsigned int height = r->height / (i != 0 ? info->vsub : 1);
|
||||
unsigned int width = fb_plane_width(r->width, info, i);
|
||||
unsigned int height = fb_plane_height(r->height, info, i);
|
||||
unsigned int cpp = info->cpp[i];
|
||||
|
||||
if (!r->handles[i]) {
|
||||
|
@ -263,7 +286,7 @@ drm_internal_framebuffer_create(struct drm_device *dev,
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ret = framebuffer_check(r);
|
||||
ret = framebuffer_check(dev, r);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -816,10 +839,7 @@ int drm_framebuffer_plane_width(int width,
|
|||
if (plane >= fb->format->num_planes)
|
||||
return 0;
|
||||
|
||||
if (plane == 0)
|
||||
return width;
|
||||
|
||||
return width / fb->format->hsub;
|
||||
return fb_plane_width(width, fb->format, plane);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_plane_width);
|
||||
|
||||
|
@ -838,9 +858,6 @@ int drm_framebuffer_plane_height(int height,
|
|||
if (plane >= fb->format->num_planes)
|
||||
return 0;
|
||||
|
||||
if (plane == 0)
|
||||
return height;
|
||||
|
||||
return height / fb->format->vsub;
|
||||
return fb_plane_height(height, fb->format, plane);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_framebuffer_plane_height);
|
||||
|
|
|
@ -100,7 +100,7 @@ int drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
|||
void drm_gem_open(struct drm_device *dev, struct drm_file *file_private);
|
||||
void drm_gem_release(struct drm_device *dev, struct drm_file *file_private);
|
||||
|
||||
/* drm_debugfs.c */
|
||||
/* drm_debugfs.c drm_debugfs_crc.c */
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
int drm_debugfs_init(struct drm_minor *minor, int minor_id,
|
||||
struct dentry *root);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include "drm_legacy.h"
|
||||
|
|
|
@ -325,6 +325,8 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
|
|||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
|
||||
assert_spin_locked(&dev->vbl_lock);
|
||||
|
||||
/* Prevent vblank irq processing while disabling vblank irqs,
|
||||
* so no updates of timestamps or count can happen after we've
|
||||
* disabled. Needed to prevent races in case of delayed irq's.
|
||||
|
@ -384,7 +386,7 @@ void drm_vblank_cleanup(struct drm_device *dev)
|
|||
for (pipe = 0; pipe < dev->num_crtcs; pipe++) {
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
WARN_ON(vblank->enabled &&
|
||||
WARN_ON(READ_ONCE(vblank->enabled) &&
|
||||
drm_core_check_feature(dev, DRIVER_MODESET));
|
||||
|
||||
del_timer_sync(&vblank->disable_timer);
|
||||
|
@ -810,14 +812,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
|
|||
/* Return upper bound of timestamp precision error. */
|
||||
*max_error = duration_ns;
|
||||
|
||||
/* Check if in vblank area:
|
||||
* vpos is >=0 in video scanout area, but negative
|
||||
* within vblank area, counting down the number of lines until
|
||||
* start of scanout.
|
||||
*/
|
||||
if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK)
|
||||
ret |= DRM_VBLANKTIME_IN_VBLANK;
|
||||
|
||||
/* Convert scanout position into elapsed time at raw_time query
|
||||
* since start of scanout at first display scanline. delta_ns
|
||||
* can be negative if start of scanout hasn't happened yet.
|
||||
|
@ -1105,11 +1099,16 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
|
|||
*/
|
||||
ret = __enable_vblank(dev, pipe);
|
||||
DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
atomic_dec(&vblank->refcount);
|
||||
else {
|
||||
vblank->enabled = true;
|
||||
} else {
|
||||
drm_update_vblank_count(dev, pipe, 0);
|
||||
/* drm_update_vblank_count() includes a wmb so we just
|
||||
* need to ensure that the compiler emits the write
|
||||
* to mark the vblank as enabled after the call
|
||||
* to drm_update_vblank_count().
|
||||
*/
|
||||
WRITE_ONCE(vblank->enabled, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1487,6 +1486,11 @@ int drm_legacy_modeset_ctl(struct drm_device *dev, void *data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline bool vblank_passed(u32 seq, u32 ref)
|
||||
{
|
||||
return (seq - ref) <= (1 << 23);
|
||||
}
|
||||
|
||||
static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
||||
union drm_wait_vblank *vblwait,
|
||||
struct drm_file *file_priv)
|
||||
|
@ -1517,7 +1521,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
|||
* vblank disable, so no need for further locking. The reference from
|
||||
* drm_vblank_get() protects against vblank disable from another source.
|
||||
*/
|
||||
if (!vblank->enabled) {
|
||||
if (!READ_ONCE(vblank->enabled)) {
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
@ -1537,7 +1541,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
|||
vblwait->request.sequence);
|
||||
|
||||
e->event.sequence = vblwait->request.sequence;
|
||||
if ((seq - vblwait->request.sequence) <= (1 << 23)) {
|
||||
if (vblank_passed(seq, vblwait->request.sequence)) {
|
||||
drm_vblank_put(dev, pipe);
|
||||
send_vblank_event(dev, e, seq, &now);
|
||||
vblwait->reply.sequence = seq;
|
||||
|
@ -1559,6 +1563,17 @@ err_put:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
|
||||
{
|
||||
if (vblwait->request.sequence)
|
||||
return false;
|
||||
|
||||
return _DRM_VBLANK_RELATIVE ==
|
||||
(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
|
||||
_DRM_VBLANK_EVENT |
|
||||
_DRM_VBLANK_NEXTONMISS));
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for VBLANK.
|
||||
*
|
||||
|
@ -1608,6 +1623,21 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
|||
|
||||
vblank = &dev->vblank[pipe];
|
||||
|
||||
/* If the counter is currently enabled and accurate, short-circuit
|
||||
* queries to return the cached timestamp of the last vblank.
|
||||
*/
|
||||
if (dev->vblank_disable_immediate &&
|
||||
drm_wait_vblank_is_query(vblwait) &&
|
||||
READ_ONCE(vblank->enabled)) {
|
||||
struct timeval now;
|
||||
|
||||
vblwait->reply.sequence =
|
||||
drm_vblank_count_and_time(dev, pipe, &now);
|
||||
vblwait->reply.tval_sec = now.tv_sec;
|
||||
vblwait->reply.tval_usec = now.tv_usec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (ret) {
|
||||
DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
|
||||
|
@ -1627,9 +1657,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
|
||||
(seq - vblwait->request.sequence) <= (1 << 23)) {
|
||||
vblank_passed(seq, vblwait->request.sequence))
|
||||
vblwait->request.sequence = seq + 1;
|
||||
}
|
||||
|
||||
if (flags & _DRM_VBLANK_EVENT) {
|
||||
/* must hold on to the vblank ref until the event fires
|
||||
|
@ -1642,10 +1671,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
|||
DRM_DEBUG("waiting on vblank count %u, crtc %u\n",
|
||||
vblwait->request.sequence, pipe);
|
||||
DRM_WAIT_ON(ret, vblank->queue, 3 * HZ,
|
||||
(((drm_vblank_count(dev, pipe) -
|
||||
vblwait->request.sequence) <= (1 << 23)) ||
|
||||
!vblank->enabled ||
|
||||
!dev->irq_enabled));
|
||||
vblank_passed(drm_vblank_count(dev, pipe),
|
||||
vblwait->request.sequence) ||
|
||||
!READ_ONCE(vblank->enabled));
|
||||
}
|
||||
|
||||
if (ret != -EINTR) {
|
||||
|
@ -1679,7 +1707,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
|
|||
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||
if (e->pipe != pipe)
|
||||
continue;
|
||||
if ((seq - e->event.sequence) > (1<<23))
|
||||
if (!vblank_passed(seq, e->event.sequence))
|
||||
continue;
|
||||
|
||||
DRM_DEBUG("vblank event on %u, current %u\n",
|
||||
|
@ -1707,6 +1735,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
bool disable_irq;
|
||||
|
||||
if (WARN_ON_ONCE(!dev->num_crtcs))
|
||||
return false;
|
||||
|
@ -1734,20 +1763,23 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
spin_unlock(&dev->vblank_time_lock);
|
||||
|
||||
wake_up(&vblank->queue);
|
||||
drm_handle_vblank_events(dev, pipe);
|
||||
|
||||
/* With instant-off, we defer disabling the interrupt until after
|
||||
* we finish processing the following vblank. The disable has to
|
||||
* be last (after drm_handle_vblank_events) so that the timestamp
|
||||
* is always accurate.
|
||||
* we finish processing the following vblank after all events have
|
||||
* been signaled. The disable has to be last (after
|
||||
* drm_handle_vblank_events) so that the timestamp is always accurate.
|
||||
*/
|
||||
if (dev->vblank_disable_immediate &&
|
||||
drm_vblank_offdelay > 0 &&
|
||||
!atomic_read(&vblank->refcount))
|
||||
vblank_disable_fn((unsigned long)vblank);
|
||||
disable_irq = (dev->vblank_disable_immediate &&
|
||||
drm_vblank_offdelay > 0 &&
|
||||
!atomic_read(&vblank->refcount));
|
||||
|
||||
drm_handle_vblank_events(dev, pipe);
|
||||
|
||||
spin_unlock_irqrestore(&dev->event_lock, irqflags);
|
||||
|
||||
if (disable_irq)
|
||||
vblank_disable_fn((unsigned long)vblank);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_handle_vblank);
|
||||
|
|
|
@ -78,7 +78,7 @@ void drm_helper_mode_fill_fb_struct(struct drm_device *dev,
|
|||
int i;
|
||||
|
||||
fb->dev = dev;
|
||||
fb->format = drm_format_info(mode_cmd->pixel_format);
|
||||
fb->format = drm_get_format_info(dev, mode_cmd);
|
||||
fb->width = mode_cmd->width;
|
||||
fb->height = mode_cmd->height;
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
|
|
@ -277,6 +277,12 @@ EXPORT_SYMBOL(drm_plane_from_index);
|
|||
*
|
||||
* Used when the plane's current framebuffer is destroyed,
|
||||
* and when restoring fbdev mode.
|
||||
*
|
||||
* Note that this function is not suitable for atomic drivers, since it doesn't
|
||||
* wire through the lock acquisition context properly and hence can't handle
|
||||
* retries or driver private locks. You probably want to use
|
||||
* drm_atomic_helper_disable_plane() or
|
||||
* drm_atomic_helper_disable_planes_on_crtc() instead.
|
||||
*/
|
||||
void drm_plane_force_disable(struct drm_plane *plane)
|
||||
{
|
||||
|
@ -285,8 +291,10 @@ void drm_plane_force_disable(struct drm_plane *plane)
|
|||
if (!plane->fb)
|
||||
return;
|
||||
|
||||
WARN_ON(drm_drv_uses_atomic_modeset(plane->dev));
|
||||
|
||||
plane->old_fb = plane->fb;
|
||||
ret = plane->funcs->disable_plane(plane);
|
||||
ret = plane->funcs->disable_plane(plane, NULL);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to disable plane with busy fb\n");
|
||||
plane->old_fb = NULL;
|
||||
|
@ -457,14 +465,15 @@ static int __setplane_internal(struct drm_plane *plane,
|
|||
uint32_t crtc_w, uint32_t crtc_h,
|
||||
/* src_{x,y,w,h} values are 16.16 fixed point */
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* No fb means shut it down */
|
||||
if (!fb) {
|
||||
plane->old_fb = plane->fb;
|
||||
ret = plane->funcs->disable_plane(plane);
|
||||
ret = plane->funcs->disable_plane(plane, ctx);
|
||||
if (!ret) {
|
||||
plane->crtc = NULL;
|
||||
plane->fb = NULL;
|
||||
|
@ -509,7 +518,7 @@ static int __setplane_internal(struct drm_plane *plane,
|
|||
plane->old_fb = plane->fb;
|
||||
ret = plane->funcs->update_plane(plane, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h);
|
||||
src_x, src_y, src_w, src_h, ctx);
|
||||
if (!ret) {
|
||||
plane->crtc = crtc;
|
||||
plane->fb = fb;
|
||||
|
@ -537,13 +546,25 @@ static int setplane_internal(struct drm_plane *plane,
|
|||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
{
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret;
|
||||
|
||||
drm_modeset_lock_all(plane->dev);
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
retry:
|
||||
ret = drm_modeset_lock_all_ctx(plane->dev, &ctx);
|
||||
if (ret)
|
||||
goto fail;
|
||||
ret = __setplane_internal(plane, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h);
|
||||
drm_modeset_unlock_all(plane->dev);
|
||||
src_x, src_y, src_w, src_h, &ctx);
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -613,11 +634,21 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
|
|||
int32_t crtc_x, crtc_y;
|
||||
uint32_t crtc_w = 0, crtc_h = 0;
|
||||
uint32_t src_w = 0, src_h = 0;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(!crtc->cursor);
|
||||
WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
retry:
|
||||
ret = drm_modeset_lock(&crtc->mutex, &ctx);
|
||||
if (ret)
|
||||
goto fail;
|
||||
ret = drm_modeset_lock(&crtc->cursor->mutex, &ctx);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Obtain fb we'll be using (either new or existing) and take an extra
|
||||
* reference to it if fb != null. setplane will take care of dropping
|
||||
|
@ -662,7 +693,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
|
|||
*/
|
||||
ret = __setplane_internal(crtc->cursor, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
0, 0, src_w, src_h);
|
||||
0, 0, src_w, src_h, &ctx);
|
||||
|
||||
/* Update successful; save new cursor position, if necessary */
|
||||
if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
|
||||
|
@ -670,6 +701,15 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
|
|||
crtc->cursor_y = req->y;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -696,12 +736,10 @@ static int drm_mode_cursor_common(struct drm_device *dev,
|
|||
* If this crtc has a universal cursor plane, call that plane's update
|
||||
* handler rather than using legacy cursor handlers.
|
||||
*/
|
||||
drm_modeset_lock_crtc(crtc, crtc->cursor);
|
||||
if (crtc->cursor) {
|
||||
ret = drm_mode_cursor_universal(crtc, req, file_priv);
|
||||
goto out;
|
||||
}
|
||||
if (crtc->cursor)
|
||||
return drm_mode_cursor_universal(crtc, req, file_priv);
|
||||
|
||||
drm_modeset_lock_crtc(crtc, crtc->cursor);
|
||||
if (req->flags & DRM_MODE_CURSOR_BO) {
|
||||
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
|
||||
ret = -ENXIO;
|
||||
|
@ -765,6 +803,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||
struct drm_framebuffer *fb = NULL;
|
||||
struct drm_pending_vblank_event *e = NULL;
|
||||
u32 target_vblank = page_flip->sequence;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
|
@ -828,7 +867,15 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
drm_modeset_lock_crtc(crtc, crtc->primary);
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
retry:
|
||||
ret = drm_modeset_lock(&crtc->mutex, &ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
ret = drm_modeset_lock(&crtc->primary->mutex, &ctx);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (crtc->primary->fb == NULL) {
|
||||
/* The framebuffer is currently unbound, presumably
|
||||
* due to a hotplug event, that userspace has not
|
||||
|
@ -876,6 +923,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||
ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
|
||||
if (ret) {
|
||||
kfree(e);
|
||||
e = NULL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -884,9 +932,11 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
|
|||
if (crtc->funcs->page_flip_target)
|
||||
ret = crtc->funcs->page_flip_target(crtc, fb, e,
|
||||
page_flip->flags,
|
||||
target_vblank);
|
||||
target_vblank,
|
||||
&ctx);
|
||||
else
|
||||
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
|
||||
ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags,
|
||||
&ctx);
|
||||
if (ret) {
|
||||
if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
|
||||
drm_event_cancel_free(dev, &e->base);
|
||||
|
@ -906,7 +956,14 @@ out:
|
|||
if (crtc->primary->old_fb)
|
||||
drm_framebuffer_put(crtc->primary->old_fb);
|
||||
crtc->primary->old_fb = NULL;
|
||||
drm_modeset_unlock_crtc(crtc);
|
||||
|
||||
if (ret == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -275,6 +275,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_update);
|
|||
* @src_y: y offset of @fb for panning
|
||||
* @src_w: width of source rectangle in @fb
|
||||
* @src_h: height of source rectangle in @fb
|
||||
* @ctx: lock acquire context, not used here
|
||||
*
|
||||
* Provides a default plane update handler for primary planes. This is handler
|
||||
* is called in response to a userspace SetPlane operation on the plane with a
|
||||
|
@ -303,7 +304,8 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_mode_set set = {
|
||||
.crtc = crtc,
|
||||
|
@ -347,7 +349,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
* provides their own disable function, this will just
|
||||
* wind up returning -EINVAL to userspace.
|
||||
*/
|
||||
return plane->funcs->disable_plane(plane);
|
||||
return plane->funcs->disable_plane(plane, ctx);
|
||||
|
||||
/* Find current connectors for CRTC */
|
||||
num_connectors = get_connectors_for_crtc(crtc, NULL, 0);
|
||||
|
@ -369,7 +371,7 @@ int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
* drm_mode_setplane() already handles the basic refcounting for the
|
||||
* framebuffers involved in this operation.
|
||||
*/
|
||||
ret = crtc->funcs->set_config(&set);
|
||||
ret = crtc->funcs->set_config(&set, ctx);
|
||||
|
||||
kfree(connector_list);
|
||||
return ret;
|
||||
|
@ -396,7 +398,8 @@ EXPORT_SYMBOL(drm_primary_helper_update);
|
|||
* RETURNS:
|
||||
* Unconditionally returns -EINVAL.
|
||||
*/
|
||||
int drm_primary_helper_disable(struct drm_plane *plane)
|
||||
int drm_primary_helper_disable(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *pstate)
|
||||
struct drm_plane_state *old_pstate)
|
||||
{
|
||||
struct drm_simple_display_pipe *pipe;
|
||||
|
||||
|
@ -122,7 +122,7 @@ static void drm_simple_kms_plane_atomic_update(struct drm_plane *plane,
|
|||
if (!pipe->funcs || !pipe->funcs->update)
|
||||
return;
|
||||
|
||||
pipe->funcs->update(pipe, pstate);
|
||||
pipe->funcs->update(pipe, old_pstate);
|
||||
}
|
||||
|
||||
static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane,
|
||||
|
|
|
@ -514,17 +514,18 @@ void gma_crtc_destroy(struct drm_crtc *crtc)
|
|||
kfree(gma_crtc);
|
||||
}
|
||||
|
||||
int gma_crtc_set_config(struct drm_mode_set *set)
|
||||
int gma_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev = set->crtc->dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv->rpm_enabled)
|
||||
return drm_crtc_helper_set_config(set);
|
||||
return drm_crtc_helper_set_config(set, ctx);
|
||||
|
||||
pm_runtime_forbid(&dev->pdev->dev);
|
||||
ret = drm_crtc_helper_set_config(set);
|
||||
ret = drm_crtc_helper_set_config(set, ctx);
|
||||
pm_runtime_allow(&dev->pdev->dev);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -79,7 +79,8 @@ extern void gma_crtc_prepare(struct drm_crtc *crtc);
|
|||
extern void gma_crtc_commit(struct drm_crtc *crtc);
|
||||
extern void gma_crtc_disable(struct drm_crtc *crtc);
|
||||
extern void gma_crtc_destroy(struct drm_crtc *crtc);
|
||||
extern int gma_crtc_set_config(struct drm_mode_set *set);
|
||||
extern int gma_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
extern void gma_crtc_save(struct drm_crtc *crtc);
|
||||
extern void gma_crtc_restore(struct drm_crtc *crtc);
|
||||
|
|
|
@ -1307,8 +1307,6 @@ void i915_driver_unload(struct drm_device *dev)
|
|||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct pci_dev *pdev = dev_priv->drm.pdev;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int ret;
|
||||
|
||||
intel_fbdev_fini(dev);
|
||||
|
||||
|
@ -1317,23 +1315,7 @@ void i915_driver_unload(struct drm_device *dev)
|
|||
|
||||
intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
while (1) {
|
||||
ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (!ret)
|
||||
ret = drm_atomic_helper_disable_all(dev, &ctx);
|
||||
|
||||
if (ret != -EDEADLK)
|
||||
break;
|
||||
|
||||
drm_modeset_backoff(&ctx);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret);
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
|
||||
intel_gvt_cleanup(dev_priv);
|
||||
|
||||
|
|
|
@ -13426,7 +13426,8 @@ intel_legacy_cursor_update(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(crtc->dev);
|
||||
int ret;
|
||||
|
@ -13539,7 +13540,7 @@ out_free:
|
|||
slow:
|
||||
return drm_atomic_helper_update_plane(plane, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h);
|
||||
src_x, src_y, src_w, src_h, ctx);
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs intel_cursor_plane_funcs = {
|
||||
|
|
|
@ -149,7 +149,6 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
|
|||
to_intel_connector(conn_state->connector);
|
||||
int ret;
|
||||
uint32_t temp;
|
||||
int slots;
|
||||
|
||||
/* MST encoders are bound to a crtc, not to a connector,
|
||||
* force the mapping here for get_hw_state.
|
||||
|
@ -165,7 +164,8 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder,
|
|||
|
||||
ret = drm_dp_mst_allocate_vcpi(&intel_dp->mst_mgr,
|
||||
connector->port,
|
||||
pipe_config->pbn, &slots);
|
||||
pipe_config->pbn,
|
||||
pipe_config->dp_m_n.tu);
|
||||
if (ret == false) {
|
||||
DRM_ERROR("failed to allocate vcpi\n");
|
||||
return;
|
||||
|
|
|
@ -37,7 +37,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
static void set_scanout_locked(struct drm_plane *plane,
|
||||
struct drm_framebuffer *fb);
|
||||
|
@ -886,7 +887,8 @@ static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_plane_state *plane_state, *new_plane_state;
|
||||
struct mdp5_plane_state *mdp5_pstate;
|
||||
|
@ -954,7 +956,7 @@ slow_free:
|
|||
slow:
|
||||
return drm_atomic_helper_update_plane(plane, crtc, fb,
|
||||
crtc_x, crtc_y, crtc_w, crtc_h,
|
||||
src_x, src_y, src_w, src_h);
|
||||
src_x, src_y, src_w, src_h, ctx);
|
||||
}
|
||||
|
||||
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane)
|
||||
|
|
|
@ -1031,8 +1031,9 @@ nv04_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_crtc_set_config(struct drm_mode_set *set)
|
||||
static int
|
||||
nouveau_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct nouveau_drm *drm;
|
||||
|
@ -1049,7 +1050,7 @@ nouveau_crtc_set_config(struct drm_mode_set *set)
|
|||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
|
||||
ret = drm_crtc_helper_set_config(set);
|
||||
ret = drm_crtc_helper_set_config(set, ctx);
|
||||
|
||||
drm = nouveau_drm(dev);
|
||||
|
||||
|
|
|
@ -94,7 +94,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct nouveau_drm *drm = nouveau_drm(plane->dev);
|
||||
struct nvif_object *dev = &drm->client.device.object;
|
||||
|
@ -172,7 +173,8 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
static int
|
||||
nv10_disable_plane(struct drm_plane *plane)
|
||||
nv10_disable_plane(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
|
||||
struct nouveau_plane *nv_plane =
|
||||
|
@ -190,7 +192,7 @@ nv10_disable_plane(struct drm_plane *plane)
|
|||
static void
|
||||
nv_destroy_plane(struct drm_plane *plane)
|
||||
{
|
||||
plane->funcs->disable_plane(plane);
|
||||
drm_plane_force_disable(plane);
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(plane);
|
||||
}
|
||||
|
@ -331,7 +333,7 @@ nv10_overlay_init(struct drm_device *device)
|
|||
|
||||
plane->set_params = nv10_set_params;
|
||||
nv10_set_params(plane);
|
||||
nv10_disable_plane(&plane->base);
|
||||
drm_plane_force_disable(&plane->base);
|
||||
return;
|
||||
cleanup:
|
||||
drm_plane_cleanup(&plane->base);
|
||||
|
@ -345,7 +347,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
|
||||
struct nouveau_plane *nv_plane =
|
||||
|
@ -425,7 +428,8 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
static int
|
||||
nv04_disable_plane(struct drm_plane *plane)
|
||||
nv04_disable_plane(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct nvif_object *dev = &nouveau_drm(plane->dev)->client.device.object;
|
||||
struct nouveau_plane *nv_plane =
|
||||
|
@ -483,7 +487,7 @@ nv04_overlay_init(struct drm_device *device)
|
|||
drm_object_attach_property(&plane->base.base,
|
||||
plane->props.brightness, plane->brightness);
|
||||
|
||||
nv04_disable_plane(&plane->base);
|
||||
drm_plane_force_disable(&plane->base);
|
||||
return;
|
||||
cleanup:
|
||||
drm_plane_cleanup(&plane->base);
|
||||
|
|
|
@ -436,8 +436,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend)
|
|||
struct drm_connector *connector;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (!suspend)
|
||||
drm_crtc_force_disable_all(dev);
|
||||
if (!suspend) {
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
else
|
||||
drm_crtc_force_disable_all(dev);
|
||||
}
|
||||
|
||||
/* Make sure that drm and hw vblank irqs get properly disabled. */
|
||||
drm_for_each_crtc(crtc, dev)
|
||||
|
@ -788,7 +792,8 @@ fail:
|
|||
|
||||
int
|
||||
nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event, u32 flags)
|
||||
struct drm_pending_vblank_event *event, u32 flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
const int swap_interval = (flags & DRM_MODE_PAGE_FLIP_ASYNC) ? 0 : 1;
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
|
|
@ -76,7 +76,8 @@ int nouveau_display_vblstamp(struct drm_device *, unsigned int, int *,
|
|||
|
||||
int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags);
|
||||
uint32_t page_flip_flags,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int nouveau_finish_page_flip(struct nouveau_channel *,
|
||||
struct nouveau_page_flip_state *);
|
||||
|
||||
|
@ -87,7 +88,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
|
|||
|
||||
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
|
||||
|
||||
int nouveau_crtc_set_config(struct drm_mode_set *set);
|
||||
#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
|
||||
extern int nouveau_backlight_init(struct drm_device *);
|
||||
extern void nouveau_backlight_exit(struct drm_device *);
|
||||
|
|
|
@ -95,6 +95,10 @@ nouveau_vga_init(struct nouveau_drm *drm)
|
|||
|
||||
vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
|
||||
|
||||
/* don't register Thunderbolt eGPU with vga_switcheroo */
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
|
@ -111,6 +115,11 @@ nouveau_vga_fini(struct nouveau_drm *drm)
|
|||
struct drm_device *dev = drm->dev;
|
||||
bool runtime = false;
|
||||
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
|
||||
if (pci_is_thunderbolt_attached(dev->pdev))
|
||||
return;
|
||||
|
||||
if (nouveau_runtime_pm == 1)
|
||||
runtime = true;
|
||||
if ((nouveau_runtime_pm == -1) && (nouveau_is_optimus() || nouveau_is_v1_dsm()))
|
||||
|
@ -119,7 +128,6 @@ nouveau_vga_fini(struct nouveau_drm *drm)
|
|||
vga_switcheroo_unregister_client(dev->pdev);
|
||||
if (runtime && nouveau_is_v1_dsm() && !nouveau_is_optimus())
|
||||
vga_switcheroo_fini_domain_pm_ops(drm->dev->dev);
|
||||
vga_client_register(dev->pdev, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2895,7 +2895,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
|
|||
if (WARN_ON(!mstc))
|
||||
return;
|
||||
|
||||
r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, &slots);
|
||||
slots = drm_dp_find_vcpi_slots(&mstm->mgr, mstc->pbn);
|
||||
r = drm_dp_mst_allocate_vcpi(&mstm->mgr, mstc->port, mstc->pbn, slots);
|
||||
WARN_ON(!r);
|
||||
|
||||
if (mstm->outp->dcb->sorconf.link & 1)
|
||||
|
|
|
@ -1468,7 +1468,9 @@ int radeon_device_init(struct radeon_device *rdev,
|
|||
|
||||
if (rdev->flags & RADEON_IS_PX)
|
||||
runtime = true;
|
||||
vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime);
|
||||
if (!pci_is_thunderbolt_attached(rdev->pdev))
|
||||
vga_switcheroo_register_client(rdev->pdev,
|
||||
&radeon_switcheroo_ops, runtime);
|
||||
if (runtime)
|
||||
vga_switcheroo_init_domain_pm_ops(rdev->dev, &rdev->vga_pm_domain);
|
||||
|
||||
|
@ -1561,7 +1563,8 @@ void radeon_device_fini(struct radeon_device *rdev)
|
|||
/* evict vram memory */
|
||||
radeon_bo_evict_vram(rdev);
|
||||
radeon_fini(rdev);
|
||||
vga_switcheroo_unregister_client(rdev->pdev);
|
||||
if (!pci_is_thunderbolt_attached(rdev->pdev))
|
||||
vga_switcheroo_unregister_client(rdev->pdev);
|
||||
if (rdev->flags & RADEON_IS_PX)
|
||||
vga_switcheroo_fini_domain_pm_ops(rdev->dev);
|
||||
vga_client_register(rdev->pdev, NULL, NULL, NULL);
|
||||
|
|
|
@ -485,7 +485,8 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags,
|
||||
uint32_t target)
|
||||
uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct radeon_device *rdev = dev->dev_private;
|
||||
|
@ -623,7 +624,8 @@ cleanup:
|
|||
}
|
||||
|
||||
static int
|
||||
radeon_crtc_set_config(struct drm_mode_set *set)
|
||||
radeon_crtc_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
struct radeon_device *rdev;
|
||||
|
@ -640,7 +642,7 @@ radeon_crtc_set_config(struct drm_mode_set *set)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = drm_crtc_helper_set_config(set);
|
||||
ret = drm_crtc_helper_set_config(set, ctx);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
|
||||
if (crtc->enabled)
|
||||
|
|
|
@ -453,9 +453,11 @@ radeon_mst_encoder_dpms(struct drm_encoder *encoder, int mode)
|
|||
DRM_DEBUG_KMS("dig encoder is %d %d %d\n", dig_enc->dig_encoder,
|
||||
dig_enc->linkb, radeon_crtc->crtc_id);
|
||||
|
||||
slots = drm_dp_find_vcpi_slots(&radeon_connector->mst_port->mst_mgr,
|
||||
mst_enc->pbn);
|
||||
ret = drm_dp_mst_allocate_vcpi(&radeon_connector->mst_port->mst_mgr,
|
||||
radeon_connector->port,
|
||||
mst_enc->pbn, &slots);
|
||||
mst_enc->pbn, slots);
|
||||
ret = drm_dp_update_payload_part1(&radeon_connector->mst_port->mst_mgr);
|
||||
|
||||
radeon_dp_mst_set_be_cntl(primary, mst_enc,
|
||||
|
|
|
@ -115,7 +115,8 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
|
|||
|
||||
if ((radeon_runtime_pm != 0) &&
|
||||
radeon_has_atpx() &&
|
||||
((flags & RADEON_IS_IGP) == 0))
|
||||
((flags & RADEON_IS_IGP) == 0) &&
|
||||
!pci_is_thunderbolt_attached(rdev->pdev))
|
||||
flags |= RADEON_IS_PX;
|
||||
|
||||
/* radeon_device_init should report only fatal error
|
||||
|
|
|
@ -13,7 +13,7 @@ config DRM_ROCKCHIP
|
|||
IP found on the SoC.
|
||||
|
||||
config ROCKCHIP_ANALOGIX_DP
|
||||
tristate "Rockchip specific extensions for Analogix DP driver"
|
||||
bool "Rockchip specific extensions for Analogix DP driver"
|
||||
depends on DRM_ROCKCHIP
|
||||
select DRM_ANALOGIX_DP
|
||||
help
|
||||
|
@ -22,7 +22,7 @@ config ROCKCHIP_ANALOGIX_DP
|
|||
on RK3288 based SoC, you should selet this option.
|
||||
|
||||
config ROCKCHIP_CDN_DP
|
||||
tristate "Rockchip cdn DP"
|
||||
bool "Rockchip cdn DP"
|
||||
depends on DRM_ROCKCHIP
|
||||
depends on EXTCON
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
|
@ -33,7 +33,7 @@ config ROCKCHIP_CDN_DP
|
|||
option.
|
||||
|
||||
config ROCKCHIP_DW_HDMI
|
||||
tristate "Rockchip specific extensions for Synopsys DW HDMI"
|
||||
bool "Rockchip specific extensions for Synopsys DW HDMI"
|
||||
depends on DRM_ROCKCHIP
|
||||
select DRM_DW_HDMI
|
||||
help
|
||||
|
@ -43,7 +43,7 @@ config ROCKCHIP_DW_HDMI
|
|||
option.
|
||||
|
||||
config ROCKCHIP_DW_MIPI_DSI
|
||||
tristate "Rockchip specific extensions for Synopsys DW MIPI DSI"
|
||||
bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
|
||||
depends on DRM_ROCKCHIP
|
||||
select DRM_MIPI_DSI
|
||||
help
|
||||
|
@ -53,7 +53,7 @@ config ROCKCHIP_DW_MIPI_DSI
|
|||
option.
|
||||
|
||||
config ROCKCHIP_INNO_HDMI
|
||||
tristate "Rockchip specific extensions for Innosilicon HDMI"
|
||||
bool "Rockchip specific extensions for Innosilicon HDMI"
|
||||
depends on DRM_ROCKCHIP
|
||||
help
|
||||
This selects support for Rockchip SoC specific extensions
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \
|
||||
rockchip_drm_gem.o rockchip_drm_psr.o rockchip_drm_vop.o
|
||||
rockchip_drm_gem.o rockchip_drm_psr.o \
|
||||
rockchip_drm_vop.o rockchip_vop_reg.o
|
||||
rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o
|
||||
|
||||
obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
|
||||
obj-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp.o
|
||||
cdn-dp-objs := cdn-dp-core.o cdn-dp-reg.o
|
||||
obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
|
||||
obj-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
|
||||
obj-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi.o
|
||||
rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
|
||||
|
||||
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_vop_reg.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o
|
||||
|
|
|
@ -507,7 +507,7 @@ static const struct of_device_id rockchip_dp_dt_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
|
||||
|
||||
static struct platform_driver rockchip_dp_driver = {
|
||||
struct platform_driver rockchip_dp_driver = {
|
||||
.probe = rockchip_dp_probe,
|
||||
.remove = rockchip_dp_remove,
|
||||
.driver = {
|
||||
|
@ -516,10 +516,3 @@ static struct platform_driver rockchip_dp_driver = {
|
|||
.of_match_table = of_match_ptr(rockchip_dp_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rockchip_dp_driver);
|
||||
|
||||
MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
|
||||
MODULE_AUTHOR("Jeff chen <jeff.chen@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -1244,7 +1244,7 @@ static const struct dev_pm_ops cdn_dp_pm_ops = {
|
|||
cdn_dp_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver cdn_dp_driver = {
|
||||
struct platform_driver cdn_dp_driver = {
|
||||
.probe = cdn_dp_probe,
|
||||
.remove = cdn_dp_remove,
|
||||
.shutdown = cdn_dp_shutdown,
|
||||
|
@ -1255,9 +1255,3 @@ static struct platform_driver cdn_dp_driver = {
|
|||
.pm = &cdn_dp_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(cdn_dp_driver);
|
||||
|
||||
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("cdn DP Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#define RK3288_DSI0_SEL_VOP_LIT BIT(6)
|
||||
#define RK3288_DSI1_SEL_VOP_LIT BIT(9)
|
||||
|
||||
#define RK3399_GRF_SOC_CON19 0x6250
|
||||
#define RK3399_GRF_SOC_CON20 0x6250
|
||||
#define RK3399_DSI0_SEL_VOP_LIT BIT(0)
|
||||
#define RK3399_DSI1_SEL_VOP_LIT BIT(4)
|
||||
|
||||
|
@ -251,6 +251,9 @@
|
|||
#define THS_PRE_PROGRAM_EN BIT(7)
|
||||
#define THS_ZERO_PROGRAM_EN BIT(6)
|
||||
|
||||
#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0)
|
||||
#define DW_MIPI_NEEDS_GRF_CLK BIT(1)
|
||||
|
||||
enum {
|
||||
BANDGAP_97_07,
|
||||
BANDGAP_98_05,
|
||||
|
@ -279,6 +282,7 @@ struct dw_mipi_dsi_plat_data {
|
|||
u32 grf_switch_reg;
|
||||
u32 grf_dsi0_mode;
|
||||
u32 grf_dsi0_mode_reg;
|
||||
unsigned int flags;
|
||||
unsigned int max_data_lanes;
|
||||
};
|
||||
|
||||
|
@ -291,6 +295,7 @@ struct dw_mipi_dsi {
|
|||
struct regmap *grf_regmap;
|
||||
void __iomem *base;
|
||||
|
||||
struct clk *grf_clk;
|
||||
struct clk *pllref_clk;
|
||||
struct clk *pclk;
|
||||
struct clk *phy_cfg_clk;
|
||||
|
@ -979,6 +984,17 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
|
|||
dw_mipi_dsi_dphy_interface_config(dsi);
|
||||
dw_mipi_dsi_clear_err(dsi);
|
||||
|
||||
/*
|
||||
* For the RK3399, the clk of grf must be enabled before writing grf
|
||||
* register. And for RK3288 or other soc, this grf_clk must be NULL,
|
||||
* the clk_prepare_enable return true directly.
|
||||
*/
|
||||
ret = clk_prepare_enable(dsi->grf_clk);
|
||||
if (ret) {
|
||||
dev_err(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pdata->grf_dsi0_mode_reg)
|
||||
regmap_write(dsi->grf_regmap, pdata->grf_dsi0_mode_reg,
|
||||
pdata->grf_dsi0_mode);
|
||||
|
@ -1003,6 +1019,8 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder)
|
|||
regmap_write(dsi->grf_regmap, pdata->grf_switch_reg, val);
|
||||
dev_dbg(dsi->dev, "vop %s output to dsi0\n", (mux) ? "LIT" : "BIG");
|
||||
dsi->dpms_mode = DRM_MODE_DPMS_ON;
|
||||
|
||||
clk_disable_unprepare(dsi->grf_clk);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1133,9 +1151,10 @@ static struct dw_mipi_dsi_plat_data rk3288_mipi_dsi_drv_data = {
|
|||
static struct dw_mipi_dsi_plat_data rk3399_mipi_dsi_drv_data = {
|
||||
.dsi0_en_bit = RK3399_DSI0_SEL_VOP_LIT,
|
||||
.dsi1_en_bit = RK3399_DSI1_SEL_VOP_LIT,
|
||||
.grf_switch_reg = RK3399_GRF_SOC_CON19,
|
||||
.grf_switch_reg = RK3399_GRF_SOC_CON20,
|
||||
.grf_dsi0_mode = RK3399_GRF_DSI_MODE,
|
||||
.grf_dsi0_mode_reg = RK3399_GRF_SOC_CON22,
|
||||
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
|
||||
.max_data_lanes = 4,
|
||||
};
|
||||
|
||||
|
@ -1227,15 +1246,22 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
|
|||
clk_disable_unprepare(dsi->pclk);
|
||||
}
|
||||
|
||||
dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
|
||||
if (IS_ERR(dsi->phy_cfg_clk)) {
|
||||
ret = PTR_ERR(dsi->phy_cfg_clk);
|
||||
if (ret != -ENOENT) {
|
||||
if (pdata->flags & DW_MIPI_NEEDS_PHY_CFG_CLK) {
|
||||
dsi->phy_cfg_clk = devm_clk_get(dev, "phy_cfg");
|
||||
if (IS_ERR(dsi->phy_cfg_clk)) {
|
||||
ret = PTR_ERR(dsi->phy_cfg_clk);
|
||||
dev_err(dev, "Unable to get phy_cfg_clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
dsi->phy_cfg_clk = NULL;
|
||||
dev_dbg(dev, "have not phy_cfg_clk\n");
|
||||
}
|
||||
|
||||
if (pdata->flags & DW_MIPI_NEEDS_GRF_CLK) {
|
||||
dsi->grf_clk = devm_clk_get(dev, "grf");
|
||||
if (IS_ERR(dsi->grf_clk)) {
|
||||
ret = PTR_ERR(dsi->grf_clk);
|
||||
dev_err(dev, "Unable to get grf_clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->pllref_clk);
|
||||
|
@ -1304,7 +1330,7 @@ static int dw_mipi_dsi_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver dw_mipi_dsi_driver = {
|
||||
struct platform_driver dw_mipi_dsi_driver = {
|
||||
.probe = dw_mipi_dsi_probe,
|
||||
.remove = dw_mipi_dsi_remove,
|
||||
.driver = {
|
||||
|
@ -1312,9 +1338,3 @@ static struct platform_driver dw_mipi_dsi_driver = {
|
|||
.name = DRIVER_NAME,
|
||||
},
|
||||
};
|
||||
module_platform_driver(dw_mipi_dsi_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ROCKCHIP MIPI DSI host controller driver");
|
||||
MODULE_AUTHOR("Chris Zhong <zyw@rock-chips.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
|
|
|
@ -325,7 +325,7 @@ static int dw_hdmi_rockchip_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
|
||||
struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
|
||||
.probe = dw_hdmi_rockchip_probe,
|
||||
.remove = dw_hdmi_rockchip_remove,
|
||||
.driver = {
|
||||
|
@ -333,11 +333,3 @@ static struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
|
|||
.of_match_table = dw_hdmi_rockchip_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(dw_hdmi_rockchip_pltfm_driver);
|
||||
|
||||
MODULE_AUTHOR("Andy Yan <andy.yan@rock-chips.com>");
|
||||
MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Rockchip Specific DW-HDMI Driver Extension");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:dwhdmi-rockchip");
|
||||
|
|
|
@ -923,7 +923,7 @@ static const struct of_device_id inno_hdmi_dt_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
|
||||
|
||||
static struct platform_driver inno_hdmi_driver = {
|
||||
struct platform_driver inno_hdmi_driver = {
|
||||
.probe = inno_hdmi_probe,
|
||||
.remove = inno_hdmi_remove,
|
||||
.driver = {
|
||||
|
@ -931,11 +931,3 @@ static struct platform_driver inno_hdmi_driver = {
|
|||
.of_match_table = inno_hdmi_dt_ids,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(inno_hdmi_driver);
|
||||
|
||||
MODULE_AUTHOR("Zheng Yang <zhengyang@rock-chips.com>");
|
||||
MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("Rockchip Specific INNO-HDMI Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:innohdmi-rockchip");
|
||||
|
|
|
@ -304,34 +304,37 @@ static const struct dev_pm_ops rockchip_drm_pm_ops = {
|
|||
rockchip_drm_sys_resume)
|
||||
};
|
||||
|
||||
static int compare_of(struct device *dev, void *data)
|
||||
{
|
||||
struct device_node *np = data;
|
||||
#define MAX_ROCKCHIP_SUB_DRIVERS 16
|
||||
static struct platform_driver *rockchip_sub_drivers[MAX_ROCKCHIP_SUB_DRIVERS];
|
||||
static int num_rockchip_sub_drivers;
|
||||
|
||||
return dev->of_node == np;
|
||||
static int compare_dev(struct device *dev, void *data)
|
||||
{
|
||||
return dev == (struct device *)data;
|
||||
}
|
||||
|
||||
static void rockchip_add_endpoints(struct device *dev,
|
||||
struct component_match **match,
|
||||
struct device_node *port)
|
||||
static struct component_match *rockchip_drm_match_add(struct device *dev)
|
||||
{
|
||||
struct device_node *ep, *remote;
|
||||
struct component_match *match = NULL;
|
||||
int i;
|
||||
|
||||
for_each_child_of_node(port, ep) {
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
if (!remote || !of_device_is_available(remote)) {
|
||||
of_node_put(remote);
|
||||
continue;
|
||||
} else if (!of_device_is_available(remote->parent)) {
|
||||
dev_warn(dev, "parent device of %s is not available\n",
|
||||
remote->full_name);
|
||||
of_node_put(remote);
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < num_rockchip_sub_drivers; i++) {
|
||||
struct platform_driver *drv = rockchip_sub_drivers[i];
|
||||
struct device *p = NULL, *d;
|
||||
|
||||
drm_of_component_match_add(dev, match, compare_of, remote);
|
||||
of_node_put(remote);
|
||||
do {
|
||||
d = bus_find_device(&platform_bus_type, p, &drv->driver,
|
||||
(void *)platform_bus_type.match);
|
||||
put_device(p);
|
||||
p = d;
|
||||
|
||||
if (!d)
|
||||
break;
|
||||
component_match_add(dev, &match, compare_dev, d);
|
||||
} while (true);
|
||||
}
|
||||
|
||||
return match ?: ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
static const struct component_master_ops rockchip_drm_ops = {
|
||||
|
@ -339,21 +342,16 @@ static const struct component_master_ops rockchip_drm_ops = {
|
|||
.unbind = rockchip_drm_unbind,
|
||||
};
|
||||
|
||||
static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
||||
static int rockchip_drm_platform_of_probe(struct device *dev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct component_match *match = NULL;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *port;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Bind the crtc ports first, so that
|
||||
* drm_of_find_possible_crtcs called from encoder .bind callbacks
|
||||
* works as expected.
|
||||
*/
|
||||
|
||||
for (i = 0;; i++) {
|
||||
struct device_node *iommu;
|
||||
|
||||
|
@ -377,9 +375,9 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
|||
is_support_iommu = false;
|
||||
}
|
||||
|
||||
found = true;
|
||||
|
||||
of_node_put(iommu);
|
||||
drm_of_component_match_add(dev, &match, compare_of,
|
||||
port->parent);
|
||||
of_node_put(port);
|
||||
}
|
||||
|
||||
|
@ -388,27 +386,27 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
if (!found) {
|
||||
dev_err(dev, "No available vop found for display-subsystem.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
/*
|
||||
* For each bound crtc, bind the encoders attached to its
|
||||
* remote endpoint.
|
||||
*/
|
||||
for (i = 0;; i++) {
|
||||
port = of_parse_phandle(np, "ports", i);
|
||||
if (!port)
|
||||
break;
|
||||
|
||||
if (!of_device_is_available(port->parent)) {
|
||||
of_node_put(port);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
rockchip_add_endpoints(dev, &match, port);
|
||||
of_node_put(port);
|
||||
}
|
||||
static int rockchip_drm_platform_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct component_match *match = NULL;
|
||||
int ret;
|
||||
|
||||
ret = rockchip_drm_platform_of_probe(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
match = rockchip_drm_match_add(dev);
|
||||
if (IS_ERR(match))
|
||||
return PTR_ERR(match);
|
||||
|
||||
return component_master_add_with_match(dev, &rockchip_drm_ops, match);
|
||||
}
|
||||
|
@ -436,7 +434,54 @@ static struct platform_driver rockchip_drm_platform_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
module_platform_driver(rockchip_drm_platform_driver);
|
||||
#define ADD_ROCKCHIP_SUB_DRIVER(drv, cond) { \
|
||||
if (IS_ENABLED(cond) && \
|
||||
!WARN_ON(num_rockchip_sub_drivers >= MAX_ROCKCHIP_SUB_DRIVERS)) \
|
||||
rockchip_sub_drivers[num_rockchip_sub_drivers++] = &drv; \
|
||||
}
|
||||
|
||||
static int __init rockchip_drm_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
num_rockchip_sub_drivers = 0;
|
||||
ADD_ROCKCHIP_SUB_DRIVER(vop_platform_driver, CONFIG_DRM_ROCKCHIP);
|
||||
ADD_ROCKCHIP_SUB_DRIVER(rockchip_dp_driver,
|
||||
CONFIG_ROCKCHIP_ANALOGIX_DP);
|
||||
ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
|
||||
ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
|
||||
CONFIG_ROCKCHIP_DW_HDMI);
|
||||
ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_driver,
|
||||
CONFIG_ROCKCHIP_DW_MIPI_DSI);
|
||||
ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
|
||||
|
||||
ret = platform_register_drivers(rockchip_sub_drivers,
|
||||
num_rockchip_sub_drivers);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = platform_driver_register(&rockchip_drm_platform_driver);
|
||||
if (ret)
|
||||
goto err_unreg_drivers;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unreg_drivers:
|
||||
platform_unregister_drivers(rockchip_sub_drivers,
|
||||
num_rockchip_sub_drivers);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rockchip_drm_fini(void)
|
||||
{
|
||||
platform_driver_unregister(&rockchip_drm_platform_driver);
|
||||
|
||||
platform_unregister_drivers(rockchip_sub_drivers,
|
||||
num_rockchip_sub_drivers);
|
||||
}
|
||||
|
||||
module_init(rockchip_drm_init);
|
||||
module_exit(rockchip_drm_fini);
|
||||
|
||||
MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("ROCKCHIP DRM Driver");
|
||||
|
|
|
@ -65,4 +65,10 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
|
|||
int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num,
|
||||
unsigned int mstimeout);
|
||||
|
||||
extern struct platform_driver cdn_dp_driver;
|
||||
extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
|
||||
extern struct platform_driver dw_mipi_dsi_driver;
|
||||
extern struct platform_driver inno_hdmi_driver;
|
||||
extern struct platform_driver rockchip_dp_driver;
|
||||
extern struct platform_driver vop_platform_driver;
|
||||
#endif /* _ROCKCHIP_DRM_DRV_H_ */
|
||||
|
|
|
@ -404,7 +404,7 @@ static int vop_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver vop_platform_driver = {
|
||||
struct platform_driver vop_platform_driver = {
|
||||
.probe = vop_probe,
|
||||
.remove = vop_remove,
|
||||
.driver = {
|
||||
|
@ -412,9 +412,3 @@ static struct platform_driver vop_platform_driver = {
|
|||
.of_match_table = of_match_ptr(vop_driver_dt_match),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(vop_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Mark Yao <mark.yao@rock-chips.com>");
|
||||
MODULE_DESCRIPTION("ROCKCHIP VOP Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
|
@ -449,7 +449,8 @@ void shmob_drm_crtc_finish_page_flip(struct shmob_drm_crtc *scrtc)
|
|||
static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags)
|
||||
uint32_t page_flip_flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
|
||||
struct drm_device *dev = scrtc->crtc.dev;
|
||||
|
|
|
@ -177,7 +177,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
struct drm_framebuffer *fb, int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct shmob_drm_plane *splane = to_shmob_plane(plane);
|
||||
struct shmob_drm_device *sdev = plane->dev->dev_private;
|
||||
|
@ -208,7 +209,8 @@ shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int shmob_drm_plane_disable(struct drm_plane *plane)
|
||||
static int shmob_drm_plane_disable(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct shmob_drm_plane *splane = to_shmob_plane(plane);
|
||||
struct shmob_drm_device *sdev = plane->dev->dev_private;
|
||||
|
@ -221,7 +223,7 @@ static int shmob_drm_plane_disable(struct drm_plane *plane)
|
|||
|
||||
static void shmob_drm_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
shmob_drm_plane_disable(plane);
|
||||
drm_plane_force_disable(plane);
|
||||
drm_plane_cleanup(plane);
|
||||
}
|
||||
|
||||
|
|
|
@ -1382,7 +1382,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data)
|
|||
struct tegra_dc *dc = node->info_ent->data;
|
||||
int err = 0;
|
||||
|
||||
drm_modeset_lock_crtc(&dc->base, NULL);
|
||||
drm_modeset_lock(&dc->base.mutex, NULL);
|
||||
|
||||
if (!dc->base.state->active) {
|
||||
err = -EBUSY;
|
||||
|
@ -1609,7 +1609,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data)
|
|||
#undef DUMP_REG
|
||||
|
||||
unlock:
|
||||
drm_modeset_unlock_crtc(&dc->base);
|
||||
drm_modeset_unlock(&dc->base.mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1620,7 +1620,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data)
|
|||
int err = 0;
|
||||
u32 value;
|
||||
|
||||
drm_modeset_lock_crtc(&dc->base, NULL);
|
||||
drm_modeset_lock(&dc->base.mutex, NULL);
|
||||
|
||||
if (!dc->base.state->active) {
|
||||
err = -EBUSY;
|
||||
|
@ -1640,7 +1640,7 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data)
|
|||
tegra_dc_writel(dc, 0, DC_COM_CRC_CONTROL);
|
||||
|
||||
unlock:
|
||||
drm_modeset_unlock_crtc(&dc->base);
|
||||
drm_modeset_unlock(&dc->base.mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -579,7 +579,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work)
|
|||
|
||||
dev_info(crtc->dev->dev, "%s: Reset CRTC", __func__);
|
||||
|
||||
drm_modeset_lock_crtc(crtc, NULL);
|
||||
drm_modeset_lock(&crtc->mutex, NULL);
|
||||
|
||||
if (!tilcdc_crtc_is_on(crtc))
|
||||
goto out;
|
||||
|
@ -587,7 +587,7 @@ static void tilcdc_crtc_recover_work(struct work_struct *work)
|
|||
tilcdc_crtc_disable(crtc);
|
||||
tilcdc_crtc_enable(crtc);
|
||||
out:
|
||||
drm_modeset_unlock_crtc(crtc);
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
}
|
||||
|
||||
static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
|
||||
|
@ -595,9 +595,9 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)
|
|||
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
||||
struct tilcdc_drm_private *priv = crtc->dev->dev_private;
|
||||
|
||||
drm_modeset_lock_crtc(crtc, NULL);
|
||||
drm_modeset_lock(&crtc->mutex, NULL);
|
||||
tilcdc_crtc_disable(crtc);
|
||||
drm_modeset_unlock_crtc(crtc);
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
|
||||
flush_workqueue(priv->wq);
|
||||
|
||||
|
@ -856,7 +856,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
|
|||
struct tilcdc_drm_private *priv = dev->dev_private;
|
||||
struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
|
||||
|
||||
drm_modeset_lock_crtc(crtc, NULL);
|
||||
drm_modeset_lock(&crtc->mutex, NULL);
|
||||
if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) {
|
||||
if (tilcdc_crtc_is_on(crtc)) {
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
|
@ -868,7 +868,7 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc)
|
|||
pm_runtime_put_sync(dev->dev);
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_crtc(crtc);
|
||||
drm_modeset_unlock(&crtc->mutex);
|
||||
}
|
||||
|
||||
#define SYNC_LOST_COUNT_LIMIT 50
|
||||
|
|
|
@ -122,21 +122,6 @@ void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object);
|
||||
|
||||
const struct file_operations tinydrm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
.release = drm_release,
|
||||
.unlocked_ioctl = drm_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = drm_compat_ioctl,
|
||||
#endif
|
||||
.poll = drm_poll,
|
||||
.read = drm_read,
|
||||
.llseek = no_llseek,
|
||||
.mmap = drm_gem_cma_mmap,
|
||||
};
|
||||
EXPORT_SYMBOL(tinydrm_fops);
|
||||
|
||||
static struct drm_framebuffer *
|
||||
tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
|
@ -251,7 +236,7 @@ static void tinydrm_unregister(struct tinydrm_device *tdev)
|
|||
{
|
||||
struct drm_fbdev_cma *fbdev_cma = tdev->fbdev_cma;
|
||||
|
||||
drm_crtc_force_disable_all(tdev->drm);
|
||||
drm_atomic_helper_shutdown(tdev->drm);
|
||||
/* don't restore fbdev in lastclose, keep pipeline disabled */
|
||||
tdev->fbdev_cma = NULL;
|
||||
drm_dev_unregister(tdev->drm);
|
||||
|
@ -302,7 +287,7 @@ EXPORT_SYMBOL(devm_tinydrm_register);
|
|||
*/
|
||||
void tinydrm_shutdown(struct tinydrm_device *tdev)
|
||||
{
|
||||
drm_crtc_force_disable_all(tdev->drm);
|
||||
drm_atomic_helper_shutdown(tdev->drm);
|
||||
}
|
||||
EXPORT_SYMBOL(tinydrm_shutdown);
|
||||
|
||||
|
|
|
@ -132,9 +132,12 @@ static const struct drm_display_mode mi0283qt_mode = {
|
|||
TINYDRM_MODE(320, 240, 58, 43),
|
||||
};
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops);
|
||||
|
||||
static struct drm_driver mi0283qt_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME |
|
||||
DRIVER_ATOMIC,
|
||||
.fops = &mi0283qt_fops,
|
||||
TINYDRM_GEM_DRIVER_OPS,
|
||||
.lastclose = tinydrm_lastclose,
|
||||
.debugfs_init = mipi_dbi_debugfs_init,
|
||||
|
|
|
@ -361,7 +361,8 @@ static void udl_crtc_destroy(struct drm_crtc *crtc)
|
|||
static int udl_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t page_flip_flags)
|
||||
uint32_t page_flip_flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct udl_framebuffer *ufb = to_udl_fb(fb);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
|
|
@ -807,12 +807,13 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
|
|||
static int vc4_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
if (flags & DRM_MODE_PAGE_FLIP_ASYNC)
|
||||
return vc4_async_page_flip(crtc, fb, event, flags);
|
||||
else
|
||||
return drm_atomic_helper_page_flip(crtc, fb, event, flags);
|
||||
return drm_atomic_helper_page_flip(crtc, fb, event, flags, ctx);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *vc4_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
|
|
|
@ -756,7 +756,8 @@ vc4_update_plane(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h)
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_plane_state *plane_state;
|
||||
struct vc4_plane_state *vc4_state;
|
||||
|
@ -817,7 +818,8 @@ out:
|
|||
crtc_x, crtc_y,
|
||||
crtc_w, crtc_h,
|
||||
src_x, src_y,
|
||||
src_w, src_h);
|
||||
src_w, src_h,
|
||||
ctx);
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs vc4_plane_funcs = {
|
||||
|
|
|
@ -2947,10 +2947,11 @@ vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv,
|
|||
* the vmwgfx modesetting. So explicitly clear that member before calling
|
||||
* into drm_atomic_helper_set_config.
|
||||
*/
|
||||
int vmw_kms_set_config(struct drm_mode_set *set)
|
||||
int vmw_kms_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
if (set && set->mode)
|
||||
set->mode->type = 0;
|
||||
|
||||
return drm_atomic_helper_set_config(set);
|
||||
return drm_atomic_helper_set_config(set, ctx);
|
||||
}
|
||||
|
|
|
@ -453,6 +453,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
|
|||
bool to_surface,
|
||||
bool interruptible);
|
||||
|
||||
int vmw_kms_set_config(struct drm_mode_set *set);
|
||||
int vmw_kms_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -310,7 +310,8 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc)
|
|||
static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *new_fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
struct drm_framebuffer *old_fb = crtc->primary->fb;
|
||||
|
@ -323,7 +324,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
|
|||
return -EINVAL;
|
||||
|
||||
flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
|
||||
ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
|
||||
if (ret) {
|
||||
DRM_ERROR("Page flip error %d.\n", ret);
|
||||
return ret;
|
||||
|
|
|
@ -481,7 +481,8 @@ static void vmw_stdu_crtc_helper_disable(struct drm_crtc *crtc)
|
|||
static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *new_fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
|
||||
{
|
||||
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
|
||||
|
@ -504,7 +505,7 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc,
|
|||
* don't hand it to the helper.
|
||||
*/
|
||||
flags &= ~DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags);
|
||||
ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags, ctx);
|
||||
if (ret) {
|
||||
DRM_ERROR("Page flip error %d.\n", ret);
|
||||
return ret;
|
||||
|
|
|
@ -50,7 +50,6 @@ struct zx_hdmi {
|
|||
struct clk *xclk;
|
||||
bool sink_is_hdmi;
|
||||
bool sink_has_audio;
|
||||
const struct vou_inf *inf;
|
||||
struct platform_device *audio_pdev;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#define PCI_FIND_CAP_TTL 48
|
||||
|
||||
#define PCI_VSEC_ID_INTEL_TBT 0x1234 /* Thunderbolt */
|
||||
|
||||
extern const unsigned char pcie_link_speed[];
|
||||
|
||||
bool pcie_cap_has_lnkctl(const struct pci_dev *dev);
|
||||
|
|
|
@ -1208,6 +1208,24 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev)
|
|||
pdev->is_hotplug_bridge = 1;
|
||||
}
|
||||
|
||||
static void set_pcie_thunderbolt(struct pci_dev *dev)
|
||||
{
|
||||
int vsec = 0;
|
||||
u32 header;
|
||||
|
||||
while ((vsec = pci_find_next_ext_capability(dev, vsec,
|
||||
PCI_EXT_CAP_ID_VNDR))) {
|
||||
pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER, &header);
|
||||
|
||||
/* Is the device part of a Thunderbolt controller? */
|
||||
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||
PCI_VNDR_HEADER_ID(header) == PCI_VSEC_ID_INTEL_TBT) {
|
||||
dev->is_thunderbolt = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_ext_cfg_is_aliased - is ext config space just an alias of std config?
|
||||
* @dev: PCI device
|
||||
|
@ -1360,6 +1378,9 @@ int pci_setup_device(struct pci_dev *dev)
|
|||
/* need to have dev->class ready */
|
||||
dev->cfg_size = pci_cfg_space_size(dev);
|
||||
|
||||
/* need to have dev->cfg_size ready */
|
||||
set_pcie_thunderbolt(dev);
|
||||
|
||||
/* "Unknown power state" */
|
||||
dev->current_state = PCI_UNKNOWN;
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ struct apple_gmux_data {
|
|||
/* switcheroo data */
|
||||
acpi_handle dhandle;
|
||||
int gpe;
|
||||
bool external_switchable;
|
||||
enum vga_switcheroo_client_id switch_state_display;
|
||||
enum vga_switcheroo_client_id switch_state_ddc;
|
||||
enum vga_switcheroo_client_id switch_state_external;
|
||||
|
@ -358,6 +359,19 @@ static const struct backlight_ops gmux_bl_ops = {
|
|||
* ports while the discrete GPU is asleep, but currently we do not make use
|
||||
* of this feature.
|
||||
*
|
||||
* Our switching policy for the external port is that on those generations
|
||||
* which are able to switch it fully, the port is switched together with the
|
||||
* panel when IGD / DIS commands are issued to vga_switcheroo. It is thus
|
||||
* possible to drive e.g. a beamer on battery power with the integrated GPU.
|
||||
* The user may manually switch to the discrete GPU if more performance is
|
||||
* needed.
|
||||
*
|
||||
* On all newer generations, the external port can only be driven by the
|
||||
* discrete GPU. If a display is plugged in while the panel is switched to
|
||||
* the integrated GPU, *both* GPUs will be in use for maximum performance.
|
||||
* To decrease power consumption, the user may manually switch to the
|
||||
* discrete GPU, thereby suspending the integrated GPU.
|
||||
*
|
||||
* gmux' initial switch state on bootup is user configurable via the EFI
|
||||
* variable ``gpu-power-prefs-fa4ce28d-b62f-4c99-9cc3-6815686e30f9`` (5th byte,
|
||||
* 1 = IGD, 0 = DIS). Based on this setting, the EFI firmware tells gmux to
|
||||
|
@ -414,7 +428,8 @@ static int gmux_switchto(enum vga_switcheroo_client_id id)
|
|||
{
|
||||
apple_gmux_data->switch_state_ddc = id;
|
||||
apple_gmux_data->switch_state_display = id;
|
||||
apple_gmux_data->switch_state_external = id;
|
||||
if (apple_gmux_data->external_switchable)
|
||||
apple_gmux_data->switch_state_external = id;
|
||||
|
||||
gmux_write_switch_state(apple_gmux_data);
|
||||
|
||||
|
@ -601,6 +616,11 @@ static struct pci_dev *gmux_get_io_pdev(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int is_thunderbolt(struct device *dev, void *data)
|
||||
{
|
||||
return to_pci_dev(dev)->is_thunderbolt;
|
||||
}
|
||||
|
||||
static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
||||
{
|
||||
struct apple_gmux_data *gmux_data;
|
||||
|
@ -755,6 +775,15 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
|
|||
gmux_data->gpe = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If Thunderbolt is present, the external DP port is not fully
|
||||
* switchable. Force its AUX channel to the discrete GPU.
|
||||
*/
|
||||
gmux_data->external_switchable =
|
||||
!bus_for_each_dev(&pci_bus_type, NULL, NULL, is_thunderbolt);
|
||||
if (!gmux_data->external_switchable)
|
||||
gmux_write8(gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
|
||||
|
||||
apple_gmux_data = gmux_data;
|
||||
init_completion(&gmux_data->powerchange_done);
|
||||
gmux_enable_interrupts(gmux_data);
|
||||
|
|
|
@ -78,6 +78,8 @@
|
|||
#include <drm/drm_prime.h>
|
||||
#include <drm/drm_pci.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
|
||||
struct module;
|
||||
|
||||
|
@ -316,81 +318,16 @@ struct pci_controller;
|
|||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
|
||||
/**
|
||||
* Ioctl function type.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param file_priv DRM file private pointer.
|
||||
* \param cmd command.
|
||||
* \param arg argument.
|
||||
*/
|
||||
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
#define DRM_IOCTL_NR(n) _IOC_NR(n)
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
#define DRM_AUTH 0x1
|
||||
#define DRM_MASTER 0x2
|
||||
#define DRM_ROOT_ONLY 0x4
|
||||
#define DRM_CONTROL_ALLOW 0x8
|
||||
#define DRM_UNLOCKED 0x10
|
||||
#define DRM_RENDER_ALLOW 0x20
|
||||
|
||||
struct drm_ioctl_desc {
|
||||
unsigned int cmd;
|
||||
int flags;
|
||||
drm_ioctl_t *func;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a driver or general drm_ioctl_desc array entry for the given
|
||||
* ioctl, for use by drm_ioctl().
|
||||
*/
|
||||
|
||||
#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \
|
||||
.cmd = DRM_IOCTL_##ioctl, \
|
||||
.func = _func, \
|
||||
.flags = _flags, \
|
||||
.name = #ioctl \
|
||||
}
|
||||
|
||||
/* Flags and return codes for get_vblank_timestamp() driver function. */
|
||||
#define DRM_CALLED_FROM_VBLIRQ 1
|
||||
#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0)
|
||||
#define DRM_VBLANKTIME_IN_VBLANK (1 << 1)
|
||||
|
||||
/* get_scanout_position() return flags */
|
||||
#define DRM_SCANOUTPOS_VALID (1 << 0)
|
||||
#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
|
||||
#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
|
||||
|
||||
/**
|
||||
* Info file list entry. This structure represents a debugfs or proc file to
|
||||
* be created by the drm core
|
||||
*/
|
||||
struct drm_info_list {
|
||||
const char *name; /** file name */
|
||||
int (*show)(struct seq_file*, void*); /** show callback */
|
||||
u32 driver_features; /**< Required driver features for this entry */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* debugfs node structure. This structure represents a debugfs file.
|
||||
*/
|
||||
struct drm_info_node {
|
||||
struct list_head list;
|
||||
struct drm_minor *minor;
|
||||
const struct drm_info_list *info_ent;
|
||||
struct dentry *dent;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM device structure. This structure represent a complete card that
|
||||
* may contain multiple heads.
|
||||
|
@ -569,51 +506,12 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)
|
|||
/*@{*/
|
||||
|
||||
/* Driver support (drm_drv.h) */
|
||||
extern int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
|
||||
extern long drm_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
extern long drm_compat_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
#else
|
||||
/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
|
||||
#define drm_compat_ioctl NULL
|
||||
#endif
|
||||
extern bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
|
||||
|
||||
/* Misc. IOCTL support (drm_ioctl.c) */
|
||||
int drm_noop(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_invalid_op(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
/*
|
||||
* These are exported to drivers so that they can implement fencing using
|
||||
* DMA quiscent + idle. DMA quiescent usually requires the hardware lock.
|
||||
*/
|
||||
|
||||
/* Debugfs support */
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
extern int drm_debugfs_create_files(const struct drm_info_list *files,
|
||||
int count, struct dentry *root,
|
||||
struct drm_minor *minor);
|
||||
extern int drm_debugfs_remove_files(const struct drm_info_list *files,
|
||||
int count, struct drm_minor *minor);
|
||||
#else
|
||||
static inline int drm_debugfs_create_files(const struct drm_info_list *files,
|
||||
int count, struct dentry *root,
|
||||
struct drm_minor *minor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
|
||||
int count, struct drm_minor *minor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* sysfs support (drm_sysfs.c) */
|
||||
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
|
||||
|
||||
|
|
|
@ -498,6 +498,23 @@ int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
|
|||
|
||||
void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
||||
|
||||
/**
|
||||
* for_each_connector_in_state - iterate over all connectors in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @connector: &struct drm_connector iteration cursor
|
||||
* @connector_state: &struct drm_connector_state iteration cursor
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all connectors in an atomic update. Note that before the
|
||||
* software state is committed (by calling drm_atomic_helper_swap_state(), this
|
||||
* points to the new state, while afterwards it points to the old state. Due to
|
||||
* this tricky confusion this macro is deprecated.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Replace all usage of this with one of the explicit iterators below and then
|
||||
* remove this macro.
|
||||
*/
|
||||
#define for_each_connector_in_state(__state, connector, connector_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->num_connector && \
|
||||
|
@ -506,6 +523,20 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (connector)
|
||||
|
||||
/**
|
||||
* for_each_oldnew_connector_in_state - iterate over all connectors in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @connector: &struct drm_connector iteration cursor
|
||||
* @old_connector_state: &struct drm_connector_state iteration cursor for the
|
||||
* old state
|
||||
* @new_connector_state: &struct drm_connector_state iteration cursor for the
|
||||
* new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all connectors in an atomic update, tracking both old and
|
||||
* new state. This is useful in places where the state delta needs to be
|
||||
* considered, for example in atomic check functions.
|
||||
*/
|
||||
#define for_each_oldnew_connector_in_state(__state, connector, old_connector_state, new_connector_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->num_connector && \
|
||||
|
@ -515,6 +546,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (connector)
|
||||
|
||||
/**
|
||||
* for_each_old_connector_in_state - iterate over all connectors in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @connector: &struct drm_connector iteration cursor
|
||||
* @old_connector_state: &struct drm_connector_state iteration cursor for the
|
||||
* old state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all connectors in an atomic update, tracking only the old
|
||||
* state. This is useful in disable functions, where we need the old state the
|
||||
* hardware is still in.
|
||||
*/
|
||||
#define for_each_old_connector_in_state(__state, connector, old_connector_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->num_connector && \
|
||||
|
@ -523,6 +566,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (connector)
|
||||
|
||||
/**
|
||||
* for_each_new_connector_in_state - iterate over all connectors in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @connector: &struct drm_connector iteration cursor
|
||||
* @new_connector_state: &struct drm_connector_state iteration cursor for the
|
||||
* new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all connectors in an atomic update, tracking only the new
|
||||
* state. This is useful in enable functions, where we need the new state the
|
||||
* hardware should be in when the atomic commit operation has completed.
|
||||
*/
|
||||
#define for_each_new_connector_in_state(__state, connector, new_connector_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->num_connector && \
|
||||
|
@ -531,6 +586,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (connector)
|
||||
|
||||
/**
|
||||
* for_each_crtc_in_state - iterate over all connectors in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @crtc: &struct drm_crtc iteration cursor
|
||||
* @crtc_state: &struct drm_crtc_state iteration cursor
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all CRTCs in an atomic update. Note that before the
|
||||
* software state is committed (by calling drm_atomic_helper_swap_state(), this
|
||||
* points to the new state, while afterwards it points to the old state. Due to
|
||||
* this tricky confusion this macro is deprecated.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Replace all usage of this with one of the explicit iterators below and then
|
||||
* remove this macro.
|
||||
*/
|
||||
#define for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_crtc && \
|
||||
|
@ -539,6 +611,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (crtc_state)
|
||||
|
||||
/**
|
||||
* for_each_oldnew_crtc_in_state - iterate over all CRTCs in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @crtc: &struct drm_crtc iteration cursor
|
||||
* @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
|
||||
* @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all CRTCs in an atomic update, tracking both old and
|
||||
* new state. This is useful in places where the state delta needs to be
|
||||
* considered, for example in atomic check functions.
|
||||
*/
|
||||
#define for_each_oldnew_crtc_in_state(__state, crtc, old_crtc_state, new_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_crtc && \
|
||||
|
@ -548,6 +632,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (crtc)
|
||||
|
||||
/**
|
||||
* for_each_old_crtc_in_state - iterate over all CRTCs in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @crtc: &struct drm_crtc iteration cursor
|
||||
* @old_crtc_state: &struct drm_crtc_state iteration cursor for the old state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all CRTCs in an atomic update, tracking only the old
|
||||
* state. This is useful in disable functions, where we need the old state the
|
||||
* hardware is still in.
|
||||
*/
|
||||
#define for_each_old_crtc_in_state(__state, crtc, old_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_crtc && \
|
||||
|
@ -556,6 +651,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (crtc)
|
||||
|
||||
/**
|
||||
* for_each_new_crtc_in_state - iterate over all CRTCs in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @crtc: &struct drm_crtc iteration cursor
|
||||
* @new_crtc_state: &struct drm_crtc_state iteration cursor for the new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all CRTCs in an atomic update, tracking only the new
|
||||
* state. This is useful in enable functions, where we need the new state the
|
||||
* hardware should be in when the atomic commit operation has completed.
|
||||
*/
|
||||
#define for_each_new_crtc_in_state(__state, crtc, new_crtc_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_crtc && \
|
||||
|
@ -564,6 +670,23 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (crtc)
|
||||
|
||||
/**
|
||||
* for_each_plane_in_state - iterate over all planes in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @plane: &struct drm_plane iteration cursor
|
||||
* @plane_state: &struct drm_plane_state iteration cursor
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all planes in an atomic update. Note that before the
|
||||
* software state is committed (by calling drm_atomic_helper_swap_state(), this
|
||||
* points to the new state, while afterwards it points to the old state. Due to
|
||||
* this tricky confusion this macro is deprecated.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* Replace all usage of this with one of the explicit iterators below and then
|
||||
* remove this macro.
|
||||
*/
|
||||
#define for_each_plane_in_state(__state, plane, plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_total_plane && \
|
||||
|
@ -572,6 +695,18 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (plane_state)
|
||||
|
||||
/**
|
||||
* for_each_oldnew_plane_in_state - iterate over all planes in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @plane: &struct drm_plane iteration cursor
|
||||
* @old_plane_state: &struct drm_plane_state iteration cursor for the old state
|
||||
* @new_plane_state: &struct drm_plane_state iteration cursor for the new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all planes in an atomic update, tracking both old and
|
||||
* new state. This is useful in places where the state delta needs to be
|
||||
* considered, for example in atomic check functions.
|
||||
*/
|
||||
#define for_each_oldnew_plane_in_state(__state, plane, old_plane_state, new_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_total_plane && \
|
||||
|
@ -581,6 +716,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (plane)
|
||||
|
||||
/**
|
||||
* for_each_old_plane_in_state - iterate over all planes in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @plane: &struct drm_plane iteration cursor
|
||||
* @old_plane_state: &struct drm_plane_state iteration cursor for the old state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all planes in an atomic update, tracking only the old
|
||||
* state. This is useful in disable functions, where we need the old state the
|
||||
* hardware is still in.
|
||||
*/
|
||||
#define for_each_old_plane_in_state(__state, plane, old_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_total_plane && \
|
||||
|
@ -589,6 +735,17 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
(__i)++) \
|
||||
for_each_if (plane)
|
||||
|
||||
/**
|
||||
* for_each_new_plane_in_state - iterate over all planes in an atomic update
|
||||
* @__state: &struct drm_atomic_state pointer
|
||||
* @plane: &struct drm_plane iteration cursor
|
||||
* @new_plane_state: &struct drm_plane_state iteration cursor for the new state
|
||||
* @__i: int iteration cursor, for macro-internal use
|
||||
*
|
||||
* This iterates over all planes in an atomic update, tracking only the new
|
||||
* state. This is useful in enable functions, where we need the new state the
|
||||
* hardware should be in when the atomic commit operation has completed.
|
||||
*/
|
||||
#define for_each_new_plane_in_state(__state, plane, new_plane_state, __i) \
|
||||
for ((__i) = 0; \
|
||||
(__i) < (__state)->dev->mode_config.num_total_plane && \
|
||||
|
@ -603,7 +760,7 @@ void drm_state_dump(struct drm_device *dev, struct drm_printer *p);
|
|||
*
|
||||
* To give drivers flexibility &struct drm_crtc_state has 3 booleans to track
|
||||
* whether the state CRTC changed enough to need a full modeset cycle:
|
||||
* connectors_changed, mode_changed and active_changed. This helper simply
|
||||
* planes_changed, mode_changed and active_changed. This helper simply
|
||||
* combines these three to compute the overall need for a modeset for @state.
|
||||
*
|
||||
* The atomic helper code sets these booleans, but drivers can and should
|
||||
|
|
|
@ -94,16 +94,20 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int drm_atomic_helper_disable_plane(struct drm_plane *plane);
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int drm_atomic_helper_disable_plane(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int __drm_atomic_helper_disable_plane(struct drm_plane *plane,
|
||||
struct drm_plane_state *plane_state);
|
||||
int drm_atomic_helper_set_config(struct drm_mode_set *set);
|
||||
int drm_atomic_helper_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int __drm_atomic_helper_set_config(struct drm_mode_set *set,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void drm_atomic_helper_shutdown(struct drm_device *dev);
|
||||
struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev);
|
||||
int drm_atomic_helper_commit_duplicated_state(struct drm_atomic_state *state,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
@ -122,13 +126,15 @@ int drm_atomic_helper_connector_set_property(struct drm_connector *connector,
|
|||
int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int drm_atomic_helper_page_flip_target(
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags,
|
||||
uint32_t target);
|
||||
uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int drm_atomic_helper_connector_dpms(struct drm_connector *connector,
|
||||
int mode);
|
||||
struct drm_encoder *
|
||||
|
|
|
@ -133,6 +133,7 @@ struct drm_scdc {
|
|||
* This information is available in CEA-861-F extension blocks (like HF-VSDB).
|
||||
*/
|
||||
struct drm_hdmi_info {
|
||||
/** @scdc: sink's scdc support and capabilities */
|
||||
struct drm_scdc scdc;
|
||||
};
|
||||
|
||||
|
@ -655,7 +656,6 @@ struct drm_cmdline_mode {
|
|||
* @bad_edid_counter: track sinks that give us an EDID with invalid checksum
|
||||
* @edid_corrupt: indicates whether the last read EDID was corrupt
|
||||
* @debugfs_entry: debugfs directory for this connector
|
||||
* @state: current atomic state for this connector
|
||||
* @has_tile: is this connector connected to a tiled monitor
|
||||
* @tile_group: tile group for the connected monitor
|
||||
* @tile_is_single_monitor: whether the tile is one monitor housing
|
||||
|
@ -823,6 +823,21 @@ struct drm_connector {
|
|||
|
||||
struct dentry *debugfs_entry;
|
||||
|
||||
/**
|
||||
* @state:
|
||||
*
|
||||
* Current atomic state for this connector.
|
||||
*
|
||||
* This is protected by @drm_mode_config.connection_mutex. Note that
|
||||
* nonblocking atomic commits access the current connector state without
|
||||
* taking locks. Either by going through the &struct drm_atomic_state
|
||||
* pointers, see for_each_connector_in_state(),
|
||||
* for_each_oldnew_connector_in_state(),
|
||||
* for_each_old_connector_in_state() and
|
||||
* for_each_new_connector_in_state(). Or through careful ordering of
|
||||
* atomic commit operations as implemented in the atomic helpers, see
|
||||
* &struct drm_crtc_commit.
|
||||
*/
|
||||
struct drm_connector_state *state;
|
||||
|
||||
/* DisplayID bits */
|
||||
|
|
|
@ -347,7 +347,8 @@ struct drm_crtc_funcs {
|
|||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*set_config)(struct drm_mode_set *set);
|
||||
int (*set_config)(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @page_flip:
|
||||
|
@ -405,7 +406,8 @@ struct drm_crtc_funcs {
|
|||
int (*page_flip)(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @page_flip_target:
|
||||
|
@ -423,7 +425,8 @@ struct drm_crtc_funcs {
|
|||
int (*page_flip_target)(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
struct drm_pending_vblank_event *event,
|
||||
uint32_t flags, uint32_t target);
|
||||
uint32_t flags, uint32_t target,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @set_property:
|
||||
|
@ -590,9 +593,12 @@ struct drm_crtc_funcs {
|
|||
* When CRC generation is enabled, the driver should call
|
||||
* drm_crtc_add_crc_entry() at each frame, providing any information
|
||||
* that characterizes the frame contents in the crcN arguments, as
|
||||
* provided from the configured source. Drivers must accept a "auto"
|
||||
* provided from the configured source. Drivers must accept an "auto"
|
||||
* source name that will select a default source for this CRTC.
|
||||
*
|
||||
* Note that "auto" can depend upon the current modeset configuration,
|
||||
* e.g. it could pick an encoder or output specific CRC sampling point.
|
||||
*
|
||||
* This callback is optional if the driver does not support any CRC
|
||||
* generation functionality.
|
||||
*
|
||||
|
@ -696,10 +702,12 @@ struct drm_crtc {
|
|||
/**
|
||||
* @mutex:
|
||||
*
|
||||
* This provides a read lock for the overall crtc state (mode, dpms
|
||||
* This provides a read lock for the overall CRTC state (mode, dpms
|
||||
* state, ...) and a write lock for everything which can be update
|
||||
* without a full modeset (fb, cursor data, crtc properties ...). A full
|
||||
* without a full modeset (fb, cursor data, CRTC properties ...). A full
|
||||
* modeset also need to grab &drm_mode_config.connection_mutex.
|
||||
*
|
||||
* For atomic drivers specifically this protects @state.
|
||||
*/
|
||||
struct drm_modeset_lock mutex;
|
||||
|
||||
|
@ -745,6 +753,14 @@ struct drm_crtc {
|
|||
* @state:
|
||||
*
|
||||
* Current atomic state for this CRTC.
|
||||
*
|
||||
* This is protected by @mutex. Note that nonblocking atomic commits
|
||||
* access the current CRTC state without taking locks. Either by going
|
||||
* through the &struct drm_atomic_state pointers, see
|
||||
* for_each_crtc_in_state(), for_each_oldnew_crtc_in_state(),
|
||||
* for_each_old_crtc_in_state() and for_each_new_crtc_in_state(). Or
|
||||
* through careful ordering of atomic commit operations as implemented
|
||||
* in the atomic helpers, see &struct drm_crtc_commit.
|
||||
*/
|
||||
struct drm_crtc_state *state;
|
||||
|
||||
|
|
|
@ -43,18 +43,19 @@
|
|||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
|
||||
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
|
||||
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
|
||||
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
|
||||
extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
|
||||
void drm_helper_disable_unused_functions(struct drm_device *dev);
|
||||
int drm_crtc_helper_set_config(struct drm_mode_set *set,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
|
||||
bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
|
||||
|
||||
extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
|
||||
int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
|
||||
|
||||
extern void drm_helper_resume_force_mode(struct drm_device *dev);
|
||||
void drm_helper_resume_force_mode(struct drm_device *dev);
|
||||
|
||||
int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode, int x, int y,
|
||||
|
@ -63,15 +64,15 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
struct drm_framebuffer *old_fb);
|
||||
|
||||
/* drm_probe_helper.c */
|
||||
extern int drm_helper_probe_single_connector_modes(struct drm_connector
|
||||
*connector, uint32_t maxX,
|
||||
uint32_t maxY);
|
||||
extern void drm_kms_helper_poll_init(struct drm_device *dev);
|
||||
extern void drm_kms_helper_poll_fini(struct drm_device *dev);
|
||||
extern bool drm_helper_hpd_irq_event(struct drm_device *dev);
|
||||
extern void drm_kms_helper_hotplug_event(struct drm_device *dev);
|
||||
int drm_helper_probe_single_connector_modes(struct drm_connector
|
||||
*connector, uint32_t maxX,
|
||||
uint32_t maxY);
|
||||
void drm_kms_helper_poll_init(struct drm_device *dev);
|
||||
void drm_kms_helper_poll_fini(struct drm_device *dev);
|
||||
bool drm_helper_hpd_irq_event(struct drm_device *dev);
|
||||
void drm_kms_helper_hotplug_event(struct drm_device *dev);
|
||||
|
||||
extern void drm_kms_helper_poll_disable(struct drm_device *dev);
|
||||
extern void drm_kms_helper_poll_enable(struct drm_device *dev);
|
||||
void drm_kms_helper_poll_disable(struct drm_device *dev);
|
||||
void drm_kms_helper_poll_enable(struct drm_device *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Internal Header for the Direct Rendering Manager
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* Copyright (c) 2009-2010, Code Aurora Forum.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Author: Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_DEBUGFS_H_
|
||||
#define _DRM_DEBUGFS_H_
|
||||
|
||||
/**
|
||||
* struct drm_info_list - debugfs info list entry
|
||||
*
|
||||
* This structure represents a debugfs file to be created by the drm
|
||||
* core.
|
||||
*/
|
||||
struct drm_info_list {
|
||||
/** @name: file name */
|
||||
const char *name;
|
||||
/**
|
||||
* @show:
|
||||
*
|
||||
* Show callback. &seq_file->private will be set to the &struct
|
||||
* drm_info_node corresponding to the instance of this info on a given
|
||||
* &struct drm_minor.
|
||||
*/
|
||||
int (*show)(struct seq_file*, void*);
|
||||
/** @driver_features: Required driver features for this entry */
|
||||
u32 driver_features;
|
||||
/** @data: Driver-private data, should not be device-specific. */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_info_node - Per-minor debugfs node structure
|
||||
*
|
||||
* This structure represents a debugfs file, as an instantiation of a &struct
|
||||
* drm_info_list on a &struct drm_minor.
|
||||
*
|
||||
* FIXME:
|
||||
*
|
||||
* No it doesn't make a hole lot of sense that we duplicate debugfs entries for
|
||||
* both the render and the primary nodes, but that's how this has organically
|
||||
* grown. It should probably be fixed, with a compatibility link, if needed.
|
||||
*/
|
||||
struct drm_info_node {
|
||||
/** @minor: &struct drm_minor for this node. */
|
||||
struct drm_minor *minor;
|
||||
/** @info_ent: template for this node. */
|
||||
const struct drm_info_list *info_ent;
|
||||
/* private: */
|
||||
struct list_head list;
|
||||
struct dentry *dent;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
int drm_debugfs_create_files(const struct drm_info_list *files,
|
||||
int count, struct dentry *root,
|
||||
struct drm_minor *minor);
|
||||
int drm_debugfs_remove_files(const struct drm_info_list *files,
|
||||
int count, struct drm_minor *minor);
|
||||
#else
|
||||
static inline int drm_debugfs_create_files(const struct drm_info_list *files,
|
||||
int count, struct dentry *root,
|
||||
struct drm_minor *minor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int drm_debugfs_remove_files(const struct drm_info_list *files,
|
||||
int count, struct drm_minor *minor)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DRM_DEBUGFS_H_ */
|
|
@ -479,18 +479,6 @@ struct drm_dp_mst_topology_mgr {
|
|||
* @pbn_div: PBN to slots divisor.
|
||||
*/
|
||||
int pbn_div;
|
||||
/**
|
||||
* @total_slots: Total slots that can be allocated.
|
||||
*/
|
||||
int total_slots;
|
||||
/**
|
||||
* @avail_slots: Still available slots that can be allocated.
|
||||
*/
|
||||
int avail_slots;
|
||||
/**
|
||||
* @total_pbn: Total PBN count.
|
||||
*/
|
||||
int total_pbn;
|
||||
|
||||
/**
|
||||
* @qlock: protects @tx_msg_downq, the &drm_dp_mst_branch.txslost and
|
||||
|
@ -579,7 +567,8 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
|
|||
int drm_dp_calc_pbn_mode(int clock, int bpp);
|
||||
|
||||
|
||||
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int *slots);
|
||||
bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port, int pbn, int slots);
|
||||
|
||||
int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port);
|
||||
|
||||
|
|
|
@ -522,11 +522,11 @@ struct drm_driver {
|
|||
int dev_priv_size;
|
||||
};
|
||||
|
||||
extern __printf(6, 7)
|
||||
__printf(6, 7)
|
||||
void drm_dev_printk(const struct device *dev, const char *level,
|
||||
unsigned int category, const char *function_name,
|
||||
const char *prefix, const char *format, ...);
|
||||
extern __printf(3, 4)
|
||||
__printf(3, 4)
|
||||
void drm_printk(const char *level, unsigned int category,
|
||||
const char *format, ...);
|
||||
extern unsigned int drm_debug;
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <linux/types.h>
|
||||
#include <uapi/drm/drm_fourcc.h>
|
||||
|
||||
struct drm_device;
|
||||
struct drm_mode_fb_cmd2;
|
||||
|
||||
/**
|
||||
* struct drm_format_info - information about a DRM format
|
||||
* @format: 4CC format identifier (DRM_FORMAT_*)
|
||||
|
@ -55,6 +58,9 @@ struct drm_format_name_buf {
|
|||
|
||||
const struct drm_format_info *__drm_format_info(u32 format);
|
||||
const struct drm_format_info *drm_format_info(u32 format);
|
||||
const struct drm_format_info *
|
||||
drm_get_format_info(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
|
||||
int drm_format_num_planes(uint32_t format);
|
||||
int drm_format_plane_cpp(uint32_t format, int plane);
|
||||
|
|
|
@ -45,9 +45,9 @@ struct drm_global_reference {
|
|||
void (*release) (struct drm_global_reference *);
|
||||
};
|
||||
|
||||
extern void drm_global_init(void);
|
||||
extern void drm_global_release(void);
|
||||
extern int drm_global_item_ref(struct drm_global_reference *ref);
|
||||
extern void drm_global_item_unref(struct drm_global_reference *ref);
|
||||
void drm_global_init(void);
|
||||
void drm_global_release(void);
|
||||
int drm_global_item_ref(struct drm_global_reference *ref);
|
||||
void drm_global_item_unref(struct drm_global_reference *ref);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -49,17 +49,17 @@ struct drm_open_hash {
|
|||
u8 order;
|
||||
};
|
||||
|
||||
extern int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
|
||||
extern int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
|
||||
extern int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
|
||||
unsigned long seed, int bits, int shift,
|
||||
unsigned long add);
|
||||
extern int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
|
||||
int drm_ht_create(struct drm_open_hash *ht, unsigned int order);
|
||||
int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item);
|
||||
int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item,
|
||||
unsigned long seed, int bits, int shift,
|
||||
unsigned long add);
|
||||
int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item);
|
||||
|
||||
extern void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
|
||||
extern int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
|
||||
extern int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
|
||||
extern void drm_ht_remove(struct drm_open_hash *ht);
|
||||
void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key);
|
||||
int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key);
|
||||
int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item);
|
||||
void drm_ht_remove(struct drm_open_hash *ht);
|
||||
|
||||
/*
|
||||
* RCU-safe interface
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Internal Header for the Direct Rendering Manager
|
||||
*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* Copyright (c) 2009-2010, Code Aurora Forum.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
* Author: Gareth Hughes <gareth@valinux.com>
|
||||
*
|
||||
* 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
|
||||
* VA LINUX SYSTEMS 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.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_IOCTL_H_
|
||||
#define _DRM_IOCTL_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/ioctl.h>
|
||||
|
||||
struct drm_device;
|
||||
struct drm_file;
|
||||
struct file;
|
||||
|
||||
/**
|
||||
* Ioctl function type.
|
||||
*
|
||||
* \param inode device inode.
|
||||
* \param file_priv DRM file private pointer.
|
||||
* \param cmd command.
|
||||
* \param arg argument.
|
||||
*/
|
||||
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
#define DRM_IOCTL_NR(n) _IOC_NR(n)
|
||||
#define DRM_MAJOR 226
|
||||
|
||||
#define DRM_AUTH 0x1
|
||||
#define DRM_MASTER 0x2
|
||||
#define DRM_ROOT_ONLY 0x4
|
||||
#define DRM_CONTROL_ALLOW 0x8
|
||||
#define DRM_UNLOCKED 0x10
|
||||
#define DRM_RENDER_ALLOW 0x20
|
||||
|
||||
struct drm_ioctl_desc {
|
||||
unsigned int cmd;
|
||||
int flags;
|
||||
drm_ioctl_t *func;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a driver or general drm_ioctl_desc array entry for the given
|
||||
* ioctl, for use by drm_ioctl().
|
||||
*/
|
||||
|
||||
#define DRM_IOCTL_DEF_DRV(ioctl, _func, _flags) \
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = { \
|
||||
.cmd = DRM_IOCTL_##ioctl, \
|
||||
.func = _func, \
|
||||
.flags = _flags, \
|
||||
.name = #ioctl \
|
||||
}
|
||||
|
||||
int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
|
||||
long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#ifdef CONFIG_COMPAT
|
||||
long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
|
||||
#else
|
||||
/* Let drm_compat_ioctl be assigned to .compat_ioctl unconditionally */
|
||||
#define drm_compat_ioctl NULL
|
||||
#endif
|
||||
bool drm_ioctl_flags(unsigned int nr, unsigned int *flags);
|
||||
|
||||
int drm_noop(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
int drm_invalid_op(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
#endif /* _DRM_IOCTL_H_ */
|
|
@ -34,6 +34,7 @@ struct drm_file;
|
|||
struct drm_device;
|
||||
struct drm_atomic_state;
|
||||
struct drm_mode_fb_cmd2;
|
||||
struct drm_format_info;
|
||||
|
||||
/**
|
||||
* struct drm_mode_config_funcs - basic driver provided mode setting functions
|
||||
|
@ -69,6 +70,19 @@ struct drm_mode_config_funcs {
|
|||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
/**
|
||||
* @get_format_info:
|
||||
*
|
||||
* Allows a driver to return custom format information for special
|
||||
* fb layouts (eg. ones with auxiliary compression control planes).
|
||||
*
|
||||
* RETURNS:
|
||||
*
|
||||
* The format information specific to the given fb metadata, or
|
||||
* NULL if none is found.
|
||||
*/
|
||||
const struct drm_format_info *(*get_format_info)(const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
/**
|
||||
* @output_poll_changed:
|
||||
*
|
||||
|
@ -293,21 +307,6 @@ struct drm_mode_config_funcs {
|
|||
|
||||
/**
|
||||
* struct drm_mode_config - Mode configuration control structure
|
||||
* @mutex: mutex protecting KMS related lists and structures
|
||||
* @connection_mutex: ww mutex protecting connector state and routing
|
||||
* @acquire_ctx: global implicit acquire context used by atomic drivers for
|
||||
* legacy IOCTLs
|
||||
* @fb_lock: mutex to protect fb state and lists
|
||||
* @num_fb: number of fbs available
|
||||
* @fb_list: list of framebuffers available
|
||||
* @num_encoder: number of encoders on this device
|
||||
* @encoder_list: list of encoder objects
|
||||
* @num_overlay_plane: number of overlay planes on this device
|
||||
* @num_total_plane: number of universal (i.e. with primary/curso) planes on this device
|
||||
* @plane_list: list of plane objects
|
||||
* @num_crtc: number of CRTCs on this device
|
||||
* @crtc_list: list of CRTC objects
|
||||
* @property_list: list of property objects
|
||||
* @min_width: minimum pixel width on this device
|
||||
* @min_height: minimum pixel height on this device
|
||||
* @max_width: maximum pixel width on this device
|
||||
|
@ -318,9 +317,6 @@ struct drm_mode_config_funcs {
|
|||
* @poll_running: track polling status for this device
|
||||
* @delayed_event: track delayed poll uevent deliver for this device
|
||||
* @output_poll_work: delayed work for polling in process context
|
||||
* @property_blob_list: list of all the blob property objects
|
||||
* @blob_lock: mutex for blob property allocation and management
|
||||
* @*_property: core property tracking
|
||||
* @preferred_depth: preferred RBG pixel depth, used by fb helpers
|
||||
* @prefer_shadow: hint to userspace to prefer shadow-fb rendering
|
||||
* @cursor_width: hint to userspace for max cursor width
|
||||
|
@ -332,9 +328,37 @@ struct drm_mode_config_funcs {
|
|||
* global restrictions are also here, e.g. dimension restrictions.
|
||||
*/
|
||||
struct drm_mode_config {
|
||||
struct mutex mutex; /* protects configuration (mode lists etc.) */
|
||||
struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
|
||||
struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
|
||||
/**
|
||||
* @mutex:
|
||||
*
|
||||
* This is the big scary modeset BKL which protects everything that
|
||||
* isn't protect otherwise. Scope is unclear and fuzzy, try to remove
|
||||
* anything from under it's protection and move it into more well-scoped
|
||||
* locks.
|
||||
*
|
||||
* The one important thing this protects is the use of @acquire_ctx.
|
||||
*/
|
||||
struct mutex mutex;
|
||||
|
||||
/**
|
||||
* @connection_mutex:
|
||||
*
|
||||
* This protects connector state and the connector to encoder to CRTC
|
||||
* routing chain.
|
||||
*
|
||||
* For atomic drivers specifically this protects &drm_connector.state.
|
||||
*/
|
||||
struct drm_modeset_lock connection_mutex;
|
||||
|
||||
/**
|
||||
* @acquire_ctx:
|
||||
*
|
||||
* Global implicit acquire context used by atomic drivers for legacy
|
||||
* IOCTLs. Deprecated, since implicit locking contexts make it
|
||||
* impossible to use driver-private &struct drm_modeset_lock. Users of
|
||||
* this must hold @mutex.
|
||||
*/
|
||||
struct drm_modeset_acquire_ctx *acquire_ctx;
|
||||
|
||||
/**
|
||||
* @idr_mutex:
|
||||
|
@ -360,8 +384,11 @@ struct drm_mode_config {
|
|||
*/
|
||||
struct idr tile_idr;
|
||||
|
||||
struct mutex fb_lock; /* proctects global and per-file fb lists */
|
||||
/** @fb_lock: Mutex to protect fb the global @fb_list and @num_fb. */
|
||||
struct mutex fb_lock;
|
||||
/** @num_fb: Number of entries on @fb_list. */
|
||||
int num_fb;
|
||||
/** @fb_list: List of all &struct drm_framebuffer. */
|
||||
struct list_head fb_list;
|
||||
|
||||
/**
|
||||
|
@ -379,27 +406,80 @@ struct drm_mode_config {
|
|||
*/
|
||||
struct ida connector_ida;
|
||||
/**
|
||||
* @connector_list: List of connector objects. Protected by
|
||||
* @connector_list_lock. Only use drm_for_each_connector_iter() and
|
||||
* @connector_list:
|
||||
*
|
||||
* List of connector objects linked with &drm_connector.head. Protected
|
||||
* by @connector_list_lock. Only use drm_for_each_connector_iter() and
|
||||
* &struct drm_connector_list_iter to walk this list.
|
||||
*/
|
||||
struct list_head connector_list;
|
||||
/**
|
||||
* @num_encoder:
|
||||
*
|
||||
* Number of encoders on this device. This is invariant over the
|
||||
* lifetime of a device and hence doesn't need any locks.
|
||||
*/
|
||||
int num_encoder;
|
||||
/**
|
||||
* @encoder_list:
|
||||
*
|
||||
* List of encoder objects linked with &drm_encoder.head. This is
|
||||
* invariant over the lifetime of a device and hence doesn't need any
|
||||
* locks.
|
||||
*/
|
||||
struct list_head encoder_list;
|
||||
|
||||
/*
|
||||
* Track # of overlay planes separately from # of total planes. By
|
||||
* default we only advertise overlay planes to userspace; if userspace
|
||||
* sets the "universal plane" capability bit, we'll go ahead and
|
||||
* expose all planes.
|
||||
/**
|
||||
* @num_overlay_plane:
|
||||
*
|
||||
* Number of overlay planes on this device, excluding primary and cursor
|
||||
* planes.
|
||||
*
|
||||
* Track number of overlay planes separately from number of total
|
||||
* planes. By default we only advertise overlay planes to userspace; if
|
||||
* userspace sets the "universal plane" capability bit, we'll go ahead
|
||||
* and expose all planes. This is invariant over the lifetime of a
|
||||
* device and hence doesn't need any locks.
|
||||
*/
|
||||
int num_overlay_plane;
|
||||
/**
|
||||
* @num_total_plane:
|
||||
*
|
||||
* Number of universal (i.e. with primary/curso) planes on this device.
|
||||
* This is invariant over the lifetime of a device and hence doesn't
|
||||
* need any locks.
|
||||
*/
|
||||
int num_total_plane;
|
||||
/**
|
||||
* @plane_list:
|
||||
*
|
||||
* List of plane objects linked with &drm_plane.head. This is invariant
|
||||
* over the lifetime of a device and hence doesn't need any locks.
|
||||
*/
|
||||
struct list_head plane_list;
|
||||
|
||||
/**
|
||||
* @num_crtc:
|
||||
*
|
||||
* Number of CRTCs on this device linked with &drm_crtc.head. This is invariant over the lifetime
|
||||
* of a device and hence doesn't need any locks.
|
||||
*/
|
||||
int num_crtc;
|
||||
/**
|
||||
* @crtc_list:
|
||||
*
|
||||
* List of CRTC objects linked with &drm_crtc.head. This is invariant
|
||||
* over the lifetime of a device and hence doesn't need any locks.
|
||||
*/
|
||||
struct list_head crtc_list;
|
||||
|
||||
/**
|
||||
* @property_list:
|
||||
*
|
||||
* List of property type objects linked with &drm_property.head. This is
|
||||
* invariant over the lifetime of a device and hence doesn't need any
|
||||
* locks.
|
||||
*/
|
||||
struct list_head property_list;
|
||||
|
||||
int min_width, min_height;
|
||||
|
@ -413,10 +493,24 @@ struct drm_mode_config {
|
|||
bool delayed_event;
|
||||
struct delayed_work output_poll_work;
|
||||
|
||||
/**
|
||||
* @blob_lock:
|
||||
*
|
||||
* Mutex for blob property allocation and management, protects
|
||||
* @property_blob_list and &drm_file.blobs.
|
||||
*/
|
||||
struct mutex blob_lock;
|
||||
|
||||
/* pointers to standard properties */
|
||||
/**
|
||||
* @property_blob_list:
|
||||
*
|
||||
* List of all the blob property objects linked with
|
||||
* &drm_property_blob.head. Protected by @blob_lock.
|
||||
*/
|
||||
struct list_head property_blob_list;
|
||||
|
||||
/* pointers to standard properties */
|
||||
|
||||
/**
|
||||
* @edid_property: Default connector property to hold the EDID of the
|
||||
* currently connected sink, if any.
|
||||
|
|
|
@ -11,18 +11,18 @@ struct drm_encoder;
|
|||
struct device_node;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||
struct device_node *port);
|
||||
extern void drm_of_component_match_add(struct device *master,
|
||||
struct component_match **matchptr,
|
||||
int (*compare)(struct device *, void *),
|
||||
struct device_node *node);
|
||||
extern int drm_of_component_probe(struct device *dev,
|
||||
int (*compare_of)(struct device *, void *),
|
||||
const struct component_master_ops *m_ops);
|
||||
extern int drm_of_encoder_active_endpoint(struct device_node *node,
|
||||
struct drm_encoder *encoder,
|
||||
struct of_endpoint *endpoint);
|
||||
uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||
struct device_node *port);
|
||||
void drm_of_component_match_add(struct device *master,
|
||||
struct component_match **matchptr,
|
||||
int (*compare)(struct device *, void *),
|
||||
struct device_node *node);
|
||||
int drm_of_component_probe(struct device *dev,
|
||||
int (*compare_of)(struct device *, void *),
|
||||
const struct component_master_ops *m_ops);
|
||||
int drm_of_encoder_active_endpoint(struct device_node *node,
|
||||
struct drm_encoder *encoder,
|
||||
struct of_endpoint *endpoint);
|
||||
#else
|
||||
static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
|
||||
struct device_node *port)
|
||||
|
|
|
@ -39,17 +39,17 @@ struct drm_device;
|
|||
struct drm_driver;
|
||||
struct drm_master;
|
||||
|
||||
extern struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
|
||||
size_t align);
|
||||
extern void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
|
||||
struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, size_t size,
|
||||
size_t align);
|
||||
void drm_pci_free(struct drm_device *dev, struct drm_dma_handle * dmah);
|
||||
|
||||
extern int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
|
||||
extern void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
|
||||
int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver);
|
||||
void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver);
|
||||
#ifdef CONFIG_PCI
|
||||
extern int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
extern int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
|
||||
int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
struct drm_driver *driver);
|
||||
int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master);
|
||||
#else
|
||||
static inline int drm_get_pci_dev(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent,
|
||||
|
@ -69,7 +69,7 @@ static inline int drm_pci_set_busid(struct drm_device *dev,
|
|||
#define DRM_PCIE_SPEED_50 2
|
||||
#define DRM_PCIE_SPEED_80 4
|
||||
|
||||
extern int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
|
||||
extern int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
|
||||
int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *speed_mask);
|
||||
int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw);
|
||||
|
||||
#endif /* _DRM_PCI_H_ */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
struct drm_crtc;
|
||||
struct drm_printer;
|
||||
struct drm_modeset_acquire_ctx;
|
||||
|
||||
/**
|
||||
* struct drm_plane_state - mutable plane state
|
||||
|
@ -184,7 +185,8 @@ struct drm_plane_funcs {
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @disable_plane:
|
||||
|
@ -201,7 +203,8 @@ struct drm_plane_funcs {
|
|||
*
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int (*disable_plane)(struct drm_plane *plane);
|
||||
int (*disable_plane)(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
/**
|
||||
* @destroy:
|
||||
|
@ -456,7 +459,6 @@ enum drm_plane_type {
|
|||
* @funcs: helper functions
|
||||
* @properties: property tracking for this plane
|
||||
* @type: type of plane (overlay, primary, cursor)
|
||||
* @state: current atomic state for this plane
|
||||
* @zpos_property: zpos property for this plane
|
||||
* @rotation_property: rotation property for this plane
|
||||
* @helper_private: mid-layer private data
|
||||
|
@ -473,6 +475,8 @@ struct drm_plane {
|
|||
* Protects modeset plane state, together with the &drm_crtc.mutex of
|
||||
* CRTC this plane is linked to (when active, getting activated or
|
||||
* getting disabled).
|
||||
*
|
||||
* For atomic drivers specifically this protects @state.
|
||||
*/
|
||||
struct drm_modeset_lock mutex;
|
||||
|
||||
|
@ -502,6 +506,19 @@ struct drm_plane {
|
|||
|
||||
const struct drm_plane_helper_funcs *helper_private;
|
||||
|
||||
/**
|
||||
* @state:
|
||||
*
|
||||
* Current atomic state for this plane.
|
||||
*
|
||||
* This is protected by @mutex. Note that nonblocking atomic commits
|
||||
* access the current plane state without taking locks. Either by going
|
||||
* through the &struct drm_atomic_state pointers, see
|
||||
* for_each_plane_in_state(), for_each_oldnew_plane_in_state(),
|
||||
* for_each_old_plane_in_state() and for_each_new_plane_in_state(). Or
|
||||
* through careful ordering of atomic commit operations as implemented
|
||||
* in the atomic helpers, see &struct drm_crtc_commit.
|
||||
*/
|
||||
struct drm_plane_state *state;
|
||||
|
||||
struct drm_property *zpos_property;
|
||||
|
@ -510,7 +527,7 @@ struct drm_plane {
|
|||
|
||||
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
|
||||
|
||||
extern __printf(8, 9)
|
||||
__printf(8, 9)
|
||||
int drm_universal_plane_init(struct drm_device *dev,
|
||||
struct drm_plane *plane,
|
||||
uint32_t possible_crtcs,
|
||||
|
@ -519,13 +536,13 @@ int drm_universal_plane_init(struct drm_device *dev,
|
|||
unsigned int format_count,
|
||||
enum drm_plane_type type,
|
||||
const char *name, ...);
|
||||
extern int drm_plane_init(struct drm_device *dev,
|
||||
struct drm_plane *plane,
|
||||
uint32_t possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
bool is_primary);
|
||||
extern void drm_plane_cleanup(struct drm_plane *plane);
|
||||
int drm_plane_init(struct drm_device *dev,
|
||||
struct drm_plane *plane,
|
||||
uint32_t possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
bool is_primary);
|
||||
void drm_plane_cleanup(struct drm_plane *plane);
|
||||
|
||||
/**
|
||||
* drm_plane_index - find the index of a registered plane
|
||||
|
@ -538,8 +555,8 @@ static inline unsigned int drm_plane_index(struct drm_plane *plane)
|
|||
{
|
||||
return plane->index;
|
||||
}
|
||||
extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
|
||||
extern void drm_plane_force_disable(struct drm_plane *plane);
|
||||
struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
|
||||
void drm_plane_force_disable(struct drm_plane *plane);
|
||||
|
||||
int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
|
||||
struct drm_property *property,
|
||||
|
|
|
@ -61,8 +61,10 @@ int drm_primary_helper_update(struct drm_plane *plane,
|
|||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h);
|
||||
int drm_primary_helper_disable(struct drm_plane *plane);
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
int drm_primary_helper_disable(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
void drm_primary_helper_destroy(struct drm_plane *plane);
|
||||
extern const struct drm_plane_funcs drm_primary_helper_funcs;
|
||||
|
||||
|
|
|
@ -57,24 +57,24 @@ struct drm_device;
|
|||
struct drm_gem_object;
|
||||
struct drm_file;
|
||||
|
||||
extern struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
|
||||
struct drm_gem_object *obj,
|
||||
int flags);
|
||||
extern int drm_gem_prime_handle_to_fd(struct drm_device *dev,
|
||||
struct drm_file *file_priv, uint32_t handle, uint32_t flags,
|
||||
int *prime_fd);
|
||||
extern struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
extern int drm_gem_prime_fd_to_handle(struct drm_device *dev,
|
||||
struct drm_file *file_priv, int prime_fd, uint32_t *handle);
|
||||
struct dma_buf *drm_gem_prime_export(struct drm_device *dev,
|
||||
struct drm_gem_object *obj,
|
||||
int flags);
|
||||
int drm_gem_prime_handle_to_fd(struct drm_device *dev,
|
||||
struct drm_file *file_priv, uint32_t handle, uint32_t flags,
|
||||
int *prime_fd);
|
||||
struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
||||
struct dma_buf *dma_buf);
|
||||
int drm_gem_prime_fd_to_handle(struct drm_device *dev,
|
||||
struct drm_file *file_priv, int prime_fd, uint32_t *handle);
|
||||
struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev,
|
||||
struct dma_buf_export_info *exp_info);
|
||||
extern void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
|
||||
void drm_gem_dmabuf_release(struct dma_buf *dma_buf);
|
||||
|
||||
extern int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
||||
dma_addr_t *addrs, int max_pages);
|
||||
extern struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
|
||||
extern void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
|
||||
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
||||
dma_addr_t *addrs, int max_pages);
|
||||
struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages);
|
||||
void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg);
|
||||
|
||||
|
||||
#endif /* __DRM_PRIME_H__ */
|
||||
|
|
|
@ -129,6 +129,8 @@ static inline int drm_scdc_writeb(struct i2c_adapter *adapter, u8 offset,
|
|||
return drm_scdc_write(adapter, offset, &value, sizeof(value));
|
||||
}
|
||||
|
||||
bool drm_scdc_get_scrambling_status(struct i2c_adapter *adapter);
|
||||
|
||||
/**
|
||||
* drm_scdc_set_scrambling - enable scrambling
|
||||
* @adapter: I2C adapter for DDC channel
|
||||
|
|
|
@ -72,7 +72,7 @@ struct drm_simple_display_pipe_funcs {
|
|||
* the hardware lacks vblank support entirely.
|
||||
*/
|
||||
void (*update)(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_plane_state *plane_state);
|
||||
struct drm_plane_state *old_plane_state);
|
||||
|
||||
/**
|
||||
* @prepare_fb:
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* don't want to include the full drmP.h file.
|
||||
*/
|
||||
|
||||
extern int drm_class_device_register(struct device *dev);
|
||||
extern void drm_class_device_unregister(struct device *dev);
|
||||
int drm_class_device_register(struct device *dev);
|
||||
void drm_class_device_unregister(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -58,8 +58,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
|
|||
.gem_prime_mmap = drm_gem_cma_prime_mmap, \
|
||||
.dumb_create = drm_gem_cma_dumb_create, \
|
||||
.dumb_map_offset = drm_gem_cma_dumb_map_offset, \
|
||||
.dumb_destroy = drm_gem_dumb_destroy, \
|
||||
.fops = &tinydrm_fops
|
||||
.dumb_destroy = drm_gem_dumb_destroy
|
||||
|
||||
/**
|
||||
* TINYDRM_MODE - tinydrm display mode
|
||||
|
@ -84,7 +83,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe)
|
|||
.type = DRM_MODE_TYPE_DRIVER, \
|
||||
.clock = 1 /* pass validation */
|
||||
|
||||
extern const struct file_operations tinydrm_fops;
|
||||
void tinydrm_lastclose(struct drm_device *drm);
|
||||
void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj);
|
||||
struct drm_gem_object *
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue