Commit df45eaca authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc into drm-next

Last drm-misc-next pull req for 4.12

Core changes:
 - fb_helper checkpatch cleanup and simplified _add_one_connector() (Thierry)
 - drm_ioctl and drm_sysfs improved/gained documentation (Daniel)
 - [ABI] Repurpose reserved field in drm_event_vblank for crtc_id (Ander)
 - Plumb acquire ctx through legacy paths to avoid lock_all and legacy_backoff
   (Daniel)
 - Add connector_atomic_check to check conn constraints on modeset (Maarten)
 - Add drm_of_find_panel_or_bridge to remove boilerplate in drivers (Rob)

Driver changes:
 - meson moved to drm-misc (Neil)
 - Added support for Amlogic GX SoCs in dw-hdmi (Neil)
 - Rockchip unbind actually cleans up the things bind initializes (Jeffy)
 - A couple misc fixes in virtio, dw-hdmi

NOTE: this also includes a backmerge of drm-next as well rc5 (we needed vmwgfx
      as well as the new synopsys media formats)

* tag 'drm-misc-next-2017-04-07' of git://anongit.freedesktop.org/git/drm-misc: (77 commits)
  Revert "drm: Don't allow interruptions when opening debugfs/crc"
  drm: Only take cursor locks when the cursor plane exists
  drm/vmwgfx: Fix fbdev emulation using legacy functions
  drm/rockchip: Shutdown all crtcs when unbinding drm
  drm/rockchip: Reorder drm bind/unbind sequence
  drm/rockchip: analogix_dp: Disable clock when unbinding
  drm/rockchip: vop: Unprepare clocks when unbinding
  drm/rockchip: vop: Enable pm domain before vop_initial
  drm/rockchip: cdn-dp: Don't unregister audio dev when unbinding
  drm/rockchip: cdn-dp: Don't try to release firmware when not loaded
  drm: bridge: analogix: Destroy connector & encoder when unbinding
  drm: bridge: analogix: Disable clock when unbinding
  drm: bridge: analogix: Unregister dp aux when unbinding
  drm: bridge: analogix: Detach panel when unbinding analogix dp
  drm: Don't allow interruptions when opening debugfs/crc
  drm/virtio: don't leak bo on drm_gem_object_init failure
  drm: bridge: dw-hdmi: fix input format/encoding from plat_data
  drm: omap: use common OF graph helpers
  drm: convert drivers to use drm_of_find_panel_or_bridge
  drm: convert drivers to use of_graph_get_remote_node
  ...
parents b769fefb c98cdff9
Amlogic specific extensions to the Synopsys Designware HDMI Controller
======================================================================
The Amlogic Meson Synopsys Designware Integration is composed of :
- A Synopsys DesignWare HDMI Controller IP
- A TOP control block controlling the Clocks and PHY
- A custom HDMI PHY in order to convert video to TMDS signal
___________________________________
| HDMI TOP |<= HPD
|___________________________________|
| | |
| Synopsys HDMI | HDMI PHY |=> TMDS
| Controller |________________|
|___________________________________|<=> DDC
The HDMI TOP block only supports HPD sensing.
The Synopsys HDMI Controller interrupt is routed through the
TOP Block interrupt.
Communication to the TOP Block and the Synopsys HDMI Controller is done
via a pair of dedicated addr+read/write registers.
The HDMI PHY is configured by registers in the HHI register block.
Pixel data arrives in 4:4:4 format from the VENC block and the VPU HDMI mux
selects either the ENCI encoder for the 576i or 480i formats or the ENCP
encoder for all the other formats including interlaced HD formats.
The VENC uses a DVI encoder on top of the ENCI or ENCP encoders to generate
DVI timings for the HDMI controller.
Amlogic Meson GXBB, GXL and GXM SoCs families embeds the Synopsys DesignWare
HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
audio source interfaces.
Required properties:
- compatible: value should be different for each SoC family as :
- GXBB (S905) : "amlogic,meson-gxbb-dw-hdmi"
- GXL (S905X, S905D) : "amlogic,meson-gxl-dw-hdmi"
- GXM (S912) : "amlogic,meson-gxm-dw-hdmi"
followed by the common "amlogic,meson-gx-dw-hdmi"
- reg: Physical base address and length of the controller's registers.
- interrupts: The HDMI interrupt number
- clocks, clock-names : must have the phandles to the HDMI iahb and isfr clocks,
and the Amlogic Meson venci clocks as described in
Documentation/devicetree/bindings/clock/clock-bindings.txt,
the clocks are soc specific, the clock-names should be "iahb", "isfr", "venci"
- resets, resets-names: must have the phandles to the HDMI apb, glue and phy
resets as described in :
Documentation/devicetree/bindings/reset/reset.txt,
the reset-names should be "hdmitx_apb", "hdmitx", "hdmitx_phy"
Required nodes:
The connections to the HDMI ports are modeled using the OF graph
bindings specified in Documentation/devicetree/bindings/graph.txt.
The following table lists for each supported model the port number
corresponding to each HDMI output and input.
Port 0 Port 1
-----------------------------------------
S905 (GXBB) VENC Input TMDS Output
S905X (GXL) VENC Input TMDS Output
S905D (GXL) VENC Input TMDS Output
S912 (GXM) VENC Input TMDS Output
Example:
hdmi-connector {
compatible = "hdmi-connector";
type = "a";
port {
hdmi_connector_in: endpoint {
remote-endpoint = <&hdmi_tx_tmds_out>;
};
};
};
hdmi_tx: hdmi-tx@c883a000 {
compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
reg = <0x0 0xc883a000 0x0 0x1c>;
interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
resets = <&reset RESET_HDMITX_CAPB3>,
<&reset RESET_HDMI_SYSTEM_RESET>,
<&reset RESET_HDMI_TX>;
reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
clocks = <&clkc CLKID_HDMI_PCLK>,
<&clkc CLKID_CLK81>,
<&clkc CLKID_GCLK_VENCI_INT0>;
clock-names = "isfr", "iahb", "venci";
#address-cells = <1>;
#size-cells = <0>;
/* VPU VENC Input */
hdmi_tx_venc_port: port@0 {
reg = <0>;
hdmi_tx_in: endpoint {
remote-endpoint = <&hdmi_tx_out>;
};
};
/* TMDS Output */
hdmi_tx_tmds_port: port@1 {
reg = <1>;
hdmi_tx_tmds_out: endpoint {
remote-endpoint = <&hdmi_connector_in>;
};
};
};
......@@ -17,9 +17,12 @@ Required properties:
Optional properties:
- power-domains: a phandle to mipi dsi power domain node.
- resets: list of phandle + reset specifier pairs, as described in [3].
- reset-names: string reset name, must be "apb".
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Documentation/devicetree/bindings/media/video-interfaces.txt
[3] Documentation/devicetree/bindings/reset/reset.txt
Example:
mipi_dsi: mipi@ff960000 {
......@@ -30,6 +33,8 @@ Example:
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_MIPI_24M>, <&cru PCLK_MIPI_DSI0>;
clock-names = "ref", "pclk";
resets = <&cru SRST_MIPIDSI0>;
reset-names = "apb";
rockchip,grf = <&grf>;
status = "okay";
......
=======================================================
drm/bridge/dw-hdmi Synopsys DesignWare HDMI Controller
=======================================================
Synopsys DesignWare HDMI Controller
===================================
This section covers everything related to the Synopsys DesignWare HDMI
Controller implemented as a DRM bridge.
Supported Input Formats and Encodings
-------------------------------------
.. kernel-doc:: include/drm/bridge/dw_hdmi.h
:doc: Supported input formats and encodings
......@@ -255,56 +255,6 @@ File Operations
.. kernel-doc:: drivers/gpu/drm/drm_file.c
:export:
IOCTLs
------
struct drm_ioctl_desc \*ioctls; int num_ioctls;
Driver-specific ioctls descriptors table.
Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls
descriptors table is indexed by the ioctl number offset from the base
value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize
the table entries.
::
DRM_IOCTL_DEF_DRV(ioctl, func, flags)
``ioctl`` is the ioctl name. Drivers must define the DRM_##ioctl and
DRM_IOCTL_##ioctl macros to the ioctl number offset from
DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
private to the device while the second must be exposed to userspace in a
public header.
``func`` is a pointer to the ioctl handler function compatible with the
``drm_ioctl_t`` type.
::
typedef int drm_ioctl_t(struct drm_device *dev, void *data,
struct drm_file *file_priv);
``flags`` is a bitmask combination of the following values. It restricts
how the ioctl is allowed to be called.
- DRM_AUTH - Only authenticated callers allowed
- DRM_MASTER - The ioctl can only be called on the master file handle
- DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
- DRM_CONTROL_ALLOW - The ioctl can only be called on a control
device
- DRM_UNLOCKED - The ioctl handler will be called without locking the
DRM global mutex. This is the enforced default for kms drivers (i.e.
using the DRIVER_MODESET flag) and hence shouldn't be used any more
for new drivers.
.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
:export:
Misc Utilities
==============
......
......@@ -160,6 +160,20 @@ other hand, a driver requires shared state between clients which is
visible to user-space and accessible beyond open-file boundaries, they
cannot support render nodes.
IOCTL Support on Device Nodes
=============================
.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
:doc: driver specific ioctls
.. kernel-doc:: include/drm/drm_ioctl.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
:export:
.. kernel-doc:: drivers/gpu/drm/drm_ioc32.c
:export:
Testing and validation
======================
......@@ -219,6 +233,16 @@ Debugfs Support
.. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
:export:
Sysfs Support
=============
.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
:export:
VBlank event handling
=====================
......
......@@ -11,10 +11,12 @@ Linux GPU Driver Developer's Guide
drm-kms-helpers
drm-uapi
i915
meson
tinydrm
vc4
vga-switcheroo
vgaarbiter
bridge/dw-hdmi
todo
.. only:: subproject and html
......
=============================================
drm/meson AmLogic Meson Video Processing Unit
=============================================
.. kernel-doc:: drivers/gpu/drm/meson/meson_drv.c
:doc: Video Processing Unit
Video Processing Unit
=====================
The Amlogic Meson Display controller is composed of several components
that are going to be documented below:
.. code::
DMC|---------------VPU (Video Processing Unit)----------------|------HHI------|
| vd1 _______ _____________ _________________ | |
D |-------| |----| | | | | HDMI PLL |
D | vd2 | VIU | | Video Post | | Video Encoders |<---|-----VCLK |
R |-------| |----| Processing | | | | |
| osd2 | | | |---| Enci ----------|----|-----VDAC------|
R |-------| CSC |----| Scalers | | Encp ----------|----|----HDMI-TX----|
A | osd1 | | | Blenders | | Encl ----------|----|---------------|
M |-------|______|----|____________| |________________| | |
___|__________________________________________________________|_______________|
Video Input Unit
================
.. kernel-doc:: drivers/gpu/drm/meson/meson_viu.c
:doc: Video Input Unit
Video Post Processing
=====================
.. kernel-doc:: drivers/gpu/drm/meson/meson_vpp.c
:doc: Video Post Processing
Video Encoder
=============
.. kernel-doc:: drivers/gpu/drm/meson/meson_venc.c
:doc: Video Encoder
Video Canvas Management
=======================
.. kernel-doc:: drivers/gpu/drm/meson/meson_canvas.c
:doc: Canvas
Video Clocks
============
.. kernel-doc:: drivers/gpu/drm/meson/meson_vclk.c
:doc: Video Clocks
HDMI Video Output
=================
.. kernel-doc:: drivers/gpu/drm/meson/meson_dw_hdmi.c
:doc: HDMI Output
......@@ -16,7 +16,7 @@ De-midlayer drivers
With the recent ``drm_bus`` cleanup patches for 3.17 it is no longer required
to have a ``drm_bus`` structure set up. Drivers can directly set up the
``drm_device`` structure instead of relying on bus methods in ``drm_usb.c``
and ``drm_platform.c``. The goal is to get rid of the driver's ``->load`` /
and ``drm_pci.c``. The goal is to get rid of the driver's ``->load`` /
``->unload`` callbacks and open-code the load/unload sequence properly, using
the new two-stage ``drm_device`` setup/teardown.
......@@ -175,7 +175,7 @@ fine-grained per-buffer object and per-context lockings scheme. Currently the
following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
``udl``.
Contact: Daniel Vetter
Contact: Daniel Vetter, respective driver maintainers
Switch to drm_connector_list_iter for any connector_list walking
----------------------------------------------------------------
......@@ -217,6 +217,8 @@ plan is to switch to per-file driver API headers, which will also structure
the kerneldoc better. This should also allow more fine-grained ``#include``
directives.
In the end no .c file should need to include ``drmP.h`` anymore.
Contact: Daniel Vetter
Add missing kerneldoc for exported functions
......@@ -244,13 +246,8 @@ be hidden so that driver writers don't accidentally end up using it. And to
prevent security issues in those legacy IOCTLs from being exploited on modern
drivers. This has multiple possible subtasks:
* Make sure legacy IOCTLs can't be used on modern drivers.
* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
module and compile it only when one of the legacy drivers is enabled.
* Extract legacy functions into their own headers and remove it that from the
monolithic ``drmP.h`` header.
* Remove any lingering cruft from the OS abstraction layer from modern
drivers.
This is mostly done, the only thing left is to split up ``drm_irq.c`` into
legacy cruft and the parts needed by modern KMS drivers.
......@@ -408,23 +405,3 @@ Contact: Noralf Trønnes, Daniel Vetter
Outside DRM
===========
Better kerneldoc
----------------
This is pretty much done, but there's some advanced topics:
Come up with a way to hyperlink to struct members. Currently you can hyperlink
to the struct using ``#struct_name``, but not to a member within. Would need
buy-in from kerneldoc maintainers, and the big question is how to make it work
without totally unsightly
``drm_foo_bar_really_long_structure->even_longer_memeber`` all over the text
which breaks text flow.
Figure out how to integrate the asciidoc support for ascii-diagrams. We have a
few of those (e.g. to describe mode timings), and asciidoc supports converting
some ascii-art dialect into pngs. Would be really pretty to make that work.
Contact: Daniel Vetter, Jani Nikula
Jani is working on this already, hopefully lands in 4.8.
......@@ -4256,7 +4256,8 @@ W: http://linux-meson.com/
S: Supported
F: drivers/gpu/drm/meson/
F: Documentation/devicetree/bindings/display/amlogic,meson-vpu.txt
T: git git://anongit.freedesktop.org/drm/drm-meson
F: Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.txt
F: Documentation/gpu/meson.rst
T: git git://anongit.freedesktop.org/drm/drm-misc
DRM DRIVERS FOR EXYNOS
......
......@@ -1059,7 +1059,11 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
int ret;
struct dma_buf *buf_obj;
struct dma_buf_attachment *attach_obj;
int count = 0, attach_count;
struct reservation_object *robj;
struct reservation_object_list *fobj;
struct dma_fence *fence;
unsigned seq;
int count = 0, attach_count, shared_count, i;
size_t size = 0;
ret = mutex_lock_interruptible(&db_list.lock);
......@@ -1068,7 +1072,8 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
return ret;
seq_puts(s, "\nDma-buf Objects:\n");
seq_puts(s, "size\tflags\tmode\tcount\texp_name\n");
seq_printf(s, "%-8s\t%-8s\t%-8s\t%-8s\texp_name\n",
"size", "flags", "mode", "count");
list_for_each_entry(buf_obj, &db_list.head, list_node) {
ret = mutex_lock_interruptible(&buf_obj->lock);
......@@ -1085,6 +1090,34 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused)
file_count(buf_obj->file),
buf_obj->exp_name);
robj = buf_obj->resv;
while (true) {
seq = read_seqcount_begin(&robj->seq);
rcu_read_lock();
fobj = rcu_dereference(robj->fence);
shared_count = fobj ? fobj->shared_count : 0;
fence = rcu_dereference(robj->fence_excl);
if (!read_seqcount_retry(&robj->seq, seq))
break;
rcu_read_unlock();
}
if (fence)
seq_printf(s, "\tExclusive fence: %s %s %ssignalled\n",
fence->ops->get_driver_name(fence),
fence->ops->get_timeline_name(fence),
dma_fence_is_signaled(fence) ? "" : "un");
for (i = 0; i < shared_count; i++) {
fence = rcu_dereference(fobj->shared[i]);
if (!dma_fence_get_rcu(fence))
continue;
seq_printf(s, "\tShared fence: %s %s %ssignalled\n",
fence->ops->get_driver_name(fence),
fence->ops->get_timeline_name(fence),
dma_fence_is_signaled(fence) ? "" : "un");
}
rcu_read_unlock();
seq_puts(s, "\tAttached Devices:\n");
attach_count = 0;
......
......@@ -2618,7 +2618,8 @@ static void dce_v10_0_cursor_reset(struct drm_crtc *crtc)
}
static int dce_v10_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int i;
......
......@@ -2638,7 +2638,8 @@ static void dce_v11_0_cursor_reset(struct drm_crtc *crtc)
}
static int dce_v11_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int i;
......
......@@ -1985,7 +1985,8 @@ static void dce_v6_0_cursor_reset(struct drm_crtc *crtc)
}
static int dce_v6_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int i;
......
......@@ -2469,7 +2469,8 @@ static void dce_v8_0_cursor_reset(struct drm_crtc *crtc)
}
static int dce_v8_0_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int i;
......
......@@ -165,7 +165,8 @@ static void dce_virtual_bandwidth_update(struct amdgpu_device *adev)
}
static int dce_virtual_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
u16 *green, u16 *blue, uint32_t size)
u16 *green, u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
int i;
......
......@@ -392,29 +392,13 @@ static int compare_dev(struct device *dev, void *data)
static int hdlcd_probe(struct platform_device *pdev)
{
struct device_node *port, *ep;
struct device_node *port;
struct component_match *match = NULL;
if (!pdev->dev.of_node)
return -ENODEV;
/* there is only one output port inside each device, find it */
ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
if (!ep)
return -ENODEV;
if (!of_device_is_available(ep)) {
of_node_put(ep);
port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
if (!port)
return -ENODEV;
}
/* add the remote encoder port as component */
port = of_graph_get_remote_port_parent(ep);
of_node_put(ep);
if (!port || !of_device_is_available(port)) {
of_node_put(port);
return -EAGAIN;
}
drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
of_node_put(port);
......
......@@ -283,7 +283,6 @@ static int malidp_bind(struct device *dev)
{
struct resource *res;
struct drm_device *drm;
struct device_node *ep;
struct malidp_drm *malidp;
struct malidp_hw_device *hwdev;
struct platform_device *pdev = to_platform_device(dev);
......@@ -398,12 +397,7 @@ static int malidp_bind(struct device *dev)
goto init_fail;
/* Set the CRTC's port so that the encoder component can find it */
ep = of_graph_get_next_endpoint(dev->of_node, NULL);
if (!ep) {
ret = -EINVAL;
goto port_fail;
}
malidp->crtc.port = of_get_next_parent(ep);
malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
ret = component_bind_all(dev, drm);
if (ret) {
......@@ -458,7 +452,6 @@ static int malidp_bind(struct device *dev)
bind_fail:
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
port_fail:
malidp_fini(drm);
init_fail:
drm->dev_private = NULL;
......@@ -516,29 +509,16 @@ static int malidp_compare_dev(struct device *dev, void *data)
static int malidp_platform_probe(struct platform_device *pdev)
{
struct device_node *port, *ep;
struct device_node *port;
struct component_match *match = NULL;
if (!pdev->dev.of_node)
return -ENODEV;
/* there is only one output port inside each device, find it */
ep = of_graph_get_next_endpoint(pdev->dev.of_node, NULL);
if (!ep)
return -ENODEV;
if (!of_device_is_available(ep)) {
of_node_put(ep);
port = of_graph_get_remote_node(pdev->dev.of_node, 0, 0);
if (!port)
return -ENODEV;
}
/* add the remote encoder port as component */
port = of_graph_get_remote_port_parent(ep);
of_node_put(ep);
if (!port || !of_device_is_available(port)) {
of_node_put(port);
return -EAGAIN;
}
drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
port);
......
......@@ -645,7 +645,8 @@ static void ast_crtc_reset(struct drm_crtc *crtc)
}
static int ast_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
int i;
......
......@@ -22,7 +22,7 @@
#include <linux/of_graph.h>
#include <drm/drmP.h>
#include <drm/drm_panel.h>
#include <drm/drm_of.h>
#include "atmel_hlcdc_dc.h"
......@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
const struct of_endpoint *ep)
{
struct device_node *np;
void *obj;
np = of_graph_get_remote_port_parent(ep->local_node);
obj = of_drm_find_panel(np);
if (!obj)
obj = of_drm_find_bridge(np);
of_node_put(np);
return obj ? 0 : -EPROBE_DEFER;
}
static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
const struct of_endpoint *ep)
const struct device_node *np)
{
struct atmel_hlcdc_dc *dc = dev->dev_private;
struct atmel_hlcdc_rgb_output *output;
struct device_node *np;
struct drm_panel *panel;
struct drm_bridge *bridge;
int ret;
......@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
output->encoder.possible_crtcs = 0x1;
np = of_graph_get_remote_port_parent(ep->local_node);
ret = -EPROBE_DEFER;
ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
if (ret)
return ret;
panel = of_drm_find_panel(np);
if (panel) {
of_node_put(np);
output->connector.dpms = DRM_MODE_DPMS_OFF;
output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
drm_connector_helper_add(&output->connector,
......@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
return 0;
}
bridge = of_drm_find_bridge(np);
of_node_put(np);
if (bridge) {
ret = drm_bridge_attach(&output->encoder, bridge, NULL);
if (!ret)
......@@ -243,31 +220,23 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
int atmel_hlcdc_create_outputs(struct drm_device *dev)
{
struct device_node *ep_np = NULL;
struct of_endpoint ep;
int ret;
for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
ret = of_graph_parse_endpoint(ep_np, &ep);
if (!ret)
ret = atmel_hlcdc_check_endpoint(dev, &ep);
if (ret) {
of_node_put(ep_np);
return ret;
}
}
for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
ret = of_graph_parse_endpoint(ep_np, &ep);
if (!ret)
ret = atmel_hlcdc_attach_endpoint(dev, &ep);
if (ret) {
of_node_put(ep_np);
struct device_node *remote;
int ret, endpoint = 0;
while (true) {
/* Loop thru possible multiple connections to the output */
remote = of_graph_get_remote_node(dev->dev->of_node, 0,
endpoint++);
if (!remote)
break;
ret = atmel_hlcdc_attach_endpoint(dev, remote);
of_node_put(remote);
if (ret)
return ret;
}
}
return 0;
if (!endpoint)
return -ENODEV;
return ret;
}
......@@ -232,7 +232,6 @@ void adv7533_detach_dsi(struct adv7511 *adv)
int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
{
u32 num_lanes;
struct device_node *endpoint;
of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
......@@ -241,17 +240,10 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
adv->num_dsi_lanes = num_lanes;
endpoint = of_graph_get_next_endpoint(np, NULL);
if (!endpoint)
adv->host_node = of_graph_get_remote_node(np, 0, 0);
if (!adv->host_node)
return -ENODEV;
adv->host_node = of_graph_get_remote_port_parent(endpoint);
if (!adv->host_node) {
of_node_put(endpoint);
return -ENODEV;
}
of_node_put(endpoint);
of_node_put(adv->host_node);
adv->use_timing_gen = !of_property_read_bool(np,
......
......@@ -1439,13 +1439,19 @@ void analogix_dp_unbind(struct device *dev, struct device *master,
struct analogix_dp_device *dp = dev_get_drvdata(dev);
analogix_dp_bridge_disable(dp->bridge);
dp->connector.funcs->destroy(&dp->connector);
dp->encoder->funcs->destroy(dp->encoder);
if (dp->plat_data->panel) {
if (drm_panel_unprepare(dp->plat_data->panel))
DRM_ERROR("failed to turnoff the panel\n");
if (drm_panel_detach(dp->plat_data->panel))
DRM_ERROR("failed to detach the panel\n");
}
drm_dp_aux_unregister(&dp->aux);
pm_runtime_disable(dev);
clk_disable_unprepare(dp->clock);
}
EXPORT_SYMBOL_GPL(analogix_dp_unbind);
......
......@@ -154,21 +154,12 @@ static const struct drm_bridge_funcs dumb_vga_bridge_funcs = {
static struct i2c_adapter *dumb_vga_retrieve_ddc(struct device *dev)
{
struct device_node *end_node, *phandle, *remote;
struct device_node *phandle, *remote;
struct i2c_adapter *ddc;
end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
if (!end_node) {
dev_err(dev, "Missing connector endpoint\n");
return ERR_PTR(-ENODEV);
}
remote = of_graph_get_remote_port_parent(end_node);
of_node_put(end_node);
if (!remote) {
dev_err(dev, "Enable to parse remote node\n");
remote = of_graph_get_remote_node(dev->of_node, 1, -1);
if (!remote)
return ERR_PTR(-EINVAL);
}
phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
of_node_put(remote);
......
......@@ -279,10 +279,6 @@ static int ge_b850v3_lvds_init(struct device *dev)
return -ENOMEM;
}
ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
drm_bridge_add(&ge_b850v3_lvds_ptr->bridge);
success:
mutex_unlock(&ge_b850v3_lvds_dev_mutex);
return 0;
......@@ -317,6 +313,11 @@ static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
/* drm bridge initialization */
ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
drm_bridge_add(&ge_b850v3_lvds_ptr->bridge);
/* Clear pending interrupts since power up. */
i2c_smbus_write_word_data(stdp4028_i2c,
STDP4028_DPTX_IRQ_STS_REG,
......
......@@ -20,8 +20,8 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include "drm_crtc.h"
......@@ -292,7 +292,6 @@ static int ptn3460_probe(struct i2c_client *client,
{
struct device *dev = &client->dev;
struct ptn3460_bridge *ptn_bridge;
struct device_node *endpoint, *panel_node;
int ret;
ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL);
......@@ -300,16 +299,9 @@ static int ptn3460_probe(struct i2c_client *client,
return -ENOMEM;
}
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
if (endpoint) {
panel_node = of_graph_get_remote_port_parent(endpoint);
if (panel_node) {
ptn_bridge->panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);
if (!ptn_bridge->panel)
return -EPROBE_DEFER;
}
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ptn_bridge->panel, NULL);
if (ret)
return ret;
ptn_bridge->client = client;
......
......@@ -22,10 +22,10 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/pm.h>
#include <linux/regulator/consumer.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include "drmP.h"
......@@ -536,7 +536,6 @@ static int ps8622_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *endpoint, *panel_node;
struct ps8622_bridge *ps8622;
int ret;
......@@ -544,16 +543,9 @@ static int ps8622_probe(struct i2c_client *client,
if (!ps8622)
return -ENOMEM;
endpoint = of_graph_get_next_endpoint(dev->of_node, NULL);
if (endpoint) {
panel_node = of_graph_get_remote_port_parent(endpoint);
if (panel_node) {
ps8622->panel = of_drm_find_panel(panel_node);
of_node_put(panel_node);
if (!ps8622->panel)
return -EPROBE_DEFER;
}
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &ps8622->panel, NULL);
if (ret)
return ret;
ps8622->client = client;
......
This diff is collapsed.
......@@ -1244,7 +1244,6 @@ static const struct regmap_config tc_regmap_config = {
static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *ep;
struct tc_data *tc;
int ret;
......@@ -1255,29 +1254,9 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
tc->dev = dev;
/* port@2 is the output port */
ep = of_graph_get_endpoint_by_regs(dev->of_node, 2, -1);
if (ep) {
struct device_node *remote;
remote = of_graph_get_remote_port_parent(ep);
if (!remote) {
dev_warn(dev, "endpoint %s not connected\n",
ep->full_name);
of_node_put(ep);
return -ENODEV;
}
of_node_put(ep);
tc->panel = of_drm_find_panel(remote);
if (tc->panel) {
dev_dbg(dev, "found panel %s\n", remote->full_name);
} else {
dev_dbg(dev, "waiting for panel %s\n",
remote->full_name);
of_node_put(remote);
return -EPROBE_DEFER;
}
of_node_put(remote);
}
ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &tc->panel, NULL);
if (ret)
return ret;
/* Shut down GPIO is optional */
tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH);
......
......@@ -165,18 +165,13 @@ static irqreturn_t tfp410_hpd_irq_thread(int irq, void *arg)
static int tfp410_get_connector_properties(struct tfp410 *dvi)
{
struct device_node *ep = NULL, *connector_node = NULL;
struct device_node *ddc_phandle = NULL;
struct device_node *connector_node, *ddc_phandle;
int ret = 0;
/* port@1 is the connector node */
ep = of_graph_get_endpoint_by_regs(dvi->dev->of_node, 1, -1);
if (!ep)
goto fail;
connector_node = of_graph_get_remote_port_parent(ep);
connector_node = of_graph_get_remote_node(dvi->dev->of_node, 1, -1);
if (!connector_node)
goto fail;
return -ENODEV;
dvi->hpd = fwnode_get_named_gpiod(&connector_node->fwnode,
"hpd-gpios", 0, GPIOD_IN, "hpd");
......@@ -199,10 +194,10 @@ static int tfp410_get_connector_properties(struct tfp410 *dvi)
else
ret = -EPROBE_DEFER;
of_node_put(ddc_phandle);
fail:
of_node_put(ep);
of_node_put(connector_node);
of_node_put(ddc_phandle);
return ret;
}
......
......@@ -327,7 +327,8 @@ static void cirrus_crtc_commit(struct drm_crtc *crtc)
* but it's a requirement that we provide the function
*/
static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
u16 *blue, uint32_t size,
struct drm_modeset_acquire_ctx *ctx)
{
struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
int i;
......
This diff is collapsed.
This diff is collapsed.
......@@ -218,28 +218,28 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
struct drm_crtc *crtc;
void *r_base, *g_base, *b_base;
int size;
struct drm_modeset_acquire_ctx ctx;
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
drm_modeset_lock_all(dev);
crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
if (!crtc) {
ret = -ENOENT;
goto out;
}
if (!crtc)
return -ENOENT;
if (crtc->funcs->gamma_set == NULL) {
ret = -ENOSYS;
goto out;
}
if (crtc->funcs->gamma_set == NULL)
return -ENOSYS;
/* memcpy into gamma store */
if (crtc_lut->gamma_size != crtc->gamma_size) {
ret = -EINVAL;
if (crtc_lut->gamma_size != crtc->gamma_size)
return -EINVAL;
drm_modeset_acquire_init(&ctx, 0);
retry:
ret = drm_modeset_lock_all_ctx(dev, &ctx);
if (ret)
goto out;
}
size = crtc_lut->gamma_size * (sizeof(uint16_t));
r_base = crtc->gamma_store;
......@@ -260,10 +260,17 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
goto out;
}
ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
crtc->gamma_size, &ctx);
out:
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;
}
......@@ -295,19 +302,15 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
drm_modeset_lock_all(dev);
crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
if (!crtc) {
ret = -ENOENT;
goto out;
}
if (!crtc)
return -ENOENT;
/* memcpy into gamma store */
if (crtc_lut->gamma_size != crtc->gamma_size) {
ret = -EINVAL;
goto out;
}
if (crtc_lut->gamma_size != crtc->gamma_size)
return -EINVAL;
drm_modeset_lock(&crtc->mutex, NULL);
size = crtc_lut->gamma_size * (sizeof(uint16_t));
r_base = crtc->gamma_store;
if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
......@@ -327,6 +330,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
goto out;
}
out:
drm_modeset_unlock_all(dev);
drm_modeset_unlock(&crtc->mutex);
return ret;
}
......@@ -576,6 +576,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
}
DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
mutex_lock(&crtc->dev->mode_config.mutex);
drm_modeset_acquire_init(&ctx, 0);
retry:
ret = drm_modeset_lock_all_ctx(crtc->dev, &ctx);
......@@ -721,6 +722,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
}
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
mutex_unlock(&crtc->dev->mode_config.mutex);
return ret;
}
......
......@@ -182,7 +182,6 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val);
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_atomic_remove_fb(struct drm_framebuffer *fb);
/* drm_plane.c */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -1026,6 +1026,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
e->pipe = pipe;
e->event.sequence = drm_vblank_count(dev, pipe);
e->event.crtc_id = crtc->base.id;
list_add_tail(&e->base.link, &dev->vblank_event_list);
}
EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
......@@ -1056,6 +1057,7 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
now = get_drm_timestamp();
}
e->pipe = pipe;
e->event.crtc_id = crtc->base.id;
send_vblank_event(dev, e, seq, &now);
}
EXPORT_SYMBOL(drm_crtc_send_vblank_event);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -177,7 +177,8 @@ void gma_crtc_load_lut(struct drm_crtc *crtc)
}
int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue,
u32 size)
u32 size,
struct drm_modeset_acquire_ctx *ctx)
{
struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
int i;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment