drm-misc-next for v5.9:
UAPI Changes: - Add DRM_MODE_TYPE_USERDEF for video modes specified in cmdline. Cross-subsystem Changes: - Assorted devicetree binding updates. - Add might_sleep() to dma_fence_wait(). - Fix fbdev's get_user_pages_fast() handling, and use pin_user_pages. - Small cleanup with IS_BUILTIN in video/fbdev drivers. - Fix video/hdmi coding style for infoframe size. Core Changes: - Silence vblank output during init. - Fix DP-MST corruption during send msg timeout. - Clear leak in drm_gem_objecs_lookup(). - Make newlines work with force connector attribute. - Fix module refcounting error in drm_encoder_slave, and use new i2c api. - Header fix for drm_managed.c - More struct_mutex removal for !legacy drivers: - Remove gem_free_object() - Removal of drm_gem_object_put_unlocked(). - Show current->comm alongside pid in debug printfs. - Add drm_client_modeset_check() + drm_client_framebuffer_flush(). - Replace drm_fb_swab16 with drm_fb_swap that also supports 32-bits. - Remove mode->vrefresh, and compactify drm_display_mode. - Use drm_* macros for logging and warnings. - Add WARN when drm_gem_get_pages is used on a private obj. - Handle importing and imported dmabuf better in shmem helpers. - Small fix for drm/mm hole size comparison, and remove invalid entry optimization. - Add a drm/mm selftest. - Set DSI connector type for DSI panels. - Assorted small fixes and documentation updates. - Fix DDI I2C device registration for MST ports, and flushing on destroy. - Fix master_set return type, used by vmwgfx. - Make the drm_set/drop_master ioctl symmetrical. Driver Changes: Allow iommu in the sun4i driver and use it for sun8i. - Simplify backlight lookup for omap, amba-clcd and tilcdc. - Hold reg_lock for rockchip. - Add support for bridge gpio and lane reordering + polarity to ti-sn65dsi86, and fix clock choice. - Small assorted fixes to tilcdc, vc4, i915, omap, fbdev/sm712fb, fbdev/pxafb, console/newport_con, msm, virtio, udl, malidp, hdlcd, bridge/ti-sn65dsi86, panfrost. - Remove hw cursor support for mgag200, and use simple kms helper + shmem helpers. - Add support for KOE Allow iommu in the sun4i driver and use it for sun8i. - Simplify backlight lookup for omap, amba-clcd and tilcdc. - Hold reg_lock for rockchip. - Add support for bridge gpio and lane reordering + polarity to ti-sn65dsi86, and fix clock choice. - Small assorted fixes to tilcdc, vc4 (multiple), i915. - Remove hw cursor support for mgag200, and use simple kms helper + shmem helpers. - Add support for KOE TX26D202VM0BWA panel. - Use GEM CMA functions in arc, arm, atmel-hlcdc, fsi-dcu, hisilicon, imx, ingenic, komeda, malidp, mcde, meson, msxfb, rcar-du, shmobile, stm, sti, tilcdc, tve200, zte. - Remove gem_print_info. - Improve gem_create_object_helper so udl can use shmem helpers. - Convert vc4 dt bindings to schemas, and add clock properties. - Device initialization cleanups for mgag200. - Add a workaround to fix DP-MST short pulses handling on broken hardware in i915. - Allow build test compiling arm drivers. - Use managed pci functions in mgag200 and ast. - Use dev_groups in malidp. - Add per pixel alpha support for PX30 VOP in rockchip. - Silence deferred probe logs in panfrost. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAl7s11IACgkQ/lWMcqZw E8OYnQ/+K4ZGpU11t4IzXCyJYis2ZPYs/FlJ2BWXH89YhOckN1e1tq7uDBzUE8qK Hlz0gvH5C0WXR/PWqNglPXW7INwc0LtC8PSmvS4vvrZQBaJ2bvf19y7dROqJbR0E xTUje95eq+10H9TysCRTf1osIUuZIoR0gRna22pb+nplKVBkqsQPyPT21AWq4fN0 H/LQfKNfAAHtKwvfsMsuG2U+ZTyTYo7Xi6UP413WAqDmzhewnCm5plifM29m5LhB 9BmKk0/1pL3KzZuCQvcZw4kYUjXYsgoOqD4hkMAOLsjyf6Ad5zbPB5YTxNK0C+NU N04aHWvkRVl62A6rehgXdS5GJ3M4ORPDpIV9zQCVxMZV/886JLTGA1Wb+b3+umdk t5M40kzgYQTDqdSwFoCDCd1tFpEjnLbE7E+eM89AyzTPOxZowrVS0No1dJA3+ST/ g7JOdDu2Zg7VAar6zByow0pMppikZro9H1mpSnk+WHbYNF3dFmW3QHKRuxoRt+Ee l5G52LylwH3ZMPebGH9XB4cWtAUAHOsioe3CS/PKzGeUWNlUK29AqDCCBQmUdbcT HNm5/Yygdg3rRjkDBuUI0I/pifxMYvm+28eNfNGjwq5To9ABXPNONQCEBH6rke+S d1Z2nMmiVDf2MqhpkJppTKtHdMz13IGyZykXB7CdGnAu6k5s59c= =ZmKI -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-06-19' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.9: UAPI Changes: - Add DRM_MODE_TYPE_USERDEF for video modes specified in cmdline. Cross-subsystem Changes: - Assorted devicetree binding updates. - Add might_sleep() to dma_fence_wait(). - Fix fbdev's get_user_pages_fast() handling, and use pin_user_pages. - Small cleanup with IS_BUILTIN in video/fbdev drivers. - Fix video/hdmi coding style for infoframe size. Core Changes: - Silence vblank output during init. - Fix DP-MST corruption during send msg timeout. - Clear leak in drm_gem_objecs_lookup(). - Make newlines work with force connector attribute. - Fix module refcounting error in drm_encoder_slave, and use new i2c api. - Header fix for drm_managed.c - More struct_mutex removal for !legacy drivers: - Remove gem_free_object() - Removal of drm_gem_object_put_unlocked(). - Show current->comm alongside pid in debug printfs. - Add drm_client_modeset_check() + drm_client_framebuffer_flush(). - Replace drm_fb_swab16 with drm_fb_swap that also supports 32-bits. - Remove mode->vrefresh, and compactify drm_display_mode. - Use drm_* macros for logging and warnings. - Add WARN when drm_gem_get_pages is used on a private obj. - Handle importing and imported dmabuf better in shmem helpers. - Small fix for drm/mm hole size comparison, and remove invalid entry optimization. - Add a drm/mm selftest. - Set DSI connector type for DSI panels. - Assorted small fixes and documentation updates. - Fix DDI I2C device registration for MST ports, and flushing on destroy. - Fix master_set return type, used by vmwgfx. - Make the drm_set/drop_master ioctl symmetrical. Driver Changes: Allow iommu in the sun4i driver and use it for sun8i. - Simplify backlight lookup for omap, amba-clcd and tilcdc. - Hold reg_lock for rockchip. - Add support for bridge gpio and lane reordering + polarity to ti-sn65dsi86, and fix clock choice. - Small assorted fixes to tilcdc, vc4, i915, omap, fbdev/sm712fb, fbdev/pxafb, console/newport_con, msm, virtio, udl, malidp, hdlcd, bridge/ti-sn65dsi86, panfrost. - Remove hw cursor support for mgag200, and use simple kms helper + shmem helpers. - Add support for KOE Allow iommu in the sun4i driver and use it for sun8i. - Simplify backlight lookup for omap, amba-clcd and tilcdc. - Hold reg_lock for rockchip. - Add support for bridge gpio and lane reordering + polarity to ti-sn65dsi86, and fix clock choice. - Small assorted fixes to tilcdc, vc4 (multiple), i915. - Remove hw cursor support for mgag200, and use simple kms helper + shmem helpers. - Add support for KOE TX26D202VM0BWA panel. - Use GEM CMA functions in arc, arm, atmel-hlcdc, fsi-dcu, hisilicon, imx, ingenic, komeda, malidp, mcde, meson, msxfb, rcar-du, shmobile, stm, sti, tilcdc, tve200, zte. - Remove gem_print_info. - Improve gem_create_object_helper so udl can use shmem helpers. - Convert vc4 dt bindings to schemas, and add clock properties. - Device initialization cleanups for mgag200. - Add a workaround to fix DP-MST short pulses handling on broken hardware in i915. - Allow build test compiling arm drivers. - Use managed pci functions in mgag200 and ast. - Use dev_groups in malidp. - Add per pixel alpha support for PX30 VOP in rockchip. - Silence deferred probe logs in panfrost. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/001cd9a6-405d-4e29-43d8-354f53ae4e8b@linux.intel.com
This commit is contained in:
Коммит
0a19b068ac
|
@ -36,6 +36,9 @@ properties:
|
|||
- const: bus
|
||||
- const: mod
|
||||
|
||||
iommus:
|
||||
maxItems: 1
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
|
|
|
@ -1,174 +0,0 @@
|
|||
Broadcom VC4 (VideoCore4) GPU
|
||||
|
||||
The VC4 device present on the Raspberry Pi includes a display system
|
||||
with HDMI output and the HVS (Hardware Video Scaler) for compositing
|
||||
display planes.
|
||||
|
||||
Required properties for VC4:
|
||||
- compatible: Should be "brcm,bcm2835-vc4" or "brcm,cygnus-vc4"
|
||||
|
||||
Required properties for Pixel Valve:
|
||||
- compatible: Should be one of "brcm,bcm2835-pixelvalve0",
|
||||
"brcm,bcm2835-pixelvalve1", or "brcm,bcm2835-pixelvalve2"
|
||||
- reg: Physical base address and length of the PV's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for HVS:
|
||||
- compatible: Should be "brcm,bcm2835-hvs"
|
||||
- reg: Physical base address and length of the HVS's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for HDMI
|
||||
- compatible: Should be "brcm,bcm2835-hdmi"
|
||||
- reg: Physical base address and length of the two register ranges
|
||||
("HDMI" and "HD", in that order)
|
||||
- interrupts: The interrupt numbers
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
- ddc: phandle of the I2C controller used for DDC EDID probing
|
||||
- clocks: a) hdmi: The HDMI state machine clock
|
||||
b) pixel: The pixel clock.
|
||||
|
||||
Optional properties for HDMI:
|
||||
- hpd-gpios: The GPIO pin for HDMI hotplug detect (if it doesn't appear
|
||||
as an interrupt/status bit in the HDMI controller
|
||||
itself). See bindings/pinctrl/brcm,bcm2835-gpio.txt
|
||||
- dmas: Should contain one entry pointing to the DMA channel used to
|
||||
transfer audio data
|
||||
- dma-names: Should contain "audio-rx"
|
||||
|
||||
Required properties for DPI:
|
||||
- compatible: Should be "brcm,bcm2835-dpi"
|
||||
- reg: Physical base address and length of the registers
|
||||
- clocks: a) core: The core clock the unit runs on
|
||||
b) pixel: The pixel clock that feeds the pixelvalve
|
||||
- port: Port node with a single endpoint connecting to the panel
|
||||
device, as defined in [1]
|
||||
|
||||
Required properties for VEC:
|
||||
- compatible: Should be "brcm,bcm2835-vec"
|
||||
- reg: Physical base address and length of the registers
|
||||
- clocks: The core clock the unit runs on
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Required properties for V3D:
|
||||
- compatible: Should be "brcm,bcm2835-v3d" or "brcm,cygnus-v3d"
|
||||
- reg: Physical base address and length of the V3D's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
Optional properties for V3D:
|
||||
- clocks: The clock the unit runs on
|
||||
|
||||
Required properties for DSI:
|
||||
- compatible: Should be "brcm,bcm2835-dsi0" or "brcm,bcm2835-dsi1"
|
||||
- reg: Physical base address and length of the DSI block's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
- clocks: a) phy: The DSI PLL clock feeding the DSI analog PHY
|
||||
b) escape: The DSI ESC clock from CPRMAN
|
||||
c) pixel: The DSI pixel clock from CPRMAN
|
||||
- clock-output-names:
|
||||
The 3 clocks output from the DSI analog PHY: dsi[01]_byte,
|
||||
dsi[01]_ddr2, and dsi[01]_ddr
|
||||
|
||||
Required properties for the TXP (writeback) block:
|
||||
- compatible: Should be "brcm,bcm2835-txp"
|
||||
- reg: Physical base address and length of the TXP block's registers
|
||||
- interrupts: The interrupt number
|
||||
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
|
||||
|
||||
[1] Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
Example:
|
||||
pixelvalve@7e807000 {
|
||||
compatible = "brcm,bcm2835-pixelvalve2";
|
||||
reg = <0x7e807000 0x100>;
|
||||
interrupts = <2 10>; /* pixelvalve */
|
||||
};
|
||||
|
||||
hvs@7e400000 {
|
||||
compatible = "brcm,bcm2835-hvs";
|
||||
reg = <0x7e400000 0x6000>;
|
||||
interrupts = <2 1>;
|
||||
};
|
||||
|
||||
hdmi: hdmi@7e902000 {
|
||||
compatible = "brcm,bcm2835-hdmi";
|
||||
reg = <0x7e902000 0x600>,
|
||||
<0x7e808000 0x100>;
|
||||
interrupts = <2 8>, <2 9>;
|
||||
ddc = <&i2c2>;
|
||||
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&clocks BCM2835_PLLH_PIX>,
|
||||
<&clocks BCM2835_CLOCK_HSM>;
|
||||
clock-names = "pixel", "hdmi";
|
||||
};
|
||||
|
||||
dpi: dpi@7e208000 {
|
||||
compatible = "brcm,bcm2835-dpi";
|
||||
reg = <0x7e208000 0x8c>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>,
|
||||
<&clocks BCM2835_CLOCK_DPI>;
|
||||
clock-names = "core", "pixel";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port {
|
||||
dpi_out: endpoint@0 {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dsi1: dsi@7e700000 {
|
||||
compatible = "brcm,bcm2835-dsi1";
|
||||
reg = <0x7e700000 0x8c>;
|
||||
interrupts = <2 12>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&clocks BCM2835_PLLD_DSI1>,
|
||||
<&clocks BCM2835_CLOCK_DSI1E>,
|
||||
<&clocks BCM2835_CLOCK_DSI1P>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
|
||||
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
|
||||
|
||||
pitouchscreen: panel@0 {
|
||||
compatible = "raspberrypi,touchscreen";
|
||||
reg = <0>;
|
||||
|
||||
<...>
|
||||
};
|
||||
};
|
||||
|
||||
vec: vec@7e806000 {
|
||||
compatible = "brcm,bcm2835-vec";
|
||||
reg = <0x7e806000 0x1000>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VEC>;
|
||||
interrupts = <2 27>;
|
||||
};
|
||||
|
||||
v3d: v3d@7ec00000 {
|
||||
compatible = "brcm,bcm2835-v3d";
|
||||
reg = <0x7ec00000 0x1000>;
|
||||
interrupts = <1 10>;
|
||||
};
|
||||
|
||||
vc4: gpu {
|
||||
compatible = "brcm,bcm2835-vc4";
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "ontat,yx700wv03", "simple-panel";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-dpi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) DPI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-dpi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The core clock the unit runs on
|
||||
- description: The pixel clock that feeds the pixelvalve
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core
|
||||
- const: pixel
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: >
|
||||
Port node with a single endpoint connecting to the panel, as
|
||||
defined in Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
panel: panel {
|
||||
compatible = "ontat,yx700wv03", "simple-panel";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dpi: dpi@7e208000 {
|
||||
compatible = "brcm,bcm2835-dpi";
|
||||
reg = <0x7e208000 0x8c>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>,
|
||||
<&clocks BCM2835_CLOCK_DPI>;
|
||||
clock-names = "core", "pixel";
|
||||
|
||||
port {
|
||||
dpi_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,84 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-dsi0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) DSI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
"#clock-cells":
|
||||
const: 1
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-dsi0
|
||||
- brcm,bcm2835-dsi1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The DSI PLL clock feeding the DSI analog PHY
|
||||
- description: The DSI ESC clock
|
||||
- description: The DSI pixel clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: phy
|
||||
- const: escape
|
||||
- const: pixel
|
||||
|
||||
clock-output-names: true
|
||||
# FIXME: The meta-schemas don't seem to allow it for now
|
||||
# items:
|
||||
# - description: The DSI byte clock for the PHY
|
||||
# - description: The DSI DDR2 clock
|
||||
# - description: The DSI DDR clock
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- "#clock-cells"
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- clock-names
|
||||
- clock-output-names
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
dsi1: dsi@7e700000 {
|
||||
compatible = "brcm,bcm2835-dsi1";
|
||||
reg = <0x7e700000 0x8c>;
|
||||
interrupts = <2 12>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&clocks BCM2835_PLLD_DSI1>,
|
||||
<&clocks BCM2835_CLOCK_DSI1E>,
|
||||
<&clocks BCM2835_CLOCK_DSI1P>;
|
||||
clock-names = "phy", "escape", "pixel";
|
||||
|
||||
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
|
||||
|
||||
pitouchscreen: panel@0 {
|
||||
compatible = "raspberrypi,touchscreen";
|
||||
reg = <0>;
|
||||
|
||||
/* ... */
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-hdmi.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) HDMI Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-hdmi
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: HDMI register range
|
||||
- description: HD register range
|
||||
|
||||
interrupts:
|
||||
minItems: 2
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: The pixel clock
|
||||
- description: The HDMI state machine clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: pixel
|
||||
- const: hdmi
|
||||
|
||||
ddc:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: >
|
||||
Phandle of the I2C controller used for DDC EDID probing
|
||||
|
||||
hpd-gpios:
|
||||
description: >
|
||||
The GPIO pin for the HDMI hotplug detect (if it doesn't appear
|
||||
as an interrupt/status bit in the HDMI controller itself)
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
description: >
|
||||
Should contain one entry pointing to the DMA channel used to
|
||||
transfer audio data.
|
||||
|
||||
dma-names:
|
||||
const: audio-rx
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- ddc
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
hdmi: hdmi@7e902000 {
|
||||
compatible = "brcm,bcm2835-hdmi";
|
||||
reg = <0x7e902000 0x600>,
|
||||
<0x7e808000 0x100>;
|
||||
interrupts = <2 8>, <2 9>;
|
||||
ddc = <&i2c2>;
|
||||
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
|
||||
clocks = <&clocks BCM2835_PLLH_PIX>,
|
||||
<&clocks BCM2835_CLOCK_HSM>;
|
||||
clock-names = "pixel", "hdmi";
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-hvs.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) Hardware Video Scaler
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-hvs
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
hvs@7e400000 {
|
||||
compatible = "brcm,bcm2835-hvs";
|
||||
reg = <0x7e400000 0x6000>;
|
||||
interrupts = <2 1>;
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,40 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-pixelvalve0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) PixelValve
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-pixelvalve0
|
||||
- brcm,bcm2835-pixelvalve1
|
||||
- brcm,bcm2835-pixelvalve2
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
pixelvalve@7e807000 {
|
||||
compatible = "brcm,bcm2835-pixelvalve2";
|
||||
reg = <0x7e807000 0x100>;
|
||||
interrupts = <2 10>; /* pixelvalve */
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-txp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) TXP (writeback) Controller
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-txp
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
txp: txp@7e004000 {
|
||||
compatible = "brcm,bcm2835-txp";
|
||||
reg = <0x7e004000 0x20>;
|
||||
interrupts = <1 11>;
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,42 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-v3d.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) V3D GPU
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-v3d
|
||||
- brcm,cygnus-v3d
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
v3d: v3d@7ec00000 {
|
||||
compatible = "brcm,bcm2835-v3d";
|
||||
reg = <0x7ec00000 0x1000>;
|
||||
interrupts = <1 10>;
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,34 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-vc4.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) GPU
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
description: >
|
||||
The VC4 device present on the Raspberry Pi includes a display system
|
||||
with HDMI output and the HVS (Hardware Video Scaler) for compositing
|
||||
display planes.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2835-vc4
|
||||
- brcm,cygnus-vc4
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
vc4: gpu {
|
||||
compatible = "brcm,bcm2835-vc4";
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,44 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/brcm,bcm2835-vec.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Broadcom VC4 (VideoCore4) VEC
|
||||
|
||||
maintainers:
|
||||
- Eric Anholt <eric@anholt.net>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: brcm,bcm2835-vec
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- interrupts
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
vec: vec@7e806000 {
|
||||
compatible = "brcm,bcm2835-vec";
|
||||
reg = <0x7e806000 0x1000>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VEC>;
|
||||
interrupts = <2 27>;
|
||||
};
|
||||
|
||||
...
|
|
@ -1,87 +0,0 @@
|
|||
SN65DSI86 DSI to eDP bridge chip
|
||||
--------------------------------
|
||||
|
||||
This is the binding for Texas Instruments SN65DSI86 bridge.
|
||||
http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "ti,sn65dsi86"
|
||||
- reg: i2c address of the chip, 0x2d as per datasheet
|
||||
- enable-gpios: gpio specification for bridge_en pin (active high)
|
||||
|
||||
- vccio-supply: A 1.8V supply that powers up the digital IOs.
|
||||
- vpll-supply: A 1.8V supply that powers up the displayport PLL.
|
||||
- vcca-supply: A 1.2V supply that powers up the analog circuits.
|
||||
- vcc-supply: A 1.2V supply that powers up the digital core.
|
||||
|
||||
Optional properties:
|
||||
- interrupts-extended: Specifier for the SN65DSI86 interrupt line.
|
||||
|
||||
- gpio-controller: Marks the device has a GPIO controller.
|
||||
- #gpio-cells : Should be two. The first cell is the pin number and
|
||||
the second cell is used to specify flags.
|
||||
See ../../gpio/gpio.txt for more information.
|
||||
- #pwm-cells : Should be one. See ../../pwm/pwm.yaml for description of
|
||||
the cell formats.
|
||||
|
||||
- clock-names: should be "refclk"
|
||||
- clocks: Specification for input reference clock. The reference
|
||||
clock rate must be 12 MHz, 19.2 MHz, 26 MHz, 27 MHz or 38.4 MHz.
|
||||
|
||||
- data-lanes: See ../../media/video-interface.txt
|
||||
- lane-polarities: See ../../media/video-interface.txt
|
||||
|
||||
- suspend-gpios: specification for GPIO1 pin on bridge (active low)
|
||||
|
||||
Required nodes:
|
||||
This device has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 for DSI input
|
||||
- Video port 1 for eDP output
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
edp-bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x2d>;
|
||||
|
||||
enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>;
|
||||
suspend-gpios = <&msmgpio 34 GPIO_ACTIVE_LOW>;
|
||||
|
||||
interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
vccio-supply = <&pm8916_l17>;
|
||||
vcca-supply = <&pm8916_l6>;
|
||||
vpll-supply = <&pm8916_l17>;
|
||||
vcc-supply = <&pm8916_l6>;
|
||||
|
||||
clock-names = "refclk";
|
||||
clocks = <&input_refclk>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
edp_bridge_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
edp_bridge_out: endpoint {
|
||||
data-lanes = <2 1 3 0>;
|
||||
lane-polarities = <0 1 0 1>;
|
||||
remote-endpoint = <&edp_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,293 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/ti,sn65dsi86.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: SN65DSI86 DSI to eDP bridge chip
|
||||
|
||||
maintainers:
|
||||
- Sandeep Panda <spanda@codeaurora.org>
|
||||
|
||||
description: |
|
||||
The Texas Instruments SN65DSI86 bridge takes MIPI DSI in and outputs eDP.
|
||||
http://www.ti.com/general/docs/lit/getliterature.tsp?genericPartNumber=sn65dsi86&fileType=pdf
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ti,sn65dsi86
|
||||
|
||||
reg:
|
||||
const: 0x2d
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier for bridge_en pin (active high).
|
||||
|
||||
suspend-gpios:
|
||||
maxItems: 1
|
||||
description: GPIO specifier for GPIO1 pin on bridge (active low).
|
||||
|
||||
no-hpd:
|
||||
type: boolean
|
||||
description:
|
||||
Set if the HPD line on the bridge isn't hooked up to anything or is
|
||||
otherwise unusable.
|
||||
|
||||
vccio-supply:
|
||||
description: A 1.8V supply that powers the digital IOs.
|
||||
|
||||
vpll-supply:
|
||||
description: A 1.8V supply that powers the DisplayPort PLL.
|
||||
|
||||
vcca-supply:
|
||||
description: A 1.2V supply that powers the analog circuits.
|
||||
|
||||
vcc-supply:
|
||||
description: A 1.2V supply that powers the digital core.
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
maxItems: 1
|
||||
description:
|
||||
Clock specifier for input reference clock. The reference clock rate must
|
||||
be 12 MHz, 19.2 MHz, 26 MHz, 27 MHz or 38.4 MHz.
|
||||
|
||||
clock-names:
|
||||
const: refclk
|
||||
|
||||
gpio-controller: true
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
description:
|
||||
First cell is pin number, second cell is flags. GPIO pin numbers are
|
||||
1-based to match the datasheet. See ../../gpio/gpio.txt for more
|
||||
information.
|
||||
|
||||
'#pwm-cells':
|
||||
const: 1
|
||||
description: See ../../pwm/pwm.yaml for description of the cell formats.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
description:
|
||||
Video port for MIPI DSI input
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
description:
|
||||
Video port for eDP output (panel or connector).
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
data-lanes:
|
||||
oneOf:
|
||||
- minItems: 1
|
||||
maxItems: 1
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description:
|
||||
If you have 1 logical lane the bridge supports routing
|
||||
to either port 0 or port 1. Port 0 is suggested.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
- minItems: 2
|
||||
maxItems: 2
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description:
|
||||
If you have 2 logical lanes the bridge supports
|
||||
reordering but only on physical ports 0 and 1.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
- minItems: 4
|
||||
maxItems: 4
|
||||
uniqueItems: true
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
description:
|
||||
If you have 4 logical lanes the bridge supports
|
||||
reordering in any way.
|
||||
See ../../media/video-interface.txt for details.
|
||||
|
||||
lane-polarities:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
enum:
|
||||
- 0
|
||||
- 1
|
||||
description: See ../../media/video-interface.txt
|
||||
|
||||
dependencies:
|
||||
lane-polarities: [data-lanes]
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- enable-gpios
|
||||
- vccio-supply
|
||||
- vpll-supply
|
||||
- vcca-supply
|
||||
- vcc-supply
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
reg = <0x2d>;
|
||||
|
||||
interrupt-parent = <&tlmm>;
|
||||
interrupts = <10 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
enable-gpios = <&tlmm 102 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
vpll-supply = <&src_pp1800_s4a>;
|
||||
vccio-supply = <&src_pp1800_s4a>;
|
||||
vcca-supply = <&src_pp1200_l2a>;
|
||||
vcc-supply = <&src_pp1200_l2a>;
|
||||
|
||||
clocks = <&rpmhcc RPMH_LN_BB_CLK2>;
|
||||
clock-names = "refclk";
|
||||
|
||||
no-hpd;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
endpoint {
|
||||
remote-endpoint = <&dsi0_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
endpoint {
|
||||
remote-endpoint = <&panel_in_edp>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
- |
|
||||
#include <dt-bindings/clock/qcom,rpmh.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
bridge@2d {
|
||||
compatible = "ti,sn65dsi86";
|
||||
reg = <0x2d>;
|
||||
|
||||
enable-gpios = <&msmgpio 33 GPIO_ACTIVE_HIGH>;
|
||||
suspend-gpios = <&msmgpio 34 GPIO_ACTIVE_LOW>;
|
||||
|
||||
interrupts-extended = <&gpio3 4 IRQ_TYPE_EDGE_FALLING>;
|
||||
|
||||
vccio-supply = <&pm8916_l17>;
|
||||
vcca-supply = <&pm8916_l6>;
|
||||
vpll-supply = <&pm8916_l17>;
|
||||
vcc-supply = <&pm8916_l6>;
|
||||
|
||||
clock-names = "refclk";
|
||||
clocks = <&input_refclk>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
|
||||
edp_bridge_in: endpoint {
|
||||
remote-endpoint = <&dsi_out>;
|
||||
};
|
||||
};
|
||||
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
|
||||
edp_bridge_out: endpoint {
|
||||
data-lanes = <2 1 3 0>;
|
||||
lane-polarities = <0 1 0 1>;
|
||||
remote-endpoint = <&edp_panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -157,6 +157,8 @@ properties:
|
|||
- innolux,zj070na-01p
|
||||
# Kaohsiung Opto-Electronics Inc. 5.7" QVGA (320 x 240) TFT LCD panel
|
||||
- koe,tx14d24vm1bpa
|
||||
# Kaohsiung Opto-Electronics Inc. 10.1" WUXGA (1920 x 1200) LVDS TFT LCD panel
|
||||
- koe,tx26d202vm0bwa
|
||||
# Kaohsiung Opto-Electronics. TX31D200VM0BAA 12.3" HSXGA LVDS panel
|
||||
- koe,tx31d200vm0baa
|
||||
# Kyocera Corporation 12.1" XGA (1024x768) TFT LCD panel
|
||||
|
|
|
@ -411,15 +411,3 @@ Legacy CRTC/Modeset Helper Functions Reference
|
|||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
|
||||
:export:
|
||||
|
||||
SHMEM GEM Helper Reference
|
||||
==========================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:export:
|
||||
|
|
|
@ -460,6 +460,12 @@ HDMI Specific Connector Properties
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_connector.c
|
||||
:doc: HDMI connector properties
|
||||
|
||||
Standard CRTC Properties
|
||||
------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
|
||||
:doc: standard CRTC properties
|
||||
|
||||
Plane Composition Properties
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -179,10 +179,7 @@ GEM Objects Lifetime
|
|||
|
||||
All GEM objects are reference-counted by the GEM core. References can be
|
||||
acquired and release by calling drm_gem_object_get() and drm_gem_object_put()
|
||||
respectively. The caller must hold the :c:type:`struct drm_device <drm_device>`
|
||||
struct_mutex lock when calling drm_gem_object_get(). As a convenience, GEM
|
||||
provides drm_gem_object_put_unlocked() functions that can be called without
|
||||
holding the lock.
|
||||
respectively.
|
||||
|
||||
When the last reference to a GEM object is released the GEM core calls
|
||||
the :c:type:`struct drm_driver <drm_driver>` gem_free_object_unlocked
|
||||
|
@ -373,6 +370,18 @@ GEM CMA Helper Functions Reference
|
|||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:export:
|
||||
|
||||
GEM SHMEM Helper Function Reference
|
||||
-----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_shmem_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_shmem_helper.c
|
||||
:export:
|
||||
|
||||
GEM VRAM Helper Functions Reference
|
||||
-----------------------------------
|
||||
|
||||
|
|
|
@ -157,8 +157,8 @@ private lock. The tricky part is the BO free functions, since those can't
|
|||
reliably take that lock any more. Instead state needs to be protected with
|
||||
suitable subordinate locks or some cleanup work pushed to a worker thread. For
|
||||
performance-critical drivers it might also be better to go with a more
|
||||
fine-grained per-buffer object and per-context lockings scheme. Currently only the
|
||||
``msm`` driver still use ``struct_mutex``.
|
||||
fine-grained per-buffer object and per-context lockings scheme. Currently only
|
||||
the ``msm`` and `i915` drivers use ``struct_mutex``.
|
||||
|
||||
Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
|
@ -305,7 +305,7 @@ acquire context. Replace the boilerplate code surrounding
|
|||
drm_modeset_lock_all_ctx() with DRM_MODESET_LOCK_ALL_BEGIN() and
|
||||
DRM_MODESET_LOCK_ALL_END() instead.
|
||||
|
||||
This should also be done for all places where drm_modest_lock_all() is still
|
||||
This should also be done for all places where drm_modeset_lock_all() is still
|
||||
used.
|
||||
|
||||
As a reference, take a look at the conversions already completed in drm core.
|
||||
|
@ -327,26 +327,6 @@ Contact: Laurent Pinchart, Daniel Vetter
|
|||
Level: Intermediate (mostly because it is a huge tasks without good partial
|
||||
milestones, not technically itself that challenging)
|
||||
|
||||
Convert direct mode.vrefresh accesses to use drm_mode_vrefresh()
|
||||
----------------------------------------------------------------
|
||||
|
||||
drm_display_mode.vrefresh isn't guaranteed to be populated. As such, using it
|
||||
is risky and has been known to cause div-by-zero bugs. Fortunately, drm core
|
||||
has helper which will use mode.vrefresh if it's !0 and will calculate it from
|
||||
the timings when it's 0.
|
||||
|
||||
Use simple search/replace, or (more fun) cocci to replace instances of direct
|
||||
vrefresh access with a call to the helper. Check out
|
||||
https://lists.freedesktop.org/archives/dri-devel/2019-January/205186.html for
|
||||
inspiration.
|
||||
|
||||
Once all instances of vrefresh have been converted, remove vrefresh from
|
||||
drm_display_mode to avoid future use.
|
||||
|
||||
Contact: Sean Paul
|
||||
|
||||
Level: Starter
|
||||
|
||||
connector register/unregister fixes
|
||||
-----------------------------------
|
||||
|
||||
|
@ -392,6 +372,38 @@ Contact: Laurent Pinchart, respective driver maintainers
|
|||
|
||||
Level: Intermediate
|
||||
|
||||
Consolidate custom driver modeset properties
|
||||
--------------------------------------------
|
||||
|
||||
Before atomic modeset took place, many drivers where creating their own
|
||||
properties. Among other things, atomic brought the requirement that custom,
|
||||
driver specific properties should not be used.
|
||||
|
||||
For this task, we aim to introduce core helpers or reuse the existing ones
|
||||
if available:
|
||||
|
||||
A quick, unconfirmed, examples list.
|
||||
|
||||
Introduce core helpers:
|
||||
- audio (amdgpu, intel, gma500, radeon)
|
||||
- brightness, contrast, etc (armada, nouveau) - overlay only (?)
|
||||
- broadcast rgb (gma500, intel)
|
||||
- colorkey (armada, nouveau, rcar) - overlay only (?)
|
||||
- dither (amdgpu, nouveau, radeon) - varies across drivers
|
||||
- underscan family (amdgpu, radeon, nouveau)
|
||||
|
||||
Already in core:
|
||||
- colorspace (sti)
|
||||
- tv format names, enhancements (gma500, intel)
|
||||
- tv overscan, margins, etc. (gma500, intel)
|
||||
- zorder (omapdrm) - same as zpos (?)
|
||||
|
||||
|
||||
Contact: Emil Velikov, respective driver maintainers
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
|
|
|
@ -5819,7 +5819,7 @@ M: Eric Anholt <eric@anholt.net>
|
|||
S: Supported
|
||||
T: git git://github.com/anholt/linux
|
||||
T: git git://anongit.freedesktop.org/drm/drm-misc
|
||||
F: Documentation/devicetree/bindings/display/brcm,bcm-vc4.txt
|
||||
F: Documentation/devicetree/bindings/display/brcm,bcm2835-*.yaml
|
||||
F: drivers/gpu/drm/vc4/
|
||||
F: include/uapi/drm/vc4_drm.h
|
||||
|
||||
|
|
|
@ -208,6 +208,8 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
|
|||
if (WARN_ON(timeout < 0))
|
||||
return -EINVAL;
|
||||
|
||||
might_sleep();
|
||||
|
||||
trace_dma_fence_wait_start(fence);
|
||||
if (fence->ops->wait)
|
||||
ret = fence->ops->wait(fence, intr, timeout);
|
||||
|
|
|
@ -1354,7 +1354,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
|||
}
|
||||
|
||||
/* Free the BO*/
|
||||
drm_gem_object_put_unlocked(&mem->bo->tbo.base);
|
||||
drm_gem_object_put(&mem->bo->tbo.base);
|
||||
mutex_destroy(&mem->lock);
|
||||
kfree(mem);
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ int amdgpu_bo_list_create(struct amdgpu_device *adev, struct drm_file *filp,
|
|||
}
|
||||
|
||||
bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
usermm = amdgpu_ttm_tt_get_usermm(bo->tbo.ttm);
|
||||
if (usermm) {
|
||||
|
|
|
@ -57,7 +57,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
|
|||
/* One for TTM and one for the CS job */
|
||||
p->uf_entry.tv.num_shared = 2;
|
||||
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
size = amdgpu_bo_size(bo);
|
||||
if (size != PAGE_SIZE || (data->offset + 8) > size) {
|
||||
|
|
|
@ -576,14 +576,14 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
|
|||
|
||||
amdgpu_fb = kzalloc(sizeof(*amdgpu_fb), GFP_KERNEL);
|
||||
if (amdgpu_fb == NULL) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = amdgpu_display_framebuffer_init(dev, amdgpu_fb, mode_cmd, obj);
|
||||
if (ret) {
|
||||
kfree(amdgpu_fb);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
|
|||
amdgpu_bo_unpin(abo);
|
||||
amdgpu_bo_unreserve(abo);
|
||||
}
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
}
|
||||
|
||||
static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev,
|
||||
|
@ -278,7 +278,7 @@ out:
|
|||
|
||||
}
|
||||
if (fb && ret) {
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
drm_framebuffer_unregister_private(fb);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
|
|
|
@ -106,7 +106,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev)
|
|||
spin_lock(&file->table_lock);
|
||||
idr_for_each_entry(&file->object_idr, gobj, handle) {
|
||||
WARN_ONCE(1, "And also active allocations!\n");
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
}
|
||||
idr_destroy(&file->object_idr);
|
||||
spin_unlock(&file->table_lock);
|
||||
|
@ -285,7 +285,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
r = drm_gem_handle_create(filp, gobj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -369,7 +369,7 @@ user_pages_done:
|
|||
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm);
|
||||
|
||||
release_object:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -388,11 +388,11 @@ int amdgpu_mode_dumb_mmap(struct drm_file *filp,
|
|||
robj = gem_to_amdgpu_bo(gobj);
|
||||
if (amdgpu_ttm_tt_get_usermm(robj->tbo.ttm) ||
|
||||
(robj->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)) {
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return -EPERM;
|
||||
}
|
||||
*offset_p = amdgpu_bo_mmap_offset(robj);
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -462,7 +462,7 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
|
|||
} else
|
||||
r = ret;
|
||||
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -505,7 +505,7 @@ int amdgpu_gem_metadata_ioctl(struct drm_device *dev, void *data,
|
|||
unreserve:
|
||||
amdgpu_bo_unreserve(robj);
|
||||
out:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ error_backoff:
|
|||
ttm_eu_backoff_reservation(&ticket, &list);
|
||||
|
||||
error_unref:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -780,7 +780,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
out:
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -817,7 +817,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
|
|||
|
||||
r = drm_gem_handle_create(file_priv, gobj, &handle);
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_gem_object_put(gobj);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -2404,7 +2404,7 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
aobj = gem_to_amdgpu_bo(obj);
|
||||
ret = amdgpu_bo_reserve(aobj, false);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2412,7 +2412,7 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
amdgpu_bo_unreserve(aobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
|
@ -2447,7 +2447,7 @@ unpin:
|
|||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
drm_gem_object_put_unlocked(amdgpu_crtc->cursor_bo);
|
||||
drm_gem_object_put(amdgpu_crtc->cursor_bo);
|
||||
}
|
||||
|
||||
amdgpu_crtc->cursor_bo = obj;
|
||||
|
|
|
@ -2483,7 +2483,7 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
aobj = gem_to_amdgpu_bo(obj);
|
||||
ret = amdgpu_bo_reserve(aobj, false);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2491,7 +2491,7 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
amdgpu_bo_unreserve(aobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
|
@ -2526,7 +2526,7 @@ unpin:
|
|||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
drm_gem_object_put_unlocked(amdgpu_crtc->cursor_bo);
|
||||
drm_gem_object_put(amdgpu_crtc->cursor_bo);
|
||||
}
|
||||
|
||||
amdgpu_crtc->cursor_bo = obj;
|
||||
|
|
|
@ -2299,7 +2299,7 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
aobj = gem_to_amdgpu_bo(obj);
|
||||
ret = amdgpu_bo_reserve(aobj, false);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2307,7 +2307,7 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
amdgpu_bo_unreserve(aobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
|
@ -2342,7 +2342,7 @@ unpin:
|
|||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
drm_gem_object_put_unlocked(amdgpu_crtc->cursor_bo);
|
||||
drm_gem_object_put(amdgpu_crtc->cursor_bo);
|
||||
}
|
||||
|
||||
amdgpu_crtc->cursor_bo = obj;
|
||||
|
|
|
@ -2305,7 +2305,7 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
aobj = gem_to_amdgpu_bo(obj);
|
||||
ret = amdgpu_bo_reserve(aobj, false);
|
||||
if (ret != 0) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2313,7 +2313,7 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
|
|||
amdgpu_bo_unreserve(aobj);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj);
|
||||
|
@ -2348,7 +2348,7 @@ unpin:
|
|||
amdgpu_bo_unpin(aobj);
|
||||
amdgpu_bo_unreserve(aobj);
|
||||
}
|
||||
drm_gem_object_put_unlocked(amdgpu_crtc->cursor_bo);
|
||||
drm_gem_object_put(amdgpu_crtc->cursor_bo);
|
||||
}
|
||||
|
||||
amdgpu_crtc->cursor_bo = obj;
|
||||
|
|
|
@ -154,17 +154,7 @@ static struct drm_driver arcpgu_drm_driver = {
|
|||
.minor = 0,
|
||||
.patchlevel = 0,
|
||||
.fops = &arcpgu_drm_ops,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_print_info = drm_gem_cma_print_info,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = arcpgu_debugfs_init,
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@ menu "ARM devices"
|
|||
|
||||
config DRM_HDLCD
|
||||
tristate "ARM HDLCD"
|
||||
depends on DRM && OF && (ARM || ARM64)
|
||||
depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
depends on COMMON_CLK
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_CMA_HELPER
|
||||
|
@ -24,7 +24,7 @@ config DRM_HDLCD_SHOW_UNDERRUN
|
|||
|
||||
config DRM_MALI_DISPLAY
|
||||
tristate "ARM Mali Display Processor"
|
||||
depends on DRM && OF && (ARM || ARM64)
|
||||
depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
depends on COMMON_CLK
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_KMS_CMA_HELPER
|
||||
|
|
|
@ -19,7 +19,7 @@ static void komeda_fb_destroy(struct drm_framebuffer *fb)
|
|||
u32 i;
|
||||
|
||||
for (i = 0; i < fb->format->num_planes; i++)
|
||||
drm_gem_object_put_unlocked(fb->obj[i]);
|
||||
drm_gem_object_put(fb->obj[i]);
|
||||
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(kfb);
|
||||
|
@ -103,7 +103,7 @@ komeda_fb_afbc_size_check(struct komeda_fb *kfb, struct drm_file *file,
|
|||
return 0;
|
||||
|
||||
check_failed:
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ komeda_fb_create(struct drm_device *dev, struct drm_file *file,
|
|||
|
||||
err_cleanup:
|
||||
for (i = 0; i < kfb->base.format->num_planes; i++)
|
||||
drm_gem_object_put_unlocked(kfb->base.obj[i]);
|
||||
drm_gem_object_put(kfb->base.obj[i]);
|
||||
|
||||
kfree(kfb);
|
||||
return ERR_PTR(ret);
|
||||
|
|
|
@ -61,16 +61,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
|
|||
static struct drm_driver komeda_kms_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.lastclose = drm_fb_helper_lastclose,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = komeda_gem_cma_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create),
|
||||
.fops = &komeda_cma_fops,
|
||||
.name = "komeda",
|
||||
.desc = "Arm Komeda Display Processor driver",
|
||||
|
|
|
@ -240,17 +240,7 @@ static struct drm_driver hdlcd_driver = {
|
|||
.irq_preinstall = hdlcd_irq_preinstall,
|
||||
.irq_postinstall = hdlcd_irq_postinstall,
|
||||
.irq_uninstall = hdlcd_irq_uninstall,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_print_info = drm_gem_cma_print_info,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = hdlcd_debugfs_init,
|
||||
#endif
|
||||
|
@ -347,9 +337,8 @@ static void hdlcd_drm_unbind(struct device *dev)
|
|||
of_node_put(hdlcd->crtc.port);
|
||||
hdlcd->crtc.port = NULL;
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_crtc_vblank_off(&hdlcd->crtc);
|
||||
drm_irq_uninstall(drm);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
drm_irq_uninstall(drm);
|
||||
pm_runtime_put(dev);
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
|
|
|
@ -349,11 +349,11 @@ malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
|
|||
if (objs->size < afbc_size) {
|
||||
DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n",
|
||||
objs->size, afbc_size);
|
||||
drm_gem_object_put_unlocked(objs);
|
||||
drm_gem_object_put(objs);
|
||||
return false;
|
||||
}
|
||||
|
||||
drm_gem_object_put_unlocked(objs);
|
||||
drm_gem_object_put(objs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -563,16 +563,7 @@ static void malidp_debugfs_init(struct drm_minor *minor)
|
|||
|
||||
static struct drm_driver malidp_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = malidp_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = malidp_debugfs_init,
|
||||
#endif
|
||||
|
@ -666,20 +657,11 @@ static ssize_t core_id_show(struct device *dev, struct device_attribute *attr,
|
|||
|
||||
static DEVICE_ATTR_RO(core_id);
|
||||
|
||||
static int malidp_init_sysfs(struct device *dev)
|
||||
{
|
||||
int ret = device_create_file(dev, &dev_attr_core_id);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("failed to create device file for core_id\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void malidp_fini_sysfs(struct device *dev)
|
||||
{
|
||||
device_remove_file(dev, &dev_attr_core_id);
|
||||
}
|
||||
static struct attribute *mali_dp_attrs[] = {
|
||||
&dev_attr_core_id.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mali_dp);
|
||||
|
||||
#define MAX_OUTPUT_CHANNELS 3
|
||||
|
||||
|
@ -841,10 +823,6 @@ static int malidp_bind(struct device *dev)
|
|||
if (ret < 0)
|
||||
goto query_hw_fail;
|
||||
|
||||
ret = malidp_init_sysfs(dev);
|
||||
if (ret)
|
||||
goto init_fail;
|
||||
|
||||
/* Set the CRTC's port so that the encoder component can find it */
|
||||
malidp->crtc.port = of_graph_get_port_by_id(dev->of_node, 0);
|
||||
|
||||
|
@ -902,8 +880,6 @@ irq_init_fail:
|
|||
bind_fail:
|
||||
of_node_put(malidp->crtc.port);
|
||||
malidp->crtc.port = NULL;
|
||||
init_fail:
|
||||
malidp_fini_sysfs(dev);
|
||||
malidp_fini(drm);
|
||||
query_hw_fail:
|
||||
pm_runtime_put(dev);
|
||||
|
@ -929,15 +905,13 @@ static void malidp_unbind(struct device *dev)
|
|||
drm_dev_unregister(drm);
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_crtc_vblank_off(&malidp->crtc);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
malidp_se_irq_fini(hwdev);
|
||||
malidp_de_irq_fini(hwdev);
|
||||
drm->irq_enabled = false;
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
component_unbind_all(dev, drm);
|
||||
of_node_put(malidp->crtc.port);
|
||||
malidp->crtc.port = NULL;
|
||||
malidp_fini_sysfs(dev);
|
||||
malidp_fini(drm);
|
||||
pm_runtime_put(dev);
|
||||
if (pm_runtime_enabled(dev))
|
||||
|
@ -1033,6 +1007,7 @@ static struct platform_driver malidp_platform_driver = {
|
|||
.name = "mali-dp",
|
||||
.pm = &malidp_pm_ops,
|
||||
.of_match_table = malidp_drm_of_match,
|
||||
.dev_groups = mali_dp_groups,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -710,13 +710,13 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
|
||||
/* Must be a kernel-mapped object */
|
||||
if (!obj->addr) {
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (obj->obj.size < w * h * 4) {
|
||||
DRM_ERROR("buffer is too small\n");
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
@ -724,7 +724,7 @@ static int armada_drm_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
if (dcrtc->cursor_obj) {
|
||||
dcrtc->cursor_obj->update = NULL;
|
||||
dcrtc->cursor_obj->update_data = NULL;
|
||||
drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj);
|
||||
drm_gem_object_put(&dcrtc->cursor_obj->obj);
|
||||
}
|
||||
dcrtc->cursor_obj = obj;
|
||||
dcrtc->cursor_w = w;
|
||||
|
@ -760,7 +760,7 @@ static void armada_drm_crtc_destroy(struct drm_crtc *crtc)
|
|||
struct armada_private *priv = crtc->dev->dev_private;
|
||||
|
||||
if (dcrtc->cursor_obj)
|
||||
drm_gem_object_put_unlocked(&dcrtc->cursor_obj->obj);
|
||||
drm_gem_object_put(&dcrtc->cursor_obj->obj);
|
||||
|
||||
priv->dcrtc[dcrtc->num] = NULL;
|
||||
drm_crtc_cleanup(&dcrtc->crtc);
|
||||
|
|
|
@ -129,12 +129,12 @@ struct drm_framebuffer *armada_fb_create(struct drm_device *dev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
|
||||
return &dfb->fb;
|
||||
|
||||
err_unref:
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
err:
|
||||
DRM_ERROR("failed to initialize framebuffer: %d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
|
|
|
@ -51,13 +51,13 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
|
|||
|
||||
ret = armada_gem_linear_back(dev, obj);
|
||||
if (ret) {
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ptr = armada_gem_map_object(dev, obj);
|
||||
if (!ptr) {
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
|
|||
* A reference is now held by the framebuffer object if
|
||||
* successful, otherwise this drops the ref for the error path.
|
||||
*/
|
||||
drm_gem_object_put_unlocked(&obj->obj);
|
||||
drm_gem_object_put(&obj->obj);
|
||||
|
||||
if (IS_ERR(dfb))
|
||||
return PTR_ERR(dfb);
|
||||
|
|
|
@ -256,7 +256,7 @@ int armada_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
|
|||
/* drop reference from allocate - handle holds it now */
|
||||
DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
|
||||
err:
|
||||
drm_gem_object_put_unlocked(&dobj->obj);
|
||||
drm_gem_object_put(&dobj->obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ int armada_gem_create_ioctl(struct drm_device *dev, void *data,
|
|||
/* drop reference from allocate - handle holds it now */
|
||||
DRM_DEBUG_DRIVER("obj %p size %zu handle %#x\n", dobj, size, handle);
|
||||
err:
|
||||
drm_gem_object_put_unlocked(&dobj->obj);
|
||||
drm_gem_object_put(&dobj->obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -305,13 +305,13 @@ int armada_gem_mmap_ioctl(struct drm_device *dev, void *data,
|
|||
return -ENOENT;
|
||||
|
||||
if (!dobj->obj.filp) {
|
||||
drm_gem_object_put_unlocked(&dobj->obj);
|
||||
drm_gem_object_put(&dobj->obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = vm_mmap(dobj->obj.filp, 0, args->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, args->offset);
|
||||
drm_gem_object_put_unlocked(&dobj->obj);
|
||||
drm_gem_object_put(&dobj->obj);
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
|
||||
|
@ -366,7 +366,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data,
|
|||
}
|
||||
|
||||
unref:
|
||||
drm_gem_object_put_unlocked(&dobj->obj);
|
||||
drm_gem_object_put(&dobj->obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ DEFINE_DRM_GEM_CMA_FOPS(fops);
|
|||
|
||||
static struct drm_driver aspeed_gfx_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.gem_create_object = drm_cma_gem_create_object_default_funcs,
|
||||
.gem_create_object = drm_gem_cma_create_object_default_funcs,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
|
|
|
@ -91,15 +91,13 @@ static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
ast_kick_out_firmware_fb(pdev);
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
ret = pcim_enable_device(pdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev = drm_dev_alloc(&driver, &pdev->dev);
|
||||
if (IS_ERR(dev)) {
|
||||
ret = PTR_ERR(dev);
|
||||
goto err_pci_disable_device;
|
||||
}
|
||||
if (IS_ERR(dev))
|
||||
return PTR_ERR(dev);
|
||||
|
||||
dev->pdev = pdev;
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
@ -120,8 +118,6 @@ err_ast_driver_unload:
|
|||
ast_driver_unload(dev);
|
||||
err_drm_dev_put:
|
||||
drm_dev_put(dev);
|
||||
err_pci_disable_device:
|
||||
pci_disable_device(pdev);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
|
|
@ -531,8 +531,5 @@ void ast_driver_unload(struct drm_device *dev)
|
|||
drm_mode_config_cleanup(dev);
|
||||
|
||||
ast_mm_fini(ast);
|
||||
if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET)
|
||||
pci_iounmap(dev->pdev, ast->ioregs);
|
||||
pci_iounmap(dev->pdev, ast->regs);
|
||||
kfree(ast);
|
||||
}
|
||||
|
|
|
@ -821,16 +821,7 @@ static struct drm_driver atmel_hlcdc_dc_driver = {
|
|||
.irq_preinstall = atmel_hlcdc_dc_irq_uninstall,
|
||||
.irq_postinstall = atmel_hlcdc_dc_irq_postinstall,
|
||||
.irq_uninstall = atmel_hlcdc_dc_irq_uninstall,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &fops,
|
||||
.name = "atmel-hlcdc",
|
||||
.desc = "Atmel HLCD Controller DRM",
|
||||
|
|
|
@ -360,7 +360,7 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
|||
|
||||
buf[0] = pixel_clock_10kHz & 0xff;
|
||||
buf[1] = pixel_clock_10kHz >> 8;
|
||||
buf[2] = adj->vrefresh;
|
||||
buf[2] = drm_mode_vrefresh(adj);
|
||||
buf[3] = 0x00;
|
||||
buf[4] = adj->hdisplay;
|
||||
buf[5] = adj->hdisplay >> 8;
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
* datasheet: http://www.ti.com/lit/ds/symlink/sn65dsi86.pdf
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -48,12 +50,24 @@
|
|||
#define SN_CHA_VERTICAL_BACK_PORCH_REG 0x36
|
||||
#define SN_CHA_HORIZONTAL_FRONT_PORCH_REG 0x38
|
||||
#define SN_CHA_VERTICAL_FRONT_PORCH_REG 0x3A
|
||||
#define SN_LN_ASSIGN_REG 0x59
|
||||
#define LN_ASSIGN_WIDTH 2
|
||||
#define SN_ENH_FRAME_REG 0x5A
|
||||
#define VSTREAM_ENABLE BIT(3)
|
||||
#define LN_POLRS_OFFSET 4
|
||||
#define LN_POLRS_MASK 0xf0
|
||||
#define SN_DATA_FORMAT_REG 0x5B
|
||||
#define BPP_18_RGB BIT(0)
|
||||
#define SN_HPD_DISABLE_REG 0x5C
|
||||
#define HPD_DISABLE BIT(0)
|
||||
#define SN_GPIO_IO_REG 0x5E
|
||||
#define SN_GPIO_INPUT_SHIFT 4
|
||||
#define SN_GPIO_OUTPUT_SHIFT 0
|
||||
#define SN_GPIO_CTRL_REG 0x5F
|
||||
#define SN_GPIO_MUX_INPUT 0
|
||||
#define SN_GPIO_MUX_OUTPUT 1
|
||||
#define SN_GPIO_MUX_SPECIAL 2
|
||||
#define SN_GPIO_MUX_MASK 0x3
|
||||
#define SN_AUX_WDATA_REG(x) (0x64 + (x))
|
||||
#define SN_AUX_ADDR_19_16_REG 0x74
|
||||
#define SN_AUX_ADDR_15_8_REG 0x75
|
||||
|
@ -88,6 +102,38 @@
|
|||
|
||||
#define SN_REGULATOR_SUPPLY_NUM 4
|
||||
|
||||
#define SN_MAX_DP_LANES 4
|
||||
#define SN_NUM_GPIOS 4
|
||||
#define SN_GPIO_PHYSICAL_OFFSET 1
|
||||
|
||||
/**
|
||||
* struct ti_sn_bridge - Platform data for ti-sn65dsi86 driver.
|
||||
* @dev: Pointer to our device.
|
||||
* @regmap: Regmap for accessing i2c.
|
||||
* @aux: Our aux channel.
|
||||
* @bridge: Our bridge.
|
||||
* @connector: Our connector.
|
||||
* @debugfs: Used for managing our debugfs.
|
||||
* @host_node: Remote DSI node.
|
||||
* @dsi: Our MIPI DSI source.
|
||||
* @refclk: Our reference clock.
|
||||
* @panel: Our panel.
|
||||
* @enable_gpio: The GPIO we toggle to enable the bridge.
|
||||
* @supplies: Data for bulk enabling/disabling our regulators.
|
||||
* @dp_lanes: Count of dp_lanes we're using.
|
||||
* @ln_assign: Value to program to the LN_ASSIGN register.
|
||||
* @ln_polrs: Value for the 4-bit LN_POLRS field of SN_ENH_FRAME_REG.
|
||||
*
|
||||
* @gchip: If we expose our GPIOs, this is used.
|
||||
* @gchip_output: A cache of whether we've set GPIOs to output. This
|
||||
* serves double-duty of keeping track of the direction and
|
||||
* also keeping track of whether we've incremented the
|
||||
* pm_runtime reference count for this pin, which we do
|
||||
* whenever a pin is configured as an output. This is a
|
||||
* bitmap so we can do atomic ops on it without an extra
|
||||
* lock so concurrent users of our 4 GPIOs don't stomp on
|
||||
* each other's read-modify-write.
|
||||
*/
|
||||
struct ti_sn_bridge {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
|
@ -102,6 +148,13 @@ struct ti_sn_bridge {
|
|||
struct gpio_desc *enable_gpio;
|
||||
struct regulator_bulk_data supplies[SN_REGULATOR_SUPPLY_NUM];
|
||||
int dp_lanes;
|
||||
u8 ln_assign;
|
||||
u8 ln_polrs;
|
||||
|
||||
#if defined(CONFIG_OF_GPIO)
|
||||
struct gpio_chip gchip;
|
||||
DECLARE_BITMAP(gchip_output, SN_NUM_GPIOS);
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct regmap_range ti_sn_bridge_volatile_ranges[] = {
|
||||
|
@ -451,7 +504,7 @@ static unsigned int ti_sn_bridge_get_bpp(struct ti_sn_bridge *pdata)
|
|||
return 24;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* LUT index corresponds to register value and
|
||||
* LUT values corresponds to dp data rate supported
|
||||
* by the bridge in Mbps unit.
|
||||
|
@ -475,7 +528,7 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn_bridge *pdata)
|
|||
1000 * pdata->dp_lanes * DP_CLK_FUDGE_DEN);
|
||||
|
||||
for (i = 1; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++)
|
||||
if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz)
|
||||
if (ti_sn_bridge_dp_rate_lut[i] >= dp_rate_mhz)
|
||||
break;
|
||||
|
||||
return i;
|
||||
|
@ -666,26 +719,20 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge)
|
|||
int dp_rate_idx;
|
||||
unsigned int val;
|
||||
int ret = -EINVAL;
|
||||
int max_dp_lanes;
|
||||
|
||||
/*
|
||||
* Run with the maximum number of lanes that the DP sink supports.
|
||||
*
|
||||
* Depending use cases, we might want to revisit this later because:
|
||||
* - It's plausible that someone may have run fewer lines to the
|
||||
* sink than the sink actually supports, assuming that the lines
|
||||
* will just be driven at a higher rate.
|
||||
* - The DP spec seems to indicate that it's more important to minimize
|
||||
* the number of lanes than the link rate.
|
||||
*
|
||||
* If we do revisit, it would be important to measure the power impact.
|
||||
*/
|
||||
pdata->dp_lanes = ti_sn_get_max_lanes(pdata);
|
||||
max_dp_lanes = ti_sn_get_max_lanes(pdata);
|
||||
pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes);
|
||||
|
||||
/* DSI_A lane config */
|
||||
val = CHA_DSI_LANES(4 - pdata->dsi->lanes);
|
||||
val = CHA_DSI_LANES(SN_MAX_DP_LANES - pdata->dsi->lanes);
|
||||
regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG,
|
||||
CHA_DSI_LANES_MASK, val);
|
||||
|
||||
regmap_write(pdata->regmap, SN_LN_ASSIGN_REG, pdata->ln_assign);
|
||||
regmap_update_bits(pdata->regmap, SN_ENH_FRAME_REG, LN_POLRS_MASK,
|
||||
pdata->ln_polrs << LN_POLRS_OFFSET);
|
||||
|
||||
/* set dsi clk frequency value */
|
||||
ti_sn_bridge_set_dsi_rate(pdata);
|
||||
|
||||
|
@ -827,6 +874,12 @@ static ssize_t ti_sn_aux_transfer(struct drm_dp_aux *aux,
|
|||
buf[i]);
|
||||
}
|
||||
|
||||
/* Clear old status bits before start so we don't get confused */
|
||||
regmap_write(pdata->regmap, SN_AUX_CMD_STATUS_REG,
|
||||
AUX_IRQ_STATUS_NAT_I2C_FAIL |
|
||||
AUX_IRQ_STATUS_AUX_RPLY_TOUT |
|
||||
AUX_IRQ_STATUS_AUX_SHORT);
|
||||
|
||||
regmap_write(pdata->regmap, SN_AUX_CMD_REG, request_val | AUX_CMD_SEND);
|
||||
|
||||
ret = regmap_read_poll_timeout(pdata->regmap, SN_AUX_CMD_REG, val,
|
||||
|
@ -874,6 +927,236 @@ static int ti_sn_bridge_parse_dsi_host(struct ti_sn_bridge *pdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF_GPIO)
|
||||
|
||||
static int tn_sn_bridge_of_xlate(struct gpio_chip *chip,
|
||||
const struct of_phandle_args *gpiospec,
|
||||
u32 *flags)
|
||||
{
|
||||
if (WARN_ON(gpiospec->args_count < chip->of_gpio_n_cells))
|
||||
return -EINVAL;
|
||||
|
||||
if (gpiospec->args[0] > chip->ngpio || gpiospec->args[0] < 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (flags)
|
||||
*flags = gpiospec->args[1];
|
||||
|
||||
return gpiospec->args[0] - SN_GPIO_PHYSICAL_OFFSET;
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_gpio_get_direction(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct ti_sn_bridge *pdata = gpiochip_get_data(chip);
|
||||
|
||||
/*
|
||||
* We already have to keep track of the direction because we use
|
||||
* that to figure out whether we've powered the device. We can
|
||||
* just return that rather than (maybe) powering up the device
|
||||
* to ask its direction.
|
||||
*/
|
||||
return test_bit(offset, pdata->gchip_output) ?
|
||||
GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
struct ti_sn_bridge *pdata = gpiochip_get_data(chip);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* When the pin is an input we don't forcibly keep the bridge
|
||||
* powered--we just power it on to read the pin. NOTE: part of
|
||||
* the reason this works is that the bridge defaults (when
|
||||
* powered back on) to all 4 GPIOs being configured as GPIO input.
|
||||
* Also note that if something else is keeping the chip powered the
|
||||
* pm_runtime functions are lightweight increments of a refcount.
|
||||
*/
|
||||
pm_runtime_get_sync(pdata->dev);
|
||||
ret = regmap_read(pdata->regmap, SN_GPIO_IO_REG, &val);
|
||||
pm_runtime_put(pdata->dev);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return !!(val & BIT(SN_GPIO_INPUT_SHIFT + offset));
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_gpio_set(struct gpio_chip *chip, unsigned int offset,
|
||||
int val)
|
||||
{
|
||||
struct ti_sn_bridge *pdata = gpiochip_get_data(chip);
|
||||
int ret;
|
||||
|
||||
if (!test_bit(offset, pdata->gchip_output)) {
|
||||
dev_err(pdata->dev, "Ignoring GPIO set while input\n");
|
||||
return;
|
||||
}
|
||||
|
||||
val &= 1;
|
||||
ret = regmap_update_bits(pdata->regmap, SN_GPIO_IO_REG,
|
||||
BIT(SN_GPIO_OUTPUT_SHIFT + offset),
|
||||
val << (SN_GPIO_OUTPUT_SHIFT + offset));
|
||||
if (ret)
|
||||
dev_warn(pdata->dev,
|
||||
"Failed to set bridge GPIO %u: %d\n", offset, ret);
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_gpio_direction_input(struct gpio_chip *chip,
|
||||
unsigned int offset)
|
||||
{
|
||||
struct ti_sn_bridge *pdata = gpiochip_get_data(chip);
|
||||
int shift = offset * 2;
|
||||
int ret;
|
||||
|
||||
if (!test_and_clear_bit(offset, pdata->gchip_output))
|
||||
return 0;
|
||||
|
||||
ret = regmap_update_bits(pdata->regmap, SN_GPIO_CTRL_REG,
|
||||
SN_GPIO_MUX_MASK << shift,
|
||||
SN_GPIO_MUX_INPUT << shift);
|
||||
if (ret) {
|
||||
set_bit(offset, pdata->gchip_output);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: if nobody else is powering the device this may fully power
|
||||
* it off and when it comes back it will have lost all state, but
|
||||
* that's OK because the default is input and we're now an input.
|
||||
*/
|
||||
pm_runtime_put(pdata->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_gpio_direction_output(struct gpio_chip *chip,
|
||||
unsigned int offset, int val)
|
||||
{
|
||||
struct ti_sn_bridge *pdata = gpiochip_get_data(chip);
|
||||
int shift = offset * 2;
|
||||
int ret;
|
||||
|
||||
if (test_and_set_bit(offset, pdata->gchip_output))
|
||||
return 0;
|
||||
|
||||
pm_runtime_get_sync(pdata->dev);
|
||||
|
||||
/* Set value first to avoid glitching */
|
||||
ti_sn_bridge_gpio_set(chip, offset, val);
|
||||
|
||||
/* Set direction */
|
||||
ret = regmap_update_bits(pdata->regmap, SN_GPIO_CTRL_REG,
|
||||
SN_GPIO_MUX_MASK << shift,
|
||||
SN_GPIO_MUX_OUTPUT << shift);
|
||||
if (ret) {
|
||||
clear_bit(offset, pdata->gchip_output);
|
||||
pm_runtime_put(pdata->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_gpio_free(struct gpio_chip *chip, unsigned int offset)
|
||||
{
|
||||
/* We won't keep pm_runtime if we're input, so switch there on free */
|
||||
ti_sn_bridge_gpio_direction_input(chip, offset);
|
||||
}
|
||||
|
||||
static const char * const ti_sn_bridge_gpio_names[SN_NUM_GPIOS] = {
|
||||
"GPIO1", "GPIO2", "GPIO3", "GPIO4"
|
||||
};
|
||||
|
||||
static int ti_sn_setup_gpio_controller(struct ti_sn_bridge *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Only init if someone is going to use us as a GPIO controller */
|
||||
if (!of_property_read_bool(pdata->dev->of_node, "gpio-controller"))
|
||||
return 0;
|
||||
|
||||
pdata->gchip.label = dev_name(pdata->dev);
|
||||
pdata->gchip.parent = pdata->dev;
|
||||
pdata->gchip.owner = THIS_MODULE;
|
||||
pdata->gchip.of_xlate = tn_sn_bridge_of_xlate;
|
||||
pdata->gchip.of_gpio_n_cells = 2;
|
||||
pdata->gchip.free = ti_sn_bridge_gpio_free;
|
||||
pdata->gchip.get_direction = ti_sn_bridge_gpio_get_direction;
|
||||
pdata->gchip.direction_input = ti_sn_bridge_gpio_direction_input;
|
||||
pdata->gchip.direction_output = ti_sn_bridge_gpio_direction_output;
|
||||
pdata->gchip.get = ti_sn_bridge_gpio_get;
|
||||
pdata->gchip.set = ti_sn_bridge_gpio_set;
|
||||
pdata->gchip.can_sleep = true;
|
||||
pdata->gchip.names = ti_sn_bridge_gpio_names;
|
||||
pdata->gchip.ngpio = SN_NUM_GPIOS;
|
||||
pdata->gchip.base = -1;
|
||||
ret = devm_gpiochip_add_data(pdata->dev, &pdata->gchip, pdata);
|
||||
if (ret)
|
||||
dev_err(pdata->dev, "can't add gpio chip\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline int ti_sn_setup_gpio_controller(struct ti_sn_bridge *pdata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void ti_sn_bridge_parse_lanes(struct ti_sn_bridge *pdata,
|
||||
struct device_node *np)
|
||||
{
|
||||
u32 lane_assignments[SN_MAX_DP_LANES] = { 0, 1, 2, 3 };
|
||||
u32 lane_polarities[SN_MAX_DP_LANES] = { };
|
||||
struct device_node *endpoint;
|
||||
u8 ln_assign = 0;
|
||||
u8 ln_polrs = 0;
|
||||
int dp_lanes;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Read config from the device tree about lane remapping and lane
|
||||
* polarities. These are optional and we assume identity map and
|
||||
* normal polarity if nothing is specified. It's OK to specify just
|
||||
* data-lanes but not lane-polarities but not vice versa.
|
||||
*
|
||||
* Error checking is light (we just make sure we don't crash or
|
||||
* buffer overrun) and we assume dts is well formed and specifying
|
||||
* mappings that the hardware supports.
|
||||
*/
|
||||
endpoint = of_graph_get_endpoint_by_regs(np, 1, -1);
|
||||
dp_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
|
||||
if (dp_lanes > 0 && dp_lanes <= SN_MAX_DP_LANES) {
|
||||
of_property_read_u32_array(endpoint, "data-lanes",
|
||||
lane_assignments, dp_lanes);
|
||||
of_property_read_u32_array(endpoint, "lane-polarities",
|
||||
lane_polarities, dp_lanes);
|
||||
} else {
|
||||
dp_lanes = SN_MAX_DP_LANES;
|
||||
}
|
||||
of_node_put(endpoint);
|
||||
|
||||
/*
|
||||
* Convert into register format. Loop over all lanes even if
|
||||
* data-lanes had fewer elements so that we nicely initialize
|
||||
* the LN_ASSIGN register.
|
||||
*/
|
||||
for (i = SN_MAX_DP_LANES - 1; i >= 0; i--) {
|
||||
ln_assign = ln_assign << LN_ASSIGN_WIDTH | lane_assignments[i];
|
||||
ln_polrs = ln_polrs << 1 | lane_polarities[i];
|
||||
}
|
||||
|
||||
/* Stash in our struct for when we power on */
|
||||
pdata->dp_lanes = dp_lanes;
|
||||
pdata->ln_assign = ln_assign;
|
||||
pdata->ln_polrs = ln_polrs;
|
||||
}
|
||||
|
||||
static int ti_sn_bridge_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -916,6 +1199,8 @@ static int ti_sn_bridge_probe(struct i2c_client *client,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ti_sn_bridge_parse_lanes(pdata, client->dev.of_node);
|
||||
|
||||
ret = ti_sn_bridge_parse_regulators(pdata);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to parse regulators\n");
|
||||
|
@ -937,6 +1222,12 @@ static int ti_sn_bridge_probe(struct i2c_client *client,
|
|||
|
||||
pm_runtime_enable(pdata->dev);
|
||||
|
||||
ret = ti_sn_setup_gpio_controller(pdata);
|
||||
if (ret) {
|
||||
pm_runtime_disable(pdata->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, pdata);
|
||||
|
||||
pdata->aux.name = "ti-sn65dsi86-aux";
|
||||
|
|
|
@ -1097,7 +1097,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
|||
else if (funcs->dpms)
|
||||
funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
|
||||
if (!(dev->irq_enabled && dev->num_crtcs))
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
continue;
|
||||
|
||||
ret = drm_crtc_vblank_get(crtc);
|
||||
|
|
|
@ -122,27 +122,19 @@ struct drm_master *drm_master_create(struct drm_device *dev)
|
|||
return master;
|
||||
}
|
||||
|
||||
static int drm_set_master(struct drm_device *dev, struct drm_file *fpriv,
|
||||
bool new_master)
|
||||
static void drm_set_master(struct drm_device *dev, struct drm_file *fpriv,
|
||||
bool new_master)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
dev->master = drm_master_get(fpriv->master);
|
||||
if (dev->driver->master_set) {
|
||||
ret = dev->driver->master_set(dev, fpriv, new_master);
|
||||
if (unlikely(ret != 0)) {
|
||||
drm_master_put(&dev->master);
|
||||
}
|
||||
}
|
||||
if (dev->driver->master_set)
|
||||
dev->driver->master_set(dev, fpriv, new_master);
|
||||
|
||||
fpriv->was_master = (ret == 0);
|
||||
return ret;
|
||||
fpriv->was_master = true;
|
||||
}
|
||||
|
||||
static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
||||
{
|
||||
struct drm_master *old_master;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held_once(&dev->master_mutex);
|
||||
|
||||
|
@ -157,22 +149,12 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
|
|||
fpriv->is_master = 1;
|
||||
fpriv->authenticated = 1;
|
||||
|
||||
ret = drm_set_master(dev, fpriv, true);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
drm_set_master(dev, fpriv, true);
|
||||
|
||||
if (old_master)
|
||||
drm_master_put(&old_master);
|
||||
|
||||
return 0;
|
||||
|
||||
out_err:
|
||||
/* drop references and restore old master on failure */
|
||||
drm_master_put(&fpriv->master);
|
||||
fpriv->master = old_master;
|
||||
fpriv->is_master = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -233,7 +215,7 @@ drm_master_check_perm(struct drm_device *dev, struct drm_file *file_priv)
|
|||
int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->master_mutex);
|
||||
|
||||
|
@ -265,7 +247,7 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = drm_set_master(dev, file_priv, false);
|
||||
drm_set_master(dev, file_priv, false);
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
return ret;
|
||||
|
@ -282,7 +264,7 @@ static void drm_drop_master(struct drm_device *dev,
|
|||
int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dev->master_mutex);
|
||||
|
||||
|
@ -290,12 +272,15 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (!drm_is_current_master(file_priv))
|
||||
if (!drm_is_current_master(file_priv)) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (!dev->master)
|
||||
if (!dev->master) {
|
||||
ret = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (file_priv->master->lessor != NULL) {
|
||||
DRM_DEBUG_LEASE("Attempt to drop lessee %d as master\n", file_priv->master->lessee_id);
|
||||
|
@ -303,7 +288,6 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
drm_drop_master(dev, file_priv);
|
||||
out_unlock:
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
|
|
|
@ -237,7 +237,7 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
|
|||
drm_gem_vunmap(buffer->gem, buffer->vaddr);
|
||||
|
||||
if (buffer->gem)
|
||||
drm_gem_object_put_unlocked(buffer->gem);
|
||||
drm_gem_object_put(buffer->gem);
|
||||
|
||||
if (buffer->handle)
|
||||
drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
|
||||
|
@ -437,6 +437,39 @@ void drm_client_framebuffer_delete(struct drm_client_buffer *buffer)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_client_framebuffer_delete);
|
||||
|
||||
/**
|
||||
* drm_client_framebuffer_flush - Manually flush client framebuffer
|
||||
* @buffer: DRM client buffer (can be NULL)
|
||||
* @rect: Damage rectangle (if NULL flushes all)
|
||||
*
|
||||
* This calls &drm_framebuffer_funcs->dirty (if present) to flush buffer changes
|
||||
* for drivers that need it.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or negative error code on failure.
|
||||
*/
|
||||
int drm_client_framebuffer_flush(struct drm_client_buffer *buffer, struct drm_rect *rect)
|
||||
{
|
||||
if (!buffer || !buffer->fb || !buffer->fb->funcs->dirty)
|
||||
return 0;
|
||||
|
||||
if (rect) {
|
||||
struct drm_clip_rect clip = {
|
||||
.x1 = rect->x1,
|
||||
.y1 = rect->y1,
|
||||
.x2 = rect->x2,
|
||||
.y2 = rect->y2,
|
||||
};
|
||||
|
||||
return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
|
||||
0, 0, &clip, 1);
|
||||
}
|
||||
|
||||
return buffer->fb->funcs->dirty(buffer->fb, buffer->client->file,
|
||||
0, 0, NULL, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_client_framebuffer_flush);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)
|
||||
{
|
||||
|
|
|
@ -186,7 +186,7 @@ again:
|
|||
continue;
|
||||
|
||||
if (cmdline_mode->refresh_specified) {
|
||||
if (mode->vrefresh != cmdline_mode->refresh)
|
||||
if (drm_mode_vrefresh(mode) != cmdline_mode->refresh)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -563,7 +563,7 @@ static bool drm_client_firmware_config(struct drm_client_dev *client,
|
|||
struct drm_client_offset *offsets,
|
||||
bool *enabled, int width, int height)
|
||||
{
|
||||
unsigned int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
|
||||
const int count = min_t(unsigned int, connector_count, BITS_PER_LONG);
|
||||
unsigned long conn_configured, conn_seq, mask;
|
||||
struct drm_device *dev = client->dev;
|
||||
int i, j;
|
||||
|
@ -577,6 +577,9 @@ static bool drm_client_firmware_config(struct drm_client_dev *client,
|
|||
if (!drm_drv_uses_atomic_modeset(dev))
|
||||
return false;
|
||||
|
||||
if (WARN_ON(count <= 0))
|
||||
return false;
|
||||
|
||||
save_enabled = kcalloc(count, sizeof(bool), GFP_KERNEL);
|
||||
if (!save_enabled)
|
||||
return false;
|
||||
|
@ -966,7 +969,7 @@ bool drm_client_rotation(struct drm_mode_set *modeset, unsigned int *rotation)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_client_rotation);
|
||||
|
||||
static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active)
|
||||
static int drm_client_modeset_commit_atomic(struct drm_client_dev *client, bool active, bool check)
|
||||
{
|
||||
struct drm_device *dev = client->dev;
|
||||
struct drm_plane *plane;
|
||||
|
@ -1033,7 +1036,10 @@ retry:
|
|||
}
|
||||
}
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (check)
|
||||
ret = drm_atomic_check_only(state);
|
||||
else
|
||||
ret = drm_atomic_commit(state);
|
||||
|
||||
out_state:
|
||||
if (ret == -EDEADLK)
|
||||
|
@ -1094,6 +1100,30 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_client_modeset_check() - Check modeset configuration
|
||||
* @client: DRM client
|
||||
*
|
||||
* Check modeset configuration.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or negative error code on failure.
|
||||
*/
|
||||
int drm_client_modeset_check(struct drm_client_dev *client)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!drm_drv_uses_atomic_modeset(client->dev))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
ret = drm_client_modeset_commit_atomic(client, true, true);
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_client_modeset_check);
|
||||
|
||||
/**
|
||||
* drm_client_modeset_commit_locked() - Force commit CRTC configuration
|
||||
* @client: DRM client
|
||||
|
@ -1112,7 +1142,7 @@ int drm_client_modeset_commit_locked(struct drm_client_dev *client)
|
|||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
ret = drm_client_modeset_commit_atomic(client, true);
|
||||
ret = drm_client_modeset_commit_atomic(client, true, false);
|
||||
else
|
||||
ret = drm_client_modeset_commit_legacy(client);
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
@ -1188,7 +1218,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
|
|||
|
||||
mutex_lock(&client->modeset_mutex);
|
||||
if (drm_drv_uses_atomic_modeset(dev))
|
||||
ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON);
|
||||
ret = drm_client_modeset_commit_atomic(client, mode == DRM_MODE_DPMS_ON, false);
|
||||
else
|
||||
drm_client_modeset_dpms_legacy(client, mode);
|
||||
mutex_unlock(&client->modeset_mutex);
|
||||
|
|
|
@ -953,8 +953,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
|
|||
* connector is linked to. Drivers should never set this property directly,
|
||||
* it is handled by the DRM core by calling the &drm_connector_funcs.dpms
|
||||
* callback. For atomic drivers the remapping to the "ACTIVE" property is
|
||||
* implemented in the DRM core. This is the only standard connector
|
||||
* property that userspace can change.
|
||||
* implemented in the DRM core.
|
||||
*
|
||||
* Note that this property cannot be set through the MODE_ATOMIC ioctl,
|
||||
* userspace must use "ACTIVE" on the CRTC instead.
|
||||
|
@ -1000,6 +999,32 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
|
|||
* after modeset, the kernel driver may set this to "BAD" and issue a
|
||||
* hotplug uevent. Drivers should update this value using
|
||||
* drm_connector_set_link_status_property().
|
||||
*
|
||||
* When user-space receives the hotplug uevent and detects a "BAD"
|
||||
* link-status, the sink doesn't receive pixels anymore (e.g. the screen
|
||||
* becomes completely black). The list of available modes may have
|
||||
* changed. User-space is expected to pick a new mode if the current one
|
||||
* has disappeared and perform a new modeset with link-status set to
|
||||
* "GOOD" to re-enable the connector.
|
||||
*
|
||||
* If multiple connectors share the same CRTC and one of them gets a "BAD"
|
||||
* link-status, the other are unaffected (ie. the sinks still continue to
|
||||
* receive pixels).
|
||||
*
|
||||
* When user-space performs an atomic commit on a connector with a "BAD"
|
||||
* link-status without resetting the property to "GOOD", the sink may
|
||||
* still not receive pixels. When user-space performs an atomic commit
|
||||
* which resets the link-status property to "GOOD" without the
|
||||
* ALLOW_MODESET flag set, it might fail because a modeset is required.
|
||||
*
|
||||
* User-space can only change link-status to "GOOD", changing it to "BAD"
|
||||
* is a no-op.
|
||||
*
|
||||
* For backwards compatibility with non-atomic userspace the kernel
|
||||
* tries to automatically set the link-status back to "GOOD" in the
|
||||
* SETCRTC IOCTL. This might fail if the mode is no longer valid, similar
|
||||
* to how it might fail if a different screen has been connected in the
|
||||
* interim.
|
||||
* non_desktop:
|
||||
* Indicates the output should be ignored for purposes of displaying a
|
||||
* standard desktop environment or console. This is most likely because
|
||||
|
|
|
@ -204,6 +204,33 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
|
|||
return fence;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: standard CRTC properties
|
||||
*
|
||||
* DRM CRTCs have a few standardized properties:
|
||||
*
|
||||
* ACTIVE:
|
||||
* Atomic property for setting the power state of the CRTC. When set to 1
|
||||
* the CRTC will actively display content. When set to 0 the CRTC will be
|
||||
* powered off. There is no expectation that user-space will reset CRTC
|
||||
* resources like the mode and planes when setting ACTIVE to 0.
|
||||
*
|
||||
* User-space can rely on an ACTIVE change to 1 to never fail an atomic
|
||||
* test as long as no other property has changed. If a change to ACTIVE
|
||||
* fails an atomic test, this is a driver bug. For this reason setting
|
||||
* ACTIVE to 0 must not release internal resources (like reserved memory
|
||||
* bandwidth or clock generators).
|
||||
*
|
||||
* Note that the legacy DPMS property on connectors is internally routed
|
||||
* to control this property for atomic drivers.
|
||||
* MODE_ID:
|
||||
* Atomic property for setting the CRTC display timings. The value is the
|
||||
* ID of a blob containing the DRM mode info. To disable the CRTC,
|
||||
* user-space must set this property to 0.
|
||||
*
|
||||
* Setting MODE_ID to 0 will release reserved resources for the CRTC.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_crtc_init_with_planes - Initialise a new CRTC object with
|
||||
* specified primary and cursor planes.
|
||||
|
|
|
@ -311,13 +311,13 @@ static ssize_t connector_write(struct file *file, const char __user *ubuf,
|
|||
|
||||
buf[len] = '\0';
|
||||
|
||||
if (!strcmp(buf, "on"))
|
||||
if (sysfs_streq(buf, "on"))
|
||||
connector->force = DRM_FORCE_ON;
|
||||
else if (!strcmp(buf, "digital"))
|
||||
else if (sysfs_streq(buf, "digital"))
|
||||
connector->force = DRM_FORCE_ON_DIGITAL;
|
||||
else if (!strcmp(buf, "off"))
|
||||
else if (sysfs_streq(buf, "off"))
|
||||
connector->force = DRM_FORCE_OFF;
|
||||
else if (!strcmp(buf, "unspecified"))
|
||||
else if (sysfs_streq(buf, "unspecified"))
|
||||
connector->force = DRM_FORCE_UNSPECIFIED;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
|
|
@ -1365,7 +1365,7 @@ EXPORT_SYMBOL(drm_dp_get_edid_quirks);
|
|||
/**
|
||||
* drm_dp_read_desc - read sink/branch descriptor from DPCD
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @desc: Device decriptor to fill from DPCD
|
||||
* @desc: Device descriptor to fill from DPCD
|
||||
* @is_branch: true for branch devices, false for sink devices
|
||||
*
|
||||
* Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the
|
||||
|
@ -1591,6 +1591,7 @@ EXPORT_SYMBOL(drm_dp_get_phy_test_pattern);
|
|||
* drm_dp_set_phy_test_pattern() - set the pattern to the sink.
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @data: DP phy compliance test parameters.
|
||||
* @dp_rev: DP revision to use for compliance testing
|
||||
*
|
||||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
|
|
|
@ -88,8 +88,8 @@ static int drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr,
|
|||
static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr,
|
||||
u8 *guid);
|
||||
|
||||
static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux);
|
||||
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux);
|
||||
static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port);
|
||||
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port);
|
||||
static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr);
|
||||
|
||||
#define DBG_PREFIX "[dp_mst]"
|
||||
|
@ -1178,12 +1178,38 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
|
|||
struct drm_dp_sideband_msg_tx *txmsg)
|
||||
{
|
||||
struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
|
||||
unsigned long wait_timeout = msecs_to_jiffies(4000);
|
||||
unsigned long wait_expires = jiffies + wait_timeout;
|
||||
int ret;
|
||||
|
||||
ret = wait_event_timeout(mgr->tx_waitq,
|
||||
check_txmsg_state(mgr, txmsg),
|
||||
(4 * HZ));
|
||||
mutex_lock(&mstb->mgr->qlock);
|
||||
for (;;) {
|
||||
/*
|
||||
* If the driver provides a way for this, change to
|
||||
* poll-waiting for the MST reply interrupt if we didn't receive
|
||||
* it for 50 msec. This would cater for cases where the HPD
|
||||
* pulse signal got lost somewhere, even though the sink raised
|
||||
* the corresponding MST interrupt correctly. One example is the
|
||||
* Club 3D CAC-1557 TypeC -> DP adapter which for some reason
|
||||
* filters out short pulses with a duration less than ~540 usec.
|
||||
*
|
||||
* The poll period is 50 msec to avoid missing an interrupt
|
||||
* after the sink has cleared it (after a 110msec timeout
|
||||
* since it raised the interrupt).
|
||||
*/
|
||||
ret = wait_event_timeout(mgr->tx_waitq,
|
||||
check_txmsg_state(mgr, txmsg),
|
||||
mgr->cbs->poll_hpd_irq ?
|
||||
msecs_to_jiffies(50) :
|
||||
wait_timeout);
|
||||
|
||||
if (ret || !mgr->cbs->poll_hpd_irq ||
|
||||
time_after(jiffies, wait_expires))
|
||||
break;
|
||||
|
||||
mgr->cbs->poll_hpd_irq(mgr);
|
||||
}
|
||||
|
||||
mutex_lock(&mgr->qlock);
|
||||
if (ret > 0) {
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_TIMEOUT) {
|
||||
ret = -EIO;
|
||||
|
@ -1197,7 +1223,8 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
|
|||
|
||||
/* remove from q */
|
||||
if (txmsg->state == DRM_DP_SIDEBAND_TX_QUEUED ||
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND)
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_START_SEND ||
|
||||
txmsg->state == DRM_DP_SIDEBAND_TX_SENT)
|
||||
list_del(&txmsg->next);
|
||||
}
|
||||
out:
|
||||
|
@ -1603,7 +1630,7 @@ static void drm_dp_destroy_mst_branch_device(struct kref *kref)
|
|||
mutex_lock(&mgr->delayed_destroy_lock);
|
||||
list_add(&mstb->destroy_next, &mgr->destroy_branch_device_list);
|
||||
mutex_unlock(&mgr->delayed_destroy_lock);
|
||||
schedule_work(&mgr->delayed_destroy_work);
|
||||
queue_work(mgr->delayed_destroy_wq, &mgr->delayed_destroy_work);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1720,7 +1747,7 @@ static void drm_dp_destroy_port(struct kref *kref)
|
|||
mutex_lock(&mgr->delayed_destroy_lock);
|
||||
list_add(&port->next, &mgr->destroy_port_list);
|
||||
mutex_unlock(&mgr->delayed_destroy_lock);
|
||||
schedule_work(&mgr->delayed_destroy_work);
|
||||
queue_work(mgr->delayed_destroy_wq, &mgr->delayed_destroy_work);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1966,7 +1993,7 @@ drm_dp_port_set_pdt(struct drm_dp_mst_port *port, u8 new_pdt,
|
|||
}
|
||||
|
||||
/* remove i2c over sideband */
|
||||
drm_dp_mst_unregister_i2c_bus(&port->aux);
|
||||
drm_dp_mst_unregister_i2c_bus(port);
|
||||
} else {
|
||||
mutex_lock(&mgr->lock);
|
||||
drm_dp_mst_topology_put_mstb(port->mstb);
|
||||
|
@ -1981,7 +2008,7 @@ drm_dp_port_set_pdt(struct drm_dp_mst_port *port, u8 new_pdt,
|
|||
if (port->pdt != DP_PEER_DEVICE_NONE) {
|
||||
if (drm_dp_mst_is_end_device(port->pdt, port->mcs)) {
|
||||
/* add i2c over sideband */
|
||||
ret = drm_dp_mst_register_i2c_bus(&port->aux);
|
||||
ret = drm_dp_mst_register_i2c_bus(port);
|
||||
} else {
|
||||
lct = drm_dp_calculate_rad(port, rad);
|
||||
mstb = drm_dp_add_mst_branch_device(lct, rad);
|
||||
|
@ -2894,8 +2921,9 @@ out:
|
|||
return ret < 0 ? ret : changed;
|
||||
}
|
||||
|
||||
void drm_dp_send_clear_payload_id_table(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_branch *mstb)
|
||||
static void
|
||||
drm_dp_send_clear_payload_id_table(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_branch *mstb)
|
||||
{
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
int ret;
|
||||
|
@ -4641,12 +4669,13 @@ static void drm_dp_tx_work(struct work_struct *work)
|
|||
static inline void
|
||||
drm_dp_delayed_destroy_port(struct drm_dp_mst_port *port)
|
||||
{
|
||||
drm_dp_port_set_pdt(port, DP_PEER_DEVICE_NONE, port->mcs);
|
||||
|
||||
if (port->connector) {
|
||||
drm_connector_unregister(port->connector);
|
||||
drm_connector_put(port->connector);
|
||||
}
|
||||
|
||||
drm_dp_port_set_pdt(port, DP_PEER_DEVICE_NONE, port->mcs);
|
||||
drm_dp_mst_put_port_malloc(port);
|
||||
}
|
||||
|
||||
|
@ -5179,6 +5208,15 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr,
|
|||
INIT_LIST_HEAD(&mgr->destroy_port_list);
|
||||
INIT_LIST_HEAD(&mgr->destroy_branch_device_list);
|
||||
INIT_LIST_HEAD(&mgr->up_req_list);
|
||||
|
||||
/*
|
||||
* delayed_destroy_work will be queued on a dedicated WQ, so that any
|
||||
* requeuing will be also flushed when deiniting the topology manager.
|
||||
*/
|
||||
mgr->delayed_destroy_wq = alloc_ordered_workqueue("drm_dp_mst_wq", 0);
|
||||
if (mgr->delayed_destroy_wq == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_WORK(&mgr->work, drm_dp_mst_link_probe_work);
|
||||
INIT_WORK(&mgr->tx_work, drm_dp_tx_work);
|
||||
INIT_WORK(&mgr->delayed_destroy_work, drm_dp_delayed_destroy_work);
|
||||
|
@ -5223,7 +5261,11 @@ void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr)
|
|||
{
|
||||
drm_dp_mst_topology_mgr_set_mst(mgr, false);
|
||||
flush_work(&mgr->work);
|
||||
cancel_work_sync(&mgr->delayed_destroy_work);
|
||||
/* The following will also drain any requeued work on the WQ. */
|
||||
if (mgr->delayed_destroy_wq) {
|
||||
destroy_workqueue(mgr->delayed_destroy_wq);
|
||||
mgr->delayed_destroy_wq = NULL;
|
||||
}
|
||||
mutex_lock(&mgr->payload_lock);
|
||||
kfree(mgr->payloads);
|
||||
mgr->payloads = NULL;
|
||||
|
@ -5346,22 +5388,26 @@ static const struct i2c_algorithm drm_dp_mst_i2c_algo = {
|
|||
|
||||
/**
|
||||
* drm_dp_mst_register_i2c_bus() - register an I2C adapter for I2C-over-AUX
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @port: The port to add the I2C bus on
|
||||
*
|
||||
* Returns 0 on success or a negative error code on failure.
|
||||
*/
|
||||
static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux)
|
||||
static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port)
|
||||
{
|
||||
struct drm_dp_aux *aux = &port->aux;
|
||||
struct device *parent_dev = port->mgr->dev->dev;
|
||||
|
||||
aux->ddc.algo = &drm_dp_mst_i2c_algo;
|
||||
aux->ddc.algo_data = aux;
|
||||
aux->ddc.retries = 3;
|
||||
|
||||
aux->ddc.class = I2C_CLASS_DDC;
|
||||
aux->ddc.owner = THIS_MODULE;
|
||||
aux->ddc.dev.parent = aux->dev;
|
||||
aux->ddc.dev.of_node = aux->dev->of_node;
|
||||
/* FIXME: set the kdev of the port's connector as parent */
|
||||
aux->ddc.dev.parent = parent_dev;
|
||||
aux->ddc.dev.of_node = parent_dev->of_node;
|
||||
|
||||
strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(aux->dev),
|
||||
strlcpy(aux->ddc.name, aux->name ? aux->name : dev_name(parent_dev),
|
||||
sizeof(aux->ddc.name));
|
||||
|
||||
return i2c_add_adapter(&aux->ddc);
|
||||
|
@ -5369,11 +5415,11 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_aux *aux)
|
|||
|
||||
/**
|
||||
* drm_dp_mst_unregister_i2c_bus() - unregister an I2C-over-AUX adapter
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @port: The port to remove the I2C bus from
|
||||
*/
|
||||
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux)
|
||||
static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port)
|
||||
{
|
||||
i2c_del_adapter(&aux->ddc);
|
||||
i2c_del_adapter(&port->aux.ddc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5447,7 +5493,7 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port)
|
|||
{
|
||||
struct drm_dp_mst_port *immediate_upstream_port;
|
||||
struct drm_dp_mst_port *fec_port;
|
||||
struct drm_dp_desc desc = { };
|
||||
struct drm_dp_desc desc = {};
|
||||
u8 endpoint_fec;
|
||||
u8 endpoint_dsc;
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -253,8 +253,8 @@ void drm_file_free(struct drm_file *file)
|
|||
|
||||
dev = file->minor->dev;
|
||||
|
||||
DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
|
||||
task_pid_nr(current),
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, open_count=%d\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file->minor->kdev->devt),
|
||||
atomic_read(&dev->open_count));
|
||||
|
||||
|
@ -342,10 +342,12 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
|||
return -EBUSY; /* No exclusive opens */
|
||||
if (!drm_cpu_valid())
|
||||
return -EINVAL;
|
||||
if (dev->switch_power_state != DRM_SWITCH_POWER_ON && dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
|
||||
if (dev->switch_power_state != DRM_SWITCH_POWER_ON &&
|
||||
dev->switch_power_state != DRM_SWITCH_POWER_DYNAMIC_OFF)
|
||||
return -EINVAL;
|
||||
|
||||
DRM_DEBUG("pid = %d, minor = %d\n", task_pid_nr(current), minor->index);
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, minor=%d\n", current->comm,
|
||||
task_pid_nr(current), minor->index);
|
||||
|
||||
priv = drm_file_alloc(minor);
|
||||
if (IS_ERR(priv))
|
||||
|
|
|
@ -79,39 +79,60 @@ void drm_fb_memcpy_dstclip(void __iomem *dst, void *vaddr,
|
|||
EXPORT_SYMBOL(drm_fb_memcpy_dstclip);
|
||||
|
||||
/**
|
||||
* drm_fb_swab16 - Swap bytes into clip buffer
|
||||
* @dst: RGB565 destination buffer
|
||||
* @vaddr: RGB565 source buffer
|
||||
* drm_fb_swab - Swap bytes into clip buffer
|
||||
* @dst: Destination buffer
|
||||
* @src: Source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
* @cached: Source buffer is mapped cached (eg. not write-combined)
|
||||
*
|
||||
* If @cached is false a temporary buffer is used to cache one pixel line at a
|
||||
* time to speed up slow uncached reads.
|
||||
*
|
||||
* This function does not apply clipping on dst, i.e. the destination
|
||||
* is a small buffer containing the clip rect only.
|
||||
*/
|
||||
void drm_fb_swab16(u16 *dst, void *vaddr, struct drm_framebuffer *fb,
|
||||
struct drm_rect *clip)
|
||||
void drm_fb_swab(void *dst, void *src, struct drm_framebuffer *fb,
|
||||
struct drm_rect *clip, bool cached)
|
||||
{
|
||||
size_t len = (clip->x2 - clip->x1) * sizeof(u16);
|
||||
u8 cpp = fb->format->cpp[0];
|
||||
size_t len = drm_rect_width(clip) * cpp;
|
||||
u16 *src16, *dst16 = dst;
|
||||
u32 *src32, *dst32 = dst;
|
||||
unsigned int x, y;
|
||||
u16 *src, *buf;
|
||||
void *buf = NULL;
|
||||
|
||||
/*
|
||||
* The cma memory is write-combined so reads are uncached.
|
||||
* Speed up by fetching one line at a time.
|
||||
*/
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
if (WARN_ON_ONCE(cpp != 2 && cpp != 4))
|
||||
return;
|
||||
|
||||
if (!cached)
|
||||
buf = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
src += clip_offset(clip, fb->pitches[0], cpp);
|
||||
|
||||
for (y = clip->y1; y < clip->y2; y++) {
|
||||
src = vaddr + (y * fb->pitches[0]);
|
||||
src += clip->x1;
|
||||
memcpy(buf, src, len);
|
||||
src = buf;
|
||||
for (x = clip->x1; x < clip->x2; x++)
|
||||
*dst++ = swab16(*src++);
|
||||
if (buf) {
|
||||
memcpy(buf, src, len);
|
||||
src16 = buf;
|
||||
src32 = buf;
|
||||
} else {
|
||||
src16 = src;
|
||||
src32 = src;
|
||||
}
|
||||
|
||||
for (x = clip->x1; x < clip->x2; x++) {
|
||||
if (cpp == 4)
|
||||
*dst32++ = swab32(*src32++);
|
||||
else
|
||||
*dst16++ = swab16(*src16++);
|
||||
}
|
||||
|
||||
src += fb->pitches[0];
|
||||
}
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_swab16);
|
||||
EXPORT_SYMBOL(drm_fb_swab);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgb565_line(u16 *dbuf, u32 *sbuf,
|
||||
unsigned int pixels,
|
||||
|
|
|
@ -235,7 +235,7 @@ drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
|
|||
mutex_unlock(&dev->object_name_lock);
|
||||
|
||||
if (final)
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -331,7 +331,7 @@ int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
|
|||
|
||||
*offset = drm_vma_node_offset_addr(&obj->vma_node);
|
||||
out:
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -548,6 +548,10 @@ static void drm_gem_check_release_pagevec(struct pagevec *pvec)
|
|||
* set during initialization. If you have special zone constraints, set them
|
||||
* after drm_gem_object_init() via mapping_set_gfp_mask(). shmem-core takes care
|
||||
* to keep pages in the required zone during swap-in.
|
||||
*
|
||||
* This function is only valid on objects initialized with
|
||||
* drm_gem_object_init(), but not for those initialized with
|
||||
* drm_gem_private_object_init() only.
|
||||
*/
|
||||
struct page **drm_gem_get_pages(struct drm_gem_object *obj)
|
||||
{
|
||||
|
@ -556,6 +560,10 @@ struct page **drm_gem_get_pages(struct drm_gem_object *obj)
|
|||
struct pagevec pvec;
|
||||
int i, npages;
|
||||
|
||||
|
||||
if (WARN_ON(!obj->filp))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* This is the shared memory object that backs the GEM resource */
|
||||
mapping = obj->filp->f_mapping;
|
||||
|
||||
|
@ -709,6 +717,8 @@ int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
|
|||
if (!objs)
|
||||
return -ENOMEM;
|
||||
|
||||
*objs_out = objs;
|
||||
|
||||
handles = kvmalloc_array(count, sizeof(u32), GFP_KERNEL);
|
||||
if (!handles) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -722,8 +732,6 @@ int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles,
|
|||
}
|
||||
|
||||
ret = objects_lookup(filp, handles, count, objs);
|
||||
*objs_out = objs;
|
||||
|
||||
out:
|
||||
kvfree(handles);
|
||||
return ret;
|
||||
|
@ -785,7 +793,7 @@ long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle,
|
|||
else if (ret > 0)
|
||||
ret = 0;
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -860,7 +868,7 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
err:
|
||||
mutex_unlock(&dev->object_name_lock);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -898,7 +906,7 @@ drm_gem_open_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
/* drm_gem_handle_create_tail unlocks dev->object_name_lock. */
|
||||
ret = drm_gem_handle_create_tail(file_priv, obj, &handle);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -965,7 +973,6 @@ EXPORT_SYMBOL(drm_gem_object_release);
|
|||
* @kref: kref of the object to free
|
||||
*
|
||||
* Called after the last reference to the object has been lost.
|
||||
* Must be called holding &drm_device.struct_mutex.
|
||||
*
|
||||
* Frees the object
|
||||
*/
|
||||
|
@ -976,50 +983,15 @@ drm_gem_object_free(struct kref *kref)
|
|||
container_of(kref, struct drm_gem_object, refcount);
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
if (obj->funcs) {
|
||||
if (obj->funcs)
|
||||
obj->funcs->free(obj);
|
||||
} else if (dev->driver->gem_free_object_unlocked) {
|
||||
else if (dev->driver->gem_free_object_unlocked)
|
||||
dev->driver->gem_free_object_unlocked(obj);
|
||||
} else if (dev->driver->gem_free_object) {
|
||||
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
|
||||
|
||||
dev->driver->gem_free_object(obj);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_free);
|
||||
|
||||
/**
|
||||
* drm_gem_object_put_unlocked - drop a GEM buffer object reference
|
||||
* @obj: GEM buffer object
|
||||
*
|
||||
* This releases a reference to @obj. Callers must not hold the
|
||||
* &drm_device.struct_mutex lock when calling this function.
|
||||
*
|
||||
* See also __drm_gem_object_put().
|
||||
*/
|
||||
void
|
||||
drm_gem_object_put_unlocked(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev;
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
dev = obj->dev;
|
||||
|
||||
if (dev->driver->gem_free_object) {
|
||||
might_lock(&dev->struct_mutex);
|
||||
if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
|
||||
&dev->struct_mutex))
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
} else {
|
||||
kref_put(&obj->refcount, drm_gem_object_free);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_put_unlocked);
|
||||
|
||||
/**
|
||||
* drm_gem_object_put - release a GEM buffer object reference
|
||||
* drm_gem_object_put_locked - release a GEM buffer object reference
|
||||
* @obj: GEM buffer object
|
||||
*
|
||||
* This releases a reference to @obj. Callers must hold the
|
||||
|
@ -1027,10 +999,10 @@ EXPORT_SYMBOL(drm_gem_object_put_unlocked);
|
|||
* driver doesn't use &drm_device.struct_mutex for anything.
|
||||
*
|
||||
* For drivers not encumbered with legacy locking use
|
||||
* drm_gem_object_put_unlocked() instead.
|
||||
* drm_gem_object_put() instead.
|
||||
*/
|
||||
void
|
||||
drm_gem_object_put(struct drm_gem_object *obj)
|
||||
drm_gem_object_put_locked(struct drm_gem_object *obj)
|
||||
{
|
||||
if (obj) {
|
||||
WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
|
||||
|
@ -1038,7 +1010,7 @@ drm_gem_object_put(struct drm_gem_object *obj)
|
|||
kref_put(&obj->refcount, drm_gem_object_free);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_object_put);
|
||||
EXPORT_SYMBOL(drm_gem_object_put_locked);
|
||||
|
||||
/**
|
||||
* drm_gem_vm_open - vma->ops->open implementation for GEM
|
||||
|
@ -1066,7 +1038,7 @@ void drm_gem_vm_close(struct vm_area_struct *vma)
|
|||
{
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_vm_close);
|
||||
|
||||
|
@ -1115,7 +1087,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
|
|||
if (obj->funcs && obj->funcs->mmap) {
|
||||
ret = obj->funcs->mmap(obj, vma);
|
||||
if (ret) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
WARN_ON(!(vma->vm_flags & VM_DONTEXPAND));
|
||||
|
@ -1125,7 +1097,7 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size,
|
|||
else if (dev->driver->gem_vm_ops)
|
||||
vma->vm_ops = dev->driver->gem_vm_ops;
|
||||
else {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1191,13 +1163,13 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
return -EINVAL;
|
||||
|
||||
if (!drm_vma_node_is_allowed(node, priv)) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
if (node->readonly) {
|
||||
if (vma->vm_flags & VM_WRITE) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1207,7 +1179,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,
|
||||
vma);
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1227,8 +1199,6 @@ void drm_gem_print_info(struct drm_printer *p, unsigned int indent,
|
|||
|
||||
if (obj->funcs && obj->funcs->print_info)
|
||||
obj->funcs->print_info(p, indent, obj);
|
||||
else if (obj->dev->driver->gem_print_info)
|
||||
obj->dev->driver->gem_print_info(p, indent, obj);
|
||||
}
|
||||
|
||||
int drm_gem_pin(struct drm_gem_object *obj)
|
||||
|
|
|
@ -114,7 +114,7 @@ struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
|||
return cma_obj;
|
||||
|
||||
error:
|
||||
drm_gem_object_put_unlocked(&cma_obj->base);
|
||||
drm_gem_object_put(&cma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
|
||||
|
@ -156,7 +156,7 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
|
|||
*/
|
||||
ret = drm_gem_handle_create(file_priv, gem_obj, handle);
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_put_unlocked(gem_obj);
|
||||
drm_gem_object_put(gem_obj);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -380,13 +380,13 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
|
|||
return -EINVAL;
|
||||
|
||||
if (!drm_vma_node_is_allowed(node, priv)) {
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL;
|
||||
}
|
||||
|
@ -572,7 +572,7 @@ void drm_gem_cma_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vunmap);
|
||||
|
||||
static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = {
|
||||
static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
|
||||
.free = drm_gem_cma_free_object,
|
||||
.print_info = drm_gem_cma_print_info,
|
||||
.get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
|
@ -581,7 +581,7 @@ static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = {
|
|||
};
|
||||
|
||||
/**
|
||||
* drm_cma_gem_create_object_default_funcs - Create a CMA GEM object with a
|
||||
* drm_gem_cma_create_object_default_funcs - Create a CMA GEM object with a
|
||||
* default function table
|
||||
* @dev: DRM device
|
||||
* @size: Size of the object to allocate
|
||||
|
@ -593,7 +593,7 @@ static const struct drm_gem_object_funcs drm_cma_gem_default_funcs = {
|
|||
* A pointer to a allocated GEM object or an error pointer on failure.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size)
|
||||
drm_gem_cma_create_object_default_funcs(struct drm_device *dev, size_t size)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
|
||||
|
@ -601,11 +601,11 @@ drm_cma_gem_create_object_default_funcs(struct drm_device *dev, size_t size)
|
|||
if (!cma_obj)
|
||||
return NULL;
|
||||
|
||||
cma_obj->base.funcs = &drm_cma_gem_default_funcs;
|
||||
cma_obj->base.funcs = &drm_gem_cma_default_funcs;
|
||||
|
||||
return &cma_obj->base;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_cma_gem_create_object_default_funcs);
|
||||
EXPORT_SYMBOL(drm_gem_cma_create_object_default_funcs);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
|
||||
|
@ -620,7 +620,7 @@ EXPORT_SYMBOL(drm_cma_gem_create_object_default_funcs);
|
|||
* address set. This address is released when the object is freed.
|
||||
*
|
||||
* This function can be used as the &drm_driver.gem_prime_import_sg_table
|
||||
* callback. The DRM_GEM_CMA_VMAP_DRIVER_OPS() macro provides a shortcut to set
|
||||
* callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set
|
||||
* the necessary DRM driver operations.
|
||||
*
|
||||
* Returns:
|
||||
|
|
|
@ -95,7 +95,7 @@ void drm_gem_fb_destroy(struct drm_framebuffer *fb)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
drm_gem_object_put_unlocked(fb->obj[i]);
|
||||
drm_gem_object_put(fb->obj[i]);
|
||||
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
|
@ -175,7 +175,7 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
|||
+ mode_cmd->offsets[i];
|
||||
|
||||
if (objs[i]->size < min_size) {
|
||||
drm_gem_object_put_unlocked(objs[i]);
|
||||
drm_gem_object_put(objs[i]);
|
||||
ret = -EINVAL;
|
||||
goto err_gem_object_put;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev,
|
|||
|
||||
err_gem_object_put:
|
||||
for (i--; i >= 0; i--)
|
||||
drm_gem_object_put_unlocked(objs[i]);
|
||||
drm_gem_object_put(objs[i]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -35,22 +35,12 @@ static const struct drm_gem_object_funcs drm_gem_shmem_funcs = {
|
|||
.mmap = drm_gem_shmem_mmap,
|
||||
};
|
||||
|
||||
/**
|
||||
* drm_gem_shmem_create - Allocate an object with the given size
|
||||
* @dev: DRM device
|
||||
* @size: Size of the object to allocate
|
||||
*
|
||||
* This function creates a shmem GEM object.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
|
||||
* error code on failure.
|
||||
*/
|
||||
struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
|
||||
static struct drm_gem_shmem_object *
|
||||
__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
|
||||
{
|
||||
struct drm_gem_shmem_object *shmem;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
size = PAGE_ALIGN(size);
|
||||
|
||||
|
@ -64,7 +54,10 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t
|
|||
if (!obj->funcs)
|
||||
obj->funcs = &drm_gem_shmem_funcs;
|
||||
|
||||
ret = drm_gem_object_init(dev, obj, size);
|
||||
if (private)
|
||||
drm_gem_private_object_init(dev, obj, size);
|
||||
else
|
||||
ret = drm_gem_object_init(dev, obj, size);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
|
@ -77,15 +70,17 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t
|
|||
mutex_init(&shmem->vmap_lock);
|
||||
INIT_LIST_HEAD(&shmem->madv_list);
|
||||
|
||||
/*
|
||||
* Our buffers are kept pinned, so allocating them
|
||||
* from the MOVABLE zone is a really bad idea, and
|
||||
* conflicts with CMA. See comments above new_inode()
|
||||
* why this is required _and_ expected if you're
|
||||
* going to pin these pages.
|
||||
*/
|
||||
mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER |
|
||||
__GFP_RETRY_MAYFAIL | __GFP_NOWARN);
|
||||
if (!private) {
|
||||
/*
|
||||
* Our buffers are kept pinned, so allocating them
|
||||
* from the MOVABLE zone is a really bad idea, and
|
||||
* conflicts with CMA. See comments above new_inode()
|
||||
* why this is required _and_ expected if you're
|
||||
* going to pin these pages.
|
||||
*/
|
||||
mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER |
|
||||
__GFP_RETRY_MAYFAIL | __GFP_NOWARN);
|
||||
}
|
||||
|
||||
return shmem;
|
||||
|
||||
|
@ -96,6 +91,21 @@ err_free:
|
|||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
/**
|
||||
* drm_gem_shmem_create - Allocate an object with the given size
|
||||
* @dev: DRM device
|
||||
* @size: Size of the object to allocate
|
||||
*
|
||||
* This function creates a shmem GEM object.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
|
||||
* error code on failure.
|
||||
*/
|
||||
struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
|
||||
{
|
||||
return __drm_gem_shmem_create(dev, size, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
|
||||
|
||||
/**
|
||||
|
@ -103,7 +113,8 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
|
|||
* @obj: GEM object to free
|
||||
*
|
||||
* This function cleans up the GEM object state and frees the memory used to
|
||||
* store the object itself.
|
||||
* store the object itself. It should be used to implement
|
||||
* &drm_gem_object_funcs.free.
|
||||
*/
|
||||
void drm_gem_shmem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
|
@ -112,9 +123,7 @@ void drm_gem_shmem_free_object(struct drm_gem_object *obj)
|
|||
WARN_ON(shmem->vmap_use_count);
|
||||
|
||||
if (obj->import_attach) {
|
||||
shmem->pages_use_count--;
|
||||
drm_prime_gem_destroy(obj, shmem->sgt);
|
||||
kvfree(shmem->pages);
|
||||
} else {
|
||||
if (shmem->sgt) {
|
||||
dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl,
|
||||
|
@ -169,6 +178,8 @@ int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
|
|||
{
|
||||
int ret;
|
||||
|
||||
WARN_ON(shmem->base.import_attach);
|
||||
|
||||
ret = mutex_lock_interruptible(&shmem->pages_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -214,7 +225,8 @@ EXPORT_SYMBOL(drm_gem_shmem_put_pages);
|
|||
* @obj: GEM object
|
||||
*
|
||||
* This function makes sure the backing pages are pinned in memory while the
|
||||
* buffer is exported.
|
||||
* buffer is exported. It should only be used to implement
|
||||
* &drm_gem_object_funcs.pin.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
|
@ -223,6 +235,8 @@ int drm_gem_shmem_pin(struct drm_gem_object *obj)
|
|||
{
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
WARN_ON(shmem->base.import_attach);
|
||||
|
||||
return drm_gem_shmem_get_pages(shmem);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_pin);
|
||||
|
@ -232,12 +246,14 @@ EXPORT_SYMBOL(drm_gem_shmem_pin);
|
|||
* @obj: GEM object
|
||||
*
|
||||
* This function removes the requirement that the backing pages are pinned in
|
||||
* memory.
|
||||
* memory. It should only be used to implement &drm_gem_object_funcs.unpin.
|
||||
*/
|
||||
void drm_gem_shmem_unpin(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
WARN_ON(shmem->base.import_attach);
|
||||
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_unpin);
|
||||
|
@ -250,15 +266,15 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
|
|||
if (shmem->vmap_use_count++ > 0)
|
||||
return shmem->vaddr;
|
||||
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
if (ret)
|
||||
goto err_zero_use;
|
||||
|
||||
if (obj->import_attach) {
|
||||
shmem->vaddr = dma_buf_vmap(obj->import_attach->dmabuf);
|
||||
} else {
|
||||
pgprot_t prot = PAGE_KERNEL;
|
||||
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
if (ret)
|
||||
goto err_zero_use;
|
||||
|
||||
if (!shmem->map_cached)
|
||||
prot = pgprot_writecombine(prot);
|
||||
shmem->vaddr = vmap(shmem->pages, obj->size >> PAGE_SHIFT,
|
||||
|
@ -274,7 +290,8 @@ static void *drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem)
|
|||
return shmem->vaddr;
|
||||
|
||||
err_put_pages:
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
if (!obj->import_attach)
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
err_zero_use:
|
||||
shmem->vmap_use_count = 0;
|
||||
|
||||
|
@ -285,8 +302,14 @@ err_zero_use:
|
|||
* drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
*
|
||||
* This function makes sure that a virtual address exists for the buffer backing
|
||||
* the shmem GEM object.
|
||||
* This function makes sure that a contiguous kernel virtual address mapping
|
||||
* exists for the buffer backing the shmem GEM object.
|
||||
*
|
||||
* This function can be used to implement &drm_gem_object_funcs.vmap. But it can
|
||||
* also be called by drivers directly, in which case it will hide the
|
||||
* differences between dma-buf imported and natively allocated objects.
|
||||
*
|
||||
* Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap().
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
|
@ -330,7 +353,13 @@ static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem)
|
|||
* drm_gem_shmem_vunmap - Unmap a virtual mapping fo a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
*
|
||||
* This function removes the virtual address when use count drops to zero.
|
||||
* This function cleans up a kernel virtual address mapping acquired by
|
||||
* drm_gem_shmem_vmap(). The mapping is only removed when the use count drops to
|
||||
* zero.
|
||||
*
|
||||
* This function can be used to implement &drm_gem_object_funcs.vmap. But it can
|
||||
* also be called by drivers directly, in which case it will hide the
|
||||
* differences between dma-buf imported and natively allocated objects.
|
||||
*/
|
||||
void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr)
|
||||
{
|
||||
|
@ -360,7 +389,7 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
|
|||
*/
|
||||
ret = drm_gem_handle_create(file_priv, &shmem->base, handle);
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_put_unlocked(&shmem->base);
|
||||
drm_gem_object_put(&shmem->base);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -433,6 +462,33 @@ bool drm_gem_shmem_purge(struct drm_gem_object *obj)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_purge);
|
||||
|
||||
/**
|
||||
* drm_gem_shmem_create_object_cached - Create a shmem buffer object with
|
||||
* cached mappings
|
||||
* @dev: DRM device
|
||||
* @size: Size of the object to allocate
|
||||
*
|
||||
* By default, shmem buffer objects use writecombine mappings. This
|
||||
* function implements struct drm_driver.gem_create_object for shmem
|
||||
* buffer objects with cached mappings.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_shmem_object * on success or NULL negative on failure.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
drm_gem_shmem_create_object_cached(struct drm_device *dev, size_t size)
|
||||
{
|
||||
struct drm_gem_shmem_object *shmem;
|
||||
|
||||
shmem = kzalloc(sizeof(*shmem), GFP_KERNEL);
|
||||
if (!shmem)
|
||||
return NULL;
|
||||
shmem->map_cached = true;
|
||||
|
||||
return &shmem->base;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_create_object_cached);
|
||||
|
||||
/**
|
||||
* drm_gem_shmem_dumb_create - Create a dumb shmem buffer object
|
||||
* @file: DRM file structure to create the dumb buffer for
|
||||
|
@ -495,6 +551,8 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
|
|||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
int ret;
|
||||
|
||||
WARN_ON(shmem->base.import_attach);
|
||||
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
WARN_ON_ONCE(ret != 0);
|
||||
|
||||
|
@ -536,6 +594,9 @@ int drm_gem_shmem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
|
|||
/* Remove the fake offset */
|
||||
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
|
||||
|
||||
if (obj->import_attach)
|
||||
return dma_buf_mmap(obj->dma_buf, vma, 0);
|
||||
|
||||
shmem = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
|
@ -559,6 +620,8 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_mmap);
|
|||
* @p: DRM printer
|
||||
* @indent: Tab indentation level
|
||||
* @obj: GEM object
|
||||
*
|
||||
* This implements the &drm_gem_object_funcs.info callback.
|
||||
*/
|
||||
void drm_gem_shmem_print_info(struct drm_printer *p, unsigned int indent,
|
||||
const struct drm_gem_object *obj)
|
||||
|
@ -577,7 +640,12 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info);
|
|||
* @obj: GEM object
|
||||
*
|
||||
* This function exports a scatter/gather table suitable for PRIME usage by
|
||||
* calling the standard DMA mapping API.
|
||||
* calling the standard DMA mapping API. Drivers should not call this function
|
||||
* directly, instead it should only be used as an implementation for
|
||||
* &drm_gem_object_funcs.get_sg_table.
|
||||
*
|
||||
* Drivers who need to acquire an scatter/gather table for objects need to call
|
||||
* drm_gem_shmem_get_pages_sgt() instead.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the scatter/gather table of pinned pages or NULL on failure.
|
||||
|
@ -586,6 +654,8 @@ struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_object *obj)
|
|||
{
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
WARN_ON(shmem->base.import_attach);
|
||||
|
||||
return drm_prime_pages_to_sg(shmem->pages, obj->size >> PAGE_SHIFT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table);
|
||||
|
@ -599,6 +669,10 @@ EXPORT_SYMBOL_GPL(drm_gem_shmem_get_sg_table);
|
|||
* the sg table doesn't exist, the pages are pinned, dma-mapped, and a sg
|
||||
* table created.
|
||||
*
|
||||
* This is the main function for drivers to get at backing storage, and it hides
|
||||
* and difference between dma-buf imported and natively allocated objects.
|
||||
* drm_gem_shmem_get_sg_table() should not be directly called by drivers.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the scatter/gather table of pinned pages or errno on failure.
|
||||
*/
|
||||
|
@ -656,36 +730,16 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
|
|||
struct sg_table *sgt)
|
||||
{
|
||||
size_t size = PAGE_ALIGN(attach->dmabuf->size);
|
||||
size_t npages = size >> PAGE_SHIFT;
|
||||
struct drm_gem_shmem_object *shmem;
|
||||
int ret;
|
||||
|
||||
shmem = drm_gem_shmem_create(dev, size);
|
||||
shmem = __drm_gem_shmem_create(dev, size, true);
|
||||
if (IS_ERR(shmem))
|
||||
return ERR_CAST(shmem);
|
||||
|
||||
shmem->pages = kvmalloc_array(npages, sizeof(struct page *), GFP_KERNEL);
|
||||
if (!shmem->pages) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_gem;
|
||||
}
|
||||
|
||||
ret = drm_prime_sg_to_page_addr_arrays(sgt, shmem->pages, NULL, npages);
|
||||
if (ret < 0)
|
||||
goto err_free_array;
|
||||
|
||||
shmem->sgt = sgt;
|
||||
shmem->pages_use_count = 1; /* Permanently pinned from our point of view */
|
||||
|
||||
DRM_DEBUG_PRIME("size = %zu\n", size);
|
||||
|
||||
return &shmem->base;
|
||||
|
||||
err_free_array:
|
||||
kvfree(shmem->pages);
|
||||
err_free_gem:
|
||||
drm_gem_object_put_unlocked(&shmem->base);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_sg_table);
|
||||
|
|
|
@ -74,7 +74,7 @@ int drm_gem_ttm_mmap(struct drm_gem_object *gem,
|
|||
* ttm has its own object refcounting, so drop gem reference
|
||||
* to avoid double accounting counting.
|
||||
*/
|
||||
drm_gem_object_put_unlocked(gem);
|
||||
drm_gem_object_put(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -618,9 +618,9 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
|
|||
|
||||
ret = drm_gem_handle_create(file, &gbo->bo.base, &handle);
|
||||
if (ret)
|
||||
goto err_drm_gem_object_put_unlocked;
|
||||
goto err_drm_gem_object_put;
|
||||
|
||||
drm_gem_object_put_unlocked(&gbo->bo.base);
|
||||
drm_gem_object_put(&gbo->bo.base);
|
||||
|
||||
args->pitch = pitch;
|
||||
args->size = size;
|
||||
|
@ -628,8 +628,8 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file,
|
|||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_object_put_unlocked:
|
||||
drm_gem_object_put_unlocked(&gbo->bo.base);
|
||||
err_drm_gem_object_put:
|
||||
drm_gem_object_put(&gbo->bo.base);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
|
||||
|
@ -737,7 +737,7 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
|
|||
gbo = drm_gem_vram_of_gem(gem);
|
||||
*offset = drm_gem_vram_mmap_offset(gbo);
|
||||
|
||||
drm_gem_object_put_unlocked(gem);
|
||||
drm_gem_object_put(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -985,8 +985,8 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
|||
if (!fn)
|
||||
return drm_ioctl(filp, cmd, arg);
|
||||
|
||||
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
task_pid_nr(current),
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated,
|
||||
drm_compat_ioctls[nr].name);
|
||||
|
|
|
@ -852,8 +852,8 @@ long drm_ioctl(struct file *filp,
|
|||
out_size = 0;
|
||||
ksize = max(max(in_size, out_size), drv_size);
|
||||
|
||||
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
task_pid_nr(current),
|
||||
DRM_DEBUG("comm=\"%s\" pid=%d, dev=0x%lx, auth=%d, %s\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, ioctl->name);
|
||||
|
||||
|
@ -890,15 +890,16 @@ long drm_ioctl(struct file *filp,
|
|||
|
||||
err_i1:
|
||||
if (!ioctl)
|
||||
DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
|
||||
task_pid_nr(current),
|
||||
DRM_DEBUG("invalid ioctl: comm=\"%s\", pid=%d, dev=0x%lx, auth=%d, cmd=0x%02x, nr=0x%02x\n",
|
||||
current->comm, task_pid_nr(current),
|
||||
(long)old_encode_dev(file_priv->minor->kdev->devt),
|
||||
file_priv->authenticated, cmd, nr);
|
||||
|
||||
if (kdata != stack_kdata)
|
||||
kfree(kdata);
|
||||
if (retcode)
|
||||
DRM_DEBUG("pid=%d, ret = %d\n", task_pid_nr(current), retcode);
|
||||
DRM_DEBUG("comm=\"%s\", pid=%d, ret=%d\n", current->comm,
|
||||
task_pid_nr(current), retcode);
|
||||
return retcode;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_ioctl);
|
||||
|
|
|
@ -181,7 +181,7 @@ int drm_irq_uninstall(struct drm_device *dev)
|
|||
* vblank/irq handling. KMS drivers must ensure that vblanks are all
|
||||
* disabled when uninstalling the irq handler.
|
||||
*/
|
||||
if (dev->num_crtcs) {
|
||||
if (drm_dev_has_vblank(dev)) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
for (i = 0; i < dev->num_crtcs; i++) {
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[i];
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: managed resources
|
||||
*
|
||||
|
|
|
@ -217,7 +217,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
|
|||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_RGB565:
|
||||
if (swap)
|
||||
drm_fb_swab16(dst, src, fb, clip);
|
||||
drm_fb_swab(dst, src, fb, clip, !import_attach);
|
||||
else
|
||||
drm_fb_memcpy(dst, src, fb, clip);
|
||||
break;
|
||||
|
|
|
@ -406,8 +406,7 @@ next_hole_high_addr(struct drm_mm_node *entry, u64 size)
|
|||
parent_rb_node = rb_parent(rb_node);
|
||||
left_node = rb_entry(left_rb_node,
|
||||
struct drm_mm_node, rb_hole_addr);
|
||||
if ((left_node->subtree_max_hole < size ||
|
||||
entry->size == entry->subtree_max_hole) &&
|
||||
if (left_node->subtree_max_hole < size &&
|
||||
parent_rb_node && parent_rb_node->rb_left != rb_node)
|
||||
return rb_hole_addr_to_node(parent_rb_node);
|
||||
}
|
||||
|
@ -446,8 +445,7 @@ next_hole_low_addr(struct drm_mm_node *entry, u64 size)
|
|||
parent_rb_node = rb_parent(rb_node);
|
||||
right_node = rb_entry(right_rb_node,
|
||||
struct drm_mm_node, rb_hole_addr);
|
||||
if ((right_node->subtree_max_hole < size ||
|
||||
entry->size == entry->subtree_max_hole) &&
|
||||
if (right_node->subtree_max_hole < size &&
|
||||
parent_rb_node && parent_rb_node->rb_right != rb_node)
|
||||
return rb_hole_addr_to_node(parent_rb_node);
|
||||
}
|
||||
|
|
|
@ -757,26 +757,22 @@ EXPORT_SYMBOL(drm_mode_set_name);
|
|||
*/
|
||||
int drm_mode_vrefresh(const struct drm_display_mode *mode)
|
||||
{
|
||||
int refresh = 0;
|
||||
unsigned int num, den;
|
||||
|
||||
if (mode->vrefresh > 0)
|
||||
refresh = mode->vrefresh;
|
||||
else if (mode->htotal > 0 && mode->vtotal > 0) {
|
||||
unsigned int num, den;
|
||||
if (mode->htotal == 0 || mode->vtotal == 0)
|
||||
return 0;
|
||||
|
||||
num = mode->clock * 1000;
|
||||
den = mode->htotal * mode->vtotal;
|
||||
num = mode->clock * 1000;
|
||||
den = mode->htotal * mode->vtotal;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
num *= 2;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
den *= 2;
|
||||
if (mode->vscan > 1)
|
||||
den *= mode->vscan;
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
num *= 2;
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
den *= 2;
|
||||
if (mode->vscan > 1)
|
||||
den *= mode->vscan;
|
||||
|
||||
refresh = DIV_ROUND_CLOSEST(num, den);
|
||||
}
|
||||
return refresh;
|
||||
return DIV_ROUND_CLOSEST(num, den);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_vrefresh);
|
||||
|
||||
|
@ -1308,7 +1304,7 @@ static int drm_mode_compare(void *priv, struct list_head *lh_a, struct list_head
|
|||
if (diff)
|
||||
return diff;
|
||||
|
||||
diff = b->vrefresh - a->vrefresh;
|
||||
diff = drm_mode_vrefresh(b) - drm_mode_vrefresh(a);
|
||||
if (diff)
|
||||
return diff;
|
||||
|
||||
|
@ -1903,13 +1899,6 @@ EXPORT_SYMBOL(drm_mode_create_from_cmdline_mode);
|
|||
void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
|
||||
const struct drm_display_mode *in)
|
||||
{
|
||||
WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
|
||||
in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
|
||||
in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
|
||||
in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
|
||||
in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX,
|
||||
"timing values too large for mode info\n");
|
||||
|
||||
out->clock = in->clock;
|
||||
out->hdisplay = in->hdisplay;
|
||||
out->hsync_start = in->hsync_start;
|
||||
|
@ -1921,7 +1910,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
|
|||
out->vsync_end = in->vsync_end;
|
||||
out->vtotal = in->vtotal;
|
||||
out->vscan = in->vscan;
|
||||
out->vrefresh = in->vrefresh;
|
||||
out->vrefresh = drm_mode_vrefresh(in);
|
||||
out->flags = in->flags;
|
||||
out->type = in->type;
|
||||
|
||||
|
@ -1981,7 +1970,6 @@ int drm_mode_convert_umode(struct drm_device *dev,
|
|||
out->vsync_end = in->vsync_end;
|
||||
out->vtotal = in->vtotal;
|
||||
out->vscan = in->vscan;
|
||||
out->vrefresh = in->vrefresh;
|
||||
out->flags = in->flags;
|
||||
/*
|
||||
* Old xf86-video-vmware (possibly others too) used to
|
||||
|
|
|
@ -270,7 +270,7 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf)
|
|||
struct drm_device *dev = obj->dev;
|
||||
|
||||
/* drop the reference on the export fd holds */
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
drm_dev_put(dev);
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ int drm_gem_prime_fd_to_handle(struct drm_device *dev,
|
|||
|
||||
/* _handle_create_tail unconditionally unlocks dev->object_name_lock. */
|
||||
ret = drm_gem_handle_create_tail(file_priv, obj, handle);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
if (ret)
|
||||
goto out_put;
|
||||
|
||||
|
@ -500,7 +500,7 @@ out_have_handle:
|
|||
fail_put_dmabuf:
|
||||
dma_buf_put(dmabuf);
|
||||
out:
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
out_unlock:
|
||||
mutex_unlock(&file_priv->prime.lock);
|
||||
|
||||
|
|
|
@ -159,6 +159,8 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* Mark the matching mode as being preferred by the user */
|
||||
mode->type |= DRM_MODE_TYPE_USERDEF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -532,9 +534,6 @@ prune:
|
|||
if (list_empty(&connector->modes))
|
||||
return 0;
|
||||
|
||||
list_for_each_entry(mode, &connector->modes, head)
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
drm_mode_sort(&connector->modes);
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
|
||||
|
|
|
@ -194,7 +194,7 @@ static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
|
|||
*/
|
||||
static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
|
||||
{
|
||||
WARN_ON_ONCE(drm_max_vblank_count(dev, pipe) != 0);
|
||||
drm_WARN_ON_ONCE(dev, drm_max_vblank_count(dev, pipe) != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
if (drm_WARN_ON(dev, !crtc))
|
||||
return 0;
|
||||
|
||||
if (crtc->funcs->get_vblank_counter)
|
||||
|
@ -311,15 +311,15 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
|
|||
* frame/field duration.
|
||||
*/
|
||||
|
||||
DRM_DEBUG_VBL("crtc %u: Calculating number of vblanks."
|
||||
" diff_ns = %lld, framedur_ns = %d)\n",
|
||||
pipe, (long long) diff_ns, framedur_ns);
|
||||
drm_dbg_vbl(dev, "crtc %u: Calculating number of vblanks."
|
||||
" diff_ns = %lld, framedur_ns = %d)\n",
|
||||
pipe, (long long)diff_ns, framedur_ns);
|
||||
|
||||
diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
|
||||
|
||||
if (diff == 0 && in_vblank_irq)
|
||||
DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored\n",
|
||||
pipe);
|
||||
drm_dbg_vbl(dev, "crtc %u: Redundant vblirq ignored\n",
|
||||
pipe);
|
||||
} else {
|
||||
/* some kind of default for drivers w/o accurate vbl timestamping */
|
||||
diff = in_vblank_irq ? 1 : 0;
|
||||
|
@ -335,18 +335,19 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
|
|||
* random large forward jumps of the software vblank counter.
|
||||
*/
|
||||
if (diff > 1 && (vblank->inmodeset & 0x2)) {
|
||||
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u"
|
||||
" due to pre-modeset.\n", pipe, diff);
|
||||
drm_dbg_vbl(dev,
|
||||
"clamping vblank bump to 1 on crtc %u: diffr=%u"
|
||||
" due to pre-modeset.\n", pipe, diff);
|
||||
diff = 1;
|
||||
}
|
||||
|
||||
DRM_DEBUG_VBL("updating vblank count on crtc %u:"
|
||||
" current=%llu, diff=%u, hw=%u hw_last=%u\n",
|
||||
pipe, (unsigned long long)atomic64_read(&vblank->count),
|
||||
diff, cur_vblank, vblank->last);
|
||||
drm_dbg_vbl(dev, "updating vblank count on crtc %u:"
|
||||
" current=%llu, diff=%u, hw=%u hw_last=%u\n",
|
||||
pipe, (unsigned long long)atomic64_read(&vblank->count),
|
||||
diff, cur_vblank, vblank->last);
|
||||
|
||||
if (diff == 0) {
|
||||
WARN_ON_ONCE(cur_vblank != vblank->last);
|
||||
drm_WARN_ON_ONCE(dev, cur_vblank != vblank->last);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -367,7 +368,7 @@ static u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
|
|||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
u64 count;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return 0;
|
||||
|
||||
count = atomic64_read(&vblank->count);
|
||||
|
@ -402,9 +403,9 @@ u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc)
|
|||
u64 vblank;
|
||||
unsigned long flags;
|
||||
|
||||
WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) &&
|
||||
!crtc->funcs->get_vblank_timestamp,
|
||||
"This function requires support for accurate vblank timestamps.");
|
||||
drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) &&
|
||||
!crtc->funcs->get_vblank_timestamp,
|
||||
"This function requires support for accurate vblank timestamps.");
|
||||
|
||||
spin_lock_irqsave(&dev->vblank_time_lock, flags);
|
||||
|
||||
|
@ -422,7 +423,7 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
if (drm_WARN_ON(dev, !crtc))
|
||||
return;
|
||||
|
||||
if (crtc->funcs->disable_vblank)
|
||||
|
@ -483,7 +484,7 @@ static void vblank_disable_fn(struct timer_list *t)
|
|||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
|
||||
DRM_DEBUG("disabling vblank on crtc %u\n", pipe);
|
||||
drm_dbg_core(dev, "disabling vblank on crtc %u\n", pipe);
|
||||
drm_vblank_disable_and_save(dev, pipe);
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
@ -496,8 +497,8 @@ static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
|
|||
for (pipe = 0; pipe < dev->num_crtcs; pipe++) {
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
WARN_ON(READ_ONCE(vblank->enabled) &&
|
||||
drm_core_check_feature(dev, DRIVER_MODESET));
|
||||
drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
|
||||
drm_core_check_feature(dev, DRIVER_MODESET));
|
||||
|
||||
del_timer_sync(&vblank->disable_timer);
|
||||
}
|
||||
|
@ -543,8 +544,6 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
|
|||
seqlock_init(&vblank->seqlock);
|
||||
}
|
||||
|
||||
DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_init);
|
||||
|
@ -606,10 +605,10 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
|
|||
int linedur_ns = 0, framedur_ns = 0;
|
||||
int dotclock = mode->crtc_clock;
|
||||
|
||||
if (!dev->num_crtcs)
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
return;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
/* Valid dotclock? */
|
||||
|
@ -629,19 +628,21 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
|
|||
*/
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
framedur_ns /= 2;
|
||||
} else
|
||||
DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n",
|
||||
crtc->base.id);
|
||||
} else {
|
||||
drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
|
||||
crtc->base.id);
|
||||
}
|
||||
|
||||
vblank->linedur_ns = linedur_ns;
|
||||
vblank->framedur_ns = framedur_ns;
|
||||
vblank->hwmode = *mode;
|
||||
|
||||
DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
|
||||
crtc->base.id, mode->crtc_htotal,
|
||||
mode->crtc_vtotal, mode->crtc_vdisplay);
|
||||
DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n",
|
||||
crtc->base.id, dotclock, framedur_ns, linedur_ns);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
|
||||
crtc->base.id, mode->crtc_htotal,
|
||||
mode->crtc_vtotal, mode->crtc_vdisplay);
|
||||
drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
|
||||
crtc->base.id, dotclock, framedur_ns, linedur_ns);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_calc_timestamping_constants);
|
||||
|
||||
|
@ -694,13 +695,13 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
|
|||
int delta_ns, duration_ns;
|
||||
|
||||
if (pipe >= dev->num_crtcs) {
|
||||
DRM_ERROR("Invalid crtc %u\n", pipe);
|
||||
drm_err(dev, "Invalid crtc %u\n", pipe);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Scanout position query not supported? Should not happen. */
|
||||
if (!get_scanout_position) {
|
||||
DRM_ERROR("Called from CRTC w/o get_scanout_position()!?\n");
|
||||
drm_err(dev, "Called from CRTC w/o get_scanout_position()!?\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -713,8 +714,9 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
|
|||
* Happens during initial modesetting of a crtc.
|
||||
*/
|
||||
if (mode->crtc_clock == 0) {
|
||||
DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
|
||||
WARN_ON_ONCE(drm_drv_uses_atomic_modeset(dev));
|
||||
drm_dbg_core(dev, "crtc %u: Noop due to uninitialized mode.\n",
|
||||
pipe);
|
||||
drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -737,8 +739,9 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
|
|||
|
||||
/* Return as no-op if scanout query unsupported or failed. */
|
||||
if (!vbl_status) {
|
||||
DRM_DEBUG("crtc %u : scanoutpos query failed.\n",
|
||||
pipe);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %u : scanoutpos query failed.\n",
|
||||
pipe);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -752,8 +755,9 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
|
|||
|
||||
/* Noisy system timing? */
|
||||
if (i == DRM_TIMESTAMP_MAXRETRIES) {
|
||||
DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
|
||||
pipe, duration_ns/1000, *max_error/1000, i);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
|
||||
pipe, duration_ns / 1000, *max_error / 1000, i);
|
||||
}
|
||||
|
||||
/* Return upper bound of timestamp precision error. */
|
||||
|
@ -777,11 +781,12 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
|
|||
ts_etime = ktime_to_timespec64(etime);
|
||||
ts_vblank_time = ktime_to_timespec64(*vblank_time);
|
||||
|
||||
DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
|
||||
pipe, hpos, vpos,
|
||||
(u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000,
|
||||
(u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000,
|
||||
duration_ns / 1000, i);
|
||||
drm_dbg_vbl(dev,
|
||||
"crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
|
||||
pipe, hpos, vpos,
|
||||
(u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000,
|
||||
(u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000,
|
||||
duration_ns / 1000, i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -925,7 +930,7 @@ static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
|
|||
u64 vblank_count;
|
||||
unsigned int seq;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs)) {
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) {
|
||||
*vblanktime = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1066,7 +1071,7 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
|||
unsigned int pipe = drm_crtc_index(crtc);
|
||||
ktime_t now;
|
||||
|
||||
if (dev->num_crtcs > 0) {
|
||||
if (drm_dev_has_vblank(dev)) {
|
||||
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
} else {
|
||||
seq = 0;
|
||||
|
@ -1083,7 +1088,7 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (WARN_ON(!crtc))
|
||||
if (drm_WARN_ON(dev, !crtc))
|
||||
return 0;
|
||||
|
||||
if (crtc->funcs->enable_vblank)
|
||||
|
@ -1113,7 +1118,8 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
|
|||
* prevent double-accounting of same vblank interval.
|
||||
*/
|
||||
ret = __enable_vblank(dev, pipe);
|
||||
DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
|
||||
drm_dbg_core(dev, "enabling vblank on crtc %u, ret: %d\n",
|
||||
pipe, ret);
|
||||
if (ret) {
|
||||
atomic_dec(&vblank->refcount);
|
||||
} else {
|
||||
|
@ -1138,10 +1144,10 @@ static int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
|
|||
unsigned long irqflags;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev->num_crtcs)
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
|
@ -1179,10 +1185,10 @@ static void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
|
|||
{
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
if (WARN_ON(atomic_read(&vblank->refcount) == 0))
|
||||
if (drm_WARN_ON(dev, atomic_read(&vblank->refcount) == 0))
|
||||
return;
|
||||
|
||||
/* Last user schedules interrupt disable */
|
||||
|
@ -1227,11 +1233,12 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
int ret;
|
||||
u64 last;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (WARN(ret, "vblank not available on crtc %i, ret=%i\n", pipe, ret))
|
||||
if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",
|
||||
pipe, ret))
|
||||
return;
|
||||
|
||||
last = drm_vblank_count(dev, pipe);
|
||||
|
@ -1240,7 +1247,7 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
last != drm_vblank_count(dev, pipe),
|
||||
msecs_to_jiffies(100));
|
||||
|
||||
WARN(ret == 0, "vblank wait timed out on crtc %i\n", pipe);
|
||||
drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);
|
||||
|
||||
drm_vblank_put(dev, pipe);
|
||||
}
|
||||
|
@ -1282,14 +1289,14 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
|
|||
unsigned long irqflags;
|
||||
u64 seq;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||
|
||||
spin_lock(&dev->vbl_lock);
|
||||
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
|
||||
pipe, vblank->enabled, vblank->inmodeset);
|
||||
drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
|
||||
pipe, vblank->enabled, vblank->inmodeset);
|
||||
|
||||
/* Avoid redundant vblank disables without previous
|
||||
* drm_crtc_vblank_on(). */
|
||||
|
@ -1314,9 +1321,9 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
|
|||
list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
|
||||
if (e->pipe != pipe)
|
||||
continue;
|
||||
DRM_DEBUG("Sending premature vblank event on disable: "
|
||||
"wanted %llu, current %llu\n",
|
||||
e->sequence, seq);
|
||||
drm_dbg_core(dev, "Sending premature vblank event on disable: "
|
||||
"wanted %llu, current %llu\n",
|
||||
e->sequence, seq);
|
||||
list_del(&e->base.link);
|
||||
drm_vblank_put(dev, pipe);
|
||||
send_vblank_event(dev, e, seq, now);
|
||||
|
@ -1359,7 +1366,7 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)
|
|||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
WARN_ON(!list_empty(&dev->vblank_event_list));
|
||||
drm_WARN_ON(dev, !list_empty(&dev->vblank_event_list));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_vblank_reset);
|
||||
|
||||
|
@ -1387,8 +1394,8 @@ void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
|
|||
unsigned int pipe = drm_crtc_index(crtc);
|
||||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
WARN_ON(dev->max_vblank_count);
|
||||
WARN_ON(!READ_ONCE(vblank->inmodeset));
|
||||
drm_WARN_ON(dev, dev->max_vblank_count);
|
||||
drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
|
||||
|
||||
vblank->max_vblank_count = max_vblank_count;
|
||||
}
|
||||
|
@ -1411,12 +1418,12 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc)
|
|||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
unsigned long irqflags;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",
|
||||
pipe, vblank->enabled, vblank->inmodeset);
|
||||
drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
|
||||
pipe, vblank->enabled, vblank->inmodeset);
|
||||
|
||||
/* Drop our private "prevent drm_vblank_get" refcount */
|
||||
if (vblank->inmodeset) {
|
||||
|
@ -1431,7 +1438,7 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc)
|
|||
* user wishes vblank interrupts to be enabled all the time.
|
||||
*/
|
||||
if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
|
||||
WARN_ON(drm_vblank_enable(dev, pipe));
|
||||
drm_WARN_ON(dev, drm_vblank_enable(dev, pipe));
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_vblank_on);
|
||||
|
@ -1458,15 +1465,16 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
|
|||
u32 cur_vblank, diff = 1;
|
||||
int count = DRM_TIMESTAMP_MAXRETRIES;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
assert_spin_locked(&dev->vbl_lock);
|
||||
assert_spin_locked(&dev->vblank_time_lock);
|
||||
|
||||
vblank = &dev->vblank[pipe];
|
||||
WARN_ONCE(drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
|
||||
"Cannot compute missed vblanks without frame duration\n");
|
||||
drm_WARN_ONCE(dev,
|
||||
drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
|
||||
"Cannot compute missed vblanks without frame duration\n");
|
||||
framedur_ns = vblank->framedur_ns;
|
||||
|
||||
do {
|
||||
|
@ -1479,8 +1487,9 @@ void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
|
|||
diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
|
||||
|
||||
|
||||
DRM_DEBUG_VBL("missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
|
||||
diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
|
||||
drm_dbg_vbl(dev,
|
||||
"missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
|
||||
diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
|
||||
store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_restore);
|
||||
|
@ -1507,10 +1516,10 @@ static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
|
|||
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
|
||||
|
||||
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
||||
if (!dev->num_crtcs)
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
return;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@ -1534,10 +1543,10 @@ static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
|
|||
unsigned long irqflags;
|
||||
|
||||
/* vblank is not initialized (IRQ not installed ?), or has been freed */
|
||||
if (!dev->num_crtcs)
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
return;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return;
|
||||
|
||||
if (vblank->inmodeset) {
|
||||
|
@ -1559,7 +1568,7 @@ int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data,
|
|||
unsigned int pipe;
|
||||
|
||||
/* If drm_vblank_init() hasn't been called yet, just no-op */
|
||||
if (!dev->num_crtcs)
|
||||
if (!drm_dev_has_vblank(dev))
|
||||
return 0;
|
||||
|
||||
/* KMS drivers handle this internally */
|
||||
|
@ -1639,8 +1648,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
|||
|
||||
seq = drm_vblank_count_and_time(dev, pipe, &now);
|
||||
|
||||
DRM_DEBUG("event on vblank count %llu, current %llu, crtc %u\n",
|
||||
req_seq, seq, pipe);
|
||||
drm_dbg_core(dev, "event on vblank count %llu, current %llu, crtc %u\n",
|
||||
req_seq, seq, pipe);
|
||||
|
||||
trace_drm_vblank_event_queued(file_priv, pipe, req_seq);
|
||||
|
||||
|
@ -1731,10 +1740,11 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
|||
if (vblwait->request.type &
|
||||
~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
|
||||
_DRM_VBLANK_HIGH_CRTC_MASK)) {
|
||||
DRM_DEBUG("Unsupported type value 0x%x, supported mask 0x%x\n",
|
||||
vblwait->request.type,
|
||||
(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
|
||||
_DRM_VBLANK_HIGH_CRTC_MASK));
|
||||
drm_dbg_core(dev,
|
||||
"Unsupported type value 0x%x, supported mask 0x%x\n",
|
||||
vblwait->request.type,
|
||||
(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
|
||||
_DRM_VBLANK_HIGH_CRTC_MASK));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1777,7 +1787,9 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (ret) {
|
||||
DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %d failed to acquire vblank counter, %d\n",
|
||||
pipe, ret);
|
||||
return ret;
|
||||
}
|
||||
seq = drm_vblank_count(dev, pipe);
|
||||
|
@ -1813,8 +1825,8 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
|||
if (req_seq != seq) {
|
||||
int wait;
|
||||
|
||||
DRM_DEBUG("waiting on vblank count %llu, crtc %u\n",
|
||||
req_seq, pipe);
|
||||
drm_dbg_core(dev, "waiting on vblank count %llu, crtc %u\n",
|
||||
req_seq, pipe);
|
||||
wait = wait_event_interruptible_timeout(vblank->queue,
|
||||
vblank_passed(drm_vblank_count(dev, pipe), req_seq) ||
|
||||
!READ_ONCE(vblank->enabled),
|
||||
|
@ -1838,10 +1850,11 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
|
|||
if (ret != -EINTR) {
|
||||
drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
|
||||
|
||||
DRM_DEBUG("crtc %d returning %u to client\n",
|
||||
pipe, vblwait->reply.sequence);
|
||||
drm_dbg_core(dev, "crtc %d returning %u to client\n",
|
||||
pipe, vblwait->reply.sequence);
|
||||
} else {
|
||||
DRM_DEBUG("crtc %d vblank wait interrupted by signal\n", pipe);
|
||||
drm_dbg_core(dev, "crtc %d vblank wait interrupted by signal\n",
|
||||
pipe);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -1867,8 +1880,8 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
|
|||
if (!vblank_passed(seq, e->sequence))
|
||||
continue;
|
||||
|
||||
DRM_DEBUG("vblank event on %llu, current %llu\n",
|
||||
e->sequence, seq);
|
||||
drm_dbg_core(dev, "vblank event on %llu, current %llu\n",
|
||||
e->sequence, seq);
|
||||
|
||||
list_del(&e->base.link);
|
||||
drm_vblank_put(dev, pipe);
|
||||
|
@ -1897,10 +1910,10 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
|
|||
unsigned long irqflags;
|
||||
bool disable_irq;
|
||||
|
||||
if (WARN_ON_ONCE(!dev->num_crtcs))
|
||||
if (drm_WARN_ON_ONCE(dev, !drm_dev_has_vblank(dev)))
|
||||
return false;
|
||||
|
||||
if (WARN_ON(pipe >= dev->num_crtcs))
|
||||
if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
|
||||
return false;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, irqflags);
|
||||
|
@ -2007,7 +2020,9 @@ int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
|
|||
if (!vblank_enabled) {
|
||||
ret = drm_crtc_vblank_get(crtc);
|
||||
if (ret) {
|
||||
DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %d failed to acquire vblank counter, %d\n",
|
||||
pipe, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -2073,7 +2088,9 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
|
|||
|
||||
ret = drm_crtc_vblank_get(crtc);
|
||||
if (ret) {
|
||||
DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret);
|
||||
drm_dbg_core(dev,
|
||||
"crtc %d failed to acquire vblank counter, %d\n",
|
||||
pipe, ret);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,6 @@
|
|||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_internal.h"
|
||||
|
|
|
@ -108,7 +108,6 @@ static const struct dma_fence_ops drm_writeback_fence_ops = {
|
|||
.get_driver_name = drm_writeback_fence_get_driver_name,
|
||||
.get_timeline_name = drm_writeback_fence_get_timeline_name,
|
||||
.enable_signaling = drm_writeback_fence_enable_signaling,
|
||||
.wait = dma_fence_default_wait,
|
||||
};
|
||||
|
||||
static int create_writeback_properties(struct drm_device *dev)
|
||||
|
|
|
@ -289,7 +289,7 @@ static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
|
|||
|
||||
ret = etnaviv_gem_cpu_prep(obj, args->op, &args->timeout);
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ static int etnaviv_ioctl_gem_cpu_fini(struct drm_device *dev, void *data,
|
|||
|
||||
ret = etnaviv_gem_cpu_fini(obj);
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ static int etnaviv_ioctl_gem_info(struct drm_device *dev, void *data,
|
|||
return -ENOENT;
|
||||
|
||||
ret = etnaviv_gem_mmap_offset(obj, &args->offset);
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -413,7 +413,7 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data,
|
|||
|
||||
ret = etnaviv_gem_wait_bo(gpu, obj, timeout);
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -244,7 +244,7 @@ void etnaviv_gem_mapping_unreference(struct etnaviv_vram_mapping *mapping)
|
|||
mapping->use -= 1;
|
||||
mutex_unlock(&etnaviv_obj->lock);
|
||||
|
||||
drm_gem_object_put_unlocked(&etnaviv_obj->base);
|
||||
drm_gem_object_put(&etnaviv_obj->base);
|
||||
}
|
||||
|
||||
struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
|
||||
|
@ -633,7 +633,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
|
|||
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
fail:
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -742,6 +742,6 @@ int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
|
|||
ret = drm_gem_handle_create(file, &etnaviv_obj->base, handle);
|
||||
|
||||
/* drop reference from allocate - handle holds it now */
|
||||
drm_gem_object_put_unlocked(&etnaviv_obj->base);
|
||||
drm_gem_object_put(&etnaviv_obj->base);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
|
|||
return &etnaviv_obj->base;
|
||||
|
||||
fail:
|
||||
drm_gem_object_put_unlocked(&etnaviv_obj->base);
|
||||
drm_gem_object_put(&etnaviv_obj->base);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ static void submit_cleanup(struct kref *kref)
|
|||
|
||||
/* if the GPU submit failed, objects might still be locked */
|
||||
submit_unlock_object(submit, i);
|
||||
drm_gem_object_put_unlocked(&etnaviv_obj->base);
|
||||
drm_gem_object_put(&etnaviv_obj->base);
|
||||
}
|
||||
|
||||
wake_up_all(&submit->gpu->fence_event);
|
||||
|
|
|
@ -100,7 +100,7 @@ static int exynos_drm_gem_handle_create(struct drm_gem_object *obj,
|
|||
DRM_DEV_DEBUG_KMS(to_dma_dev(obj->dev), "gem handle = 0x%x\n", *handle);
|
||||
|
||||
/* drop reference from allocate - handle holds it now. */
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
|
|||
args->flags = exynos_gem->flags;
|
||||
args->size = exynos_gem->size;
|
||||
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ struct exynos_drm_gem *exynos_drm_gem_get(struct drm_file *filp,
|
|||
*/
|
||||
static inline void exynos_drm_gem_put(struct exynos_drm_gem *exynos_gem)
|
||||
{
|
||||
drm_gem_object_put_unlocked(&exynos_gem->base);
|
||||
drm_gem_object_put(&exynos_gem->base);
|
||||
}
|
||||
|
||||
/* get buffer information to memory region allocated by gem. */
|
||||
|
|
|
@ -921,7 +921,8 @@ static int hdmi_mode_valid(struct drm_connector *connector,
|
|||
|
||||
DRM_DEV_DEBUG_KMS(hdata->dev,
|
||||
"xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
|
||||
mode->hdisplay, mode->vdisplay, mode->vrefresh,
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
drm_mode_vrefresh(mode),
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE) ? true :
|
||||
false, mode->clock * 1000);
|
||||
|
||||
|
@ -1020,7 +1021,7 @@ static bool hdmi_mode_fixup(struct drm_encoder *encoder,
|
|||
DRM_DEV_DEBUG_KMS(dev->dev,
|
||||
"Adjusted Mode: [%d]x[%d] [%d]Hz\n",
|
||||
m->hdisplay, m->vdisplay,
|
||||
m->vrefresh);
|
||||
drm_mode_vrefresh(m));
|
||||
|
||||
drm_mode_copy(adjusted_mode, m);
|
||||
break;
|
||||
|
|
|
@ -1046,7 +1046,7 @@ static int mixer_mode_valid(struct exynos_drm_crtc *crtc,
|
|||
u32 w = mode->hdisplay, h = mode->vdisplay;
|
||||
|
||||
DRM_DEV_DEBUG_KMS(ctx->dev, "xres=%d, yres=%d, refresh=%d, intl=%d\n",
|
||||
w, h, mode->vrefresh,
|
||||
w, h, drm_mode_vrefresh(mode),
|
||||
!!(mode->flags & DRM_MODE_FLAG_INTERLACE));
|
||||
|
||||
if (ctx->mxr_ver == MXR_VER_128_0_0_184)
|
||||
|
|
|
@ -141,16 +141,7 @@ static struct drm_driver fsl_dcu_drm_driver = {
|
|||
.irq_handler = fsl_dcu_drm_irq,
|
||||
.irq_preinstall = fsl_dcu_irq_uninstall,
|
||||
.irq_uninstall = fsl_dcu_irq_uninstall,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
.dumb_create = drm_gem_cma_dumb_create,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &fsl_dcu_drm_fops,
|
||||
.name = "fsl-dcu-drm",
|
||||
.desc = "Freescale DCU DRM",
|
||||
|
|
|
@ -491,7 +491,7 @@ static int psb_fbdev_destroy(struct drm_device *dev,
|
|||
drm_framebuffer_cleanup(fb);
|
||||
|
||||
if (fb->obj[0])
|
||||
drm_gem_object_put_unlocked(fb->obj[0]);
|
||||
drm_gem_object_put(fb->obj[0]);
|
||||
kfree(fb);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -82,7 +82,7 @@ int psb_gem_create(struct drm_file *file, struct drm_device *dev, u64 size,
|
|||
return ret;
|
||||
}
|
||||
/* We have the initial and handle reference but need only one now */
|
||||
drm_gem_object_put_unlocked(&r->gem);
|
||||
drm_gem_object_put(&r->gem);
|
||||
*handlep = handle;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -351,7 +351,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
gt = container_of(gma_crtc->cursor_obj,
|
||||
struct gtt_range, gem);
|
||||
psb_gtt_unpin(gt);
|
||||
drm_gem_object_put_unlocked(gma_crtc->cursor_obj);
|
||||
drm_gem_object_put(gma_crtc->cursor_obj);
|
||||
gma_crtc->cursor_obj = NULL;
|
||||
}
|
||||
return 0;
|
||||
|
@ -427,7 +427,7 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc,
|
|||
if (gma_crtc->cursor_obj) {
|
||||
gt = container_of(gma_crtc->cursor_obj, struct gtt_range, gem);
|
||||
psb_gtt_unpin(gt);
|
||||
drm_gem_object_put_unlocked(gma_crtc->cursor_obj);
|
||||
drm_gem_object_put(gma_crtc->cursor_obj);
|
||||
}
|
||||
|
||||
gma_crtc->cursor_obj = obj;
|
||||
|
@ -435,7 +435,7 @@ unlock:
|
|||
return ret;
|
||||
|
||||
unref_cursor:
|
||||
drm_gem_object_put_unlocked(obj);
|
||||
drm_gem_object_put(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -507,7 +507,7 @@ static struct drm_driver driver = {
|
|||
.irq_uninstall = psb_irq_uninstall,
|
||||
.irq_handler = psb_irq_handler,
|
||||
|
||||
.gem_free_object = psb_gem_free_object,
|
||||
.gem_free_object_unlocked = psb_gem_free_object,
|
||||
.gem_vm_ops = &psb_gem_vm_ops,
|
||||
|
||||
.dumb_create = psb_gem_dumb_create,
|
||||
|
|
|
@ -56,25 +56,6 @@
|
|||
#define INTEL_OUTPUT_DISPLAYPORT 9
|
||||
#define INTEL_OUTPUT_EDP 10
|
||||
|
||||
#define INTEL_MODE_PIXEL_MULTIPLIER_SHIFT (0x0)
|
||||
#define INTEL_MODE_PIXEL_MULTIPLIER_MASK (0xf << INTEL_MODE_PIXEL_MULTIPLIER_SHIFT)
|
||||
|
||||
static inline void
|
||||
psb_intel_mode_set_pixel_multiplier(struct drm_display_mode *mode,
|
||||
int multiplier)
|
||||
{
|
||||
mode->clock *= multiplier;
|
||||
mode->private_flags |= multiplier;
|
||||
}
|
||||
|
||||
static inline int
|
||||
psb_intel_mode_get_pixel_multiplier(const struct drm_display_mode *mode)
|
||||
{
|
||||
return (mode->private_flags & INTEL_MODE_PIXEL_MULTIPLIER_MASK)
|
||||
>> INTEL_MODE_PIXEL_MULTIPLIER_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Hold information useally put on the device driver privates here,
|
||||
* since it needs to be shared across multiple of devices drivers privates.
|
||||
|
|
|
@ -132,6 +132,8 @@ struct psb_intel_sdvo {
|
|||
/* DDC bus used by this SDVO encoder */
|
||||
uint8_t ddc_bus;
|
||||
|
||||
u8 pixel_multiplier;
|
||||
|
||||
/* Input timings for adjusted_mode */
|
||||
struct psb_intel_sdvo_dtd input_dtd;
|
||||
|
||||
|
@ -928,7 +930,6 @@ static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct psb_intel_sdvo *psb_intel_sdvo = to_psb_intel_sdvo(encoder);
|
||||
int multiplier;
|
||||
|
||||
/* We need to construct preferred input timings based on our
|
||||
* output timings. To do that, we have to set the output
|
||||
|
@ -955,8 +956,9 @@ static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder,
|
|||
/* Make the CRTC code factor in the SDVO pixel multiplier. The
|
||||
* SDVO device will factor out the multiplier during mode_set.
|
||||
*/
|
||||
multiplier = psb_intel_sdvo_get_pixel_multiplier(adjusted_mode);
|
||||
psb_intel_mode_set_pixel_multiplier(adjusted_mode, multiplier);
|
||||
psb_intel_sdvo->pixel_multiplier =
|
||||
psb_intel_sdvo_get_pixel_multiplier(adjusted_mode);
|
||||
adjusted_mode->clock *= psb_intel_sdvo->pixel_multiplier;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -972,7 +974,6 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|||
u32 sdvox;
|
||||
struct psb_intel_sdvo_in_out_map in_out;
|
||||
struct psb_intel_sdvo_dtd input_dtd;
|
||||
int pixel_multiplier = psb_intel_mode_get_pixel_multiplier(adjusted_mode);
|
||||
int rate;
|
||||
int need_aux = IS_MRST(dev) ? 1 : 0;
|
||||
|
||||
|
@ -1030,7 +1031,7 @@ static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder,
|
|||
|
||||
(void) psb_intel_sdvo_set_input_timing(psb_intel_sdvo, &input_dtd);
|
||||
|
||||
switch (pixel_multiplier) {
|
||||
switch (psb_intel_sdvo->pixel_multiplier) {
|
||||
default:
|
||||
case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break;
|
||||
case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break;
|
||||
|
|
|
@ -921,17 +921,7 @@ DEFINE_DRM_GEM_CMA_FOPS(ade_fops);
|
|||
static struct drm_driver ade_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.fops = &ade_fops,
|
||||
.gem_free_object_unlocked = drm_gem_cma_free_object,
|
||||
.gem_vm_ops = &drm_gem_cma_vm_ops,
|
||||
.dumb_create = drm_gem_cma_dumb_create_internal,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
.gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
|
||||
.gem_prime_vmap = drm_gem_cma_prime_vmap,
|
||||
.gem_prime_vunmap = drm_gem_cma_prime_vunmap,
|
||||
.gem_prime_mmap = drm_gem_cma_prime_mmap,
|
||||
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.name = "kirin",
|
||||
.desc = "Hisilicon Kirin620 SoC DRM Driver",
|
||||
.date = "20150718",
|
||||
|
|
|
@ -121,7 +121,6 @@ const struct ch7006_tv_norm_info ch7006_tv_norms[] = {
|
|||
.vscan = 0, \
|
||||
.flags = DRM_MODE_FLAG_##hsynp##HSYNC | \
|
||||
DRM_MODE_FLAG_##vsynp##VSYNC, \
|
||||
.vrefresh = 0, \
|
||||
}, \
|
||||
.enc_hdisp = e_hd, \
|
||||
.enc_vdisp = e_vd, \
|
||||
|
|
|
@ -8886,7 +8886,6 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,
|
|||
|
||||
mode->clock = pipe_config->hw.adjusted_mode.crtc_clock;
|
||||
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
drm_mode_set_name(mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -1099,10 +1099,10 @@ static void drrs_status_per_crtc(struct seq_file *m,
|
|||
seq_puts(m, "\n\t\t");
|
||||
if (drrs->refresh_rate_type == DRRS_HIGH_RR) {
|
||||
seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n");
|
||||
vrefresh = panel->fixed_mode->vrefresh;
|
||||
vrefresh = drm_mode_vrefresh(panel->fixed_mode);
|
||||
} else if (drrs->refresh_rate_type == DRRS_LOW_RR) {
|
||||
seq_puts(m, "DRRS_State: DRRS_LOW_RR\n");
|
||||
vrefresh = panel->downclock_mode->vrefresh;
|
||||
vrefresh = drm_mode_vrefresh(panel->downclock_mode);
|
||||
} else {
|
||||
seq_printf(m, "DRRS_State: Unknown(%d)\n",
|
||||
drrs->refresh_rate_type);
|
||||
|
|
|
@ -7694,7 +7694,7 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
|
|||
return;
|
||||
}
|
||||
|
||||
if (intel_dp->attached_connector->panel.downclock_mode->vrefresh ==
|
||||
if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
|
||||
refresh_rate)
|
||||
index = DRRS_LOW_RR;
|
||||
|
||||
|
@ -7807,7 +7807,7 @@ void intel_edp_drrs_disable(struct intel_dp *intel_dp,
|
|||
|
||||
if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, old_crtc_state,
|
||||
intel_dp->attached_connector->panel.fixed_mode->vrefresh);
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
dev_priv->drrs.dp = NULL;
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
|
@ -7840,7 +7840,7 @@ static void intel_edp_drrs_downclock_work(struct work_struct *work)
|
|||
struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
intel_dp->attached_connector->panel.downclock_mode->vrefresh);
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
|
||||
}
|
||||
|
||||
unlock:
|
||||
|
@ -7860,6 +7860,7 @@ unlock:
|
|||
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
|
@ -7869,12 +7870,14 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
|||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (!dev_priv->drrs.dp) {
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
|
@ -7883,7 +7886,7 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
|||
/* invalidate means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh);
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
@ -7903,6 +7906,7 @@ void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
|||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
|
@ -7912,12 +7916,14 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
|||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (!dev_priv->drrs.dp) {
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(dev_priv->drrs.dp)->base.base.crtc;
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
|
@ -7926,7 +7932,7 @@ void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
|||
/* flush means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
dev_priv->drrs.dp->attached_connector->panel.fixed_mode->vrefresh);
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
/*
|
||||
* flush also means no more activity hence schedule downclock, if all
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "intel_connector.h"
|
||||
#include "intel_ddi.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_hotplug.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
|
@ -773,8 +774,17 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_mst_poll_hpd_irq(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
|
||||
|
||||
intel_hpd_trigger_irq(dp_to_dig_port(intel_dp));
|
||||
}
|
||||
|
||||
static const struct drm_dp_mst_topology_cbs mst_cbs = {
|
||||
.add_connector = intel_dp_add_mst_connector,
|
||||
.poll_hpd_irq = intel_dp_mst_poll_hpd_irq,
|
||||
};
|
||||
|
||||
static struct intel_dp_mst_encoder *
|
||||
|
|
|
@ -347,6 +347,24 @@ static void i915_digport_work_func(struct work_struct *work)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_hpd_trigger_irq - trigger an hpd irq event for a port
|
||||
* @dig_port: digital port
|
||||
*
|
||||
* Trigger an HPD interrupt event for the given port, emulating a short pulse
|
||||
* generated by the sink, and schedule the dig port work to handle it.
|
||||
*/
|
||||
void intel_hpd_trigger_irq(struct intel_digital_port *dig_port)
|
||||
{
|
||||
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
|
||||
|
||||
spin_lock_irq(&i915->irq_lock);
|
||||
i915->hotplug.short_port_mask |= BIT(dig_port->base.port);
|
||||
spin_unlock_irq(&i915->irq_lock);
|
||||
|
||||
queue_work(i915->hotplug.dp_wq, &i915->hotplug.dig_port_work);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle hotplug events outside the interrupt handler proper.
|
||||
*/
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
struct drm_i915_private;
|
||||
struct intel_connector;
|
||||
struct intel_digital_port;
|
||||
struct intel_encoder;
|
||||
enum port;
|
||||
|
||||
|
@ -18,6 +19,7 @@ enum intel_hotplug_state intel_encoder_hotplug(struct intel_encoder *encoder,
|
|||
struct intel_connector *connector);
|
||||
void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
|
||||
u32 pin_mask, u32 long_mask);
|
||||
void intel_hpd_trigger_irq(struct intel_digital_port *dig_port);
|
||||
void intel_hpd_init(struct drm_i915_private *dev_priv);
|
||||
void intel_hpd_init_work(struct drm_i915_private *dev_priv);
|
||||
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
|
||||
|
|
|
@ -1038,9 +1038,6 @@ intel_tv_mode_to_mode(struct drm_display_mode *mode,
|
|||
/* TV has it's own notion of sync and other mode flags, so clear them. */
|
||||
mode->flags = 0;
|
||||
|
||||
mode->vrefresh = 0;
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
|
||||
snprintf(mode->name, sizeof(mode->name),
|
||||
"%dx%d%c (%s)",
|
||||
mode->hdisplay, mode->vdisplay,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче