You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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
@@ -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);
|
||||
|
||||
|
||||
+52
-21
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user