mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
drm-misc-next for v5.15:
UAPI Changes: - Add modifiers for arm fixed rate compression. Cross-subsystem Changes: - Assorted dt binding fixes. - Convert ssd1307fb to json-schema. - Update a lot of irc channels to point to OFTC, as everyone moved there. - Fix the same divide by zero for asilantfb, kyro, rivafb. Core Changes: - Document requirements for new atomic properties. - Add drm_gem_fb_(begin/end)_cpu_access helpers, and use them in some drivers. - Document drm_property_enum.value for bitfields. - Add explicit _NO_ for MIPI_DSI flags that disable features. - Assorted documentation fixes. - Update fb_damage handling, and move drm_plane_enable_fb_damage_clips to core. - Add logging and docs to RMFB ioctl. - Assorted small fixes to dp_mst, master handling. - Clarify drm lease usage. Driver Changes: - Assorted small fixes to panfrost, hibmc, bridge/nwl-dsi, rockchip, vc4. - More drm -> linux irq conversions. - Add support for some Logic Technologies and Multi-Inno panels. - Expose phy-functionality for drm/rockchip, to allow controlling from the media subsystem. - Add support for 2 AUO panels. - Add damage handling to ssd1307fb. - Improve FIFO handling on mxsfb. - Assorted small fixes to vmwgfx, and bump version to 2.19 for the new ioctls. - Improve sony acx424akp backlight handling. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAmEDFiUACgkQ/lWMcqZw E8NSbA//aw/TgTpwGNnJNHDJPwXS8WSC+1ouUJ6IKmFUkxZhpK++bJYaCZ5cj//I pf9078qC4hXXmCCzTtQ3JawLhaZ2G33qfKod0JiB+4jrdQ4W5vYaZ3uFxiws0iu9 6KoPL1k8wO8L8CntXi3akSM/KFFrYQzjtt0MDZspIxVdd2AKBFAdwdLDqVvk1Ix6 xBpnpC7uXBVev4kTL8W7SN7HxnKHaPTwE4pUUNrR56rvjYIRd9rgdsJKNaR9oTeO I6ARYRKSjeVsguVV6Eqy2hEBOG2v0Zy/T54z/2ksjw64A6uerenv92nwO34FXthx 59tuBYYsfKlEsKTQVHCys2+8RwcFVZIk+k1tr1h7LM7My6ynFVIOMDV+Upuv77+p q2YiM0r6c3TgmZiqAuTdkvs8dbTgSb2j7Enq04ee3QnXnNek9hvdCyIsLQvkqrGT m9I6F/2Rl9X2IFbVv+ia4hLk0IlBPAgZrNMP363AodQAjq54ED8baO26qKY9Y+aG AIS4DEJ0odNE/G+MKhz84Lpdyq+kOK4tgaORBOQTeDlZLzHyxrYgl8wV+E/RNTKN YU5cLOJaVedd/onHgq51XVio5djWCRfwCHM9HKAgDONcW8LvHXFidvscg2Mw4f1g 1rfnSOJyV8CARjjiigjBfnxweWvEK6J13lt8tl0z7OYpuVOQkxU= =ZSMl -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2021-07-29' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.15: UAPI Changes: - Add modifiers for arm fixed rate compression. Cross-subsystem Changes: - Assorted dt binding fixes. - Convert ssd1307fb to json-schema. - Update a lot of irc channels to point to OFTC, as everyone moved there. - Fix the same divide by zero for asilantfb, kyro, rivafb. Core Changes: - Document requirements for new atomic properties. - Add drm_gem_fb_(begin/end)_cpu_access helpers, and use them in some drivers. - Document drm_property_enum.value for bitfields. - Add explicit _NO_ for MIPI_DSI flags that disable features. - Assorted documentation fixes. - Update fb_damage handling, and move drm_plane_enable_fb_damage_clips to core. - Add logging and docs to RMFB ioctl. - Assorted small fixes to dp_mst, master handling. - Clarify drm lease usage. Driver Changes: - Assorted small fixes to panfrost, hibmc, bridge/nwl-dsi, rockchip, vc4. - More drm -> linux irq conversions. - Add support for some Logic Technologies and Multi-Inno panels. - Expose phy-functionality for drm/rockchip, to allow controlling from the media subsystem. - Add support for 2 AUO panels. - Add damage handling to ssd1307fb. - Improve FIFO handling on mxsfb. - Assorted small fixes to vmwgfx, and bump version to 2.19 for the new ioctls. - Improve sony acx424akp backlight handling. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/a753221a-e23e-0dc4-7ca6-8c1b179738d0@linux.intel.com
This commit is contained in:
commit
cfeeb0b5e0
@ -46,9 +46,13 @@ properties:
|
||||
# AU Optronics Corporation 11.6" HD (1366x768) color TFT-LCD panel
|
||||
- auo,b116xw03
|
||||
# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
|
||||
- auo,b133han05
|
||||
# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
|
||||
- auo,b133htn01
|
||||
# AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
|
||||
- auo,b133xtn01
|
||||
# AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
|
||||
- auo,b140han06
|
||||
# AU Optronics Corporation 7.0" FHD (800 x 480) TFT LCD panel
|
||||
- auo,g070vvn01
|
||||
# AU Optronics Corporation 10.1" (1280x800) color TFT LCD panel
|
||||
@ -208,8 +212,14 @@ properties:
|
||||
- logictechno,lt161010-2nhr
|
||||
# Logic Technologies LT170410-2WHC 10.1" 1280x800 IPS TFT Cap Touch Mod.
|
||||
- logictechno,lt170410-2whc
|
||||
# Logic Technologies LTTD800x480 L2RT 7" 800x480 TFT Resistive Touch Module
|
||||
- logictechno,lttd800480070-l2rt
|
||||
# Logic Technologies LTTD800480070-L6WH-RT 7” 800x480 TFT Resistive Touch Module
|
||||
- logictechno,lttd800480070-l6wh-rt
|
||||
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
|
||||
- mitsubishi,aa070mc01-ca1
|
||||
# Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.
|
||||
- multi-inno,mi1010ait-1cp
|
||||
# NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
|
||||
- nec,nl12880bc20-05
|
||||
# NEC LCD Technologies,Ltd. WQVGA TFT LCD panel
|
||||
|
@ -23,6 +23,7 @@ Required properties:
|
||||
Optional properties:
|
||||
- phys: from general PHY binding: the phandle for the PHY device.
|
||||
- phy-names: Should be "dphy" if phys references an external phy.
|
||||
- #phy-cells: Defined when used as ISP phy, should be 0.
|
||||
- power-domains: a phandle to mipi dsi power domain node.
|
||||
- resets: list of phandle + reset specifier pairs, as described in [3].
|
||||
- reset-names: string reset name, must be "apb".
|
||||
|
208
Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
Normal file
208
Documentation/devicetree/bindings/display/solomon,ssd1307fb.yaml
Normal file
@ -0,0 +1,208 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/solomon,ssd1307fb.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Solomon SSD1307 OLED Controller Framebuffer
|
||||
|
||||
maintainers:
|
||||
- Maxime Ripard <mripard@kernel.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- solomon,ssd1305fb-i2c
|
||||
- solomon,ssd1306fb-i2c
|
||||
- solomon,ssd1307fb-i2c
|
||||
- solomon,ssd1309fb-i2c
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
pwms:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vbat-supply:
|
||||
description: The supply for VBAT
|
||||
|
||||
solomon,height:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 16
|
||||
description:
|
||||
Height in pixel of the screen driven by the controller
|
||||
|
||||
solomon,width:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 96
|
||||
description:
|
||||
Width in pixel of the screen driven by the controller
|
||||
|
||||
solomon,page-offset:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 1
|
||||
description:
|
||||
Offset of pages (band of 8 pixels) that the screen is mapped to
|
||||
|
||||
solomon,segment-no-remap:
|
||||
type: boolean
|
||||
description:
|
||||
Display needs normal (non-inverted) data column to segment mapping
|
||||
|
||||
solomon,col-offset:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 0
|
||||
description:
|
||||
Offset of columns (COL/SEG) that the screen is mapped to
|
||||
|
||||
solomon,com-seq:
|
||||
type: boolean
|
||||
description:
|
||||
Display uses sequential COM pin configuration
|
||||
|
||||
solomon,com-lrremap:
|
||||
type: boolean
|
||||
description:
|
||||
Display uses left-right COM pin remap
|
||||
|
||||
solomon,com-invdir:
|
||||
type: boolean
|
||||
description:
|
||||
Display uses inverted COM pin scan direction
|
||||
|
||||
solomon,com-offset:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 0
|
||||
description:
|
||||
Number of the COM pin wired to the first display line
|
||||
|
||||
solomon,prechargep1:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 2
|
||||
description:
|
||||
Length of deselect period (phase 1) in clock cycles
|
||||
|
||||
solomon,prechargep2:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
default: 2
|
||||
description:
|
||||
Length of precharge period (phase 2) in clock cycles. This needs to be
|
||||
the higher, the higher the capacitance of the OLED's pixels is.
|
||||
|
||||
solomon,dclk-div:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 1
|
||||
maximum: 16
|
||||
description:
|
||||
Clock divisor. The default value is controller-dependent.
|
||||
|
||||
solomon,dclk-frq:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
minimum: 0
|
||||
maximum: 15
|
||||
description:
|
||||
Clock frequency, higher value means higher frequency.
|
||||
The default value is controller-dependent.
|
||||
|
||||
solomon,lookup-table:
|
||||
$ref: /schemas/types.yaml#/definitions/uint8-array
|
||||
maxItems: 4
|
||||
description:
|
||||
8 bit value array of current drive pulse widths for BANK0, and colors A,
|
||||
B, and C. Each value in range of 31 to 63 for pulse widths of 32 to 64.
|
||||
Color D is always width 64.
|
||||
|
||||
solomon,area-color-enable:
|
||||
type: boolean
|
||||
description:
|
||||
Display uses color mode
|
||||
|
||||
solomon,low-power:
|
||||
type: boolean
|
||||
description:
|
||||
Display runs in low power mode
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: solomon,ssd1305fb-i2c
|
||||
then:
|
||||
properties:
|
||||
solomon,dclk-div:
|
||||
default: 1
|
||||
solomon,dclk-frq:
|
||||
default: 7
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: solomon,ssd1306fb-i2c
|
||||
then:
|
||||
properties:
|
||||
solomon,dclk-div:
|
||||
default: 1
|
||||
solomon,dclk-frq:
|
||||
default: 8
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: solomon,ssd1307fb-i2c
|
||||
then:
|
||||
properties:
|
||||
solomon,dclk-div:
|
||||
default: 2
|
||||
solomon,dclk-frq:
|
||||
default: 12
|
||||
required:
|
||||
- pwms
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: solomon,ssd1309fb-i2c
|
||||
then:
|
||||
properties:
|
||||
solomon,dclk-div:
|
||||
default: 1
|
||||
solomon,dclk-frq:
|
||||
default: 10
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ssd1307: oled@3c {
|
||||
compatible = "solomon,ssd1307fb-i2c";
|
||||
reg = <0x3c>;
|
||||
pwms = <&pwm 4 3000>;
|
||||
reset-gpios = <&gpio2 7>;
|
||||
};
|
||||
|
||||
ssd1306: oled@3d {
|
||||
compatible = "solomon,ssd1306fb-i2c";
|
||||
reg = <0x3c>;
|
||||
pwms = <&pwm 4 3000>;
|
||||
reset-gpios = <&gpio2 7>;
|
||||
solomon,com-lrremap;
|
||||
solomon,com-invdir;
|
||||
solomon,com-offset = <32>;
|
||||
solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;
|
||||
};
|
||||
};
|
@ -1,60 +0,0 @@
|
||||
* Solomon SSD1307 Framebuffer Driver
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "solomon,<chip>fb-<bus>". The only supported bus for
|
||||
now is i2c, and the supported chips are ssd1305, ssd1306, ssd1307 and
|
||||
ssd1309.
|
||||
- reg: Should contain address of the controller on the I2C bus. Most likely
|
||||
0x3c or 0x3d
|
||||
- pwm: Should contain the pwm to use according to the OF device tree PWM
|
||||
specification [0]. Only required for the ssd1307.
|
||||
- solomon,height: Height in pixel of the screen driven by the controller
|
||||
- solomon,width: Width in pixel of the screen driven by the controller
|
||||
- solomon,page-offset: Offset of pages (band of 8 pixels) that the screen is
|
||||
mapped to.
|
||||
|
||||
Optional properties:
|
||||
- reset-gpios: The GPIO used to reset the OLED display, if available. See
|
||||
Documentation/devicetree/bindings/gpio/gpio.txt for details.
|
||||
- vbat-supply: The supply for VBAT
|
||||
- solomon,segment-no-remap: Display needs normal (non-inverted) data column
|
||||
to segment mapping
|
||||
- solomon,col-offset: Offset of columns (COL/SEG) that the screen is mapped to.
|
||||
- solomon,com-seq: Display uses sequential COM pin configuration
|
||||
- solomon,com-lrremap: Display uses left-right COM pin remap
|
||||
- solomon,com-invdir: Display uses inverted COM pin scan direction
|
||||
- solomon,com-offset: Number of the COM pin wired to the first display line
|
||||
- solomon,prechargep1: Length of deselect period (phase 1) in clock cycles.
|
||||
- solomon,prechargep2: Length of precharge period (phase 2) in clock cycles.
|
||||
This needs to be the higher, the higher the capacitance
|
||||
of the OLED's pixels is
|
||||
- solomon,dclk-div: Clock divisor 1 to 16
|
||||
- solomon,dclk-frq: Clock frequency 0 to 15, higher value means higher
|
||||
frequency
|
||||
- solomon,lookup-table: 8 bit value array of current drive pulse widths for
|
||||
BANK0, and colors A, B, and C. Each value in range
|
||||
of 31 to 63 for pulse widths of 32 to 64. Color D
|
||||
is always width 64.
|
||||
- solomon,area-color-enable: Display uses color mode
|
||||
- solomon,low-power. Display runs in low power mode
|
||||
|
||||
[0]: Documentation/devicetree/bindings/pwm/pwm.txt
|
||||
|
||||
Examples:
|
||||
ssd1307: oled@3c {
|
||||
compatible = "solomon,ssd1307fb-i2c";
|
||||
reg = <0x3c>;
|
||||
pwms = <&pwm 4 3000>;
|
||||
reset-gpios = <&gpio2 7>;
|
||||
};
|
||||
|
||||
ssd1306: oled@3c {
|
||||
compatible = "solomon,ssd1306fb-i2c";
|
||||
reg = <0x3c>;
|
||||
pwms = <&pwm 4 3000>;
|
||||
reset-gpios = <&gpio2 7>;
|
||||
solomon,com-lrremap;
|
||||
solomon,com-invdir;
|
||||
solomon,com-offset = <32>;
|
||||
solomon,lookup-table = /bits/ 8 <0x3f 0x3f 0x3f 0x3f>;
|
||||
};
|
@ -936,6 +936,8 @@ patternProperties:
|
||||
description: Chengdu Kaixuan Information Technology Co., Ltd.
|
||||
"^qiaodian,.*":
|
||||
description: QiaoDian XianShi Corporation
|
||||
"^qishenglong,.*":
|
||||
description: Shenzhen QiShenglong Industrialist Co., Ltd.
|
||||
"^qnap,.*":
|
||||
description: QNAP Systems, Inc.
|
||||
"^radxa,.*":
|
||||
|
@ -90,7 +90,7 @@ Bug reports
|
||||
-----------
|
||||
|
||||
Thermal management on Nouveau is new and may not work on all cards. If you have
|
||||
inquiries, please ping mupuf on IRC (#nouveau, freenode).
|
||||
inquiries, please ping mupuf on IRC (#nouveau, OFTC).
|
||||
|
||||
Bug reports should be filled on Freedesktop's bug tracker. Please follow
|
||||
https://nouveau.freedesktop.org/wiki/Bugs
|
||||
|
@ -463,6 +463,35 @@ KMS Properties
|
||||
This section of the documentation is primarily aimed at user-space developers.
|
||||
For the driver APIs, see the other sections.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
KMS drivers might need to add extra properties to support new features. Each
|
||||
new property introduced in a driver needs to meet a few requirements, in
|
||||
addition to the one mentioned above:
|
||||
|
||||
* It must be standardized, documenting:
|
||||
|
||||
* The full, exact, name string;
|
||||
* If the property is an enum, all the valid value name strings;
|
||||
* What values are accepted, and what these values mean;
|
||||
* What the property does and how it can be used;
|
||||
* How the property might interact with other, existing properties.
|
||||
|
||||
* It must provide a generic helper in the core code to register that
|
||||
property on the object it attaches to.
|
||||
|
||||
* Its content must be decoded by the core and provided in the object's
|
||||
associated state structure. That includes anything drivers might want
|
||||
to precompute, like struct drm_clip_rect for planes.
|
||||
|
||||
* Its initial state must match the behavior prior to the property
|
||||
introduction. This might be a fixed value matching what the hardware
|
||||
does, or it may be inherited from the state the firmware left the
|
||||
system in during boot.
|
||||
|
||||
* An IGT test must be submitted where reasonable.
|
||||
|
||||
Property Types and Blob Property Support
|
||||
----------------------------------------
|
||||
|
||||
@ -508,8 +537,8 @@ Plane Composition Properties
|
||||
Damage Tracking Properties
|
||||
--------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_damage_helper.c
|
||||
:doc: overview
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_plane.c
|
||||
:doc: damage tracking
|
||||
|
||||
Color Management Properties
|
||||
---------------------------
|
||||
|
@ -37,6 +37,15 @@ Primary Nodes, DRM Master and Authentication
|
||||
.. kernel-doc:: include/drm/drm_auth.h
|
||||
:internal:
|
||||
|
||||
|
||||
.. _drm_leasing:
|
||||
|
||||
DRM Display Resource Leasing
|
||||
============================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_lease.c
|
||||
:doc: drm leasing
|
||||
|
||||
Open-Source Userspace Requirements
|
||||
==================================
|
||||
|
||||
|
@ -1690,7 +1690,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
W: https://asahilinux.org
|
||||
B: https://github.com/AsahiLinux/linux/issues
|
||||
C: irc://chat.freenode.net/asahi-dev
|
||||
C: irc://irc.oftc.net/asahi-dev
|
||||
T: git https://github.com/AsahiLinux/linux.git
|
||||
F: Documentation/devicetree/bindings/arm/apple.yaml
|
||||
F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
|
||||
@ -6080,7 +6080,7 @@ M: Daniel Vetter <daniel@ffwll.ch>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
B: https://gitlab.freedesktop.org/drm
|
||||
C: irc://chat.freenode.net/dri-devel
|
||||
C: irc://irc.oftc.net/dri-devel
|
||||
T: git git://anongit.freedesktop.org/drm/drm
|
||||
F: Documentation/devicetree/bindings/display/
|
||||
F: Documentation/devicetree/bindings/gpu/
|
||||
@ -9264,7 +9264,7 @@ S: Supported
|
||||
W: https://01.org/linuxgraphics/
|
||||
Q: http://patchwork.freedesktop.org/project/intel-gfx/
|
||||
B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
|
||||
C: irc://chat.freenode.net/intel-gfx
|
||||
C: irc://irc.oftc.net/intel-gfx
|
||||
T: git git://anongit.freedesktop.org/drm-intel
|
||||
F: Documentation/gpu/i915.rst
|
||||
F: drivers/gpu/drm/i915/
|
||||
|
@ -165,7 +165,7 @@ int adv7533_attach_dsi(struct adv7511 *adv)
|
||||
dsi->lanes = adv->num_dsi_lanes;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
||||
MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -1307,7 +1307,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
||||
MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_MODE_VIDEO_HSE;
|
||||
|
||||
if (mipi_dsi_attach(dsi) < 0) {
|
||||
|
@ -829,7 +829,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
|
||||
DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
|
||||
|
||||
if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
|
||||
|
||||
tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
|
||||
@ -902,7 +902,7 @@ static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
|
||||
tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
|
||||
|
||||
if (!(output->dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
tmp |= HOST_EOT_GEN;
|
||||
|
||||
if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO)
|
||||
|
@ -487,7 +487,7 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM |
|
||||
MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
ret = mipi_dsi_attach(dsi);
|
||||
if (ret < 0) {
|
||||
|
@ -190,7 +190,7 @@ static u32 ps2bc(struct nwl_dsi *dsi, unsigned long long ps)
|
||||
u32 bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
|
||||
|
||||
return DIV64_U64_ROUND_UP(ps * dsi->mode.clock * bpp,
|
||||
dsi->lanes * 8 * NSEC_PER_SEC);
|
||||
dsi->lanes * 8ULL * NSEC_PER_SEC);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -246,6 +246,7 @@ struct dw_mipi_dsi {
|
||||
|
||||
struct clk *pclk;
|
||||
|
||||
bool device_found;
|
||||
unsigned int lane_mbps; /* per lane */
|
||||
u32 channel;
|
||||
u32 lanes;
|
||||
@ -309,13 +310,37 @@ static inline u32 dsi_read(struct dw_mipi_dsi *dsi, u32 reg)
|
||||
return readl(dsi->base + reg);
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_panel_or_bridge(struct dw_mipi_dsi *dsi,
|
||||
struct device_node *node)
|
||||
{
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
int ret;
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(node, 1, 0, &panel, &bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (panel) {
|
||||
bridge = drm_panel_bridge_add_typed(panel,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (IS_ERR(bridge))
|
||||
return PTR_ERR(bridge);
|
||||
}
|
||||
|
||||
dsi->panel_bridge = bridge;
|
||||
|
||||
if (!dsi->panel_bridge)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
struct mipi_dsi_device *device)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = host_to_dsi(host);
|
||||
const struct dw_mipi_dsi_plat_data *pdata = dsi->plat_data;
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
int ret;
|
||||
|
||||
if (device->lanes > dsi->plat_data->max_data_lanes) {
|
||||
@ -329,22 +354,14 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
|
||||
dsi->format = device->format;
|
||||
dsi->mode_flags = device->mode_flags;
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(host->dev->of_node, 1, 0,
|
||||
&panel, &bridge);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!dsi->device_found) {
|
||||
ret = dw_mipi_dsi_panel_or_bridge(dsi, host->dev->of_node);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (panel) {
|
||||
bridge = drm_panel_bridge_add_typed(panel,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
if (IS_ERR(bridge))
|
||||
return PTR_ERR(bridge);
|
||||
dsi->device_found = true;
|
||||
}
|
||||
|
||||
dsi->panel_bridge = bridge;
|
||||
|
||||
drm_bridge_add(&dsi->bridge);
|
||||
|
||||
if (pdata->host_ops && pdata->host_ops->attach) {
|
||||
ret = pdata->host_ops->attach(pdata->priv_data, device);
|
||||
if (ret < 0)
|
||||
@ -999,6 +1016,16 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
|
||||
/* Set the encoder type as caller does not know it */
|
||||
bridge->encoder->encoder_type = DRM_MODE_ENCODER_DSI;
|
||||
|
||||
if (!dsi->device_found) {
|
||||
int ret;
|
||||
|
||||
ret = dw_mipi_dsi_panel_or_bridge(dsi, dsi->dev->of_node);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dsi->device_found = true;
|
||||
}
|
||||
|
||||
/* Attach the panel-bridge to the dsi bridge */
|
||||
return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
|
||||
flags);
|
||||
@ -1181,6 +1208,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
|
||||
#ifdef CONFIG_OF
|
||||
dsi->bridge.of_node = pdev->dev.of_node;
|
||||
#endif
|
||||
drm_bridge_add(&dsi->bridge);
|
||||
|
||||
return dsi;
|
||||
}
|
||||
|
@ -825,7 +825,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
|
||||
if (!(dsi_dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
|
||||
val |= TC358768_DSI_CONTROL_HSCKMD;
|
||||
|
||||
if (dsi_dev->mode_flags & MIPI_DSI_MODE_EOT_PACKET)
|
||||
if (dsi_dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET)
|
||||
val |= TC358768_DSI_CONTROL_EOTDIS;
|
||||
|
||||
tc358768_write(priv, TC358768_DSI_CONFW, val);
|
||||
|
@ -660,7 +660,7 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
clips = drm_plane_get_damage_clips(new_plane_state);
|
||||
clips = __drm_plane_get_damage_clips(new_plane_state);
|
||||
num_clips = drm_plane_get_damage_clips_count(new_plane_state);
|
||||
|
||||
/* Make sure damage clips are valid and inside the fb. */
|
||||
|
@ -63,8 +63,9 @@
|
||||
|
||||
static bool drm_is_current_master_locked(struct drm_file *fpriv)
|
||||
{
|
||||
lockdep_assert_held_once(&fpriv->minor->dev->master_mutex);
|
||||
|
||||
/* Either drm_device.master_mutex or drm_file.master_lookup_lock
|
||||
* should be held here.
|
||||
*/
|
||||
return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
|
||||
}
|
||||
|
||||
@ -82,9 +83,9 @@ bool drm_is_current_master(struct drm_file *fpriv)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
mutex_lock(&fpriv->minor->dev->master_mutex);
|
||||
spin_lock(&fpriv->master_lookup_lock);
|
||||
ret = drm_is_current_master_locked(fpriv);
|
||||
mutex_unlock(&fpriv->minor->dev->master_mutex);
|
||||
spin_unlock(&fpriv->master_lookup_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -262,6 +262,8 @@ int drm_plane_register_all(struct drm_device *dev);
|
||||
void drm_plane_unregister_all(struct drm_device *dev);
|
||||
int drm_plane_check_pixel_format(struct drm_plane *plane,
|
||||
u32 format, u64 modifier);
|
||||
struct drm_mode_rect *
|
||||
__drm_plane_get_damage_clips(const struct drm_plane_state *state);
|
||||
|
||||
/* drm_bridge.c */
|
||||
void drm_bridge_detach(struct drm_bridge *bridge);
|
||||
|
@ -34,44 +34,6 @@
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
|
||||
/**
|
||||
* DOC: overview
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is an optional plane property which provides a means to
|
||||
* specify a list of damage rectangles on a plane in framebuffer coordinates of
|
||||
* the framebuffer attached to the plane. In current context damage is the area
|
||||
* of plane framebuffer that has changed since last plane update (also called
|
||||
* page-flip), irrespective of whether currently attached framebuffer is same as
|
||||
* framebuffer attached during last plane update or not.
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
|
||||
* to optimize internally especially for virtual devices where each framebuffer
|
||||
* change needs to be transmitted over network, usb, etc.
|
||||
*
|
||||
* Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
|
||||
* ignore damage clips property and in that case driver will do a full plane
|
||||
* update. In case damage clips are provided then it is guaranteed that the area
|
||||
* inside damage clips will be updated to plane. For efficiency driver can do
|
||||
* full update or can update more than specified in damage clips. Since driver
|
||||
* is free to read more, user-space must always render the entire visible
|
||||
* framebuffer. Otherwise there can be corruptions. Also, if a user-space
|
||||
* provides damage clips which doesn't encompass the actual damage to
|
||||
* framebuffer (since last plane update) can result in incorrect rendering.
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
|
||||
* array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
|
||||
* damage clips are not in 16.16 fixed point. Similar to plane src in
|
||||
* framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
|
||||
* inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
|
||||
* damage clips, it is strongly discouraged.
|
||||
*
|
||||
* Drivers that are interested in damage interface for plane should enable
|
||||
* FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
|
||||
* Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
|
||||
* drm_atomic_helper_damage_iter_next() helper iterator function to get damage
|
||||
* rectangles clipped to &drm_plane_state.src.
|
||||
*/
|
||||
|
||||
static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
|
||||
struct drm_mode_rect *dest,
|
||||
uint32_t num_clips, uint32_t src_inc)
|
||||
@ -87,22 +49,6 @@ static void convert_clip_rect_to_rect(const struct drm_clip_rect *src,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
|
||||
* @plane: Plane on which to enable damage clips property.
|
||||
*
|
||||
* This function lets driver to enable the damage clips property on a plane.
|
||||
*/
|
||||
void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
||||
drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
|
||||
0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_check_plane_damage - Verify plane damage on atomic_check.
|
||||
* @state: The driver state object.
|
||||
@ -282,7 +228,7 @@ drm_atomic_helper_damage_iter_init(struct drm_atomic_helper_damage_iter *iter,
|
||||
if (!state || !state->crtc || !state->fb || !state->visible)
|
||||
return;
|
||||
|
||||
iter->clips = drm_helper_get_plane_damage_clips(state);
|
||||
iter->clips = (struct drm_rect *)drm_plane_get_damage_clips(state);
|
||||
iter->num_clips = drm_plane_get_damage_clips_count(state);
|
||||
|
||||
/* Round down for x1/y1 and round up for x2/y2 to catch all pixels */
|
||||
|
@ -2872,11 +2872,13 @@ static int process_single_tx_qlock(struct drm_dp_mst_topology_mgr *mgr,
|
||||
idx += tosend + 1;
|
||||
|
||||
ret = drm_dp_send_sideband_msg(mgr, up, chunk, idx);
|
||||
if (unlikely(ret) && drm_debug_enabled(DRM_UT_DP)) {
|
||||
struct drm_printer p = drm_debug_printer(DBG_PREFIX);
|
||||
if (ret) {
|
||||
if (drm_debug_enabled(DRM_UT_DP)) {
|
||||
struct drm_printer p = drm_debug_printer(DBG_PREFIX);
|
||||
|
||||
drm_printf(&p, "sideband msg failed to send\n");
|
||||
drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
|
||||
drm_printf(&p, "sideband msg failed to send\n");
|
||||
drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -404,6 +404,9 @@ static void drm_mode_rmfb_work_fn(struct work_struct *w)
|
||||
struct drm_framebuffer *fb =
|
||||
list_first_entry(&arg->fbs, typeof(*fb), filp_head);
|
||||
|
||||
drm_dbg_kms(fb->dev,
|
||||
"Removing [FB:%d] from all active usage due to RMFB ioctl\n",
|
||||
fb->base.id);
|
||||
list_del_init(&fb->filp_head);
|
||||
drm_framebuffer_remove(fb);
|
||||
}
|
||||
@ -981,6 +984,10 @@ retry:
|
||||
if (plane->state->fb != fb)
|
||||
continue;
|
||||
|
||||
drm_dbg_kms(dev,
|
||||
"Disabling [PLANE:%d:%s] because [FB:%d] is removed\n",
|
||||
plane->base.id, plane->name, fb->base.id);
|
||||
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state)) {
|
||||
ret = PTR_ERR(plane_state);
|
||||
@ -990,6 +997,11 @@ retry:
|
||||
if (disable_crtcs && plane_state->crtc->primary == plane) {
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
drm_dbg_kms(dev,
|
||||
"Disabling [CRTC:%d:%s] because [FB:%d] is removed\n",
|
||||
plane_state->crtc->base.id,
|
||||
plane_state->crtc->name, fb->base.id);
|
||||
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, plane_state->crtc);
|
||||
|
||||
ret = drm_atomic_add_affected_connectors(state, plane_state->crtc);
|
||||
@ -1052,6 +1064,10 @@ static void legacy_remove_fb(struct drm_framebuffer *fb)
|
||||
/* remove from any CRTC */
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (crtc->primary->fb == fb) {
|
||||
drm_dbg_kms(dev,
|
||||
"Disabling [CRTC:%d:%s] because [FB:%d] is removed\n",
|
||||
crtc->base.id, crtc->name, fb->base.id);
|
||||
|
||||
/* should turn off the crtc */
|
||||
if (drm_crtc_force_disable(crtc))
|
||||
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
|
||||
@ -1059,8 +1075,12 @@ static void legacy_remove_fb(struct drm_framebuffer *fb)
|
||||
}
|
||||
|
||||
drm_for_each_plane(plane, dev) {
|
||||
if (plane->fb == fb)
|
||||
if (plane->fb == fb) {
|
||||
drm_dbg_kms(dev,
|
||||
"Disabling [PLANE:%d:%s] because [FB:%d] is removed\n",
|
||||
plane->base.id, plane->name, fb->base.id);
|
||||
drm_plane_force_disable(plane);
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
|
@ -306,6 +306,95 @@ drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty);
|
||||
|
||||
/**
|
||||
* drm_gem_fb_begin_cpu_access - prepares GEM buffer objects for CPU access
|
||||
* @fb: the framebuffer
|
||||
* @dir: access mode
|
||||
*
|
||||
* Prepares a framebuffer's GEM buffer objects for CPU access. This function
|
||||
* must be called before accessing the BO data within the kernel. For imported
|
||||
* BOs, the function calls dma_buf_begin_cpu_access().
|
||||
*
|
||||
* See drm_gem_fb_end_cpu_access() for signalling the end of CPU access.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative errno code otherwise.
|
||||
*/
|
||||
int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
|
||||
{
|
||||
struct dma_buf_attachment *import_attach;
|
||||
struct drm_gem_object *obj;
|
||||
size_t i;
|
||||
int ret, ret2;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fb->obj); ++i) {
|
||||
obj = drm_gem_fb_get_obj(fb, i);
|
||||
if (!obj)
|
||||
continue;
|
||||
import_attach = obj->import_attach;
|
||||
if (!import_attach)
|
||||
continue;
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf, dir);
|
||||
if (ret)
|
||||
goto err_dma_buf_end_cpu_access;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_dma_buf_end_cpu_access:
|
||||
while (i) {
|
||||
--i;
|
||||
obj = drm_gem_fb_get_obj(fb, i);
|
||||
if (!obj)
|
||||
continue;
|
||||
import_attach = obj->import_attach;
|
||||
if (!import_attach)
|
||||
continue;
|
||||
ret2 = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
|
||||
if (ret2) {
|
||||
drm_err(fb->dev,
|
||||
"dma_buf_end_cpu_access() failed during error handling: %d\n",
|
||||
ret2);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_fb_begin_cpu_access);
|
||||
|
||||
/**
|
||||
* drm_gem_fb_end_cpu_access - signals end of CPU access to GEM buffer objects
|
||||
* @fb: the framebuffer
|
||||
* @dir: access mode
|
||||
*
|
||||
* Signals the end of CPU access to the given framebuffer's GEM buffer objects. This
|
||||
* function must be paired with a corresponding call to drm_gem_fb_begin_cpu_access().
|
||||
* For imported BOs, the function calls dma_buf_end_cpu_access().
|
||||
*
|
||||
* See also drm_gem_fb_begin_cpu_access().
|
||||
*/
|
||||
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir)
|
||||
{
|
||||
size_t i = ARRAY_SIZE(fb->obj);
|
||||
struct dma_buf_attachment *import_attach;
|
||||
struct drm_gem_object *obj;
|
||||
int ret;
|
||||
|
||||
while (i) {
|
||||
--i;
|
||||
obj = drm_gem_fb_get_obj(fb, i);
|
||||
if (!obj)
|
||||
continue;
|
||||
import_attach = obj->import_attach;
|
||||
if (!import_attach)
|
||||
continue;
|
||||
ret = dma_buf_end_cpu_access(import_attach->dmabuf, dir);
|
||||
if (ret)
|
||||
drm_err(fb->dev, "dma_buf_end_cpu_access() failed: %d\n", ret);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);
|
||||
|
||||
static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
|
@ -15,6 +15,57 @@
|
||||
#include "drm_crtc_internal.h"
|
||||
#include "drm_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: drm leasing
|
||||
*
|
||||
* DRM leases provide information about whether a DRM master may control a DRM
|
||||
* mode setting object. This enables the creation of multiple DRM masters that
|
||||
* manage subsets of display resources.
|
||||
*
|
||||
* The original DRM master of a device 'owns' the available drm resources. It
|
||||
* may create additional DRM masters and 'lease' resources which it controls
|
||||
* to the new DRM master. This gives the new DRM master control over the
|
||||
* leased resources until the owner revokes the lease, or the new DRM master
|
||||
* is closed. Some helpful terminology:
|
||||
*
|
||||
* - An 'owner' is a &struct drm_master that is not leasing objects from
|
||||
* another &struct drm_master, and hence 'owns' the objects. The owner can be
|
||||
* identified as the &struct drm_master for which &drm_master.lessor is NULL.
|
||||
*
|
||||
* - A 'lessor' is a &struct drm_master which is leasing objects to one or more
|
||||
* other &struct drm_master. Currently, lessees are not allowed to
|
||||
* create sub-leases, hence the lessor is the same as the owner.
|
||||
*
|
||||
* - A 'lessee' is a &struct drm_master which is leasing objects from some
|
||||
* other &struct drm_master. Each lessee only leases resources from a single
|
||||
* lessor recorded in &drm_master.lessor, and holds the set of objects that
|
||||
* it is leasing in &drm_master.leases.
|
||||
*
|
||||
* - A 'lease' is a contract between the lessor and lessee that identifies
|
||||
* which resources may be controlled by the lessee. All of the resources
|
||||
* that are leased must be owned by or leased to the lessor, and lessors are
|
||||
* not permitted to lease the same object to multiple lessees.
|
||||
*
|
||||
* The set of objects any &struct drm_master 'controls' is limited to the set
|
||||
* of objects it leases (for lessees) or all objects (for owners).
|
||||
*
|
||||
* Objects not controlled by a &struct drm_master cannot be modified through
|
||||
* the various state manipulating ioctls, and any state reported back to user
|
||||
* space will be edited to make them appear idle and/or unusable. For
|
||||
* instance, connectors always report 'disconnected', while encoders
|
||||
* report no possible crtcs or clones.
|
||||
*
|
||||
* Since each lessee may lease objects from a single lessor, display resource
|
||||
* leases form a tree of &struct drm_master. As lessees are currently not
|
||||
* allowed to create sub-leases, the tree depth is limited to 1. All of
|
||||
* these get activated simultaneously when the top level device owner changes
|
||||
* through the SETMASTER or DROPMASTER IOCTL, so &drm_device.master points to
|
||||
* the owner at the top of the lease tree (i.e. the &struct drm_master for which
|
||||
* &drm_master.lessor is NULL). The full list of lessees that are leasing
|
||||
* objects from the owner can be searched via the owner's
|
||||
* &drm_master.lessee_idr.
|
||||
*/
|
||||
|
||||
#define drm_for_each_lessee(lessee, lessor) \
|
||||
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
@ -202,21 +201,17 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
|
||||
{
|
||||
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
|
||||
struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem);
|
||||
struct dma_buf_attachment *import_attach = gem->import_attach;
|
||||
void *src = cma_obj->vaddr;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_RGB565:
|
||||
if (swap)
|
||||
drm_fb_swab(dst, src, fb, clip, !import_attach);
|
||||
drm_fb_swab(dst, src, fb, clip, !gem->import_attach);
|
||||
else
|
||||
drm_fb_memcpy(dst, src, fb, clip);
|
||||
break;
|
||||
@ -229,9 +224,8 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (import_attach)
|
||||
ret = dma_buf_end_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(mipi_dbi_buf_copy);
|
||||
|
@ -1397,6 +1397,110 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: damage tracking
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is an optional plane property which provides a means to
|
||||
* specify a list of damage rectangles on a plane in framebuffer coordinates of
|
||||
* the framebuffer attached to the plane. In current context damage is the area
|
||||
* of plane framebuffer that has changed since last plane update (also called
|
||||
* page-flip), irrespective of whether currently attached framebuffer is same as
|
||||
* framebuffer attached during last plane update or not.
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is a hint to kernel which could be helpful for some drivers
|
||||
* to optimize internally especially for virtual devices where each framebuffer
|
||||
* change needs to be transmitted over network, usb, etc.
|
||||
*
|
||||
* Since FB_DAMAGE_CLIPS is a hint so it is an optional property. User-space can
|
||||
* ignore damage clips property and in that case driver will do a full plane
|
||||
* update. In case damage clips are provided then it is guaranteed that the area
|
||||
* inside damage clips will be updated to plane. For efficiency driver can do
|
||||
* full update or can update more than specified in damage clips. Since driver
|
||||
* is free to read more, user-space must always render the entire visible
|
||||
* framebuffer. Otherwise there can be corruptions. Also, if a user-space
|
||||
* provides damage clips which doesn't encompass the actual damage to
|
||||
* framebuffer (since last plane update) can result in incorrect rendering.
|
||||
*
|
||||
* FB_DAMAGE_CLIPS is a blob property with the layout of blob data is simply an
|
||||
* array of &drm_mode_rect. Unlike plane &drm_plane_state.src coordinates,
|
||||
* damage clips are not in 16.16 fixed point. Similar to plane src in
|
||||
* framebuffer, damage clips cannot be negative. In damage clip, x1/y1 are
|
||||
* inclusive and x2/y2 are exclusive. While kernel does not error for overlapped
|
||||
* damage clips, it is strongly discouraged.
|
||||
*
|
||||
* Drivers that are interested in damage interface for plane should enable
|
||||
* FB_DAMAGE_CLIPS property by calling drm_plane_enable_fb_damage_clips().
|
||||
* Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and
|
||||
* drm_atomic_helper_damage_iter_next() helper iterator function to get damage
|
||||
* rectangles clipped to &drm_plane_state.src.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_plane_enable_fb_damage_clips - Enables plane fb damage clips property.
|
||||
* @plane: Plane on which to enable damage clips property.
|
||||
*
|
||||
* This function lets driver to enable the damage clips property on a plane.
|
||||
*/
|
||||
void drm_plane_enable_fb_damage_clips(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
||||
drm_object_attach_property(&plane->base, config->prop_fb_damage_clips,
|
||||
0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_enable_fb_damage_clips);
|
||||
|
||||
/**
|
||||
* drm_plane_get_damage_clips_count - Returns damage clips count.
|
||||
* @state: Plane state.
|
||||
*
|
||||
* Simple helper to get the number of &drm_mode_rect clips set by user-space
|
||||
* during plane update.
|
||||
*
|
||||
* Return: Number of clips in plane fb_damage_clips blob property.
|
||||
*/
|
||||
unsigned int
|
||||
drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
|
||||
{
|
||||
return (state && state->fb_damage_clips) ?
|
||||
state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_get_damage_clips_count);
|
||||
|
||||
struct drm_mode_rect *
|
||||
__drm_plane_get_damage_clips(const struct drm_plane_state *state)
|
||||
{
|
||||
return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
|
||||
state->fb_damage_clips->data : NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_get_damage_clips - Returns damage clips.
|
||||
* @state: Plane state.
|
||||
*
|
||||
* Note that this function returns uapi type &drm_mode_rect. Drivers might want
|
||||
* to use the helper functions drm_atomic_helper_damage_iter_init() and
|
||||
* drm_atomic_helper_damage_iter_next() or drm_atomic_helper_damage_merged() if
|
||||
* the driver can only handle a single damage region at most.
|
||||
*
|
||||
* Return: Damage clips in plane fb_damage_clips blob property.
|
||||
*/
|
||||
struct drm_mode_rect *
|
||||
drm_plane_get_damage_clips(const struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_device *dev = state->plane->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
||||
/* check that drm_plane_enable_fb_damage_clips() was called */
|
||||
if (!drm_mode_obj_find_prop_id(&state->plane->base,
|
||||
config->prop_fb_damage_clips->base.id))
|
||||
drm_warn_once(dev, "drm_plane_enable_fb_damage_clips() not called\n");
|
||||
|
||||
return __drm_plane_get_damage_clips(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_get_damage_clips);
|
||||
|
||||
struct drm_property *
|
||||
drm_create_scaling_filter_prop(struct drm_device *dev,
|
||||
unsigned int supported_filters)
|
||||
|
@ -549,7 +549,7 @@ int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data,
|
||||
*
|
||||
* FIXME: The underlying helper functions are named rather inconsistently.
|
||||
*
|
||||
* Exporting buffers
|
||||
* Importing buffers
|
||||
* ~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Importing dma-bufs using drm_gem_prime_import() relies on
|
||||
|
@ -809,15 +809,15 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
|
||||
reg |= DSIM_AUTO_MODE;
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSE)
|
||||
reg |= DSIM_HSE_MODE;
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HFP))
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HFP))
|
||||
reg |= DSIM_HFP_MODE;
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HBP))
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HBP))
|
||||
reg |= DSIM_HBP_MODE;
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_HSA))
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_NO_HSA))
|
||||
reg |= DSIM_HSA_MODE;
|
||||
}
|
||||
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
reg |= DSIM_EOT_DISABLE;
|
||||
|
||||
switch (dsi->format) {
|
||||
|
@ -3,7 +3,6 @@
|
||||
* Copyright 2020 Noralf Trønnes
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/lz4.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -15,6 +14,7 @@
|
||||
#include <drm/drm_format_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_shmem_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_rect.h>
|
||||
@ -168,11 +168,9 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
|
||||
|
||||
vaddr = map.vaddr + fb->offsets[0];
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
goto vunmap;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
goto vunmap;
|
||||
retry:
|
||||
if (compression)
|
||||
buf = gdrm->compress_buf;
|
||||
@ -225,8 +223,7 @@ retry:
|
||||
}
|
||||
|
||||
end_cpu_access:
|
||||
if (import_attach)
|
||||
dma_buf_end_cpu_access(import_attach->dmabuf, DMA_FROM_DEVICE);
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
vunmap:
|
||||
drm_gem_shmem_vunmap(fb->obj[0], &map);
|
||||
|
||||
|
@ -249,7 +249,6 @@ static int hibmc_hw_init(struct hibmc_drm_private *priv)
|
||||
|
||||
static int hibmc_unload(struct drm_device *dev)
|
||||
{
|
||||
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
|
||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
|
@ -760,7 +760,7 @@ static void mcde_dsi_start(struct mcde_dsi *d)
|
||||
DSI_MCTL_MAIN_DATA_CTL_BTA_EN |
|
||||
DSI_MCTL_MAIN_DATA_CTL_READ_EN |
|
||||
DSI_MCTL_MAIN_DATA_CTL_REG_TE_EN;
|
||||
if (!(d->mdsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(d->mdsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
val |= DSI_MCTL_MAIN_DATA_CTL_HOST_EOT_GEN;
|
||||
writel(val, d->regs + DSI_MCTL_MAIN_DATA_CTL);
|
||||
|
||||
|
@ -404,7 +404,7 @@ static void mtk_dsi_rxtx_control(struct mtk_dsi *dsi)
|
||||
if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
|
||||
tmp_reg |= HSTX_CKLP_EN;
|
||||
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
tmp_reg |= DIS_EOT;
|
||||
|
||||
writel(tmp_reg, dsi->regs + DSI_TXRX_CTRL);
|
||||
@ -481,7 +481,7 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
|
||||
timing->da_hs_zero + timing->da_hs_exit + 3;
|
||||
|
||||
delta = dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST ? 18 : 12;
|
||||
delta += dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET ? 2 : 0;
|
||||
delta += dsi->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET ? 2 : 0;
|
||||
|
||||
horizontal_frontporch_byte = vm->hfront_porch * dsi_tmp_buf_bpp;
|
||||
horizontal_front_back_byte = horizontal_frontporch_byte + horizontal_backporch_byte;
|
||||
|
@ -849,11 +849,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
|
||||
if (flags & MIPI_DSI_MODE_VIDEO) {
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_HSE)
|
||||
data |= DSI_VID_CFG0_PULSE_MODE_HSA_HE;
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_HFP)
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_NO_HFP)
|
||||
data |= DSI_VID_CFG0_HFP_POWER_STOP;
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_HBP)
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_NO_HBP)
|
||||
data |= DSI_VID_CFG0_HBP_POWER_STOP;
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_HSA)
|
||||
if (flags & MIPI_DSI_MODE_VIDEO_NO_HSA)
|
||||
data |= DSI_VID_CFG0_HSA_POWER_STOP;
|
||||
/* Always set low power stop mode for BLLP
|
||||
* to let command engine send packets
|
||||
@ -908,7 +908,7 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
|
||||
DSI_T_CLK_PRE_EXTEND_INC_BY_2_BYTECLK);
|
||||
|
||||
data = 0;
|
||||
if (!(flags & MIPI_DSI_MODE_EOT_PACKET))
|
||||
if (!(flags & MIPI_DSI_MODE_NO_EOT_PACKET))
|
||||
data |= DSI_EOT_PACKET_CTRL_TX_EOT_APPEND;
|
||||
dsi_write(msm_host, REG_DSI_EOT_PACKET_CTRL, data);
|
||||
|
||||
|
@ -51,6 +51,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
|
||||
.hs_wdth_mask = 0xff,
|
||||
.hs_wdth_shift = 24,
|
||||
.has_overlay = false,
|
||||
.has_ctrl2 = false,
|
||||
},
|
||||
[MXSFB_V4] = {
|
||||
.transfer_count = LCDC_V4_TRANSFER_COUNT,
|
||||
@ -59,6 +60,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
|
||||
.hs_wdth_mask = 0x3fff,
|
||||
.hs_wdth_shift = 18,
|
||||
.has_overlay = false,
|
||||
.has_ctrl2 = true,
|
||||
},
|
||||
[MXSFB_V6] = {
|
||||
.transfer_count = LCDC_V4_TRANSFER_COUNT,
|
||||
@ -67,6 +69,7 @@ static const struct mxsfb_devdata mxsfb_devdata[] = {
|
||||
.hs_wdth_mask = 0x3fff,
|
||||
.hs_wdth_shift = 18,
|
||||
.has_overlay = true,
|
||||
.has_ctrl2 = true,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,7 @@ struct mxsfb_devdata {
|
||||
unsigned int hs_wdth_mask;
|
||||
unsigned int hs_wdth_shift;
|
||||
bool has_overlay;
|
||||
bool has_ctrl2;
|
||||
};
|
||||
|
||||
struct mxsfb_drm_private {
|
||||
|
@ -47,16 +47,13 @@ static u32 set_hsync_pulse_width(struct mxsfb_drm_private *mxsfb, u32 val)
|
||||
* Setup the MXSFB registers for decoding the pixels out of the framebuffer and
|
||||
* outputting them on the bus.
|
||||
*/
|
||||
static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb)
|
||||
static void mxsfb_set_formats(struct mxsfb_drm_private *mxsfb,
|
||||
const u32 bus_format)
|
||||
{
|
||||
struct drm_device *drm = mxsfb->drm;
|
||||
const u32 format = mxsfb->crtc.primary->state->fb->format->format;
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
u32 ctrl, ctrl1;
|
||||
|
||||
if (mxsfb->connector->display_info.num_bus_formats)
|
||||
bus_format = mxsfb->connector->display_info.bus_formats[0];
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "Using bus_format: 0x%08X\n",
|
||||
bus_format);
|
||||
|
||||
@ -107,6 +104,14 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
|
||||
clk_prepare_enable(mxsfb->clk_disp_axi);
|
||||
clk_prepare_enable(mxsfb->clk);
|
||||
|
||||
/* Increase number of outstanding requests on all supported IPs */
|
||||
if (mxsfb->devdata->has_ctrl2) {
|
||||
reg = readl(mxsfb->base + LCDC_V4_CTRL2);
|
||||
reg &= ~CTRL2_SET_OUTSTANDING_REQS_MASK;
|
||||
reg |= CTRL2_SET_OUTSTANDING_REQS_16;
|
||||
writel(reg, mxsfb->base + LCDC_V4_CTRL2);
|
||||
}
|
||||
|
||||
/* If it was disabled, re-enable the mode again */
|
||||
writel(CTRL_DOTCLK_MODE, mxsfb->base + LCDC_CTRL + REG_SET);
|
||||
|
||||
@ -115,6 +120,35 @@ static void mxsfb_enable_controller(struct mxsfb_drm_private *mxsfb)
|
||||
reg |= VDCTRL4_SYNC_SIGNALS_ON;
|
||||
writel(reg, mxsfb->base + LCDC_VDCTRL4);
|
||||
|
||||
/*
|
||||
* Enable recovery on underflow.
|
||||
*
|
||||
* There is some sort of corner case behavior of the controller,
|
||||
* which could rarely be triggered at least on i.MX6SX connected
|
||||
* to 800x480 DPI panel and i.MX8MM connected to DPI->DSI->LVDS
|
||||
* bridged 1920x1080 panel (and likely on other setups too), where
|
||||
* the image on the panel shifts to the right and wraps around.
|
||||
* This happens either when the controller is enabled on boot or
|
||||
* even later during run time. The condition does not correct
|
||||
* itself automatically, i.e. the display image remains shifted.
|
||||
*
|
||||
* It seems this problem is known and is due to sporadic underflows
|
||||
* of the LCDIF FIFO. While the LCDIF IP does have underflow/overflow
|
||||
* IRQs, neither of the IRQs trigger and neither IRQ status bit is
|
||||
* asserted when this condition occurs.
|
||||
*
|
||||
* All known revisions of the LCDIF IP have CTRL1 RECOVER_ON_UNDERFLOW
|
||||
* bit, which is described in the reference manual since i.MX23 as
|
||||
* "
|
||||
* Set this bit to enable the LCDIF block to recover in the next
|
||||
* field/frame if there was an underflow in the current field/frame.
|
||||
* "
|
||||
* Enable this bit to mitigate the sporadic underflows.
|
||||
*/
|
||||
reg = readl(mxsfb->base + LCDC_CTRL1);
|
||||
reg |= CTRL1_RECOVER_ON_UNDERFLOW;
|
||||
writel(reg, mxsfb->base + LCDC_CTRL1);
|
||||
|
||||
writel(CTRL_RUN, mxsfb->base + LCDC_CTRL + REG_SET);
|
||||
}
|
||||
|
||||
@ -185,7 +219,8 @@ static dma_addr_t mxsfb_get_fb_paddr(struct drm_plane *plane)
|
||||
return gem->paddr;
|
||||
}
|
||||
|
||||
static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
|
||||
static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb,
|
||||
const u32 bus_format)
|
||||
{
|
||||
struct drm_device *drm = mxsfb->crtc.dev;
|
||||
struct drm_display_mode *m = &mxsfb->crtc.state->adjusted_mode;
|
||||
@ -206,11 +241,14 @@ static void mxsfb_crtc_mode_set_nofb(struct mxsfb_drm_private *mxsfb)
|
||||
|
||||
/* Clear the FIFOs */
|
||||
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_SET);
|
||||
readl(mxsfb->base + LCDC_CTRL1);
|
||||
writel(CTRL1_FIFO_CLEAR, mxsfb->base + LCDC_CTRL1 + REG_CLR);
|
||||
readl(mxsfb->base + LCDC_CTRL1);
|
||||
|
||||
if (mxsfb->devdata->has_overlay)
|
||||
writel(0, mxsfb->base + LCDC_AS_CTRL);
|
||||
|
||||
mxsfb_set_formats(mxsfb);
|
||||
mxsfb_set_formats(mxsfb, bus_format);
|
||||
|
||||
clk_set_rate(mxsfb->clk, m->crtc_clock * 1000);
|
||||
|
||||
@ -308,7 +346,9 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mxsfb_drm_private *mxsfb = to_mxsfb_drm_private(crtc->dev);
|
||||
struct drm_bridge_state *bridge_state;
|
||||
struct drm_device *drm = mxsfb->drm;
|
||||
u32 bus_format = 0;
|
||||
dma_addr_t paddr;
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
@ -316,7 +356,23 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
|
||||
drm_crtc_vblank_on(crtc);
|
||||
|
||||
mxsfb_crtc_mode_set_nofb(mxsfb);
|
||||
/* If there is a bridge attached to the LCDIF, use its bus format */
|
||||
if (mxsfb->bridge) {
|
||||
bridge_state =
|
||||
drm_atomic_get_new_bridge_state(state,
|
||||
mxsfb->bridge);
|
||||
bus_format = bridge_state->input_bus_cfg.format;
|
||||
}
|
||||
|
||||
/* If there is no bridge, use bus format from connector */
|
||||
if (!bus_format && mxsfb->connector->display_info.num_bus_formats)
|
||||
bus_format = mxsfb->connector->display_info.bus_formats[0];
|
||||
|
||||
/* If all else fails, default to RGB888_1X24 */
|
||||
if (!bus_format)
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
mxsfb_crtc_mode_set_nofb(mxsfb, bus_format);
|
||||
|
||||
/* Write cur_buf as well to avoid an initial corrupt frame */
|
||||
paddr = mxsfb_get_fb_paddr(crtc->primary);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LCDC_CTRL 0x00
|
||||
#define LCDC_CTRL1 0x10
|
||||
#define LCDC_V3_TRANSFER_COUNT 0x20
|
||||
#define LCDC_V4_CTRL2 0x20
|
||||
#define LCDC_V4_TRANSFER_COUNT 0x30
|
||||
#define LCDC_V4_CUR_BUF 0x40
|
||||
#define LCDC_V4_NEXT_BUF 0x50
|
||||
@ -54,12 +55,20 @@
|
||||
#define CTRL_DF24 BIT(1)
|
||||
#define CTRL_RUN BIT(0)
|
||||
|
||||
#define CTRL1_RECOVER_ON_UNDERFLOW BIT(24)
|
||||
#define CTRL1_FIFO_CLEAR BIT(21)
|
||||
#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16)
|
||||
#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf)
|
||||
#define CTRL1_CUR_FRAME_DONE_IRQ_EN BIT(13)
|
||||
#define CTRL1_CUR_FRAME_DONE_IRQ BIT(9)
|
||||
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_1 0
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_2 (0x1 << 21)
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_4 (0x2 << 21)
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_8 (0x3 << 21)
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_16 (0x4 << 21)
|
||||
#define CTRL2_SET_OUTSTANDING_REQS_MASK (0x7 << 21)
|
||||
|
||||
#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16)
|
||||
#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff)
|
||||
#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff)
|
||||
|
@ -302,7 +302,7 @@ static int tm5p5_nt35596_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM;
|
||||
|
||||
drm_panel_init(&ctx->panel, dev, &tm5p5_nt35596_panel_funcs,
|
||||
|
@ -574,7 +574,7 @@ static int dsicm_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 2;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
dsi->hs_rate = ddata->panel_data->max_hs_rate;
|
||||
dsi->lp_rate = ddata->panel_data->max_lp_rate;
|
||||
|
||||
|
@ -273,7 +273,7 @@ static int kd35t133_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 1;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &kd35t133_funcs,
|
||||
|
@ -809,7 +809,7 @@ static int khadas_ts050_panel_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
khadas_ts050 = devm_kzalloc(&dsi->dev, sizeof(*khadas_ts050),
|
||||
GFP_KERNEL);
|
||||
|
@ -593,7 +593,7 @@ static int ltk050h3146w_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, <k050h3146w_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
@ -442,7 +442,7 @@ static int ltk500hd1829_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, <k500hd1829_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
@ -184,7 +184,7 @@ static int osd101t2587_panel_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
||||
MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
osd101t2587 = devm_kzalloc(&dsi->dev, sizeof(*osd101t2587), GFP_KERNEL);
|
||||
if (!osd101t2587)
|
||||
|
@ -446,7 +446,7 @@ static int s6e63j0x03_probe(struct mipi_dsi_device *dsi)
|
||||
|
||||
dsi->lanes = 1;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_EOT_PACKET;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
ctx->supplies[0].supply = "vdd3";
|
||||
ctx->supplies[1].supply = "vci";
|
||||
|
@ -990,8 +990,8 @@ static int s6e8aa0_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST
|
||||
| MIPI_DSI_MODE_VIDEO_HFP | MIPI_DSI_MODE_VIDEO_HBP
|
||||
| MIPI_DSI_MODE_VIDEO_HSA | MIPI_DSI_MODE_EOT_PACKET
|
||||
| MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP
|
||||
| MIPI_DSI_MODE_VIDEO_NO_HSA | MIPI_DSI_MODE_NO_EOT_PACKET
|
||||
| MIPI_DSI_MODE_VSYNC_FLUSH | MIPI_DSI_MODE_VIDEO_AUTO_VERT;
|
||||
|
||||
ret = s6e8aa0_parse_dt(ctx);
|
||||
|
@ -282,7 +282,7 @@ static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
|
||||
MIPI_DSI_MODE_VIDEO_HSE |
|
||||
MIPI_DSI_CLOCK_NON_CONTINUOUS |
|
||||
MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL);
|
||||
if (!sharp_nt)
|
||||
|
@ -1122,6 +1122,36 @@ static const struct panel_desc auo_b133xtn01 = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_b133han05_mode = {
|
||||
.clock = 142600,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 58,
|
||||
.hsync_end = 1920 + 58 + 42,
|
||||
.htotal = 1920 + 58 + 42 + 60,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 5,
|
||||
.vtotal = 1080 + 3 + 5 + 54,
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_b133han05 = {
|
||||
.modes = &auo_b133han05_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 293,
|
||||
.height = 165,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 100,
|
||||
.enable = 20,
|
||||
.unprepare = 50,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_b133htn01_mode = {
|
||||
.clock = 150660,
|
||||
.hdisplay = 1920,
|
||||
@ -1149,6 +1179,36 @@ static const struct panel_desc auo_b133htn01 = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct drm_display_mode auo_b140han06_mode = {
|
||||
.clock = 141000,
|
||||
.hdisplay = 1920,
|
||||
.hsync_start = 1920 + 16,
|
||||
.hsync_end = 1920 + 16 + 16,
|
||||
.htotal = 1920 + 16 + 16 + 152,
|
||||
.vdisplay = 1080,
|
||||
.vsync_start = 1080 + 3,
|
||||
.vsync_end = 1080 + 3 + 14,
|
||||
.vtotal = 1080 + 3 + 14 + 19,
|
||||
};
|
||||
|
||||
static const struct panel_desc auo_b140han06 = {
|
||||
.modes = &auo_b140han06_mode,
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 309,
|
||||
.height = 174,
|
||||
},
|
||||
.delay = {
|
||||
.prepare = 100,
|
||||
.enable = 20,
|
||||
.unprepare = 50,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB,
|
||||
.connector_type = DRM_MODE_CONNECTOR_eDP,
|
||||
};
|
||||
|
||||
static const struct display_timing auo_g070vvn01_timings = {
|
||||
.pixelclock = { 33300000, 34209000, 45000000 },
|
||||
.hactive = { 800, 800, 800 },
|
||||
@ -4363,9 +4423,15 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "auo,b116xw03",
|
||||
.data = &auo_b116xw03,
|
||||
}, {
|
||||
.compatible = "auo,b133han05",
|
||||
.data = &auo_b133han05,
|
||||
}, {
|
||||
.compatible = "auo,b133htn01",
|
||||
.data = &auo_b133htn01,
|
||||
}, {
|
||||
.compatible = "auo,b140han06",
|
||||
.data = &auo_b140han06,
|
||||
}, {
|
||||
.compatible = "auo,b133xtn01",
|
||||
.data = &auo_b133xtn01,
|
||||
@ -5006,7 +5072,7 @@ static const struct panel_desc_dsi osd101t2045_53ts = {
|
||||
},
|
||||
.flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
|
||||
MIPI_DSI_MODE_EOT_PACKET,
|
||||
MIPI_DSI_MODE_NO_EOT_PACKET,
|
||||
.format = MIPI_DSI_FMT_RGB888,
|
||||
.lanes = 4,
|
||||
};
|
||||
|
@ -40,7 +40,6 @@
|
||||
struct acx424akp {
|
||||
struct drm_panel panel;
|
||||
struct device *dev;
|
||||
struct backlight_device *bl;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *reset_gpio;
|
||||
bool video_mode;
|
||||
@ -102,6 +101,18 @@ static int acx424akp_set_brightness(struct backlight_device *bl)
|
||||
u8 par;
|
||||
int ret;
|
||||
|
||||
if (backlight_is_blank(bl)) {
|
||||
/* Disable backlight */
|
||||
par = 0x00;
|
||||
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
|
||||
&par, 1);
|
||||
if (ret) {
|
||||
dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate the PWM duty cycle in n/256's */
|
||||
pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
|
||||
pwm_div = max(1,
|
||||
@ -172,6 +183,12 @@ static const struct backlight_ops acx424akp_bl_ops = {
|
||||
.update_status = acx424akp_set_brightness,
|
||||
};
|
||||
|
||||
static const struct backlight_properties acx424akp_bl_props = {
|
||||
.type = BACKLIGHT_RAW,
|
||||
.brightness = 512,
|
||||
.max_brightness = 1023,
|
||||
};
|
||||
|
||||
static int acx424akp_read_id(struct acx424akp *acx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
|
||||
@ -310,8 +327,6 @@ static int acx424akp_prepare(struct drm_panel *panel)
|
||||
}
|
||||
}
|
||||
|
||||
acx->bl->props.power = FB_BLANK_NORMAL;
|
||||
|
||||
return 0;
|
||||
|
||||
err_power_off:
|
||||
@ -323,18 +338,8 @@ static int acx424akp_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct acx424akp *acx = panel_to_acx424akp(panel);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
|
||||
u8 par;
|
||||
int ret;
|
||||
|
||||
/* Disable backlight */
|
||||
par = 0x00;
|
||||
ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
|
||||
&par, 1);
|
||||
if (ret) {
|
||||
dev_err(acx->dev, "failed to disable display backlight (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret) {
|
||||
dev_err(acx->dev, "failed to turn display off (%d)\n", ret);
|
||||
@ -350,36 +355,10 @@ static int acx424akp_unprepare(struct drm_panel *panel)
|
||||
msleep(85);
|
||||
|
||||
acx424akp_power_off(acx);
|
||||
acx->bl->props.power = FB_BLANK_POWERDOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acx424akp_enable(struct drm_panel *panel)
|
||||
{
|
||||
struct acx424akp *acx = panel_to_acx424akp(panel);
|
||||
|
||||
/*
|
||||
* The backlight is on as long as the display is on
|
||||
* so no use to call backlight_enable() here.
|
||||
*/
|
||||
acx->bl->props.power = FB_BLANK_UNBLANK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acx424akp_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct acx424akp *acx = panel_to_acx424akp(panel);
|
||||
|
||||
/*
|
||||
* The backlight is on as long as the display is on
|
||||
* so no use to call backlight_disable() here.
|
||||
*/
|
||||
acx->bl->props.power = FB_BLANK_NORMAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acx424akp_get_modes(struct drm_panel *panel,
|
||||
struct drm_connector *connector)
|
||||
@ -409,10 +388,8 @@ static int acx424akp_get_modes(struct drm_panel *panel,
|
||||
}
|
||||
|
||||
static const struct drm_panel_funcs acx424akp_drm_funcs = {
|
||||
.disable = acx424akp_disable,
|
||||
.unprepare = acx424akp_unprepare,
|
||||
.prepare = acx424akp_prepare,
|
||||
.enable = acx424akp_enable,
|
||||
.get_modes = acx424akp_get_modes,
|
||||
};
|
||||
|
||||
@ -458,25 +435,18 @@ static int acx424akp_probe(struct mipi_dsi_device *dsi)
|
||||
/* This asserts RESET by default */
|
||||
acx->reset_gpio = devm_gpiod_get_optional(dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(acx->reset_gpio)) {
|
||||
ret = PTR_ERR(acx->reset_gpio);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "failed to request GPIO (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(acx->reset_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(acx->reset_gpio),
|
||||
"failed to request GPIO\n");
|
||||
|
||||
drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
||||
acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx,
|
||||
&acx424akp_bl_ops, NULL);
|
||||
if (IS_ERR(acx->bl)) {
|
||||
dev_err(dev, "failed to register backlight device\n");
|
||||
return PTR_ERR(acx->bl);
|
||||
}
|
||||
acx->bl->props.max_brightness = 1023;
|
||||
acx->bl->props.brightness = 512;
|
||||
acx->bl->props.power = FB_BLANK_POWERDOWN;
|
||||
acx->panel.backlight = devm_backlight_device_register(dev, "acx424akp", dev, acx,
|
||||
&acx424akp_bl_ops, &acx424akp_bl_props);
|
||||
if (IS_ERR(acx->panel.backlight))
|
||||
return dev_err_probe(dev, PTR_ERR(acx->panel.backlight),
|
||||
"failed to register backlight device\n");
|
||||
|
||||
drm_panel_add(&acx->panel);
|
||||
|
||||
|
@ -311,7 +311,7 @@ static int xpp055c272_probe(struct mipi_dsi_device *dsi)
|
||||
dsi->lanes = 4;
|
||||
dsi->format = MIPI_DSI_FMT_RGB888;
|
||||
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET;
|
||||
MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
|
||||
|
||||
drm_panel_init(&ctx->panel, &dsi->dev, &xpp055c272_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
|
@ -106,7 +106,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
|
||||
if (ret) {
|
||||
/* Continue if the optional regulator is missing */
|
||||
if (ret != -ENODEV) {
|
||||
DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
|
||||
if (ret != -EPROBE_DEFER)
|
||||
DRM_DEV_ERROR(dev, "Couldn't set OPP regulators\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ config DRM_ROCKCHIP
|
||||
select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
|
||||
select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
|
||||
select DRM_RGB if ROCKCHIP_RGB
|
||||
select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
|
||||
select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
|
||||
select SND_SOC_HDMI_CODEC if ROCKCHIP_CDN_DP && SND_SOC
|
||||
help
|
||||
Choose this option if you have a Rockchip soc chipset.
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
@ -125,7 +126,9 @@
|
||||
#define BANDGAP_AND_BIAS_CONTROL 0x20
|
||||
#define TERMINATION_RESISTER_CONTROL 0x21
|
||||
#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22
|
||||
#define HS_RX_CONTROL_OF_LANE_CLK 0x34
|
||||
#define HS_RX_CONTROL_OF_LANE_0 0x44
|
||||
#define HS_RX_CONTROL_OF_LANE_1 0x54
|
||||
#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60
|
||||
#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61
|
||||
#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62
|
||||
@ -137,6 +140,9 @@
|
||||
#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72
|
||||
#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73
|
||||
#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74
|
||||
#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL 0x75
|
||||
#define HS_RX_CONTROL_OF_LANE_2 0x84
|
||||
#define HS_RX_CONTROL_OF_LANE_3 0x94
|
||||
|
||||
#define DW_MIPI_NEEDS_PHY_CFG_CLK BIT(0)
|
||||
#define DW_MIPI_NEEDS_GRF_CLK BIT(1)
|
||||
@ -171,11 +177,19 @@
|
||||
#define RK3399_TXRX_MASTERSLAVEZ BIT(7)
|
||||
#define RK3399_TXRX_ENABLECLK BIT(6)
|
||||
#define RK3399_TXRX_BASEDIR BIT(5)
|
||||
#define RK3399_TXRX_SRC_SEL_ISP0 BIT(4)
|
||||
#define RK3399_TXRX_TURNREQUEST GENMASK(3, 0)
|
||||
|
||||
#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
|
||||
|
||||
#define to_dsi(nm) container_of(nm, struct dw_mipi_dsi_rockchip, nm)
|
||||
|
||||
enum {
|
||||
DW_DSI_USAGE_IDLE,
|
||||
DW_DSI_USAGE_DSI,
|
||||
DW_DSI_USAGE_PHY,
|
||||
};
|
||||
|
||||
enum {
|
||||
BANDGAP_97_07,
|
||||
BANDGAP_98_05,
|
||||
@ -213,6 +227,10 @@ struct rockchip_dw_dsi_chip_data {
|
||||
u32 lanecfg2_grf_reg;
|
||||
u32 lanecfg2;
|
||||
|
||||
int (*dphy_rx_init)(struct phy *phy);
|
||||
int (*dphy_rx_power_on)(struct phy *phy);
|
||||
int (*dphy_rx_power_off)(struct phy *phy);
|
||||
|
||||
unsigned int flags;
|
||||
unsigned int max_data_lanes;
|
||||
};
|
||||
@ -223,6 +241,7 @@ struct dw_mipi_dsi_rockchip {
|
||||
void __iomem *base;
|
||||
|
||||
struct regmap *grf_regmap;
|
||||
struct clk *pclk;
|
||||
struct clk *pllref_clk;
|
||||
struct clk *grf_clk;
|
||||
struct clk *phy_cfg_clk;
|
||||
@ -235,6 +254,12 @@ struct dw_mipi_dsi_rockchip {
|
||||
struct phy *phy;
|
||||
union phy_configure_opts phy_opts;
|
||||
|
||||
/* being a phy for other mipi hosts */
|
||||
unsigned int usage_mode;
|
||||
struct mutex usage_mutex;
|
||||
struct phy *dphy;
|
||||
struct phy_configure_opts_mipi_dphy dphy_config;
|
||||
|
||||
unsigned int lane_mbps; /* per lane */
|
||||
u16 input_div;
|
||||
u16 feedback_div;
|
||||
@ -978,6 +1003,17 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data,
|
||||
struct device *second;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dsi->usage_mutex);
|
||||
|
||||
if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
|
||||
DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dsi->usage_mode = DW_DSI_USAGE_DSI;
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
|
||||
ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_ops);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n",
|
||||
@ -1013,6 +1049,10 @@ static int dw_mipi_dsi_rockchip_host_detach(void *priv_data,
|
||||
|
||||
component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops);
|
||||
|
||||
mutex_lock(&dsi->usage_mutex);
|
||||
dsi->usage_mode = DW_DSI_USAGE_IDLE;
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1021,11 +1061,227 @@ static const struct dw_mipi_dsi_host_ops dw_mipi_dsi_rockchip_host_ops = {
|
||||
.detach = dw_mipi_dsi_rockchip_host_detach,
|
||||
};
|
||||
|
||||
static int dw_mipi_dsi_rockchip_dphy_bind(struct device *dev,
|
||||
struct device *master,
|
||||
void *data)
|
||||
{
|
||||
/*
|
||||
* Nothing to do when used as a dphy.
|
||||
* Just make the rest of Rockchip-DRM happy
|
||||
* by being here.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_rockchip_dphy_unbind(struct device *dev,
|
||||
struct device *master,
|
||||
void *data)
|
||||
{
|
||||
/* Nothing to do when used as a dphy. */
|
||||
}
|
||||
|
||||
static const struct component_ops dw_mipi_dsi_rockchip_dphy_ops = {
|
||||
.bind = dw_mipi_dsi_rockchip_dphy_bind,
|
||||
.unbind = dw_mipi_dsi_rockchip_dphy_unbind,
|
||||
};
|
||||
|
||||
static int dw_mipi_dsi_dphy_init(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&dsi->usage_mutex);
|
||||
|
||||
if (dsi->usage_mode != DW_DSI_USAGE_IDLE) {
|
||||
DRM_DEV_ERROR(dsi->dev, "dsi controller already in use\n");
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dsi->usage_mode = DW_DSI_USAGE_PHY;
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
|
||||
ret = component_add(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
|
||||
if (ret < 0)
|
||||
goto err_graph;
|
||||
|
||||
if (dsi->cdata->dphy_rx_init) {
|
||||
ret = clk_prepare_enable(dsi->pclk);
|
||||
if (ret < 0)
|
||||
goto err_init;
|
||||
|
||||
ret = clk_prepare_enable(dsi->grf_clk);
|
||||
if (ret) {
|
||||
clk_disable_unprepare(dsi->pclk);
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
ret = dsi->cdata->dphy_rx_init(phy);
|
||||
clk_disable_unprepare(dsi->grf_clk);
|
||||
clk_disable_unprepare(dsi->pclk);
|
||||
if (ret < 0)
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_init:
|
||||
component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
|
||||
err_graph:
|
||||
mutex_lock(&dsi->usage_mutex);
|
||||
dsi->usage_mode = DW_DSI_USAGE_IDLE;
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_dphy_exit(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
|
||||
component_del(dsi->dev, &dw_mipi_dsi_rockchip_dphy_ops);
|
||||
|
||||
mutex_lock(&dsi->usage_mutex);
|
||||
dsi->usage_mode = DW_DSI_USAGE_IDLE;
|
||||
mutex_unlock(&dsi->usage_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_dphy_configure(struct phy *phy, union phy_configure_opts *opts)
|
||||
{
|
||||
struct phy_configure_opts_mipi_dphy *config = &opts->mipi_dphy;
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
ret = phy_mipi_dphy_config_validate(&opts->mipi_dphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dsi->dphy_config = *config;
|
||||
dsi->lane_mbps = div_u64(config->hs_clk_rate, 1000 * 1000 * 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_dphy_power_on(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
int i, ret;
|
||||
|
||||
DRM_DEV_DEBUG(dsi->dev, "lanes %d - data_rate_mbps %u\n",
|
||||
dsi->dphy_config.lanes, dsi->lane_mbps);
|
||||
|
||||
i = max_mbps_to_parameter(dsi->lane_mbps);
|
||||
if (i < 0) {
|
||||
DRM_DEV_ERROR(dsi->dev, "failed to get parameter for %dmbps clock\n",
|
||||
dsi->lane_mbps);
|
||||
return i;
|
||||
}
|
||||
|
||||
ret = pm_runtime_get_sync(dsi->dev);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dsi->dev, "failed to enable device: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->pclk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to enable pclk: %d\n", ret);
|
||||
goto err_pclk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->grf_clk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
|
||||
goto err_grf_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(dsi->phy_cfg_clk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to enable phy_cfg_clk: %d\n", ret);
|
||||
goto err_phy_cfg_clk;
|
||||
}
|
||||
|
||||
/* do soc-variant specific init */
|
||||
if (dsi->cdata->dphy_rx_power_on) {
|
||||
ret = dsi->cdata->dphy_rx_power_on(phy);
|
||||
if (ret < 0) {
|
||||
DRM_DEV_ERROR(dsi->dev, "hardware-specific phy bringup failed: %d\n", ret);
|
||||
goto err_pwr_on;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure hsfreqrange according to frequency values
|
||||
* Set clock lane and hsfreqrange by lane0(test code 0x44)
|
||||
*/
|
||||
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_CLK, 0);
|
||||
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
|
||||
HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
|
||||
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_1, 0);
|
||||
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_2, 0);
|
||||
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_3, 0);
|
||||
|
||||
/* Normal operation */
|
||||
dw_mipi_dsi_phy_write(dsi, 0x0, 0);
|
||||
|
||||
clk_disable_unprepare(dsi->phy_cfg_clk);
|
||||
clk_disable_unprepare(dsi->grf_clk);
|
||||
|
||||
return ret;
|
||||
|
||||
err_pwr_on:
|
||||
clk_disable_unprepare(dsi->phy_cfg_clk);
|
||||
err_phy_cfg_clk:
|
||||
clk_disable_unprepare(dsi->grf_clk);
|
||||
err_grf_clk:
|
||||
clk_disable_unprepare(dsi->pclk);
|
||||
err_pclk:
|
||||
pm_runtime_put(dsi->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi_dphy_power_off(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(dsi->grf_clk);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (dsi->cdata->dphy_rx_power_off) {
|
||||
ret = dsi->cdata->dphy_rx_power_off(phy);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(dsi->dev, "hardware-specific phy shutdown failed: %d\n", ret);
|
||||
}
|
||||
|
||||
clk_disable_unprepare(dsi->grf_clk);
|
||||
clk_disable_unprepare(dsi->pclk);
|
||||
|
||||
pm_runtime_put(dsi->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct phy_ops dw_mipi_dsi_dphy_ops = {
|
||||
.configure = dw_mipi_dsi_dphy_configure,
|
||||
.power_on = dw_mipi_dsi_dphy_power_on,
|
||||
.power_off = dw_mipi_dsi_dphy_power_off,
|
||||
.init = dw_mipi_dsi_dphy_init,
|
||||
.exit = dw_mipi_dsi_dphy_exit,
|
||||
};
|
||||
|
||||
static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct dw_mipi_dsi_rockchip *dsi;
|
||||
struct phy_provider *phy_provider;
|
||||
struct resource *res;
|
||||
const struct rockchip_dw_dsi_chip_data *cdata =
|
||||
of_device_get_match_data(dev);
|
||||
@ -1065,6 +1321,13 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->pclk = devm_clk_get(dev, "pclk");
|
||||
if (IS_ERR(dsi->pclk)) {
|
||||
ret = PTR_ERR(dsi->pclk);
|
||||
DRM_DEV_ERROR(dev, "Unable to get pclk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->pllref_clk = devm_clk_get(dev, "ref");
|
||||
if (IS_ERR(dsi->pllref_clk)) {
|
||||
if (dsi->phy) {
|
||||
@ -1115,6 +1378,19 @@ static int dw_mipi_dsi_rockchip_probe(struct platform_device *pdev)
|
||||
dsi->pdata.priv_data = dsi;
|
||||
platform_set_drvdata(pdev, dsi);
|
||||
|
||||
mutex_init(&dsi->usage_mutex);
|
||||
|
||||
dsi->dphy = devm_phy_create(dev, NULL, &dw_mipi_dsi_dphy_ops);
|
||||
if (IS_ERR(dsi->dphy)) {
|
||||
DRM_DEV_ERROR(&pdev->dev, "failed to create PHY\n");
|
||||
return PTR_ERR(dsi->dphy);
|
||||
}
|
||||
|
||||
phy_set_drvdata(dsi->dphy, dsi);
|
||||
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||
if (IS_ERR(phy_provider))
|
||||
return PTR_ERR(phy_provider);
|
||||
|
||||
dsi->dmd = dw_mipi_dsi_probe(pdev, &dsi->pdata);
|
||||
if (IS_ERR(dsi->dmd)) {
|
||||
ret = PTR_ERR(dsi->dmd);
|
||||
@ -1178,6 +1454,75 @@ static const struct rockchip_dw_dsi_chip_data rk3288_chip_data[] = {
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static int rk3399_dphy_tx1rx1_init(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
|
||||
/*
|
||||
* Set TX1RX1 source to isp1.
|
||||
* Assume ISP0 is supplied by the RX0 dphy.
|
||||
*/
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(0, RK3399_TXRX_SRC_SEL_ISP0));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(0, RK3399_TXRX_BASEDIR));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3399_dphy_tx1rx1_power_on(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
|
||||
/* tester reset pulse */
|
||||
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_TESTCLR);
|
||||
usleep_range(100, 150);
|
||||
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(0, RK3399_TXRX_MASTERSLAVEZ));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(RK3399_TXRX_BASEDIR, RK3399_TXRX_BASEDIR));
|
||||
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(0, RK3399_DSI1_FORCERXMODE));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(0, RK3399_DSI1_FORCETXSTOPMODE));
|
||||
|
||||
/* Disable lane turn around, which is ignored in receive mode */
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON24,
|
||||
HIWORD_UPDATE(0, RK3399_TXRX_TURNREQUEST));
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(RK3399_DSI1_TURNDISABLE,
|
||||
RK3399_DSI1_TURNDISABLE));
|
||||
usleep_range(100, 150);
|
||||
|
||||
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
|
||||
usleep_range(100, 150);
|
||||
|
||||
/* Enable dphy lanes */
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(GENMASK(dsi->dphy_config.lanes - 1, 0),
|
||||
RK3399_DSI1_ENABLE));
|
||||
|
||||
usleep_range(100, 150);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk3399_dphy_tx1rx1_power_off(struct phy *phy)
|
||||
{
|
||||
struct dw_mipi_dsi_rockchip *dsi = phy_get_drvdata(phy);
|
||||
|
||||
regmap_write(dsi->grf_regmap, RK3399_GRF_SOC_CON23,
|
||||
HIWORD_UPDATE(0, RK3399_DSI1_ENABLE));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
|
||||
{
|
||||
.reg = 0xff960000,
|
||||
@ -1220,6 +1565,10 @@ static const struct rockchip_dw_dsi_chip_data rk3399_chip_data[] = {
|
||||
|
||||
.flags = DW_MIPI_NEEDS_PHY_CFG_CLK | DW_MIPI_NEEDS_GRF_CLK,
|
||||
.max_data_lanes = 4,
|
||||
|
||||
.dphy_rx_init = rk3399_dphy_tx1rx1_init,
|
||||
.dphy_rx_power_on = rk3399_dphy_tx1rx1_power_on,
|
||||
.dphy_rx_power_off = rk3399_dphy_tx1rx1_power_off,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
@ -130,7 +129,6 @@ DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops);
|
||||
|
||||
static const struct drm_driver shmob_drm_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET,
|
||||
.irq_handler = shmob_drm_irq,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
.fops = &shmob_drm_fops,
|
||||
.name = "shmob-drm",
|
||||
@ -183,7 +181,7 @@ static int shmob_drm_remove(struct platform_device *pdev)
|
||||
|
||||
drm_dev_unregister(ddev);
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
drm_irq_uninstall(ddev);
|
||||
free_irq(sdev->irq, ddev);
|
||||
drm_dev_put(ddev);
|
||||
|
||||
return 0;
|
||||
@ -258,7 +256,13 @@ static int shmob_drm_probe(struct platform_device *pdev)
|
||||
goto err_modeset_cleanup;
|
||||
}
|
||||
|
||||
ret = drm_irq_install(ddev, platform_get_irq(pdev, 0));
|
||||
ret = platform_get_irq(pdev, 0);
|
||||
if (ret < 0)
|
||||
goto err_modeset_cleanup;
|
||||
sdev->irq = ret;
|
||||
|
||||
ret = request_irq(sdev->irq, shmob_drm_irq, 0, ddev->driver->name,
|
||||
ddev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to install IRQ handler\n");
|
||||
goto err_modeset_cleanup;
|
||||
@ -275,7 +279,7 @@ static int shmob_drm_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
err_irq_uninstall:
|
||||
drm_irq_uninstall(ddev);
|
||||
free_irq(sdev->irq, ddev);
|
||||
err_modeset_cleanup:
|
||||
drm_kms_helper_poll_fini(ddev);
|
||||
err_free_drm_dev:
|
||||
|
@ -29,6 +29,7 @@ struct shmob_drm_device {
|
||||
u32 lddckr;
|
||||
u32 ldmt1r;
|
||||
|
||||
unsigned int irq;
|
||||
spinlock_t irq_lock; /* Protects hardware LDINTR register */
|
||||
|
||||
struct drm_device *ddev;
|
||||
|
@ -3,7 +3,6 @@
|
||||
* Copyright 2019 Hans de Goede <hdegoede@redhat.com>
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
@ -268,13 +267,10 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
|
||||
y2 = gm12u320->fb_update.rect.y2;
|
||||
vaddr = gm12u320->fb_update.src_map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
if (fb->obj[0]->import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(
|
||||
fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE);
|
||||
if (ret) {
|
||||
GM12U320_ERR("dma_buf_begin_cpu_access err: %d\n", ret);
|
||||
goto put_fb;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret) {
|
||||
GM12U320_ERR("drm_gem_fb_begin_cpu_access err: %d\n", ret);
|
||||
goto put_fb;
|
||||
}
|
||||
|
||||
src = vaddr + y1 * fb->pitches[0] + x1 * 4;
|
||||
@ -311,12 +307,7 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320)
|
||||
src += fb->pitches[0];
|
||||
}
|
||||
|
||||
if (fb->obj[0]->import_attach) {
|
||||
ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
GM12U320_ERR("dma_buf_end_cpu_access err: %d\n", ret);
|
||||
}
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
put_fb:
|
||||
drm_framebuffer_put(fb);
|
||||
gm12u320->fb_update.fb = NULL;
|
||||
|
@ -14,7 +14,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
@ -532,7 +531,6 @@ static void repaper_gray8_to_mono_reversed(u8 *buf, u32 width, u32 height)
|
||||
static int repaper_fb_dirty(struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
|
||||
struct repaper_epd *epd = drm_to_epd(fb->dev);
|
||||
struct drm_rect clip;
|
||||
int idx, ret = 0;
|
||||
@ -558,21 +556,13 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb)
|
||||
goto out_exit;
|
||||
}
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
drm_fb_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip);
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_end_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
}
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
|
||||
repaper_gray8_to_mono_reversed(buf, fb->width, fb->height);
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/property.h>
|
||||
@ -21,6 +20,7 @@
|
||||
#include <drm/drm_format_helper.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_mipi_dbi.h>
|
||||
#include <drm/drm_rect.h>
|
||||
@ -92,24 +92,18 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb,
|
||||
struct drm_rect *clip)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
struct dma_buf_attachment *import_attach = cma_obj->base.import_attach;
|
||||
void *src = cma_obj->vaddr;
|
||||
int ret = 0;
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
st7586_xrgb8888_to_gray332(dst, src, fb, clip);
|
||||
|
||||
if (import_attach)
|
||||
ret = dma_buf_end_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
|
||||
|
@ -6,11 +6,8 @@
|
||||
* Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
|
||||
* Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
|
||||
* Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
|
||||
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
@ -271,9 +268,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
struct drm_device *dev = fb->dev;
|
||||
struct dma_buf_attachment *import_attach = fb->obj[0]->import_attach;
|
||||
void *vaddr = map->vaddr; /* TODO: Use mapping abstraction properly */
|
||||
int i, ret, tmp_ret;
|
||||
int i, ret;
|
||||
char *cmd;
|
||||
struct urb *urb;
|
||||
struct drm_rect clip;
|
||||
@ -290,17 +286,14 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
|
||||
else if ((clip.x2 > fb->width) || (clip.y2 > fb->height))
|
||||
return -EINVAL;
|
||||
|
||||
if (import_attach) {
|
||||
ret = dma_buf_begin_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
urb = udl_get_urb(dev);
|
||||
if (!urb) {
|
||||
ret = -ENOMEM;
|
||||
goto out_dma_buf_end_cpu_access;
|
||||
goto out_drm_gem_fb_end_cpu_access;
|
||||
}
|
||||
cmd = urb->transfer_buffer;
|
||||
|
||||
@ -313,7 +306,7 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
|
||||
&cmd, byte_offset, dev_byte_offset,
|
||||
byte_width);
|
||||
if (ret)
|
||||
goto out_dma_buf_end_cpu_access;
|
||||
goto out_drm_gem_fb_end_cpu_access;
|
||||
}
|
||||
|
||||
if (cmd > (char *)urb->transfer_buffer) {
|
||||
@ -329,14 +322,8 @@ static int udl_handle_damage(struct drm_framebuffer *fb, const struct dma_buf_ma
|
||||
|
||||
ret = 0;
|
||||
|
||||
out_dma_buf_end_cpu_access:
|
||||
if (import_attach) {
|
||||
tmp_ret = dma_buf_end_cpu_access(import_attach->dmabuf,
|
||||
DMA_FROM_DEVICE);
|
||||
if (tmp_ret && !ret)
|
||||
ret = tmp_ret; /* only update ret if not set yet */
|
||||
}
|
||||
|
||||
out_drm_gem_fb_end_cpu_access:
|
||||
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1184,12 +1184,13 @@ static u32 vc5_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
|
||||
}
|
||||
|
||||
/* HDMI audio codec callbacks */
|
||||
static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
|
||||
static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi,
|
||||
unsigned int samplerate)
|
||||
{
|
||||
u32 hsm_clock = clk_get_rate(vc4_hdmi->audio_clock);
|
||||
unsigned long n, m;
|
||||
|
||||
rational_best_approximation(hsm_clock, vc4_hdmi->audio.samplerate,
|
||||
rational_best_approximation(hsm_clock, samplerate,
|
||||
VC4_HD_MAI_SMP_N_MASK >>
|
||||
VC4_HD_MAI_SMP_N_SHIFT,
|
||||
(VC4_HD_MAI_SMP_M_MASK >>
|
||||
@ -1201,12 +1202,11 @@ static void vc4_hdmi_audio_set_mai_clock(struct vc4_hdmi *vc4_hdmi)
|
||||
VC4_SET_FIELD(m - 1, VC4_HD_MAI_SMP_M));
|
||||
}
|
||||
|
||||
static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi)
|
||||
static void vc4_hdmi_set_n_cts(struct vc4_hdmi *vc4_hdmi, unsigned int samplerate)
|
||||
{
|
||||
struct drm_connector *connector = &vc4_hdmi->connector;
|
||||
struct drm_crtc *crtc = connector->state->crtc;
|
||||
const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
|
||||
u32 samplerate = vc4_hdmi->audio.samplerate;
|
||||
u32 n, cts;
|
||||
u64 tmp;
|
||||
|
||||
@ -1340,27 +1340,25 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
|
||||
{
|
||||
struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
|
||||
struct drm_encoder *encoder = &vc4_hdmi->encoder.base.base;
|
||||
unsigned int sample_rate = params->sample_rate;
|
||||
unsigned int channels = params->channels;
|
||||
u32 audio_packet_config, channel_mask;
|
||||
u32 channel_map;
|
||||
u32 mai_audio_format;
|
||||
u32 mai_sample_rate;
|
||||
|
||||
dev_dbg(dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
|
||||
params->sample_rate, params->sample_width,
|
||||
params->channels);
|
||||
|
||||
vc4_hdmi->audio.channels = params->channels;
|
||||
vc4_hdmi->audio.samplerate = params->sample_rate;
|
||||
sample_rate, params->sample_width, channels);
|
||||
|
||||
HDMI_WRITE(HDMI_MAI_CTL,
|
||||
VC4_SET_FIELD(params->channels, VC4_HD_MAI_CTL_CHNUM) |
|
||||
VC4_SET_FIELD(channels, VC4_HD_MAI_CTL_CHNUM) |
|
||||
VC4_HD_MAI_CTL_WHOLSMP |
|
||||
VC4_HD_MAI_CTL_CHALIGN |
|
||||
VC4_HD_MAI_CTL_ENABLE);
|
||||
|
||||
vc4_hdmi_audio_set_mai_clock(vc4_hdmi);
|
||||
vc4_hdmi_audio_set_mai_clock(vc4_hdmi, sample_rate);
|
||||
|
||||
mai_sample_rate = sample_rate_to_mai_fmt(vc4_hdmi->audio.samplerate);
|
||||
mai_sample_rate = sample_rate_to_mai_fmt(sample_rate);
|
||||
if (params->iec.status[0] & IEC958_AES0_NONAUDIO &&
|
||||
params->channels == 8)
|
||||
mai_audio_format = VC4_HDMI_MAI_FORMAT_HBR;
|
||||
@ -1378,7 +1376,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
|
||||
VC4_HDMI_AUDIO_PACKET_ZERO_DATA_ON_INACTIVE_CHANNELS |
|
||||
VC4_SET_FIELD(0x8, VC4_HDMI_AUDIO_PACKET_B_FRAME_IDENTIFIER);
|
||||
|
||||
channel_mask = GENMASK(vc4_hdmi->audio.channels - 1, 0);
|
||||
channel_mask = GENMASK(channels - 1, 0);
|
||||
audio_packet_config |= VC4_SET_FIELD(channel_mask,
|
||||
VC4_HDMI_AUDIO_PACKET_CEA_MASK);
|
||||
|
||||
@ -1397,7 +1395,7 @@ static int vc4_hdmi_audio_prepare(struct device *dev, void *data,
|
||||
channel_map = vc4_hdmi->variant->channel_map(vc4_hdmi, channel_mask);
|
||||
HDMI_WRITE(HDMI_MAI_CHANNEL_MAP, channel_map);
|
||||
HDMI_WRITE(HDMI_AUDIO_PACKET_CONFIG, audio_packet_config);
|
||||
vc4_hdmi_set_n_cts(vc4_hdmi);
|
||||
vc4_hdmi_set_n_cts(vc4_hdmi, sample_rate);
|
||||
|
||||
memcpy(&vc4_hdmi->audio.infoframe, ¶ms->cea, sizeof(params->cea));
|
||||
vc4_hdmi_set_audio_infoframe(encoder);
|
||||
@ -1413,18 +1411,6 @@ static const struct snd_soc_dapm_route vc4_hdmi_audio_routes[] = {
|
||||
{ "TX", NULL, "Playback" },
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver vc4_hdmi_audio_component_drv = {
|
||||
.name = "vc4-hdmi-codec-dai-component",
|
||||
.dapm_widgets = vc4_hdmi_audio_widgets,
|
||||
.num_dapm_widgets = ARRAY_SIZE(vc4_hdmi_audio_widgets),
|
||||
.dapm_routes = vc4_hdmi_audio_routes,
|
||||
.num_dapm_routes = ARRAY_SIZE(vc4_hdmi_audio_routes),
|
||||
.idle_bias_on = 1,
|
||||
.use_pmdown_time = 1,
|
||||
.endianness = 1,
|
||||
.non_legacy_dai_naming = 1,
|
||||
};
|
||||
|
||||
static const struct snd_soc_component_driver vc4_hdmi_audio_cpu_dai_comp = {
|
||||
.name = "vc4-hdmi-cpu-dai-component",
|
||||
};
|
||||
|
@ -111,8 +111,6 @@ struct vc4_hdmi_audio {
|
||||
struct snd_soc_dai_link_component cpu;
|
||||
struct snd_soc_dai_link_component codec;
|
||||
struct snd_soc_dai_link_component platform;
|
||||
int samplerate;
|
||||
int channels;
|
||||
struct snd_dmaengine_dai_dma_data dma_data;
|
||||
struct hdmi_audio_infoframe infoframe;
|
||||
bool streaming;
|
||||
|
@ -140,7 +140,8 @@ struct vmw_fifo_state *vmw_fifo_create(struct vmw_private *dev_priv)
|
||||
min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN);
|
||||
fifo->capabilities = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CAPABILITIES);
|
||||
|
||||
DRM_INFO("Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
|
||||
drm_info(&dev_priv->drm,
|
||||
"Fifo max 0x%08x min 0x%08x cap 0x%08x\n",
|
||||
(unsigned int) max,
|
||||
(unsigned int) min,
|
||||
(unsigned int) fifo->capabilities);
|
||||
|
@ -1272,7 +1272,8 @@ int vmw_cmdbuf_set_pool_size(struct vmw_cmdbuf_man *man, size_t size)
|
||||
* submissions to be able to free up space.
|
||||
*/
|
||||
man->default_size = VMW_CMDBUF_INLINE_SIZE;
|
||||
DRM_INFO("Using command buffers with %s pool.\n",
|
||||
drm_info(&dev_priv->drm,
|
||||
"Using command buffers with %s pool.\n",
|
||||
(man->using_mob) ? "MOB" : "DMA");
|
||||
|
||||
return 0;
|
||||
|
@ -159,110 +159,102 @@
|
||||
DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_MKSSTAT_REMOVE, \
|
||||
struct drm_vmw_mksstat_remove_arg)
|
||||
|
||||
/*
|
||||
* The core DRM version of this macro doesn't account for
|
||||
* DRM_COMMAND_BASE.
|
||||
*/
|
||||
|
||||
#define VMW_IOCTL_DEF(ioctl, func, flags) \
|
||||
[DRM_IOCTL_NR(DRM_IOCTL_##ioctl) - DRM_COMMAND_BASE] = {DRM_IOCTL_##ioctl, flags, func}
|
||||
|
||||
/*
|
||||
* Ioctl definitions.
|
||||
*/
|
||||
|
||||
static const struct drm_ioctl_desc vmw_ioctls[] = {
|
||||
VMW_IOCTL_DEF(VMW_GET_PARAM, vmw_getparam_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CURSOR_BYPASS,
|
||||
vmw_kms_cursor_bypass_ioctl,
|
||||
DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GET_PARAM, vmw_getparam_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_ALLOC_DMABUF, vmw_bo_alloc_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UNREF_DMABUF, vmw_bo_unref_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CURSOR_BYPASS,
|
||||
vmw_kms_cursor_bypass_ioctl,
|
||||
DRM_MASTER),
|
||||
|
||||
VMW_IOCTL_DEF(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
|
||||
DRM_MASTER),
|
||||
VMW_IOCTL_DEF(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
|
||||
DRM_MASTER),
|
||||
VMW_IOCTL_DEF(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
|
||||
DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CONTROL_STREAM, vmw_overlay_ioctl,
|
||||
DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CLAIM_STREAM, vmw_stream_claim_ioctl,
|
||||
DRM_MASTER),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UNREF_STREAM, vmw_stream_unref_ioctl,
|
||||
DRM_MASTER),
|
||||
|
||||
VMW_IOCTL_DEF(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_FENCE_SIGNALED,
|
||||
vmw_fence_obj_signaled_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CREATE_CONTEXT, vmw_context_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CREATE_SURFACE, vmw_surface_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_REF_SURFACE, vmw_surface_reference_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_EXECBUF, vmw_execbuf_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_FENCE_SIGNALED,
|
||||
vmw_fence_obj_signaled_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_FENCE_UNREF, vmw_fence_obj_unref_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_FENCE_EVENT, vmw_fence_event_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GET_3D_CAP, vmw_get_cap_3d_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
|
||||
/* these allow direct access to the framebuffers mark as master only */
|
||||
VMW_IOCTL_DEF(VMW_PRESENT, vmw_present_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
|
||||
vmw_present_readback_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(VMW_PRESENT, vmw_present_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(VMW_PRESENT_READBACK,
|
||||
vmw_present_readback_ioctl,
|
||||
DRM_MASTER | DRM_AUTH),
|
||||
/*
|
||||
* The permissions of the below ioctl are overridden in
|
||||
* vmw_generic_ioctl(). We require either
|
||||
* DRM_MASTER or capable(CAP_SYS_ADMIN).
|
||||
*/
|
||||
VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
|
||||
vmw_kms_update_layout_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CREATE_SHADER,
|
||||
vmw_shader_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_UNREF_SHADER,
|
||||
vmw_shader_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE,
|
||||
vmw_gb_surface_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF,
|
||||
vmw_gb_surface_reference_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_SYNCCPU,
|
||||
vmw_user_bo_synccpu_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_CREATE_EXTENDED_CONTEXT,
|
||||
vmw_extended_context_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_GB_SURFACE_CREATE_EXT,
|
||||
vmw_gb_surface_define_ext_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_GB_SURFACE_REF_EXT,
|
||||
vmw_gb_surface_reference_ext_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_MSG,
|
||||
vmw_msg_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_MKSSTAT_RESET,
|
||||
vmw_mksstat_reset_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_MKSSTAT_ADD,
|
||||
vmw_mksstat_add_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
VMW_IOCTL_DEF(VMW_MKSSTAT_REMOVE,
|
||||
vmw_mksstat_remove_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UPDATE_LAYOUT,
|
||||
vmw_kms_update_layout_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CREATE_SHADER,
|
||||
vmw_shader_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_UNREF_SHADER,
|
||||
vmw_shader_destroy_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE,
|
||||
vmw_gb_surface_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF,
|
||||
vmw_gb_surface_reference_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_SYNCCPU,
|
||||
vmw_user_bo_synccpu_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_CREATE_EXTENDED_CONTEXT,
|
||||
vmw_extended_context_define_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_CREATE_EXT,
|
||||
vmw_gb_surface_define_ext_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_GB_SURFACE_REF_EXT,
|
||||
vmw_gb_surface_reference_ext_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_MSG,
|
||||
vmw_msg_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_RESET,
|
||||
vmw_mksstat_reset_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_ADD,
|
||||
vmw_mksstat_add_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(VMW_MKSSTAT_REMOVE,
|
||||
vmw_mksstat_remove_ioctl,
|
||||
DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static const struct pci_device_id vmw_pci_id_list[] = {
|
||||
@ -294,62 +286,92 @@ MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
|
||||
module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
|
||||
|
||||
|
||||
static void vmw_print_capabilities2(uint32_t capabilities2)
|
||||
struct bitmap_name {
|
||||
uint32 value;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct bitmap_name cap1_names[] = {
|
||||
{ SVGA_CAP_RECT_COPY, "rect copy" },
|
||||
{ SVGA_CAP_CURSOR, "cursor" },
|
||||
{ SVGA_CAP_CURSOR_BYPASS, "cursor bypass" },
|
||||
{ SVGA_CAP_CURSOR_BYPASS_2, "cursor bypass 2" },
|
||||
{ SVGA_CAP_8BIT_EMULATION, "8bit emulation" },
|
||||
{ SVGA_CAP_ALPHA_CURSOR, "alpha cursor" },
|
||||
{ SVGA_CAP_3D, "3D" },
|
||||
{ SVGA_CAP_EXTENDED_FIFO, "extended fifo" },
|
||||
{ SVGA_CAP_MULTIMON, "multimon" },
|
||||
{ SVGA_CAP_PITCHLOCK, "pitchlock" },
|
||||
{ SVGA_CAP_IRQMASK, "irq mask" },
|
||||
{ SVGA_CAP_DISPLAY_TOPOLOGY, "display topology" },
|
||||
{ SVGA_CAP_GMR, "gmr" },
|
||||
{ SVGA_CAP_TRACES, "traces" },
|
||||
{ SVGA_CAP_GMR2, "gmr2" },
|
||||
{ SVGA_CAP_SCREEN_OBJECT_2, "screen object 2" },
|
||||
{ SVGA_CAP_COMMAND_BUFFERS, "command buffers" },
|
||||
{ SVGA_CAP_CMD_BUFFERS_2, "command buffers 2" },
|
||||
{ SVGA_CAP_GBOBJECTS, "gbobject" },
|
||||
{ SVGA_CAP_DX, "dx" },
|
||||
{ SVGA_CAP_HP_CMD_QUEUE, "hp cmd queue" },
|
||||
{ SVGA_CAP_NO_BB_RESTRICTION, "no bb restriction" },
|
||||
{ SVGA_CAP_CAP2_REGISTER, "cap2 register" },
|
||||
};
|
||||
|
||||
|
||||
static const struct bitmap_name cap2_names[] = {
|
||||
{ SVGA_CAP2_GROW_OTABLE, "grow otable" },
|
||||
{ SVGA_CAP2_INTRA_SURFACE_COPY, "intra surface copy" },
|
||||
{ SVGA_CAP2_DX2, "dx2" },
|
||||
{ SVGA_CAP2_GB_MEMSIZE_2, "gb memsize 2" },
|
||||
{ SVGA_CAP2_SCREENDMA_REG, "screendma reg" },
|
||||
{ SVGA_CAP2_OTABLE_PTDEPTH_2, "otable ptdepth2" },
|
||||
{ SVGA_CAP2_NON_MS_TO_MS_STRETCHBLT, "non ms to ms stretchblt" },
|
||||
{ SVGA_CAP2_CURSOR_MOB, "cursor mob" },
|
||||
{ SVGA_CAP2_MSHINT, "mshint" },
|
||||
{ SVGA_CAP2_CB_MAX_SIZE_4MB, "cb max size 4mb" },
|
||||
{ SVGA_CAP2_DX3, "dx3" },
|
||||
{ SVGA_CAP2_FRAME_TYPE, "frame type" },
|
||||
{ SVGA_CAP2_COTABLE_COPY, "cotable copy" },
|
||||
{ SVGA_CAP2_TRACE_FULL_FB, "trace full fb" },
|
||||
{ SVGA_CAP2_EXTRA_REGS, "extra regs" },
|
||||
{ SVGA_CAP2_LO_STAGING, "lo staging" },
|
||||
};
|
||||
|
||||
static void vmw_print_bitmap(struct drm_device *drm,
|
||||
const char *prefix, uint32_t bitmap,
|
||||
const struct bitmap_name *bnames,
|
||||
uint32_t num_names)
|
||||
{
|
||||
DRM_INFO("Capabilities2:\n");
|
||||
if (capabilities2 & SVGA_CAP2_GROW_OTABLE)
|
||||
DRM_INFO(" Grow oTable.\n");
|
||||
if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)
|
||||
DRM_INFO(" IntraSurface copy.\n");
|
||||
if (capabilities2 & SVGA_CAP2_DX3)
|
||||
DRM_INFO(" DX3.\n");
|
||||
char buf[512];
|
||||
uint32_t i;
|
||||
uint32_t offset = 0;
|
||||
for (i = 0; i < num_names; ++i) {
|
||||
if ((bitmap & bnames[i].value) != 0) {
|
||||
offset += snprintf(buf + offset,
|
||||
ARRAY_SIZE(buf) - offset,
|
||||
"%s, ", bnames[i].name);
|
||||
bitmap &= ~bnames[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
drm_info(drm, "%s: %s\n", prefix, buf);
|
||||
if (bitmap != 0)
|
||||
drm_dbg(drm, "%s: unknown enums: %x\n", prefix, bitmap);
|
||||
}
|
||||
|
||||
static void vmw_print_capabilities(uint32_t capabilities)
|
||||
|
||||
static void vmw_print_sm_type(struct vmw_private *dev_priv)
|
||||
{
|
||||
DRM_INFO("Capabilities:\n");
|
||||
if (capabilities & SVGA_CAP_RECT_COPY)
|
||||
DRM_INFO(" Rect copy.\n");
|
||||
if (capabilities & SVGA_CAP_CURSOR)
|
||||
DRM_INFO(" Cursor.\n");
|
||||
if (capabilities & SVGA_CAP_CURSOR_BYPASS)
|
||||
DRM_INFO(" Cursor bypass.\n");
|
||||
if (capabilities & SVGA_CAP_CURSOR_BYPASS_2)
|
||||
DRM_INFO(" Cursor bypass 2.\n");
|
||||
if (capabilities & SVGA_CAP_8BIT_EMULATION)
|
||||
DRM_INFO(" 8bit emulation.\n");
|
||||
if (capabilities & SVGA_CAP_ALPHA_CURSOR)
|
||||
DRM_INFO(" Alpha cursor.\n");
|
||||
if (capabilities & SVGA_CAP_3D)
|
||||
DRM_INFO(" 3D.\n");
|
||||
if (capabilities & SVGA_CAP_EXTENDED_FIFO)
|
||||
DRM_INFO(" Extended Fifo.\n");
|
||||
if (capabilities & SVGA_CAP_MULTIMON)
|
||||
DRM_INFO(" Multimon.\n");
|
||||
if (capabilities & SVGA_CAP_PITCHLOCK)
|
||||
DRM_INFO(" Pitchlock.\n");
|
||||
if (capabilities & SVGA_CAP_IRQMASK)
|
||||
DRM_INFO(" Irq mask.\n");
|
||||
if (capabilities & SVGA_CAP_DISPLAY_TOPOLOGY)
|
||||
DRM_INFO(" Display Topology.\n");
|
||||
if (capabilities & SVGA_CAP_GMR)
|
||||
DRM_INFO(" GMR.\n");
|
||||
if (capabilities & SVGA_CAP_TRACES)
|
||||
DRM_INFO(" Traces.\n");
|
||||
if (capabilities & SVGA_CAP_GMR2)
|
||||
DRM_INFO(" GMR2.\n");
|
||||
if (capabilities & SVGA_CAP_SCREEN_OBJECT_2)
|
||||
DRM_INFO(" Screen Object 2.\n");
|
||||
if (capabilities & SVGA_CAP_COMMAND_BUFFERS)
|
||||
DRM_INFO(" Command Buffers.\n");
|
||||
if (capabilities & SVGA_CAP_CMD_BUFFERS_2)
|
||||
DRM_INFO(" Command Buffers 2.\n");
|
||||
if (capabilities & SVGA_CAP_GBOBJECTS)
|
||||
DRM_INFO(" Guest Backed Resources.\n");
|
||||
if (capabilities & SVGA_CAP_DX)
|
||||
DRM_INFO(" DX Features.\n");
|
||||
if (capabilities & SVGA_CAP_HP_CMD_QUEUE)
|
||||
DRM_INFO(" HP Command Queue.\n");
|
||||
static const char *names[] = {
|
||||
[VMW_SM_LEGACY] = "Legacy",
|
||||
[VMW_SM_4] = "SM4",
|
||||
[VMW_SM_4_1] = "SM4_1",
|
||||
[VMW_SM_5] = "SM_5",
|
||||
[VMW_SM_MAX] = "Invalid"
|
||||
};
|
||||
BUILD_BUG_ON(ARRAY_SIZE(names) != (VMW_SM_MAX + 1));
|
||||
drm_info(&dev_priv->drm, "Available shader model: %s.\n",
|
||||
names[dev_priv->sm_type]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -416,10 +438,6 @@ static int vmw_device_init(struct vmw_private *dev_priv)
|
||||
{
|
||||
bool uses_fb_traces = false;
|
||||
|
||||
DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
|
||||
DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
|
||||
DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
|
||||
|
||||
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
|
||||
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
|
||||
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
|
||||
@ -658,7 +676,8 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
|
||||
else
|
||||
dev_priv->map_mode = vmw_dma_map_populate;
|
||||
|
||||
DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
|
||||
drm_info(&dev_priv->drm,
|
||||
"DMA map mode: %s\n", names[dev_priv->map_mode]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -677,7 +696,8 @@ static int vmw_dma_masks(struct vmw_private *dev_priv)
|
||||
|
||||
ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
|
||||
if (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask) {
|
||||
DRM_INFO("Restricting DMA addresses to 44 bits.\n");
|
||||
drm_info(&dev_priv->drm,
|
||||
"Restricting DMA addresses to 44 bits.\n");
|
||||
return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
|
||||
}
|
||||
|
||||
@ -729,13 +749,15 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
|
||||
dev->vram_start = pci_resource_start(pdev, 2);
|
||||
dev->vram_size = pci_resource_len(pdev, 2);
|
||||
|
||||
DRM_INFO("Register MMIO at 0x%pa size is %llu kiB\n",
|
||||
drm_info(&dev->drm,
|
||||
"Register MMIO at 0x%pa size is %llu kiB\n",
|
||||
&rmmio_start, (uint64_t)rmmio_size / 1024);
|
||||
dev->rmmio = devm_ioremap(dev->drm.dev,
|
||||
rmmio_start,
|
||||
rmmio_size);
|
||||
if (!dev->rmmio) {
|
||||
DRM_ERROR("Failed mapping registers mmio memory.\n");
|
||||
drm_err(&dev->drm,
|
||||
"Failed mapping registers mmio memory.\n");
|
||||
pci_release_regions(pdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -746,7 +768,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
|
||||
fifo_start = pci_resource_start(pdev, 2);
|
||||
fifo_size = pci_resource_len(pdev, 2);
|
||||
|
||||
DRM_INFO("FIFO at %pa size is %llu kiB\n",
|
||||
drm_info(&dev->drm,
|
||||
"FIFO at %pa size is %llu kiB\n",
|
||||
&fifo_start, (uint64_t)fifo_size / 1024);
|
||||
dev->fifo_mem = devm_memremap(dev->drm.dev,
|
||||
fifo_start,
|
||||
@ -754,7 +777,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
|
||||
MEMREMAP_WB);
|
||||
|
||||
if (IS_ERR(dev->fifo_mem)) {
|
||||
DRM_ERROR("Failed mapping FIFO memory.\n");
|
||||
drm_err(&dev->drm,
|
||||
"Failed mapping FIFO memory.\n");
|
||||
pci_release_regions(pdev);
|
||||
return PTR_ERR(dev->fifo_mem);
|
||||
}
|
||||
@ -769,7 +793,8 @@ static int vmw_setup_pci_resources(struct vmw_private *dev,
|
||||
* size will be equal to or bigger than the size reported by
|
||||
* SVGA_REG_VRAM_SIZE.
|
||||
*/
|
||||
DRM_INFO("VRAM at %pa size is %llu kiB\n",
|
||||
drm_info(&dev->drm,
|
||||
"VRAM at %pa size is %llu kiB\n",
|
||||
&dev->vram_start, (uint64_t)dev->vram_size / 1024);
|
||||
|
||||
return 0;
|
||||
@ -783,12 +808,14 @@ static int vmw_detect_version(struct vmw_private *dev)
|
||||
SVGA_ID_3 : SVGA_ID_2);
|
||||
svga_id = vmw_read(dev, SVGA_REG_ID);
|
||||
if (svga_id != SVGA_ID_2 && svga_id != SVGA_ID_3) {
|
||||
DRM_ERROR("Unsupported SVGA ID 0x%x on chipset 0x%x\n",
|
||||
svga_id, dev->pci_id);
|
||||
drm_err(&dev->drm,
|
||||
"Unsupported SVGA ID 0x%x on chipset 0x%x\n",
|
||||
svga_id, dev->pci_id);
|
||||
return -ENOSYS;
|
||||
}
|
||||
BUG_ON(vmw_is_svga_v3(dev) && (svga_id != SVGA_ID_3));
|
||||
DRM_INFO("Running on SVGA version %d.\n", (svga_id & 0xff));
|
||||
drm_info(&dev->drm,
|
||||
"Running on SVGA version %d.\n", (svga_id & 0xff));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -842,10 +869,12 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
|
||||
ret = vmw_dma_select_mode(dev_priv);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_INFO("Restricting capabilities since DMA not available.\n");
|
||||
drm_info(&dev_priv->drm,
|
||||
"Restricting capabilities since DMA not available.\n");
|
||||
refuse_dma = true;
|
||||
if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
|
||||
DRM_INFO("Disabling 3D acceleration.\n");
|
||||
drm_info(&dev_priv->drm,
|
||||
"Disabling 3D acceleration.\n");
|
||||
}
|
||||
|
||||
dev_priv->vram_size = vmw_read(dev_priv, SVGA_REG_VRAM_SIZE);
|
||||
@ -913,12 +942,23 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
dev_priv->texture_max_height = 8192;
|
||||
dev_priv->max_primary_mem = dev_priv->vram_size;
|
||||
}
|
||||
drm_info(&dev_priv->drm,
|
||||
"Legacy memory limits: VRAM = %llu kB, FIFO = %llu kB, surface = %u kB\n",
|
||||
(u64)dev_priv->vram_size / 1024,
|
||||
(u64)dev_priv->fifo_mem_size / 1024,
|
||||
dev_priv->memory_size / 1024);
|
||||
|
||||
vmw_print_capabilities(dev_priv->capabilities);
|
||||
drm_info(&dev_priv->drm,
|
||||
"MOB limits: max mob size = %u kB, max mob pages = %u\n",
|
||||
dev_priv->max_mob_size / 1024, dev_priv->max_mob_pages);
|
||||
|
||||
vmw_print_bitmap(&dev_priv->drm, "Capabilities",
|
||||
dev_priv->capabilities,
|
||||
cap1_names, ARRAY_SIZE(cap1_names));
|
||||
if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER)
|
||||
vmw_print_capabilities2(dev_priv->capabilities2);
|
||||
DRM_INFO("Supports command queues = %d\n",
|
||||
vmw_cmd_supported((dev_priv)));
|
||||
vmw_print_bitmap(&dev_priv->drm, "Capabilities2",
|
||||
dev_priv->capabilities2,
|
||||
cap2_names, ARRAY_SIZE(cap2_names));
|
||||
|
||||
ret = vmw_dma_masks(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
@ -927,14 +967,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
dma_set_max_seg_size(dev_priv->drm.dev, U32_MAX);
|
||||
|
||||
if (dev_priv->capabilities & SVGA_CAP_GMR2) {
|
||||
DRM_INFO("Max GMR ids is %u\n",
|
||||
drm_info(&dev_priv->drm,
|
||||
"Max GMR ids is %u\n",
|
||||
(unsigned)dev_priv->max_gmr_ids);
|
||||
DRM_INFO("Max number of GMR pages is %u\n",
|
||||
drm_info(&dev_priv->drm,
|
||||
"Max number of GMR pages is %u\n",
|
||||
(unsigned)dev_priv->max_gmr_pages);
|
||||
DRM_INFO("Max dedicated hypervisor surface memory is %u kiB\n",
|
||||
(unsigned)dev_priv->memory_size / 1024);
|
||||
}
|
||||
DRM_INFO("Maximum display memory size is %llu kiB\n",
|
||||
drm_info(&dev_priv->drm,
|
||||
"Maximum display memory size is %llu kiB\n",
|
||||
(uint64_t)dev_priv->max_primary_mem / 1024);
|
||||
|
||||
/* Need mmio memory to check for fifo pitchlock cap. */
|
||||
@ -950,7 +991,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
&vmw_prime_dmabuf_ops);
|
||||
|
||||
if (unlikely(dev_priv->tdev == NULL)) {
|
||||
DRM_ERROR("Unable to initialize TTM object management.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Unable to initialize TTM object management.\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_err0;
|
||||
}
|
||||
@ -958,7 +1000,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK) {
|
||||
ret = vmw_irq_install(&dev_priv->drm, pdev->irq);
|
||||
if (ret != 0) {
|
||||
DRM_ERROR("Failed installing irq: %d\n", ret);
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed installing irq: %d\n", ret);
|
||||
goto out_no_irq;
|
||||
}
|
||||
}
|
||||
@ -979,7 +1022,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
dev_priv->map_mode == vmw_dma_alloc_coherent,
|
||||
false);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed initializing TTM buffer object driver.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed initializing TTM buffer object driver.\n");
|
||||
goto out_no_bdev;
|
||||
}
|
||||
|
||||
@ -990,13 +1034,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
|
||||
ret = vmw_vram_manager_init(dev_priv);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed initializing memory manager for VRAM.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed initializing memory manager for VRAM.\n");
|
||||
goto out_no_vram;
|
||||
}
|
||||
|
||||
ret = vmw_devcaps_create(dev_priv);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed initializing device caps.\n");
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed initializing device caps.\n");
|
||||
goto out_no_vram;
|
||||
}
|
||||
|
||||
@ -1010,7 +1056,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
|
||||
refuse_dma ||
|
||||
vmw_gmrid_man_init(dev_priv, VMW_PL_GMR) != 0) {
|
||||
DRM_INFO("No GMR memory available. "
|
||||
drm_info(&dev_priv->drm,
|
||||
"No GMR memory available. "
|
||||
"Graphics memory resources are very limited.\n");
|
||||
dev_priv->has_gmr = false;
|
||||
}
|
||||
@ -1019,7 +1066,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
dev_priv->has_mob = true;
|
||||
|
||||
if (vmw_gmrid_man_init(dev_priv, VMW_PL_MOB) != 0) {
|
||||
DRM_INFO("No MOB memory available. "
|
||||
drm_info(&dev_priv->drm,
|
||||
"No MOB memory available. "
|
||||
"3D will be disabled.\n");
|
||||
dev_priv->has_mob = false;
|
||||
}
|
||||
@ -1053,14 +1101,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
|
||||
if (ret)
|
||||
goto out_no_fifo;
|
||||
|
||||
if (dev_priv->sm_type == VMW_SM_5)
|
||||
DRM_INFO("SM5 support available.\n");
|
||||
if (dev_priv->sm_type == VMW_SM_4_1)
|
||||
DRM_INFO("SM4_1 support available.\n");
|
||||
if (dev_priv->sm_type == VMW_SM_4)
|
||||
DRM_INFO("SM4 support available.\n");
|
||||
DRM_INFO("Running without reservation semaphore\n");
|
||||
|
||||
vmw_print_sm_type(dev_priv);
|
||||
vmw_host_printf("vmwgfx: Module Version: %d.%d.%d (kernel: %s)",
|
||||
VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
|
||||
VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
|
||||
|
@ -54,10 +54,10 @@
|
||||
|
||||
|
||||
#define VMWGFX_DRIVER_NAME "vmwgfx"
|
||||
#define VMWGFX_DRIVER_DATE "20210218"
|
||||
#define VMWGFX_DRIVER_DATE "20210722"
|
||||
#define VMWGFX_DRIVER_MAJOR 2
|
||||
#define VMWGFX_DRIVER_MINOR 18
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 1
|
||||
#define VMWGFX_DRIVER_MINOR 19
|
||||
#define VMWGFX_DRIVER_PATCHLEVEL 0
|
||||
#define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
|
||||
#define VMWGFX_MAX_RELOCATIONS 2048
|
||||
#define VMWGFX_MAX_VALIDATIONS 2048
|
||||
@ -367,7 +367,8 @@ enum vmw_display_unit_type {
|
||||
vmw_du_invalid = 0,
|
||||
vmw_du_legacy,
|
||||
vmw_du_screen_object,
|
||||
vmw_du_screen_target
|
||||
vmw_du_screen_target,
|
||||
vmw_du_max
|
||||
};
|
||||
|
||||
struct vmw_validation_context;
|
||||
|
@ -71,8 +71,40 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
|
||||
|
||||
if (gman->max_gmr_pages > 0) {
|
||||
gman->used_gmr_pages += (*res)->num_pages;
|
||||
if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages))
|
||||
goto nospace;
|
||||
/*
|
||||
* Because the graphics memory is a soft limit we can try to
|
||||
* expand it instead of letting the userspace apps crash.
|
||||
* We're just going to have a sane limit (half of RAM)
|
||||
* on the number of MOB's that we create and will try to keep
|
||||
* the system running until we reach that.
|
||||
*/
|
||||
if (unlikely(gman->used_gmr_pages > gman->max_gmr_pages)) {
|
||||
const unsigned long max_graphics_pages = totalram_pages() / 2;
|
||||
uint32_t new_max_pages = 0;
|
||||
|
||||
DRM_WARN("vmwgfx: mob memory overflow. Consider increasing guest RAM and graphicsMemory.\n");
|
||||
vmw_host_printf("vmwgfx, warning: mob memory overflow. Consider increasing guest RAM and graphicsMemory.\n");
|
||||
|
||||
if (gman->max_gmr_pages > (max_graphics_pages / 2)) {
|
||||
DRM_WARN("vmwgfx: guest requires more than half of RAM for graphics.\n");
|
||||
new_max_pages = max_graphics_pages;
|
||||
} else
|
||||
new_max_pages = gman->max_gmr_pages * 2;
|
||||
if (new_max_pages > gman->max_gmr_pages && new_max_pages >= gman->used_gmr_pages) {
|
||||
DRM_WARN("vmwgfx: increasing guest mob limits to %u kB.\n",
|
||||
((new_max_pages) << (PAGE_SHIFT - 10)));
|
||||
|
||||
gman->max_gmr_pages = new_max_pages;
|
||||
} else {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"vmwgfx, error: guest graphics is out of memory (mob limit at: %ukB).\n",
|
||||
((gman->max_gmr_pages) << (PAGE_SHIFT - 10)));
|
||||
vmw_host_printf(buf);
|
||||
DRM_WARN("%s", buf);
|
||||
goto nospace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*res)->start = id;
|
||||
|
@ -1793,6 +1793,13 @@ int vmw_kms_init(struct vmw_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
int ret;
|
||||
static const char *display_unit_names[] = {
|
||||
"Invalid",
|
||||
"Legacy",
|
||||
"Screen Object",
|
||||
"Screen Target",
|
||||
"Invalid (max)"
|
||||
};
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
dev->mode_config.funcs = &vmw_kms_funcs;
|
||||
@ -1810,6 +1817,9 @@ int vmw_kms_init(struct vmw_private *dev_priv)
|
||||
if (ret) /* Fallback */
|
||||
ret = vmw_kms_ldu_init_display(dev_priv);
|
||||
}
|
||||
BUILD_BUG_ON(ARRAY_SIZE(display_unit_names) != (vmw_du_max + 1));
|
||||
drm_info(&dev_priv->drm, "%s display unit initialized\n",
|
||||
display_unit_names[dev_priv->active_display_unit]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -493,8 +493,7 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
|
||||
struct drm_device *dev = &dev_priv->drm;
|
||||
int i, ret;
|
||||
|
||||
if (dev_priv->ldu_priv) {
|
||||
DRM_INFO("ldu system already on\n");
|
||||
if (unlikely(dev_priv->ldu_priv)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -527,8 +526,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
DRM_INFO("Legacy Display Unit initialized\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
|
@ -954,8 +954,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
||||
int i, ret;
|
||||
|
||||
if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
|
||||
DRM_INFO("Not using screen objects,"
|
||||
" missing cap SCREEN_OBJECT_2\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
@ -972,8 +970,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
DRM_INFO("Screen Objects Display Unit initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1889,14 +1889,13 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
|
||||
ret = vmw_stdu_init(dev_priv, i);
|
||||
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed to initialize STDU %d", i);
|
||||
drm_err(&dev_priv->drm,
|
||||
"Failed to initialize STDU %d", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
DRM_INFO("Screen Target Display device initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -227,6 +227,9 @@ static int asiliantfb_check_var(struct fb_var_screeninfo *var,
|
||||
{
|
||||
unsigned long Ftarget, ratio, remainder;
|
||||
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
ratio = 1000000 / var->pixclock;
|
||||
remainder = 1000000 % var->pixclock;
|
||||
Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock;
|
||||
|
@ -548,7 +548,7 @@ static int ep93xxfb_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ep93xxfb_set_par(info);
|
||||
clk_enable(fbi->clk);
|
||||
clk_prepare_enable(fbi->clk);
|
||||
|
||||
err = register_framebuffer(info);
|
||||
if (err)
|
||||
@ -577,7 +577,7 @@ static int ep93xxfb_remove(struct platform_device *pdev)
|
||||
struct ep93xx_fbi *fbi = info->par;
|
||||
|
||||
unregister_framebuffer(info);
|
||||
clk_disable(fbi->clk);
|
||||
clk_disable_unprepare(fbi->clk);
|
||||
ep93xxfb_dealloc_videomem(info);
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
|
||||
|
@ -399,6 +399,9 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
{
|
||||
struct kyrofb_info *par = info->par;
|
||||
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) {
|
||||
printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel);
|
||||
return -EINVAL;
|
||||
|
@ -1084,6 +1084,9 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
int mode_valid = 0;
|
||||
|
||||
NVTRACE_ENTER();
|
||||
if (!var->pixclock)
|
||||
return -EINVAL;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 1 ... 8:
|
||||
var->red.offset = var->green.offset = var->blue.offset = 0;
|
||||
|
@ -82,6 +82,11 @@ struct ssd1307fb_par {
|
||||
struct regulator *vbat_reg;
|
||||
u32 vcomh;
|
||||
u32 width;
|
||||
/* Cached address ranges */
|
||||
u8 col_start;
|
||||
u8 col_end;
|
||||
u8 page_start;
|
||||
u8 page_end;
|
||||
};
|
||||
|
||||
struct ssd1307fb_array {
|
||||
@ -152,17 +157,72 @@ static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ssd1307fb_update_display(struct ssd1307fb_par *par)
|
||||
static int ssd1307fb_set_col_range(struct ssd1307fb_par *par, u8 col_start,
|
||||
u8 cols)
|
||||
{
|
||||
u8 col_end = col_start + cols - 1;
|
||||
int ret;
|
||||
|
||||
if (col_start == par->col_start && col_end == par->col_end)
|
||||
return 0;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, col_start);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, col_end);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
par->col_start = col_start;
|
||||
par->col_end = col_end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start,
|
||||
u8 pages)
|
||||
{
|
||||
u8 page_end = page_start + pages - 1;
|
||||
int ret;
|
||||
|
||||
if (page_start == par->page_start && page_end == par->page_end)
|
||||
return 0;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, page_start);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, page_end);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
par->page_start = page_start;
|
||||
par->page_end = page_end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x,
|
||||
unsigned int y, unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
struct ssd1307fb_array *array;
|
||||
u8 *vmem = par->info->screen_buffer;
|
||||
unsigned int line_length = par->info->fix.line_length;
|
||||
unsigned int pages = DIV_ROUND_UP(par->height, 8);
|
||||
int i, j, k;
|
||||
unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8);
|
||||
u32 array_idx = 0;
|
||||
int ret, i, j, k;
|
||||
|
||||
array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA);
|
||||
array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA);
|
||||
if (!array)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* The screen is divided in pages, each having a height of 8
|
||||
@ -193,27 +253,44 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par)
|
||||
* (5) A4 B4 C4 D4 E4 F4 G4 H4
|
||||
*/
|
||||
|
||||
for (i = 0; i < pages; i++) {
|
||||
for (j = 0; j < par->width; j++) {
|
||||
int m = 8;
|
||||
u32 array_idx = i * par->width + j;
|
||||
array->data[array_idx] = 0;
|
||||
/* Last page may be partial */
|
||||
if (i + 1 == pages && par->height % 8)
|
||||
m = par->height % 8;
|
||||
ret = ssd1307fb_set_col_range(par, par->col_offset + x, width);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages);
|
||||
if (ret < 0)
|
||||
goto out_free;
|
||||
|
||||
for (i = y / 8; i < y / 8 + pages; i++) {
|
||||
int m = 8;
|
||||
|
||||
/* Last page may be partial */
|
||||
if (8 * (i + 1) > par->height)
|
||||
m = par->height % 8;
|
||||
for (j = x; j < x + width; j++) {
|
||||
u8 data = 0;
|
||||
|
||||
for (k = 0; k < m; k++) {
|
||||
u8 byte = vmem[(8 * i + k) * line_length +
|
||||
j / 8];
|
||||
u8 bit = (byte >> (j % 8)) & 1;
|
||||
array->data[array_idx] |= bit << k;
|
||||
data |= bit << k;
|
||||
}
|
||||
array->data[array_idx++] = data;
|
||||
}
|
||||
}
|
||||
|
||||
ssd1307fb_write_array(par->client, array, par->width * pages);
|
||||
ret = ssd1307fb_write_array(par->client, array, width * pages);
|
||||
|
||||
out_free:
|
||||
kfree(array);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ssd1307fb_update_display(struct ssd1307fb_par *par)
|
||||
{
|
||||
return ssd1307fb_update_rect(par, 0, 0, par->width, par->height);
|
||||
}
|
||||
|
||||
static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -222,6 +299,7 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
|
||||
unsigned long total_size;
|
||||
unsigned long p = *ppos;
|
||||
void *dst;
|
||||
int ret;
|
||||
|
||||
total_size = info->fix.smem_len;
|
||||
|
||||
@ -239,7 +317,9 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf,
|
||||
if (copy_from_user(dst, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
ssd1307fb_update_display(par);
|
||||
ret = ssd1307fb_update_display(par);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*ppos += count;
|
||||
|
||||
@ -260,21 +340,24 @@ static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *r
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_fillrect(info, rect);
|
||||
ssd1307fb_update_display(par);
|
||||
ssd1307fb_update_rect(par, rect->dx, rect->dy, rect->width,
|
||||
rect->height);
|
||||
}
|
||||
|
||||
static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_copyarea(info, area);
|
||||
ssd1307fb_update_display(par);
|
||||
ssd1307fb_update_rect(par, area->dx, area->dy, area->width,
|
||||
area->height);
|
||||
}
|
||||
|
||||
static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct ssd1307fb_par *par = info->par;
|
||||
sys_imageblit(info, image);
|
||||
ssd1307fb_update_display(par);
|
||||
ssd1307fb_update_rect(par, image->dx, image->dy, image->width,
|
||||
image->height);
|
||||
}
|
||||
|
||||
static const struct fb_ops ssd1307fb_ops = {
|
||||
@ -454,36 +537,10 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Set column range */
|
||||
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, par->col_offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, par->col_offset + par->width - 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Set page range */
|
||||
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client, par->page_offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ssd1307fb_write_cmd(par->client,
|
||||
par->page_offset +
|
||||
DIV_ROUND_UP(par->height, 8) - 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Clear the screen */
|
||||
ssd1307fb_update_display(par);
|
||||
ret = ssd1307fb_update_display(par);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Turn on the display */
|
||||
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON);
|
||||
|
@ -58,12 +58,6 @@ struct drm_lock_data {
|
||||
* @refcount: Refcount for this master object.
|
||||
* @dev: Link back to the DRM device
|
||||
* @driver_priv: Pointer to driver-private information.
|
||||
* @lessor: Lease holder
|
||||
* @lessee_id: id for lessees. Owners always have id 0
|
||||
* @lessee_list: other lessees of the same master
|
||||
* @lessees: drm_masters leasing from this one
|
||||
* @leases: Objects leased to this drm_master.
|
||||
* @lessee_idr: All lessees under this owner (only used where lessor == NULL)
|
||||
*
|
||||
* Note that master structures are only relevant for the legacy/primary device
|
||||
* nodes, hence there can only be one per device, not one per drm_minor.
|
||||
@ -88,17 +82,68 @@ struct drm_master {
|
||||
struct idr magic_map;
|
||||
void *driver_priv;
|
||||
|
||||
/* Tree of display resource leases, each of which is a drm_master struct
|
||||
* All of these get activated simultaneously, so drm_device master points
|
||||
* at the top of the tree (for which lessor is NULL). Protected by
|
||||
* &drm_device.mode_config.idr_mutex.
|
||||
/**
|
||||
* @lessor:
|
||||
*
|
||||
* Lease grantor, only set if this &struct drm_master represents a
|
||||
* lessee holding a lease of objects from @lessor. Full owners of the
|
||||
* device have this set to NULL.
|
||||
*
|
||||
* The lessor does not change once it's set in drm_lease_create(), and
|
||||
* each lessee holds a reference to its lessor that it releases upon
|
||||
* being destroyed in drm_lease_destroy().
|
||||
*
|
||||
* See also the :ref:`section on display resource leasing
|
||||
* <drm_leasing>`.
|
||||
*/
|
||||
|
||||
struct drm_master *lessor;
|
||||
|
||||
/**
|
||||
* @lessee_id:
|
||||
*
|
||||
* ID for lessees. Owners (i.e. @lessor is NULL) always have ID 0.
|
||||
* Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex.
|
||||
*/
|
||||
int lessee_id;
|
||||
|
||||
/**
|
||||
* @lessee_list:
|
||||
*
|
||||
* List entry of lessees of @lessor, where they are linked to @lessees.
|
||||
* Not used for owners. Protected by &drm_device.mode_config's
|
||||
* &drm_mode_config.idr_mutex.
|
||||
*/
|
||||
struct list_head lessee_list;
|
||||
|
||||
/**
|
||||
* @lessees:
|
||||
*
|
||||
* List of drm_masters leasing from this one. Protected by
|
||||
* &drm_device.mode_config's &drm_mode_config.idr_mutex.
|
||||
*
|
||||
* This list is empty if no leases have been granted, or if all lessees
|
||||
* have been destroyed. Since lessors are referenced by all their
|
||||
* lessees, this master cannot be destroyed unless the list is empty.
|
||||
*/
|
||||
struct list_head lessees;
|
||||
|
||||
/**
|
||||
* @leases:
|
||||
*
|
||||
* Objects leased to this drm_master. Protected by
|
||||
* &drm_device.mode_config's &drm_mode_config.idr_mutex.
|
||||
*
|
||||
* Objects are leased all together in drm_lease_create(), and are
|
||||
* removed all together when the lease is revoked.
|
||||
*/
|
||||
struct idr leases;
|
||||
|
||||
/**
|
||||
* @lessee_idr:
|
||||
*
|
||||
* All lessees under this owner (only used where @lessor is NULL).
|
||||
* Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex.
|
||||
*/
|
||||
struct idr lessee_idr;
|
||||
/* private: */
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY)
|
||||
|
@ -64,7 +64,6 @@ struct drm_atomic_helper_damage_iter {
|
||||
bool full_update;
|
||||
};
|
||||
|
||||
void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
|
||||
void drm_atomic_helper_check_plane_damage(struct drm_atomic_state *state,
|
||||
struct drm_plane_state *plane_state);
|
||||
int drm_atomic_helper_dirtyfb(struct drm_framebuffer *fb,
|
||||
@ -82,21 +81,4 @@ bool drm_atomic_helper_damage_merged(const struct drm_plane_state *old_state,
|
||||
struct drm_plane_state *state,
|
||||
struct drm_rect *rect);
|
||||
|
||||
/**
|
||||
* drm_helper_get_plane_damage_clips - Returns damage clips in &drm_rect.
|
||||
* @state: Plane state.
|
||||
*
|
||||
* Returns plane damage rectangles in internal &drm_rect. Currently &drm_rect
|
||||
* can be obtained by simply typecasting &drm_mode_rect. This is because both
|
||||
* are signed 32 and during drm_atomic_check_only() it is verified that damage
|
||||
* clips are inside fb.
|
||||
*
|
||||
* Return: Clips in plane fb_damage_clips blob property.
|
||||
*/
|
||||
static inline struct drm_rect *
|
||||
drm_helper_get_plane_damage_clips(const struct drm_plane_state *state)
|
||||
{
|
||||
return (struct drm_rect *)drm_plane_get_damage_clips(state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,9 @@
|
||||
#ifndef __DRM_GEM_FB_HELPER_H__
|
||||
#define __DRM_GEM_FB_HELPER_H__
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-buf-map.h>
|
||||
|
||||
struct drm_afbc_framebuffer;
|
||||
struct drm_device;
|
||||
struct drm_fb_helper_surface_size;
|
||||
@ -34,6 +37,9 @@ struct drm_framebuffer *
|
||||
drm_gem_fb_create_with_dirty(struct drm_device *dev, struct drm_file *file,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd);
|
||||
|
||||
int drm_gem_fb_begin_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
|
||||
void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_direction dir);
|
||||
|
||||
#define drm_is_afbc(modifier) \
|
||||
(((modifier) & AFBC_VENDOR_AND_TYPE_MASK) == DRM_FORMAT_MOD_ARM_AFBC(0))
|
||||
|
||||
|
@ -124,15 +124,15 @@ struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
|
||||
/* enable hsync-end packets in vsync-pulse and v-porch area */
|
||||
#define MIPI_DSI_MODE_VIDEO_HSE BIT(4)
|
||||
/* disable hfront-porch area */
|
||||
#define MIPI_DSI_MODE_VIDEO_HFP BIT(5)
|
||||
#define MIPI_DSI_MODE_VIDEO_NO_HFP BIT(5)
|
||||
/* disable hback-porch area */
|
||||
#define MIPI_DSI_MODE_VIDEO_HBP BIT(6)
|
||||
#define MIPI_DSI_MODE_VIDEO_NO_HBP BIT(6)
|
||||
/* disable hsync-active area */
|
||||
#define MIPI_DSI_MODE_VIDEO_HSA BIT(7)
|
||||
#define MIPI_DSI_MODE_VIDEO_NO_HSA BIT(7)
|
||||
/* flush display FIFO on vsync pulse */
|
||||
#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8)
|
||||
/* disable EoT packets in HS mode */
|
||||
#define MIPI_DSI_MODE_EOT_PACKET BIT(9)
|
||||
#define MIPI_DSI_MODE_NO_EOT_PACKET BIT(9)
|
||||
/* device supports non-continuous clock behavior (DSI spec 5.6.1) */
|
||||
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
|
||||
/* transmit data in low power */
|
||||
|
@ -186,6 +186,9 @@ struct drm_plane_state {
|
||||
* since last plane update) as an array of &drm_mode_rect in framebuffer
|
||||
* coodinates of the attached framebuffer. Note that unlike plane src,
|
||||
* damage clips are not in 16.16 fixed point.
|
||||
*
|
||||
* See drm_plane_get_damage_clips() and
|
||||
* drm_plane_get_damage_clips_count() for accessing these.
|
||||
*/
|
||||
struct drm_property_blob *fb_damage_clips;
|
||||
|
||||
@ -894,38 +897,12 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
|
||||
|
||||
bool drm_any_plane_has_format(struct drm_device *dev,
|
||||
u32 format, u64 modifier);
|
||||
/**
|
||||
* drm_plane_get_damage_clips_count - Returns damage clips count.
|
||||
* @state: Plane state.
|
||||
*
|
||||
* Simple helper to get the number of &drm_mode_rect clips set by user-space
|
||||
* during plane update.
|
||||
*
|
||||
* Return: Number of clips in plane fb_damage_clips blob property.
|
||||
*/
|
||||
static inline unsigned int
|
||||
drm_plane_get_damage_clips_count(const struct drm_plane_state *state)
|
||||
{
|
||||
return (state && state->fb_damage_clips) ?
|
||||
state->fb_damage_clips->length/sizeof(struct drm_mode_rect) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_plane_get_damage_clips - Returns damage clips.
|
||||
* @state: Plane state.
|
||||
*
|
||||
* Note that this function returns uapi type &drm_mode_rect. Drivers might
|
||||
* instead be interested in internal &drm_rect which can be obtained by calling
|
||||
* drm_helper_get_plane_damage_clips().
|
||||
*
|
||||
* Return: Damage clips in plane fb_damage_clips blob property.
|
||||
*/
|
||||
static inline struct drm_mode_rect *
|
||||
drm_plane_get_damage_clips(const struct drm_plane_state *state)
|
||||
{
|
||||
return (struct drm_mode_rect *)((state && state->fb_damage_clips) ?
|
||||
state->fb_damage_clips->data : NULL);
|
||||
}
|
||||
void drm_plane_enable_fb_damage_clips(struct drm_plane *plane);
|
||||
unsigned int
|
||||
drm_plane_get_damage_clips_count(const struct drm_plane_state *state);
|
||||
struct drm_mode_rect *
|
||||
drm_plane_get_damage_clips(const struct drm_plane_state *state);
|
||||
|
||||
int drm_plane_create_scaling_filter_property(struct drm_plane *plane,
|
||||
unsigned int supported_filters);
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
/**
|
||||
* struct drm_property_enum - symbolic values for enumerations
|
||||
* @value: numeric property value for this enum entry
|
||||
* @head: list of enum values, linked to &drm_property.enum_list
|
||||
* @name: symbolic name for the enum
|
||||
*
|
||||
@ -39,6 +38,14 @@
|
||||
* decoding for each value. This is used for example for the rotation property.
|
||||
*/
|
||||
struct drm_property_enum {
|
||||
/**
|
||||
* @value: numeric property value for this enum entry
|
||||
*
|
||||
* If the property has the type &DRM_MODE_PROP_BITMASK, @value stores a
|
||||
* bitshift, not a bitmask. In other words, the enum entry is enabled
|
||||
* if the bit number @value is set in the property's value. This enum
|
||||
* entry has the bitmask ``1 << value``.
|
||||
*/
|
||||
uint64_t value;
|
||||
struct list_head head;
|
||||
char name[DRM_PROP_NAME_LEN];
|
||||
|
@ -39,6 +39,9 @@
|
||||
* @x2: horizontal ending coordinate (exclusive)
|
||||
* @y1: vertical starting coordinate (inclusive)
|
||||
* @y2: vertical ending coordinate (exclusive)
|
||||
*
|
||||
* Note that this must match the layout of struct drm_mode_rect or the damage
|
||||
* helpers like drm_atomic_helper_damage_iter_init() break.
|
||||
*/
|
||||
struct drm_rect {
|
||||
int x1, y1, x2, y2;
|
||||
|
@ -1050,6 +1050,16 @@ extern "C" {
|
||||
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
|
||||
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
|
||||
/**
|
||||
* DRM_IOCTL_MODE_RMFB - Remove a framebuffer.
|
||||
*
|
||||
* This removes a framebuffer previously added via ADDFB/ADDFB2. The IOCTL
|
||||
* argument is a framebuffer object ID.
|
||||
*
|
||||
* Warning: removing a framebuffer currently in-use on an enabled plane will
|
||||
* disable that plane. The CRTC the plane is linked to may also be disabled
|
||||
* (depending on driver capabilities).
|
||||
*/
|
||||
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
|
||||
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
|
||||
#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
|
||||
|
@ -900,9 +900,9 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
|
||||
|
||||
/*
|
||||
* The top 4 bits (out of the 56 bits alloted for specifying vendor specific
|
||||
* modifiers) denote the category for modifiers. Currently we have only two
|
||||
* categories of modifiers ie AFBC and MISC. We can have a maximum of sixteen
|
||||
* different categories.
|
||||
* modifiers) denote the category for modifiers. Currently we have three
|
||||
* categories of modifiers ie AFBC, MISC and AFRC. We can have a maximum of
|
||||
* sixteen different categories.
|
||||
*/
|
||||
#define DRM_FORMAT_MOD_ARM_CODE(__type, __val) \
|
||||
fourcc_mod_code(ARM, ((__u64)(__type) << 52) | ((__val) & 0x000fffffffffffffULL))
|
||||
@ -1017,6 +1017,109 @@ drm_fourcc_canonicalize_nvidia_format_mod(__u64 modifier)
|
||||
*/
|
||||
#define AFBC_FORMAT_MOD_USM (1ULL << 12)
|
||||
|
||||
/*
|
||||
* Arm Fixed-Rate Compression (AFRC) modifiers
|
||||
*
|
||||
* AFRC is a proprietary fixed rate image compression protocol and format,
|
||||
* designed to provide guaranteed bandwidth and memory footprint
|
||||
* reductions in graphics and media use-cases.
|
||||
*
|
||||
* AFRC buffers consist of one or more planes, with the same components
|
||||
* and meaning as an uncompressed buffer using the same pixel format.
|
||||
*
|
||||
* Within each plane, the pixel/luma/chroma values are grouped into
|
||||
* "coding unit" blocks which are individually compressed to a
|
||||
* fixed size (in bytes). All coding units within a given plane of a buffer
|
||||
* store the same number of values, and have the same compressed size.
|
||||
*
|
||||
* The coding unit size is configurable, allowing different rates of compression.
|
||||
*
|
||||
* The start of each AFRC buffer plane must be aligned to an alignment granule which
|
||||
* depends on the coding unit size.
|
||||
*
|
||||
* Coding Unit Size Plane Alignment
|
||||
* ---------------- ---------------
|
||||
* 16 bytes 1024 bytes
|
||||
* 24 bytes 512 bytes
|
||||
* 32 bytes 2048 bytes
|
||||
*
|
||||
* Coding units are grouped into paging tiles. AFRC buffer dimensions must be aligned
|
||||
* to a multiple of the paging tile dimensions.
|
||||
* The dimensions of each paging tile depend on whether the buffer is optimised for
|
||||
* scanline (SCAN layout) or rotated (ROT layout) access.
|
||||
*
|
||||
* Layout Paging Tile Width Paging Tile Height
|
||||
* ------ ----------------- ------------------
|
||||
* SCAN 16 coding units 4 coding units
|
||||
* ROT 8 coding units 8 coding units
|
||||
*
|
||||
* The dimensions of each coding unit depend on the number of components
|
||||
* in the compressed plane and whether the buffer is optimised for
|
||||
* scanline (SCAN layout) or rotated (ROT layout) access.
|
||||
*
|
||||
* Number of Components in Plane Layout Coding Unit Width Coding Unit Height
|
||||
* ----------------------------- --------- ----------------- ------------------
|
||||
* 1 SCAN 16 samples 4 samples
|
||||
* Example: 16x4 luma samples in a 'Y' plane
|
||||
* 16x4 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer
|
||||
* ----------------------------- --------- ----------------- ------------------
|
||||
* 1 ROT 8 samples 8 samples
|
||||
* Example: 8x8 luma samples in a 'Y' plane
|
||||
* 8x8 chroma 'V' values, in the 'V' plane of a fully-planar YUV buffer
|
||||
* ----------------------------- --------- ----------------- ------------------
|
||||
* 2 DONT CARE 8 samples 4 samples
|
||||
* Example: 8x4 chroma pairs in the 'UV' plane of a semi-planar YUV buffer
|
||||
* ----------------------------- --------- ----------------- ------------------
|
||||
* 3 DONT CARE 4 samples 4 samples
|
||||
* Example: 4x4 pixels in an RGB buffer without alpha
|
||||
* ----------------------------- --------- ----------------- ------------------
|
||||
* 4 DONT CARE 4 samples 4 samples
|
||||
* Example: 4x4 pixels in an RGB buffer with alpha
|
||||
*/
|
||||
|
||||
#define DRM_FORMAT_MOD_ARM_TYPE_AFRC 0x02
|
||||
|
||||
#define DRM_FORMAT_MOD_ARM_AFRC(__afrc_mode) \
|
||||
DRM_FORMAT_MOD_ARM_CODE(DRM_FORMAT_MOD_ARM_TYPE_AFRC, __afrc_mode)
|
||||
|
||||
/*
|
||||
* AFRC coding unit size modifier.
|
||||
*
|
||||
* Indicates the number of bytes used to store each compressed coding unit for
|
||||
* one or more planes in an AFRC encoded buffer. The coding unit size for chrominance
|
||||
* is the same for both Cb and Cr, which may be stored in separate planes.
|
||||
*
|
||||
* AFRC_FORMAT_MOD_CU_SIZE_P0 indicates the number of bytes used to store
|
||||
* each compressed coding unit in the first plane of the buffer. For RGBA buffers
|
||||
* this is the only plane, while for semi-planar and fully-planar YUV buffers,
|
||||
* this corresponds to the luma plane.
|
||||
*
|
||||
* AFRC_FORMAT_MOD_CU_SIZE_P12 indicates the number of bytes used to store
|
||||
* each compressed coding unit in the second and third planes in the buffer.
|
||||
* For semi-planar and fully-planar YUV buffers, this corresponds to the chroma plane(s).
|
||||
*
|
||||
* For single-plane buffers, AFRC_FORMAT_MOD_CU_SIZE_P0 must be specified
|
||||
* and AFRC_FORMAT_MOD_CU_SIZE_P12 must be zero.
|
||||
* For semi-planar and fully-planar buffers, both AFRC_FORMAT_MOD_CU_SIZE_P0 and
|
||||
* AFRC_FORMAT_MOD_CU_SIZE_P12 must be specified.
|
||||
*/
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_MASK 0xf
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_16 (1ULL)
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_24 (2ULL)
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_32 (3ULL)
|
||||
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_P0(__afrc_cu_size) (__afrc_cu_size)
|
||||
#define AFRC_FORMAT_MOD_CU_SIZE_P12(__afrc_cu_size) ((__afrc_cu_size) << 4)
|
||||
|
||||
/*
|
||||
* AFRC scanline memory layout.
|
||||
*
|
||||
* Indicates if the buffer uses the scanline-optimised layout
|
||||
* for an AFRC encoded buffer, otherwise, it uses the rotation-optimised layout.
|
||||
* The memory layout is the same for all planes.
|
||||
*/
|
||||
#define AFRC_FORMAT_MOD_LAYOUT_SCAN (1ULL << 8)
|
||||
|
||||
/*
|
||||
* Arm 16x16 Block U-Interleaved modifier
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user