drm-misc-next for v5.9:
UAPI Changes: Cross-subsystem Changes: - Add ckoenig as dma-buf maintainer. - Revert invalid fix for dma-fence-chain, and fix selftest. - Add fixmes to amifb about APUS support. - Use array3_size in fbcon_prepare_logo, and struct_size() in alloc_apertures. - Fix leaks in neofb, fb/savage and omapfb. - Other small fixes to fb code. - Convert some dt bindings to schema for some panels, and fix simple-framebuffer dt example. Core Changes: - Add DRM_FORMAT_MOD_GENERIC_16_16_TILE as alias to DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, as it can be used more generic. - Add support for multiple DispID extension blocks in edid. - Use https instead of http for some of the urls. - Use drm_* macros for logging in mipi-dsi and fb-helper. - Further cleanup ttm_mem_reg handling. - Remove duplicated words in comments. Driver Changes: - Use __drm_atomic_helper_crtc_reset in all atomic drivers. - Add Amlogic Video FBC support to meson and fourcc to core. - Refactor hisilicon's hibmc_drv_vdac. - Create a TXP CRTC for vc4. - Rework cursor support in ast. - Fix runtime PM in STM. - Allow bigger cursors in vkms. - Cleanup sg handling in radeon and amdgpu, and stop creating dummy gtt nodes with ttm fixed. - Rework crtc handling in mgag200. - Miscellaneous small fixes to meson, vgem, bridge/dw-hdmi, panel/auo,b116xw03, panel/LG LB070WV8, lima, bridge/sil_sii8620, virtio, tilcdc. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAl8QO6cACgkQ/lWMcqZw E8O/xxAAick0N8Q8sf0bL7Emh7iiHeUl2fWzbfQ8VmKEOjoScO9KYz7SSuSW8868 qsy1pdI+T/ko2shl9w8hZ8aunNDOdCycL7F3WNSKT+SNAP2XY7R57xXjn0NCsfm/ iY3RsST6vU1gJMFyS/6U+4OddbTcqjDT5dwSD26/kva86s2CiS/P/I6dxoH0bcDg Yo9QcNflZKjnP/0imRYDAmm3y7N09VKtYa2Df5dOCJiiijXxMTSQN6TB/TfFtYTi CfyIm7dEF1Nnmy+jlxiYxAXVZYlPvIJ/7nTInO/gRGLhiEyIuG9u1lZSna9kRGrn 5eg+41u4sq3YnDB5+qZmMJ7yBKFIy51+5JweVQeaykBW8p4Z4Qrir2ENPLZWuyeC CR1cOUUrUkSaMThy2H6IPe+T6BDzKpceuHnOxv7MmTfBSzLwRR7Bn216zrC33sET i6AsS6Ir+lfkH26oGceceEHdL5biMjFuRPiq8MfzzEfnh1o7RZ2wvEg7gHV/QeiE ugD7peLR28gJnupFQyBzcbyqKr761W7twgwAOvEOo3Up1LldxYLmQmc3VQeB84j2 mndhyBfXD6Jniuit2+PxuNXGRcK1oYExRxJKD9msZCkUMe1pezSDrHZcc+emnh2G bqy8EPWcpCL0KkO/xICdJx57UwaLfAMsyP1C4u0vxy2GGSirxeg= =XKYB -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-07-16' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.9: UAPI Changes: Cross-subsystem Changes: - Add ckoenig as dma-buf maintainer. - Revert invalid fix for dma-fence-chain, and fix selftest. - Add fixmes to amifb about APUS support. - Use array3_size in fbcon_prepare_logo, and struct_size() in alloc_apertures. - Fix leaks in neofb, fb/savage and omapfb. - Other small fixes to fb code. - Convert some dt bindings to schema for some panels, and fix simple-framebuffer dt example. Core Changes: - Add DRM_FORMAT_MOD_GENERIC_16_16_TILE as alias to DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, as it can be used more generic. - Add support for multiple DispID extension blocks in edid. - Use https instead of http for some of the urls. - Use drm_* macros for logging in mipi-dsi and fb-helper. - Further cleanup ttm_mem_reg handling. - Remove duplicated words in comments. Driver Changes: - Use __drm_atomic_helper_crtc_reset in all atomic drivers. - Add Amlogic Video FBC support to meson and fourcc to core. - Refactor hisilicon's hibmc_drv_vdac. - Create a TXP CRTC for vc4. - Rework cursor support in ast. - Fix runtime PM in STM. - Allow bigger cursors in vkms. - Cleanup sg handling in radeon and amdgpu, and stop creating dummy gtt nodes with ttm fixed. - Rework crtc handling in mgag200. - Miscellaneous small fixes to meson, vgem, bridge/dw-hdmi, panel/auo,b116xw03, panel/LG LB070WV8, lima, bridge/sil_sii8620, virtio, tilcdc. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/8b360d65-f228-9286-d247-3004156a5254@linux.intel.com
This commit is contained in:
commit
3ffff3c685
|
@ -45,16 +45,6 @@ examples:
|
|||
- |
|
||||
#include <dt-bindings/clock/bcm2835.h>
|
||||
|
||||
panel: panel {
|
||||
compatible = "ontat,yx700wv03", "simple-panel";
|
||||
|
||||
port {
|
||||
panel_in: endpoint {
|
||||
remote-endpoint = <&dpi_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
dpi: dpi@7e208000 {
|
||||
compatible = "brcm,bcm2835-dpi";
|
||||
reg = <0x7e208000 0x8c>;
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
Renesas R-Car LVDS Encoder
|
||||
==========================
|
||||
|
||||
These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
|
||||
Gen2, R-Car Gen3 and RZ/G SoCs.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : Shall contain one of
|
||||
- "renesas,r8a7743-lvds" for R8A7743 (RZ/G1M) compatible LVDS encoders
|
||||
- "renesas,r8a7744-lvds" for R8A7744 (RZ/G1N) compatible LVDS encoders
|
||||
- "renesas,r8a774a1-lvds" for R8A774A1 (RZ/G2M) compatible LVDS encoders
|
||||
- "renesas,r8a774b1-lvds" for R8A774B1 (RZ/G2N) compatible LVDS encoders
|
||||
- "renesas,r8a774c0-lvds" for R8A774C0 (RZ/G2E) compatible LVDS encoders
|
||||
- "renesas,r8a7790-lvds" for R8A7790 (R-Car H2) compatible LVDS encoders
|
||||
- "renesas,r8a7791-lvds" for R8A7791 (R-Car M2-W) compatible LVDS encoders
|
||||
- "renesas,r8a7793-lvds" for R8A7793 (R-Car M2-N) compatible LVDS encoders
|
||||
- "renesas,r8a7795-lvds" for R8A7795 (R-Car H3) compatible LVDS encoders
|
||||
- "renesas,r8a7796-lvds" for R8A7796 (R-Car M3-W) compatible LVDS encoders
|
||||
- "renesas,r8a77965-lvds" for R8A77965 (R-Car M3-N) compatible LVDS encoders
|
||||
- "renesas,r8a77970-lvds" for R8A77970 (R-Car V3M) compatible LVDS encoders
|
||||
- "renesas,r8a77980-lvds" for R8A77980 (R-Car V3H) compatible LVDS encoders
|
||||
- "renesas,r8a77990-lvds" for R8A77990 (R-Car E3) compatible LVDS encoders
|
||||
- "renesas,r8a77995-lvds" for R8A77995 (R-Car D3) compatible LVDS encoders
|
||||
|
||||
- reg: Base address and length for the memory-mapped registers
|
||||
- clocks: A list of phandles + clock-specifier pairs, one for each entry in
|
||||
the clock-names property.
|
||||
- clock-names: Name of the clocks. This property is model-dependent.
|
||||
- The functional clock, which mandatory for all models, shall be listed
|
||||
first, and shall be named "fck".
|
||||
- On R8A77990, R8A77995 and R8A774C0, the LVDS encoder can use the EXTAL or
|
||||
DU_DOTCLKINx clocks. Those clocks are optional. When supplied they must be
|
||||
named "extal" and "dclkin.x" respectively, with "x" being the DU_DOTCLKIN
|
||||
numerical index.
|
||||
- When the clocks property only contains the functional clock, the
|
||||
clock-names property may be omitted.
|
||||
- resets: A phandle + reset specifier for the module reset
|
||||
|
||||
Required nodes:
|
||||
|
||||
The LVDS encoder has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
- Video port 0 corresponds to the parallel RGB input
|
||||
- Video port 1 corresponds to the LVDS output
|
||||
|
||||
Each port shall have a single endpoint.
|
||||
|
||||
Optional properties:
|
||||
|
||||
- renesas,companion : phandle to the companion LVDS encoder. This property is
|
||||
mandatory for the first LVDS encoder on D3 and E3 SoCs, and shall point to
|
||||
the second encoder to be used as a companion in dual-link mode. It shall not
|
||||
be set for any other LVDS encoder.
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
lvds0: lvds@feb90000 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0 0xfeb90000 0 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>;
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
renesas,companion = <&lvds1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds0_out: endpoint {
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,248 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/bridge/renesas,lvds.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Renesas R-Car LVDS Encoder
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
|
||||
description: |
|
||||
These DT bindings describe the LVDS encoder embedded in the Renesas R-Car
|
||||
Gen2, R-Car Gen3, RZ/G1 and RZ/G2 SoCs.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r8a7743-lvds # for RZ/G1M compatible LVDS encoders
|
||||
- renesas,r8a7744-lvds # for RZ/G1N compatible LVDS encoders
|
||||
- renesas,r8a774a1-lvds # for RZ/G2M compatible LVDS encoders
|
||||
- renesas,r8a774b1-lvds # for RZ/G2N compatible LVDS encoders
|
||||
- renesas,r8a774c0-lvds # for RZ/G2E compatible LVDS encoders
|
||||
- renesas,r8a7790-lvds # for R-Car H2 compatible LVDS encoders
|
||||
- renesas,r8a7791-lvds # for R-Car M2-W compatible LVDS encoders
|
||||
- renesas,r8a7793-lvds # for R-Car M2-N compatible LVDS encoders
|
||||
- renesas,r8a7795-lvds # for R-Car H3 compatible LVDS encoders
|
||||
- renesas,r8a7796-lvds # for R-Car M3-W compatible LVDS encoders
|
||||
- renesas,r8a77965-lvds # for R-Car M3-N compatible LVDS encoders
|
||||
- renesas,r8a77970-lvds # for R-Car V3M compatible LVDS encoders
|
||||
- renesas,r8a77980-lvds # for R-Car V3H compatible LVDS encoders
|
||||
- renesas,r8a77990-lvds # for R-Car E3 compatible LVDS encoders
|
||||
- renesas,r8a77995-lvds # for R-Car D3 compatible LVDS encoders
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description: |
|
||||
This device has two video ports. Their connections are modelled using the
|
||||
OF graph bindings specified in Documentation/devicetree/bindings/graph.txt.
|
||||
Each port shall have a single endpoint.
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
description: Parallel RGB input port
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
description: LVDS output port
|
||||
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
renesas,companion:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
phandle to the companion LVDS encoder. This property is mandatory
|
||||
for the first LVDS encoder on D3 and E3 SoCs, and shall point to
|
||||
the second encoder to be used as a companion in dual-link mode. It
|
||||
shall not be set for any other LVDS encoder.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- power-domains
|
||||
- resets
|
||||
- ports
|
||||
|
||||
if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- renesas,r8a774c0-lvds
|
||||
- renesas,r8a77990-lvds
|
||||
- renesas,r8a77995-lvds
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
- description: Functional clock
|
||||
- description: EXTAL input clock
|
||||
- description: DU_DOTCLKIN0 input clock
|
||||
- description: DU_DOTCLKIN1 input clock
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
items:
|
||||
- const: fck
|
||||
# The LVDS encoder can use the EXTAL or DU_DOTCLKINx clocks.
|
||||
# These clocks are optional.
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
- enum:
|
||||
- extal
|
||||
- dclkin.0
|
||||
- dclkin.1
|
||||
|
||||
required:
|
||||
- clock-names
|
||||
|
||||
else:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 1
|
||||
items:
|
||||
- description: Functional clock
|
||||
|
||||
clock-names:
|
||||
maxItems: 1
|
||||
items:
|
||||
- const: fck
|
||||
|
||||
renesas,companion: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a7795-sysc.h>
|
||||
|
||||
lvds@feb90000 {
|
||||
compatible = "renesas,r8a7795-lvds";
|
||||
reg = <0xfeb90000 0x14>;
|
||||
clocks = <&cpg CPG_MOD 727>;
|
||||
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds_out: endpoint {
|
||||
remote-endpoint = <&panel_in>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
#include <dt-bindings/power/r8a77990-sysc.h>
|
||||
|
||||
lvds0: lvds@feb90000 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0xfeb90000 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>,
|
||||
<&x13_clk>,
|
||||
<&extal_clk>;
|
||||
clock-names = "fck", "dclkin.0", "extal";
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 727>;
|
||||
|
||||
renesas,companion = <&lvds1>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds0_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds0>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds0_out: endpoint {
|
||||
remote-endpoint = <&panel_in1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lvds1: lvds@feb90100 {
|
||||
compatible = "renesas,r8a77990-lvds";
|
||||
reg = <0xfeb90100 0x20>;
|
||||
clocks = <&cpg CPG_MOD 727>,
|
||||
<&x13_clk>,
|
||||
<&extal_clk>;
|
||||
clock-names = "fck", "dclkin.0", "extal";
|
||||
power-domains = <&sysc R8A77990_PD_ALWAYS_ON>;
|
||||
resets = <&cpg 726>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
reg = <0>;
|
||||
lvds1_in: endpoint {
|
||||
remote-endpoint = <&du_out_lvds1>;
|
||||
};
|
||||
};
|
||||
port@1 {
|
||||
reg = <1>;
|
||||
lvds1_out: endpoint {
|
||||
remote-endpoint = <&panel_in2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,31 +0,0 @@
|
|||
Analog TV Connector
|
||||
===================
|
||||
|
||||
Required properties:
|
||||
- compatible: "composite-video-connector" or "svideo-connector"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- sdtv-standards: limit the supported TV standards on a connector to the given
|
||||
ones. If not specified all TV standards are allowed.
|
||||
Possible TV standards are defined in
|
||||
include/dt-bindings/display/sdtv-standards.h.
|
||||
|
||||
Required nodes:
|
||||
- Video port for TV input
|
||||
|
||||
Example
|
||||
-------
|
||||
#include <dt-bindings/display/sdtv-standards.h>
|
||||
|
||||
tv: connector {
|
||||
compatible = "composite-video-connector";
|
||||
label = "tv";
|
||||
sdtv-standards = <(SDTV_STD_PAL | SDTV_STD_NTSC)>;
|
||||
|
||||
port {
|
||||
tv_connector_in: endpoint {
|
||||
remote-endpoint = <&venc_out>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/analog-tv-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Analog TV Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- composite-video-connector
|
||||
- svideo-connector
|
||||
|
||||
label: true
|
||||
|
||||
sdtv-standards:
|
||||
description:
|
||||
Limit the supported TV standards on a connector to the given ones. If
|
||||
not specified all TV standards are allowed. Possible TV standards are
|
||||
defined in include/dt-bindings/display/sdtv-standards.h.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
port:
|
||||
description: Connection to controller providing analog TV signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/display/sdtv-standards.h>
|
||||
|
||||
connector {
|
||||
compatible = "composite-video-connector";
|
||||
label = "tv";
|
||||
sdtv-standards = <(SDTV_STD_PAL | SDTV_STD_NTSC)>;
|
||||
|
||||
port {
|
||||
tv_connector_in: endpoint {
|
||||
remote-endpoint = <&venc_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,36 +0,0 @@
|
|||
DVI Connector
|
||||
==============
|
||||
|
||||
Required properties:
|
||||
- compatible: "dvi-connector"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- ddc-i2c-bus: phandle to the i2c bus that is connected to DVI DDC
|
||||
- analog: the connector has DVI analog pins
|
||||
- digital: the connector has DVI digital pins
|
||||
- dual-link: the connector has pins for DVI dual-link
|
||||
- hpd-gpios: HPD GPIO number
|
||||
|
||||
Required nodes:
|
||||
- Video port for DVI input
|
||||
|
||||
Note: One (or both) of 'analog' or 'digital' must be set.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
dvi0: connector@0 {
|
||||
compatible = "dvi-connector";
|
||||
label = "dvi";
|
||||
|
||||
digital;
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
dvi_connector_in: endpoint {
|
||||
remote-endpoint = <&tfp410_out>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/dvi-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: DVI Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: dvi-connector
|
||||
|
||||
label: true
|
||||
|
||||
hpd-gpios:
|
||||
description: A GPIO line connected to HPD
|
||||
maxItems: 1
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
analog:
|
||||
type: boolean
|
||||
description: the connector has DVI analog pins
|
||||
|
||||
digital:
|
||||
type: boolean
|
||||
description: the connector has DVI digital pins
|
||||
|
||||
dual-link:
|
||||
type: boolean
|
||||
description: the connector has pins for DVI dual-link
|
||||
|
||||
port:
|
||||
description: Connection to controller providing DVI signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- analog
|
||||
- required:
|
||||
- digital
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "dvi-connector";
|
||||
label = "dvi";
|
||||
|
||||
digital;
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
dvi_connector_in: endpoint {
|
||||
remote-endpoint = <&tfp410_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,31 +0,0 @@
|
|||
HDMI Connector
|
||||
==============
|
||||
|
||||
Required properties:
|
||||
- compatible: "hdmi-connector"
|
||||
- type: the HDMI connector type: "a", "b", "c", "d" or "e"
|
||||
|
||||
Optional properties:
|
||||
- label: a symbolic name for the connector
|
||||
- hpd-gpios: HPD GPIO number
|
||||
- ddc-i2c-bus: phandle link to the I2C controller used for DDC EDID probing
|
||||
- ddc-en-gpios: signal to enable DDC bus
|
||||
|
||||
Required nodes:
|
||||
- Video port for HDMI input
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
hdmi0: connector@1 {
|
||||
compatible = "hdmi-connector";
|
||||
label = "hdmi";
|
||||
|
||||
type = "a";
|
||||
|
||||
port {
|
||||
hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&tpd12s015_out>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/hdmi-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: HDMI Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: hdmi-connector
|
||||
|
||||
type:
|
||||
description: The HDMI connector type
|
||||
enum:
|
||||
- a # Standard full size
|
||||
- b # Never deployed?
|
||||
- c # Mini
|
||||
- d # Micro
|
||||
- e # automotive
|
||||
|
||||
label: true
|
||||
|
||||
hpd-gpios:
|
||||
description: A GPIO line connected to HPD
|
||||
maxItems: 1
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
ddc-en-gpios:
|
||||
description: GPIO signal to enable DDC bus
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
description: Connection to controller providing HDMI signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
- type
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "hdmi-connector";
|
||||
label = "hdmi";
|
||||
|
||||
type = "a";
|
||||
|
||||
port {
|
||||
hdmi_connector_in: endpoint {
|
||||
remote-endpoint = <&tpd12s015_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,36 +0,0 @@
|
|||
VGA Connector
|
||||
=============
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "vga-connector"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- label: a symbolic name for the connector corresponding to a hardware label
|
||||
- ddc-i2c-bus: phandle to the I2C bus that is connected to VGA DDC
|
||||
|
||||
Required nodes:
|
||||
|
||||
The VGA connector internal connections are modeled using the OF graph bindings
|
||||
specified in Documentation/devicetree/bindings/graph.txt.
|
||||
|
||||
The VGA connector has a single port that must be connected to a video source
|
||||
port.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
vga0: connector@0 {
|
||||
compatible = "vga-connector";
|
||||
label = "vga";
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
vga_connector_in: endpoint {
|
||||
remote-endpoint = <&adv7123_out>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/vga-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: VGA Connector
|
||||
|
||||
maintainers:
|
||||
- Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: vga-connector
|
||||
|
||||
label: true
|
||||
|
||||
ddc-i2c-bus:
|
||||
description: phandle link to the I2C controller used for DDC EDID probing
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
|
||||
port:
|
||||
description: Connection to controller providing VGA signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "vga-connector";
|
||||
label = "vga";
|
||||
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
|
||||
port {
|
||||
vga_connector_in: endpoint {
|
||||
remote-endpoint = <&adv7123_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,22 +0,0 @@
|
|||
Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "innolux,p079zca"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
- power-supply: phandle of the regulator that provides the supply voltage
|
||||
- enable-gpios: panel enable gpio
|
||||
|
||||
Optional properties:
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
|
||||
Example:
|
||||
|
||||
&mipi_dsi {
|
||||
panel@0 {
|
||||
compatible = "innolux,p079zca";
|
||||
reg = <0>;
|
||||
power-supply = <...>;
|
||||
backlight = <&backlight>;
|
||||
enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
|
@ -33,6 +33,8 @@ properties:
|
|||
- auo,b080uan01
|
||||
# Boe Corporation 8.0" WUXGA TFT LCD panel
|
||||
- boe,tv080wum-nl0
|
||||
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
- innolux,p079zca
|
||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||
- kingdisplay,kd097d04
|
||||
# LG ACX467AKM-7 4.95" 1080×1920 LCD Panel
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
Rocktech jh057n00900 5.5" 720x1440 TFT LCD panel
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "rocktech,jh057n00900"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
- reset-gpios: panel reset gpio
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
- vcc-supply: phandle of the regulator that provides the vcc supply voltage.
|
||||
- iovcc-supply: phandle of the regulator that provides the iovcc supply
|
||||
voltage.
|
||||
|
||||
Example:
|
||||
|
||||
&mipi_dsi {
|
||||
panel@0 {
|
||||
compatible = "rocktech,jh057n00900";
|
||||
reg = <0>;
|
||||
backlight = <&backlight>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,70 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/rocktech,jh057n00900.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
|
||||
|
||||
maintainers:
|
||||
- Ondrej Jirman <megi@xff.cz>
|
||||
|
||||
description: |
|
||||
Rocktech JH057N00900 is a 720x1440 TFT LCD panel
|
||||
connected using a MIPI-DSI video interface.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
# Rocktech JH057N00900 5.5" 720x1440 TFT LCD panel
|
||||
- rocktech,jh057n00900
|
||||
# Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
|
||||
- xingbangda,xbd599
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
description: DSI virtual channel
|
||||
|
||||
vcc-supply:
|
||||
description: Panel power supply
|
||||
|
||||
iovcc-supply:
|
||||
description: I/O voltage supply
|
||||
|
||||
reset-gpios:
|
||||
description: GPIO used for the reset pin
|
||||
maxItems: 1
|
||||
|
||||
backlight:
|
||||
description: Backlight used by the panel
|
||||
$ref: "/schemas/types.yaml#/definitions/phandle"
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vcc-supply
|
||||
- iovcc-supply
|
||||
- reset-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
panel@0 {
|
||||
compatible = "rocktech,jh057n00900";
|
||||
reg = <0>;
|
||||
vcc-supply = <®_2v8_p>;
|
||||
iovcc-supply = <®_1v8_p>;
|
||||
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
...
|
|
@ -1,56 +0,0 @@
|
|||
Samsung S6E8AA0 AMOLED LCD 5.3 inch panel
|
||||
|
||||
Required properties:
|
||||
- compatible: "samsung,s6e8aa0"
|
||||
- reg: the virtual channel number of a DSI peripheral
|
||||
- vdd3-supply: core voltage supply
|
||||
- vci-supply: voltage supply for analog circuits
|
||||
- reset-gpios: a GPIO spec for the reset pin
|
||||
- display-timings: timings for the connected panel as described by [1]
|
||||
|
||||
Optional properties:
|
||||
- power-on-delay: delay after turning regulators on [ms]
|
||||
- reset-delay: delay after reset sequence [ms]
|
||||
- init-delay: delay after initialization sequence [ms]
|
||||
- panel-width-mm: physical panel width [mm]
|
||||
- panel-height-mm: physical panel height [mm]
|
||||
- flip-horizontal: boolean to flip image horizontally
|
||||
- flip-vertical: boolean to flip image vertically
|
||||
|
||||
The device node can contain one 'port' child node with one child
|
||||
'endpoint' node, according to the bindings defined in [2]. This
|
||||
node should describe panel's video bus.
|
||||
|
||||
[1]: Documentation/devicetree/bindings/display/panel/display-timing.txt
|
||||
[2]: Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
Example:
|
||||
|
||||
panel {
|
||||
compatible = "samsung,s6e8aa0";
|
||||
reg = <0>;
|
||||
vdd3-supply = <&vcclcd_reg>;
|
||||
vci-supply = <&vlcd_reg>;
|
||||
reset-gpios = <&gpy4 5 0>;
|
||||
power-on-delay= <50>;
|
||||
reset-delay = <100>;
|
||||
init-delay = <100>;
|
||||
panel-width-mm = <58>;
|
||||
panel-height-mm = <103>;
|
||||
flip-horizontal;
|
||||
flip-vertical;
|
||||
|
||||
display-timings {
|
||||
timing0: timing-0 {
|
||||
clock-frequency = <57153600>;
|
||||
hactive = <720>;
|
||||
vactive = <1280>;
|
||||
hfront-porch = <5>;
|
||||
hback-porch = <5>;
|
||||
hsync-len = <5>;
|
||||
vfront-porch = <13>;
|
||||
vback-porch = <1>;
|
||||
vsync-len = <2>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/samsung,s6e8aa0.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Samsung S6E8AA0 AMOLED LCD 5.3 inch panel
|
||||
|
||||
maintainers:
|
||||
- Andrzej Hajda <a.hajda@samsung.com>
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: samsung,s6e8aa0
|
||||
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
display-timings: true
|
||||
|
||||
vdd3-supply:
|
||||
description: core voltage supply
|
||||
|
||||
vci-supply:
|
||||
description: voltage supply for analog circuits
|
||||
|
||||
power-on-delay:
|
||||
description: delay after turning regulators on [ms]
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
reset-delay:
|
||||
description: delay after reset sequence [ms]
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
|
||||
init-delay:
|
||||
description: delay after initialization sequence [ms]
|
||||
|
||||
panel-width-mm:
|
||||
description: physical panel width [mm]
|
||||
|
||||
panel-height-mm:
|
||||
description: physical panel height [mm]
|
||||
|
||||
flip-horizontal:
|
||||
description: boolean to flip image horizontally
|
||||
type: boolean
|
||||
|
||||
flip-vertical:
|
||||
description: boolean to flip image vertically
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vdd3-supply
|
||||
- vci-supply
|
||||
- reset-gpios
|
||||
- display-timings
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "samsung,s6e8aa0";
|
||||
reg = <0>;
|
||||
vdd3-supply = <&vcclcd_reg>;
|
||||
vci-supply = <&vlcd_reg>;
|
||||
reset-gpios = <&gpy4 5 0>;
|
||||
power-on-delay= <50>;
|
||||
reset-delay = <100>;
|
||||
init-delay = <100>;
|
||||
panel-width-mm = <58>;
|
||||
panel-height-mm = <103>;
|
||||
flip-horizontal;
|
||||
flip-vertical;
|
||||
|
||||
display-timings {
|
||||
timing0: timing-0 {
|
||||
clock-frequency = <57153600>;
|
||||
hactive = <720>;
|
||||
vactive = <1280>;
|
||||
hfront-porch = <5>;
|
||||
hback-porch = <5>;
|
||||
hsync-len = <5>;
|
||||
vfront-porch = <13>;
|
||||
vback-porch = <1>;
|
||||
vsync-len = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,49 +0,0 @@
|
|||
Sharp Microelectronics 10.1" WQXGA TFT LCD panel
|
||||
|
||||
This panel requires a dual-channel DSI host to operate. It supports two modes:
|
||||
- left-right: each channel drives the left or right half of the screen
|
||||
- even-odd: each channel drives the even or odd lines of the screen
|
||||
|
||||
Each of the DSI channels controls a separate DSI peripheral. The peripheral
|
||||
driven by the first link (DSI-LINK1), left or even, is considered the primary
|
||||
peripheral and controls the device. The 'link2' property contains a phandle
|
||||
to the peripheral driven by the second link (DSI-LINK2, right or odd).
|
||||
|
||||
Note that in video mode the DSI-LINK1 interface always provides the left/even
|
||||
pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
|
||||
is possible to program either link to drive the left/even or right/odd pixels
|
||||
but for the sake of consistency this binding assumes that the same assignment
|
||||
is chosen as for video mode.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "sharp,lq101r1sx01"
|
||||
- reg: DSI virtual channel of the peripheral
|
||||
|
||||
Required properties (for DSI-LINK1 only):
|
||||
- link2: phandle to the DSI peripheral on the secondary link. Note that the
|
||||
presence of this property marks the containing node as DSI-LINK1.
|
||||
- power-supply: phandle of the regulator that provides the supply voltage
|
||||
|
||||
Optional properties (for DSI-LINK1 only):
|
||||
- backlight: phandle of the backlight device attached to the panel
|
||||
|
||||
Example:
|
||||
|
||||
dsi@54300000 {
|
||||
panel: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
|
||||
link2 = <&secondary>;
|
||||
|
||||
power-supply = <...>;
|
||||
backlight = <...>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi@54400000 {
|
||||
secondary: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,87 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/panel/sharp,lq101r1sx01.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sharp Microelectronics 10.1" WQXGA TFT LCD panel
|
||||
|
||||
maintainers:
|
||||
- Thierry Reding <treding@nvidia.com>
|
||||
|
||||
description: |
|
||||
This panel requires a dual-channel DSI host to operate. It supports two modes:
|
||||
- left-right: each channel drives the left or right half of the screen
|
||||
- even-odd: each channel drives the even or odd lines of the screen
|
||||
|
||||
Each of the DSI channels controls a separate DSI peripheral. The peripheral
|
||||
driven by the first link (DSI-LINK1), left or even, is considered the primary
|
||||
peripheral and controls the device. The 'link2' property contains a phandle
|
||||
to the peripheral driven by the second link (DSI-LINK2, right or odd).
|
||||
|
||||
Note that in video mode the DSI-LINK1 interface always provides the left/even
|
||||
pixels and DSI-LINK2 always provides the right/odd pixels. In command mode it
|
||||
is possible to program either link to drive the left/even or right/odd pixels
|
||||
but for the sake of consistency this binding assumes that the same assignment
|
||||
is chosen as for video mode.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sharp,lq101r1sx01
|
||||
|
||||
reg: true
|
||||
power-supply: true
|
||||
backlight: true
|
||||
|
||||
link2:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description: |
|
||||
phandle to the DSI peripheral on the secondary link. Note that the
|
||||
presence of this property marks the containing node as DSI-LINK1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
if:
|
||||
required:
|
||||
- link2
|
||||
then:
|
||||
required:
|
||||
- power-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
dsi0: dsi@fd922800 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfd922800 0x200>;
|
||||
|
||||
panel: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
|
||||
link2 = <&secondary>;
|
||||
|
||||
power-supply = <&power>;
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi1: dsi@fd922a00 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0xfd922a00 0x200>;
|
||||
|
||||
secondary: panel@0 {
|
||||
compatible = "sharp,lq101r1sx01";
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -152,28 +152,28 @@ additionalProperties: false
|
|||
|
||||
examples:
|
||||
- |
|
||||
aliases {
|
||||
display0 = &lcdc0;
|
||||
};
|
||||
/ {
|
||||
compatible = "foo";
|
||||
model = "foo";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
chosen {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
stdout-path = "display0";
|
||||
framebuffer0: framebuffer@1d385000 {
|
||||
compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
|
||||
allwinner,pipeline = "de_be0-lcd0";
|
||||
reg = <0x1d385000 3840000>;
|
||||
width = <1600>;
|
||||
height = <1200>;
|
||||
stride = <3200>;
|
||||
format = "r5g6b5";
|
||||
clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
|
||||
lcd-supply = <®_dc1sw>;
|
||||
display = <&lcdc0>;
|
||||
};
|
||||
chosen {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
framebuffer0: framebuffer@1d385000 {
|
||||
compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
|
||||
allwinner,pipeline = "de_be0-lcd0";
|
||||
reg = <0x1d385000 3840000>;
|
||||
width = <1600>;
|
||||
height = <1200>;
|
||||
stride = <3200>;
|
||||
format = "r5g6b5";
|
||||
clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
|
||||
lcd-supply = <®_dc1sw>;
|
||||
display = <&lcdc0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lcdc0: lcdc { };
|
||||
|
||||
...
|
||||
|
|
|
@ -1157,6 +1157,8 @@ patternProperties:
|
|||
description: Xiaomi Technology Co., Ltd.
|
||||
"^xillybus,.*":
|
||||
description: Xillybus Ltd.
|
||||
"^xingbangda,.*":
|
||||
description: Shenzhen Xingbangda Display Technology Co., Ltd
|
||||
"^xinpeng,.*":
|
||||
description: Shenzhen Xinpeng Technology Co., Ltd
|
||||
"^xlnx,.*":
|
||||
|
|
|
@ -1448,11 +1448,6 @@ S: Odd Fixes
|
|||
F: drivers/amba/
|
||||
F: include/linux/amba/bus.h
|
||||
|
||||
ARM PRIMECELL CLCD PL110 DRIVER
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
S: Odd Fixes
|
||||
F: drivers/video/fbdev/amba-clcd.*
|
||||
|
||||
ARM PRIMECELL KMI PL050 DRIVER
|
||||
M: Russell King <linux@armlinux.org.uk>
|
||||
S: Odd Fixes
|
||||
|
@ -5094,6 +5089,7 @@ F: fs/dlm/
|
|||
|
||||
DMA BUFFER SHARING FRAMEWORK
|
||||
M: Sumit Semwal <sumit.semwal@linaro.org>
|
||||
M: Christian König <christian.koenig@amd.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
L: linaro-mm-sig@lists.linaro.org (moderated for non-subscribers)
|
||||
|
|
|
@ -99,12 +99,6 @@ int dma_fence_chain_find_seqno(struct dma_fence **pfence, uint64_t seqno)
|
|||
return -EINVAL;
|
||||
|
||||
dma_fence_chain_for_each(*pfence, &chain->base) {
|
||||
if ((*pfence)->seqno < seqno) { /* already signaled */
|
||||
dma_fence_put(*pfence);
|
||||
*pfence = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((*pfence)->context != chain->base.context ||
|
||||
to_dma_fence_chain(*pfence)->prev_seqno < seqno)
|
||||
break;
|
||||
|
@ -228,7 +222,6 @@ EXPORT_SYMBOL(dma_fence_chain_ops);
|
|||
* @chain: the chain node to initialize
|
||||
* @prev: the previous fence
|
||||
* @fence: the current fence
|
||||
* @seqno: the sequence number (syncpt) of the fence within the chain
|
||||
*
|
||||
* Initialize a new chain node and either start a new chain or add the node to
|
||||
* the existing chain of the previous fence.
|
||||
|
|
|
@ -318,15 +318,16 @@ static int find_out_of_order(void *arg)
|
|||
goto err;
|
||||
}
|
||||
|
||||
if (fence && fence != fc.chains[1]) {
|
||||
/*
|
||||
* We signaled the middle fence (2) of the 1-2-3 chain. The behavior
|
||||
* of the dma-fence-chain is to make us wait for all the fences up to
|
||||
* the point we want. Since fence 1 is still not signaled, this what
|
||||
* we should get as fence to wait upon (fence 2 being garbage
|
||||
* collected during the traversal of the chain).
|
||||
*/
|
||||
if (fence != fc.chains[0]) {
|
||||
pr_err("Incorrect chain-fence.seqno:%lld reported for completed seqno:2\n",
|
||||
fence->seqno);
|
||||
|
||||
dma_fence_get(fence);
|
||||
err = dma_fence_chain_find_seqno(&fence, 2);
|
||||
dma_fence_put(fence);
|
||||
if (err)
|
||||
pr_err("Reported %d for finding self!\n", err);
|
||||
fence ? fence->seqno : 0);
|
||||
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
@ -415,20 +416,18 @@ static int __find_race(void *arg)
|
|||
if (!fence)
|
||||
goto signal;
|
||||
|
||||
err = dma_fence_chain_find_seqno(&fence, seqno);
|
||||
if (err) {
|
||||
pr_err("Reported an invalid fence for find-self:%d\n",
|
||||
seqno);
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fence->seqno < seqno) {
|
||||
pr_err("Reported an earlier fence.seqno:%lld for seqno:%d\n",
|
||||
fence->seqno, seqno);
|
||||
err = -EINVAL;
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
/*
|
||||
* We can only find ourselves if we are on fence we were
|
||||
* looking for.
|
||||
*/
|
||||
if (fence->seqno == seqno) {
|
||||
err = dma_fence_chain_find_seqno(&fence, seqno);
|
||||
if (err) {
|
||||
pr_err("Reported an invalid fence for find-self:%d\n",
|
||||
seqno);
|
||||
dma_fence_put(fence);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dma_fence_put(fence);
|
||||
|
|
|
@ -307,8 +307,8 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
|
|||
if (IS_ERR(sgt))
|
||||
return sgt;
|
||||
|
||||
if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC))
|
||||
if (dma_map_sgtable(attach->dev, sgt, dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC))
|
||||
goto error_free;
|
||||
break;
|
||||
|
||||
|
@ -349,7 +349,7 @@ static void amdgpu_dma_buf_unmap(struct dma_buf_attachment *attach,
|
|||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
|
||||
if (sgt->sgl->page_link) {
|
||||
dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir);
|
||||
dma_unmap_sgtable(attach->dev, sgt, dir, 0);
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
} else {
|
||||
|
|
|
@ -150,60 +150,7 @@ static int amdgpu_gtt_mgr_fini(struct ttm_mem_type_manager *man)
|
|||
*/
|
||||
bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem)
|
||||
{
|
||||
struct amdgpu_gtt_node *node = mem->mm_node;
|
||||
|
||||
return (node->node.start != AMDGPU_BO_INVALID_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_gtt_mgr_alloc - allocate new ranges
|
||||
*
|
||||
* @man: TTM memory type manager
|
||||
* @tbo: TTM BO we need this range for
|
||||
* @place: placement flags and restrictions
|
||||
* @mem: the resulting mem object
|
||||
*
|
||||
* Allocate the address space for a node.
|
||||
*/
|
||||
static int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
|
||||
struct ttm_buffer_object *tbo,
|
||||
const struct ttm_place *place,
|
||||
struct ttm_mem_reg *mem)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
|
||||
struct amdgpu_gtt_mgr *mgr = man->priv;
|
||||
struct amdgpu_gtt_node *node = mem->mm_node;
|
||||
enum drm_mm_insert_mode mode;
|
||||
unsigned long fpfn, lpfn;
|
||||
int r;
|
||||
|
||||
if (amdgpu_gtt_mgr_has_gart_addr(mem))
|
||||
return 0;
|
||||
|
||||
if (place)
|
||||
fpfn = place->fpfn;
|
||||
else
|
||||
fpfn = 0;
|
||||
|
||||
if (place && place->lpfn)
|
||||
lpfn = place->lpfn;
|
||||
else
|
||||
lpfn = adev->gart.num_cpu_pages;
|
||||
|
||||
mode = DRM_MM_INSERT_BEST;
|
||||
if (place && place->flags & TTM_PL_FLAG_TOPDOWN)
|
||||
mode = DRM_MM_INSERT_HIGH;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
r = drm_mm_insert_node_in_range(&mgr->mm, &node->node, mem->num_pages,
|
||||
mem->page_alignment, 0, fpfn, lpfn,
|
||||
mode);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
if (!r)
|
||||
mem->start = node->node.start;
|
||||
|
||||
return r;
|
||||
return mem->mm_node != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,35 +176,42 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man,
|
|||
if ((&tbo->mem == mem || tbo->mem.mem_type != TTM_PL_TT) &&
|
||||
atomic64_read(&mgr->available) < mem->num_pages) {
|
||||
spin_unlock(&mgr->lock);
|
||||
return 0;
|
||||
return -ENOSPC;
|
||||
}
|
||||
atomic64_sub(mem->num_pages, &mgr->available);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
if (!place->lpfn) {
|
||||
mem->mm_node = NULL;
|
||||
mem->start = AMDGPU_BO_INVALID_OFFSET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = kzalloc(sizeof(*node), GFP_KERNEL);
|
||||
if (!node) {
|
||||
r = -ENOMEM;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
node->node.start = AMDGPU_BO_INVALID_OFFSET;
|
||||
node->node.size = mem->num_pages;
|
||||
node->tbo = tbo;
|
||||
mem->mm_node = node;
|
||||
|
||||
if (place->fpfn || place->lpfn || place->flags & TTM_PL_FLAG_TOPDOWN) {
|
||||
r = amdgpu_gtt_mgr_alloc(man, tbo, place, mem);
|
||||
if (unlikely(r)) {
|
||||
kfree(node);
|
||||
mem->mm_node = NULL;
|
||||
r = 0;
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
mem->start = node->node.start;
|
||||
}
|
||||
spin_lock(&mgr->lock);
|
||||
r = drm_mm_insert_node_in_range(&mgr->mm, &node->node, mem->num_pages,
|
||||
mem->page_alignment, 0, place->fpfn,
|
||||
place->lpfn, DRM_MM_INSERT_BEST);
|
||||
spin_unlock(&mgr->lock);
|
||||
|
||||
if (unlikely(r))
|
||||
goto err_free;
|
||||
|
||||
mem->mm_node = node;
|
||||
mem->start = node->node.start;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree(node);
|
||||
|
||||
err_out:
|
||||
atomic64_add(mem->num_pages, &mgr->available);
|
||||
|
||||
|
@ -278,17 +232,14 @@ static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man,
|
|||
struct amdgpu_gtt_mgr *mgr = man->priv;
|
||||
struct amdgpu_gtt_node *node = mem->mm_node;
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
spin_lock(&mgr->lock);
|
||||
if (node->node.start != AMDGPU_BO_INVALID_OFFSET)
|
||||
if (node) {
|
||||
spin_lock(&mgr->lock);
|
||||
drm_mm_remove_node(&node->node);
|
||||
spin_unlock(&mgr->lock);
|
||||
atomic64_add(mem->num_pages, &mgr->available);
|
||||
spin_unlock(&mgr->lock);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
kfree(node);
|
||||
mem->mm_node = NULL;
|
||||
atomic64_add(mem->num_pages, &mgr->available);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -430,12 +430,22 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev,
|
|||
}
|
||||
|
||||
src_offset = src->offset;
|
||||
src_mm = amdgpu_find_mm_node(src->mem, &src_offset);
|
||||
src_node_size = (src_mm->size << PAGE_SHIFT) - src_offset;
|
||||
if (src->mem->mm_node) {
|
||||
src_mm = amdgpu_find_mm_node(src->mem, &src_offset);
|
||||
src_node_size = (src_mm->size << PAGE_SHIFT) - src_offset;
|
||||
} else {
|
||||
src_mm = NULL;
|
||||
src_node_size = ULLONG_MAX;
|
||||
}
|
||||
|
||||
dst_offset = dst->offset;
|
||||
dst_mm = amdgpu_find_mm_node(dst->mem, &dst_offset);
|
||||
dst_node_size = (dst_mm->size << PAGE_SHIFT) - dst_offset;
|
||||
if (dst->mem->mm_node) {
|
||||
dst_mm = amdgpu_find_mm_node(dst->mem, &dst_offset);
|
||||
dst_node_size = (dst_mm->size << PAGE_SHIFT) - dst_offset;
|
||||
} else {
|
||||
dst_mm = NULL;
|
||||
dst_node_size = ULLONG_MAX;
|
||||
}
|
||||
|
||||
mutex_lock(&adev->mman.gtt_window_lock);
|
||||
|
||||
|
@ -1044,7 +1054,6 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
|||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(ttm->bdev);
|
||||
struct amdgpu_ttm_tt *gtt = (void *)ttm;
|
||||
unsigned nents;
|
||||
int r;
|
||||
|
||||
int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY);
|
||||
|
@ -1059,9 +1068,8 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_tt *ttm)
|
|||
goto release_sg;
|
||||
|
||||
/* Map SG to device */
|
||||
r = -ENOMEM;
|
||||
nents = dma_map_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction);
|
||||
if (nents == 0)
|
||||
r = dma_map_sgtable(adev->dev, ttm->sg, direction, 0);
|
||||
if (r)
|
||||
goto release_sg;
|
||||
|
||||
/* convert SG to linear array of pages and dma addresses */
|
||||
|
@ -1092,8 +1100,7 @@ static void amdgpu_ttm_tt_unpin_userptr(struct ttm_tt *ttm)
|
|||
return;
|
||||
|
||||
/* unmap the pages mapped to the device */
|
||||
dma_unmap_sg(adev->dev, ttm->sg->sgl, ttm->sg->nents, direction);
|
||||
|
||||
dma_unmap_sgtable(adev->dev, ttm->sg, direction, 0);
|
||||
sg_free_table(ttm->sg);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_AMDGPU_USERPTR)
|
||||
|
|
|
@ -144,7 +144,7 @@ static void amdgpu_vm_sdma_copy_ptes(struct amdgpu_vm_update_params *p,
|
|||
|
||||
src += p->num_dw_left * 4;
|
||||
|
||||
pe += amdgpu_bo_gpu_offset_no_check(bo);
|
||||
pe += amdgpu_gmc_sign_extend(amdgpu_bo_gpu_offset_no_check(bo));
|
||||
trace_amdgpu_vm_copy_ptes(pe, src, count, p->immediate);
|
||||
|
||||
amdgpu_vm_copy_pte(p->adev, ib, pe, src, count);
|
||||
|
@ -171,7 +171,7 @@ static void amdgpu_vm_sdma_set_ptes(struct amdgpu_vm_update_params *p,
|
|||
{
|
||||
struct amdgpu_ib *ib = p->job->ibs;
|
||||
|
||||
pe += amdgpu_bo_gpu_offset_no_check(bo);
|
||||
pe += amdgpu_gmc_sign_extend(amdgpu_bo_gpu_offset_no_check(bo));
|
||||
trace_amdgpu_vm_set_ptes(pe, addr, count, incr, flags, p->immediate);
|
||||
if (count < 3) {
|
||||
amdgpu_vm_write_pte(p->adev, ib, pe, addr | flags,
|
||||
|
|
|
@ -319,8 +319,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
|
|||
mem_bytes = (u64)mem->num_pages << PAGE_SHIFT;
|
||||
if (atomic64_add_return(mem_bytes, &mgr->usage) > max_bytes) {
|
||||
atomic64_sub(mem_bytes, &mgr->usage);
|
||||
mem->mm_node = NULL;
|
||||
return 0;
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
|
||||
|
@ -400,7 +399,7 @@ error:
|
|||
atomic64_sub(mem->num_pages << PAGE_SHIFT, &mgr->usage);
|
||||
|
||||
kvfree(nodes);
|
||||
return r == -ENOSPC ? 0 : r;
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -475,11 +474,11 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev,
|
|||
if (r)
|
||||
goto error_free;
|
||||
|
||||
for_each_sg((*sgt)->sgl, sg, num_entries, i)
|
||||
for_each_sgtable_sg((*sgt), sg, i)
|
||||
sg->length = 0;
|
||||
|
||||
node = mem->mm_node;
|
||||
for_each_sg((*sgt)->sgl, sg, num_entries, i) {
|
||||
for_each_sgtable_sg((*sgt), sg, i) {
|
||||
phys_addr_t phys = (node->start << PAGE_SHIFT) +
|
||||
adev->gmc.aper_base;
|
||||
size_t size = node->size << PAGE_SHIFT;
|
||||
|
@ -499,7 +498,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev,
|
|||
return 0;
|
||||
|
||||
error_unmap:
|
||||
for_each_sg((*sgt)->sgl, sg, num_entries, i) {
|
||||
for_each_sgtable_sg((*sgt), sg, i) {
|
||||
if (!sg->length)
|
||||
continue;
|
||||
|
||||
|
@ -530,7 +529,7 @@ void amdgpu_vram_mgr_free_sgt(struct amdgpu_device *adev,
|
|||
struct scatterlist *sg;
|
||||
int i;
|
||||
|
||||
for_each_sg(sgt->sgl, sg, sgt->nents, i)
|
||||
for_each_sgtable_sg(sgt, sg, i)
|
||||
dma_unmap_resource(dev, sg->dma_address,
|
||||
sg->length, dir,
|
||||
DMA_ATTR_SKIP_CPU_SYNC);
|
||||
|
|
|
@ -4614,9 +4614,7 @@ static void dm_crtc_reset_state(struct drm_crtc *crtc)
|
|||
if (WARN_ON(!state))
|
||||
return;
|
||||
|
||||
crtc->state = &state->base;
|
||||
crtc->state->crtc = crtc;
|
||||
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *
|
||||
|
|
|
@ -492,10 +492,8 @@ static void komeda_crtc_reset(struct drm_crtc *crtc)
|
|||
crtc->state = NULL;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state) {
|
||||
crtc->state = &state->base;
|
||||
crtc->state->crtc = crtc;
|
||||
}
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *
|
||||
|
@ -616,7 +614,6 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
|
|||
return err;
|
||||
|
||||
drm_crtc_helper_add(crtc, &komeda_crtc_helper_funcs);
|
||||
drm_crtc_vblank_reset(crtc);
|
||||
|
||||
crtc->port = kcrtc->master->of_output_port;
|
||||
|
||||
|
|
|
@ -848,7 +848,6 @@ static int malidp_bind(struct device *dev)
|
|||
drm->irq_enabled = true;
|
||||
|
||||
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
|
||||
drm_crtc_vblank_reset(&malidp->crtc);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to initialise vblank\n");
|
||||
goto vblank_fail;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# Makefile for the drm device driver. This driver provides support for the
|
||||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
ast-y := ast_drv.o ast_main.o ast_mode.o ast_ttm.o ast_post.o ast_dp501.o
|
||||
ast-y := ast_cursor.o ast_drv.o ast_main.o ast_mode.o ast_ttm.o ast_post.o \
|
||||
ast_dp501.o
|
||||
|
||||
obj-$(CONFIG_DRM_AST) := ast.o
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright 2012 Red Hat Inc.
|
||||
* Parts based on xf86-video-ast
|
||||
* Copyright (c) 2005 ASPEED Technology Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*/
|
||||
/*
|
||||
* Authors: Dave Airlie <airlied@redhat.com>
|
||||
*/
|
||||
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
|
||||
static void ast_cursor_fini(struct ast_private *ast)
|
||||
{
|
||||
size_t i;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
}
|
||||
}
|
||||
|
||||
static void ast_cursor_release(struct drm_device *dev, void *ptr)
|
||||
{
|
||||
struct ast_private *ast = dev->dev_private;
|
||||
|
||||
ast_cursor_fini(ast);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate cursor BOs and pins them at the end of VRAM.
|
||||
*/
|
||||
int ast_cursor_init(struct ast_private *ast)
|
||||
{
|
||||
struct drm_device *dev = ast->dev;
|
||||
size_t size, i;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
void __iomem *vaddr;
|
||||
int ret;
|
||||
|
||||
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
|
||||
gbo = drm_gem_vram_create(dev, size, 0);
|
||||
if (IS_ERR(gbo)) {
|
||||
ret = PTR_ERR(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
|
||||
DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
|
||||
if (ret) {
|
||||
drm_gem_vram_put(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
vaddr = drm_gem_vram_vmap(gbo);
|
||||
if (IS_ERR(vaddr)) {
|
||||
ret = PTR_ERR(vaddr);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
|
||||
ast->cursor.gbo[i] = gbo;
|
||||
ast->cursor.vaddr[i] = vaddr;
|
||||
}
|
||||
|
||||
return drmm_add_action_or_reset(dev, ast_cursor_release, NULL);
|
||||
|
||||
err_drm_gem_vram_put:
|
||||
while (i) {
|
||||
--i;
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_vunmap(gbo, ast->cursor.vaddr[i]);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height)
|
||||
{
|
||||
union {
|
||||
u32 ul;
|
||||
u8 b[4];
|
||||
} srcdata32[2], data32;
|
||||
union {
|
||||
u16 us;
|
||||
u8 b[2];
|
||||
} data16;
|
||||
u32 csum = 0;
|
||||
s32 alpha_dst_delta, last_alpha_dst_delta;
|
||||
u8 __iomem *dstxor;
|
||||
const u8 *srcxor;
|
||||
int i, j;
|
||||
u32 per_pixel_copy, two_pixel_copy;
|
||||
|
||||
alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
|
||||
last_alpha_dst_delta = alpha_dst_delta - (width << 1);
|
||||
|
||||
srcxor = src;
|
||||
dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
|
||||
per_pixel_copy = width & 1;
|
||||
two_pixel_copy = width >> 1;
|
||||
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < two_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
|
||||
data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
|
||||
data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
|
||||
|
||||
writel(data32.ul, dstxor);
|
||||
csum += data32.ul;
|
||||
|
||||
dstxor += 4;
|
||||
srcxor += 8;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < per_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
writew(data16.us, dstxor);
|
||||
csum += (u32)data16.us;
|
||||
|
||||
dstxor += 2;
|
||||
srcxor += 4;
|
||||
}
|
||||
dstxor += last_alpha_dst_delta;
|
||||
}
|
||||
|
||||
/* write checksum + signature */
|
||||
dst += AST_HWC_SIZE;
|
||||
writel(csum, dst);
|
||||
writel(width, dst + AST_HWC_SIGNATURE_SizeX);
|
||||
writel(height, dst + AST_HWC_SIGNATURE_SizeY);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
|
||||
}
|
||||
|
||||
int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev = ast->dev;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
int ret;
|
||||
void *src;
|
||||
void __iomem *dst;
|
||||
|
||||
if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) ||
|
||||
drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT))
|
||||
return -EINVAL;
|
||||
|
||||
gbo = drm_gem_vram_of_gem(fb->obj[0]);
|
||||
|
||||
ret = drm_gem_vram_pin(gbo, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
src = drm_gem_vram_vmap(gbo);
|
||||
if (IS_ERR(src)) {
|
||||
ret = PTR_ERR(src);
|
||||
goto err_drm_gem_vram_unpin;
|
||||
}
|
||||
|
||||
dst = ast->cursor.vaddr[ast->cursor.next_index];
|
||||
|
||||
/* do data transfer to cursor BO */
|
||||
update_cursor_image(dst, src, fb->width, fb->height);
|
||||
|
||||
drm_gem_vram_vunmap(gbo, src);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_vram_unpin:
|
||||
drm_gem_vram_unpin(gbo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ast_cursor_set_base(struct ast_private *ast, u64 address)
|
||||
{
|
||||
u8 addr0 = (address >> 3) & 0xff;
|
||||
u8 addr1 = (address >> 11) & 0xff;
|
||||
u8 addr2 = (address >> 19) & 0xff;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
|
||||
}
|
||||
|
||||
void ast_cursor_page_flip(struct ast_private *ast)
|
||||
{
|
||||
struct drm_device *dev = ast->dev;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
s64 off;
|
||||
|
||||
gbo = ast->cursor.gbo[ast->cursor.next_index];
|
||||
|
||||
off = drm_gem_vram_offset(gbo);
|
||||
if (drm_WARN_ON_ONCE(dev, off < 0))
|
||||
return; /* Bug: we didn't pin the cursor HW BO to VRAM. */
|
||||
|
||||
ast_cursor_set_base(ast, off);
|
||||
|
||||
++ast->cursor.next_index;
|
||||
ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo);
|
||||
}
|
||||
|
||||
static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y,
|
||||
u8 x_offset, u8 y_offset)
|
||||
{
|
||||
u8 x0 = (x & 0x00ff);
|
||||
u8 x1 = (x & 0x0f00) >> 8;
|
||||
u8 y0 = (y & 0x00ff);
|
||||
u8 y1 = (y & 0x0700) >> 8;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, x0);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, x1);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, y0);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, y1);
|
||||
}
|
||||
|
||||
void ast_cursor_show(struct ast_private *ast, int x, int y,
|
||||
unsigned int offset_x, unsigned int offset_y)
|
||||
{
|
||||
u8 x_offset, y_offset;
|
||||
u8 __iomem *dst, __iomem *sig;
|
||||
u8 jreg;
|
||||
|
||||
dst = ast->cursor.vaddr[ast->cursor.next_index];
|
||||
|
||||
sig = dst + AST_HWC_SIZE;
|
||||
writel(x, sig + AST_HWC_SIGNATURE_X);
|
||||
writel(y, sig + AST_HWC_SIGNATURE_Y);
|
||||
|
||||
if (x < 0) {
|
||||
x_offset = (-x) + offset_x;
|
||||
x = 0;
|
||||
} else {
|
||||
x_offset = offset_x;
|
||||
}
|
||||
if (y < 0) {
|
||||
y_offset = (-y) + offset_y;
|
||||
y = 0;
|
||||
} else {
|
||||
y_offset = offset_y;
|
||||
}
|
||||
|
||||
ast_cursor_set_location(ast, x, y, x_offset, y_offset);
|
||||
|
||||
/* dummy write to fire HWC */
|
||||
jreg = 0x02 |
|
||||
0x01; /* enable ARGB4444 cursor */
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
|
||||
}
|
||||
|
||||
void ast_cursor_hide(struct ast_private *ast)
|
||||
{
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
|
||||
}
|
|
@ -116,6 +116,7 @@ struct ast_private {
|
|||
|
||||
struct {
|
||||
struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM];
|
||||
void __iomem *vaddr[AST_DEFAULT_HWC_NUM];
|
||||
unsigned int next_index;
|
||||
} cursor;
|
||||
|
||||
|
@ -237,12 +238,6 @@ struct ast_connector {
|
|||
struct ast_i2c_chan *i2c;
|
||||
};
|
||||
|
||||
struct ast_crtc {
|
||||
struct drm_crtc base;
|
||||
u8 offset_x, offset_y;
|
||||
};
|
||||
|
||||
#define to_ast_crtc(x) container_of(x, struct ast_crtc, base)
|
||||
#define to_ast_connector(x) container_of(x, struct ast_connector, base)
|
||||
|
||||
struct ast_vbios_stdtable {
|
||||
|
@ -291,8 +286,7 @@ struct ast_crtc_state {
|
|||
|
||||
#define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base)
|
||||
|
||||
extern int ast_mode_init(struct drm_device *dev);
|
||||
extern void ast_mode_fini(struct drm_device *dev);
|
||||
int ast_mode_config_init(struct ast_private *ast);
|
||||
|
||||
#define AST_MM_ALIGN_SHIFT 4
|
||||
#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
|
||||
|
@ -314,4 +308,13 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata);
|
|||
u8 ast_get_dp501_max_clk(struct drm_device *dev);
|
||||
void ast_init_3rdtx(struct drm_device *dev);
|
||||
void ast_release_firmware(struct drm_device *dev);
|
||||
|
||||
/* ast_cursor.c */
|
||||
int ast_cursor_init(struct ast_private *ast);
|
||||
int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb);
|
||||
void ast_cursor_page_flip(struct ast_private *ast);
|
||||
void ast_cursor_show(struct ast_private *ast, int x, int y,
|
||||
unsigned int offset_x, unsigned int offset_y);
|
||||
void ast_cursor_hide(struct ast_private *ast);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
|
@ -379,13 +378,6 @@ static int ast_get_dram_info(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_mode_config_funcs ast_mode_funcs = {
|
||||
.fb_create = drm_gem_fb_create,
|
||||
.mode_valid = drm_vram_helper_mode_valid,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
static u32 ast_get_vram_info(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = to_ast_private(dev);
|
||||
|
@ -473,33 +465,10 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
|
|||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
drm_mode_config_init(dev);
|
||||
|
||||
dev->mode_config.funcs = (void *)&ast_mode_funcs;
|
||||
dev->mode_config.min_width = 0;
|
||||
dev->mode_config.min_height = 0;
|
||||
dev->mode_config.preferred_depth = 24;
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0);
|
||||
|
||||
if (ast->chip == AST2100 ||
|
||||
ast->chip == AST2200 ||
|
||||
ast->chip == AST2300 ||
|
||||
ast->chip == AST2400 ||
|
||||
ast->chip == AST2500) {
|
||||
dev->mode_config.max_width = 1920;
|
||||
dev->mode_config.max_height = 2048;
|
||||
} else {
|
||||
dev->mode_config.max_width = 1600;
|
||||
dev->mode_config.max_height = 1200;
|
||||
}
|
||||
|
||||
ret = ast_mode_init(dev);
|
||||
ret = ast_mode_config_init(ast);
|
||||
if (ret)
|
||||
goto out_free;
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
return 0;
|
||||
out_free:
|
||||
kfree(ast);
|
||||
|
@ -516,8 +485,6 @@ void ast_driver_unload(struct drm_device *dev)
|
|||
|
||||
ast_release_firmware(dev);
|
||||
kfree(ast->dp501_fw_addr);
|
||||
ast_mode_fini(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
ast_mm_fini(ast);
|
||||
kfree(ast);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
@ -47,16 +48,6 @@
|
|||
|
||||
static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev);
|
||||
static void ast_i2c_destroy(struct ast_i2c_chan *i2c);
|
||||
static int ast_cursor_move(struct drm_crtc *crtc,
|
||||
int x, int y);
|
||||
|
||||
|
||||
static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height);
|
||||
static int ast_cursor_update(void *dst, void *src, unsigned int width,
|
||||
unsigned int height);
|
||||
static void ast_cursor_set_base(struct ast_private *ast, u64 address);
|
||||
static int ast_cursor_move(struct drm_crtc *crtc,
|
||||
int x, int y);
|
||||
|
||||
static inline void ast_load_palette_index(struct ast_private *ast,
|
||||
u8 index, u8 red, u8 green,
|
||||
|
@ -621,56 +612,21 @@ static int
|
|||
ast_cursor_plane_helper_prepare_fb(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_framebuffer *fb = new_state->fb;
|
||||
struct drm_crtc *crtc = new_state->crtc;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
struct ast_private *ast;
|
||||
int ret;
|
||||
void *src, *dst;
|
||||
|
||||
if (!crtc || !fb)
|
||||
return 0;
|
||||
|
||||
if (drm_WARN_ON_ONCE(dev, fb->width > AST_MAX_HWC_WIDTH) ||
|
||||
drm_WARN_ON_ONCE(dev, fb->height > AST_MAX_HWC_HEIGHT))
|
||||
return -EINVAL; /* BUG: didn't test in atomic_check() */
|
||||
ast = to_ast_private(plane->dev);
|
||||
|
||||
ast = to_ast_private(dev);
|
||||
|
||||
gbo = drm_gem_vram_of_gem(fb->obj[0]);
|
||||
src = drm_gem_vram_vmap(gbo);
|
||||
if (IS_ERR(src)) {
|
||||
ret = PTR_ERR(src);
|
||||
goto err_drm_gem_vram_unpin;
|
||||
}
|
||||
|
||||
dst = drm_gem_vram_vmap(ast->cursor.gbo[ast->cursor.next_index]);
|
||||
if (IS_ERR(dst)) {
|
||||
ret = PTR_ERR(dst);
|
||||
goto err_drm_gem_vram_vunmap_src;
|
||||
}
|
||||
|
||||
ret = ast_cursor_update(dst, src, fb->width, fb->height);
|
||||
ret = ast_cursor_blit(ast, fb);
|
||||
if (ret)
|
||||
goto err_drm_gem_vram_vunmap_dst;
|
||||
|
||||
/* Always unmap buffers here. Destination buffers are
|
||||
* perma-pinned while the driver is active. We're only
|
||||
* changing ref-counters here.
|
||||
*/
|
||||
drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst);
|
||||
drm_gem_vram_vunmap(gbo, src);
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_vram_vunmap_dst:
|
||||
drm_gem_vram_vunmap(ast->cursor.gbo[ast->cursor.next_index], dst);
|
||||
err_drm_gem_vram_vunmap_src:
|
||||
drm_gem_vram_vunmap(gbo, src);
|
||||
err_drm_gem_vram_unpin:
|
||||
drm_gem_vram_unpin(gbo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
|
@ -705,37 +661,21 @@ static void
|
|||
ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = plane->dev;
|
||||
struct drm_plane_state *state = plane->state;
|
||||
struct drm_crtc *crtc = state->crtc;
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct ast_private *ast = to_ast_private(plane->dev);
|
||||
struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
|
||||
struct drm_gem_vram_object *gbo;
|
||||
s64 off;
|
||||
u8 jreg;
|
||||
struct ast_private *ast = plane->dev->dev_private;
|
||||
unsigned int offset_x, offset_y;
|
||||
|
||||
ast_crtc->offset_x = AST_MAX_HWC_WIDTH - fb->width;
|
||||
ast_crtc->offset_y = AST_MAX_HWC_WIDTH - fb->height;
|
||||
offset_x = AST_MAX_HWC_WIDTH - fb->width;
|
||||
offset_y = AST_MAX_HWC_WIDTH - fb->height;
|
||||
|
||||
if (state->fb != old_state->fb) {
|
||||
/* A new cursor image was installed. */
|
||||
gbo = ast->cursor.gbo[ast->cursor.next_index];
|
||||
off = drm_gem_vram_offset(gbo);
|
||||
if (drm_WARN_ON_ONCE(dev, off < 0))
|
||||
return; /* Bug: we didn't pin cursor HW BO to VRAM. */
|
||||
ast_cursor_set_base(ast, off);
|
||||
|
||||
++ast->cursor.next_index;
|
||||
ast->cursor.next_index %= ARRAY_SIZE(ast->cursor.gbo);
|
||||
ast_cursor_page_flip(ast);
|
||||
}
|
||||
|
||||
ast_cursor_move(crtc, state->crtc_x, state->crtc_y);
|
||||
|
||||
jreg = 0x2;
|
||||
/* enable ARGB cursor */
|
||||
jreg |= 1;
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
|
||||
ast_cursor_show(ast, state->crtc_x, state->crtc_y,
|
||||
offset_x, offset_y);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -744,7 +684,7 @@ ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
|
|||
{
|
||||
struct ast_private *ast = to_ast_private(plane->dev);
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, 0x00);
|
||||
ast_cursor_hide(ast);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
|
||||
|
@ -942,21 +882,22 @@ static const struct drm_crtc_funcs ast_crtc_funcs = {
|
|||
static int ast_crtc_init(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = to_ast_private(dev);
|
||||
struct ast_crtc *crtc;
|
||||
struct drm_crtc *crtc;
|
||||
int ret;
|
||||
|
||||
crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL);
|
||||
crtc = kzalloc(sizeof(*crtc), GFP_KERNEL);
|
||||
if (!crtc)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane,
|
||||
ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane,
|
||||
&ast->cursor_plane, &ast_crtc_funcs,
|
||||
NULL);
|
||||
if (ret)
|
||||
goto err_kfree;
|
||||
|
||||
drm_mode_crtc_set_gamma_size(&crtc->base, 256);
|
||||
drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
|
||||
drm_mode_crtc_set_gamma_size(crtc, 256);
|
||||
drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
|
||||
|
||||
return 0;
|
||||
|
||||
err_kfree:
|
||||
|
@ -1129,63 +1070,49 @@ static int ast_connector_init(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* allocate cursor cache and pin at start of VRAM */
|
||||
static int ast_cursor_init(struct drm_device *dev)
|
||||
/*
|
||||
* Mode config
|
||||
*/
|
||||
|
||||
static const struct drm_mode_config_funcs ast_mode_config_funcs = {
|
||||
.fb_create = drm_gem_fb_create,
|
||||
.mode_valid = drm_vram_helper_mode_valid,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
};
|
||||
|
||||
int ast_mode_config_init(struct ast_private *ast)
|
||||
{
|
||||
struct ast_private *ast = to_ast_private(dev);
|
||||
size_t size, i;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
struct drm_device *dev = ast->dev;
|
||||
int ret;
|
||||
|
||||
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
ret = ast_cursor_init(ast);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
|
||||
gbo = drm_gem_vram_create(dev, size, 0);
|
||||
if (IS_ERR(gbo)) {
|
||||
ret = PTR_ERR(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
|
||||
DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
|
||||
if (ret) {
|
||||
drm_gem_vram_put(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
ret = drmm_mode_config_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ast->cursor.gbo[i] = gbo;
|
||||
dev->mode_config.funcs = &ast_mode_config_funcs;
|
||||
dev->mode_config.min_width = 0;
|
||||
dev->mode_config.min_height = 0;
|
||||
dev->mode_config.preferred_depth = 24;
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
dev->mode_config.fb_base = pci_resource_start(ast->dev->pdev, 0);
|
||||
|
||||
if (ast->chip == AST2100 ||
|
||||
ast->chip == AST2200 ||
|
||||
ast->chip == AST2300 ||
|
||||
ast->chip == AST2400 ||
|
||||
ast->chip == AST2500) {
|
||||
dev->mode_config.max_width = 1920;
|
||||
dev->mode_config.max_height = 2048;
|
||||
} else {
|
||||
dev->mode_config.max_width = 1600;
|
||||
dev->mode_config.max_height = 1200;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_vram_put:
|
||||
while (i) {
|
||||
--i;
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
ast->cursor.gbo[i] = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ast_cursor_fini(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = to_ast_private(dev);
|
||||
size_t i;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
}
|
||||
}
|
||||
|
||||
int ast_mode_init(struct drm_device *dev)
|
||||
{
|
||||
struct ast_private *ast = to_ast_private(dev);
|
||||
int ret;
|
||||
|
||||
memset(&ast->primary_plane, 0, sizeof(ast->primary_plane));
|
||||
ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01,
|
||||
&ast_primary_plane_funcs,
|
||||
|
@ -1211,17 +1138,13 @@ int ast_mode_init(struct drm_device *dev)
|
|||
drm_plane_helper_add(&ast->cursor_plane,
|
||||
&ast_cursor_plane_helper_funcs);
|
||||
|
||||
ast_cursor_init(dev);
|
||||
ast_crtc_init(dev);
|
||||
ast_encoder_init(dev);
|
||||
ast_connector_init(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
void ast_mode_fini(struct drm_device *dev)
|
||||
{
|
||||
ast_cursor_fini(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_clock(void *i2c_priv)
|
||||
|
@ -1344,136 +1267,3 @@ static void ast_i2c_destroy(struct ast_i2c_chan *i2c)
|
|||
i2c_del_adapter(&i2c->adapter);
|
||||
kfree(i2c);
|
||||
}
|
||||
|
||||
static u32 copy_cursor_image(u8 *src, u8 *dst, int width, int height)
|
||||
{
|
||||
union {
|
||||
u32 ul;
|
||||
u8 b[4];
|
||||
} srcdata32[2], data32;
|
||||
union {
|
||||
u16 us;
|
||||
u8 b[2];
|
||||
} data16;
|
||||
u32 csum = 0;
|
||||
s32 alpha_dst_delta, last_alpha_dst_delta;
|
||||
u8 *srcxor, *dstxor;
|
||||
int i, j;
|
||||
u32 per_pixel_copy, two_pixel_copy;
|
||||
|
||||
alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
|
||||
last_alpha_dst_delta = alpha_dst_delta - (width << 1);
|
||||
|
||||
srcxor = src;
|
||||
dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
|
||||
per_pixel_copy = width & 1;
|
||||
two_pixel_copy = width >> 1;
|
||||
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < two_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
|
||||
data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
|
||||
data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
|
||||
|
||||
writel(data32.ul, dstxor);
|
||||
csum += data32.ul;
|
||||
|
||||
dstxor += 4;
|
||||
srcxor += 8;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < per_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
writew(data16.us, dstxor);
|
||||
csum += (u32)data16.us;
|
||||
|
||||
dstxor += 2;
|
||||
srcxor += 4;
|
||||
}
|
||||
dstxor += last_alpha_dst_delta;
|
||||
}
|
||||
return csum;
|
||||
}
|
||||
|
||||
static int ast_cursor_update(void *dst, void *src, unsigned int width,
|
||||
unsigned int height)
|
||||
{
|
||||
u32 csum;
|
||||
|
||||
/* do data transfer to cursor cache */
|
||||
csum = copy_cursor_image(src, dst, width, height);
|
||||
|
||||
/* write checksum + signature */
|
||||
dst += AST_HWC_SIZE;
|
||||
writel(csum, dst);
|
||||
writel(width, dst + AST_HWC_SIGNATURE_SizeX);
|
||||
writel(height, dst + AST_HWC_SIGNATURE_SizeY);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ast_cursor_set_base(struct ast_private *ast, u64 address)
|
||||
{
|
||||
u8 addr0 = (address >> 3) & 0xff;
|
||||
u8 addr1 = (address >> 11) & 0xff;
|
||||
u8 addr2 = (address >> 19) & 0xff;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc8, addr0);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc9, addr1);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xca, addr2);
|
||||
}
|
||||
|
||||
static int ast_cursor_move(struct drm_crtc *crtc,
|
||||
int x, int y)
|
||||
{
|
||||
struct ast_crtc *ast_crtc = to_ast_crtc(crtc);
|
||||
struct ast_private *ast = to_ast_private(crtc->dev);
|
||||
struct drm_gem_vram_object *gbo;
|
||||
int x_offset, y_offset;
|
||||
u8 *dst, *sig;
|
||||
u8 jreg;
|
||||
|
||||
gbo = ast->cursor.gbo[ast->cursor.next_index];
|
||||
dst = drm_gem_vram_vmap(gbo);
|
||||
if (IS_ERR(dst))
|
||||
return PTR_ERR(dst);
|
||||
|
||||
sig = dst + AST_HWC_SIZE;
|
||||
writel(x, sig + AST_HWC_SIGNATURE_X);
|
||||
writel(y, sig + AST_HWC_SIGNATURE_Y);
|
||||
|
||||
x_offset = ast_crtc->offset_x;
|
||||
y_offset = ast_crtc->offset_y;
|
||||
if (x < 0) {
|
||||
x_offset = (-x) + ast_crtc->offset_x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
y_offset = (-y) + ast_crtc->offset_y;
|
||||
y = 0;
|
||||
}
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc2, x_offset);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc3, y_offset);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc4, (x & 0xff));
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc5, ((x >> 8) & 0x0f));
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc6, (y & 0xff));
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));
|
||||
|
||||
/* dummy write to fire HWC */
|
||||
jreg = 0x02 |
|
||||
0x01; /* enable ARGB4444 cursor */
|
||||
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xcb, 0xfc, jreg);
|
||||
|
||||
drm_gem_vram_vunmap(gbo, dst);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -411,10 +411,8 @@ static void atmel_hlcdc_crtc_reset(struct drm_crtc *crtc)
|
|||
}
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state) {
|
||||
crtc->state = &state->base;
|
||||
crtc->state->crtc = crtc;
|
||||
}
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *
|
||||
|
@ -528,7 +526,6 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
|
|||
}
|
||||
|
||||
drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
|
||||
drm_crtc_vblank_reset(&crtc->base);
|
||||
|
||||
drm_mode_crtc_set_gamma_size(&crtc->base, ATMEL_HLCDC_CLUT_SIZE);
|
||||
drm_crtc_enable_color_mgmt(&crtc->base, 0, false,
|
||||
|
|
|
@ -178,7 +178,7 @@ static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len)
|
|||
|
||||
static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
|
||||
{
|
||||
u8 ret;
|
||||
u8 ret = 0;
|
||||
|
||||
sii8620_read_buf(ctx, addr, &ret, 1);
|
||||
return ret;
|
||||
|
|
|
@ -3179,9 +3179,11 @@ static void dw_hdmi_init_hw(struct dw_hdmi *hdmi)
|
|||
hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
|
||||
}
|
||||
|
||||
static struct dw_hdmi *
|
||||
__dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Probe/remove API, used from platforms based on the DRM bridge API.
|
||||
*/
|
||||
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
@ -3438,14 +3440,11 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
|||
hdmi->cec = platform_device_register_full(&pdevinfo);
|
||||
}
|
||||
|
||||
drm_bridge_add(&hdmi->bridge);
|
||||
|
||||
return hdmi;
|
||||
|
||||
err_iahb:
|
||||
if (hdmi->i2c) {
|
||||
i2c_del_adapter(&hdmi->i2c->adap);
|
||||
hdmi->ddc = NULL;
|
||||
}
|
||||
|
||||
clk_disable_unprepare(hdmi->iahb_clk);
|
||||
if (hdmi->cec_clk)
|
||||
clk_disable_unprepare(hdmi->cec_clk);
|
||||
|
@ -3456,9 +3455,12 @@ err_res:
|
|||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_probe);
|
||||
|
||||
static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
void dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
{
|
||||
drm_bridge_remove(&hdmi->bridge);
|
||||
|
||||
if (hdmi->audio && !IS_ERR(hdmi->audio))
|
||||
platform_device_unregister(hdmi->audio);
|
||||
if (!IS_ERR(hdmi->cec))
|
||||
|
@ -3477,31 +3479,6 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
|
|||
else
|
||||
i2c_put_adapter(hdmi->ddc);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Probe/remove API, used from platforms based on the DRM bridge API.
|
||||
*/
|
||||
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
|
||||
const struct dw_hdmi_plat_data *plat_data)
|
||||
{
|
||||
struct dw_hdmi *hdmi;
|
||||
|
||||
hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
if (IS_ERR(hdmi))
|
||||
return hdmi;
|
||||
|
||||
drm_bridge_add(&hdmi->bridge);
|
||||
|
||||
return hdmi;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_probe);
|
||||
|
||||
void dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||
{
|
||||
drm_bridge_remove(&hdmi->bridge);
|
||||
|
||||
__dw_hdmi_remove(hdmi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_remove);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
@ -3514,7 +3491,7 @@ struct dw_hdmi *dw_hdmi_bind(struct platform_device *pdev,
|
|||
struct dw_hdmi *hdmi;
|
||||
int ret;
|
||||
|
||||
hdmi = __dw_hdmi_probe(pdev, plat_data);
|
||||
hdmi = dw_hdmi_probe(pdev, plat_data);
|
||||
if (IS_ERR(hdmi))
|
||||
return hdmi;
|
||||
|
||||
|
@ -3531,7 +3508,7 @@ EXPORT_SYMBOL_GPL(dw_hdmi_bind);
|
|||
|
||||
void dw_hdmi_unbind(struct dw_hdmi *hdmi)
|
||||
{
|
||||
__dw_hdmi_remove(hdmi);
|
||||
dw_hdmi_remove(hdmi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_unbind);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
|
||||
* Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com
|
||||
* Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
* datasheet: http://www.ti.com/lit/ds/symlink/sn65dsi86.pdf
|
||||
* datasheet: https://www.ti.com/lit/ds/symlink/sn65dsi86.pdf
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
@ -212,6 +212,8 @@ static int __maybe_unused ti_sn_bridge_suspend(struct device *dev)
|
|||
|
||||
static const struct dev_pm_ops ti_sn_bridge_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(ti_sn_bridge_suspend, ti_sn_bridge_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
static int status_show(struct seq_file *s, void *data)
|
||||
|
|
|
@ -575,6 +575,7 @@ static int drm_atomic_plane_check(const struct drm_plane_state *old_plane_state,
|
|||
fb->modifier);
|
||||
if (ret) {
|
||||
struct drm_format_name_buf format_name;
|
||||
|
||||
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] invalid pixel format %s, modifier 0x%llx\n",
|
||||
plane->base.id, plane->name,
|
||||
drm_get_format_name(fb->format->format,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
@ -93,6 +94,9 @@ __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc,
|
|||
if (crtc_state)
|
||||
__drm_atomic_helper_crtc_state_reset(crtc_state, crtc);
|
||||
|
||||
if (drm_dev_has_vblank(crtc->dev))
|
||||
drm_crtc_vblank_reset(crtc);
|
||||
|
||||
crtc->state = crtc_state;
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_atomic_helper_crtc_reset);
|
||||
|
|
|
@ -522,6 +522,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
|
|||
|
||||
if (property == config->prop_fb_id) {
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, file_priv, val);
|
||||
drm_atomic_set_fb_for_plane(state, fb);
|
||||
if (fb)
|
||||
|
@ -539,6 +540,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane,
|
|||
|
||||
} else if (property == config->prop_crtc_id) {
|
||||
struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
|
||||
|
||||
if (val && !crtc)
|
||||
return -EACCES;
|
||||
return drm_atomic_set_crtc_for_plane(state, crtc);
|
||||
|
@ -681,6 +683,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
|
|||
|
||||
if (property == config->prop_crtc_id) {
|
||||
struct drm_crtc *crtc = drm_crtc_find(dev, file_priv, val);
|
||||
|
||||
if (val && !crtc)
|
||||
return -EACCES;
|
||||
return drm_atomic_set_crtc_for_connector(state, crtc);
|
||||
|
@ -754,6 +757,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
|
|||
} else if (property == config->writeback_fb_id_property) {
|
||||
struct drm_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
fb = drm_framebuffer_lookup(dev, file_priv, val);
|
||||
ret = drm_atomic_set_writeback_fb_for_connector(state, fb);
|
||||
if (fb)
|
||||
|
@ -861,6 +865,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
|
|||
switch (obj->type) {
|
||||
case DRM_MODE_OBJECT_CONNECTOR: {
|
||||
struct drm_connector *connector = obj_to_connector(obj);
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
|
||||
ret = drm_atomic_connector_get_property(connector,
|
||||
connector->state, property, val);
|
||||
|
@ -868,6 +873,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
|
|||
}
|
||||
case DRM_MODE_OBJECT_CRTC: {
|
||||
struct drm_crtc *crtc = obj_to_crtc(obj);
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
|
||||
ret = drm_atomic_crtc_get_property(crtc,
|
||||
crtc->state, property, val);
|
||||
|
@ -875,6 +881,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
|
|||
}
|
||||
case DRM_MODE_OBJECT_PLANE: {
|
||||
struct drm_plane *plane = obj_to_plane(obj);
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&plane->mutex));
|
||||
ret = drm_atomic_plane_get_property(plane,
|
||||
plane->state, property, val);
|
||||
|
|
|
@ -53,6 +53,7 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
|
|||
struct drm_local_map *map)
|
||||
{
|
||||
struct drm_map_list *entry;
|
||||
|
||||
list_for_each_entry(entry, &dev->maplist, head) {
|
||||
/*
|
||||
* Because the kernel-userspace ABI is fixed at a 32-bit offset
|
||||
|
@ -102,6 +103,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash,
|
|||
|
||||
if (!use_hashed_handle) {
|
||||
int ret;
|
||||
|
||||
hash->key = user_token >> PAGE_SHIFT;
|
||||
ret = drm_ht_insert_item(&dev->map_hash, hash);
|
||||
if (ret != -EINVAL)
|
||||
|
@ -391,6 +393,7 @@ struct drm_local_map *drm_legacy_findmap(struct drm_device *dev,
|
|||
unsigned int token)
|
||||
{
|
||||
struct drm_map_list *_entry;
|
||||
|
||||
list_for_each_entry(_entry, &dev->maplist, head)
|
||||
if (_entry->user_token == token)
|
||||
return _entry->map;
|
||||
|
@ -1323,6 +1326,7 @@ int __drm_legacy_infobufs(struct drm_device *dev,
|
|||
if (*p >= count) {
|
||||
for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) {
|
||||
struct drm_buf_entry *from = &dma->bufs[i];
|
||||
|
||||
if (from->buf_count) {
|
||||
if (f(data, count, from) < 0)
|
||||
return -EFAULT;
|
||||
|
@ -1359,6 +1363,7 @@ int drm_legacy_infobufs(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_buf_info *request = data;
|
||||
|
||||
return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf);
|
||||
}
|
||||
|
||||
|
@ -1570,6 +1575,7 @@ int drm_legacy_mapbufs(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_buf_map *request = data;
|
||||
|
||||
return __drm_legacy_mapbufs(dev, data, &request->count,
|
||||
&request->virtual, map_one_buf,
|
||||
file_priv);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
* DOC: overview
|
||||
*
|
||||
* In DRM connectors are the general abstraction for display sinks, and include
|
||||
* als fixed panels or anything else that can display pixels in some form. As
|
||||
* also fixed panels or anything else that can display pixels in some form. As
|
||||
* opposed to all other KMS objects representing hardware (like CRTC, encoder or
|
||||
* plane abstractions) connectors can be hotplugged and unplugged at runtime.
|
||||
* Hence they are reference-counted using drm_connector_get() and
|
||||
|
@ -129,7 +129,7 @@ EXPORT_SYMBOL(drm_get_connector_type_name);
|
|||
|
||||
/**
|
||||
* drm_connector_get_cmdline_mode - reads the user's cmdline mode
|
||||
* @connector: connector to quwery
|
||||
* @connector: connector to query
|
||||
*
|
||||
* The kernel supports per-connector configuration of its consoles through
|
||||
* use of the video= parameter. This function parses that option and
|
||||
|
@ -269,6 +269,7 @@ int drm_connector_init(struct drm_device *dev,
|
|||
INIT_LIST_HEAD(&connector->modes);
|
||||
mutex_init(&connector->mutex);
|
||||
connector->edid_blob_ptr = NULL;
|
||||
connector->epoch_counter = 0;
|
||||
connector->tile_blob_ptr = NULL;
|
||||
connector->status = connector_status_unknown;
|
||||
connector->display_info.panel_orientation =
|
||||
|
@ -990,7 +991,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
|
|||
* DP MST sinks), or high-res integrated panels (like dual-link DSI) which
|
||||
* are not gen-locked. Note that for tiled panels which are genlocked, like
|
||||
* dual-link LVDS or dual-link DSI, the driver should try to not expose the
|
||||
* tiling and virtualize both &drm_crtc and &drm_plane if needed. Drivers
|
||||
* tiling and virtualise both &drm_crtc and &drm_plane if needed. Drivers
|
||||
* should update this value using drm_connector_set_tile_property().
|
||||
* Userspace cannot change this property.
|
||||
* link-status:
|
||||
|
@ -1156,7 +1157,7 @@ static const struct drm_prop_enum_list dp_colorspaces[] = {
|
|||
*
|
||||
* It will even need to do colorspace conversion and get all layers
|
||||
* to one common colorspace for blending. It can use either GL, Media
|
||||
* or display engine to get this done based on the capabilties of the
|
||||
* or display engine to get this done based on the capabilities of the
|
||||
* associated hardware.
|
||||
*
|
||||
* Driver expects metadata to be put in &struct hdr_output_metadata
|
||||
|
@ -1639,7 +1640,7 @@ EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
|
|||
* variable refresh rate capability for a connector.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errono on failure.
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_connector_attach_vrr_capable_property(
|
||||
struct drm_connector *connector)
|
||||
|
@ -1784,7 +1785,7 @@ EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
|
|||
* HDMI connectors.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errono on failure.
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_create_hdmi_colorspace_property(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -1813,7 +1814,7 @@ EXPORT_SYMBOL(drm_mode_create_hdmi_colorspace_property);
|
|||
* DP connectors.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative errono on failure.
|
||||
* Zero on success, negative errno on failure.
|
||||
*/
|
||||
int drm_mode_create_dp_colorspace_property(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -1865,7 +1866,7 @@ EXPORT_SYMBOL(drm_mode_create_content_type_property);
|
|||
* drm_mode_create_suggested_offset_properties - create suggests offset properties
|
||||
* @dev: DRM device
|
||||
*
|
||||
* Create the the suggested x/y offset property for connectors.
|
||||
* Create the suggested x/y offset property for connectors.
|
||||
*/
|
||||
int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
|
||||
{
|
||||
|
@ -1979,6 +1980,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
|
|||
struct drm_device *dev = connector->dev;
|
||||
size_t size = 0;
|
||||
int ret;
|
||||
const struct edid *old_edid;
|
||||
|
||||
/* ignore requests to set edid when overridden */
|
||||
if (connector->override_edid)
|
||||
|
@ -1988,7 +1990,7 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
|
|||
size = EDID_LENGTH * (1 + edid->extensions);
|
||||
|
||||
/* Set the display info, using edid if available, otherwise
|
||||
* reseting the values to defaults. This duplicates the work
|
||||
* resetting the values to defaults. This duplicates the work
|
||||
* done in drm_add_edid_modes, but that function is not
|
||||
* consistently called before this one in all drivers and the
|
||||
* computation is cheap enough that it seems better to
|
||||
|
@ -2002,6 +2004,20 @@ int drm_connector_update_edid_property(struct drm_connector *connector,
|
|||
|
||||
drm_update_tile_info(connector, edid);
|
||||
|
||||
if (connector->edid_blob_ptr) {
|
||||
old_edid = (const struct edid *)connector->edid_blob_ptr->data;
|
||||
if (old_edid) {
|
||||
if (!drm_edid_are_equal(edid, old_edid)) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Edid was changed.\n",
|
||||
connector->base.id, connector->name);
|
||||
|
||||
connector->epoch_counter += 1;
|
||||
DRM_DEBUG_KMS("Updating change counter to %llu\n",
|
||||
connector->epoch_counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drm_object_property_set_value(&connector->base,
|
||||
dev->mode_config.non_desktop_property,
|
||||
connector->display_info.non_desktop);
|
||||
|
@ -2101,7 +2117,7 @@ void drm_connector_set_vrr_capable_property(
|
|||
EXPORT_SYMBOL(drm_connector_set_vrr_capable_property);
|
||||
|
||||
/**
|
||||
* drm_connector_set_panel_orientation - sets the connecter's panel_orientation
|
||||
* drm_connector_set_panel_orientation - sets the connector's panel_orientation
|
||||
* @connector: connector for which to set the panel-orientation property.
|
||||
* @panel_orientation: drm_panel_orientation value to set
|
||||
*
|
||||
|
@ -2156,7 +2172,7 @@ EXPORT_SYMBOL(drm_connector_set_panel_orientation);
|
|||
|
||||
/**
|
||||
* drm_connector_set_panel_orientation_with_quirk -
|
||||
* set the connecter's panel_orientation after checking for quirks
|
||||
* set the connector's panel_orientation after checking for quirks
|
||||
* @connector: connector for which to init the panel-orientation property.
|
||||
* @panel_orientation: drm_panel_orientation value to set
|
||||
* @width: width in pixels of the panel, used for panel quirk detection
|
||||
|
@ -2393,6 +2409,7 @@ static void drm_tile_group_free(struct kref *kref)
|
|||
{
|
||||
struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount);
|
||||
struct drm_device *dev = tg->dev;
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
idr_remove(&dev->mode_config.tile_idr, tg->id);
|
||||
mutex_unlock(&dev->mode_config.idr_mutex);
|
||||
|
@ -2428,6 +2445,7 @@ struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
|
|||
{
|
||||
struct drm_tile_group *tg;
|
||||
int id;
|
||||
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
|
||||
if (!memcmp(tg->group_data, topology, 8)) {
|
||||
|
|
|
@ -656,6 +656,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
|
|||
fb->modifier);
|
||||
if (ret) {
|
||||
struct drm_format_name_buf format_name;
|
||||
|
||||
DRM_DEBUG_KMS("Invalid pixel format %s, modifier 0x%llx\n",
|
||||
drm_get_format_name(fb->format->format,
|
||||
&format_name),
|
||||
|
|
|
@ -185,6 +185,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
|
|||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
crtc->enabled = drm_helper_crtc_in_use(crtc);
|
||||
if (!crtc->enabled) {
|
||||
if (crtc_funcs->disable)
|
||||
|
@ -884,6 +885,7 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
|
|||
if (mode < old_dpms) {
|
||||
if (crtc) {
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
if (crtc_funcs->dpms)
|
||||
(*crtc_funcs->dpms) (crtc,
|
||||
drm_helper_choose_crtc_dpms(crtc));
|
||||
|
@ -898,6 +900,7 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
|
|||
drm_helper_encoder_dpms(encoder, encoder_dpms);
|
||||
if (crtc) {
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
if (crtc_funcs->dpms)
|
||||
(*crtc_funcs->dpms) (crtc,
|
||||
drm_helper_choose_crtc_dpms(crtc));
|
||||
|
|
|
@ -57,6 +57,7 @@ static u8 dp_get_lane_status(const u8 link_status[DP_LINK_STATUS_SIZE],
|
|||
int i = DP_LANE0_1_STATUS + (lane >> 1);
|
||||
int s = (lane & 1) * 4;
|
||||
u8 l = dp_link_status(link_status, i);
|
||||
|
||||
return (l >> s) & 0xf;
|
||||
}
|
||||
|
||||
|
@ -257,7 +258,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
|
|||
err = ret;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Too many retries, giving up. First error: %d\n", err);
|
||||
DRM_DEBUG_KMS("%s: Too many retries, giving up. First error: %d\n",
|
||||
aux->name, err);
|
||||
ret = err;
|
||||
|
||||
unlock:
|
||||
|
@ -376,43 +378,44 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux,
|
|||
|
||||
if (drm_dp_dpcd_read(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
|
||||
&auto_test_req, 1) < 1) {
|
||||
DRM_ERROR("DPCD failed read at register 0x%x\n",
|
||||
DP_DEVICE_SERVICE_IRQ_VECTOR);
|
||||
DRM_ERROR("%s: DPCD failed read at register 0x%x\n",
|
||||
aux->name, DP_DEVICE_SERVICE_IRQ_VECTOR);
|
||||
return false;
|
||||
}
|
||||
auto_test_req &= DP_AUTOMATED_TEST_REQUEST;
|
||||
|
||||
if (drm_dp_dpcd_read(aux, DP_TEST_REQUEST, &link_edid_read, 1) < 1) {
|
||||
DRM_ERROR("DPCD failed read at register 0x%x\n",
|
||||
DP_TEST_REQUEST);
|
||||
DRM_ERROR("%s: DPCD failed read at register 0x%x\n",
|
||||
aux->name, DP_TEST_REQUEST);
|
||||
return false;
|
||||
}
|
||||
link_edid_read &= DP_TEST_LINK_EDID_READ;
|
||||
|
||||
if (!auto_test_req || !link_edid_read) {
|
||||
DRM_DEBUG_KMS("Source DUT does not support TEST_EDID_READ\n");
|
||||
DRM_DEBUG_KMS("%s: Source DUT does not support TEST_EDID_READ\n",
|
||||
aux->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (drm_dp_dpcd_write(aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
|
||||
&auto_test_req, 1) < 1) {
|
||||
DRM_ERROR("DPCD failed write at register 0x%x\n",
|
||||
DP_DEVICE_SERVICE_IRQ_VECTOR);
|
||||
DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
|
||||
aux->name, DP_DEVICE_SERVICE_IRQ_VECTOR);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* send back checksum for the last edid extension block data */
|
||||
if (drm_dp_dpcd_write(aux, DP_TEST_EDID_CHECKSUM,
|
||||
&real_edid_checksum, 1) < 1) {
|
||||
DRM_ERROR("DPCD failed write at register 0x%x\n",
|
||||
DP_TEST_EDID_CHECKSUM);
|
||||
DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
|
||||
aux->name, DP_TEST_EDID_CHECKSUM);
|
||||
return false;
|
||||
}
|
||||
|
||||
test_resp |= DP_TEST_EDID_CHECKSUM_WRITE;
|
||||
if (drm_dp_dpcd_write(aux, DP_TEST_RESPONSE, &test_resp, 1) < 1) {
|
||||
DRM_ERROR("DPCD failed write at register 0x%x\n",
|
||||
DP_TEST_RESPONSE);
|
||||
DRM_ERROR("%s: DPCD failed write at register 0x%x\n",
|
||||
aux->name, DP_TEST_RESPONSE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -737,10 +740,11 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
* Avoid spamming the kernel log with timeout errors.
|
||||
*/
|
||||
if (ret == -ETIMEDOUT)
|
||||
DRM_DEBUG_KMS_RATELIMITED("transaction timed out\n");
|
||||
DRM_DEBUG_KMS_RATELIMITED("%s: transaction timed out\n",
|
||||
aux->name);
|
||||
else
|
||||
DRM_DEBUG_KMS("transaction failed: %d\n", ret);
|
||||
|
||||
DRM_DEBUG_KMS("%s: transaction failed: %d\n",
|
||||
aux->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -754,11 +758,12 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
break;
|
||||
|
||||
case DP_AUX_NATIVE_REPLY_NACK:
|
||||
DRM_DEBUG_KMS("native nack (result=%d, size=%zu)\n", ret, msg->size);
|
||||
DRM_DEBUG_KMS("%s: native nack (result=%d, size=%zu)\n",
|
||||
aux->name, ret, msg->size);
|
||||
return -EREMOTEIO;
|
||||
|
||||
case DP_AUX_NATIVE_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("native defer\n");
|
||||
DRM_DEBUG_KMS("%s: native defer\n", aux->name);
|
||||
/*
|
||||
* We could check for I2C bit rate capabilities and if
|
||||
* available adjust this interval. We could also be
|
||||
|
@ -772,7 +777,8 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
continue;
|
||||
|
||||
default:
|
||||
DRM_ERROR("invalid native reply %#04x\n", msg->reply);
|
||||
DRM_ERROR("%s: invalid native reply %#04x\n",
|
||||
aux->name, msg->reply);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
|
@ -787,13 +793,13 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
return ret;
|
||||
|
||||
case DP_AUX_I2C_REPLY_NACK:
|
||||
DRM_DEBUG_KMS("I2C nack (result=%d, size=%zu)\n",
|
||||
ret, msg->size);
|
||||
DRM_DEBUG_KMS("%s: I2C nack (result=%d, size=%zu)\n",
|
||||
aux->name, ret, msg->size);
|
||||
aux->i2c_nack_count++;
|
||||
return -EREMOTEIO;
|
||||
|
||||
case DP_AUX_I2C_REPLY_DEFER:
|
||||
DRM_DEBUG_KMS("I2C defer\n");
|
||||
DRM_DEBUG_KMS("%s: I2C defer\n", aux->name);
|
||||
/* DP Compliance Test 4.2.2.5 Requirement:
|
||||
* Must have at least 7 retries for I2C defers on the
|
||||
* transaction to pass this test
|
||||
|
@ -807,12 +813,13 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
|||
continue;
|
||||
|
||||
default:
|
||||
DRM_ERROR("invalid I2C reply %#04x\n", msg->reply);
|
||||
DRM_ERROR("%s: invalid I2C reply %#04x\n",
|
||||
aux->name, msg->reply);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("too many retries, giving up\n");
|
||||
DRM_DEBUG_KMS("%s: Too many retries, giving up\n", aux->name);
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
|
@ -841,8 +848,8 @@ static int drm_dp_i2c_drain_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *o
|
|||
return err == 0 ? -EPROTO : err;
|
||||
|
||||
if (err < msg.size && err < ret) {
|
||||
DRM_DEBUG_KMS("Partial I2C reply: requested %zu bytes got %d bytes\n",
|
||||
msg.size, err);
|
||||
DRM_DEBUG_KMS("%s: Partial I2C reply: requested %zu bytes got %d bytes\n",
|
||||
aux->name, msg.size, err);
|
||||
ret = err;
|
||||
}
|
||||
|
||||
|
@ -1021,11 +1028,12 @@ static void drm_dp_aux_crc_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
if (ret == -EAGAIN) {
|
||||
DRM_DEBUG_KMS("Get CRC failed after retrying: %d\n",
|
||||
ret);
|
||||
DRM_DEBUG_KMS("%s: Get CRC failed after retrying: %d\n",
|
||||
aux->name, ret);
|
||||
continue;
|
||||
} else if (ret) {
|
||||
DRM_DEBUG_KMS("Failed to get a CRC: %d\n", ret);
|
||||
DRM_DEBUG_KMS("%s: Failed to get a CRC: %d\n",
|
||||
aux->name, ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1388,8 +1396,8 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,
|
|||
|
||||
dev_id_len = strnlen(ident->device_id, sizeof(ident->device_id));
|
||||
|
||||
DRM_DEBUG_KMS("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
|
||||
is_branch ? "branch" : "sink",
|
||||
DRM_DEBUG_KMS("%s: DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n",
|
||||
aux->name, is_branch ? "branch" : "sink",
|
||||
(int)sizeof(ident->oui), ident->oui,
|
||||
dev_id_len, ident->device_id,
|
||||
ident->hw_rev >> 4, ident->hw_rev & 0xf,
|
||||
|
|
|
@ -259,6 +259,7 @@ static u8 drm_dp_msg_data_crc4(const uint8_t *data, u8 number_of_bytes)
|
|||
static inline u8 drm_dp_calc_sb_hdr_size(struct drm_dp_sideband_msg_hdr *hdr)
|
||||
{
|
||||
u8 size = 3;
|
||||
|
||||
size += (hdr->lct / 2);
|
||||
return size;
|
||||
}
|
||||
|
@ -269,6 +270,7 @@ static void drm_dp_encode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
|
|||
int idx = 0;
|
||||
int i;
|
||||
u8 crc4;
|
||||
|
||||
buf[idx++] = ((hdr->lct & 0xf) << 4) | (hdr->lcr & 0xf);
|
||||
for (i = 0; i < (hdr->lct / 2); i++)
|
||||
buf[idx++] = hdr->rad[i];
|
||||
|
@ -289,6 +291,7 @@ static bool drm_dp_decode_sideband_msg_hdr(struct drm_dp_sideband_msg_hdr *hdr,
|
|||
u8 len;
|
||||
int i;
|
||||
u8 idx;
|
||||
|
||||
if (buf[0] == 0)
|
||||
return false;
|
||||
len = 3;
|
||||
|
@ -326,6 +329,7 @@ drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
|
|||
int idx = 0;
|
||||
int i;
|
||||
u8 *buf = raw->msg;
|
||||
|
||||
buf[idx++] = req->req_type & 0x7f;
|
||||
|
||||
switch (req->req_type) {
|
||||
|
@ -673,6 +677,7 @@ drm_dp_mst_dump_sideband_msg_tx(struct drm_printer *p,
|
|||
static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len)
|
||||
{
|
||||
u8 crc4;
|
||||
|
||||
crc4 = drm_dp_msg_data_crc4(msg, len);
|
||||
msg[len] = crc4;
|
||||
}
|
||||
|
@ -747,6 +752,7 @@ static bool drm_dp_sideband_parse_link_address(struct drm_dp_sideband_msg_rx *ra
|
|||
{
|
||||
int idx = 1;
|
||||
int i;
|
||||
|
||||
memcpy(repmsg->u.link_addr.guid, &raw->msg[idx], 16);
|
||||
idx += 16;
|
||||
repmsg->u.link_addr.nports = raw->msg[idx] & 0xf;
|
||||
|
@ -798,6 +804,7 @@ static bool drm_dp_sideband_parse_remote_dpcd_read(struct drm_dp_sideband_msg_rx
|
|||
struct drm_dp_sideband_msg_reply_body *repmsg)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
repmsg->u.remote_dpcd_read_ack.port_number = raw->msg[idx] & 0xf;
|
||||
idx++;
|
||||
if (idx > raw->curlen)
|
||||
|
@ -818,6 +825,7 @@ static bool drm_dp_sideband_parse_remote_dpcd_write(struct drm_dp_sideband_msg_r
|
|||
struct drm_dp_sideband_msg_reply_body *repmsg)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
repmsg->u.remote_dpcd_write_ack.port_number = raw->msg[idx] & 0xf;
|
||||
idx++;
|
||||
if (idx > raw->curlen)
|
||||
|
@ -851,6 +859,7 @@ static bool drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband
|
|||
struct drm_dp_sideband_msg_reply_body *repmsg)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
|
||||
repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
|
||||
idx++;
|
||||
|
@ -874,6 +883,7 @@ static bool drm_dp_sideband_parse_allocate_payload_ack(struct drm_dp_sideband_ms
|
|||
struct drm_dp_sideband_msg_reply_body *repmsg)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
repmsg->u.allocate_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
|
||||
idx++;
|
||||
if (idx > raw->curlen)
|
||||
|
@ -896,6 +906,7 @@ static bool drm_dp_sideband_parse_query_payload_ack(struct drm_dp_sideband_msg_r
|
|||
struct drm_dp_sideband_msg_reply_body *repmsg)
|
||||
{
|
||||
int idx = 1;
|
||||
|
||||
repmsg->u.query_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
|
||||
idx++;
|
||||
if (idx > raw->curlen)
|
||||
|
@ -1082,6 +1093,7 @@ static void build_allocate_payload(struct drm_dp_sideband_msg_tx *msg,
|
|||
u8 *sdp_stream_sink)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.req_type = DP_ALLOCATE_PAYLOAD;
|
||||
req.u.allocate_payload.port_number = port_num;
|
||||
|
@ -1142,6 +1154,7 @@ static void drm_dp_mst_put_payload_id(struct drm_dp_mst_topology_mgr *mgr,
|
|||
int vcpi)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (vcpi == 0)
|
||||
return;
|
||||
|
||||
|
@ -1940,6 +1953,7 @@ static u8 drm_dp_calculate_rad(struct drm_dp_mst_port *port,
|
|||
int parent_lct = port->parent->lct;
|
||||
int shift = 4;
|
||||
int idx = (parent_lct - 1) / 2;
|
||||
|
||||
if (parent_lct > 1) {
|
||||
memcpy(rad, port->parent->rad, idx + 1);
|
||||
shift = (parent_lct % 2) ? 4 : 0;
|
||||
|
@ -2118,10 +2132,12 @@ static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb,
|
|||
{
|
||||
int i;
|
||||
char temp[8];
|
||||
|
||||
snprintf(proppath, proppath_size, "mst:%d", mstb->mgr->conn_base_id);
|
||||
for (i = 0; i < (mstb->lct - 1); i++) {
|
||||
int shift = (i % 2) ? 0 : 4;
|
||||
int port_num = (mstb->rad[i / 2] >> shift) & 0xf;
|
||||
|
||||
snprintf(temp, sizeof(temp), "-%d", port_num);
|
||||
strlcat(proppath, temp, proppath_size);
|
||||
}
|
||||
|
@ -3158,6 +3174,7 @@ static int drm_dp_create_payload_step2(struct drm_dp_mst_topology_mgr *mgr,
|
|||
struct drm_dp_payload *payload)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_dp_payload_send_msg(mgr, port, id, port->vcpi.pbn);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
@ -3314,6 +3331,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr)
|
|||
struct drm_dp_mst_port *port;
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&mgr->payload_lock);
|
||||
for (i = 0; i < mgr->max_payloads; i++) {
|
||||
|
||||
|
@ -3779,6 +3797,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
|
|||
/* Were we actually expecting a response, and from this mstb? */
|
||||
if (!txmsg || txmsg->dst != mstb) {
|
||||
struct drm_dp_sideband_msg_hdr *hdr;
|
||||
|
||||
hdr = &msg->initial_hdr;
|
||||
DRM_DEBUG_KMS("Got MST reply with no msg %p %d %d %02x %02x\n",
|
||||
mstb, hdr->seqno, hdr->lct, hdr->rad[0],
|
||||
|
@ -4326,6 +4345,7 @@ EXPORT_SYMBOL(drm_dp_mst_allocate_vcpi);
|
|||
int drm_dp_mst_get_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port)
|
||||
{
|
||||
int slots = 0;
|
||||
|
||||
port = drm_dp_mst_topology_get_port_validated(mgr, port);
|
||||
if (!port)
|
||||
return slots;
|
||||
|
|
|
@ -1615,6 +1615,37 @@ static bool drm_edid_is_zero(const u8 *in_edid, int length)
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_edid_are_equal - compare two edid blobs.
|
||||
* @edid1: pointer to first blob
|
||||
* @edid2: pointer to second blob
|
||||
* This helper can be used during probing to determine if
|
||||
* edid had changed.
|
||||
*/
|
||||
bool drm_edid_are_equal(const struct edid *edid1, const struct edid *edid2)
|
||||
{
|
||||
int edid1_len, edid2_len;
|
||||
bool edid1_present = edid1 != NULL;
|
||||
bool edid2_present = edid2 != NULL;
|
||||
|
||||
if (edid1_present != edid2_present)
|
||||
return false;
|
||||
|
||||
if (edid1) {
|
||||
edid1_len = EDID_LENGTH * (1 + edid1->extensions);
|
||||
edid2_len = EDID_LENGTH * (1 + edid2->extensions);
|
||||
|
||||
if (edid1_len != edid2_len)
|
||||
return false;
|
||||
|
||||
if (memcmp(edid1, edid2, edid1_len))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_edid_are_equal);
|
||||
|
||||
/**
|
||||
* drm_edid_block_valid - Sanity check the EDID block (base or extension)
|
||||
* @raw_edid: pointer to raw EDID block
|
||||
|
@ -1641,6 +1672,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
|
|||
|
||||
if (block == 0) {
|
||||
int score = drm_edid_header_is_valid(raw_edid);
|
||||
|
||||
if (score == 8) {
|
||||
if (edid_corrupt)
|
||||
*edid_corrupt = false;
|
||||
|
@ -2017,13 +2049,17 @@ EXPORT_SYMBOL(drm_probe_ddc);
|
|||
struct edid *drm_get_edid(struct drm_connector *connector,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct edid *edid;
|
||||
|
||||
if (connector->force == DRM_FORCE_OFF)
|
||||
return NULL;
|
||||
|
||||
if (connector->force == DRM_FORCE_UNSPECIFIED && !drm_probe_ddc(adapter))
|
||||
return NULL;
|
||||
|
||||
return drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
|
||||
edid = drm_do_get_edid(connector, drm_do_probe_ddc_edid, adapter);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
return edid;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_get_edid);
|
||||
|
||||
|
@ -2188,6 +2224,7 @@ struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(drm_dmt_modes); i++) {
|
||||
const struct drm_display_mode *ptr = &drm_dmt_modes[i];
|
||||
|
||||
if (hsize != ptr->hdisplay)
|
||||
continue;
|
||||
if (vsize != ptr->vdisplay)
|
||||
|
@ -2259,6 +2296,7 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure)
|
|||
|
||||
for (i = 1; i <= raw_edid[0x7e]; i++) {
|
||||
u8 *ext = raw_edid + (i * EDID_LENGTH);
|
||||
|
||||
switch (*ext) {
|
||||
case CEA_EXT:
|
||||
cea_for_each_detailed_block(ext, cb, closure);
|
||||
|
@ -2290,6 +2328,7 @@ drm_monitor_supports_rb(struct edid *edid)
|
|||
{
|
||||
if (edid->revision >= 4) {
|
||||
bool ret = false;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, is_rb, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2314,6 +2353,7 @@ static int
|
|||
drm_gtf2_hbreak(struct edid *edid)
|
||||
{
|
||||
u8 *r = NULL;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
|
||||
return r ? (r[12] * 2) : 0;
|
||||
}
|
||||
|
@ -2322,6 +2362,7 @@ static int
|
|||
drm_gtf2_2c(struct edid *edid)
|
||||
{
|
||||
u8 *r = NULL;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
|
||||
return r ? r[13] : 0;
|
||||
}
|
||||
|
@ -2330,6 +2371,7 @@ static int
|
|||
drm_gtf2_m(struct edid *edid)
|
||||
{
|
||||
u8 *r = NULL;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
|
||||
return r ? (r[15] << 8) + r[14] : 0;
|
||||
}
|
||||
|
@ -2338,6 +2380,7 @@ static int
|
|||
drm_gtf2_k(struct edid *edid)
|
||||
{
|
||||
u8 *r = NULL;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
|
||||
return r ? r[16] : 0;
|
||||
}
|
||||
|
@ -2346,6 +2389,7 @@ static int
|
|||
drm_gtf2_2j(struct edid *edid)
|
||||
{
|
||||
u8 *r = NULL;
|
||||
|
||||
drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r);
|
||||
return r ? r[17] : 0;
|
||||
}
|
||||
|
@ -2797,6 +2841,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
|
||||
const struct minimode *m = &extra_modes[i];
|
||||
|
||||
newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0);
|
||||
if (!newmode)
|
||||
return modes;
|
||||
|
@ -2826,6 +2871,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
|
||||
const struct minimode *m = &extra_modes[i];
|
||||
|
||||
newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0);
|
||||
if (!newmode)
|
||||
return modes;
|
||||
|
@ -2961,6 +3007,7 @@ add_established_modes(struct drm_connector *connector, struct edid *edid)
|
|||
for (i = 0; i <= EDID_EST_TIMINGS; i++) {
|
||||
if (est_bits & (1<<i)) {
|
||||
struct drm_display_mode *newmode;
|
||||
|
||||
newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
|
||||
if (newmode) {
|
||||
drm_mode_probed_add(connector, newmode);
|
||||
|
@ -3049,6 +3096,7 @@ static int drm_cvt_modes(struct drm_connector *connector,
|
|||
|
||||
for (i = 0; i < 4; i++) {
|
||||
int uninitialized_var(width), height;
|
||||
|
||||
cvt = &(timing->data.other_data.data.cvt[i]);
|
||||
|
||||
if (!memcmp(cvt->code, empty, 3))
|
||||
|
@ -3188,7 +3236,8 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid,
|
|||
/*
|
||||
* Search EDID for CEA extension block.
|
||||
*/
|
||||
static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id)
|
||||
static u8 *drm_find_edid_extension(const struct edid *edid,
|
||||
int ext_id, int *ext_index)
|
||||
{
|
||||
u8 *edid_ext = NULL;
|
||||
int i;
|
||||
|
@ -3198,23 +3247,26 @@ static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id)
|
|||
return NULL;
|
||||
|
||||
/* Find CEA extension */
|
||||
for (i = 0; i < edid->extensions; i++) {
|
||||
for (i = *ext_index; i < edid->extensions; i++) {
|
||||
edid_ext = (u8 *)edid + EDID_LENGTH * (i + 1);
|
||||
if (edid_ext[0] == ext_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == edid->extensions)
|
||||
if (i >= edid->extensions)
|
||||
return NULL;
|
||||
|
||||
*ext_index = i + 1;
|
||||
|
||||
return edid_ext;
|
||||
}
|
||||
|
||||
|
||||
static u8 *drm_find_displayid_extension(const struct edid *edid,
|
||||
int *length, int *idx)
|
||||
int *length, int *idx,
|
||||
int *ext_index)
|
||||
{
|
||||
u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT);
|
||||
u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index);
|
||||
struct displayid_hdr *base;
|
||||
int ret;
|
||||
|
||||
|
@ -3241,26 +3293,31 @@ static u8 *drm_find_cea_extension(const struct edid *edid)
|
|||
struct displayid_block *block;
|
||||
u8 *cea;
|
||||
u8 *displayid;
|
||||
int ext_index;
|
||||
|
||||
/* Look for a top level CEA extension block */
|
||||
cea = drm_find_edid_extension(edid, CEA_EXT);
|
||||
/* FIXME: make callers iterate through multiple CEA ext blocks? */
|
||||
ext_index = 0;
|
||||
cea = drm_find_edid_extension(edid, CEA_EXT, &ext_index);
|
||||
if (cea)
|
||||
return cea;
|
||||
|
||||
/* CEA blocks can also be found embedded in a DisplayID block */
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx);
|
||||
if (!displayid)
|
||||
return NULL;
|
||||
ext_index = 0;
|
||||
for (;;) {
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx,
|
||||
&ext_index);
|
||||
if (!displayid)
|
||||
return NULL;
|
||||
|
||||
idx += sizeof(struct displayid_hdr);
|
||||
for_each_displayid_db(displayid, block, idx, length) {
|
||||
if (block->tag == DATA_BLOCK_CTA) {
|
||||
cea = (u8 *)block;
|
||||
break;
|
||||
idx += sizeof(struct displayid_hdr);
|
||||
for_each_displayid_db(displayid, block, idx, length) {
|
||||
if (block->tag == DATA_BLOCK_CTA)
|
||||
return (u8 *)block;
|
||||
}
|
||||
}
|
||||
|
||||
return cea;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __always_inline const struct drm_display_mode *cea_mode_for_vic(u8 vic)
|
||||
|
@ -3691,6 +3748,7 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
|
|||
|
||||
for (i = 0; i < len; i++) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_display_mode_from_vic_index(connector, db, len, i);
|
||||
if (mode) {
|
||||
/*
|
||||
|
@ -4532,6 +4590,7 @@ int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads)
|
|||
|
||||
if (cea_db_tag(db) == AUDIO_BLOCK) {
|
||||
int j;
|
||||
|
||||
dbl = cea_db_payload_len(db);
|
||||
|
||||
count = dbl / 3; /* SAD is 3B */
|
||||
|
@ -5135,6 +5194,7 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d
|
|||
unsigned vsync_width = (timings->vsw[0] | timings->vsw[1] << 8) + 1;
|
||||
bool hsync_positive = (timings->hsync[1] >> 7) & 0x1;
|
||||
bool vsync_positive = (timings->vsync[1] >> 7) & 0x1;
|
||||
|
||||
mode = drm_mode_create(dev);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
@ -5195,19 +5255,24 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
|
|||
int length, idx;
|
||||
struct displayid_block *block;
|
||||
int num_modes = 0;
|
||||
int ext_index = 0;
|
||||
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx);
|
||||
if (!displayid)
|
||||
return 0;
|
||||
|
||||
idx += sizeof(struct displayid_hdr);
|
||||
for_each_displayid_db(displayid, block, idx, length) {
|
||||
switch (block->tag) {
|
||||
case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
|
||||
num_modes += add_displayid_detailed_1_modes(connector, block);
|
||||
for (;;) {
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx,
|
||||
&ext_index);
|
||||
if (!displayid)
|
||||
break;
|
||||
|
||||
idx += sizeof(struct displayid_hdr);
|
||||
for_each_displayid_db(displayid, block, idx, length) {
|
||||
switch (block->tag) {
|
||||
case DATA_BLOCK_TYPE_1_DETAILED_TIMING:
|
||||
num_modes += add_displayid_detailed_1_modes(connector, block);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num_modes;
|
||||
}
|
||||
|
||||
|
@ -5316,6 +5381,7 @@ int drm_add_modes_noedid(struct drm_connector *connector,
|
|||
|
||||
for (i = 0; i < count; i++) {
|
||||
const struct drm_display_mode *ptr = &drm_dmt_modes[i];
|
||||
|
||||
if (hdisplay && vdisplay) {
|
||||
/*
|
||||
* Only when two are valid, they will be used to check
|
||||
|
@ -5787,8 +5853,8 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_hdmi_vendor_infoframe_from_display_mode);
|
||||
|
||||
static int drm_parse_tiled_block(struct drm_connector *connector,
|
||||
const struct displayid_block *block)
|
||||
static void drm_parse_tiled_block(struct drm_connector *connector,
|
||||
const struct displayid_block *block)
|
||||
{
|
||||
const struct displayid_tiled_block *tile = (struct displayid_tiled_block *)block;
|
||||
u16 w, h;
|
||||
|
@ -5822,30 +5888,27 @@ static int drm_parse_tiled_block(struct drm_connector *connector,
|
|||
DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
|
||||
|
||||
tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
|
||||
if (!tg) {
|
||||
tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
|
||||
}
|
||||
if (!tg)
|
||||
return -ENOMEM;
|
||||
tg = drm_mode_create_tile_group(connector->dev, tile->topology_id);
|
||||
if (!tg)
|
||||
return;
|
||||
|
||||
if (connector->tile_group != tg) {
|
||||
/* if we haven't got a pointer,
|
||||
take the reference, drop ref to old tile group */
|
||||
if (connector->tile_group) {
|
||||
if (connector->tile_group)
|
||||
drm_mode_put_tile_group(connector->dev, connector->tile_group);
|
||||
}
|
||||
connector->tile_group = tg;
|
||||
} else
|
||||
} else {
|
||||
/* if same tile group, then release the ref we just took. */
|
||||
drm_mode_put_tile_group(connector->dev, tg);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int drm_displayid_parse_tiled(struct drm_connector *connector,
|
||||
const u8 *displayid, int length, int idx)
|
||||
static void drm_displayid_parse_tiled(struct drm_connector *connector,
|
||||
const u8 *displayid, int length, int idx)
|
||||
{
|
||||
const struct displayid_block *block;
|
||||
int ret;
|
||||
|
||||
idx += sizeof(struct displayid_hdr);
|
||||
for_each_displayid_db(displayid, block, idx, length) {
|
||||
|
@ -5854,42 +5917,34 @@ static int drm_displayid_parse_tiled(struct drm_connector *connector,
|
|||
|
||||
switch (block->tag) {
|
||||
case DATA_BLOCK_TILED_DISPLAY:
|
||||
ret = drm_parse_tiled_block(connector, block);
|
||||
if (ret)
|
||||
return ret;
|
||||
drm_parse_tiled_block(connector, block);
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG_KMS("found DisplayID tag 0x%x, unhandled\n", block->tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void drm_update_tile_info(struct drm_connector *connector,
|
||||
const struct edid *edid)
|
||||
{
|
||||
const void *displayid = NULL;
|
||||
int ext_index = 0;
|
||||
int length, idx;
|
||||
int ret;
|
||||
|
||||
connector->has_tile = false;
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx);
|
||||
if (!displayid) {
|
||||
/* drop reference to any tile group we had */
|
||||
goto out_drop_ref;
|
||||
for (;;) {
|
||||
displayid = drm_find_displayid_extension(edid, &length, &idx,
|
||||
&ext_index);
|
||||
if (!displayid)
|
||||
break;
|
||||
|
||||
drm_displayid_parse_tiled(connector, displayid, length, idx);
|
||||
}
|
||||
|
||||
ret = drm_displayid_parse_tiled(connector, displayid, length, idx);
|
||||
if (ret < 0)
|
||||
goto out_drop_ref;
|
||||
if (!connector->has_tile)
|
||||
goto out_drop_ref;
|
||||
return;
|
||||
out_drop_ref:
|
||||
if (connector->tile_group) {
|
||||
if (!connector->has_tile && connector->tile_group) {
|
||||
drm_mode_put_tile_group(connector->dev, connector->tile_group);
|
||||
connector->tile_group = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1784,7 +1784,7 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_info(dev->dev, "fb%d: %s frame buffer device\n",
|
||||
drm_info(dev, "fb%d: %s frame buffer device\n",
|
||||
info->node, info->fix.id);
|
||||
|
||||
mutex_lock(&kernel_fb_helper_lock);
|
||||
|
|
|
@ -375,6 +375,7 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
|
|||
*/
|
||||
if (!dev->hose) {
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
|
||||
if (pci_dev) {
|
||||
dev->hose = pci_dev->sysdata;
|
||||
|
@ -758,6 +759,7 @@ void drm_event_cancel_free(struct drm_device *dev,
|
|||
struct drm_pending_event *p)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->event_lock, flags);
|
||||
if (p->file_priv) {
|
||||
p->file_priv->event_space += p->event->length;
|
||||
|
|
|
@ -1110,6 +1110,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
|
|||
if (drm_framebuffer_read_refcount(fb) > 1) {
|
||||
if (drm_drv_uses_atomic_modeset(dev)) {
|
||||
int ret = atomic_remove_fb(fb);
|
||||
|
||||
WARN(ret, "atomic remove_fb failed with %i\n", ret);
|
||||
} else
|
||||
legacy_remove_fb(fb);
|
||||
|
|
|
@ -388,6 +388,7 @@ static int drm_legacy_infobufs32(struct drm_device *dev, void *data,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_buf_info32_t *request = data;
|
||||
|
||||
return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32);
|
||||
}
|
||||
|
||||
|
@ -813,6 +814,7 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd,
|
|||
unsigned long arg)
|
||||
{
|
||||
drm_update_draw32_t update32;
|
||||
|
||||
if (copy_from_user(&update32, (void __user *)arg, sizeof(update32)))
|
||||
return -EFAULT;
|
||||
|
||||
|
|
|
@ -166,8 +166,10 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
|
|||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (_drm_lease_held_master(master, crtc->base.id)) {
|
||||
uint32_t mask_in = 1ul << count_in;
|
||||
|
||||
if ((crtcs_in & mask_in) != 0) {
|
||||
uint32_t mask_out = 1ul << count_out;
|
||||
|
||||
crtcs_out |= mask_out;
|
||||
}
|
||||
count_out++;
|
||||
|
@ -423,6 +425,7 @@ static int fill_object_idr(struct drm_device *dev,
|
|||
for (o = 0; o < object_count; o++) {
|
||||
struct drm_mode_object *obj = objects[o];
|
||||
u32 object_id = objects[o]->id;
|
||||
|
||||
DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
|
||||
|
||||
/*
|
||||
|
@ -441,6 +444,7 @@ static int fill_object_idr(struct drm_device *dev,
|
|||
}
|
||||
if (obj->type == DRM_MODE_OBJECT_CRTC && !universal_planes) {
|
||||
struct drm_crtc *crtc = obj_to_crtc(obj);
|
||||
|
||||
ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL);
|
||||
if (ret < 0) {
|
||||
DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n",
|
||||
|
|
|
@ -330,6 +330,7 @@ static int drm_legacy_i_have_hw_lock(struct drm_device *dev,
|
|||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_master *master = file_priv->master;
|
||||
|
||||
return (file_priv->lock_count && master->lock.hw_lock &&
|
||||
_DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) &&
|
||||
master->lock.file_priv == file_priv);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/slab.h>
|
||||
|
||||
#include <drm/drm_dsc.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
/**
|
||||
|
@ -155,19 +156,18 @@ static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
|
|||
static struct mipi_dsi_device *
|
||||
of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
|
||||
{
|
||||
struct device *dev = host->dev;
|
||||
struct mipi_dsi_device_info info = { };
|
||||
int ret;
|
||||
u32 reg;
|
||||
|
||||
if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
|
||||
dev_err(dev, "modalias failure on %pOF\n", node);
|
||||
drm_err(host, "modalias failure on %pOF\n", node);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "reg", ®);
|
||||
if (ret) {
|
||||
dev_err(dev, "device node %pOF has no valid reg property: %d\n",
|
||||
drm_err(host, "device node %pOF has no valid reg property: %d\n",
|
||||
node, ret);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
@ -202,22 +202,21 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
|
|||
const struct mipi_dsi_device_info *info)
|
||||
{
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct device *dev = host->dev;
|
||||
int ret;
|
||||
|
||||
if (!info) {
|
||||
dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
|
||||
drm_err(host, "invalid mipi_dsi_device_info pointer\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (info->channel > 3) {
|
||||
dev_err(dev, "invalid virtual channel: %u\n", info->channel);
|
||||
drm_err(host, "invalid virtual channel: %u\n", info->channel);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
dsi = mipi_dsi_device_alloc(host);
|
||||
if (IS_ERR(dsi)) {
|
||||
dev_err(dev, "failed to allocate DSI device %ld\n",
|
||||
drm_err(host, "failed to allocate DSI device %ld\n",
|
||||
PTR_ERR(dsi));
|
||||
return dsi;
|
||||
}
|
||||
|
@ -228,7 +227,7 @@ mipi_dsi_device_register_full(struct mipi_dsi_host *host,
|
|||
|
||||
ret = mipi_dsi_device_add(dsi);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to add DSI device %d\n", ret);
|
||||
drm_err(host, "failed to add DSI device %d\n", ret);
|
||||
kfree(dsi);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -748,26 +747,26 @@ ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
|
|||
{
|
||||
ssize_t err;
|
||||
size_t size;
|
||||
u8 stack_tx[8];
|
||||
u8 *tx;
|
||||
|
||||
if (len > 0) {
|
||||
size = 1 + len;
|
||||
|
||||
size = 1 + len;
|
||||
if (len > ARRAY_SIZE(stack_tx) - 1) {
|
||||
tx = kmalloc(size, GFP_KERNEL);
|
||||
if (!tx)
|
||||
return -ENOMEM;
|
||||
|
||||
/* concatenate the DCS command byte and the payload */
|
||||
tx[0] = cmd;
|
||||
memcpy(&tx[1], data, len);
|
||||
} else {
|
||||
tx = &cmd;
|
||||
size = 1;
|
||||
tx = stack_tx;
|
||||
}
|
||||
|
||||
/* concatenate the DCS command byte and the payload */
|
||||
tx[0] = cmd;
|
||||
if (data)
|
||||
memcpy(&tx[1], data, len);
|
||||
|
||||
err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
|
||||
|
||||
if (len > 0)
|
||||
if (tx != stack_tx)
|
||||
kfree(tx);
|
||||
|
||||
return err;
|
||||
|
@ -1082,11 +1081,11 @@ EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
|
|||
*/
|
||||
int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
|
||||
{
|
||||
u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
|
||||
scanline & 0xff };
|
||||
u8 payload[2] = { scanline >> 8, scanline & 0xff };
|
||||
ssize_t err;
|
||||
|
||||
err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
|
||||
err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_SCANLINE, payload,
|
||||
sizeof(payload));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
|
|
|
@ -538,6 +538,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
|
|||
WARN_ON(!list_empty(&dev->mode_config.fb_list));
|
||||
list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
|
||||
struct drm_printer p = drm_debug_printer("[leaked fb]");
|
||||
|
||||
drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
|
||||
drm_framebuffer_print_info(&p, 1, fb);
|
||||
drm_framebuffer_free(&fb->base.refcount);
|
||||
|
|
|
@ -246,6 +246,15 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
|
|||
if (panel)
|
||||
*panel = NULL;
|
||||
|
||||
/*
|
||||
* of_graph_get_remote_node() produces a noisy error message if port
|
||||
* node isn't found and the absence of the port is a legit case here,
|
||||
* so at first we silently check whether graph presents in the
|
||||
* device-tree node.
|
||||
*/
|
||||
if (!of_graph_is_present(np))
|
||||
return -ENODEV;
|
||||
|
||||
remote = of_graph_get_remote_node(np, port, endpoint);
|
||||
if (!remote)
|
||||
return -ENODEV;
|
||||
|
|
|
@ -298,6 +298,7 @@ EXPORT_SYMBOL(drm_legacy_pci_init);
|
|||
void drm_legacy_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
|
||||
{
|
||||
struct drm_device *dev, *tmp;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
if (!(driver->driver_features & DRIVER_LEGACY)) {
|
||||
|
|
|
@ -216,6 +216,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
|
|||
|
||||
if (format_modifiers) {
|
||||
const uint64_t *temp_modifiers = format_modifiers;
|
||||
|
||||
while (*temp_modifiers++ != DRM_FORMAT_MOD_INVALID)
|
||||
format_modifier_count++;
|
||||
}
|
||||
|
|
|
@ -1014,6 +1014,7 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
|
|||
{
|
||||
struct dma_buf_attachment *attach;
|
||||
struct dma_buf *dma_buf;
|
||||
|
||||
attach = obj->import_attach;
|
||||
if (sg)
|
||||
dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
|
||||
|
|
|
@ -292,6 +292,9 @@ retry:
|
|||
if (WARN_ON(ret < 0))
|
||||
ret = connector_status_unknown;
|
||||
|
||||
if (ret != connector->status)
|
||||
connector->epoch_counter += 1;
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
|
||||
|
@ -325,11 +328,16 @@ drm_helper_probe_detect(struct drm_connector *connector,
|
|||
return ret;
|
||||
|
||||
if (funcs->detect_ctx)
|
||||
return funcs->detect_ctx(connector, ctx, force);
|
||||
ret = funcs->detect_ctx(connector, ctx, force);
|
||||
else if (connector->funcs->detect)
|
||||
return connector->funcs->detect(connector, force);
|
||||
ret = connector->funcs->detect(connector, force);
|
||||
else
|
||||
return connector_status_connected;
|
||||
ret = connector_status_connected;
|
||||
|
||||
if (ret != connector->status)
|
||||
connector->epoch_counter += 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_probe_detect);
|
||||
|
||||
|
@ -779,6 +787,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
|
|||
struct drm_connector_list_iter conn_iter;
|
||||
enum drm_connector_status old_status;
|
||||
bool changed = false;
|
||||
u64 old_epoch_counter;
|
||||
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return false;
|
||||
|
@ -792,20 +801,39 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
|
|||
|
||||
old_status = connector->status;
|
||||
|
||||
old_epoch_counter = connector->epoch_counter;
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Old epoch counter %llu\n", connector->base.id,
|
||||
connector->name,
|
||||
old_epoch_counter);
|
||||
|
||||
connector->status = drm_helper_probe_detect(connector, NULL, false);
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->status));
|
||||
if (old_status != connector->status)
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] New epoch counter %llu\n",
|
||||
connector->base.id,
|
||||
connector->name,
|
||||
connector->epoch_counter);
|
||||
|
||||
/*
|
||||
* Check if epoch counter had changed, meaning that we need
|
||||
* to send a uevent.
|
||||
*/
|
||||
if (old_epoch_counter != connector->epoch_counter)
|
||||
changed = true;
|
||||
|
||||
}
|
||||
drm_connector_list_iter_end(&conn_iter);
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
|
||||
if (changed)
|
||||
if (changed) {
|
||||
drm_kms_helper_hotplug_event(dev);
|
||||
DRM_DEBUG_KMS("Sent hotplug event\n");
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
|
|
@ -1188,6 +1188,7 @@ static void drm_syncobj_array_free(struct drm_syncobj **syncobjs,
|
|||
uint32_t count)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
drm_syncobj_put(syncobjs[i]);
|
||||
kfree(syncobjs);
|
||||
|
|
|
@ -1623,6 +1623,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
|
|||
e->event.vbl.crtc_id = 0;
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
|
||||
|
||||
if (crtc)
|
||||
e->event.vbl.crtc_id = crtc->base.id;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
@ -267,7 +268,7 @@ static int hibmc_load(struct drm_device *dev)
|
|||
struct hibmc_drm_private *priv;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
DRM_ERROR("no memory to allocate for hibmc_drm_private\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -29,6 +29,8 @@ struct hibmc_drm_private {
|
|||
|
||||
/* drm */
|
||||
struct drm_device *dev;
|
||||
struct drm_encoder encoder;
|
||||
struct drm_connector connector;
|
||||
bool mode_config_initialized;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,32 +52,6 @@ static const struct drm_connector_funcs hibmc_connector_funcs = {
|
|||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static struct drm_connector *
|
||||
hibmc_connector_init(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = priv->dev;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
connector = devm_kzalloc(dev->dev, sizeof(*connector), GFP_KERNEL);
|
||||
if (!connector) {
|
||||
DRM_ERROR("failed to alloc memory when init connector\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = drm_connector_init(dev, connector,
|
||||
&hibmc_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to init connector: %d\n", ret);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
drm_connector_helper_add(connector,
|
||||
&hibmc_connector_helper_funcs);
|
||||
|
||||
return connector;
|
||||
}
|
||||
|
||||
static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adj_mode)
|
||||
|
@ -105,23 +79,10 @@ static const struct drm_encoder_funcs hibmc_encoder_funcs = {
|
|||
int hibmc_vdac_init(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = priv->dev;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder = &priv->encoder;
|
||||
struct drm_connector *connector = &priv->connector;
|
||||
int ret;
|
||||
|
||||
connector = hibmc_connector_init(priv);
|
||||
if (IS_ERR(connector)) {
|
||||
DRM_ERROR("failed to create connector: %ld\n",
|
||||
PTR_ERR(connector));
|
||||
return PTR_ERR(connector);
|
||||
}
|
||||
|
||||
encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL);
|
||||
if (!encoder) {
|
||||
DRM_ERROR("failed to alloc memory when init encoder\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
encoder->possible_crtcs = 0x1;
|
||||
ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs,
|
||||
DRM_MODE_ENCODER_DAC, NULL);
|
||||
|
@ -131,6 +92,15 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
|
|||
}
|
||||
|
||||
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
|
||||
|
||||
ret = drm_connector_init(dev, connector, &hibmc_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_VGA);
|
||||
if (ret) {
|
||||
DRM_ERROR("failed to init connector: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
drm_connector_helper_add(connector, &hibmc_connector_helper_funcs);
|
||||
|
||||
drm_connector_attach_encoder(connector, encoder);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -283,24 +283,30 @@ intel_encoder_hotplug(struct intel_encoder *encoder,
|
|||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
enum drm_connector_status old_status;
|
||||
u64 old_epoch_counter;
|
||||
bool ret = false;
|
||||
|
||||
drm_WARN_ON(dev, !mutex_is_locked(&dev->mode_config.mutex));
|
||||
old_status = connector->base.status;
|
||||
old_epoch_counter = connector->base.epoch_counter;
|
||||
|
||||
connector->base.status =
|
||||
drm_helper_probe_detect(&connector->base, NULL, false);
|
||||
|
||||
if (old_status == connector->base.status)
|
||||
return INTEL_HOTPLUG_UNCHANGED;
|
||||
if (old_epoch_counter != connector->base.epoch_counter)
|
||||
ret = true;
|
||||
|
||||
drm_dbg_kms(&to_i915(dev)->drm,
|
||||
"[CONNECTOR:%d:%s] status updated from %s to %s\n",
|
||||
connector->base.base.id,
|
||||
connector->base.name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->base.status));
|
||||
|
||||
return INTEL_HOTPLUG_CHANGED;
|
||||
if (ret) {
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n",
|
||||
connector->base.base.id,
|
||||
connector->base.name,
|
||||
drm_get_connector_status_name(old_status),
|
||||
drm_get_connector_status_name(connector->base.status),
|
||||
old_epoch_counter,
|
||||
connector->base.epoch_counter);
|
||||
return INTEL_HOTPLUG_CHANGED;
|
||||
}
|
||||
return INTEL_HOTPLUG_UNCHANGED;
|
||||
}
|
||||
|
||||
static bool intel_encoder_has_hpd_pulse(struct intel_encoder *encoder)
|
||||
|
|
|
@ -109,20 +109,15 @@ static void imx_drm_crtc_reset(struct drm_crtc *crtc)
|
|||
{
|
||||
struct imx_crtc_state *state;
|
||||
|
||||
if (crtc->state) {
|
||||
if (crtc->state->mode_blob)
|
||||
drm_property_blob_put(crtc->state->mode_blob);
|
||||
if (crtc->state)
|
||||
__drm_atomic_helper_crtc_destroy_state(crtc->state);
|
||||
|
||||
state = to_imx_crtc_state(crtc->state);
|
||||
memset(state, 0, sizeof(*state));
|
||||
} else {
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return;
|
||||
crtc->state = &state->base;
|
||||
}
|
||||
kfree(to_imx_crtc_state(crtc->state));
|
||||
crtc->state = NULL;
|
||||
|
||||
state->base.crtc = crtc;
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *imx_drm_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
|
|
|
@ -419,7 +419,7 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
|
|||
cfg |= JZ_LCD_CFG_VSYNC_ACTIVE_LOW;
|
||||
if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
|
||||
cfg |= JZ_LCD_CFG_DE_ACTIVE_LOW;
|
||||
if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
|
||||
if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
|
||||
cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE;
|
||||
|
||||
if (!priv->panel_is_sharp) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
int lima_sched_timeout_ms;
|
||||
uint lima_heap_init_nr_pages = 8;
|
||||
uint lima_max_error_tasks;
|
||||
uint lima_job_hang_limit;
|
||||
|
||||
MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms");
|
||||
module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
|
||||
|
@ -29,6 +30,9 @@ module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444);
|
|||
MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save");
|
||||
module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644);
|
||||
|
||||
MODULE_PARM_DESC(job_hang_limit, "number of times to allow a job to hang before dropping it (default 0)");
|
||||
module_param_named(job_hang_limit, lima_job_hang_limit, uint, 0444);
|
||||
|
||||
static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)
|
||||
{
|
||||
struct drm_lima_get_param *args = data;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
extern int lima_sched_timeout_ms;
|
||||
extern uint lima_heap_init_nr_pages;
|
||||
extern uint lima_max_error_tasks;
|
||||
extern uint lima_job_hang_limit;
|
||||
|
||||
struct lima_vm;
|
||||
struct lima_bo;
|
||||
|
|
|
@ -503,8 +503,9 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
|
|||
|
||||
INIT_WORK(&pipe->recover_work, lima_sched_recover_work);
|
||||
|
||||
return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0,
|
||||
msecs_to_jiffies(timeout), name);
|
||||
return drm_sched_init(&pipe->base, &lima_sched_ops, 1,
|
||||
lima_job_hang_limit, msecs_to_jiffies(timeout),
|
||||
name);
|
||||
}
|
||||
|
||||
void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
|
||||
|
|
|
@ -113,19 +113,15 @@ static void mtk_drm_crtc_reset(struct drm_crtc *crtc)
|
|||
{
|
||||
struct mtk_crtc_state *state;
|
||||
|
||||
if (crtc->state) {
|
||||
if (crtc->state)
|
||||
__drm_atomic_helper_crtc_destroy_state(crtc->state);
|
||||
|
||||
state = to_mtk_crtc_state(crtc->state);
|
||||
memset(state, 0, sizeof(*state));
|
||||
} else {
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return;
|
||||
crtc->state = &state->base;
|
||||
}
|
||||
kfree(to_mtk_crtc_state(crtc->state));
|
||||
crtc->state = NULL;
|
||||
|
||||
state->base.crtc = crtc;
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *mtk_drm_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||
|
|
|
@ -291,6 +291,10 @@ static void meson_crtc_enable_vd1(struct meson_drm *priv)
|
|||
VPP_VD1_PREBLEND | VPP_VD1_POSTBLEND |
|
||||
VPP_COLOR_MNG_ENABLE,
|
||||
priv->io_base + _REG(VPP_MISC));
|
||||
|
||||
writel_bits_relaxed(VIU_CTRL0_AFBC_TO_VD1,
|
||||
priv->viu.vd1_afbc ? VIU_CTRL0_AFBC_TO_VD1 : 0,
|
||||
priv->io_base + _REG(VIU_MISC_CTRL0));
|
||||
}
|
||||
|
||||
static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
|
||||
|
@ -300,6 +304,10 @@ static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv)
|
|||
VD_BLEND_POSTBLD_SRC_VD1 |
|
||||
VD_BLEND_POSTBLD_PREMULT_EN,
|
||||
priv->io_base + _REG(VD1_BLEND_SRC_CTRL));
|
||||
|
||||
writel_relaxed(priv->viu.vd1_afbc ?
|
||||
(VD1_AXI_SEL_AFBC | AFBC_VD1_SEL) : 0,
|
||||
priv->io_base + _REG(VD1_AFBCD0_MISC_CTRL));
|
||||
}
|
||||
|
||||
void meson_crtc_irq(struct meson_drm *priv)
|
||||
|
@ -383,36 +391,86 @@ void meson_crtc_irq(struct meson_drm *priv)
|
|||
/* Update the VD1 registers */
|
||||
if (priv->viu.vd1_enabled && priv->viu.vd1_commit) {
|
||||
|
||||
switch (priv->viu.vd1_planes) {
|
||||
case 3:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_2,
|
||||
priv->viu.vd1_addr2,
|
||||
priv->viu.vd1_stride2,
|
||||
priv->viu.vd1_height2,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_1,
|
||||
priv->viu.vd1_addr1,
|
||||
priv->viu.vd1_stride1,
|
||||
priv->viu.vd1_height1,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_0,
|
||||
priv->viu.vd1_addr0,
|
||||
priv->viu.vd1_stride0,
|
||||
priv->viu.vd1_height0,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
if (priv->viu.vd1_afbc) {
|
||||
writel_relaxed(priv->viu.vd1_afbc_head_addr,
|
||||
priv->io_base +
|
||||
_REG(AFBC_HEAD_BADDR));
|
||||
writel_relaxed(priv->viu.vd1_afbc_body_addr,
|
||||
priv->io_base +
|
||||
_REG(AFBC_BODY_BADDR));
|
||||
writel_relaxed(priv->viu.vd1_afbc_en,
|
||||
priv->io_base +
|
||||
_REG(AFBC_ENABLE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_mode,
|
||||
priv->io_base +
|
||||
_REG(AFBC_MODE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_size_in,
|
||||
priv->io_base +
|
||||
_REG(AFBC_SIZE_IN));
|
||||
writel_relaxed(priv->viu.vd1_afbc_dec_def_color,
|
||||
priv->io_base +
|
||||
_REG(AFBC_DEC_DEF_COLOR));
|
||||
writel_relaxed(priv->viu.vd1_afbc_conv_ctrl,
|
||||
priv->io_base +
|
||||
_REG(AFBC_CONV_CTRL));
|
||||
writel_relaxed(priv->viu.vd1_afbc_size_out,
|
||||
priv->io_base +
|
||||
_REG(AFBC_SIZE_OUT));
|
||||
writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_ctrl,
|
||||
priv->io_base +
|
||||
_REG(AFBC_VD_CFMT_CTRL));
|
||||
writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_w,
|
||||
priv->io_base +
|
||||
_REG(AFBC_VD_CFMT_W));
|
||||
writel_relaxed(priv->viu.vd1_afbc_mif_hor_scope,
|
||||
priv->io_base +
|
||||
_REG(AFBC_MIF_HOR_SCOPE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_mif_ver_scope,
|
||||
priv->io_base +
|
||||
_REG(AFBC_MIF_VER_SCOPE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_pixel_hor_scope,
|
||||
priv->io_base+
|
||||
_REG(AFBC_PIXEL_HOR_SCOPE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_pixel_ver_scope,
|
||||
priv->io_base +
|
||||
_REG(AFBC_PIXEL_VER_SCOPE));
|
||||
writel_relaxed(priv->viu.vd1_afbc_vd_cfmt_h,
|
||||
priv->io_base +
|
||||
_REG(AFBC_VD_CFMT_H));
|
||||
} else {
|
||||
switch (priv->viu.vd1_planes) {
|
||||
case 3:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_2,
|
||||
priv->viu.vd1_addr2,
|
||||
priv->viu.vd1_stride2,
|
||||
priv->viu.vd1_height2,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
fallthrough;
|
||||
case 2:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_1,
|
||||
priv->viu.vd1_addr1,
|
||||
priv->viu.vd1_stride1,
|
||||
priv->viu.vd1_height1,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
fallthrough;
|
||||
case 1:
|
||||
meson_canvas_config(priv->canvas,
|
||||
priv->canvas_id_vd1_0,
|
||||
priv->viu.vd1_addr0,
|
||||
priv->viu.vd1_stride0,
|
||||
priv->viu.vd1_height0,
|
||||
MESON_CANVAS_WRAP_NONE,
|
||||
MESON_CANVAS_BLKMODE_LINEAR,
|
||||
MESON_CANVAS_ENDIAN_SWAP64);
|
||||
}
|
||||
|
||||
writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE));
|
||||
}
|
||||
|
||||
writel_relaxed(priv->viu.vd1_if0_gen_reg,
|
||||
|
|
|
@ -86,6 +86,7 @@ struct meson_drm {
|
|||
|
||||
bool vd1_enabled;
|
||||
bool vd1_commit;
|
||||
bool vd1_afbc;
|
||||
unsigned int vd1_planes;
|
||||
uint32_t vd1_if0_gen_reg;
|
||||
uint32_t vd1_if0_luma_x0;
|
||||
|
@ -111,6 +112,21 @@ struct meson_drm {
|
|||
uint32_t vd1_height0;
|
||||
uint32_t vd1_height1;
|
||||
uint32_t vd1_height2;
|
||||
uint32_t vd1_afbc_mode;
|
||||
uint32_t vd1_afbc_en;
|
||||
uint32_t vd1_afbc_head_addr;
|
||||
uint32_t vd1_afbc_body_addr;
|
||||
uint32_t vd1_afbc_conv_ctrl;
|
||||
uint32_t vd1_afbc_dec_def_color;
|
||||
uint32_t vd1_afbc_vd_cfmt_ctrl;
|
||||
uint32_t vd1_afbc_vd_cfmt_w;
|
||||
uint32_t vd1_afbc_vd_cfmt_h;
|
||||
uint32_t vd1_afbc_mif_hor_scope;
|
||||
uint32_t vd1_afbc_mif_ver_scope;
|
||||
uint32_t vd1_afbc_size_out;
|
||||
uint32_t vd1_afbc_pixel_hor_scope;
|
||||
uint32_t vd1_afbc_pixel_ver_scope;
|
||||
uint32_t vd1_afbc_size_in;
|
||||
uint32_t vpp_pic_in_height;
|
||||
uint32_t vpp_postblend_vd1_h_start_end;
|
||||
uint32_t vpp_postblend_vd1_v_start_end;
|
||||
|
|
|
@ -58,7 +58,8 @@
|
|||
|
||||
/* VPP_POSTBLEND_VD1_H_START_END */
|
||||
#define VD_H_END(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
#define VD_H_START(value) FIELD_PREP(GENMASK(27, 16), value)
|
||||
#define VD_H_START(value) FIELD_PREP(GENMASK(27, 16), \
|
||||
((value) & GENMASK(13, 0)))
|
||||
|
||||
/* VPP_POSTBLEND_VD1_V_START_END */
|
||||
#define VD_V_END(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
|
@ -76,6 +77,85 @@
|
|||
#define VD_REGION24_START(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
#define VD_REGION13_END(value) FIELD_PREP(GENMASK(27, 16), value)
|
||||
|
||||
/* AFBC_ENABLE */
|
||||
#define AFBC_DEC_ENABLE BIT(8)
|
||||
#define AFBC_FRM_START BIT(0)
|
||||
|
||||
/* AFBC_MODE */
|
||||
#define AFBC_HORZ_SKIP_UV(value) FIELD_PREP(GENMASK(1, 0), value)
|
||||
#define AFBC_VERT_SKIP_UV(value) FIELD_PREP(GENMASK(3, 2), value)
|
||||
#define AFBC_HORZ_SKIP_Y(value) FIELD_PREP(GENMASK(5, 4), value)
|
||||
#define AFBC_VERT_SKIP_Y(value) FIELD_PREP(GENMASK(7, 6), value)
|
||||
#define AFBC_COMPBITS_YUV(value) FIELD_PREP(GENMASK(13, 8), value)
|
||||
#define AFBC_COMPBITS_8BIT 0
|
||||
#define AFBC_COMPBITS_10BIT (2 | (2 << 2) | (2 << 4))
|
||||
#define AFBC_BURST_LEN(value) FIELD_PREP(GENMASK(15, 14), value)
|
||||
#define AFBC_HOLD_LINE_NUM(value) FIELD_PREP(GENMASK(22, 16), value)
|
||||
#define AFBC_MIF_URGENT(value) FIELD_PREP(GENMASK(25, 24), value)
|
||||
#define AFBC_REV_MODE(value) FIELD_PREP(GENMASK(27, 26), value)
|
||||
#define AFBC_BLK_MEM_MODE BIT(28)
|
||||
#define AFBC_SCATTER_MODE BIT(29)
|
||||
#define AFBC_SOFT_RESET BIT(31)
|
||||
|
||||
/* AFBC_SIZE_IN */
|
||||
#define AFBC_HSIZE_IN(value) FIELD_PREP(GENMASK(28, 16), value)
|
||||
#define AFBC_VSIZE_IN(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
/* AFBC_DEC_DEF_COLOR */
|
||||
#define AFBC_DEF_COLOR_Y(value) FIELD_PREP(GENMASK(29, 20), value)
|
||||
#define AFBC_DEF_COLOR_U(value) FIELD_PREP(GENMASK(19, 10), value)
|
||||
#define AFBC_DEF_COLOR_V(value) FIELD_PREP(GENMASK(9, 0), value)
|
||||
|
||||
/* AFBC_CONV_CTRL */
|
||||
#define AFBC_CONV_LBUF_LEN(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
|
||||
/* AFBC_LBUF_DEPTH */
|
||||
#define AFBC_DEC_LBUF_DEPTH(value) FIELD_PREP(GENMASK(27, 16), value)
|
||||
#define AFBC_MIF_LBUF_DEPTH(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
|
||||
/* AFBC_OUT_XSCOPE/AFBC_SIZE_OUT */
|
||||
#define AFBC_HSIZE_OUT(value) FIELD_PREP(GENMASK(28, 16), value)
|
||||
#define AFBC_VSIZE_OUT(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
#define AFBC_OUT_HORZ_BGN(value) FIELD_PREP(GENMASK(28, 16), value)
|
||||
#define AFBC_OUT_HORZ_END(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
/* AFBC_OUT_YSCOPE */
|
||||
#define AFBC_OUT_VERT_BGN(value) FIELD_PREP(GENMASK(28, 16), value)
|
||||
#define AFBC_OUT_VERT_END(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
/* AFBC_VD_CFMT_CTRL */
|
||||
#define AFBC_HORZ_RPT_PIXEL0 BIT(23)
|
||||
#define AFBC_HORZ_Y_C_RATIO(value) FIELD_PREP(GENMASK(22, 21), value)
|
||||
#define AFBC_HORZ_FMT_EN BIT(20)
|
||||
#define AFBC_VERT_RPT_LINE0 BIT(16)
|
||||
#define AFBC_VERT_INITIAL_PHASE(value) FIELD_PREP(GENMASK(11, 8), value)
|
||||
#define AFBC_VERT_PHASE_STEP(value) FIELD_PREP(GENMASK(7, 1), value)
|
||||
#define AFBC_VERT_FMT_EN BIT(0)
|
||||
|
||||
/* AFBC_VD_CFMT_W */
|
||||
#define AFBC_VD_V_WIDTH(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
#define AFBC_VD_H_WIDTH(value) FIELD_PREP(GENMASK(27, 16), value)
|
||||
|
||||
/* AFBC_MIF_HOR_SCOPE */
|
||||
#define AFBC_MIF_BLK_BGN_H(value) FIELD_PREP(GENMASK(25, 16), value)
|
||||
#define AFBC_MIF_BLK_END_H(value) FIELD_PREP(GENMASK(9, 0), value)
|
||||
|
||||
/* AFBC_MIF_VER_SCOPE */
|
||||
#define AFBC_MIF_BLK_BGN_V(value) FIELD_PREP(GENMASK(27, 16), value)
|
||||
#define AFBC_MIF_BLK_END_V(value) FIELD_PREP(GENMASK(11, 0), value)
|
||||
|
||||
/* AFBC_PIXEL_HOR_SCOPE */
|
||||
#define AFBC_DEC_PIXEL_BGN_H(value) FIELD_PREP(GENMASK(28, 16), \
|
||||
((value) & GENMASK(12, 0)))
|
||||
#define AFBC_DEC_PIXEL_END_H(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
/* AFBC_PIXEL_VER_SCOPE */
|
||||
#define AFBC_DEC_PIXEL_BGN_V(value) FIELD_PREP(GENMASK(28, 16), value)
|
||||
#define AFBC_DEC_PIXEL_END_V(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
/* AFBC_VD_CFMT_H */
|
||||
#define AFBC_VD_HEIGHT(value) FIELD_PREP(GENMASK(12, 0), value)
|
||||
|
||||
struct meson_overlay {
|
||||
struct drm_plane base;
|
||||
struct meson_drm *priv;
|
||||
|
@ -157,6 +237,9 @@ static void meson_overlay_setup_scaler_params(struct meson_drm *priv,
|
|||
unsigned int ratio_x, ratio_y;
|
||||
int temp_height, temp_width;
|
||||
unsigned int w_in, h_in;
|
||||
int afbc_left, afbc_right;
|
||||
int afbc_top_src, afbc_bottom_src;
|
||||
int afbc_top, afbc_bottom;
|
||||
int temp, start, end;
|
||||
|
||||
if (!crtc_state) {
|
||||
|
@ -169,7 +252,7 @@ static void meson_overlay_setup_scaler_params(struct meson_drm *priv,
|
|||
|
||||
w_in = fixed16_to_int(state->src_w);
|
||||
h_in = fixed16_to_int(state->src_h);
|
||||
crop_top = fixed16_to_int(state->src_x);
|
||||
crop_top = fixed16_to_int(state->src_y);
|
||||
crop_left = fixed16_to_int(state->src_x);
|
||||
|
||||
video_top = state->crtc_y;
|
||||
|
@ -243,6 +326,14 @@ static void meson_overlay_setup_scaler_params(struct meson_drm *priv,
|
|||
DRM_DEBUG("vsc startp %d endp %d start_lines %d end_lines %d\n",
|
||||
vsc_startp, vsc_endp, vd_start_lines, vd_end_lines);
|
||||
|
||||
afbc_top = round_down(vd_start_lines, 4);
|
||||
afbc_bottom = round_up(vd_end_lines + 1, 4);
|
||||
afbc_top_src = 0;
|
||||
afbc_bottom_src = round_up(h_in + 1, 4);
|
||||
|
||||
DRM_DEBUG("afbc top %d (src %d) bottom %d (src %d)\n",
|
||||
afbc_top, afbc_top_src, afbc_bottom, afbc_bottom_src);
|
||||
|
||||
/* Horizontal */
|
||||
|
||||
start = video_left + video_width / 2 - ((w_in << 17) / ratio_x);
|
||||
|
@ -278,6 +369,16 @@ static void meson_overlay_setup_scaler_params(struct meson_drm *priv,
|
|||
DRM_DEBUG("hsc startp %d endp %d start_lines %d end_lines %d\n",
|
||||
hsc_startp, hsc_endp, hd_start_lines, hd_end_lines);
|
||||
|
||||
if (hd_start_lines > 0 || (hd_end_lines < w_in)) {
|
||||
afbc_left = 0;
|
||||
afbc_right = round_up(w_in, 32);
|
||||
} else {
|
||||
afbc_left = round_down(hd_start_lines, 32);
|
||||
afbc_right = round_up(hd_end_lines + 1, 32);
|
||||
}
|
||||
|
||||
DRM_DEBUG("afbc left %d right %d\n", afbc_left, afbc_right);
|
||||
|
||||
priv->viu.vpp_vsc_start_phase_step = ratio_y << 6;
|
||||
|
||||
priv->viu.vpp_vsc_ini_phase = vphase << 8;
|
||||
|
@ -293,6 +394,35 @@ static void meson_overlay_setup_scaler_params(struct meson_drm *priv,
|
|||
VD_H_WIDTH(hd_end_lines - hd_start_lines + 1) |
|
||||
VD_V_WIDTH(hd_end_lines/2 - hd_start_lines/2 + 1);
|
||||
|
||||
priv->viu.vd1_afbc_vd_cfmt_w =
|
||||
AFBC_VD_H_WIDTH(afbc_right - afbc_left) |
|
||||
AFBC_VD_V_WIDTH(afbc_right / 2 - afbc_left / 2);
|
||||
|
||||
priv->viu.vd1_afbc_vd_cfmt_h =
|
||||
AFBC_VD_HEIGHT((afbc_bottom - afbc_top) / 2);
|
||||
|
||||
priv->viu.vd1_afbc_mif_hor_scope = AFBC_MIF_BLK_BGN_H(afbc_left / 32) |
|
||||
AFBC_MIF_BLK_END_H((afbc_right / 32) - 1);
|
||||
|
||||
priv->viu.vd1_afbc_mif_ver_scope = AFBC_MIF_BLK_BGN_V(afbc_top / 4) |
|
||||
AFBC_MIF_BLK_END_H((afbc_bottom / 4) - 1);
|
||||
|
||||
priv->viu.vd1_afbc_size_out =
|
||||
AFBC_HSIZE_OUT(afbc_right - afbc_left) |
|
||||
AFBC_VSIZE_OUT(afbc_bottom - afbc_top);
|
||||
|
||||
priv->viu.vd1_afbc_pixel_hor_scope =
|
||||
AFBC_DEC_PIXEL_BGN_H(hd_start_lines - afbc_left) |
|
||||
AFBC_DEC_PIXEL_END_H(hd_end_lines - afbc_left);
|
||||
|
||||
priv->viu.vd1_afbc_pixel_ver_scope =
|
||||
AFBC_DEC_PIXEL_BGN_V(vd_start_lines - afbc_top) |
|
||||
AFBC_DEC_PIXEL_END_V(vd_end_lines - afbc_top);
|
||||
|
||||
priv->viu.vd1_afbc_size_in =
|
||||
AFBC_HSIZE_IN(afbc_right - afbc_left) |
|
||||
AFBC_VSIZE_IN(afbc_bottom_src - afbc_top_src);
|
||||
|
||||
priv->viu.vd1_if0_luma_y0 = VD_Y_START(vd_start_lines) |
|
||||
VD_Y_END(vd_end_lines);
|
||||
|
||||
|
@ -350,11 +480,65 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
|
|||
|
||||
spin_lock_irqsave(&priv->drm->event_lock, flags);
|
||||
|
||||
priv->viu.vd1_if0_gen_reg = VD_URGENT_CHROMA |
|
||||
VD_URGENT_LUMA |
|
||||
VD_HOLD_LINES(9) |
|
||||
VD_CHRO_RPT_LASTL_CTRL |
|
||||
VD_ENABLE;
|
||||
if ((fb->modifier & DRM_FORMAT_MOD_AMLOGIC_FBC(0, 0)) ==
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(0, 0)) {
|
||||
priv->viu.vd1_afbc = true;
|
||||
|
||||
priv->viu.vd1_afbc_mode = AFBC_MIF_URGENT(3) |
|
||||
AFBC_HOLD_LINE_NUM(8) |
|
||||
AFBC_BURST_LEN(2);
|
||||
|
||||
if (fb->modifier & DRM_FORMAT_MOD_AMLOGIC_FBC(0,
|
||||
AMLOGIC_FBC_OPTION_MEM_SAVING))
|
||||
priv->viu.vd1_afbc_mode |= AFBC_BLK_MEM_MODE;
|
||||
|
||||
if ((fb->modifier & __fourcc_mod_amlogic_layout_mask) ==
|
||||
AMLOGIC_FBC_LAYOUT_SCATTER)
|
||||
priv->viu.vd1_afbc_mode |= AFBC_SCATTER_MODE;
|
||||
|
||||
priv->viu.vd1_afbc_en = 0x1600 | AFBC_DEC_ENABLE;
|
||||
|
||||
priv->viu.vd1_afbc_conv_ctrl = AFBC_CONV_LBUF_LEN(256);
|
||||
|
||||
priv->viu.vd1_afbc_dec_def_color = AFBC_DEF_COLOR_Y(1023);
|
||||
|
||||
/* 420: horizontal / 2, vertical / 4 */
|
||||
priv->viu.vd1_afbc_vd_cfmt_ctrl = AFBC_HORZ_RPT_PIXEL0 |
|
||||
AFBC_HORZ_Y_C_RATIO(1) |
|
||||
AFBC_HORZ_FMT_EN |
|
||||
AFBC_VERT_RPT_LINE0 |
|
||||
AFBC_VERT_INITIAL_PHASE(12) |
|
||||
AFBC_VERT_PHASE_STEP(8) |
|
||||
AFBC_VERT_FMT_EN;
|
||||
|
||||
switch (fb->format->format) {
|
||||
/* AFBC Only formats */
|
||||
case DRM_FORMAT_YUV420_10BIT:
|
||||
priv->viu.vd1_afbc_mode |=
|
||||
AFBC_COMPBITS_YUV(AFBC_COMPBITS_10BIT);
|
||||
priv->viu.vd1_afbc_dec_def_color |=
|
||||
AFBC_DEF_COLOR_U(512) |
|
||||
AFBC_DEF_COLOR_V(512);
|
||||
break;
|
||||
case DRM_FORMAT_YUV420_8BIT:
|
||||
priv->viu.vd1_afbc_dec_def_color |=
|
||||
AFBC_DEF_COLOR_U(128) |
|
||||
AFBC_DEF_COLOR_V(128);
|
||||
break;
|
||||
}
|
||||
|
||||
priv->viu.vd1_if0_gen_reg = 0;
|
||||
priv->viu.vd1_if0_canvas0 = 0;
|
||||
priv->viu.viu_vd1_fmt_ctrl = 0;
|
||||
} else {
|
||||
priv->viu.vd1_afbc = false;
|
||||
|
||||
priv->viu.vd1_if0_gen_reg = VD_URGENT_CHROMA |
|
||||
VD_URGENT_LUMA |
|
||||
VD_HOLD_LINES(9) |
|
||||
VD_CHRO_RPT_LASTL_CTRL |
|
||||
VD_ENABLE;
|
||||
}
|
||||
|
||||
/* Setup scaler params */
|
||||
meson_overlay_setup_scaler_params(priv, plane, interlace_mode);
|
||||
|
@ -370,6 +554,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
|
|||
priv->viu.vd1_if0_gen_reg2 = 0;
|
||||
priv->viu.viu_vd1_fmt_ctrl = 0;
|
||||
|
||||
/* None will match for AFBC Only formats */
|
||||
switch (fb->format->format) {
|
||||
/* TOFIX DRM_FORMAT_RGB888 should be supported */
|
||||
case DRM_FORMAT_YUYV:
|
||||
|
@ -488,13 +673,42 @@ static void meson_overlay_atomic_update(struct drm_plane *plane,
|
|||
priv->viu.vd1_stride0 = fb->pitches[0];
|
||||
priv->viu.vd1_height0 =
|
||||
drm_format_info_plane_height(fb->format,
|
||||
fb->height, 0);
|
||||
fb->height, 0);
|
||||
DRM_DEBUG("plane 0 addr 0x%x stride %d height %d\n",
|
||||
priv->viu.vd1_addr0,
|
||||
priv->viu.vd1_stride0,
|
||||
priv->viu.vd1_height0);
|
||||
}
|
||||
|
||||
if (priv->viu.vd1_afbc) {
|
||||
if (priv->viu.vd1_afbc_mode & AFBC_SCATTER_MODE) {
|
||||
/*
|
||||
* In Scatter mode, the header contains the physical
|
||||
* body content layout, thus the body content
|
||||
* size isn't needed.
|
||||
*/
|
||||
priv->viu.vd1_afbc_head_addr = priv->viu.vd1_addr0 >> 4;
|
||||
priv->viu.vd1_afbc_body_addr = 0;
|
||||
} else {
|
||||
/* Default mode is 4k per superblock */
|
||||
unsigned long block_size = 4096;
|
||||
unsigned long body_size;
|
||||
|
||||
/* 8bit mem saving mode is 3072bytes per superblock */
|
||||
if (priv->viu.vd1_afbc_mode & AFBC_BLK_MEM_MODE)
|
||||
block_size = 3072;
|
||||
|
||||
body_size = (ALIGN(priv->viu.vd1_stride0, 64) / 64) *
|
||||
(ALIGN(priv->viu.vd1_height0, 32) / 32) *
|
||||
block_size;
|
||||
|
||||
priv->viu.vd1_afbc_body_addr = priv->viu.vd1_addr0 >> 4;
|
||||
/* Header is after body content */
|
||||
priv->viu.vd1_afbc_head_addr = (priv->viu.vd1_addr0 +
|
||||
body_size) >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
priv->viu.vd1_enabled = true;
|
||||
|
||||
spin_unlock_irqrestore(&priv->drm->event_lock, flags);
|
||||
|
@ -531,6 +745,53 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = {
|
|||
.prepare_fb = drm_gem_fb_prepare_fb,
|
||||
};
|
||||
|
||||
static bool meson_overlay_format_mod_supported(struct drm_plane *plane,
|
||||
u32 format, u64 modifier)
|
||||
{
|
||||
if (modifier == DRM_FORMAT_MOD_LINEAR &&
|
||||
format != DRM_FORMAT_YUV420_8BIT &&
|
||||
format != DRM_FORMAT_YUV420_10BIT)
|
||||
return true;
|
||||
|
||||
if ((modifier & DRM_FORMAT_MOD_AMLOGIC_FBC(0, 0)) ==
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(0, 0)) {
|
||||
unsigned int layout = modifier &
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(
|
||||
__fourcc_mod_amlogic_layout_mask, 0);
|
||||
unsigned int options =
|
||||
(modifier >> __fourcc_mod_amlogic_options_shift) &
|
||||
__fourcc_mod_amlogic_options_mask;
|
||||
|
||||
if (format != DRM_FORMAT_YUV420_8BIT &&
|
||||
format != DRM_FORMAT_YUV420_10BIT) {
|
||||
DRM_DEBUG_KMS("%llx invalid format 0x%08x\n",
|
||||
modifier, format);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layout != AMLOGIC_FBC_LAYOUT_BASIC &&
|
||||
layout != AMLOGIC_FBC_LAYOUT_SCATTER) {
|
||||
DRM_DEBUG_KMS("%llx invalid layout %x\n",
|
||||
modifier, layout);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options &&
|
||||
options != AMLOGIC_FBC_OPTION_MEM_SAVING) {
|
||||
DRM_DEBUG_KMS("%llx invalid layout %x\n",
|
||||
modifier, layout);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("invalid modifier %llx for format 0x%08x\n",
|
||||
modifier, format);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs meson_overlay_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
|
@ -538,6 +799,7 @@ static const struct drm_plane_funcs meson_overlay_funcs = {
|
|||
.reset = drm_atomic_helper_plane_reset,
|
||||
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
.format_mod_supported = meson_overlay_format_mod_supported,
|
||||
};
|
||||
|
||||
static const uint32_t supported_drm_formats[] = {
|
||||
|
@ -549,6 +811,19 @@ static const uint32_t supported_drm_formats[] = {
|
|||
DRM_FORMAT_YUV420,
|
||||
DRM_FORMAT_YUV411,
|
||||
DRM_FORMAT_YUV410,
|
||||
DRM_FORMAT_YUV420_8BIT, /* Amlogic FBC Only */
|
||||
DRM_FORMAT_YUV420_10BIT, /* Amlogic FBC Only */
|
||||
};
|
||||
|
||||
static const uint64_t format_modifiers[] = {
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(AMLOGIC_FBC_LAYOUT_SCATTER,
|
||||
AMLOGIC_FBC_OPTION_MEM_SAVING),
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(AMLOGIC_FBC_LAYOUT_BASIC,
|
||||
AMLOGIC_FBC_OPTION_MEM_SAVING),
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(AMLOGIC_FBC_LAYOUT_SCATTER, 0),
|
||||
DRM_FORMAT_MOD_AMLOGIC_FBC(AMLOGIC_FBC_LAYOUT_BASIC, 0),
|
||||
DRM_FORMAT_MOD_LINEAR,
|
||||
DRM_FORMAT_MOD_INVALID,
|
||||
};
|
||||
|
||||
int meson_overlay_create(struct meson_drm *priv)
|
||||
|
@ -570,7 +845,7 @@ int meson_overlay_create(struct meson_drm *priv)
|
|||
&meson_overlay_funcs,
|
||||
supported_drm_formats,
|
||||
ARRAY_SIZE(supported_drm_formats),
|
||||
NULL,
|
||||
format_modifiers,
|
||||
DRM_PLANE_TYPE_OVERLAY, "meson_overlay_plane");
|
||||
|
||||
drm_plane_helper_add(plane, &meson_overlay_helper_funcs);
|
||||
|
|
|
@ -144,10 +144,15 @@
|
|||
#define VIU_SW_RESET_OSD1 BIT(0)
|
||||
#define VIU_MISC_CTRL0 0x1a06
|
||||
#define VIU_CTRL0_VD1_AFBC_MASK 0x170000
|
||||
#define VIU_CTRL0_AFBC_TO_VD1 BIT(20)
|
||||
#define VIU_MISC_CTRL1 0x1a07
|
||||
#define MALI_AFBC_MISC GENMASK(15, 8)
|
||||
#define D2D3_INTF_LENGTH 0x1a08
|
||||
#define D2D3_INTF_CTRL0 0x1a09
|
||||
#define VD1_AFBCD0_MISC_CTRL 0x1a0a
|
||||
#define VD1_AXI_SEL_AFBC (1 << 12)
|
||||
#define AFBC_VD1_SEL (1 << 10)
|
||||
#define VD2_AFBCD1_MISC_CTRL 0x1a0b
|
||||
#define VIU_OSD1_CTRL_STAT 0x1a10
|
||||
#define VIU_OSD1_OSD_BLK_ENABLE BIT(0)
|
||||
#define VIU_OSD1_OSD_MEM_MODE_LINEAR BIT(2)
|
||||
|
@ -365,6 +370,23 @@
|
|||
#define VIU_OSD1_OETF_LUT_ADDR_PORT 0x1add
|
||||
#define VIU_OSD1_OETF_LUT_DATA_PORT 0x1ade
|
||||
#define AFBC_ENABLE 0x1ae0
|
||||
#define AFBC_MODE 0x1ae1
|
||||
#define AFBC_SIZE_IN 0x1ae2
|
||||
#define AFBC_DEC_DEF_COLOR 0x1ae3
|
||||
#define AFBC_CONV_CTRL 0x1ae4
|
||||
#define AFBC_LBUF_DEPTH 0x1ae5
|
||||
#define AFBC_HEAD_BADDR 0x1ae6
|
||||
#define AFBC_BODY_BADDR 0x1ae7
|
||||
#define AFBC_SIZE_OUT 0x1ae8
|
||||
#define AFBC_OUT_YSCOPE 0x1ae9
|
||||
#define AFBC_STAT 0x1aea
|
||||
#define AFBC_VD_CFMT_CTRL 0x1aeb
|
||||
#define AFBC_VD_CFMT_W 0x1aec
|
||||
#define AFBC_MIF_HOR_SCOPE 0x1aed
|
||||
#define AFBC_MIF_VER_SCOPE 0x1aee
|
||||
#define AFBC_PIXEL_HOR_SCOPE 0x1aef
|
||||
#define AFBC_PIXEL_VER_SCOPE 0x1af0
|
||||
#define AFBC_VD_CFMT_H 0x1af1
|
||||
|
||||
/* vpp */
|
||||
#define VPP_DUMMY_DATA 0x1d00
|
||||
|
|
|
@ -60,6 +60,12 @@
|
|||
WREG8(MGAREG_SEQ_DATA, v); \
|
||||
} while (0) \
|
||||
|
||||
#define RREG_CRT(reg, v) \
|
||||
do { \
|
||||
WREG8(MGAREG_CRTC_INDEX, reg); \
|
||||
v = RREG8(MGAREG_CRTC_DATA); \
|
||||
} while (0) \
|
||||
|
||||
#define WREG_CRT(reg, v) \
|
||||
do { \
|
||||
WREG8(MGAREG_CRTC_INDEX, reg); \
|
||||
|
|
|
@ -712,7 +712,7 @@ static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
|
||||
static int mgag200_crtc_set_plls(struct mga_device *mdev, long clock)
|
||||
{
|
||||
u8 misc;
|
||||
|
||||
|
@ -745,9 +745,8 @@ static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void mga_g200wb_prepare(struct drm_crtc *crtc)
|
||||
static void mgag200_g200wb_hold_bmc(struct mga_device *mdev)
|
||||
{
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
u8 tmp;
|
||||
int iter_max;
|
||||
|
||||
|
@ -799,10 +798,9 @@ static void mga_g200wb_prepare(struct drm_crtc *crtc)
|
|||
}
|
||||
}
|
||||
|
||||
static void mga_g200wb_commit(struct drm_crtc *crtc)
|
||||
static void mgag200_g200wb_release_bmc(struct mga_device *mdev)
|
||||
{
|
||||
u8 tmp;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
|
||||
/* 1- The first step is to ensure that the vrsten and hrsten are set */
|
||||
WREG8(MGAREG_CRTCEXT_INDEX, 1);
|
||||
|
@ -988,7 +986,7 @@ static void mgag200_set_dac_regs(struct mga_device *mdev)
|
|||
|
||||
static void mgag200_init_regs(struct mga_device *mdev)
|
||||
{
|
||||
u8 crtcext3, crtcext4, misc;
|
||||
u8 crtc11, crtcext3, crtcext4, misc;
|
||||
|
||||
mgag200_set_pci_regs(mdev);
|
||||
mgag200_set_dac_regs(mdev);
|
||||
|
@ -1012,6 +1010,12 @@ static void mgag200_init_regs(struct mga_device *mdev)
|
|||
WREG_ECRT(0x03, crtcext3);
|
||||
WREG_ECRT(0x04, crtcext4);
|
||||
|
||||
RREG_CRT(0x11, crtc11);
|
||||
crtc11 &= ~(MGAREG_CRTC11_CRTCPROTECT |
|
||||
MGAREG_CRTC11_VINTEN |
|
||||
MGAREG_CRTC11_VINTCLR);
|
||||
WREG_CRT(0x11, crtc11);
|
||||
|
||||
if (mdev->type == G200_ER)
|
||||
WREG_ECRT(0x24, 0x5);
|
||||
|
||||
|
@ -1104,8 +1108,6 @@ static void mgag200_set_mode_regs(struct mga_device *mdev,
|
|||
WREG_ECRT(0x05, crtcext5);
|
||||
|
||||
WREG8(MGA_MISC_OUT, misc);
|
||||
|
||||
mga_crtc_set_plls(mdev, mode->clock);
|
||||
}
|
||||
|
||||
static u8 mgag200_get_bpp_shift(struct mga_device *mdev,
|
||||
|
@ -1215,14 +1217,8 @@ static void mgag200_set_format_regs(struct mga_device *mdev,
|
|||
static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
|
||||
{
|
||||
static uint32_t RESET_FLAG = 0x00200000; /* undocumented magic value */
|
||||
u8 seq1;
|
||||
u32 memctl;
|
||||
|
||||
/* screen off */
|
||||
RREG_SEQ(0x01, seq1);
|
||||
seq1 |= MGAREG_SEQ1_SCROFF;
|
||||
WREG_SEQ(0x01, seq1);
|
||||
|
||||
memctl = RREG32(MGAREG_MEMCTL);
|
||||
|
||||
memctl |= RESET_FLAG;
|
||||
|
@ -1232,11 +1228,6 @@ static void mgag200_g200er_reset_tagfifo(struct mga_device *mdev)
|
|||
|
||||
memctl &= ~RESET_FLAG;
|
||||
WREG32(MGAREG_MEMCTL, memctl);
|
||||
|
||||
/* screen on */
|
||||
RREG_SEQ(0x01, seq1);
|
||||
seq1 &= ~MGAREG_SEQ1_SCROFF;
|
||||
WREG_SEQ(0x01, seq1);
|
||||
}
|
||||
|
||||
static void mgag200_g200se_set_hiprilvl(struct mga_device *mdev,
|
||||
|
@ -1289,107 +1280,59 @@ static void mgag200_g200ev_set_hiprilvl(struct mga_device *mdev)
|
|||
WREG_ECRT(0x06, 0x00);
|
||||
}
|
||||
|
||||
static void mga_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
static void mgag200_enable_display(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
u8 seq1 = 0, crtcext1 = 0;
|
||||
u8 seq0, seq1, crtcext1;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_ON:
|
||||
seq1 = 0;
|
||||
crtcext1 = 0;
|
||||
mga_crtc_load_lut(crtc);
|
||||
break;
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
seq1 = 0x20;
|
||||
crtcext1 = 0x10;
|
||||
break;
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
seq1 = 0x20;
|
||||
crtcext1 = 0x20;
|
||||
break;
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
seq1 = 0x20;
|
||||
crtcext1 = 0x30;
|
||||
break;
|
||||
}
|
||||
RREG_SEQ(0x00, seq0);
|
||||
seq0 |= MGAREG_SEQ0_SYNCRST |
|
||||
MGAREG_SEQ0_ASYNCRST;
|
||||
WREG_SEQ(0x00, seq0);
|
||||
|
||||
WREG8(MGAREG_SEQ_INDEX, 0x01);
|
||||
seq1 |= RREG8(MGAREG_SEQ_DATA) & ~0x20;
|
||||
/*
|
||||
* TODO: replace busy waiting with vblank IRQ; put
|
||||
* msleep(50) before changing SCROFF
|
||||
*/
|
||||
mga_wait_vsync(mdev);
|
||||
mga_wait_busy(mdev);
|
||||
WREG8(MGAREG_SEQ_DATA, seq1);
|
||||
|
||||
RREG_SEQ(0x01, seq1);
|
||||
seq1 &= ~MGAREG_SEQ1_SCROFF;
|
||||
WREG_SEQ(0x01, seq1);
|
||||
|
||||
msleep(20);
|
||||
WREG8(MGAREG_CRTCEXT_INDEX, 0x01);
|
||||
crtcext1 |= RREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
|
||||
WREG8(MGAREG_CRTCEXT_DATA, crtcext1);
|
||||
|
||||
RREG_ECRT(0x01, crtcext1);
|
||||
crtcext1 &= ~MGAREG_CRTCEXT1_VSYNCOFF;
|
||||
crtcext1 &= ~MGAREG_CRTCEXT1_HSYNCOFF;
|
||||
WREG_ECRT(0x01, crtcext1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called before a mode is programmed. A typical use might be to
|
||||
* enable DPMS during the programming to avoid seeing intermediate stages,
|
||||
* but that's not relevant to us
|
||||
*/
|
||||
static void mga_crtc_prepare(struct drm_crtc *crtc)
|
||||
static void mgag200_disable_display(struct mga_device *mdev)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
u8 tmp;
|
||||
u8 seq0, seq1, crtcext1;
|
||||
|
||||
/* mga_resume(crtc);*/
|
||||
RREG_SEQ(0x00, seq0);
|
||||
seq0 &= ~MGAREG_SEQ0_SYNCRST;
|
||||
WREG_SEQ(0x00, seq0);
|
||||
|
||||
WREG8(MGAREG_CRTC_INDEX, 0x11);
|
||||
tmp = RREG8(MGAREG_CRTC_DATA);
|
||||
WREG_CRT(0x11, tmp | 0x80);
|
||||
/*
|
||||
* TODO: replace busy waiting with vblank IRQ; put
|
||||
* msleep(50) before changing SCROFF
|
||||
*/
|
||||
mga_wait_vsync(mdev);
|
||||
mga_wait_busy(mdev);
|
||||
|
||||
if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
|
||||
WREG_SEQ(0, 1);
|
||||
msleep(50);
|
||||
WREG_SEQ(1, 0x20);
|
||||
msleep(20);
|
||||
} else {
|
||||
WREG8(MGAREG_SEQ_INDEX, 0x1);
|
||||
tmp = RREG8(MGAREG_SEQ_DATA);
|
||||
RREG_SEQ(0x01, seq1);
|
||||
seq1 |= MGAREG_SEQ1_SCROFF;
|
||||
WREG_SEQ(0x01, seq1);
|
||||
|
||||
/* start sync reset */
|
||||
WREG_SEQ(0, 1);
|
||||
WREG_SEQ(1, tmp | 0x20);
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
if (mdev->type == G200_WB || mdev->type == G200_EW3)
|
||||
mga_g200wb_prepare(crtc);
|
||||
|
||||
WREG_CRT(17, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called after a mode is programmed. It should reverse anything done
|
||||
* by the prepare function
|
||||
*/
|
||||
static void mga_crtc_commit(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct mga_device *mdev = to_mga_device(dev);
|
||||
u8 tmp;
|
||||
|
||||
if (mdev->type == G200_WB || mdev->type == G200_EW3)
|
||||
mga_g200wb_commit(crtc);
|
||||
|
||||
if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
|
||||
msleep(50);
|
||||
WREG_SEQ(1, 0x0);
|
||||
msleep(20);
|
||||
WREG_SEQ(0, 0x3);
|
||||
} else {
|
||||
WREG8(MGAREG_SEQ_INDEX, 0x1);
|
||||
tmp = RREG8(MGAREG_SEQ_DATA);
|
||||
|
||||
tmp &= ~0x20;
|
||||
WREG_SEQ(0x1, tmp);
|
||||
WREG_SEQ(0, 3);
|
||||
}
|
||||
mga_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
RREG_ECRT(0x01, crtcext1);
|
||||
crtcext1 |= MGAREG_CRTCEXT1_VSYNCOFF |
|
||||
MGAREG_CRTCEXT1_HSYNCOFF;
|
||||
WREG_ECRT(0x01, crtcext1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1612,10 +1555,12 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
.y2 = fb->height,
|
||||
};
|
||||
|
||||
mga_crtc_prepare(crtc);
|
||||
if (mdev->type == G200_WB || mdev->type == G200_EW3)
|
||||
mgag200_g200wb_hold_bmc(mdev);
|
||||
|
||||
mgag200_set_format_regs(mdev, fb);
|
||||
mgag200_set_mode_regs(mdev, adjusted_mode);
|
||||
mgag200_crtc_set_plls(mdev, adjusted_mode->clock);
|
||||
|
||||
if (mdev->type == G200_ER)
|
||||
mgag200_g200er_reset_tagfifo(mdev);
|
||||
|
@ -1625,7 +1570,11 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
|
|||
else if (mdev->type == G200_EV)
|
||||
mgag200_g200ev_set_hiprilvl(mdev);
|
||||
|
||||
mga_crtc_commit(crtc);
|
||||
if (mdev->type == G200_WB || mdev->type == G200_EW3)
|
||||
mgag200_g200wb_release_bmc(mdev);
|
||||
|
||||
mga_crtc_load_lut(crtc);
|
||||
mgag200_enable_display(mdev);
|
||||
|
||||
mgag200_handle_damage(mdev, fb, &fullscreen);
|
||||
}
|
||||
|
@ -1634,8 +1583,9 @@ static void
|
|||
mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
|
||||
{
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct mga_device *mdev = to_mga_device(crtc->dev);
|
||||
|
||||
mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
mgag200_disable_display(mdev);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -236,15 +236,26 @@
|
|||
#define MGAREG_SEQ_INDEX 0x1fc4
|
||||
#define MGAREG_SEQ_DATA 0x1fc5
|
||||
|
||||
#define MGAREG_SEQ0_ASYNCRST BIT(0)
|
||||
#define MGAREG_SEQ0_SYNCRST BIT(1)
|
||||
|
||||
#define MGAREG_SEQ1_SCROFF BIT(5)
|
||||
|
||||
#define MGAREG_CRTC_INDEX 0x1fd4
|
||||
#define MGAREG_CRTC_DATA 0x1fd5
|
||||
|
||||
#define MGAREG_CRTC11_VINTCLR BIT(4)
|
||||
#define MGAREG_CRTC11_VINTEN BIT(5)
|
||||
#define MGAREG_CRTC11_CRTCPROTECT BIT(7)
|
||||
|
||||
#define MGAREG_CRTCEXT_INDEX 0x1fde
|
||||
#define MGAREG_CRTCEXT_DATA 0x1fdf
|
||||
|
||||
#define MGAREG_CRTCEXT0_OFFSET_MASK GENMASK(5, 4)
|
||||
|
||||
#define MGAREG_CRTCEXT1_VSYNCOFF BIT(5)
|
||||
#define MGAREG_CRTCEXT1_HSYNCOFF BIT(4)
|
||||
|
||||
/* Cursor X and Y position */
|
||||
#define MGA_CURPOSXL 0x3c0c
|
||||
#define MGA_CURPOSXH 0x3c0d
|
||||
|
|
|
@ -1117,8 +1117,6 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
|
|||
mdp5_crtc_destroy_state(crtc, crtc->state);
|
||||
|
||||
__drm_atomic_helper_crtc_reset(crtc, &mdp5_cstate->base);
|
||||
|
||||
drm_crtc_vblank_reset(crtc);
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs mdp5_crtc_funcs = {
|
||||
|
|
|
@ -845,7 +845,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
nvbo = nouveau_gem_object(drm_fb->obj[0]);
|
||||
nv_crtc->fb.offset = nvbo->bo.offset;
|
||||
nv_crtc->fb.offset = nvbo->offset;
|
||||
|
||||
if (nv_crtc->lut.depth != drm_fb->format->depth) {
|
||||
nv_crtc->lut.depth = drm_fb->format->depth;
|
||||
|
@ -1013,7 +1013,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
|||
nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo);
|
||||
|
||||
nouveau_bo_unmap(cursor);
|
||||
nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->bo.offset;
|
||||
nv_crtc->cursor.offset = nv_crtc->cursor.nvbo->offset;
|
||||
nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset);
|
||||
nv_crtc->cursor.show(nv_crtc, true);
|
||||
out:
|
||||
|
@ -1192,7 +1192,7 @@ nv04_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
|||
/* Initialize a page flip struct */
|
||||
*s = (struct nv04_page_flip_state)
|
||||
{ { }, event, crtc, fb->format->cpp[0] * 8, fb->pitches[0],
|
||||
new_bo->bo.offset };
|
||||
new_bo->offset };
|
||||
|
||||
/* Keep vblanks on during flip, for the target crtc of this flip */
|
||||
drm_crtc_vblank_get(crtc);
|
||||
|
|
|
@ -152,7 +152,8 @@ nv04_display_init(struct drm_device *dev, bool resume, bool runtime)
|
|||
continue;
|
||||
|
||||
if (nv_crtc->cursor.set_offset)
|
||||
nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset);
|
||||
nv_crtc->cursor.set_offset(nv_crtc,
|
||||
nv_crtc->cursor.nvbo->offset);
|
||||
nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x,
|
||||
nv_crtc->cursor_saved_y);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
nvif_mask(dev, NV_PCRTC_ENGINE_CTRL + soff2, NV_CRTC_FSEL_OVERLAY, 0);
|
||||
|
||||
nvif_wr32(dev, NV_PVIDEO_BASE(flip), 0);
|
||||
nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nvbo->bo.offset);
|
||||
nvif_wr32(dev, NV_PVIDEO_OFFSET_BUFF(flip), nvbo->offset);
|
||||
nvif_wr32(dev, NV_PVIDEO_SIZE_IN(flip), src_h << 16 | src_w);
|
||||
nvif_wr32(dev, NV_PVIDEO_POINT_IN(flip), src_y << 16 | src_x);
|
||||
nvif_wr32(dev, NV_PVIDEO_DS_DX(flip), (src_w << 20) / crtc_w);
|
||||
|
@ -174,7 +174,7 @@ nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
if (format & NV_PVIDEO_FORMAT_PLANAR) {
|
||||
nvif_wr32(dev, NV_PVIDEO_UVPLANE_BASE(flip), 0);
|
||||
nvif_wr32(dev, NV_PVIDEO_UVPLANE_OFFSET_BUFF(flip),
|
||||
nvbo->bo.offset + fb->offsets[1]);
|
||||
nvbo->offset + fb->offsets[1]);
|
||||
}
|
||||
nvif_wr32(dev, NV_PVIDEO_FORMAT(flip), format | fb->pitches[0]);
|
||||
nvif_wr32(dev, NV_PVIDEO_STOP, 0);
|
||||
|
@ -399,7 +399,7 @@ nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
|
|||
|
||||
for (i = 0; i < 2; i++) {
|
||||
nvif_wr32(dev, NV_PVIDEO_BUFF0_START_ADDRESS + 4 * i,
|
||||
nvbo->bo.offset);
|
||||
nvbo->offset);
|
||||
nvif_wr32(dev, NV_PVIDEO_BUFF0_PITCH_LENGTH + 4 * i,
|
||||
fb->pitches[0]);
|
||||
nvif_wr32(dev, NV_PVIDEO_BUFF0_OFFSET + 4 * i, 0);
|
||||
|
|
|
@ -276,7 +276,7 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format,
|
|||
|
||||
ret = nv50_dmac_create(&drm->client.device, &disp->disp.object,
|
||||
&oclass, head, &args, sizeof(args),
|
||||
disp50->sync->bo.offset, &wndw->wndw);
|
||||
disp50->sync->offset, &wndw->wndw);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "base%04x allocation failed: %d\n", oclass, ret);
|
||||
return ret;
|
||||
|
|
|
@ -115,7 +115,7 @@ core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
|
|||
|
||||
ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
|
||||
&oclass, 0, &args, sizeof(args),
|
||||
disp->sync->bo.offset, &core->chan);
|
||||
disp->sync->offset, &core->chan);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "core%04x allocation failed: %d\n", oclass, ret);
|
||||
return ret;
|
||||
|
|
|
@ -186,7 +186,7 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format,
|
|||
|
||||
ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
|
||||
&oclass, 0, &args, sizeof(args),
|
||||
disp->sync->bo.offset, &wndw->wndw);
|
||||
disp->sync->offset, &wndw->wndw);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "ovly%04x allocation failed: %d\n", oclass, ret);
|
||||
return ret;
|
||||
|
|
|
@ -526,7 +526,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
|
|||
}
|
||||
|
||||
asyw->state.fence = dma_resv_get_excl_rcu(nvbo->bo.base.resv);
|
||||
asyw->image.offset[0] = nvbo->bo.offset;
|
||||
asyw->image.offset[0] = nvbo->offset;
|
||||
|
||||
if (wndw->func->prepare) {
|
||||
asyh = nv50_head_atom_get(asyw->state.state, asyw->state.crtc);
|
||||
|
|
|
@ -298,7 +298,7 @@ wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm,
|
|||
|
||||
ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
|
||||
&oclass, 0, &args, sizeof(args),
|
||||
disp->sync->bo.offset, &wndw->wndw);
|
||||
disp->sync->offset, &wndw->wndw);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "qndw%04x allocation failed: %d\n", oclass, ret);
|
||||
return ret;
|
||||
|
|
|
@ -558,13 +558,13 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
|
|||
if (drm->agp.bridge) {
|
||||
args.target = NV_DMA_V0_TARGET_AGP;
|
||||
args.access = NV_DMA_V0_ACCESS_RDWR;
|
||||
args.start += drm->agp.base + chan->ntfy->bo.offset;
|
||||
args.limit += drm->agp.base + chan->ntfy->bo.offset;
|
||||
args.start += drm->agp.base + chan->ntfy->offset;
|
||||
args.limit += drm->agp.base + chan->ntfy->offset;
|
||||
} else {
|
||||
args.target = NV_DMA_V0_TARGET_VM;
|
||||
args.access = NV_DMA_V0_ACCESS_RDWR;
|
||||
args.start += chan->ntfy->bo.offset;
|
||||
args.limit += chan->ntfy->bo.offset;
|
||||
args.start += chan->ntfy->offset;
|
||||
args.limit += chan->ntfy->offset;
|
||||
}
|
||||
|
||||
client->route = NVDRM_OBJECT_ABI16;
|
||||
|
|
|
@ -1317,6 +1317,14 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
|
|||
nouveau_vma_unmap(vma);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_reg) {
|
||||
if (new_reg->mm_node)
|
||||
nvbo->offset = (new_reg->start << PAGE_SHIFT);
|
||||
else
|
||||
nvbo->offset = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -24,6 +24,9 @@ struct nouveau_bo {
|
|||
int pbbo_index;
|
||||
bool validate_mapped;
|
||||
|
||||
/* GPU address space is independent of CPU word size */
|
||||
uint64_t offset;
|
||||
|
||||
struct list_head vma_list;
|
||||
|
||||
unsigned contig:1;
|
||||
|
|
|
@ -162,7 +162,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
|
|||
* pushbuf lives in, this is because the GEM code requires that
|
||||
* we be able to call out to other (indirect) push buffers
|
||||
*/
|
||||
chan->push.addr = chan->push.buffer->bo.offset;
|
||||
chan->push.addr = chan->push.buffer->offset;
|
||||
|
||||
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
|
||||
ret = nouveau_vma_new(chan->push.buffer, chan->vmm,
|
||||
|
|
|
@ -100,7 +100,7 @@ unsigned long nouveau_dmem_page_addr(struct page *page)
|
|||
unsigned long off = (page_to_pfn(page) << PAGE_SHIFT) -
|
||||
chunk->pagemap.res.start;
|
||||
|
||||
return chunk->bo->bo.offset + off;
|
||||
return chunk->bo->offset + off;
|
||||
}
|
||||
|
||||
static void nouveau_dmem_page_free(struct page *page)
|
||||
|
|
|
@ -393,7 +393,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
|||
|
||||
/* To allow resizeing without swapping buffers */
|
||||
NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
|
||||
fb->width, fb->height, nvbo->bo.offset, nvbo);
|
||||
fb->width, fb->height, nvbo->offset, nvbo);
|
||||
|
||||
vga_switcheroo_client_fb_set(dev->pdev, info);
|
||||
return 0;
|
||||
|
|
|
@ -234,7 +234,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
|
|||
rep->domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
else
|
||||
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
rep->offset = nvbo->bo.offset;
|
||||
rep->offset = nvbo->offset;
|
||||
if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
|
||||
vma = nouveau_vma_find(nvbo, vmm);
|
||||
if (!vma)
|
||||
|
@ -518,7 +518,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
|
|||
}
|
||||
|
||||
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
|
||||
if (nvbo->bo.offset == b->presumed.offset &&
|
||||
if (nvbo->offset == b->presumed.offset &&
|
||||
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
|
||||
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
||||
(nvbo->bo.mem.mem_type == TTM_PL_TT &&
|
||||
|
@ -529,7 +529,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli,
|
|||
b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
else
|
||||
b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
b->presumed.offset = nvbo->bo.offset;
|
||||
b->presumed.offset = nvbo->offset;
|
||||
b->presumed.valid = 0;
|
||||
relocs++;
|
||||
}
|
||||
|
@ -807,7 +807,7 @@ revalidate:
|
|||
struct nouveau_bo *nvbo = (void *)(unsigned long)
|
||||
bo[push[i].bo_index].user_priv;
|
||||
|
||||
OUT_RING(chan, (nvbo->bo.offset + push[i].offset) | 2);
|
||||
OUT_RING(chan, (nvbo->offset + push[i].offset) | 2);
|
||||
OUT_RING(chan, 0);
|
||||
}
|
||||
} else {
|
||||
|
@ -842,7 +842,7 @@ revalidate:
|
|||
}
|
||||
|
||||
OUT_RING(chan, 0x20000000 |
|
||||
(nvbo->bo.offset + push[i].offset));
|
||||
(nvbo->offset + push[i].offset));
|
||||
OUT_RING(chan, 0);
|
||||
for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
|
||||
OUT_RING(chan, 0);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue