drm-misc-next for v5.3:
UAPI Changes: Cross-subsystem Changes: - Add devicetree bindings for new panels. - Convert allwinner's DT bindings to a schema. - Drop video/hdmi static functions from kernel docs. - Discard old fence when reserving space in reservation_object_get_fences_rcu. Core Changes: - Add missing -ENOMEM handling in edid loading. - Fix null pointer deref in scheduler. - Header cleanups, making them self-contained. - Remove drmP.h inclusion from core. - Fix make htmldocs warning in scheduler and HDR metadata. - Fix a few warnings in the uapi header and add a doc section for it. - Small MST sideband error handling fix. - Clarify userspace review requirements. - Clarify implicit/explicit fencing in docs. - Flush output polling on shutdown. Driver Changes: - Small cleanups to stm. - Add new driver for ST-Ericsson MCDE - Kconfig fix for meson HDMI. - Add support for Armadeus ST0700 Adapt panel. - Add KOE tx14d24vm1bpa panel. - Update timings for st7701. - Fix compile error in mcde. - Big series of tc358767 fixes, and enabling support for IRQ and HPD handling. - Assorted fixes to sii902x, and implementing HDMI audio support. - Enable HDR metadata support on amdgpu. - Assorted fixes to atmel-hlcdc, and add sam9x60 LCD controller support. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAlz3iIMACgkQ/lWMcqZw E8NlwA/+NxCaUyuymD7dxw266Y4HlsL+jcba1pYOjuMpknnhb4HgDEgg//UekjSN UxskzNh4H4+DD4yphgsFn5wqkivlUxTFS+mt0FdrjT8h2gij4jQQ1k8EIMeuxg5P OHjJYwvHN2c/4fiQF9Fo5/nxYciN0erzcA7mFcbMeDIWtyO7BBr/6eXKl68G9FwH cXvpshNzVNvvpoaSpZLnxm/YkLDZNj1Io0+sVu2/w0AY0jmGEFFFpXxh42nnh4TL CwLzilfstJnXmJuM5nwcpUS1pV9IovauVDD3owGL5J1ZwiFy8j+e9GAA4kv6pf8C VsK3FynFt7u1BX26yfLWVLbCFF8wrpz5B3WZXrJLGiSpQi3zshpc/CMnchLfOdYf FijrQTrciVsQglxrDqqtaJ54ReF7wr5LWW3PhB1GYZRbQb9pZ4h4zroQQToFSkBa uxAEj9khJWgLhY6CeYzVbT1kShqjG7vjskDUbw493tZ+VqvL04Cy47npYi28iYxu hl+5maJY5KWnO6YTeJbuox3GjWelURtGhqfxbWhRAn1h74UQNjG8U9x5fWf3f4v7 YgZn4Z2UvHrs5XQdZE9sZm01vKFtQM7IHqfM5l2ZkKmKY/SQ1fII/XISOoaoLIZl X35WwB727OS4vTSCusd5QGKESh0WFtUB8dFM/NfXNQM7SGXtG/c= =GrAP -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2019-06-05' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.3: UAPI Changes: Cross-subsystem Changes: - Add devicetree bindings for new panels. - Convert allwinner's DT bindings to a schema. - Drop video/hdmi static functions from kernel docs. - Discard old fence when reserving space in reservation_object_get_fences_rcu. Core Changes: - Add missing -ENOMEM handling in edid loading. - Fix null pointer deref in scheduler. - Header cleanups, making them self-contained. - Remove drmP.h inclusion from core. - Fix make htmldocs warning in scheduler and HDR metadata. - Fix a few warnings in the uapi header and add a doc section for it. - Small MST sideband error handling fix. - Clarify userspace review requirements. - Clarify implicit/explicit fencing in docs. - Flush output polling on shutdown. Driver Changes: - Small cleanups to stm. - Add new driver for ST-Ericsson MCDE - Kconfig fix for meson HDMI. - Add support for Armadeus ST0700 Adapt panel. - Add KOE tx14d24vm1bpa panel. - Update timings for st7701. - Fix compile error in mcde. - Big series of tc358767 fixes, and enabling support for IRQ and HPD handling. - Assorted fixes to sii902x, and implementing HDMI audio support. - Enable HDR metadata support on amdgpu. - Assorted fixes to atmel-hlcdc, and add sam9x60 LCD controller support. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/6c43ffa9-11ff-5354-d772-c20fd4d1e3d9@linux.intel.com
This commit is contained in:
commit
141de1d46f
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/allwinner,sun6i-a31-mipi-dsi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Allwinner A31 MIPI-DSI Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Chen-Yu Tsai <wens@csie.org>
|
||||
- Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
|
||||
properties:
|
||||
"#address-cells": true
|
||||
"#size-cells": true
|
||||
|
||||
compatible:
|
||||
const: allwinner,sun6i-a31-mipi-dsi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock
|
||||
- description: Module Clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: mod
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
|
||||
phy-names:
|
||||
const: dphy
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
A port node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt. That
|
||||
port should be the input endpoint, usually coming from the
|
||||
associated TCON.
|
||||
|
||||
patternProperties:
|
||||
"^panel@[0-9]+$": true
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- phys
|
||||
- phy-names
|
||||
- resets
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi0: dsi@1ca0000 {
|
||||
compatible = "allwinner,sun6i-a31-mipi-dsi";
|
||||
reg = <0x01ca0000 0x1000>;
|
||||
interrupts = <0 89 4>;
|
||||
clocks = <&ccu 23>, <&ccu 96>;
|
||||
clock-names = "bus", "mod";
|
||||
resets = <&ccu 4>;
|
||||
phys = <&dphy0>;
|
||||
phy-names = "dphy";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "bananapi,lhr050h41", "ilitek,ili9881c";
|
||||
reg = <0>;
|
||||
power-gpios = <&pio 1 7 0>; /* PB07 */
|
||||
reset-gpios = <&r_pio 0 5 1>; /* PL05 */
|
||||
backlight = <&pwm_bl>;
|
||||
};
|
||||
|
||||
port {
|
||||
dsi0_in_tcon0: endpoint {
|
||||
remote-endpoint = <&tcon0_out_dsi0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -5,10 +5,44 @@ Required properties:
|
|||
- reg: i2c address of the bridge
|
||||
|
||||
Optional properties:
|
||||
- interrupts: describe the interrupt line used to inform the host
|
||||
- interrupts: describe the interrupt line used to inform the host
|
||||
about hotplug events.
|
||||
- reset-gpios: OF device-tree gpio specification for RST_N pin.
|
||||
|
||||
HDMI audio properties:
|
||||
- #sound-dai-cells: <0> or <1>. <0> if only i2s or spdif pin
|
||||
is wired, <1> if the both are wired. HDMI audio is
|
||||
configured only if this property is found.
|
||||
- sil,i2s-data-lanes: Array of up to 4 integers with values of 0-3
|
||||
Each integer indicates which i2s pin is connected to which
|
||||
audio fifo. The first integer selects i2s audio pin for the
|
||||
first audio fifo#0 (HDMI channels 1&2), second for fifo#1
|
||||
(HDMI channels 3&4), and so on. There is 4 fifos and 4 i2s
|
||||
pins (SD0 - SD3). Any i2s pin can be connected to any fifo,
|
||||
but there can be no gaps. E.g. an i2s pin must be mapped to
|
||||
fifo#0 and fifo#1 before mapping a channel to fifo#2. Default
|
||||
value is <0>, describing SD0 pin beiging routed to hdmi audio
|
||||
fifo #0.
|
||||
- clocks: phandle and clock specifier for each clock listed in
|
||||
the clock-names property
|
||||
- clock-names: "mclk"
|
||||
Describes SII902x MCLK input. MCLK is used to produce
|
||||
HDMI audio CTS values. This property is required if
|
||||
"#sound-dai-cells"-property is present. This property follows
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
consumer binding.
|
||||
|
||||
If HDMI audio is configured the sii902x device becomes an I2S
|
||||
and/or spdif audio codec component (e.g a digital audio sink),
|
||||
that can be used in configuring a full audio devices with
|
||||
simple-card or audio-graph-card binding. See their binding
|
||||
documents on how to describe the way the sii902x device is
|
||||
connected to the rest of the audio system:
|
||||
Documentation/devicetree/bindings/sound/simple-card.txt
|
||||
Documentation/devicetree/bindings/sound/audio-graph-card.txt
|
||||
Note: In case of the audio-graph-card binding the used port
|
||||
index should be 3.
|
||||
|
||||
Optional subnodes:
|
||||
- video input: this subnode can contain a video input port node
|
||||
to connect the bridge to a display controller output (See this
|
||||
|
@ -21,6 +55,12 @@ Example:
|
|||
compatible = "sil,sii9022";
|
||||
reg = <0x39>;
|
||||
reset-gpios = <&pioA 1 0>;
|
||||
|
||||
#sound-dai-cells = <0>;
|
||||
sil,i2s-data-lanes = < 0 1 2 >;
|
||||
clocks = <&mclk>;
|
||||
clock-names = "mclk";
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
|
|
@ -12,6 +12,7 @@ Optional properties:
|
|||
(active high shutdown input)
|
||||
- reset-gpios: OF device-tree gpio specification for RSTX pin
|
||||
(active low system reset)
|
||||
- toshiba,hpd-pin: TC358767 GPIO pin number to which HPD is connected to (0 or 1)
|
||||
- ports: the ports node can contain video interface port nodes to connect
|
||||
to a DPI/DSI source and to an eDP/DP sink according to [1][2]:
|
||||
- port@0: DSI input port
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Armadeus ST0700 Adapt. A Santek ST0700I5Y-RBSLW 7.0" WVGA (800x480) TFT with
|
||||
an adapter board.
|
||||
|
||||
Required properties:
|
||||
- compatible: "armadeus,st0700-adapt"
|
||||
- power-supply: see panel-common.txt
|
||||
|
||||
Optional properties:
|
||||
- backlight: see panel-common.txt
|
|
@ -0,0 +1,42 @@
|
|||
Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "koe,tx14d24vm1bpa"
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
- power-supply: single regulator to provide the supply voltage
|
||||
|
||||
Required nodes:
|
||||
- port: Parallel port mapping to connect this display
|
||||
|
||||
This panel needs single power supply voltage. Its backlight is conntrolled
|
||||
via PWM signal.
|
||||
|
||||
Example:
|
||||
--------
|
||||
|
||||
Example device-tree definition when connected to iMX53 based board
|
||||
|
||||
lcd_panel: lcd-panel {
|
||||
compatible = "koe,tx14d24vm1bpa";
|
||||
backlight = <&backlight_lcd>;
|
||||
power-supply = <®_3v3>;
|
||||
|
||||
port {
|
||||
lcd_panel_in: endpoint {
|
||||
remote-endpoint = <&lcd_display_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Then one needs to extend the dispX node:
|
||||
|
||||
lcd_display: disp1 {
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
lcd_display_out: endpoint {
|
||||
remote-endpoint = <&lcd_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1,93 +0,0 @@
|
|||
Allwinner A31 DSI Encoder
|
||||
=========================
|
||||
|
||||
The DSI pipeline consists of two separate blocks: the DSI controller
|
||||
itself, and its associated D-PHY.
|
||||
|
||||
DSI Encoder
|
||||
-----------
|
||||
|
||||
The DSI Encoder generates the DSI signal from the TCON's.
|
||||
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun6i-a31-mipi-dsi
|
||||
- reg: base address and size of memory-mapped region
|
||||
- interrupts: interrupt associated to this IP
|
||||
- clocks: phandles to the clocks feeding the DSI encoder
|
||||
* bus: the DSI interface clock
|
||||
* mod: the DSI module clock
|
||||
- clock-names: the clock names mentioned above
|
||||
- phys: phandle to the D-PHY
|
||||
- phy-names: must be "dphy"
|
||||
- resets: phandle to the reset controller driving the encoder
|
||||
|
||||
- ports: A ports node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt. The
|
||||
first port should be the input endpoint, usually coming from the
|
||||
associated TCON.
|
||||
|
||||
Any MIPI-DSI device attached to this should be described according to
|
||||
the bindings defined in ../mipi-dsi-bus.txt
|
||||
|
||||
D-PHY
|
||||
-----
|
||||
|
||||
Required properties:
|
||||
- compatible: value must be one of:
|
||||
* allwinner,sun6i-a31-mipi-dphy
|
||||
- reg: base address and size of memory-mapped region
|
||||
- clocks: phandles to the clocks feeding the DSI encoder
|
||||
* bus: the DSI interface clock
|
||||
* mod: the DSI module clock
|
||||
- clock-names: the clock names mentioned above
|
||||
- resets: phandle to the reset controller driving the encoder
|
||||
|
||||
Example:
|
||||
|
||||
dsi0: dsi@1ca0000 {
|
||||
compatible = "allwinner,sun6i-a31-mipi-dsi";
|
||||
reg = <0x01ca0000 0x1000>;
|
||||
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&ccu CLK_BUS_MIPI_DSI>,
|
||||
<&ccu CLK_DSI_SCLK>;
|
||||
clock-names = "bus", "mod";
|
||||
resets = <&ccu RST_BUS_MIPI_DSI>;
|
||||
phys = <&dphy0>;
|
||||
phy-names = "dphy";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "bananapi,lhr050h41", "ilitek,ili9881c";
|
||||
reg = <0>;
|
||||
power-gpios = <&pio 1 7 GPIO_ACTIVE_HIGH>; /* PB07 */
|
||||
reset-gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL05 */
|
||||
backlight = <&pwm_bl>;
|
||||
};
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0>;
|
||||
|
||||
dsi0_in_tcon0: endpoint {
|
||||
remote-endpoint = <&tcon0_out_dsi0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dphy0: d-phy@1ca1000 {
|
||||
compatible = "allwinner,sun6i-a31-mipi-dphy";
|
||||
reg = <0x01ca1000 0x1000>;
|
||||
clocks = <&ccu CLK_BUS_MIPI_DSI>,
|
||||
<&ccu CLK_DSI_DPHY>;
|
||||
clock-names = "bus", "mod";
|
||||
resets = <&ccu RST_BUS_MIPI_DSI>;
|
||||
#phy-cells = <0>;
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/allwinner,sun6i-a31-mipi-dphy.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Allwinner A31 MIPI D-PHY Controller Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Chen-Yu Tsai <wens@csie.org>
|
||||
- Maxime Ripard <maxime.ripard@bootlin.com>
|
||||
|
||||
properties:
|
||||
"#phy-cells":
|
||||
const: 0
|
||||
|
||||
compatible:
|
||||
const: allwinner,sun6i-a31-mipi-dphy
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Bus Clock
|
||||
- description: Module Clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: mod
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#phy-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- resets
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dphy0: d-phy@1ca1000 {
|
||||
compatible = "allwinner,sun6i-a31-mipi-dphy";
|
||||
reg = <0x01ca1000 0x1000>;
|
||||
clocks = <&ccu 23>, <&ccu 97>;
|
||||
clock-names = "bus", "mod";
|
||||
resets = <&ccu 4>;
|
||||
#phy-cells = <0>;
|
||||
};
|
||||
|
||||
...
|
|
@ -7,6 +7,7 @@ GPU Driver Documentation
|
|||
amdgpu
|
||||
amdgpu-dc
|
||||
i915
|
||||
mcde
|
||||
meson
|
||||
pl111
|
||||
tegra
|
||||
|
|
|
@ -10,3 +10,6 @@ Kernel clients
|
|||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_client.c
|
||||
:export:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_client_modeset.c
|
||||
:export:
|
||||
|
|
|
@ -85,9 +85,9 @@ leads to a few additional requirements:
|
|||
- The userspace side must be fully reviewed and tested to the standards of that
|
||||
userspace project. For e.g. mesa this means piglit testcases and review on the
|
||||
mailing list. This is again to ensure that the new interface actually gets the
|
||||
job done. The userspace-side reviewer should also provide at least an
|
||||
Acked-by on the kernel uAPI patch indicating that they've looked at how the
|
||||
kernel side is implementing the new feature being used.
|
||||
job done. The userspace-side reviewer should also provide an Acked-by on the
|
||||
kernel uAPI patch indicating that they believe the proposed uAPI is sound and
|
||||
sufficiently documented and validated for userspace's consumption.
|
||||
|
||||
- The userspace patches must be against the canonical upstream, not some vendor
|
||||
fork. This is to make sure that no one cheats on the review and testing
|
||||
|
@ -329,3 +329,12 @@ DRM_IOCTL_MODESET_CTL
|
|||
mode setting, since on many devices the vertical blank counter is
|
||||
reset to 0 at some point during modeset. Modern drivers should not
|
||||
call this any more since with kernel mode setting it is a no-op.
|
||||
|
||||
Userspace API Structures
|
||||
========================
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/drm_mode.h
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/uapi/drm/drm_mode.h
|
||||
:internal:
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
=======================================================
|
||||
drm/mcde ST-Ericsson MCDE Multi-channel display engine
|
||||
=======================================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/mcde/mcde_drv.c
|
||||
:doc: ST-Ericsson MCDE DRM Driver
|
|
@ -289,6 +289,9 @@ drm_fb_helper tasks
|
|||
these igt tests need to be fixed: kms_fbcon_fbt@psr and
|
||||
kms_fbcon_fbt@psr-suspend.
|
||||
|
||||
- The max connector argument for drm_fb_helper_init() and
|
||||
drm_fb_helper_fbdev_setup() isn't used anymore and can be removed.
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
|
|
|
@ -5128,6 +5128,13 @@ S: Maintained
|
|||
F: drivers/gpu/drm/tinydrm/st7735r.c
|
||||
F: Documentation/devicetree/bindings/display/sitronix,st7735r.txt
|
||||
|
||||
DRM DRIVER FOR ST-ERICSSON MCDE
|
||||
M: Linus Walleij <linus.walleij@linaro.org>
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
S: Maintained
|
||||
F: drivers/gpu/drm/mcde/
|
||||
F: Documentation/devicetree/bindings/display/ste,mcde.txt
|
||||
|
||||
DRM DRIVER FOR TDFX VIDEO CARDS
|
||||
S: Orphan / Obsolete
|
||||
F: drivers/gpu/drm/tdfx/
|
||||
|
|
|
@ -365,6 +365,10 @@ int reservation_object_get_fences_rcu(struct reservation_object *obj,
|
|||
GFP_NOWAIT | __GFP_NOWARN);
|
||||
if (!nshared) {
|
||||
rcu_read_unlock();
|
||||
|
||||
dma_fence_put(fence_excl);
|
||||
fence_excl = NULL;
|
||||
|
||||
nshared = krealloc(shared, sz, GFP_KERNEL);
|
||||
if (nshared) {
|
||||
shared = nshared;
|
||||
|
|
|
@ -350,6 +350,8 @@ source "drivers/gpu/drm/panfrost/Kconfig"
|
|||
|
||||
source "drivers/gpu/drm/aspeed/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/mcde/Kconfig"
|
||||
|
||||
# Keep legacy drivers last
|
||||
|
||||
menuconfig DRM_LEGACY
|
||||
|
|
|
@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_cache.o \
|
|||
drm_plane.o drm_color_mgmt.o drm_print.o \
|
||||
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
|
||||
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
|
||||
drm_atomic_uapi.o drm_hdcp.o
|
||||
drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o
|
||||
|
||||
drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
|
||||
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
||||
|
@ -118,3 +118,4 @@ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
|
|||
obj-$(CONFIG_DRM_LIMA) += lima/
|
||||
obj-$(CONFIG_DRM_PANFROST) += panfrost/
|
||||
obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
|
||||
obj-$(CONFIG_DRM_MCDE) += mcde/
|
||||
|
|
|
@ -3875,6 +3875,128 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec
|
|||
return result;
|
||||
}
|
||||
|
||||
static int fill_hdr_info_packet(const struct drm_connector_state *state,
|
||||
struct dc_info_packet *out)
|
||||
{
|
||||
struct hdmi_drm_infoframe frame;
|
||||
unsigned char buf[30]; /* 26 + 4 */
|
||||
ssize_t len;
|
||||
int ret, i;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
if (!state->hdr_output_metadata)
|
||||
return 0;
|
||||
|
||||
ret = drm_hdmi_infoframe_set_hdr_metadata(&frame, state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
len = hdmi_drm_infoframe_pack_only(&frame, buf, sizeof(buf));
|
||||
if (len < 0)
|
||||
return (int)len;
|
||||
|
||||
/* Static metadata is a fixed 26 bytes + 4 byte header. */
|
||||
if (len != 30)
|
||||
return -EINVAL;
|
||||
|
||||
/* Prepare the infopacket for DC. */
|
||||
switch (state->connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_HDMIA:
|
||||
out->hb0 = 0x87; /* type */
|
||||
out->hb1 = 0x01; /* version */
|
||||
out->hb2 = 0x1A; /* length */
|
||||
out->sb[0] = buf[3]; /* checksum */
|
||||
i = 1;
|
||||
break;
|
||||
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
out->hb0 = 0x00; /* sdp id, zero */
|
||||
out->hb1 = 0x87; /* type */
|
||||
out->hb2 = 0x1D; /* payload len - 1 */
|
||||
out->hb3 = (0x13 << 2); /* sdp version */
|
||||
out->sb[0] = 0x01; /* version */
|
||||
out->sb[1] = 0x1A; /* length */
|
||||
i = 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(&out->sb[i], &buf[4], 26);
|
||||
out->valid = true;
|
||||
|
||||
print_hex_dump(KERN_DEBUG, "HDR SB:", DUMP_PREFIX_NONE, 16, 1, out->sb,
|
||||
sizeof(out->sb), false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_hdr_metadata_different(const struct drm_connector_state *old_state,
|
||||
const struct drm_connector_state *new_state)
|
||||
{
|
||||
struct drm_property_blob *old_blob = old_state->hdr_output_metadata;
|
||||
struct drm_property_blob *new_blob = new_state->hdr_output_metadata;
|
||||
|
||||
if (old_blob != new_blob) {
|
||||
if (old_blob && new_blob &&
|
||||
old_blob->length == new_blob->length)
|
||||
return memcmp(old_blob->data, new_blob->data,
|
||||
old_blob->length);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
amdgpu_dm_connector_atomic_check(struct drm_connector *conn,
|
||||
struct drm_connector_state *new_con_state)
|
||||
{
|
||||
struct drm_atomic_state *state = new_con_state->state;
|
||||
struct drm_connector_state *old_con_state =
|
||||
drm_atomic_get_old_connector_state(state, conn);
|
||||
struct drm_crtc *crtc = new_con_state->crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
int ret;
|
||||
|
||||
if (!crtc)
|
||||
return 0;
|
||||
|
||||
if (is_hdr_metadata_different(old_con_state, new_con_state)) {
|
||||
struct dc_info_packet hdr_infopacket;
|
||||
|
||||
ret = fill_hdr_info_packet(new_con_state, &hdr_infopacket);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
new_crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(new_crtc_state))
|
||||
return PTR_ERR(new_crtc_state);
|
||||
|
||||
/*
|
||||
* DC considers the stream backends changed if the
|
||||
* static metadata changes. Forcing the modeset also
|
||||
* gives a simple way for userspace to switch from
|
||||
* 8bpc to 10bpc when setting the metadata to enter
|
||||
* or exit HDR.
|
||||
*
|
||||
* Changing the static metadata after it's been
|
||||
* set is permissible, however. So only force a
|
||||
* modeset if we're entering or exiting HDR.
|
||||
*/
|
||||
new_crtc_state->mode_changed =
|
||||
!old_con_state->hdr_output_metadata ||
|
||||
!new_con_state->hdr_output_metadata;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs
|
||||
amdgpu_dm_connector_helper_funcs = {
|
||||
/*
|
||||
|
@ -3885,6 +4007,7 @@ amdgpu_dm_connector_helper_funcs = {
|
|||
*/
|
||||
.get_modes = get_modes,
|
||||
.mode_valid = amdgpu_dm_connector_mode_valid,
|
||||
.atomic_check = amdgpu_dm_connector_atomic_check,
|
||||
};
|
||||
|
||||
static void dm_crtc_helper_disable(struct drm_crtc *crtc)
|
||||
|
@ -4693,6 +4816,10 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
|
|||
if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
|
||||
connector_type == DRM_MODE_CONNECTOR_eDP) {
|
||||
drm_object_attach_property(
|
||||
&aconnector->base.base,
|
||||
dm->ddev->mode_config.hdr_output_metadata_property, 0);
|
||||
|
||||
drm_connector_attach_vrr_capable_property(
|
||||
&aconnector->base);
|
||||
}
|
||||
|
@ -5781,7 +5908,9 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc);
|
||||
struct dc_surface_update dummy_updates[MAX_SURFACES];
|
||||
struct dc_stream_update stream_update;
|
||||
struct dc_info_packet hdr_packet;
|
||||
struct dc_stream_status *status = NULL;
|
||||
bool abm_changed, hdr_changed, scaling_changed;
|
||||
|
||||
memset(&dummy_updates, 0, sizeof(dummy_updates));
|
||||
memset(&stream_update, 0, sizeof(stream_update));
|
||||
|
@ -5798,11 +5927,19 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
|
||||
|
||||
if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state) &&
|
||||
(dm_new_crtc_state->abm_level == dm_old_crtc_state->abm_level))
|
||||
scaling_changed = is_scaling_state_different(dm_new_con_state,
|
||||
dm_old_con_state);
|
||||
|
||||
abm_changed = dm_new_crtc_state->abm_level !=
|
||||
dm_old_crtc_state->abm_level;
|
||||
|
||||
hdr_changed =
|
||||
is_hdr_metadata_different(old_con_state, new_con_state);
|
||||
|
||||
if (!scaling_changed && !abm_changed && !hdr_changed)
|
||||
continue;
|
||||
|
||||
if (is_scaling_state_different(dm_new_con_state, dm_old_con_state)) {
|
||||
if (scaling_changed) {
|
||||
update_stream_scaling_settings(&dm_new_con_state->base.crtc->mode,
|
||||
dm_new_con_state, (struct dc_stream_state *)dm_new_crtc_state->stream);
|
||||
|
||||
|
@ -5810,12 +5947,17 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
|
|||
stream_update.dst = dm_new_crtc_state->stream->dst;
|
||||
}
|
||||
|
||||
if (dm_new_crtc_state->abm_level != dm_old_crtc_state->abm_level) {
|
||||
if (abm_changed) {
|
||||
dm_new_crtc_state->stream->abm_level = dm_new_crtc_state->abm_level;
|
||||
|
||||
stream_update.abm_level = &dm_new_crtc_state->abm_level;
|
||||
}
|
||||
|
||||
if (hdr_changed) {
|
||||
fill_hdr_info_packet(new_con_state, &hdr_packet);
|
||||
stream_update.hdr_static_metadata = &hdr_packet;
|
||||
}
|
||||
|
||||
status = dc_stream_get_status(dm_new_crtc_state->stream);
|
||||
WARN_ON(!status);
|
||||
WARN_ON(!status->plane_count);
|
||||
|
@ -6161,6 +6303,11 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
|
||||
dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level;
|
||||
|
||||
ret = fill_hdr_info_packet(drm_new_conn_state,
|
||||
&new_stream->hdr_static_metadata);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) &&
|
||||
dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream)) {
|
||||
new_crtc_state->mode_changed = false;
|
||||
|
|
|
@ -32,9 +32,12 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/ati_pcigart.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_os_linux.h>
|
||||
#include <drm/drm_pci.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
|||
unsigned long mode_rate;
|
||||
struct videomode vm;
|
||||
unsigned long prate;
|
||||
unsigned int cfg;
|
||||
unsigned int mask = ATMEL_HLCDC_CLKDIV_MASK | ATMEL_HLCDC_CLKPOL;
|
||||
unsigned int cfg = 0;
|
||||
int div;
|
||||
|
||||
vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay;
|
||||
|
@ -101,7 +102,10 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
|||
(adj->crtc_hdisplay - 1) |
|
||||
((adj->crtc_vdisplay - 1) << 16));
|
||||
|
||||
cfg = ATMEL_HLCDC_CLKSEL;
|
||||
if (!crtc->dc->desc->fixed_clksrc) {
|
||||
cfg |= ATMEL_HLCDC_CLKSEL;
|
||||
mask |= ATMEL_HLCDC_CLKSEL;
|
||||
}
|
||||
|
||||
prate = 2 * clk_get_rate(crtc->dc->hlcdc->sys_clk);
|
||||
mode_rate = adj->crtc_clock * 1000;
|
||||
|
@ -132,11 +136,10 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
|||
|
||||
cfg |= ATMEL_HLCDC_CLKDIV(div);
|
||||
|
||||
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0),
|
||||
ATMEL_HLCDC_CLKSEL | ATMEL_HLCDC_CLKDIV_MASK |
|
||||
ATMEL_HLCDC_CLKPOL, cfg);
|
||||
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(0), mask, cfg);
|
||||
|
||||
cfg = 0;
|
||||
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
|
||||
cfg = state->output_mode << 8;
|
||||
|
||||
if (adj->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
cfg |= ATMEL_HLCDC_VSPOL;
|
||||
|
@ -144,9 +147,6 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
|||
if (adj->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
cfg |= ATMEL_HLCDC_HSPOL;
|
||||
|
||||
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
|
||||
cfg |= state->output_mode << 8;
|
||||
|
||||
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
|
||||
ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL |
|
||||
ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE |
|
||||
|
|
|
@ -364,6 +364,103 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = {
|
|||
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
|
||||
.layers = atmel_hlcdc_sama5d4_layers,
|
||||
};
|
||||
|
||||
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = {
|
||||
{
|
||||
.name = "base",
|
||||
.formats = &atmel_hlcdc_plane_rgb_formats,
|
||||
.regs_offset = 0x60,
|
||||
.id = 0,
|
||||
.type = ATMEL_HLCDC_BASE_LAYER,
|
||||
.cfgs_offset = 0x2c,
|
||||
.layout = {
|
||||
.xstride = { 2 },
|
||||
.default_color = 3,
|
||||
.general_config = 4,
|
||||
.disc_pos = 5,
|
||||
.disc_size = 6,
|
||||
},
|
||||
.clut_offset = 0x600,
|
||||
},
|
||||
{
|
||||
.name = "overlay1",
|
||||
.formats = &atmel_hlcdc_plane_rgb_formats,
|
||||
.regs_offset = 0x160,
|
||||
.id = 1,
|
||||
.type = ATMEL_HLCDC_OVERLAY_LAYER,
|
||||
.cfgs_offset = 0x2c,
|
||||
.layout = {
|
||||
.pos = 2,
|
||||
.size = 3,
|
||||
.xstride = { 4 },
|
||||
.pstride = { 5 },
|
||||
.default_color = 6,
|
||||
.chroma_key = 7,
|
||||
.chroma_key_mask = 8,
|
||||
.general_config = 9,
|
||||
},
|
||||
.clut_offset = 0xa00,
|
||||
},
|
||||
{
|
||||
.name = "overlay2",
|
||||
.formats = &atmel_hlcdc_plane_rgb_formats,
|
||||
.regs_offset = 0x260,
|
||||
.id = 2,
|
||||
.type = ATMEL_HLCDC_OVERLAY_LAYER,
|
||||
.cfgs_offset = 0x2c,
|
||||
.layout = {
|
||||
.pos = 2,
|
||||
.size = 3,
|
||||
.xstride = { 4 },
|
||||
.pstride = { 5 },
|
||||
.default_color = 6,
|
||||
.chroma_key = 7,
|
||||
.chroma_key_mask = 8,
|
||||
.general_config = 9,
|
||||
},
|
||||
.clut_offset = 0xe00,
|
||||
},
|
||||
{
|
||||
.name = "high-end-overlay",
|
||||
.formats = &atmel_hlcdc_plane_rgb_and_yuv_formats,
|
||||
.regs_offset = 0x360,
|
||||
.id = 3,
|
||||
.type = ATMEL_HLCDC_OVERLAY_LAYER,
|
||||
.cfgs_offset = 0x4c,
|
||||
.layout = {
|
||||
.pos = 2,
|
||||
.size = 3,
|
||||
.memsize = 4,
|
||||
.xstride = { 5, 7 },
|
||||
.pstride = { 6, 8 },
|
||||
.default_color = 9,
|
||||
.chroma_key = 10,
|
||||
.chroma_key_mask = 11,
|
||||
.general_config = 12,
|
||||
.scaler_config = 13,
|
||||
.phicoeffs = {
|
||||
.x = 17,
|
||||
.y = 33,
|
||||
},
|
||||
.csc = 14,
|
||||
},
|
||||
.clut_offset = 0x1200,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = {
|
||||
.min_width = 0,
|
||||
.min_height = 0,
|
||||
.max_width = 2048,
|
||||
.max_height = 2048,
|
||||
.max_spw = 0xff,
|
||||
.max_vpw = 0xff,
|
||||
.max_hpw = 0x3ff,
|
||||
.fixed_clksrc = true,
|
||||
.nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers),
|
||||
.layers = atmel_hlcdc_sam9x60_layers,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_hlcdc_of_match[] = {
|
||||
{
|
||||
.compatible = "atmel,at91sam9n12-hlcdc",
|
||||
|
@ -385,6 +482,10 @@ static const struct of_device_id atmel_hlcdc_of_match[] = {
|
|||
.compatible = "atmel,sama5d4-hlcdc",
|
||||
.data = &atmel_hlcdc_dc_sama5d4,
|
||||
},
|
||||
{
|
||||
.compatible = "microchip,sam9x60-hlcdc",
|
||||
.data = &atmel_hlcdc_dc_sam9x60,
|
||||
},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match);
|
||||
|
@ -625,10 +726,18 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
|
|||
dc->hlcdc = dev_get_drvdata(dev->dev->parent);
|
||||
dev->dev_private = dc;
|
||||
|
||||
if (dc->desc->fixed_clksrc) {
|
||||
ret = clk_prepare_enable(dc->hlcdc->sys_clk);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "failed to enable sys_clk\n");
|
||||
goto err_destroy_wq;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dc->hlcdc->periph_clk);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "failed to enable periph_clk\n");
|
||||
goto err_destroy_wq;
|
||||
goto err_sys_clk_disable;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev->dev);
|
||||
|
@ -664,6 +773,9 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
|
|||
err_periph_clk_disable:
|
||||
pm_runtime_disable(dev->dev);
|
||||
clk_disable_unprepare(dc->hlcdc->periph_clk);
|
||||
err_sys_clk_disable:
|
||||
if (dc->desc->fixed_clksrc)
|
||||
clk_disable_unprepare(dc->hlcdc->sys_clk);
|
||||
|
||||
err_destroy_wq:
|
||||
destroy_workqueue(dc->wq);
|
||||
|
@ -688,6 +800,8 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
|
|||
|
||||
pm_runtime_disable(dev->dev);
|
||||
clk_disable_unprepare(dc->hlcdc->periph_clk);
|
||||
if (dc->desc->fixed_clksrc)
|
||||
clk_disable_unprepare(dc->hlcdc->sys_clk);
|
||||
destroy_workqueue(dc->wq);
|
||||
}
|
||||
|
||||
|
@ -805,6 +919,8 @@ static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
|
|||
regmap_read(regmap, ATMEL_HLCDC_IMR, &dc->suspend.imr);
|
||||
regmap_write(regmap, ATMEL_HLCDC_IDR, dc->suspend.imr);
|
||||
clk_disable_unprepare(dc->hlcdc->periph_clk);
|
||||
if (dc->desc->fixed_clksrc)
|
||||
clk_disable_unprepare(dc->hlcdc->sys_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -814,6 +930,8 @@ static int atmel_hlcdc_dc_drm_resume(struct device *dev)
|
|||
struct drm_device *drm_dev = dev_get_drvdata(dev);
|
||||
struct atmel_hlcdc_dc *dc = drm_dev->dev_private;
|
||||
|
||||
if (dc->desc->fixed_clksrc)
|
||||
clk_prepare_enable(dc->hlcdc->sys_clk);
|
||||
clk_prepare_enable(dc->hlcdc->periph_clk);
|
||||
regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, dc->suspend.imr);
|
||||
|
||||
|
|
|
@ -328,6 +328,7 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
|
|||
* @max_hpw: maximum horizontal back/front porch width
|
||||
* @conflicting_output_formats: true if RGBXXX output formats conflict with
|
||||
* each other.
|
||||
* @fixed_clksrc: true if clock source is fixed
|
||||
* @layers: a layer description table describing available layers
|
||||
* @nlayers: layer description table size
|
||||
*/
|
||||
|
@ -340,6 +341,7 @@ struct atmel_hlcdc_dc_desc {
|
|||
int max_vpw;
|
||||
int max_hpw;
|
||||
bool conflicting_output_formats;
|
||||
bool fixed_clksrc;
|
||||
const struct atmel_hlcdc_layer_desc *layers;
|
||||
int nlayers;
|
||||
};
|
||||
|
|
|
@ -382,7 +382,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
|
|||
cfg |= ATMEL_HLCDC_LAYER_LAEN;
|
||||
else
|
||||
cfg |= ATMEL_HLCDC_LAYER_GAEN |
|
||||
ATMEL_HLCDC_LAYER_GA(state->base.alpha >> 8);
|
||||
ATMEL_HLCDC_LAYER_GA(state->base.alpha);
|
||||
}
|
||||
|
||||
if (state->disc_h && state->disc_w)
|
||||
|
|
|
@ -6,21 +6,21 @@
|
|||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <media/cec.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include <media/cec.h>
|
||||
|
||||
#include "adv7511.h"
|
||||
|
||||
/* ADI recommended values for proper operation. */
|
||||
|
|
|
@ -16,23 +16,23 @@
|
|||
*/
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "analogix-anx78xx.h"
|
||||
|
|
|
@ -10,26 +10,26 @@
|
|||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/phy/phy.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/bridge/analogix_dp.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "analogix_dp_core.h"
|
||||
#include "analogix_dp_reg.h"
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
struct dumb_vga {
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
* the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_graph.h>
|
||||
|
||||
struct lvds_encoder {
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *panel_bridge;
|
||||
|
|
|
@ -34,11 +34,12 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#define EDID_EXT_BLOCK_CNT 0x7E
|
||||
|
||||
|
|
|
@ -20,13 +20,14 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#define PTN3460_EDID_ADDR 0x0
|
||||
#define PTN3460_EDID_EMULATION_ADDR 0x84
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
* the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
struct panel_bridge {
|
||||
|
|
|
@ -24,12 +24,13 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
/* Brightness scale on the Parade chip */
|
||||
#define PS8622_MAX_BRIGHTNESS 0xff
|
||||
|
|
|
@ -27,12 +27,16 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include <sound/hdmi-codec.h>
|
||||
|
||||
#define SII902X_TPI_VIDEO_DATA 0x0
|
||||
|
||||
#define SII902X_TPI_PIXEL_REPETITION 0x8
|
||||
|
@ -74,6 +78,77 @@
|
|||
#define SII902X_AVI_POWER_STATE_MSK GENMASK(1, 0)
|
||||
#define SII902X_AVI_POWER_STATE_D(l) ((l) & SII902X_AVI_POWER_STATE_MSK)
|
||||
|
||||
/* Audio */
|
||||
#define SII902X_TPI_I2S_ENABLE_MAPPING_REG 0x1f
|
||||
#define SII902X_TPI_I2S_CONFIG_FIFO0 (0 << 0)
|
||||
#define SII902X_TPI_I2S_CONFIG_FIFO1 (1 << 0)
|
||||
#define SII902X_TPI_I2S_CONFIG_FIFO2 (2 << 0)
|
||||
#define SII902X_TPI_I2S_CONFIG_FIFO3 (3 << 0)
|
||||
#define SII902X_TPI_I2S_LEFT_RIGHT_SWAP (1 << 2)
|
||||
#define SII902X_TPI_I2S_AUTO_DOWNSAMPLE (1 << 3)
|
||||
#define SII902X_TPI_I2S_SELECT_SD0 (0 << 4)
|
||||
#define SII902X_TPI_I2S_SELECT_SD1 (1 << 4)
|
||||
#define SII902X_TPI_I2S_SELECT_SD2 (2 << 4)
|
||||
#define SII902X_TPI_I2S_SELECT_SD3 (3 << 4)
|
||||
#define SII902X_TPI_I2S_FIFO_ENABLE (1 << 7)
|
||||
|
||||
#define SII902X_TPI_I2S_INPUT_CONFIG_REG 0x20
|
||||
#define SII902X_TPI_I2S_FIRST_BIT_SHIFT_YES (0 << 0)
|
||||
#define SII902X_TPI_I2S_FIRST_BIT_SHIFT_NO (1 << 0)
|
||||
#define SII902X_TPI_I2S_SD_DIRECTION_MSB_FIRST (0 << 1)
|
||||
#define SII902X_TPI_I2S_SD_DIRECTION_LSB_FIRST (1 << 1)
|
||||
#define SII902X_TPI_I2S_SD_JUSTIFY_LEFT (0 << 2)
|
||||
#define SII902X_TPI_I2S_SD_JUSTIFY_RIGHT (1 << 2)
|
||||
#define SII902X_TPI_I2S_WS_POLARITY_LOW (0 << 3)
|
||||
#define SII902X_TPI_I2S_WS_POLARITY_HIGH (1 << 3)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_128 (0 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_256 (1 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_384 (2 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_512 (3 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_768 (4 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_1024 (5 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_1152 (6 << 4)
|
||||
#define SII902X_TPI_I2S_MCLK_MULTIPLIER_192 (7 << 4)
|
||||
#define SII902X_TPI_I2S_SCK_EDGE_FALLING (0 << 7)
|
||||
#define SII902X_TPI_I2S_SCK_EDGE_RISING (1 << 7)
|
||||
|
||||
#define SII902X_TPI_I2S_STRM_HDR_BASE 0x21
|
||||
#define SII902X_TPI_I2S_STRM_HDR_SIZE 5
|
||||
|
||||
#define SII902X_TPI_AUDIO_CONFIG_BYTE2_REG 0x26
|
||||
#define SII902X_TPI_AUDIO_CODING_STREAM_HEADER (0 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_PCM (1 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_AC3 (2 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_MPEG1 (3 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_MP3 (4 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_MPEG2 (5 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_AAC (6 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_DTS (7 << 0)
|
||||
#define SII902X_TPI_AUDIO_CODING_ATRAC (8 << 0)
|
||||
#define SII902X_TPI_AUDIO_MUTE_DISABLE (0 << 4)
|
||||
#define SII902X_TPI_AUDIO_MUTE_ENABLE (1 << 4)
|
||||
#define SII902X_TPI_AUDIO_LAYOUT_2_CHANNELS (0 << 5)
|
||||
#define SII902X_TPI_AUDIO_LAYOUT_8_CHANNELS (1 << 5)
|
||||
#define SII902X_TPI_AUDIO_INTERFACE_DISABLE (0 << 6)
|
||||
#define SII902X_TPI_AUDIO_INTERFACE_SPDIF (1 << 6)
|
||||
#define SII902X_TPI_AUDIO_INTERFACE_I2S (2 << 6)
|
||||
|
||||
#define SII902X_TPI_AUDIO_CONFIG_BYTE3_REG 0x27
|
||||
#define SII902X_TPI_AUDIO_FREQ_STREAM (0 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_32KHZ (1 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_44KHZ (2 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_48KHZ (3 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_88KHZ (4 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_96KHZ (5 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_176KHZ (6 << 3)
|
||||
#define SII902X_TPI_AUDIO_FREQ_192KHZ (7 << 3)
|
||||
#define SII902X_TPI_AUDIO_SAMPLE_SIZE_STREAM (0 << 6)
|
||||
#define SII902X_TPI_AUDIO_SAMPLE_SIZE_16 (1 << 6)
|
||||
#define SII902X_TPI_AUDIO_SAMPLE_SIZE_20 (2 << 6)
|
||||
#define SII902X_TPI_AUDIO_SAMPLE_SIZE_24 (3 << 6)
|
||||
|
||||
#define SII902X_TPI_AUDIO_CONFIG_BYTE4_REG 0x28
|
||||
|
||||
#define SII902X_INT_ENABLE 0x3c
|
||||
#define SII902X_INT_STATUS 0x3d
|
||||
#define SII902X_HOTPLUG_EVENT BIT(0)
|
||||
|
@ -81,6 +156,16 @@
|
|||
|
||||
#define SII902X_REG_TPI_RQB 0xc7
|
||||
|
||||
/* Indirect internal register access */
|
||||
#define SII902X_IND_SET_PAGE 0xbc
|
||||
#define SII902X_IND_OFFSET 0xbd
|
||||
#define SII902X_IND_VALUE 0xbe
|
||||
|
||||
#define SII902X_TPI_MISC_INFOFRAME_BASE 0xbf
|
||||
#define SII902X_TPI_MISC_INFOFRAME_END 0xde
|
||||
#define SII902X_TPI_MISC_INFOFRAME_SIZE \
|
||||
(SII902X_TPI_MISC_INFOFRAME_END - SII902X_TPI_MISC_INFOFRAME_BASE)
|
||||
|
||||
#define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS 500
|
||||
|
||||
struct sii902x {
|
||||
|
@ -90,6 +175,16 @@ struct sii902x {
|
|||
struct drm_connector connector;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct i2c_mux_core *i2cmux;
|
||||
/*
|
||||
* Mutex protects audio and video functions from interfering
|
||||
* each other, by keeping their i2c command sequences atomic.
|
||||
*/
|
||||
struct mutex mutex;
|
||||
struct sii902x_audio {
|
||||
struct platform_device *pdev;
|
||||
struct clk *mclk;
|
||||
u32 i2s_fifo_sequence[4];
|
||||
} audio;
|
||||
};
|
||||
|
||||
static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val)
|
||||
|
@ -161,8 +256,12 @@ sii902x_connector_detect(struct drm_connector *connector, bool force)
|
|||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
unsigned int status;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return (status & SII902X_PLUGGED_STATUS) ?
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
}
|
||||
|
@ -180,12 +279,18 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
{
|
||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
|
||||
struct edid *edid;
|
||||
int num = 0, ret;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
if (edid) {
|
||||
if (drm_detect_hdmi_monitor(edid))
|
||||
output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
|
||||
|
||||
num = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
}
|
||||
|
@ -193,9 +298,19 @@ static int sii902x_get_modes(struct drm_connector *connector)
|
|||
ret = drm_display_info_set_bus_formats(&connector->display_info,
|
||||
&bus_format, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error_out;
|
||||
|
||||
return num;
|
||||
ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);
|
||||
if (ret)
|
||||
goto error_out;
|
||||
|
||||
ret = num;
|
||||
|
||||
error_out:
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
|
||||
|
@ -215,20 +330,28 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
|
|||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_PWR_DWN,
|
||||
SII902X_SYS_CTRL_PWR_DWN);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
}
|
||||
|
||||
static void sii902x_bridge_enable(struct drm_bridge *bridge)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
|
||||
SII902X_AVI_POWER_STATE_MSK,
|
||||
SII902X_AVI_POWER_STATE_D(0));
|
||||
regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_PWR_DWN, 0);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
}
|
||||
|
||||
static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
|
@ -239,10 +362,11 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
|||
struct regmap *regmap = sii902x->regmap;
|
||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
struct hdmi_avi_infoframe frame;
|
||||
u16 pixel_clock_10kHz = adj->clock / 10;
|
||||
int ret;
|
||||
|
||||
buf[0] = adj->clock;
|
||||
buf[1] = adj->clock >> 8;
|
||||
buf[0] = pixel_clock_10kHz & 0xff;
|
||||
buf[1] = pixel_clock_10kHz >> 8;
|
||||
buf[2] = adj->vrefresh;
|
||||
buf[3] = 0x00;
|
||||
buf[4] = adj->hdisplay;
|
||||
|
@ -254,27 +378,32 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
|||
buf[9] = SII902X_TPI_AVI_INPUT_RANGE_AUTO |
|
||||
SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
|
||||
if (ret)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
|
||||
&sii902x->connector, adj);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("couldn't fill AVI infoframe\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Do not send the infoframe header, but keep the CRC field. */
|
||||
regmap_bulk_write(regmap, SII902X_TPI_AVI_INFOFRAME,
|
||||
buf + HDMI_INFOFRAME_HEADER_SIZE - 1,
|
||||
HDMI_AVI_INFOFRAME_SIZE + 1);
|
||||
|
||||
out:
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
}
|
||||
|
||||
static int sii902x_bridge_attach(struct drm_bridge *bridge)
|
||||
|
@ -315,6 +444,335 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = {
|
|||
.enable = sii902x_bridge_enable,
|
||||
};
|
||||
|
||||
static int sii902x_mute(struct sii902x *sii902x, bool mute)
|
||||
{
|
||||
struct device *dev = &sii902x->i2c->dev;
|
||||
unsigned int val = mute ? SII902X_TPI_AUDIO_MUTE_ENABLE :
|
||||
SII902X_TPI_AUDIO_MUTE_DISABLE;
|
||||
|
||||
dev_dbg(dev, "%s: %s\n", __func__, mute ? "Muted" : "Unmuted");
|
||||
|
||||
return regmap_update_bits(sii902x->regmap,
|
||||
SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
|
||||
SII902X_TPI_AUDIO_MUTE_ENABLE, val);
|
||||
}
|
||||
|
||||
static const int sii902x_mclk_div_table[] = {
|
||||
128, 256, 384, 512, 768, 1024, 1152, 192 };
|
||||
|
||||
static int sii902x_select_mclk_div(u8 *i2s_config_reg, unsigned int rate,
|
||||
unsigned int mclk)
|
||||
{
|
||||
int div = mclk / rate;
|
||||
int distance = 100000;
|
||||
u8 i, nearest = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sii902x_mclk_div_table); i++) {
|
||||
unsigned int d = abs(div - sii902x_mclk_div_table[i]);
|
||||
|
||||
if (d >= distance)
|
||||
continue;
|
||||
|
||||
nearest = i;
|
||||
distance = d;
|
||||
if (d == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
*i2s_config_reg |= nearest << 4;
|
||||
|
||||
return sii902x_mclk_div_table[nearest];
|
||||
}
|
||||
|
||||
static const struct sii902x_sample_freq {
|
||||
u32 freq;
|
||||
u8 val;
|
||||
} sii902x_sample_freq[] = {
|
||||
{ .freq = 32000, .val = SII902X_TPI_AUDIO_FREQ_32KHZ },
|
||||
{ .freq = 44000, .val = SII902X_TPI_AUDIO_FREQ_44KHZ },
|
||||
{ .freq = 48000, .val = SII902X_TPI_AUDIO_FREQ_48KHZ },
|
||||
{ .freq = 88000, .val = SII902X_TPI_AUDIO_FREQ_88KHZ },
|
||||
{ .freq = 96000, .val = SII902X_TPI_AUDIO_FREQ_96KHZ },
|
||||
{ .freq = 176000, .val = SII902X_TPI_AUDIO_FREQ_176KHZ },
|
||||
{ .freq = 192000, .val = SII902X_TPI_AUDIO_FREQ_192KHZ },
|
||||
};
|
||||
|
||||
static int sii902x_audio_hw_params(struct device *dev, void *data,
|
||||
struct hdmi_codec_daifmt *daifmt,
|
||||
struct hdmi_codec_params *params)
|
||||
{
|
||||
struct sii902x *sii902x = dev_get_drvdata(dev);
|
||||
u8 i2s_config_reg = SII902X_TPI_I2S_SD_DIRECTION_MSB_FIRST;
|
||||
u8 config_byte2_reg = (SII902X_TPI_AUDIO_INTERFACE_I2S |
|
||||
SII902X_TPI_AUDIO_MUTE_ENABLE |
|
||||
SII902X_TPI_AUDIO_CODING_PCM);
|
||||
u8 config_byte3_reg = 0;
|
||||
u8 infoframe_buf[HDMI_INFOFRAME_SIZE(AUDIO)];
|
||||
unsigned long mclk_rate;
|
||||
int i, ret;
|
||||
|
||||
if (daifmt->bit_clk_master || daifmt->frame_clk_master) {
|
||||
dev_dbg(dev, "%s: I2S master mode not supported\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (daifmt->fmt) {
|
||||
case HDMI_I2S:
|
||||
i2s_config_reg |= SII902X_TPI_I2S_FIRST_BIT_SHIFT_YES |
|
||||
SII902X_TPI_I2S_SD_JUSTIFY_LEFT;
|
||||
break;
|
||||
case HDMI_RIGHT_J:
|
||||
i2s_config_reg |= SII902X_TPI_I2S_SD_JUSTIFY_RIGHT;
|
||||
break;
|
||||
case HDMI_LEFT_J:
|
||||
i2s_config_reg |= SII902X_TPI_I2S_SD_JUSTIFY_LEFT;
|
||||
break;
|
||||
default:
|
||||
dev_dbg(dev, "%s: Unsupported i2s format %u\n", __func__,
|
||||
daifmt->fmt);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (daifmt->bit_clk_inv)
|
||||
i2s_config_reg |= SII902X_TPI_I2S_SCK_EDGE_FALLING;
|
||||
else
|
||||
i2s_config_reg |= SII902X_TPI_I2S_SCK_EDGE_RISING;
|
||||
|
||||
if (daifmt->frame_clk_inv)
|
||||
i2s_config_reg |= SII902X_TPI_I2S_WS_POLARITY_LOW;
|
||||
else
|
||||
i2s_config_reg |= SII902X_TPI_I2S_WS_POLARITY_HIGH;
|
||||
|
||||
if (params->channels > 2)
|
||||
config_byte2_reg |= SII902X_TPI_AUDIO_LAYOUT_8_CHANNELS;
|
||||
else
|
||||
config_byte2_reg |= SII902X_TPI_AUDIO_LAYOUT_2_CHANNELS;
|
||||
|
||||
switch (params->sample_width) {
|
||||
case 16:
|
||||
config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_16;
|
||||
break;
|
||||
case 20:
|
||||
config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_20;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
config_byte3_reg |= SII902X_TPI_AUDIO_SAMPLE_SIZE_24;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "%s: Unsupported sample width %u\n", __func__,
|
||||
params->sample_width);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sii902x_sample_freq); i++) {
|
||||
if (params->sample_rate == sii902x_sample_freq[i].freq) {
|
||||
config_byte3_reg |= sii902x_sample_freq[i].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(sii902x->audio.mclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "Enabling mclk failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mclk_rate = clk_get_rate(sii902x->audio.mclk);
|
||||
|
||||
ret = sii902x_select_mclk_div(&i2s_config_reg, params->sample_rate,
|
||||
mclk_rate);
|
||||
if (mclk_rate != ret * params->sample_rate)
|
||||
dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n",
|
||||
mclk_rate, ret, params->sample_rate);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
ret = regmap_write(sii902x->regmap,
|
||||
SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
|
||||
config_byte2_reg);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = regmap_write(sii902x->regmap, SII902X_TPI_I2S_INPUT_CONFIG_REG,
|
||||
i2s_config_reg);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; sii902x->audio.i2s_fifo_sequence[i] &&
|
||||
i < ARRAY_SIZE(sii902x->audio.i2s_fifo_sequence); i++)
|
||||
regmap_write(sii902x->regmap,
|
||||
SII902X_TPI_I2S_ENABLE_MAPPING_REG,
|
||||
sii902x->audio.i2s_fifo_sequence[i]);
|
||||
|
||||
ret = regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE3_REG,
|
||||
config_byte3_reg);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = regmap_bulk_write(sii902x->regmap, SII902X_TPI_I2S_STRM_HDR_BASE,
|
||||
params->iec.status,
|
||||
min((size_t) SII902X_TPI_I2S_STRM_HDR_SIZE,
|
||||
sizeof(params->iec.status)));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = hdmi_audio_infoframe_pack(¶ms->cea, infoframe_buf,
|
||||
sizeof(infoframe_buf));
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: Failed to pack audio infoframe: %d\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = regmap_bulk_write(sii902x->regmap,
|
||||
SII902X_TPI_MISC_INFOFRAME_BASE,
|
||||
infoframe_buf,
|
||||
min(ret, SII902X_TPI_MISC_INFOFRAME_SIZE));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Decode Level 0 Packets */
|
||||
ret = regmap_write(sii902x->regmap, SII902X_IND_SET_PAGE, 0x02);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = regmap_write(sii902x->regmap, SII902X_IND_OFFSET, 0x24);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = regmap_write(sii902x->regmap, SII902X_IND_VALUE, 0x02);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
dev_dbg(dev, "%s: hdmi audio enabled\n", __func__);
|
||||
out:
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
if (ret) {
|
||||
clk_disable_unprepare(sii902x->audio.mclk);
|
||||
dev_err(dev, "%s: hdmi audio enable failed: %d\n", __func__,
|
||||
ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sii902x_audio_shutdown(struct device *dev, void *data)
|
||||
{
|
||||
struct sii902x *sii902x = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
regmap_write(sii902x->regmap, SII902X_TPI_AUDIO_CONFIG_BYTE2_REG,
|
||||
SII902X_TPI_AUDIO_INTERFACE_DISABLE);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
clk_disable_unprepare(sii902x->audio.mclk);
|
||||
}
|
||||
|
||||
int sii902x_audio_digital_mute(struct device *dev, void *data, bool enable)
|
||||
{
|
||||
struct sii902x *sii902x = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
sii902x_mute(sii902x, enable);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sii902x_audio_get_eld(struct device *dev, void *data,
|
||||
uint8_t *buf, size_t len)
|
||||
{
|
||||
struct sii902x *sii902x = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
memcpy(buf, sii902x->connector.eld,
|
||||
min(sizeof(sii902x->connector.eld), len));
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hdmi_codec_ops sii902x_audio_codec_ops = {
|
||||
.hw_params = sii902x_audio_hw_params,
|
||||
.audio_shutdown = sii902x_audio_shutdown,
|
||||
.digital_mute = sii902x_audio_digital_mute,
|
||||
.get_eld = sii902x_audio_get_eld,
|
||||
};
|
||||
|
||||
static int sii902x_audio_codec_init(struct sii902x *sii902x,
|
||||
struct device *dev)
|
||||
{
|
||||
static const u8 audio_fifo_id[] = {
|
||||
SII902X_TPI_I2S_CONFIG_FIFO0,
|
||||
SII902X_TPI_I2S_CONFIG_FIFO1,
|
||||
SII902X_TPI_I2S_CONFIG_FIFO2,
|
||||
SII902X_TPI_I2S_CONFIG_FIFO3,
|
||||
};
|
||||
static const u8 i2s_lane_id[] = {
|
||||
SII902X_TPI_I2S_SELECT_SD0,
|
||||
SII902X_TPI_I2S_SELECT_SD1,
|
||||
SII902X_TPI_I2S_SELECT_SD2,
|
||||
SII902X_TPI_I2S_SELECT_SD3,
|
||||
};
|
||||
struct hdmi_codec_pdata codec_data = {
|
||||
.ops = &sii902x_audio_codec_ops,
|
||||
.i2s = 1, /* Only i2s support for now. */
|
||||
.spdif = 0,
|
||||
.max_i2s_channels = 0,
|
||||
};
|
||||
u8 lanes[4];
|
||||
u32 num_lanes, i;
|
||||
|
||||
if (!of_property_read_bool(dev->of_node, "#sound-dai-cells")) {
|
||||
dev_dbg(dev, "%s: No \"#sound-dai-cells\", no audio\n",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
num_lanes = of_property_read_variable_u8_array(dev->of_node,
|
||||
"sil,i2s-data-lanes",
|
||||
lanes, 1,
|
||||
ARRAY_SIZE(lanes));
|
||||
|
||||
if (num_lanes == -EINVAL) {
|
||||
dev_dbg(dev,
|
||||
"%s: No \"sil,i2s-data-lanes\", use default <0>\n",
|
||||
__func__);
|
||||
num_lanes = 1;
|
||||
lanes[0] = 0;
|
||||
} else if (num_lanes < 0) {
|
||||
dev_err(dev,
|
||||
"%s: Error gettin \"sil,i2s-data-lanes\": %d\n",
|
||||
__func__, num_lanes);
|
||||
return num_lanes;
|
||||
}
|
||||
codec_data.max_i2s_channels = 2 * num_lanes;
|
||||
|
||||
for (i = 0; i < num_lanes; i++)
|
||||
sii902x->audio.i2s_fifo_sequence[i] |= audio_fifo_id[i] |
|
||||
i2s_lane_id[lanes[i]] | SII902X_TPI_I2S_FIFO_ENABLE;
|
||||
|
||||
if (IS_ERR(sii902x->audio.mclk)) {
|
||||
dev_err(dev, "%s: No clock (audio mclk) found: %ld\n",
|
||||
__func__, PTR_ERR(sii902x->audio.mclk));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sii902x->audio.pdev = platform_device_register_data(
|
||||
dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO,
|
||||
&codec_data, sizeof(codec_data));
|
||||
|
||||
return PTR_ERR_OR_ZERO(sii902x->audio.pdev);
|
||||
}
|
||||
|
||||
static const struct regmap_range sii902x_volatile_ranges[] = {
|
||||
{ .range_min = 0, .range_max = 0xff },
|
||||
};
|
||||
|
@ -327,6 +785,8 @@ static const struct regmap_access_table sii902x_volatile_table = {
|
|||
static const struct regmap_config sii902x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.disable_locking = true, /* struct sii902x mutex should be enough */
|
||||
.max_register = SII902X_TPI_MISC_INFOFRAME_END,
|
||||
.volatile_table = &sii902x_volatile_table,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
};
|
||||
|
@ -336,9 +796,13 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
|||
struct sii902x *sii902x = data;
|
||||
unsigned int status = 0;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
|
||||
regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
|
||||
drm_helper_hpd_irq_event(sii902x->bridge.dev);
|
||||
|
||||
|
@ -460,6 +924,12 @@ static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_timings default_sii902x_timings = {
|
||||
.input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE
|
||||
| DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE
|
||||
| DRM_BUS_FLAG_DE_HIGH,
|
||||
};
|
||||
|
||||
static int sii902x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -493,6 +963,8 @@ static int sii902x_probe(struct i2c_client *client,
|
|||
return PTR_ERR(sii902x->reset_gpio);
|
||||
}
|
||||
|
||||
mutex_init(&sii902x->mutex);
|
||||
|
||||
sii902x_reset(sii902x);
|
||||
|
||||
ret = regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x0);
|
||||
|
@ -530,8 +1002,11 @@ static int sii902x_probe(struct i2c_client *client,
|
|||
|
||||
sii902x->bridge.funcs = &sii902x_bridge_funcs;
|
||||
sii902x->bridge.of_node = dev->of_node;
|
||||
sii902x->bridge.timings = &default_sii902x_timings;
|
||||
drm_bridge_add(&sii902x->bridge);
|
||||
|
||||
sii902x_audio_codec_init(sii902x, dev);
|
||||
|
||||
i2c_set_clientdata(client, sii902x);
|
||||
|
||||
sii902x->i2cmux = i2c_mux_alloc(client->adapter, dev,
|
||||
|
|
|
@ -11,34 +11,35 @@
|
|||
* (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/drm_scdc_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
#include <uapi/linux/media-bus-format.h>
|
||||
#include <uapi/linux/videodev2.h>
|
||||
|
||||
#include "dw-hdmi.h"
|
||||
#include <drm/bridge/dw_hdmi.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_scdc_helper.h>
|
||||
|
||||
#include "dw-hdmi-audio.h"
|
||||
#include "dw-hdmi-cec.h"
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
#include "dw-hdmi.h"
|
||||
|
||||
#define DDC_SEGMENT_ADDR 0x30
|
||||
|
||||
|
|
|
@ -15,15 +15,18 @@
|
|||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/reset.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/bridge/dw_mipi_dsi.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/bridge/dw_mipi_dsi.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define HWVER_131 0x31333100 /* IP version 1.31 */
|
||||
|
||||
|
|
|
@ -7,18 +7,22 @@
|
|||
* Maciej Purski <m.purski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
|
||||
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
/* System */
|
||||
#define TC_IDREG 0x0500
|
||||
#define SYSSTAT 0x0508
|
||||
#define SYSCTRL 0x0510
|
||||
#define DP0_AUDSRC_NO_INPUT (0 << 3)
|
||||
#define DP0_AUDSRC_I2S_RX (1 << 3)
|
||||
|
@ -78,6 +79,19 @@
|
|||
#define DP0_VIDSRC_DSI_RX (1 << 0)
|
||||
#define DP0_VIDSRC_DPI_RX (2 << 0)
|
||||
#define DP0_VIDSRC_COLOR_BAR (3 << 0)
|
||||
#define GPIOM 0x0540
|
||||
#define GPIOC 0x0544
|
||||
#define GPIOO 0x0548
|
||||
#define GPIOI 0x054c
|
||||
#define INTCTL_G 0x0560
|
||||
#define INTSTS_G 0x0564
|
||||
|
||||
#define INT_SYSERR BIT(16)
|
||||
#define INT_GPIO_H(x) (1 << (x == 0 ? 2 : 10))
|
||||
#define INT_GPIO_LC(x) (1 << (x == 0 ? 3 : 11))
|
||||
|
||||
#define INT_GP0_LCNT 0x0584
|
||||
#define INT_GP1_LCNT 0x0588
|
||||
|
||||
/* Control */
|
||||
#define DP0CTL 0x0600
|
||||
|
@ -186,11 +200,8 @@ module_param_named(test, tc_test_pattern, bool, 0644);
|
|||
struct tc_edp_link {
|
||||
struct drm_dp_link base;
|
||||
u8 assr;
|
||||
int scrambler_dis;
|
||||
int spread;
|
||||
int coding8b10b;
|
||||
u8 swing;
|
||||
u8 preemp;
|
||||
bool scrambler_dis;
|
||||
bool spread;
|
||||
};
|
||||
|
||||
struct tc_data {
|
||||
|
@ -208,7 +219,7 @@ struct tc_data {
|
|||
/* display edid */
|
||||
struct edid *edid;
|
||||
/* current mode */
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_display_mode mode;
|
||||
|
||||
u32 rev;
|
||||
u8 assr;
|
||||
|
@ -216,6 +227,12 @@ struct tc_data {
|
|||
struct gpio_desc *sd_gpio;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct clk *refclk;
|
||||
|
||||
/* do we have IRQ */
|
||||
bool have_irq;
|
||||
|
||||
/* HPD pin number (0 or 1) or -ENODEV */
|
||||
int hpd_pin;
|
||||
};
|
||||
|
||||
static inline struct tc_data *aux_to_tc(struct drm_dp_aux *a)
|
||||
|
@ -286,14 +303,17 @@ static int tc_aux_get_status(struct tc_data *tc, u8 *reply)
|
|||
ret = regmap_read(tc->regmap, DP0_AUXSTATUS, &value);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (value & AUX_BUSY) {
|
||||
if (value & AUX_TIMEOUT) {
|
||||
dev_err(tc->dev, "i2c access timeout!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
dev_err(tc->dev, "aux busy!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (value & AUX_TIMEOUT) {
|
||||
dev_err(tc->dev, "aux access timeout!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
*reply = (value & AUX_STATUS_MASK) >> AUX_STATUS_SHIFT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -387,13 +407,10 @@ static u32 tc_srcctrl(struct tc_data *tc)
|
|||
* No training pattern, skew lane 1 data by two LSCLK cycles with
|
||||
* respect to lane 0 data, AutoCorrect Mode = 0
|
||||
*/
|
||||
u32 reg = DP0_SRCCTRL_NOTP | DP0_SRCCTRL_LANESKEW;
|
||||
u32 reg = DP0_SRCCTRL_NOTP | DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_EN810B;
|
||||
|
||||
if (tc->link.scrambler_dis)
|
||||
reg |= DP0_SRCCTRL_SCRMBLDIS; /* Scrambler Disabled */
|
||||
if (tc->link.coding8b10b)
|
||||
/* Enable 8/10B Encoder (TxData[19:16] not used) */
|
||||
reg |= DP0_SRCCTRL_EN810B;
|
||||
if (tc->link.spread)
|
||||
reg |= DP0_SRCCTRL_SSCG; /* Spread Spectrum Enable */
|
||||
if (tc->link.base.num_lanes == 2)
|
||||
|
@ -545,7 +562,6 @@ static int tc_aux_link_setup(struct tc_data *tc)
|
|||
unsigned long rate;
|
||||
u32 value;
|
||||
int ret;
|
||||
u32 dp_phy_ctrl;
|
||||
|
||||
rate = clk_get_rate(tc->refclk);
|
||||
switch (rate) {
|
||||
|
@ -570,10 +586,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
|
|||
value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
|
||||
tc_write(SYS_PLLPARAM, value);
|
||||
|
||||
dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
|
||||
if (tc->link.base.num_lanes == 2)
|
||||
dp_phy_ctrl |= PHY_2LANE;
|
||||
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
|
||||
tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | PHY_A0_EN);
|
||||
|
||||
/*
|
||||
* Initially PLLs are in bypass. Force PLL parameter update,
|
||||
|
@ -590,8 +603,9 @@ static int tc_aux_link_setup(struct tc_data *tc)
|
|||
if (ret == -ETIMEDOUT) {
|
||||
dev_err(tc->dev, "Timeout waiting for PHY to become ready");
|
||||
return ret;
|
||||
} else if (ret)
|
||||
} else if (ret) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Setup AUX link */
|
||||
tc_write(DP0_AUXCFG1, AUX_RX_FILTER_EN |
|
||||
|
@ -627,13 +641,13 @@ static int tc_get_display_props(struct tc_data *tc)
|
|||
ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
tc->link.spread = tmp[0] & BIT(0); /* 0.5% down spread */
|
||||
tc->link.spread = tmp[0] & DP_MAX_DOWNSPREAD_0_5;
|
||||
|
||||
ret = drm_dp_dpcd_readb(&tc->aux, DP_MAIN_LINK_CHANNEL_CODING, tmp);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
tc->link.coding8b10b = tmp[0] & BIT(0);
|
||||
tc->link.scrambler_dis = 0;
|
||||
|
||||
tc->link.scrambler_dis = false;
|
||||
/* read assr */
|
||||
ret = drm_dp_dpcd_readb(&tc->aux, DP_EDP_CONFIGURATION_SET, tmp);
|
||||
if (ret < 0)
|
||||
|
@ -646,7 +660,9 @@ static int tc_get_display_props(struct tc_data *tc)
|
|||
tc->link.base.num_lanes,
|
||||
(tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) ?
|
||||
"enhanced" : "non-enhanced");
|
||||
dev_dbg(tc->dev, "ANSI 8B/10B: %d\n", tc->link.coding8b10b);
|
||||
dev_dbg(tc->dev, "Downspread: %s, scrambler: %s\n",
|
||||
tc->link.spread ? "0.5%" : "0.0%",
|
||||
tc->link.scrambler_dis ? "disabled" : "enabled");
|
||||
dev_dbg(tc->dev, "Display ASSR: %d, TC358767 ASSR: %d\n",
|
||||
tc->link.assr, tc->assr);
|
||||
|
||||
|
@ -744,89 +760,29 @@ static int tc_set_video_mode(struct tc_data *tc,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tc_link_training(struct tc_data *tc, int pattern)
|
||||
static int tc_wait_link_training(struct tc_data *tc)
|
||||
{
|
||||
const char * const *errors;
|
||||
u32 srcctrl = tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
|
||||
DP0_SRCCTRL_AUTOCORRECT;
|
||||
int timeout;
|
||||
int retry;
|
||||
u32 timeout = 1000;
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
if (pattern == DP_TRAINING_PATTERN_1) {
|
||||
srcctrl |= DP0_SRCCTRL_TP1;
|
||||
errors = training_pattern1_errors;
|
||||
} else {
|
||||
srcctrl |= DP0_SRCCTRL_TP2;
|
||||
errors = training_pattern2_errors;
|
||||
}
|
||||
|
||||
/* Set DPCD 0x102 for Training Part 1 or 2 */
|
||||
tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE | pattern);
|
||||
|
||||
tc_write(DP0_LTLOOPCTRL,
|
||||
(0x0f << 28) | /* Defer Iteration Count */
|
||||
(0x0f << 24) | /* Loop Iteration Count */
|
||||
(0x0d << 0)); /* Loop Timer Delay */
|
||||
|
||||
retry = 5;
|
||||
do {
|
||||
/* Set DP0 Training Pattern */
|
||||
tc_write(DP0_SRCCTRL, srcctrl);
|
||||
udelay(1);
|
||||
tc_read(DP0_LTSTAT, &value);
|
||||
} while ((!(value & LT_LOOPDONE)) && (--timeout));
|
||||
|
||||
/* Enable DP0 to start Link Training */
|
||||
tc_write(DP0CTL, DP_EN);
|
||||
|
||||
/* wait */
|
||||
timeout = 1000;
|
||||
do {
|
||||
tc_read(DP0_LTSTAT, &value);
|
||||
udelay(1);
|
||||
} while ((!(value & LT_LOOPDONE)) && (--timeout));
|
||||
if (timeout == 0) {
|
||||
dev_err(tc->dev, "Link training timeout!\n");
|
||||
} else {
|
||||
int pattern = (value >> 11) & 0x3;
|
||||
int error = (value >> 8) & 0x7;
|
||||
|
||||
dev_dbg(tc->dev,
|
||||
"Link training phase %d done after %d uS: %s\n",
|
||||
pattern, 1000 - timeout, errors[error]);
|
||||
if (pattern == DP_TRAINING_PATTERN_1 && error == 0)
|
||||
break;
|
||||
if (pattern == DP_TRAINING_PATTERN_2) {
|
||||
value &= LT_CHANNEL1_EQ_BITS |
|
||||
LT_INTERLANE_ALIGN_DONE |
|
||||
LT_CHANNEL0_EQ_BITS;
|
||||
/* in case of two lanes */
|
||||
if ((tc->link.base.num_lanes == 2) &&
|
||||
(value == (LT_CHANNEL1_EQ_BITS |
|
||||
LT_INTERLANE_ALIGN_DONE |
|
||||
LT_CHANNEL0_EQ_BITS)))
|
||||
break;
|
||||
/* in case of one line */
|
||||
if ((tc->link.base.num_lanes == 1) &&
|
||||
(value == (LT_INTERLANE_ALIGN_DONE |
|
||||
LT_CHANNEL0_EQ_BITS)))
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart */
|
||||
tc_write(DP0CTL, 0);
|
||||
usleep_range(10, 20);
|
||||
} while (--retry);
|
||||
if (retry == 0) {
|
||||
dev_err(tc->dev, "Failed to finish training phase %d\n",
|
||||
pattern);
|
||||
if (timeout == 0) {
|
||||
dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return (value >> 8) & 0x7;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_main_link_setup(struct tc_data *tc)
|
||||
static int tc_main_link_enable(struct tc_data *tc)
|
||||
{
|
||||
struct drm_dp_aux *aux = &tc->aux;
|
||||
struct device *dev = tc->dev;
|
||||
|
@ -837,9 +793,11 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
int ret;
|
||||
u8 tmp[8];
|
||||
|
||||
/* display mode should be set at this point */
|
||||
if (!tc->mode)
|
||||
return -EINVAL;
|
||||
dev_dbg(tc->dev, "link enable\n");
|
||||
|
||||
tc_read(DP0CTL, &value);
|
||||
if (WARN_ON(value & DP_EN))
|
||||
tc_write(DP0CTL, 0);
|
||||
|
||||
tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
|
||||
/* SSCG and BW27 on DP1 must be set to the same as on DP0 */
|
||||
|
@ -872,7 +830,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
if (tc->link.base.num_lanes == 2)
|
||||
dp_phy_ctrl |= PHY_2LANE;
|
||||
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
|
||||
msleep(100);
|
||||
|
||||
/* PLL setup */
|
||||
tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN);
|
||||
|
@ -881,14 +838,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN);
|
||||
tc_wait_pll_lock(tc);
|
||||
|
||||
/* PXL PLL setup */
|
||||
if (tc_test_pattern) {
|
||||
ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk),
|
||||
1000 * tc->mode->clock);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Reset/Enable Main Links */
|
||||
dp_phy_ctrl |= DP_PHY_RST | PHY_M1_RST | PHY_M0_RST;
|
||||
tc_write(DP_PHY_CTRL, dp_phy_ctrl);
|
||||
|
@ -934,9 +883,9 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
|
||||
if (tmp[0] != tc->assr) {
|
||||
dev_dbg(dev, "Failed to switch display ASSR to %d, falling back to unscrambled mode\n",
|
||||
tc->assr);
|
||||
tc->assr);
|
||||
/* trying with disabled scrambler */
|
||||
tc->link.scrambler_dis = 1;
|
||||
tc->link.scrambler_dis = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -948,18 +897,81 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
/* DOWNSPREAD_CTRL */
|
||||
tmp[0] = tc->link.spread ? DP_SPREAD_AMP_0_5 : 0x00;
|
||||
/* MAIN_LINK_CHANNEL_CODING_SET */
|
||||
tmp[1] = tc->link.coding8b10b ? DP_SET_ANSI_8B10B : 0x00;
|
||||
tmp[1] = DP_SET_ANSI_8B10B;
|
||||
ret = drm_dp_dpcd_write(aux, DP_DOWNSPREAD_CTRL, tmp, 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_write;
|
||||
|
||||
ret = tc_link_training(tc, DP_TRAINING_PATTERN_1);
|
||||
if (ret)
|
||||
/* Reset voltage-swing & pre-emphasis */
|
||||
tmp[0] = tmp[1] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0 |
|
||||
DP_TRAIN_PRE_EMPH_LEVEL_0;
|
||||
ret = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, tmp, 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_write;
|
||||
|
||||
/* Clock-Recovery */
|
||||
|
||||
/* Set DPCD 0x102 for Training Pattern 1 */
|
||||
tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE |
|
||||
DP_TRAINING_PATTERN_1);
|
||||
|
||||
tc_write(DP0_LTLOOPCTRL,
|
||||
(15 << 28) | /* Defer Iteration Count */
|
||||
(15 << 24) | /* Loop Iteration Count */
|
||||
(0xd << 0)); /* Loop Timer Delay */
|
||||
|
||||
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
|
||||
DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP1);
|
||||
|
||||
/* Enable DP0 to start Link Training */
|
||||
tc_write(DP0CTL,
|
||||
((tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) |
|
||||
DP_EN);
|
||||
|
||||
/* wait */
|
||||
ret = tc_wait_link_training(tc);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = tc_link_training(tc, DP_TRAINING_PATTERN_2);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
dev_err(tc->dev, "Link training phase 1 failed: %s\n",
|
||||
training_pattern1_errors[ret]);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Channel Equalization */
|
||||
|
||||
/* Set DPCD 0x102 for Training Pattern 2 */
|
||||
tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE |
|
||||
DP_TRAINING_PATTERN_2);
|
||||
|
||||
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS |
|
||||
DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP2);
|
||||
|
||||
/* wait */
|
||||
ret = tc_wait_link_training(tc);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (ret) {
|
||||
dev_err(tc->dev, "Link training phase 2 failed: %s\n",
|
||||
training_pattern2_errors[ret]);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Toshiba's documentation suggests to first clear DPCD 0x102, then
|
||||
* clear the training pattern bit in DP0_SRCCTRL. Testing shows
|
||||
* that the link sometimes drops if those steps are done in that order,
|
||||
* but if the steps are done in reverse order, the link stays up.
|
||||
*
|
||||
* So we do the steps differently than documented here.
|
||||
*/
|
||||
|
||||
/* Clear Training Pattern, set AutoCorrect Mode = 1 */
|
||||
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_AUTOCORRECT);
|
||||
|
||||
/* Clear DPCD 0x102 */
|
||||
/* Note: Can Not use DP0_SNKLTCTRL (0x06E4) short cut */
|
||||
|
@ -968,47 +980,43 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
if (ret < 0)
|
||||
goto err_dpcd_write;
|
||||
|
||||
/* Clear Training Pattern, set AutoCorrect Mode = 1 */
|
||||
tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_AUTOCORRECT);
|
||||
/* Check link status */
|
||||
ret = drm_dp_dpcd_read_link_status(aux, tmp);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
|
||||
/* Wait */
|
||||
timeout = 100;
|
||||
do {
|
||||
udelay(1);
|
||||
/* Read DPCD 0x202-0x207 */
|
||||
ret = drm_dp_dpcd_read_link_status(aux, tmp + 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
} while ((--timeout) &&
|
||||
!(drm_dp_channel_eq_ok(tmp + 2, tc->link.base.num_lanes)));
|
||||
ret = 0;
|
||||
|
||||
if (timeout == 0) {
|
||||
/* Read DPCD 0x200-0x201 */
|
||||
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2);
|
||||
if (ret < 0)
|
||||
goto err_dpcd_read;
|
||||
dev_err(dev, "channel(s) EQ not ok\n");
|
||||
dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]);
|
||||
dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n",
|
||||
tmp[1]);
|
||||
dev_info(dev, "0x0202 LANE0_1_STATUS: 0x%02x\n", tmp[2]);
|
||||
dev_info(dev, "0x0204 LANE_ALIGN_STATUS_UPDATED: 0x%02x\n",
|
||||
tmp[4]);
|
||||
dev_info(dev, "0x0205 SINK_STATUS: 0x%02x\n", tmp[5]);
|
||||
dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n",
|
||||
tmp[6]);
|
||||
value = tmp[0] & DP_CHANNEL_EQ_BITS;
|
||||
|
||||
return -EAGAIN;
|
||||
if (value != DP_CHANNEL_EQ_BITS) {
|
||||
dev_err(tc->dev, "Lane 0 failed: %x\n", value);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
ret = tc_set_video_mode(tc, tc->mode);
|
||||
if (ret)
|
||||
goto err;
|
||||
if (tc->link.base.num_lanes == 2) {
|
||||
value = (tmp[0] >> 4) & DP_CHANNEL_EQ_BITS;
|
||||
|
||||
/* Set M/N */
|
||||
ret = tc_stream_clock_calc(tc);
|
||||
if (ret)
|
||||
if (value != DP_CHANNEL_EQ_BITS) {
|
||||
dev_err(tc->dev, "Lane 1 failed: %x\n", value);
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
if (!(tmp[2] & DP_INTERLANE_ALIGN_DONE)) {
|
||||
dev_err(tc->dev, "Interlane align failed\n");
|
||||
ret = -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(dev, "0x0202 LANE0_1_STATUS: 0x%02x\n", tmp[0]);
|
||||
dev_err(dev, "0x0203 LANE2_3_STATUS 0x%02x\n", tmp[1]);
|
||||
dev_err(dev, "0x0204 LANE_ALIGN_STATUS_UPDATED: 0x%02x\n", tmp[2]);
|
||||
dev_err(dev, "0x0205 SINK_STATUS: 0x%02x\n", tmp[3]);
|
||||
dev_err(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n", tmp[4]);
|
||||
dev_err(dev, "0x0207 ADJUST_REQUEST_LANE2_3: 0x%02x\n", tmp[5]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_dpcd_read:
|
||||
|
@ -1020,39 +1028,84 @@ static int tc_main_link_setup(struct tc_data *tc)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int tc_main_link_stream(struct tc_data *tc, int state)
|
||||
static int tc_main_link_disable(struct tc_data *tc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(tc->dev, "link disable\n");
|
||||
|
||||
tc_write(DP0_SRCCTRL, 0);
|
||||
tc_write(DP0CTL, 0);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_stream_enable(struct tc_data *tc)
|
||||
{
|
||||
int ret;
|
||||
u32 value;
|
||||
|
||||
dev_dbg(tc->dev, "stream: %d\n", state);
|
||||
dev_dbg(tc->dev, "enable video stream\n");
|
||||
|
||||
if (state) {
|
||||
value = VID_MN_GEN | DP_EN;
|
||||
if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
|
||||
value |= EF_EN;
|
||||
tc_write(DP0CTL, value);
|
||||
/*
|
||||
* VID_EN assertion should be delayed by at least N * LSCLK
|
||||
* cycles from the time VID_MN_GEN is enabled in order to
|
||||
* generate stable values for VID_M. LSCLK is 270 MHz or
|
||||
* 162 MHz, VID_N is set to 32768 in tc_stream_clock_calc(),
|
||||
* so a delay of at least 203 us should suffice.
|
||||
*/
|
||||
usleep_range(500, 1000);
|
||||
value |= VID_EN;
|
||||
tc_write(DP0CTL, value);
|
||||
/* Set input interface */
|
||||
value = DP0_AUDSRC_NO_INPUT;
|
||||
if (tc_test_pattern)
|
||||
value |= DP0_VIDSRC_COLOR_BAR;
|
||||
else
|
||||
value |= DP0_VIDSRC_DPI_RX;
|
||||
tc_write(SYSCTRL, value);
|
||||
} else {
|
||||
tc_write(DP0CTL, 0);
|
||||
/* PXL PLL setup */
|
||||
if (tc_test_pattern) {
|
||||
ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk),
|
||||
1000 * tc->mode.clock);
|
||||
if (ret)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = tc_set_video_mode(tc, &tc->mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set M/N */
|
||||
ret = tc_stream_clock_calc(tc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
value = VID_MN_GEN | DP_EN;
|
||||
if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
|
||||
value |= EF_EN;
|
||||
tc_write(DP0CTL, value);
|
||||
/*
|
||||
* VID_EN assertion should be delayed by at least N * LSCLK
|
||||
* cycles from the time VID_MN_GEN is enabled in order to
|
||||
* generate stable values for VID_M. LSCLK is 270 MHz or
|
||||
* 162 MHz, VID_N is set to 32768 in tc_stream_clock_calc(),
|
||||
* so a delay of at least 203 us should suffice.
|
||||
*/
|
||||
usleep_range(500, 1000);
|
||||
value |= VID_EN;
|
||||
tc_write(DP0CTL, value);
|
||||
/* Set input interface */
|
||||
value = DP0_AUDSRC_NO_INPUT;
|
||||
if (tc_test_pattern)
|
||||
value |= DP0_VIDSRC_COLOR_BAR;
|
||||
else
|
||||
value |= DP0_VIDSRC_DPI_RX;
|
||||
tc_write(SYSCTRL, value);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_stream_disable(struct tc_data *tc)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
dev_dbg(tc->dev, "disable video stream\n");
|
||||
|
||||
tc_read(DP0CTL, &val);
|
||||
val &= ~VID_EN;
|
||||
tc_write(DP0CTL, val);
|
||||
|
||||
tc_pxl_pll_dis(tc);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
|
@ -1070,15 +1123,22 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
|
|||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
int ret;
|
||||
|
||||
ret = tc_main_link_setup(tc);
|
||||
ret = tc_get_display_props(tc);
|
||||
if (ret < 0) {
|
||||
dev_err(tc->dev, "main link setup error: %d\n", ret);
|
||||
dev_err(tc->dev, "failed to read display props: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = tc_main_link_stream(tc, 1);
|
||||
ret = tc_main_link_enable(tc);
|
||||
if (ret < 0) {
|
||||
dev_err(tc->dev, "main link enable error: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = tc_stream_enable(tc);
|
||||
if (ret < 0) {
|
||||
dev_err(tc->dev, "main link stream start error: %d\n", ret);
|
||||
tc_main_link_disable(tc);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1092,9 +1152,13 @@ static void tc_bridge_disable(struct drm_bridge *bridge)
|
|||
|
||||
drm_panel_disable(tc->panel);
|
||||
|
||||
ret = tc_main_link_stream(tc, 0);
|
||||
ret = tc_stream_disable(tc);
|
||||
if (ret < 0)
|
||||
dev_err(tc->dev, "main link stream stop error: %d\n", ret);
|
||||
|
||||
ret = tc_main_link_disable(tc);
|
||||
if (ret < 0)
|
||||
dev_err(tc->dev, "main link disable error: %d\n", ret);
|
||||
}
|
||||
|
||||
static void tc_bridge_post_disable(struct drm_bridge *bridge)
|
||||
|
@ -1116,10 +1180,10 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
|
|||
return true;
|
||||
}
|
||||
|
||||
static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
static enum drm_mode_status tc_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct tc_data *tc = connector_to_tc(connector);
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
u32 req, avail;
|
||||
u32 bits_per_pixel = 24;
|
||||
|
||||
|
@ -1142,7 +1206,7 @@ static void tc_bridge_mode_set(struct drm_bridge *bridge,
|
|||
{
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
|
||||
tc->mode = mode;
|
||||
tc->mode = *mode;
|
||||
}
|
||||
|
||||
static int tc_connector_get_modes(struct drm_connector *connector)
|
||||
|
@ -1150,6 +1214,13 @@ static int tc_connector_get_modes(struct drm_connector *connector)
|
|||
struct tc_data *tc = connector_to_tc(connector);
|
||||
struct edid *edid;
|
||||
unsigned int count;
|
||||
int ret;
|
||||
|
||||
ret = tc_get_display_props(tc);
|
||||
if (ret < 0) {
|
||||
dev_err(tc->dev, "failed to read display props: %d\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (tc->panel && tc->panel->funcs && tc->panel->funcs->get_modes) {
|
||||
count = tc->panel->funcs->get_modes(tc->panel);
|
||||
|
@ -1170,29 +1241,40 @@ static int tc_connector_get_modes(struct drm_connector *connector)
|
|||
return count;
|
||||
}
|
||||
|
||||
static void tc_connector_set_polling(struct tc_data *tc,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
/* TODO: add support for HPD */
|
||||
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
}
|
||||
|
||||
static struct drm_encoder *
|
||||
tc_connector_best_encoder(struct drm_connector *connector)
|
||||
{
|
||||
struct tc_data *tc = connector_to_tc(connector);
|
||||
|
||||
return tc->bridge.encoder;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs tc_connector_helper_funcs = {
|
||||
.get_modes = tc_connector_get_modes,
|
||||
.mode_valid = tc_connector_mode_valid,
|
||||
.best_encoder = tc_connector_best_encoder,
|
||||
};
|
||||
|
||||
static enum drm_connector_status tc_connector_detect(struct drm_connector *connector,
|
||||
bool force)
|
||||
{
|
||||
struct tc_data *tc = connector_to_tc(connector);
|
||||
bool conn;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
if (tc->hpd_pin < 0) {
|
||||
if (tc->panel)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
tc_read(GPIOI, &val);
|
||||
|
||||
conn = val & BIT(tc->hpd_pin);
|
||||
|
||||
if (conn)
|
||||
return connector_status_connected;
|
||||
else
|
||||
return connector_status_disconnected;
|
||||
|
||||
err:
|
||||
return connector_status_unknown;
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs tc_connector_funcs = {
|
||||
.detect = tc_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = drm_connector_cleanup,
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
|
@ -1207,7 +1289,7 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
|
|||
struct drm_device *drm = bridge->dev;
|
||||
int ret;
|
||||
|
||||
/* Create eDP connector */
|
||||
/* Create DP/eDP connector */
|
||||
drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
|
||||
ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
|
||||
tc->panel ? DRM_MODE_CONNECTOR_eDP :
|
||||
|
@ -1215,6 +1297,15 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Don't poll if don't have HPD connected */
|
||||
if (tc->hpd_pin >= 0) {
|
||||
if (tc->have_irq)
|
||||
tc->connector.polled = DRM_CONNECTOR_POLL_HPD;
|
||||
else
|
||||
tc->connector.polled = DRM_CONNECTOR_POLL_CONNECT |
|
||||
DRM_CONNECTOR_POLL_DISCONNECT;
|
||||
}
|
||||
|
||||
if (tc->panel)
|
||||
drm_panel_attach(tc->panel, &tc->connector);
|
||||
|
||||
|
@ -1231,6 +1322,7 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
|
|||
|
||||
static const struct drm_bridge_funcs tc_bridge_funcs = {
|
||||
.attach = tc_bridge_attach,
|
||||
.mode_valid = tc_mode_valid,
|
||||
.mode_set = tc_bridge_mode_set,
|
||||
.pre_enable = tc_bridge_pre_enable,
|
||||
.enable = tc_bridge_enable,
|
||||
|
@ -1250,6 +1342,8 @@ static const struct regmap_range tc_volatile_ranges[] = {
|
|||
regmap_reg_range(DP_PHY_CTRL, DP_PHY_CTRL),
|
||||
regmap_reg_range(DP0_PLLCTRL, PXL_PLLCTRL),
|
||||
regmap_reg_range(VFUEN0, VFUEN0),
|
||||
regmap_reg_range(INTSTS_G, INTSTS_G),
|
||||
regmap_reg_range(GPIOI, GPIOI),
|
||||
};
|
||||
|
||||
static const struct regmap_access_table tc_volatile_table = {
|
||||
|
@ -1278,6 +1372,49 @@ static const struct regmap_config tc_regmap_config = {
|
|||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static irqreturn_t tc_irq_handler(int irq, void *arg)
|
||||
{
|
||||
struct tc_data *tc = arg;
|
||||
u32 val;
|
||||
int r;
|
||||
|
||||
r = regmap_read(tc->regmap, INTSTS_G, &val);
|
||||
if (r)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (!val)
|
||||
return IRQ_NONE;
|
||||
|
||||
if (val & INT_SYSERR) {
|
||||
u32 stat = 0;
|
||||
|
||||
regmap_read(tc->regmap, SYSSTAT, &stat);
|
||||
|
||||
dev_err(tc->dev, "syserr %x\n", stat);
|
||||
}
|
||||
|
||||
if (tc->hpd_pin >= 0 && tc->bridge.dev) {
|
||||
/*
|
||||
* H is triggered when the GPIO goes high.
|
||||
*
|
||||
* LC is triggered when the GPIO goes low and stays low for
|
||||
* the duration of LCNT
|
||||
*/
|
||||
bool h = val & INT_GPIO_H(tc->hpd_pin);
|
||||
bool lc = val & INT_GPIO_LC(tc->hpd_pin);
|
||||
|
||||
dev_dbg(tc->dev, "GPIO%d: %s %s\n", tc->hpd_pin,
|
||||
h ? "H" : "", lc ? "LC" : "");
|
||||
|
||||
if (h || lc)
|
||||
drm_kms_helper_hotplug_event(tc->bridge.dev);
|
||||
}
|
||||
|
||||
regmap_write(tc->regmap, INTSTS_G, val);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
|
@ -1329,6 +1466,33 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(dev->of_node, "toshiba,hpd-pin",
|
||||
&tc->hpd_pin);
|
||||
if (ret) {
|
||||
tc->hpd_pin = -ENODEV;
|
||||
} else {
|
||||
if (tc->hpd_pin < 0 || tc->hpd_pin > 1) {
|
||||
dev_err(dev, "failed to parse HPD number\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (client->irq > 0) {
|
||||
/* enable SysErr */
|
||||
regmap_write(tc->regmap, INTCTL_G, INT_SYSERR);
|
||||
|
||||
ret = devm_request_threaded_irq(dev, client->irq,
|
||||
NULL, tc_irq_handler,
|
||||
IRQF_ONESHOT,
|
||||
"tc358767-irq", tc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to register dp interrupt\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tc->have_irq = true;
|
||||
}
|
||||
|
||||
ret = regmap_read(tc->regmap, TC_IDREG, &tc->rev);
|
||||
if (ret) {
|
||||
dev_err(tc->dev, "can not read device ID: %d\n", ret);
|
||||
|
@ -1342,6 +1506,22 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
|
||||
tc->assr = (tc->rev == 0x6601); /* Enable ASSR for eDP panels */
|
||||
|
||||
if (tc->hpd_pin >= 0) {
|
||||
u32 lcnt_reg = tc->hpd_pin == 0 ? INT_GP0_LCNT : INT_GP1_LCNT;
|
||||
u32 h_lc = INT_GPIO_H(tc->hpd_pin) | INT_GPIO_LC(tc->hpd_pin);
|
||||
|
||||
/* Set LCNT to 2ms */
|
||||
regmap_write(tc->regmap, lcnt_reg,
|
||||
clk_get_rate(tc->refclk) * 2 / 1000);
|
||||
/* We need the "alternate" mode for HPD */
|
||||
regmap_write(tc->regmap, GPIOM, BIT(tc->hpd_pin));
|
||||
|
||||
if (tc->have_irq) {
|
||||
/* enable H & LC */
|
||||
regmap_update_bits(tc->regmap, INTCTL_G, h_lc, h_lc);
|
||||
}
|
||||
}
|
||||
|
||||
ret = tc_aux_link_setup(tc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -1354,12 +1534,6 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tc_get_display_props(tc);
|
||||
if (ret)
|
||||
goto err_unregister_aux;
|
||||
|
||||
tc_connector_set_polling(tc, &tc->connector);
|
||||
|
||||
tc->bridge.funcs = &tc_bridge_funcs;
|
||||
tc->bridge.of_node = dev->of_node;
|
||||
drm_bridge_add(&tc->bridge);
|
||||
|
@ -1367,9 +1541,6 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
i2c_set_clientdata(client, tc);
|
||||
|
||||
return 0;
|
||||
err_unregister_aux:
|
||||
drm_dp_aux_unregister(&tc->aux);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc_remove(struct i2c_client *client)
|
||||
|
@ -1379,8 +1550,6 @@ static int tc_remove(struct i2c_client *client)
|
|||
drm_bridge_remove(&tc->bridge);
|
||||
drm_dp_aux_unregister(&tc->aux);
|
||||
|
||||
tc_pxl_pll_dis(tc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,15 +5,17 @@
|
|||
* Copyright (C) 2018 Jacopo Mondi <jacopo+renesas@jmondi.org>
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
enum thc63_ports {
|
||||
THC63_LVDS_IN0,
|
||||
THC63_LVDS_IN1,
|
||||
|
|
|
@ -3,22 +3,24 @@
|
|||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#define SN_DEVICE_REV_REG 0x08
|
||||
#define SN_DPPLL_SRC_REG 0x0A
|
||||
|
|
|
@ -11,15 +11,15 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#define HOTPLUG_DEBOUNCE_MS 1100
|
||||
|
|
|
@ -31,13 +31,20 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#include <asm/agp.h>
|
||||
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/**
|
||||
* Get AGP information.
|
||||
*
|
||||
|
|
|
@ -26,13 +26,18 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/sync_file.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
#include <linux/sync_file.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
|
|
@ -25,15 +25,18 @@
|
|||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <linux/dma-fence.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
|
|
@ -24,12 +24,13 @@
|
|||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_state_helper.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
|
|
@ -28,10 +28,16 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_lease.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
#include <drm/drm_lease.h>
|
||||
|
||||
/**
|
||||
* DOC: master and authentication
|
||||
|
|
|
@ -23,13 +23,16 @@
|
|||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_blend.h>
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sort.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,15 +28,26 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <asm/shmparam.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_pci.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#include <linux/nospec.h>
|
||||
|
||||
static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
|
||||
struct drm_local_map *map)
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
@ -27,7 +27,6 @@
|
|||
* DOC: overview
|
||||
*
|
||||
* This library provides support for clients running in the kernel like fbdev and bootsplash.
|
||||
* Currently it's only partially implemented, just enough to support fbdev.
|
||||
*
|
||||
* GEM drivers which provide a GEM based dumb buffer with a virtual address are supported.
|
||||
*/
|
||||
|
@ -92,14 +91,20 @@ int drm_client_init(struct drm_device *dev, struct drm_client_dev *client,
|
|||
client->name = name;
|
||||
client->funcs = funcs;
|
||||
|
||||
ret = drm_client_open(client);
|
||||
ret = drm_client_modeset_create(client);
|
||||
if (ret)
|
||||
goto err_put_module;
|
||||
|
||||
ret = drm_client_open(client);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
drm_dev_get(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
drm_client_modeset_free(client);
|
||||
err_put_module:
|
||||
if (funcs)
|
||||
module_put(funcs->owner);
|
||||
|
@ -148,6 +153,7 @@ void drm_client_release(struct drm_client_dev *client)
|
|||
|
||||
DRM_DEV_DEBUG_KMS(dev->dev, "%s\n", client->name);
|
||||
|
||||
drm_client_modeset_free(client);
|
||||
drm_client_close(client);
|
||||
drm_dev_put(dev);
|
||||
if (client->funcs)
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright 2018 Noralf Trønnes
|
||||
* Copyright (c) 2006-2009 Red Hat Inc.
|
||||
* Copyright (c) 2006-2008 Intel Corporation
|
||||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
* Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
|
||||
int drm_client_modeset_create(struct drm_client_dev *client)
|
||||
{
|
||||
struct drm_device *dev = client->dev;
|
||||
unsigned int num_crtc = dev->mode_config.num_crtc;
|
||||
unsigned int max_connector_count = 1;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
unsigned int i = 0;
|
||||
|
||||
/* Add terminating zero entry to enable index less iteration */
|
||||
client->modesets = kcalloc(num_crtc + 1, sizeof(*client->modesets), GFP_KERNEL);
|
||||
if (!client->modesets)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&client->modeset_mutex);
|
||||
|
||||
drm_for_each_crtc(crtc, dev)
|
||||
client->modesets[i++].crtc = crtc;
|
||||
|
||||
/* Cloning is only supported in the single crtc case. */
|
||||
if (num_crtc == 1)
|
||||
max_connector_count = DRM_CLIENT_MAX_CLONED_CONNECTORS;
|
||||
|
||||
for (modeset = client->modesets; modeset->crtc; modeset++) {
|
||||
modeset->connectors = kcalloc(max_connector_count,
|
||||
sizeof(*modeset->connectors), GFP_KERNEL);
|
||||
if (!modeset->connectors)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
drm_client_modeset_free(client);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void drm_client_modeset_release(struct drm_client_dev *client)
|
||||
{
|
||||
struct drm_mode_set *modeset;
|
||||
unsigned int i;
|
||||
|
||||
drm_client_for_each_modeset(modeset, client) {
|
||||
drm_mode_destroy(client->dev, modeset->mode);
|
||||
modeset->mode = NULL;
|
||||
modeset->fb = NULL;
|
||||
|
||||
for (i = 0; i < modeset->num_connectors; i++) {
|
||||
drm_connector_put(modeset->connectors[i]);
|
||||
modeset->connectors[i] = NULL;
|
||||
}
|
||||
modeset->num_connectors = 0;
|
||||
}
|
||||
}
|
||||
/* TODO: Remove export when modeset code has been moved over */
|
||||
EXPORT_SYMBOL(drm_client_modeset_release);
|
||||
|
||||
void drm_client_modeset_free(struct drm_client_dev *client)
|
||||
{
|
||||
struct drm_mode_set *modeset;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
|
||||
drm_client_modeset_release(client);
|
||||
|
||||
drm_client_for_each_modeset(modeset, client)
|
||||
kfree(modeset->connectors);
|
||||
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
mutex_destroy(&client->modeset_mutex);
|
||||
kfree(client->modesets);
|
||||
}
|
||||
|
||||
struct drm_mode_set *drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_mode_set *modeset;
|
||||
|
||||
drm_client_for_each_modeset(modeset, client)
|
||||
if (modeset->crtc == crtc)
|
||||
return modeset;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
/* TODO: Remove export when modeset code has been moved over */
|
||||
EXPORT_SYMBOL(drm_client_find_modeset);
|
|
@ -20,9 +20,13 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
|
|
@ -956,6 +956,46 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = {
|
|||
* is no longer protected and userspace should take appropriate action
|
||||
* (whatever that might be).
|
||||
*
|
||||
* HDR_OUTPUT_METADATA:
|
||||
* Connector property to enable userspace to send HDR Metadata to
|
||||
* driver. This metadata is based on the composition and blending
|
||||
* policies decided by user, taking into account the hardware and
|
||||
* sink capabilities. The driver gets this metadata and creates a
|
||||
* Dynamic Range and Mastering Infoframe (DRM) in case of HDMI,
|
||||
* SDP packet (Non-audio INFOFRAME SDP v1.3) for DP. This is then
|
||||
* sent to sink. This notifies the sink of the upcoming frame's Color
|
||||
* Encoding and Luminance parameters.
|
||||
*
|
||||
* Userspace first need to detect the HDR capabilities of sink by
|
||||
* reading and parsing the EDID. Details of HDR metadata for HDMI
|
||||
* are added in CTA 861.G spec. For DP , its defined in VESA DP
|
||||
* Standard v1.4. It needs to then get the metadata information
|
||||
* of the video/game/app content which are encoded in HDR (basically
|
||||
* using HDR transfer functions). With this information it needs to
|
||||
* decide on a blending policy and compose the relevant
|
||||
* layers/overlays into a common format. Once this blending is done,
|
||||
* userspace will be aware of the metadata of the composed frame to
|
||||
* be send to sink. It then uses this property to communicate this
|
||||
* metadata to driver which then make a Infoframe packet and sends
|
||||
* to sink based on the type of encoder connected.
|
||||
*
|
||||
* Userspace will be responsible to do Tone mapping operation in case:
|
||||
* - Some layers are HDR and others are SDR
|
||||
* - HDR layers luminance is not same as sink
|
||||
* It will even need to do colorspace conversion and get all layers
|
||||
* to one common colorspace for blending. It can use either GL, Media
|
||||
* or display engine to get this done based on the capabilties of the
|
||||
* associated hardware.
|
||||
*
|
||||
* Driver expects metadata to be put in &struct hdr_output_metadata
|
||||
* structure from userspace. This is received as blob and stored in
|
||||
* &drm_connector_state.hdr_output_metadata. It parses EDID and saves the
|
||||
* sink metadata in &struct hdr_sink_metadata, as
|
||||
* &drm_connector.hdr_sink_metadata. Driver uses
|
||||
* drm_hdmi_infoframe_set_hdr_metadata() helper to set the HDR metadata,
|
||||
* hdmi_drm_infoframe_pack() to pack the infoframe as per spec, in case of
|
||||
* HDMI encoder.
|
||||
*
|
||||
* max bpc:
|
||||
* This range property is used by userspace to limit the bit depth. When
|
||||
* used the driver would limit the bpc in accordance with the valid range
|
||||
|
|
|
@ -28,7 +28,13 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
struct drm_ctx_list {
|
||||
|
|
|
@ -29,21 +29,23 @@
|
|||
* Jesse Barnes <jesse.barnes@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
|
|
|
@ -31,14 +31,30 @@
|
|||
* and are not exported to drivers.
|
||||
*/
|
||||
|
||||
enum drm_mode_status;
|
||||
enum drm_connector_force;
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_display_mode;
|
||||
struct work_struct;
|
||||
struct drm_connector;
|
||||
enum drm_color_encoding;
|
||||
enum drm_color_range;
|
||||
enum drm_connector_force;
|
||||
enum drm_mode_status;
|
||||
|
||||
struct drm_atomic_state;
|
||||
struct drm_bridge;
|
||||
struct drm_connector;
|
||||
struct drm_crtc;
|
||||
struct drm_device;
|
||||
struct drm_display_mode;
|
||||
struct drm_file;
|
||||
struct drm_framebuffer;
|
||||
struct drm_mode_create_dumb;
|
||||
struct drm_mode_fb_cmd2;
|
||||
struct drm_mode_fb_cmd;
|
||||
struct drm_mode_object;
|
||||
struct drm_plane;
|
||||
struct drm_property;
|
||||
struct edid;
|
||||
struct kref;
|
||||
struct work_struct;
|
||||
|
||||
/* drm_crtc.c */
|
||||
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
|
||||
|
|
|
@ -286,7 +286,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
|
|||
iter->plane_src.y2 = (state->src.y2 >> 16) + !!(state->src.y2 & 0xFFFF);
|
||||
|
||||
if (!iter->clips || !drm_rect_equals(&state->src, &old_state->src)) {
|
||||
iter->clips = 0;
|
||||
iter->clips = NULL;
|
||||
iter->num_clips = 0;
|
||||
iter->full_update = true;
|
||||
}
|
||||
|
|
|
@ -24,20 +24,23 @@
|
|||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
|
||||
|
|
|
@ -29,7 +29,14 @@
|
|||
#include <linux/circ_buf.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_debugfs_crc.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -34,7 +34,11 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_pci.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -1996,7 +1996,11 @@ static void process_single_up_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
|
|||
if (ret != 1)
|
||||
DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
|
||||
|
||||
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
|
||||
if (txmsg->seqno != -1) {
|
||||
WARN_ON((unsigned int)txmsg->seqno >
|
||||
ARRAY_SIZE(txmsg->dst->tx_slots));
|
||||
txmsg->dst->tx_slots[txmsg->seqno] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
|
||||
|
|
|
@ -35,16 +35,19 @@
|
|||
#include <linux/srcu.h>
|
||||
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/*
|
||||
* drm_debug: Enable debug output.
|
||||
* Bitmask of DRM_UT_x. See include/drm/drmP.h for details.
|
||||
* Bitmask of DRM_UT_x. See include/drm/drm_print.h for details.
|
||||
*/
|
||||
unsigned int drm_debug = 0;
|
||||
EXPORT_SYMBOL(drm_debug);
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_mode.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
|
|
@ -281,6 +281,8 @@ struct edid *drm_load_edid_firmware(struct drm_connector *connector)
|
|||
* the last one found one as a fallback.
|
||||
*/
|
||||
fwstr = kstrdup(edid_firmware, GFP_KERNEL);
|
||||
if (!fwstr)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
edidstr = fwstr;
|
||||
|
||||
while ((edidname = strsep(&edidstr, ","))) {
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
|
|
@ -32,18 +32,23 @@
|
|||
#include <linux/console.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysrq.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
||||
static bool drm_fbdev_emulation = true;
|
||||
|
@ -317,13 +322,11 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
|
|||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
int i;
|
||||
struct drm_mode_set *mode_set;
|
||||
|
||||
list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
|
||||
for (i = 0; i < helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set =
|
||||
&helper->crtc_info[i].mode_set;
|
||||
|
||||
mutex_lock(&helper->client.modeset_mutex);
|
||||
drm_client_for_each_modeset(mode_set, &helper->client) {
|
||||
if (!mode_set->crtc->enabled)
|
||||
continue;
|
||||
|
||||
|
@ -340,6 +343,7 @@ int drm_fb_helper_debug_enter(struct fb_info *info)
|
|||
mode_set->y,
|
||||
ENTER_ATOMIC_MODE_SET);
|
||||
}
|
||||
mutex_unlock(&helper->client.modeset_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -353,14 +357,14 @@ EXPORT_SYMBOL(drm_fb_helper_debug_enter);
|
|||
int drm_fb_helper_debug_leave(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
struct drm_client_dev *client = &helper->client;
|
||||
struct drm_crtc *crtc;
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
struct drm_mode_set *mode_set;
|
||||
struct drm_framebuffer *fb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
crtc = mode_set->crtc;
|
||||
if (drm_drv_uses_atomic_modeset(crtc->dev))
|
||||
continue;
|
||||
|
@ -383,6 +387,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
|
|||
funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
|
||||
crtc->y, LEAVE_ATOMIC_MODE_SET);
|
||||
}
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -433,12 +438,14 @@ static bool drm_fb_helper_panel_rotation(struct drm_mode_set *modeset,
|
|||
|
||||
static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool active)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_plane *plane;
|
||||
struct drm_atomic_state *state;
|
||||
int i, ret;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_mode_set *mode_set;
|
||||
int ret;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
|
@ -468,8 +475,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
|
|||
goto out_state;
|
||||
}
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
struct drm_plane *primary = mode_set->crtc->primary;
|
||||
unsigned int rotation;
|
||||
|
||||
|
@ -517,9 +523,11 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper, bool activ
|
|||
|
||||
static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_mode_set *mode_set;
|
||||
struct drm_plane *plane;
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
drm_modeset_lock_all(fb_helper->dev);
|
||||
drm_for_each_plane(plane, dev) {
|
||||
|
@ -532,8 +540,7 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
|
|||
DRM_MODE_ROTATE_0);
|
||||
}
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
struct drm_crtc *crtc = mode_set->crtc;
|
||||
|
||||
if (crtc->funcs->cursor_set2) {
|
||||
|
@ -559,11 +566,16 @@ static int restore_fbdev_mode_legacy(struct drm_fb_helper *fb_helper)
|
|||
static int restore_fbdev_mode_force(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&fb_helper->client.modeset_mutex);
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
return restore_fbdev_mode_atomic(fb_helper, true);
|
||||
ret = restore_fbdev_mode_atomic(fb_helper, true);
|
||||
else
|
||||
return restore_fbdev_mode_legacy(fb_helper);
|
||||
ret = restore_fbdev_mode_legacy(fb_helper);
|
||||
mutex_unlock(&fb_helper->client.modeset_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int restore_fbdev_mode(struct drm_fb_helper *fb_helper)
|
||||
|
@ -682,15 +694,14 @@ static struct sysrq_key_op sysrq_drm_fb_helper_restore_op = { };
|
|||
|
||||
static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_connector *connector;
|
||||
struct drm_mode_set *modeset;
|
||||
int i, j;
|
||||
int j;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
drm_client_for_each_modeset(modeset, client) {
|
||||
if (!modeset->crtc->enabled)
|
||||
continue;
|
||||
|
||||
|
@ -707,6 +718,7 @@ static void dpms_legacy(struct drm_fb_helper *fb_helper, int dpms_mode)
|
|||
static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
|
||||
/*
|
||||
|
@ -716,10 +728,12 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
|
|||
if (!drm_master_internal_acquire(dev))
|
||||
goto unlock;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
restore_fbdev_mode_atomic(fb_helper, dpms_mode == DRM_MODE_DPMS_ON);
|
||||
else
|
||||
dpms_legacy(fb_helper, dpms_mode);
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
drm_master_internal_release(dev);
|
||||
unlock:
|
||||
|
@ -762,43 +776,6 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_blank);
|
||||
|
||||
static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper,
|
||||
struct drm_mode_set *modeset)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < modeset->num_connectors; i++) {
|
||||
drm_connector_put(modeset->connectors[i]);
|
||||
modeset->connectors[i] = NULL;
|
||||
}
|
||||
modeset->num_connectors = 0;
|
||||
|
||||
drm_mode_destroy(helper->dev, modeset->mode);
|
||||
modeset->mode = NULL;
|
||||
|
||||
/* FIXME should hold a ref? */
|
||||
modeset->fb = NULL;
|
||||
}
|
||||
|
||||
static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < helper->connector_count; i++) {
|
||||
drm_connector_put(helper->connector_info[i]->connector);
|
||||
kfree(helper->connector_info[i]);
|
||||
}
|
||||
kfree(helper->connector_info);
|
||||
|
||||
for (i = 0; i < helper->crtc_count; i++) {
|
||||
struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set;
|
||||
|
||||
drm_fb_helper_modeset_release(helper, modeset);
|
||||
kfree(modeset->connectors);
|
||||
}
|
||||
kfree(helper->crtc_info);
|
||||
}
|
||||
|
||||
static void drm_fb_helper_resume_worker(struct work_struct *work)
|
||||
{
|
||||
struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
|
||||
|
@ -877,7 +854,7 @@ EXPORT_SYMBOL(drm_fb_helper_prepare);
|
|||
* drm_fb_helper_init - initialize a &struct drm_fb_helper
|
||||
* @dev: drm device
|
||||
* @fb_helper: driver-allocated fbdev helper structure to initialize
|
||||
* @max_conn_count: max connector count
|
||||
* @max_conn_count: max connector count (not used)
|
||||
*
|
||||
* This allocates the structures for the fbdev helper with the given limits.
|
||||
* Note that this won't yet touch the hardware (through the driver interfaces)
|
||||
|
@ -893,53 +870,36 @@ int drm_fb_helper_init(struct drm_device *dev,
|
|||
struct drm_fb_helper *fb_helper,
|
||||
int max_conn_count)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (!drm_fbdev_emulation) {
|
||||
dev->fb_helper = fb_helper;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!max_conn_count)
|
||||
return -EINVAL;
|
||||
|
||||
fb_helper->crtc_info = kcalloc(config->num_crtc, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
|
||||
if (!fb_helper->crtc_info)
|
||||
return -ENOMEM;
|
||||
|
||||
fb_helper->crtc_count = config->num_crtc;
|
||||
fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
|
||||
if (!fb_helper->connector_info) {
|
||||
kfree(fb_helper->crtc_info);
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* If this is not the generic fbdev client, initialize a drm_client
|
||||
* without callbacks so we can use the modesets.
|
||||
*/
|
||||
if (!fb_helper->client.funcs) {
|
||||
ret = drm_client_init(dev, &fb_helper->client, "drm_fb_helper", NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
|
||||
if (!fb_helper->connector_info)
|
||||
goto out_free;
|
||||
|
||||
fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
|
||||
fb_helper->connector_count = 0;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
fb_helper->crtc_info[i].mode_set.connectors =
|
||||
kcalloc(max_conn_count,
|
||||
sizeof(struct drm_connector *),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!fb_helper->crtc_info[i].mode_set.connectors)
|
||||
goto out_free;
|
||||
fb_helper->crtc_info[i].mode_set.num_connectors = 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
fb_helper->crtc_info[i].mode_set.crtc = crtc;
|
||||
i++;
|
||||
}
|
||||
|
||||
dev->fb_helper = fb_helper;
|
||||
|
||||
return 0;
|
||||
out_free:
|
||||
drm_fb_helper_crtc_free(fb_helper);
|
||||
drm_client_release(&fb_helper->client);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_init);
|
||||
|
@ -1015,6 +975,7 @@ EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
|
|||
void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct fb_info *info;
|
||||
int i;
|
||||
|
||||
if (!fb_helper)
|
||||
return;
|
||||
|
@ -1044,8 +1005,15 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
|
|||
mutex_unlock(&kernel_fb_helper_lock);
|
||||
|
||||
mutex_destroy(&fb_helper->lock);
|
||||
drm_fb_helper_crtc_free(fb_helper);
|
||||
|
||||
if (!fb_helper->client.funcs)
|
||||
drm_client_release(&fb_helper->client);
|
||||
|
||||
for (i = 0; i < fb_helper->connector_count; i++) {
|
||||
drm_connector_put(fb_helper->connector_info[i]->connector);
|
||||
kfree(fb_helper->connector_info[i]);
|
||||
}
|
||||
kfree(fb_helper->connector_info);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_fini);
|
||||
|
||||
|
@ -1390,13 +1358,14 @@ static int setcmap_pseudo_palette(struct fb_cmap *cmap, struct fb_info *info)
|
|||
static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
u16 *r, *g, *b;
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
drm_modeset_lock_all(fb_helper->dev);
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
crtc = fb_helper->crtc_info[i].mode_set.crtc;
|
||||
drm_client_for_each_modeset(modeset, &fb_helper->client) {
|
||||
crtc = modeset->crtc;
|
||||
if (!crtc->funcs->gamma_set || !crtc->gamma_size)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1472,10 +1441,11 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
|
|||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_crtc *crtc;
|
||||
u16 *r, *g, *b;
|
||||
int i, ret = 0;
|
||||
bool replaced;
|
||||
int ret = 0;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
|
@ -1487,8 +1457,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
|
|||
|
||||
state->acquire_ctx = &ctx;
|
||||
retry:
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
crtc = fb_helper->crtc_info[i].mode_set.crtc;
|
||||
drm_client_for_each_modeset(modeset, &fb_helper->client) {
|
||||
crtc = modeset->crtc;
|
||||
|
||||
if (!gamma_lut)
|
||||
gamma_lut = setcmap_new_gamma_lut(crtc, cmap);
|
||||
|
@ -1516,8 +1486,8 @@ static int setcmap_atomic(struct fb_cmap *cmap, struct fb_info *info)
|
|||
if (ret)
|
||||
goto out_state;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
crtc = fb_helper->crtc_info[i].mode_set.crtc;
|
||||
drm_client_for_each_modeset(modeset, &fb_helper->client) {
|
||||
crtc = modeset->crtc;
|
||||
|
||||
r = crtc->gamma_store;
|
||||
g = r + crtc->gamma_size;
|
||||
|
@ -1567,12 +1537,14 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
|
|||
goto unlock;
|
||||
}
|
||||
|
||||
mutex_lock(&fb_helper->client.modeset_mutex);
|
||||
if (info->fix.visual == FB_VISUAL_TRUECOLOR)
|
||||
ret = setcmap_pseudo_palette(cmap, info);
|
||||
else if (drm_drv_uses_atomic_modeset(fb_helper->dev))
|
||||
ret = setcmap_atomic(cmap, info);
|
||||
else
|
||||
ret = setcmap_legacy(cmap, info);
|
||||
mutex_unlock(&fb_helper->client.modeset_mutex);
|
||||
|
||||
drm_master_internal_release(dev);
|
||||
unlock:
|
||||
|
@ -1596,7 +1568,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_mode_set *mode_set;
|
||||
struct drm_crtc *crtc;
|
||||
int ret = 0;
|
||||
|
||||
|
@ -1624,8 +1595,7 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
* make. If we're not smart enough here, one should
|
||||
* just consider switch the userspace to KMS.
|
||||
*/
|
||||
mode_set = &fb_helper->crtc_info[0].mode_set;
|
||||
crtc = mode_set->crtc;
|
||||
crtc = fb_helper->client.modesets[0].crtc;
|
||||
|
||||
/*
|
||||
* Only wait for a vblank event if the CRTC is
|
||||
|
@ -1822,16 +1792,14 @@ EXPORT_SYMBOL(drm_fb_helper_set_par);
|
|||
|
||||
static void pan_set(struct drm_fb_helper *fb_helper, int x, int y)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
struct drm_mode_set *mode_set;
|
||||
|
||||
mutex_lock(&fb_helper->client.modeset_mutex);
|
||||
drm_client_for_each_modeset(mode_set, &fb_helper->client) {
|
||||
mode_set->x = x;
|
||||
mode_set->y = y;
|
||||
}
|
||||
mutex_unlock(&fb_helper->client.modeset_mutex);
|
||||
}
|
||||
|
||||
static int pan_display_atomic(struct fb_var_screeninfo *var,
|
||||
|
@ -1842,7 +1810,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
|
||||
pan_set(fb_helper, var->xoffset, var->yoffset);
|
||||
|
||||
ret = restore_fbdev_mode_atomic(fb_helper, true);
|
||||
ret = restore_fbdev_mode_force(fb_helper);
|
||||
if (!ret) {
|
||||
info->var.xoffset = var->xoffset;
|
||||
info->var.yoffset = var->yoffset;
|
||||
|
@ -1856,14 +1824,13 @@ static int pan_display_legacy(struct fb_var_screeninfo *var,
|
|||
struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_mode_set *modeset;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
drm_modeset_lock_all(fb_helper->dev);
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
drm_client_for_each_modeset(modeset, client) {
|
||||
modeset->x = var->xoffset;
|
||||
modeset->y = var->yoffset;
|
||||
|
||||
|
@ -1875,6 +1842,7 @@ static int pan_display_legacy(struct fb_var_screeninfo *var,
|
|||
}
|
||||
}
|
||||
}
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
drm_modeset_unlock_all(fb_helper->dev);
|
||||
|
||||
return ret;
|
||||
|
@ -1921,10 +1889,12 @@ EXPORT_SYMBOL(drm_fb_helper_pan_display);
|
|||
static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
int preferred_bpp)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
int ret = 0;
|
||||
int crtc_count = 0;
|
||||
int i;
|
||||
struct drm_fb_helper_surface_size sizes;
|
||||
struct drm_mode_set *mode_set;
|
||||
int best_depth = 0;
|
||||
|
||||
memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
|
||||
|
@ -1975,13 +1945,13 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|||
* supports RGBA5551 (16 bpp, depth 15) but not RGB565 (16 bpp, depth
|
||||
* 16) we need to scale down the depth of the sizes we request.
|
||||
*/
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
struct drm_crtc *crtc = mode_set->crtc;
|
||||
struct drm_plane *plane = crtc->primary;
|
||||
int j;
|
||||
|
||||
DRM_DEBUG("test CRTC %d primary plane\n", i);
|
||||
DRM_DEBUG("test CRTC %u primary plane\n", drm_crtc_index(crtc));
|
||||
|
||||
for (j = 0; j < plane->format_count; j++) {
|
||||
const struct drm_format_info *fmt;
|
||||
|
@ -2021,9 +1991,8 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|||
|
||||
/* first up get a count of crtcs now in use and new min/maxes width/heights */
|
||||
crtc_count = 0;
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
drm_client_for_each_modeset(mode_set, client) {
|
||||
struct drm_display_mode *desired_mode;
|
||||
struct drm_mode_set *mode_set;
|
||||
int x, y, j;
|
||||
/* in case of tile group, are we the last tile vert or horiz?
|
||||
* If no tile group you are always the last one both vertically
|
||||
|
@ -2031,7 +2000,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|||
*/
|
||||
bool lastv = true, lasth = true;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
desired_mode = mode_set->mode;
|
||||
|
||||
if (!desired_mode)
|
||||
|
@ -2061,6 +2029,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
|||
if (lastv)
|
||||
sizes.fb_height = min_t(u32, desired_mode->vdisplay + y, sizes.fb_height);
|
||||
}
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
||||
DRM_INFO("Cannot find any crtc or sizes\n");
|
||||
|
@ -2292,7 +2261,7 @@ static bool drm_target_cloned(struct drm_fb_helper *fb_helper,
|
|||
struct drm_display_mode *dmt_mode, *mode;
|
||||
|
||||
/* only contemplate cloning in the single crtc case */
|
||||
if (fb_helper->crtc_count > 1)
|
||||
if (fb_helper->dev->mode_config.num_crtc > 1)
|
||||
return false;
|
||||
|
||||
count = 0;
|
||||
|
@ -2481,15 +2450,17 @@ static bool connector_has_possible_crtc(struct drm_connector *connector,
|
|||
}
|
||||
|
||||
static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_crtc **best_crtcs,
|
||||
struct drm_crtc **best_crtcs,
|
||||
struct drm_display_mode **modes,
|
||||
int n, int width, int height)
|
||||
{
|
||||
int c, o;
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_connector *connector;
|
||||
int my_score, best_score, score;
|
||||
struct drm_fb_helper_crtc **crtcs, *crtc;
|
||||
struct drm_crtc **crtcs, *crtc;
|
||||
struct drm_mode_set *modeset;
|
||||
struct drm_fb_helper_connector *fb_helper_conn;
|
||||
int o;
|
||||
|
||||
if (n == fb_helper->connector_count)
|
||||
return 0;
|
||||
|
@ -2502,8 +2473,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|||
if (modes[n] == NULL)
|
||||
return best_score;
|
||||
|
||||
crtcs = kcalloc(fb_helper->connector_count,
|
||||
sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
|
||||
crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL);
|
||||
if (!crtcs)
|
||||
return best_score;
|
||||
|
||||
|
@ -2519,11 +2489,10 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|||
* select a crtc for this connector and then attempt to configure
|
||||
* remaining connectors
|
||||
*/
|
||||
for (c = 0; c < fb_helper->crtc_count; c++) {
|
||||
crtc = &fb_helper->crtc_info[c];
|
||||
drm_client_for_each_modeset(modeset, client) {
|
||||
crtc = modeset->crtc;
|
||||
|
||||
if (!connector_has_possible_crtc(connector,
|
||||
crtc->mode_set.crtc))
|
||||
if (!connector_has_possible_crtc(connector, crtc))
|
||||
continue;
|
||||
|
||||
for (o = 0; o < n; o++)
|
||||
|
@ -2532,7 +2501,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|||
|
||||
if (o < n) {
|
||||
/* ignore cloning unless only a single crtc */
|
||||
if (fb_helper->crtc_count > 1)
|
||||
if (fb_helper->dev->mode_config.num_crtc > 1)
|
||||
continue;
|
||||
|
||||
if (!drm_mode_equal(modes[o], modes[n]))
|
||||
|
@ -2540,14 +2509,13 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|||
}
|
||||
|
||||
crtcs[n] = crtc;
|
||||
memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
|
||||
memcpy(crtcs, best_crtcs, n * sizeof(*crtcs));
|
||||
score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
|
||||
width, height);
|
||||
if (score > best_score) {
|
||||
best_score = score;
|
||||
memcpy(best_crtcs, crtcs,
|
||||
fb_helper->connector_count *
|
||||
sizeof(struct drm_fb_helper_crtc *));
|
||||
fb_helper->connector_count * sizeof(*crtcs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2555,21 +2523,9 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
|
|||
return best_score;
|
||||
}
|
||||
|
||||
static struct drm_fb_helper_crtc *
|
||||
drm_fb_helper_crtc(struct drm_fb_helper *fb_helper, struct drm_crtc *crtc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++)
|
||||
if (fb_helper->crtc_info[i].mode_set.crtc == crtc)
|
||||
return &fb_helper->crtc_info[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Try to read the BIOS display configuration and use it for the initial config */
|
||||
static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_crtc **crtcs,
|
||||
struct drm_crtc **crtcs,
|
||||
struct drm_display_mode **modes,
|
||||
struct drm_fb_offset *offsets,
|
||||
bool *enabled, int width, int height)
|
||||
|
@ -2605,7 +2561,7 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
|
|||
struct drm_fb_helper_connector *fb_conn;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_fb_helper_crtc *new_crtc;
|
||||
struct drm_crtc *new_crtc;
|
||||
|
||||
fb_conn = fb_helper->connector_info[i];
|
||||
connector = fb_conn->connector;
|
||||
|
@ -2647,7 +2603,7 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
|
|||
|
||||
num_connectors_enabled++;
|
||||
|
||||
new_crtc = drm_fb_helper_crtc(fb_helper, connector->state->crtc);
|
||||
new_crtc = connector->state->crtc;
|
||||
|
||||
/*
|
||||
* Make sure we're not trying to drive multiple connectors
|
||||
|
@ -2747,10 +2703,11 @@ static bool drm_fb_helper_firmware_config(struct drm_fb_helper *fb_helper,
|
|||
static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
||||
u32 width, u32 height)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_fb_helper_crtc **crtcs;
|
||||
struct drm_display_mode **modes;
|
||||
struct drm_fb_offset *offsets;
|
||||
struct drm_crtc **crtcs;
|
||||
bool *enabled;
|
||||
int i;
|
||||
|
||||
|
@ -2758,8 +2715,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
|||
/* prevent concurrent modification of connector_count by hotplug */
|
||||
lockdep_assert_held(&fb_helper->lock);
|
||||
|
||||
crtcs = kcalloc(fb_helper->connector_count,
|
||||
sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
|
||||
crtcs = kcalloc(fb_helper->connector_count, sizeof(*crtcs), GFP_KERNEL);
|
||||
modes = kcalloc(fb_helper->connector_count,
|
||||
sizeof(struct drm_display_mode *), GFP_KERNEL);
|
||||
offsets = kcalloc(fb_helper->connector_count,
|
||||
|
@ -2771,6 +2727,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
|||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
|
||||
mutex_lock(&fb_helper->dev->mode_config.mutex);
|
||||
if (drm_fb_helper_probe_connector_modes(fb_helper, width, height) == 0)
|
||||
DRM_DEBUG_KMS("No connectors reported connected with modes\n");
|
||||
|
@ -2795,24 +2753,24 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
|||
}
|
||||
mutex_unlock(&fb_helper->dev->mode_config.mutex);
|
||||
|
||||
/* need to set the modesets up here for use later */
|
||||
/* fill out the connector<->crtc mappings into the modesets */
|
||||
for (i = 0; i < fb_helper->crtc_count; i++)
|
||||
drm_fb_helper_modeset_release(fb_helper,
|
||||
&fb_helper->crtc_info[i].mode_set);
|
||||
drm_client_modeset_release(client);
|
||||
|
||||
drm_fb_helper_for_each_connector(fb_helper, i) {
|
||||
struct drm_display_mode *mode = modes[i];
|
||||
struct drm_fb_helper_crtc *fb_crtc = crtcs[i];
|
||||
struct drm_crtc *crtc = crtcs[i];
|
||||
struct drm_fb_offset *offset = &offsets[i];
|
||||
|
||||
if (mode && fb_crtc) {
|
||||
struct drm_mode_set *modeset = &fb_crtc->mode_set;
|
||||
if (mode && crtc) {
|
||||
struct drm_mode_set *modeset = drm_client_find_modeset(client, crtc);
|
||||
struct drm_connector *connector =
|
||||
fb_helper->connector_info[i]->connector;
|
||||
|
||||
DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",
|
||||
mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y);
|
||||
mode->name, crtc->base.id, offset->x, offset->y);
|
||||
|
||||
if (WARN_ON_ONCE(modeset->num_connectors == DRM_CLIENT_MAX_CLONED_CONNECTORS ||
|
||||
(dev->mode_config.num_crtc > 1 && modeset->num_connectors == 1)))
|
||||
break;
|
||||
|
||||
modeset->mode = drm_mode_duplicate(dev, mode);
|
||||
drm_connector_get(connector);
|
||||
|
@ -2821,6 +2779,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
|||
modeset->y = offset->y;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
out:
|
||||
kfree(crtcs);
|
||||
kfree(modes);
|
||||
|
@ -2837,13 +2797,14 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
|
|||
*/
|
||||
static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
|
||||
{
|
||||
struct drm_client_dev *client = &fb_helper->client;
|
||||
struct fb_info *info = fb_helper->fbdev;
|
||||
unsigned int rotation, sw_rotations = 0;
|
||||
struct drm_mode_set *modeset;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *modeset = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
drm_client_for_each_modeset(modeset, client) {
|
||||
if (!modeset->num_connectors)
|
||||
continue;
|
||||
|
||||
|
@ -2855,6 +2816,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
|
|||
else
|
||||
sw_rotations |= rotation;
|
||||
}
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
mutex_lock(&fb_helper->dev->mode_config.mutex);
|
||||
drm_fb_helper_for_each_connector(fb_helper, i) {
|
||||
|
@ -3070,8 +3032,7 @@ EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
|
|||
* @funcs: fbdev helper functions
|
||||
* @preferred_bpp: Preferred bits per pixel for the device.
|
||||
* @dev->mode_config.preferred_depth is used if this is zero.
|
||||
* @max_conn_count: Maximum number of connectors.
|
||||
* @dev->mode_config.num_connector is used if this is zero.
|
||||
* @max_conn_count: Maximum number of connectors (not used)
|
||||
*
|
||||
* This function sets up fbdev emulation and registers fbdev for access by
|
||||
* userspace. If all connectors are disconnected, setup is deferred to the next
|
||||
|
@ -3099,16 +3060,9 @@ int drm_fb_helper_fbdev_setup(struct drm_device *dev,
|
|||
if (!preferred_bpp)
|
||||
preferred_bpp = 32;
|
||||
|
||||
if (!max_conn_count)
|
||||
max_conn_count = dev->mode_config.num_connector;
|
||||
if (!max_conn_count) {
|
||||
DRM_DEV_ERROR(dev->dev, "fbdev: No connectors\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
drm_fb_helper_prepare(dev, fb_helper, funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, fb_helper, max_conn_count);
|
||||
ret = drm_fb_helper_init(dev, fb_helper, 0);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dev->dev, "fbdev: Failed to initialize (ret=%d)\n", ret);
|
||||
return ret;
|
||||
|
@ -3421,7 +3375,7 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
|
|||
|
||||
drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(dev, fb_helper, dev->mode_config.num_connector);
|
||||
ret = drm_fb_helper_init(dev, fb_helper, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -31,17 +31,20 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/dma-fence.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/* from BKL pushdown */
|
||||
DEFINE_MUTEX(drm_global_mutex);
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_util.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_flip_work.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
/**
|
||||
* drm_flip_work_allocate_task - allocate a flip-work task
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
static char printable_char(int c)
|
||||
|
|
|
@ -21,16 +21,21 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
|
|
|
@ -38,10 +38,14 @@
|
|||
#include <linux/dma-buf.h>
|
||||
#include <linux/mem_encrypt.h>
|
||||
#include <linux/pagevec.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_vma_manager.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vma_manager.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
/** @file drm_gem.c
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_vma_manager.h>
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <linux/reservation.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
|
@ -285,6 +284,9 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
|
|||
* There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple
|
||||
* gem based framebuffer drivers which have their buffers always pinned in
|
||||
* memory.
|
||||
*
|
||||
* See drm_atomic_set_fence_for_plane() for a discussion of implicit and
|
||||
* explicit fencing in atomic modeset updates.
|
||||
*/
|
||||
int drm_gem_fb_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
|
@ -315,6 +317,9 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb);
|
|||
* &dma_buf attached, extracts the exclusive fence and attaches it to plane
|
||||
* state for the atomic helper to wait on. Drivers can use this as their
|
||||
* &drm_simple_display_pipe_funcs.prepare_fb callback.
|
||||
*
|
||||
* See drm_atomic_set_fence_for_plane() for a discussion of implicit and
|
||||
* explicit fencing in atomic modeset updates.
|
||||
*/
|
||||
int drm_gem_fb_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_plane_state *plane_state)
|
||||
|
|
|
@ -32,11 +32,15 @@
|
|||
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_hashtab.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <drm/drm_hashtab.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
|
||||
{
|
||||
|
|
|
@ -28,8 +28,16 @@
|
|||
|
||||
#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
|
||||
|
||||
struct drm_prime_file_private;
|
||||
struct dentry;
|
||||
struct dma_buf;
|
||||
struct drm_connector;
|
||||
struct drm_crtc;
|
||||
struct drm_framebuffer;
|
||||
struct drm_gem_object;
|
||||
struct drm_master;
|
||||
struct drm_minor;
|
||||
struct drm_prime_file_private;
|
||||
struct drm_printer;
|
||||
|
||||
/* drm_file.c */
|
||||
extern struct mutex drm_global_mutex;
|
||||
|
|
|
@ -31,10 +31,13 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_internal.h"
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
|
||||
#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
|
||||
|
|
|
@ -28,16 +28,22 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_ioctl.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
/**
|
||||
* DOC: getunique and setversion story
|
||||
|
|
|
@ -51,13 +51,18 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/interrupt.h> /* For task queue support */
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vgaarb.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
|
|
|
@ -11,14 +11,19 @@
|
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
#include <linux/file.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
#include <drm/drm_lease.h>
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_lease.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#define drm_for_each_lessee(lessee, lessor) \
|
||||
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
|
||||
|
|
|
@ -29,11 +29,15 @@
|
|||
* drivers use them, and removing them are API breaks.
|
||||
*/
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_legacy.h>
|
||||
|
||||
struct agp_memory;
|
||||
struct drm_device;
|
||||
struct drm_file;
|
||||
struct drm_buf_desc;
|
||||
|
||||
/*
|
||||
* Generic DRM Contexts
|
||||
|
|
|
@ -33,7 +33,12 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
|
|
|
@ -36,9 +36,13 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/sched/signal.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "drm_legacy.h"
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context);
|
||||
|
||||
|
|
|
@ -33,10 +33,15 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <xen/xen.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_device.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#if IS_ENABLED(CONFIG_AGP)
|
||||
|
|
|
@ -42,12 +42,13 @@
|
|||
* Thomas Hellström <thomas-at-tungstengraphics-dot-com>
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/interval_tree_generic.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stacktrace.h>
|
||||
|
||||
#include <drm/drm_mm.h>
|
||||
|
||||
/**
|
||||
* DOC: Overview
|
||||
|
|
|
@ -20,9 +20,13 @@
|
|||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_mode_config.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
|
|
@ -21,9 +21,14 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
|
|
@ -33,11 +33,14 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/list_sort.h>
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
|
||||
#include <video/of_videomode.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_modeset_lock.h>
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,12 +3,13 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
|
|
|
@ -22,12 +22,17 @@
|
|||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_agpsupport.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_pci.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
*/
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
#define SUBPIXEL_MASK 0xffff
|
||||
|
||||
|
|
|
@ -29,9 +29,12 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <drm/drm_prime.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_prime.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
|
|
|
@ -26,8 +26,13 @@
|
|||
#define DEBUG /* for pr_debug() */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
void __drm_puts_coredump(struct drm_printer *p, const char *str)
|
||||
|
|
|
@ -32,14 +32,15 @@
|
|||
#include <linux/export.h>
|
||||
#include <linux/moduleparam.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_sysfs.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
|
@ -574,6 +575,9 @@ static void output_poll_execute(struct work_struct *work)
|
|||
enum drm_connector_status old_status;
|
||||
bool repoll = false, changed;
|
||||
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
|
||||
/* Pick up any changes detected by the probe functions. */
|
||||
changed = dev->mode_config.delayed_event;
|
||||
dev->mode_config.delayed_event = false;
|
||||
|
@ -728,7 +732,11 @@ EXPORT_SYMBOL(drm_kms_helper_poll_init);
|
|||
*/
|
||||
void drm_kms_helper_poll_fini(struct drm_device *dev)
|
||||
{
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
|
||||
dev->mode_config.poll_enabled = false;
|
||||
cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_kms_helper_poll_fini);
|
||||
|
||||
|
|
|
@ -21,7 +21,12 @@
|
|||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_property.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_rect.h>
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,9 +31,14 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#define DEBUG_SCATTER 0
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_scdc_helper.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
/**
|
||||
* DOC: scdc helpers
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
|
|
|
@ -46,15 +46,20 @@
|
|||
* The file takes a reference on the kref.
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/sched/signal.h>
|
||||
#include <linux/sync_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_syncobj.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
#include <drm/drm_syncobj.h>
|
||||
|
||||
struct syncobj_wait_entry {
|
||||
struct list_head node;
|
||||
|
|
|
@ -13,13 +13,20 @@
|
|||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_modes.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_property.h>
|
||||
#include <drm/drm_sysfs.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
#define to_drm_minor(d) dev_get_drvdata(d)
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
struct drm_file;
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM drm
|
||||
#define TRACE_INCLUDE_FILE drm_trace
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue