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:
Dave Airlie 2021-07-30 14:51:22 +10:00
commit cfeeb0b5e0
84 changed files with 1795 additions and 678 deletions

View file

@ -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

View file

@ -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".

View 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>;
};
};

View file

@ -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>;
};

View file

@ -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,.*":

View file

@ -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

View file

@ -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
---------------------------

View file

@ -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
==================================

View file

@ -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/

View file

@ -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) {

View file

@ -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) {

View file

@ -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)

View file

@ -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) {

View file

@ -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);
}
/*

View file

@ -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;
}

View file

@ -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);

View file

@ -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. */

View file

@ -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;
}

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}

View file

@ -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 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
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 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
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);
}

View file

@ -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)
{

View file

@ -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)

View file

@ -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);

View file

@ -1397,6 +1397,110 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
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)

View file

@ -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

View file

@ -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) {

View file

@ -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 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
}
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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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,
},
};

View file

@ -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 {

View file

@ -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);

View file

@ -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)

View file

@ -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,

View file

@ -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;

View file

@ -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,

View file

@ -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);

View file

@ -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, &ltk050h3146w_funcs,
DRM_MODE_CONNECTOR_DSI);

View file

@ -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, &ltk500hd1829_funcs,
DRM_MODE_CONNECTOR_DSI);

View file

@ -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)

View file

@ -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";

View file

@ -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);

View file

@ -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)

View file

@ -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,
};

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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.

View file

@ -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 */ }
};

View file

@ -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:

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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, &params->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",
};

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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:

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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

View file

@ -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))

View file

@ -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 */

View file

@ -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);

View file

@ -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];

View file

@ -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;

View file

@ -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)

View file

@ -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
*