forked from Minki/linux
drm-misc-next for v5.12:
UAPI Changes: - Not necessarily one, but we document that userspace needs to force probe connectors. Cross-subsystem Changes: - Require FB_ATY_CT for aty on sparc64. - video: Fix documentation, and a few compiler warnings. - Add devicetree bindings for DP connectors. - dma-buf: Update kernel-doc, and add might_lock for resv objects in begin/end_cpu_access. Core Changes: - ttm: Warn when releasing a pinned bo. - ttm: Cleanup bo size handling. - cma-helper: Remove prime infix, and implement mmap as GEM CMA functions. - Split drm_prime_sg_to_page_addr_arrays into 2 functions. - Add a new api to install irq using devm. - Update panel kerneldoc to inline style. - Add DP support to drm/bridge. - Assorted small fixes to ttm, fb-helper, scheduler. - Add atomic_commit_setup function callback. - Automatically use the atomic gamma_set, instead of forcing drivers to declare the default atomic version. - Allow using degamma for legacy gamma if gamma is not available. - Clarify that primary/cursor planes are not tied to 1 crtc (depending on possible_crtcs). - ttm: Cleanup the lru handler. Driver Changes: - Add pm support to ingenic. - Assorted small fixes in radeon, via, rockchip, omap2fb, kmb, gma500, nouveau, virtio, hisilicon, ingenic, s6e63m0 panel, ast, udlfb. - Add BOE NV110WTM-N61, ys57pss36bh5gq, Khadas TS050 panels. - Stop using pages with drm_prime_sg_to_page_addr_arrays, and switch all callers to use ttm_sg_tt_init. - Cleanup compiler and docbook warnings in a lot of fbdev devices. - Use the drmm_vram_helper in hisilicon. - Add support for BCM2711 DSI1 in vc4. - Add support for 8-bit delta RGB panels to ingenic. - Add documentation on how to test vkms. - Convert vc4 to atomic helpers. - Use degamma instead of gamma table in omap, to add support for CTM and color encoding/range properties. - Rework omap DSI code, and merge all omapdrm modules now that the last omap panel is now a drm panel. - More refactoring of omap dsi code. - Enable 10/12 bpc outputs in vc4. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAl/bLtAACgkQ/lWMcqZw E8M5mBAAs6iA3giF+LrzQzszZqOFmtExwjHsvJXDtiINrVubdRov2XbbaOZ+8Eax Cnnc5QzokJV8v1IReImz+cP7i4uXyWmwQsthY2WvHYLXZmZfZUV+rK4cCtJIKXlR 9EvkEFtdPZ6OpyJ8p1G0r/UNqXxqOl4pEhp6NZdSj1mscz2yux/BuqX+1tX1j5+G SIfwcKIY+nIwnVpKwhJplJNfFwthRzENxq2KMt+PGLcpOWLHEgwqzKoR+ddTcKf2 Nk1w2OERbnBVRt8NzCIeyczlSp4QuB+NpE5mFEBedmLatGYqwAIwPMt22AVRP9rc SdXqjVxg3UJ5UNMYXQwjrnJq1nIm1ViYt7za/e2aMC8g9oI7tNQ5uI7XViO6+tk5 3vQV40pHVfMLGzkzqGhv9qHYAkkc+gPMAXwObuzmYppVVZn8dnrkAco7Ib8WPrRc g8JD0bpIsOrgqCTj2W54fC/ZP7hQZpffOrxWY7alhlriEl4E7To6OvTwEavIzxCm ajkO129oItOcATDTGiUV3JRWCTdCj4cNz7cQi4pC2QgaUIy8twjm57V8nnFDUCNg ifi1dIY24DOrHxdmZ8sAWZRoPzcl5a84c8EqEkGZieEsdr3Za4XMZD8tqI2uSJrU x+OfqgfvqNZenkuc+SUDZJQ855iqdkzJcqZnkAn61VpPh7XCtxk= =orEC -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2020-12-17' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v5.12: UAPI Changes: - Not necessarily one, but we document that userspace needs to force probe connectors. Cross-subsystem Changes: - Require FB_ATY_CT for aty on sparc64. - video: Fix documentation, and a few compiler warnings. - Add devicetree bindings for DP connectors. - dma-buf: Update kernel-doc, and add might_lock for resv objects in begin/end_cpu_access. Core Changes: - ttm: Warn when releasing a pinned bo. - ttm: Cleanup bo size handling. - cma-helper: Remove prime infix, and implement mmap as GEM CMA functions. - Split drm_prime_sg_to_page_addr_arrays into 2 functions. - Add a new api to install irq using devm. - Update panel kerneldoc to inline style. - Add DP support to drm/bridge. - Assorted small fixes to ttm, fb-helper, scheduler. - Add atomic_commit_setup function callback. - Automatically use the atomic gamma_set, instead of forcing drivers to declare the default atomic version. - Allow using degamma for legacy gamma if gamma is not available. - Clarify that primary/cursor planes are not tied to 1 crtc (depending on possible_crtcs). - ttm: Cleanup the lru handler. Driver Changes: - Add pm support to ingenic. - Assorted small fixes in radeon, via, rockchip, omap2fb, kmb, gma500, nouveau, virtio, hisilicon, ingenic, s6e63m0 panel, ast, udlfb. - Add BOE NV110WTM-N61, ys57pss36bh5gq, Khadas TS050 panels. - Stop using pages with drm_prime_sg_to_page_addr_arrays, and switch all callers to use ttm_sg_tt_init. - Cleanup compiler and docbook warnings in a lot of fbdev devices. - Use the drmm_vram_helper in hisilicon. - Add support for BCM2711 DSI1 in vc4. - Add support for 8-bit delta RGB panels to ingenic. - Add documentation on how to test vkms. - Convert vc4 to atomic helpers. - Use degamma instead of gamma table in omap, to add support for CTM and color encoding/range properties. - Rework omap DSI code, and merge all omapdrm modules now that the last omap panel is now a drm panel. - More refactoring of omap dsi code. - Enable 10/12 bpc outputs in vc4. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/78381a4f-45fd-aed4-174a-94ba051edd37@linux.intel.com
This commit is contained in:
commit
18589d74f4
@ -18,6 +18,7 @@ properties:
|
||||
|
||||
compatible:
|
||||
enum:
|
||||
- brcm,bcm2711-dsi1
|
||||
- brcm,bcm2835-dsi0
|
||||
- brcm,bcm2835-dsi1
|
||||
|
||||
|
@ -0,0 +1,56 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/connector/dp-connector.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: DisplayPort Connector
|
||||
|
||||
maintainers:
|
||||
- Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: dp-connector
|
||||
|
||||
label: true
|
||||
|
||||
type:
|
||||
enum:
|
||||
- full-size
|
||||
- mini
|
||||
|
||||
hpd-gpios:
|
||||
description: A GPIO line connected to HPD
|
||||
maxItems: 1
|
||||
|
||||
dp-pwr-supply:
|
||||
description: Power supply for the DP_PWR pin
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Connection to controller providing DP signals
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- type
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
connector {
|
||||
compatible = "dp-connector";
|
||||
label = "dp0";
|
||||
type = "full-size";
|
||||
|
||||
port {
|
||||
dp_connector_in: endpoint {
|
||||
remote-endpoint = <&dp_out>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -20,6 +20,7 @@ properties:
|
||||
compatible:
|
||||
enum:
|
||||
- mantix,mlaf057we51-x
|
||||
- ys,ys57pss36bh5gq
|
||||
|
||||
port: true
|
||||
reg:
|
||||
|
@ -35,6 +35,8 @@ properties:
|
||||
- boe,tv080wum-nl0
|
||||
# Innolux P079ZCA 7.85" 768x1024 TFT LCD panel
|
||||
- innolux,p079zca
|
||||
# Khadas TS050 5" 1080x1920 LCD panel
|
||||
- khadas,ts050
|
||||
# Kingdisplay KD097D04 9.7" 1536x2048 TFT LCD panel
|
||||
- kingdisplay,kd097d04
|
||||
# LG ACX467AKM-7 4.95" 1080×1920 LCD Panel
|
||||
|
@ -76,6 +76,8 @@ properties:
|
||||
# BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
|
||||
- boe,nv101wxmn51
|
||||
# BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
|
||||
- boe,nv110wtm-n61
|
||||
# BOE NV110WTM-N61 11.0" 2160x1440 TFT LCD Panel
|
||||
- boe,nv133fhm-n61
|
||||
# BOE NV133FHM-N62 13.3" FHD (1920x1080) TFT LCD Panel
|
||||
- boe,nv133fhm-n62
|
||||
|
@ -1,104 +0,0 @@
|
||||
ST-Ericsson Multi Channel Display Engine MCDE
|
||||
|
||||
The ST-Ericsson MCDE is a display controller with support for compositing
|
||||
and displaying several channels memory resident graphics data on DSI or
|
||||
LCD displays or bridges. It is used in the ST-Ericsson U8500 platform.
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be:
|
||||
"ste,mcde"
|
||||
- reg: register base for the main MCDE control registers, should be
|
||||
0x1000 in size
|
||||
- interrupts: the interrupt line for the MCDE
|
||||
- epod-supply: a phandle to the EPOD regulator
|
||||
- vana-supply: a phandle to the analog voltage regulator
|
||||
- clocks: an array of the MCDE clocks in this strict order:
|
||||
MCDECLK (main MCDE clock), LCDCLK (LCD clock), PLLDSI
|
||||
(HDMI clock), DSI0ESCLK (DSI0 energy save clock),
|
||||
DSI1ESCLK (DSI1 energy save clock), DSI2ESCLK (DSI2 energy
|
||||
save clock)
|
||||
- clock-names: must be the following array:
|
||||
"mcde", "lcd", "hdmi"
|
||||
to match the required clock inputs above.
|
||||
- #address-cells: should be <1> (for the DSI hosts that will be children)
|
||||
- #size-cells: should be <1> (for the DSI hosts that will be children)
|
||||
- ranges: this should always be stated
|
||||
|
||||
Required subnodes:
|
||||
|
||||
The devicetree must specify subnodes for the DSI host adapters.
|
||||
These must have the following characteristics:
|
||||
|
||||
- compatible: must be:
|
||||
"ste,mcde-dsi"
|
||||
- reg: must specify the register range for the DSI host
|
||||
- vana-supply: phandle to the VANA voltage regulator
|
||||
- clocks: phandles to the high speed and low power (energy save) clocks
|
||||
the high speed clock is not present on the third (dsi2) block, so it
|
||||
should only have the "lp" clock
|
||||
- clock-names: "hs" for the high speed clock and "lp" for the low power
|
||||
(energy save) clock
|
||||
- #address-cells: should be <1>
|
||||
- #size-cells: should be <0>
|
||||
|
||||
Display panels and bridges will appear as children on the DSI hosts, and
|
||||
the displays are connected to the DSI hosts using the common binding
|
||||
for video transmitter interfaces; see
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
If a DSI host is unused (not connected) it will have no children defined.
|
||||
|
||||
Example:
|
||||
|
||||
mcde@a0350000 {
|
||||
compatible = "ste,mcde";
|
||||
reg = <0xa0350000 0x1000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
epod-supply = <&db8500_b2r2_mcde_reg>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_MCDECLK>, /* Main MCDE clock */
|
||||
<&prcmu_clk PRCMU_LCDCLK>, /* LCD clock */
|
||||
<&prcmu_clk PRCMU_PLLDSI>; /* HDMI clock */
|
||||
clock-names = "mcde", "lcd", "hdmi";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
dsi0: dsi@a0351000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0351000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>;
|
||||
clock-names = "hs", "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel {
|
||||
compatible = "samsung,s6d16d0";
|
||||
reg = <0>;
|
||||
vdd1-supply = <&ab8500_ldo_aux1_reg>;
|
||||
reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
};
|
||||
dsi1: dsi@a0352000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0352000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>;
|
||||
clock-names = "hs", "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
dsi2: dsi@a0353000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0353000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
/* This DSI port only has the Low Power / Energy Save clock */
|
||||
clocks = <&prcmu_clk PRCMU_DSI2ESCCLK>;
|
||||
clock-names = "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
169
Documentation/devicetree/bindings/display/ste,mcde.yaml
Normal file
169
Documentation/devicetree/bindings/display/ste,mcde.yaml
Normal file
@ -0,0 +1,169 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/display/ste,mcde.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: ST-Ericsson Multi Channel Display Engine MCDE
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ste,mcde
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
description: an array of the MCDE clocks
|
||||
items:
|
||||
- description: MCDECLK (main MCDE clock)
|
||||
- description: LCDCLK (LCD clock)
|
||||
- description: PLLDSI (HDMI clock)
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: mcde
|
||||
- const: lcd
|
||||
- const: hdmi
|
||||
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
epod-supply:
|
||||
description: a phandle to the EPOD regulator
|
||||
|
||||
vana-supply:
|
||||
description: a phandle to the analog voltage regulator
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
A DPI port node with endpoint definitions as defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 1
|
||||
|
||||
ranges: true
|
||||
|
||||
patternProperties:
|
||||
"^dsi@[0-9a-f]+$":
|
||||
description: subnodes for the three DSI host adapters
|
||||
type: object
|
||||
allOf:
|
||||
- $ref: dsi-controller.yaml#
|
||||
properties:
|
||||
compatible:
|
||||
const: ste,mcde-dsi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vana-supply:
|
||||
description: a phandle to the analog voltage regulator
|
||||
|
||||
clocks:
|
||||
description: phandles to the high speed and low power (energy save) clocks
|
||||
the high speed clock is not present on the third (dsi2) block, so it
|
||||
should only have the "lp" clock
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
clock-names:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: hs
|
||||
- const: lp
|
||||
- items:
|
||||
- const: lp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- vana-supply
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- epod-supply
|
||||
- vana-supply
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/mfd/dbx500-prcmu.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
mcde@a0350000 {
|
||||
compatible = "ste,mcde";
|
||||
reg = <0xa0350000 0x1000>;
|
||||
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
|
||||
epod-supply = <&db8500_b2r2_mcde_reg>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_MCDECLK>,
|
||||
<&prcmu_clk PRCMU_LCDCLK>,
|
||||
<&prcmu_clk PRCMU_PLLDSI>;
|
||||
clock-names = "mcde", "lcd", "hdmi";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
dsi0: dsi@a0351000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0351000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_DSI0CLK>, <&prcmu_clk PRCMU_DSI0ESCCLK>;
|
||||
clock-names = "hs", "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
panel@0 {
|
||||
compatible = "samsung,s6d16d0";
|
||||
reg = <0>;
|
||||
vdd1-supply = <&ab8500_ldo_aux1_reg>;
|
||||
reset-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
|
||||
dsi1: dsi@a0352000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0352000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
clocks = <&prcmu_clk PRCMU_DSI1CLK>, <&prcmu_clk PRCMU_DSI1ESCCLK>;
|
||||
clock-names = "hs", "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
|
||||
dsi2: dsi@a0353000 {
|
||||
compatible = "ste,mcde-dsi";
|
||||
reg = <0xa0353000 0x1000>;
|
||||
vana-supply = <&ab8500_ldo_ana_reg>;
|
||||
/* This DSI port only has the Low Power / Energy Save clock */
|
||||
clocks = <&prcmu_clk PRCMU_DSI2ESCCLK>;
|
||||
clock-names = "lp";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1260,6 +1260,8 @@ patternProperties:
|
||||
description: YSH & ATIL
|
||||
"^yones-toptech,.*":
|
||||
description: Yones Toptech Co., Ltd.
|
||||
"^ys,.*":
|
||||
description: Shenzhen Yashi Changhua Intelligent Technology Co., Ltd.
|
||||
"^ysoft,.*":
|
||||
description: Y Soft Corporation a.s.
|
||||
"^zealz,.*":
|
||||
|
@ -7,6 +7,76 @@
|
||||
.. kernel-doc:: drivers/gpu/drm/vkms/vkms_drv.c
|
||||
:doc: vkms (Virtual Kernel Modesetting)
|
||||
|
||||
Setup
|
||||
=====
|
||||
|
||||
The VKMS driver can be setup with the following steps:
|
||||
|
||||
To check if VKMS is loaded, run::
|
||||
|
||||
lsmod | grep vkms
|
||||
|
||||
This should list the VKMS driver. If no output is obtained, then
|
||||
you need to enable and/or load the VKMS driver.
|
||||
Ensure that the VKMS driver has been set as a loadable module in your
|
||||
kernel config file. Do::
|
||||
|
||||
make nconfig
|
||||
|
||||
Go to `Device Drivers> Graphics support`
|
||||
|
||||
Enable `Virtual KMS (EXPERIMENTAL)`
|
||||
|
||||
Compile and build the kernel for the changes to get reflected.
|
||||
Now, to load the driver, use::
|
||||
|
||||
sudo modprobe vkms
|
||||
|
||||
On running the lsmod command now, the VKMS driver will appear listed.
|
||||
You can also observe the driver being loaded in the dmesg logs.
|
||||
|
||||
To disable the driver, use ::
|
||||
|
||||
sudo modprobe -r vkms
|
||||
|
||||
Testing With IGT
|
||||
================
|
||||
|
||||
The IGT GPU Tools is a test suite used specifically for debugging and
|
||||
development of the DRM drivers.
|
||||
The IGT Tools can be installed from
|
||||
`here <https://gitlab.freedesktop.org/drm/igt-gpu-tools>`_ .
|
||||
|
||||
The tests need to be run without a compositor, so you need to switch to text
|
||||
only mode. You can do this by::
|
||||
|
||||
sudo systemctl isolate multi-user.target
|
||||
|
||||
To return to graphical mode, do::
|
||||
|
||||
sudo systemctl isolate graphical.target
|
||||
|
||||
Once you are in text only mode, you can run tests using the --device switch
|
||||
or IGT_DEVICE variable to specify the device filter for the driver we want
|
||||
to test. IGT_DEVICE can also be used with the run-test.sh script to run the
|
||||
tests for a specific driver::
|
||||
|
||||
sudo ./build/tests/<name of test> --device "sys:/sys/devices/platform/vkms"
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/<name of test>
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./scripts/run-tests.sh -t <name of test>
|
||||
|
||||
For example, to test the functionality of the writeback library,
|
||||
we can run the kms_writeback test::
|
||||
|
||||
sudo ./build/tests/kms_writeback --device "sys:/sys/devices/platform/vkms"
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_writeback
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./scripts/run-tests.sh -t kms_writeback
|
||||
|
||||
You can also run subtests if you do not want to run the entire test::
|
||||
|
||||
sudo ./build/tests/kms_flip --run-subtest basic-plain-flip --device "sys:/sys/devices/platform/vkms"
|
||||
sudo IGT_DEVICE="sys:/sys/devices/platform/vkms" ./build/tests/kms_flip --run-subtest basic-plain-flip
|
||||
|
||||
TODO
|
||||
====
|
||||
|
||||
|
@ -518,6 +518,9 @@
|
||||
clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>,
|
||||
<&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>;
|
||||
clock-names = "fck", "sys_clk";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
@ -550,6 +553,9 @@
|
||||
clocks = <&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 8>,
|
||||
<&dss_clkctrl OMAP5_DSS_CORE_CLKCTRL 10>;
|
||||
clock-names = "fck", "sys_clk";
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -369,8 +369,8 @@ CONFIG_DRM_OMAP=m
|
||||
CONFIG_OMAP5_DSS_HDMI=y
|
||||
CONFIG_OMAP2_DSS_SDI=y
|
||||
CONFIG_OMAP2_DSS_DSI=y
|
||||
CONFIG_DRM_OMAP_PANEL_DSI_CM=m
|
||||
CONFIG_DRM_TILCDC=m
|
||||
CONFIG_DRM_PANEL_DSI_CM=m
|
||||
CONFIG_DRM_PANEL_SIMPLE=m
|
||||
CONFIG_DRM_PANEL_LG_LB035Q02=m
|
||||
CONFIG_DRM_PANEL_NEC_NL8048HL11=m
|
||||
|
@ -480,7 +480,7 @@ err_alloc_file:
|
||||
*
|
||||
* 4. Once a driver is done with a shared buffer it needs to call
|
||||
* dma_buf_detach() (after cleaning up any mappings) and then release the
|
||||
* reference acquired with dma_buf_get by calling dma_buf_put().
|
||||
* reference acquired with dma_buf_get() by calling dma_buf_put().
|
||||
*
|
||||
* For the detailed semantics exporters are expected to implement see
|
||||
* &dma_buf_ops.
|
||||
@ -496,9 +496,10 @@ err_alloc_file:
|
||||
* by the exporter. see &struct dma_buf_export_info
|
||||
* for further details.
|
||||
*
|
||||
* Returns, on success, a newly created dma_buf object, which wraps the
|
||||
* supplied private data and operations for dma_buf_ops. On either missing
|
||||
* ops, or error in allocating struct dma_buf, will return negative error.
|
||||
* Returns, on success, a newly created struct dma_buf object, which wraps the
|
||||
* supplied private data and operations for struct dma_buf_ops. On either
|
||||
* missing ops, or error in allocating struct dma_buf, will return negative
|
||||
* error.
|
||||
*
|
||||
* For most cases the easiest way to create @exp_info is through the
|
||||
* %DEFINE_DMA_BUF_EXPORT_INFO macro.
|
||||
@ -584,7 +585,7 @@ err_module:
|
||||
EXPORT_SYMBOL_GPL(dma_buf_export);
|
||||
|
||||
/**
|
||||
* dma_buf_fd - returns a file descriptor for the given dma_buf
|
||||
* dma_buf_fd - returns a file descriptor for the given struct dma_buf
|
||||
* @dmabuf: [in] pointer to dma_buf for which fd is required.
|
||||
* @flags: [in] flags to give to fd
|
||||
*
|
||||
@ -608,10 +609,10 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
|
||||
EXPORT_SYMBOL_GPL(dma_buf_fd);
|
||||
|
||||
/**
|
||||
* dma_buf_get - returns the dma_buf structure related to an fd
|
||||
* @fd: [in] fd associated with the dma_buf to be returned
|
||||
* dma_buf_get - returns the struct dma_buf related to an fd
|
||||
* @fd: [in] fd associated with the struct dma_buf to be returned
|
||||
*
|
||||
* On success, returns the dma_buf structure associated with an fd; uses
|
||||
* On success, returns the struct dma_buf associated with an fd; uses
|
||||
* file's refcounting done by fget to increase refcount. returns ERR_PTR
|
||||
* otherwise.
|
||||
*/
|
||||
@ -653,8 +654,7 @@ void dma_buf_put(struct dma_buf *dmabuf)
|
||||
EXPORT_SYMBOL_GPL(dma_buf_put);
|
||||
|
||||
/**
|
||||
* dma_buf_dynamic_attach - Add the device to dma_buf's attachments list; optionally,
|
||||
* calls attach() of dma_buf_ops to allow device-specific attach functionality
|
||||
* dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
|
||||
* @dmabuf: [in] buffer to attach device to.
|
||||
* @dev: [in] device to be attached.
|
||||
* @importer_ops: [in] importer operations for the attachment
|
||||
@ -663,6 +663,9 @@ EXPORT_SYMBOL_GPL(dma_buf_put);
|
||||
* Returns struct dma_buf_attachment pointer for this attachment. Attachments
|
||||
* must be cleaned up by calling dma_buf_detach().
|
||||
*
|
||||
* Optionally this calls &dma_buf_ops.attach to allow device-specific attach
|
||||
* functionality.
|
||||
*
|
||||
* Returns:
|
||||
*
|
||||
* A pointer to newly created &dma_buf_attachment on success, or a negative
|
||||
@ -769,12 +772,13 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
|
||||
EXPORT_SYMBOL_GPL(dma_buf_attach);
|
||||
|
||||
/**
|
||||
* dma_buf_detach - Remove the given attachment from dmabuf's attachments list;
|
||||
* optionally calls detach() of dma_buf_ops for device-specific detach
|
||||
* dma_buf_detach - Remove the given attachment from dmabuf's attachments list
|
||||
* @dmabuf: [in] buffer to detach from.
|
||||
* @attach: [in] attachment to be detached; is free'd after this call.
|
||||
*
|
||||
* Clean up a device attachment obtained by calling dma_buf_attach().
|
||||
*
|
||||
* Optionally this calls &dma_buf_ops.detach for device-specific detach.
|
||||
*/
|
||||
void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
|
||||
{
|
||||
@ -805,9 +809,15 @@ EXPORT_SYMBOL_GPL(dma_buf_detach);
|
||||
|
||||
/**
|
||||
* dma_buf_pin - Lock down the DMA-buf
|
||||
*
|
||||
* @attach: [in] attachment which should be pinned
|
||||
*
|
||||
* Only dynamic importers (who set up @attach with dma_buf_dynamic_attach()) may
|
||||
* call this, and only for limited use cases like scanout and not for temporary
|
||||
* pin operations. It is not permitted to allow userspace to pin arbitrary
|
||||
* amounts of buffers through this interface.
|
||||
*
|
||||
* Buffers must be unpinned by calling dma_buf_unpin().
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, negative error code on failure.
|
||||
*/
|
||||
@ -816,6 +826,8 @@ int dma_buf_pin(struct dma_buf_attachment *attach)
|
||||
struct dma_buf *dmabuf = attach->dmabuf;
|
||||
int ret = 0;
|
||||
|
||||
WARN_ON(!dma_buf_attachment_is_dynamic(attach));
|
||||
|
||||
dma_resv_assert_held(dmabuf->resv);
|
||||
|
||||
if (dmabuf->ops->pin)
|
||||
@ -826,14 +838,19 @@ int dma_buf_pin(struct dma_buf_attachment *attach)
|
||||
EXPORT_SYMBOL_GPL(dma_buf_pin);
|
||||
|
||||
/**
|
||||
* dma_buf_unpin - Remove lock from DMA-buf
|
||||
*
|
||||
* dma_buf_unpin - Unpin a DMA-buf
|
||||
* @attach: [in] attachment which should be unpinned
|
||||
*
|
||||
* This unpins a buffer pinned by dma_buf_pin() and allows the exporter to move
|
||||
* any mapping of @attach again and inform the importer through
|
||||
* &dma_buf_attach_ops.move_notify.
|
||||
*/
|
||||
void dma_buf_unpin(struct dma_buf_attachment *attach)
|
||||
{
|
||||
struct dma_buf *dmabuf = attach->dmabuf;
|
||||
|
||||
WARN_ON(!dma_buf_attachment_is_dynamic(attach));
|
||||
|
||||
dma_resv_assert_held(dmabuf->resv);
|
||||
|
||||
if (dmabuf->ops->unpin)
|
||||
@ -1001,15 +1018,15 @@ EXPORT_SYMBOL_GPL(dma_buf_move_notify);
|
||||
* vmalloc space might be limited and result in vmap calls failing.
|
||||
*
|
||||
* Interfaces::
|
||||
*
|
||||
* void \*dma_buf_vmap(struct dma_buf \*dmabuf)
|
||||
* void dma_buf_vunmap(struct dma_buf \*dmabuf, void \*vaddr)
|
||||
*
|
||||
* The vmap call can fail if there is no vmap support in the exporter, or if
|
||||
* it runs out of vmalloc space. Fallback to kmap should be implemented. Note
|
||||
* that the dma-buf layer keeps a reference count for all vmap access and
|
||||
* calls down into the exporter's vmap function only when no vmapping exists,
|
||||
* and only unmaps it once. Protection against concurrent vmap/vunmap calls is
|
||||
* provided by taking the dma_buf->lock mutex.
|
||||
* it runs out of vmalloc space. Note that the dma-buf layer keeps a reference
|
||||
* count for all vmap access and calls down into the exporter's vmap function
|
||||
* only when no vmapping exists, and only unmaps it once. Protection against
|
||||
* concurrent vmap/vunmap calls is provided by taking the &dma_buf.lock mutex.
|
||||
*
|
||||
* - For full compatibility on the importer side with existing userspace
|
||||
* interfaces, which might already support mmap'ing buffers. This is needed in
|
||||
@ -1061,11 +1078,12 @@ EXPORT_SYMBOL_GPL(dma_buf_move_notify);
|
||||
* shootdowns would increase the complexity quite a bit.
|
||||
*
|
||||
* Interface::
|
||||
*
|
||||
* int dma_buf_mmap(struct dma_buf \*, struct vm_area_struct \*,
|
||||
* unsigned long);
|
||||
*
|
||||
* If the importing subsystem simply provides a special-purpose mmap call to
|
||||
* set up a mapping in userspace, calling do_mmap with dma_buf->file will
|
||||
* set up a mapping in userspace, calling do_mmap with &dma_buf.file will
|
||||
* equally achieve that for a dma-buf object.
|
||||
*/
|
||||
|
||||
@ -1098,6 +1116,11 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
* dma_buf_end_cpu_access(). Only when cpu access is braketed by both calls is
|
||||
* it guaranteed to be coherent with other DMA access.
|
||||
*
|
||||
* This function will also wait for any DMA transactions tracked through
|
||||
* implicit synchronization in &dma_buf.resv. For DMA transactions with explicit
|
||||
* synchronization this function will only ensure cache coherency, callers must
|
||||
* ensure synchronization with such DMA transactions on their own.
|
||||
*
|
||||
* Can return negative error values, returns 0 on success.
|
||||
*/
|
||||
int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
@ -1108,6 +1131,8 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
|
||||
if (WARN_ON(!dmabuf))
|
||||
return -EINVAL;
|
||||
|
||||
might_lock(&dmabuf->resv->lock.base);
|
||||
|
||||
if (dmabuf->ops->begin_cpu_access)
|
||||
ret = dmabuf->ops->begin_cpu_access(dmabuf, direction);
|
||||
|
||||
@ -1141,6 +1166,8 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
|
||||
|
||||
WARN_ON(!dmabuf);
|
||||
|
||||
might_lock(&dmabuf->resv->lock.base);
|
||||
|
||||
if (dmabuf->ops->end_cpu_access)
|
||||
ret = dmabuf->ops->end_cpu_access(dmabuf, direction);
|
||||
|
||||
@ -1199,7 +1226,10 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap);
|
||||
* This call may fail due to lack of virtual mapping address space.
|
||||
* These calls are optional in drivers. The intended use for them
|
||||
* is for mapping objects linear in kernel space for high use objects.
|
||||
* Please attempt to use kmap/kunmap before thinking about these interfaces.
|
||||
*
|
||||
* To ensure coherency users must call dma_buf_begin_cpu_access() and
|
||||
* dma_buf_end_cpu_access() around any cpu access performed through this
|
||||
* mapping.
|
||||
*
|
||||
* Returns 0 on success, or a negative errno code otherwise.
|
||||
*/
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include <drm/ttm/ttm_bo_api.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
#include <drm/ttm/ttm_execbuf_util.h>
|
||||
|
||||
#include <drm/amdgpu_drm.h>
|
||||
|
@ -453,7 +453,7 @@ static int add_bo_to_vm(struct amdgpu_device *adev, struct kgd_mem *mem,
|
||||
struct amdgpu_bo *bo = mem->bo;
|
||||
uint64_t va = mem->va;
|
||||
struct list_head *list_bo_va = &mem->bo_va_list;
|
||||
unsigned long bo_size = bo->tbo.mem.size;
|
||||
unsigned long bo_size = bo->tbo.base.size;
|
||||
|
||||
if (!va) {
|
||||
pr_err("Invalid VA when adding BO to VM\n");
|
||||
@ -1281,7 +1281,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
|
||||
struct kgd_dev *kgd, struct kgd_mem *mem, uint64_t *size)
|
||||
{
|
||||
struct amdkfd_process_info *process_info = mem->process_info;
|
||||
unsigned long bo_size = mem->bo->tbo.mem.size;
|
||||
unsigned long bo_size = mem->bo->tbo.base.size;
|
||||
struct kfd_bo_va_list *entry, *tmp;
|
||||
struct bo_vm_reservation_context ctx;
|
||||
struct ttm_validate_buffer *bo_list_entry;
|
||||
@ -1402,7 +1402,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
|
||||
mutex_lock(&mem->lock);
|
||||
|
||||
domain = mem->domain;
|
||||
bo_size = bo->tbo.mem.size;
|
||||
bo_size = bo->tbo.base.size;
|
||||
|
||||
pr_debug("Map VA 0x%llx - 0x%llx to vm %p domain %s\n",
|
||||
mem->va,
|
||||
@ -1506,7 +1506,7 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
|
||||
struct amdgpu_device *adev = get_amdgpu_device(kgd);
|
||||
struct amdkfd_process_info *process_info =
|
||||
((struct amdgpu_vm *)vm)->process_info;
|
||||
unsigned long bo_size = mem->bo->tbo.mem.size;
|
||||
unsigned long bo_size = mem->bo->tbo.base.size;
|
||||
struct kfd_bo_va_list *entry;
|
||||
struct bo_vm_reservation_context ctx;
|
||||
int ret;
|
||||
|
@ -1427,7 +1427,7 @@ static void amdgpu_ib_preempt_job_recovery(struct drm_gpu_scheduler *sched)
|
||||
struct dma_fence *fence;
|
||||
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
|
||||
list_for_each_entry(s_job, &sched->pending_list, list) {
|
||||
fence = sched->ops->run_job(s_job);
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
@ -1459,10 +1459,10 @@ static void amdgpu_ib_preempt_mark_partial_job(struct amdgpu_ring *ring)
|
||||
|
||||
no_preempt:
|
||||
spin_lock(&sched->job_list_lock);
|
||||
list_for_each_entry_safe(s_job, tmp, &sched->ring_mirror_list, node) {
|
||||
list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) {
|
||||
if (dma_fence_is_signaled(&s_job->s_fence->finished)) {
|
||||
/* remove job from ring_mirror_list */
|
||||
list_del_init(&s_job->node);
|
||||
list_del_init(&s_job->list);
|
||||
sched->ops->free_job(s_job);
|
||||
continue;
|
||||
}
|
||||
|
@ -4155,8 +4155,8 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev)
|
||||
continue;
|
||||
|
||||
spin_lock(&ring->sched.job_list_lock);
|
||||
job = list_first_entry_or_null(&ring->sched.ring_mirror_list,
|
||||
struct drm_sched_job, node);
|
||||
job = list_first_entry_or_null(&ring->sched.pending_list,
|
||||
struct drm_sched_job, list);
|
||||
spin_unlock(&ring->sched.job_list_lock);
|
||||
if (job)
|
||||
return true;
|
||||
|
@ -269,7 +269,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach,
|
||||
case TTM_PL_TT:
|
||||
sgt = drm_prime_pages_to_sg(obj->dev,
|
||||
bo->tbo.ttm->pages,
|
||||
bo->tbo.num_pages);
|
||||
bo->tbo.ttm->num_pages);
|
||||
if (IS_ERR(sgt))
|
||||
return sgt;
|
||||
|
||||
|
@ -120,7 +120,7 @@ uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
|
||||
|
||||
if (bo->num_pages != 1 || bo->ttm->caching == ttm_cached)
|
||||
if (bo->ttm->num_pages != 1 || bo->ttm->caching == ttm_cached)
|
||||
return AMDGPU_BO_INVALID_OFFSET;
|
||||
|
||||
if (bo->ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size)
|
||||
|
@ -271,7 +271,7 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
|
||||
}
|
||||
|
||||
/* Signal all jobs already scheduled to HW */
|
||||
list_for_each_entry(s_job, &sched->ring_mirror_list, node) {
|
||||
list_for_each_entry(s_job, &sched->pending_list, list) {
|
||||
struct drm_sched_fence *s_fence = s_job->s_fence;
|
||||
|
||||
dma_fence_set_error(&s_fence->finished, -EHWPOISON);
|
||||
|
@ -787,7 +787,7 @@ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
|
||||
r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.mem.num_pages, &bo->kmap);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -174,12 +174,12 @@ static inline void amdgpu_bo_unreserve(struct amdgpu_bo *bo)
|
||||
|
||||
static inline unsigned long amdgpu_bo_size(struct amdgpu_bo *bo)
|
||||
{
|
||||
return bo->tbo.num_pages << PAGE_SHIFT;
|
||||
return bo->tbo.base.size;
|
||||
}
|
||||
|
||||
static inline unsigned amdgpu_bo_ngpu_pages(struct amdgpu_bo *bo)
|
||||
{
|
||||
return (bo->tbo.num_pages << PAGE_SHIFT) / AMDGPU_GPU_PAGE_SIZE;
|
||||
return bo->tbo.base.size / AMDGPU_GPU_PAGE_SIZE;
|
||||
}
|
||||
|
||||
static inline unsigned amdgpu_bo_gpu_page_alignment(struct amdgpu_bo *bo)
|
||||
|
@ -127,7 +127,7 @@ TRACE_EVENT(amdgpu_bo_create,
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->bo = bo;
|
||||
__entry->pages = bo->tbo.num_pages;
|
||||
__entry->pages = bo->tbo.mem.num_pages;
|
||||
__entry->type = bo->tbo.mem.mem_type;
|
||||
__entry->prefer = bo->preferred_domains;
|
||||
__entry->allow = bo->allowed_domains;
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include <drm/ttm/ttm_bo_api.h>
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
|
||||
#include <drm/drm_debugfs.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
@ -637,7 +636,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
|
||||
out:
|
||||
/* update statistics */
|
||||
atomic64_add((u64)bo->num_pages << PAGE_SHIFT, &adev->num_bytes_moved);
|
||||
atomic64_add(bo->base.size, &adev->num_bytes_moved);
|
||||
amdgpu_bo_move_notify(bo, evict, new_mem);
|
||||
return 0;
|
||||
}
|
||||
@ -918,8 +917,8 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device *bdev,
|
||||
goto release_sg;
|
||||
|
||||
/* convert SG to linear array of pages and dma addresses */
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
|
||||
gtt->ttm.dma_address, ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1265,9 +1264,8 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev,
|
||||
ttm->sg = sgt;
|
||||
}
|
||||
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
|
||||
gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, gtt->ttm.dma_address,
|
||||
ttm->num_pages);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2124,7 +2122,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
return r;
|
||||
}
|
||||
|
||||
num_pages = bo->tbo.num_pages;
|
||||
num_pages = bo->tbo.mem.num_pages;
|
||||
mm_node = bo->tbo.mem.mm_node;
|
||||
num_loops = 0;
|
||||
while (num_pages) {
|
||||
@ -2154,7 +2152,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo,
|
||||
}
|
||||
}
|
||||
|
||||
num_pages = bo->tbo.num_pages;
|
||||
num_pages = bo->tbo.mem.num_pages;
|
||||
mm_node = bo->tbo.mem.mm_node;
|
||||
|
||||
while (num_pages) {
|
||||
|
@ -1160,6 +1160,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
error:
|
||||
dma_fence_put(fence);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
amdgpu_bo_free_kernel(&bo, NULL, NULL);
|
||||
return r;
|
||||
}
|
||||
|
@ -496,6 +496,7 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
||||
struct amdgpu_job *job;
|
||||
struct amdgpu_ib *ib;
|
||||
uint64_t addr;
|
||||
void *msg = NULL;
|
||||
int i, r;
|
||||
|
||||
r = amdgpu_job_alloc_with_ib(adev, 64,
|
||||
@ -505,6 +506,7 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
||||
|
||||
ib = &job->ibs[0];
|
||||
addr = amdgpu_bo_gpu_offset(bo);
|
||||
msg = amdgpu_bo_kptr(bo);
|
||||
ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
|
||||
ib->ptr[1] = addr;
|
||||
ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
|
||||
@ -523,7 +525,7 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
|
||||
|
||||
amdgpu_bo_fence(bo, f, false);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg);
|
||||
|
||||
if (fence)
|
||||
*fence = dma_fence_get(f);
|
||||
@ -536,7 +538,7 @@ err_free:
|
||||
|
||||
err:
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
amdgpu_bo_free_kernel(&bo, NULL, (void **)&msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -890,6 +892,7 @@ int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
|
||||
error:
|
||||
dma_fence_put(fence);
|
||||
amdgpu_bo_unreserve(bo);
|
||||
amdgpu_bo_unref(&bo);
|
||||
amdgpu_bo_free_kernel(&bo, NULL, NULL);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -653,9 +653,11 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
|
||||
if (!bo->parent)
|
||||
continue;
|
||||
|
||||
ttm_bo_move_to_lru_tail(&bo->tbo, &vm->lru_bulk_move);
|
||||
ttm_bo_move_to_lru_tail(&bo->tbo, &bo->tbo.mem,
|
||||
&vm->lru_bulk_move);
|
||||
if (bo->shadow)
|
||||
ttm_bo_move_to_lru_tail(&bo->shadow->tbo,
|
||||
&bo->shadow->tbo.mem,
|
||||
&vm->lru_bulk_move);
|
||||
}
|
||||
spin_unlock(&ttm_bo_glob.lru_lock);
|
||||
|
@ -554,7 +554,7 @@ static int mes_v10_1_allocate_eop_buf(struct amdgpu_device *adev)
|
||||
return r;
|
||||
}
|
||||
|
||||
memset(eop, 0, adev->mes.eop_gpu_obj->tbo.mem.size);
|
||||
memset(eop, 0, adev->mes.eop_gpu_obj->tbo.base.size);
|
||||
|
||||
amdgpu_bo_kunmap(adev->mes.eop_gpu_obj);
|
||||
amdgpu_bo_unreserve(adev->mes.eop_gpu_obj);
|
||||
|
@ -5446,7 +5446,6 @@ static void dm_disable_vblank(struct drm_crtc *crtc)
|
||||
static const struct drm_crtc_funcs amdgpu_dm_crtc_funcs = {
|
||||
.reset = dm_crtc_reset_state,
|
||||
.destroy = amdgpu_dm_crtc_destroy,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.atomic_duplicate_state = dm_crtc_duplicate_state,
|
||||
|
@ -550,7 +550,6 @@ static void komeda_crtc_vblank_disable(struct drm_crtc *crtc)
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs komeda_crtc_funcs = {
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
|
@ -510,7 +510,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
}
|
||||
|
||||
static const struct drm_crtc_funcs malidp_crtc_funcs = {
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
|
@ -820,7 +820,6 @@ static const struct drm_crtc_funcs armada_crtc_funcs = {
|
||||
.cursor_set = armada_drm_crtc_cursor_set,
|
||||
.cursor_move = armada_drm_crtc_cursor_move,
|
||||
.destroy = armada_drm_crtc_destroy,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
||||
|
@ -39,7 +39,6 @@ static void ast_cursor_fini(struct ast_private *ast)
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ast->cursor.gbo); ++i) {
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_vunmap(gbo, &ast->cursor.map[i]);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
}
|
||||
@ -53,14 +52,13 @@ static void ast_cursor_release(struct drm_device *dev, void *ptr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate cursor BOs and pins them at the end of VRAM.
|
||||
* Allocate cursor BOs and pin them at the end of VRAM.
|
||||
*/
|
||||
int ast_cursor_init(struct ast_private *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
size_t size, i;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
struct dma_buf_map map;
|
||||
int ret;
|
||||
|
||||
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
@ -77,15 +75,7 @@ int ast_cursor_init(struct ast_private *ast)
|
||||
drm_gem_vram_put(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
ret = drm_gem_vram_vmap(gbo, &map);
|
||||
if (ret) {
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
goto err_drm_gem_vram_put;
|
||||
}
|
||||
|
||||
ast->cursor.gbo[i] = gbo;
|
||||
ast->cursor.map[i] = map;
|
||||
}
|
||||
|
||||
return drmm_add_action_or_reset(dev, ast_cursor_release, NULL);
|
||||
@ -94,7 +84,6 @@ err_drm_gem_vram_put:
|
||||
while (i) {
|
||||
--i;
|
||||
gbo = ast->cursor.gbo[i];
|
||||
drm_gem_vram_vunmap(gbo, &ast->cursor.map[i]);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_put(gbo);
|
||||
}
|
||||
@ -168,38 +157,37 @@ static void update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int h
|
||||
int ast_cursor_blit(struct ast_private *ast, struct drm_framebuffer *fb)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_gem_vram_object *gbo;
|
||||
struct dma_buf_map map;
|
||||
int ret;
|
||||
void *src;
|
||||
struct drm_gem_vram_object *dst_gbo = ast->cursor.gbo[ast->cursor.next_index];
|
||||
struct drm_gem_vram_object *src_gbo = drm_gem_vram_of_gem(fb->obj[0]);
|
||||
struct dma_buf_map src_map, dst_map;
|
||||
void __iomem *dst;
|
||||
void *src;
|
||||
int ret;
|
||||
|
||||
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);
|
||||
ret = drm_gem_vram_vmap(src_gbo, &src_map);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = drm_gem_vram_vmap(gbo, &map);
|
||||
if (ret)
|
||||
goto err_drm_gem_vram_unpin;
|
||||
src = map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
dst = ast->cursor.map[ast->cursor.next_index].vaddr_iomem;
|
||||
ret = drm_gem_vram_vmap(dst_gbo, &dst_map);
|
||||
if (ret)
|
||||
goto err_drm_gem_vram_vunmap;
|
||||
dst = dst_map.vaddr_iomem; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
/* do data transfer to cursor BO */
|
||||
update_cursor_image(dst, src, fb->width, fb->height);
|
||||
|
||||
drm_gem_vram_vunmap(gbo, &map);
|
||||
drm_gem_vram_unpin(gbo);
|
||||
drm_gem_vram_vunmap(dst_gbo, &dst_map);
|
||||
drm_gem_vram_vunmap(src_gbo, &src_map);
|
||||
|
||||
return 0;
|
||||
|
||||
err_drm_gem_vram_unpin:
|
||||
drm_gem_vram_unpin(gbo);
|
||||
err_drm_gem_vram_vunmap:
|
||||
drm_gem_vram_vunmap(src_gbo, &src_map);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -251,17 +239,26 @@ static void ast_cursor_set_location(struct ast_private *ast, u16 x, u16 y,
|
||||
void ast_cursor_show(struct ast_private *ast, int x, int y,
|
||||
unsigned int offset_x, unsigned int offset_y)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct drm_gem_vram_object *gbo = ast->cursor.gbo[ast->cursor.next_index];
|
||||
struct dma_buf_map map;
|
||||
u8 x_offset, y_offset;
|
||||
u8 __iomem *dst;
|
||||
u8 __iomem *sig;
|
||||
u8 jreg;
|
||||
int ret;
|
||||
|
||||
dst = ast->cursor.map[ast->cursor.next_index].vaddr;
|
||||
ret = drm_gem_vram_vmap(gbo, &map);
|
||||
if (drm_WARN_ONCE(dev, ret, "drm_gem_vram_vmap() failed, ret=%d\n", ret))
|
||||
return;
|
||||
dst = map.vaddr_iomem; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
sig = dst + AST_HWC_SIZE;
|
||||
writel(x, sig + AST_HWC_SIGNATURE_X);
|
||||
writel(y, sig + AST_HWC_SIGNATURE_Y);
|
||||
|
||||
drm_gem_vram_vunmap(gbo, &map);
|
||||
|
||||
if (x < 0) {
|
||||
x_offset = (-x) + offset_x;
|
||||
x = 0;
|
||||
|
@ -28,7 +28,6 @@
|
||||
#ifndef __AST_DRV_H__
|
||||
#define __AST_DRV_H__
|
||||
|
||||
#include <linux/dma-buf-map.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/io.h>
|
||||
@ -133,7 +132,6 @@ struct ast_private {
|
||||
|
||||
struct {
|
||||
struct drm_gem_vram_object *gbo[AST_DEFAULT_HWC_NUM];
|
||||
struct dma_buf_map map[AST_DEFAULT_HWC_NUM];
|
||||
unsigned int next_index;
|
||||
} cursor;
|
||||
|
||||
|
@ -903,7 +903,6 @@ static void ast_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||
|
||||
static const struct drm_crtc_funcs ast_crtc_funcs = {
|
||||
.reset = ast_crtc_reset,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
|
@ -473,7 +473,6 @@ static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
|
||||
.atomic_destroy_state = atmel_hlcdc_crtc_destroy_state,
|
||||
.enable_vblank = atmel_hlcdc_crtc_enable_vblank,
|
||||
.disable_vblank = atmel_hlcdc_crtc_disable_vblank,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
};
|
||||
|
||||
int atmel_hlcdc_crtc_create(struct drm_device *dev)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_edid.h>
|
||||
@ -20,6 +21,8 @@ struct display_connector {
|
||||
|
||||
struct gpio_desc *hpd_gpio;
|
||||
int hpd_irq;
|
||||
|
||||
struct regulator *dp_pwr;
|
||||
};
|
||||
|
||||
static inline struct display_connector *
|
||||
@ -172,11 +175,12 @@ static int display_connector_probe(struct platform_device *pdev)
|
||||
of_property_read_string(pdev->dev.of_node, "label", &label);
|
||||
|
||||
/*
|
||||
* Get the HPD GPIO for DVI and HDMI connectors. If the GPIO can provide
|
||||
* Get the HPD GPIO for DVI, HDMI and DP connectors. If the GPIO can provide
|
||||
* edge interrupts, register an interrupt handler.
|
||||
*/
|
||||
if (type == DRM_MODE_CONNECTOR_DVII ||
|
||||
type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
conn->hpd_gpio = devm_gpiod_get_optional(&pdev->dev, "hpd",
|
||||
GPIOD_IN);
|
||||
if (IS_ERR(conn->hpd_gpio)) {
|
||||
@ -223,6 +227,38 @@ static int display_connector_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the DP PWR for DP connector. */
|
||||
if (type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
int ret;
|
||||
|
||||
conn->dp_pwr = devm_regulator_get_optional(&pdev->dev, "dp-pwr");
|
||||
|
||||
if (IS_ERR(conn->dp_pwr)) {
|
||||
ret = PTR_ERR(conn->dp_pwr);
|
||||
|
||||
switch (ret) {
|
||||
case -ENODEV:
|
||||
conn->dp_pwr = NULL;
|
||||
break;
|
||||
|
||||
case -EPROBE_DEFER:
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
default:
|
||||
dev_err(&pdev->dev, "failed to get DP PWR regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->dp_pwr) {
|
||||
ret = regulator_enable(conn->dp_pwr);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable DP PWR regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conn->bridge.funcs = &display_connector_bridge_funcs;
|
||||
conn->bridge.of_node = pdev->dev.of_node;
|
||||
|
||||
@ -251,6 +287,9 @@ static int display_connector_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct display_connector *conn = platform_get_drvdata(pdev);
|
||||
|
||||
if (conn->dp_pwr)
|
||||
regulator_disable(conn->dp_pwr);
|
||||
|
||||
drm_bridge_remove(&conn->bridge);
|
||||
|
||||
if (!IS_ERR(conn->bridge.ddc))
|
||||
@ -275,6 +314,9 @@ static const struct of_device_id display_connector_match[] = {
|
||||
}, {
|
||||
.compatible = "vga-connector",
|
||||
.data = (void *)DRM_MODE_CONNECTOR_VGA,
|
||||
}, {
|
||||
.compatible = "dp-connector",
|
||||
.data = (void *)DRM_MODE_CONNECTOR_DisplayPort,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
@ -2040,6 +2040,9 @@ crtc_or_fake_commit(struct drm_atomic_state *state, struct drm_crtc *crtc)
|
||||
* should always call this function from their
|
||||
* &drm_mode_config_funcs.atomic_commit hook.
|
||||
*
|
||||
* Drivers that need to extend the commit setup to private objects can use the
|
||||
* &drm_mode_config_helper_funcs.atomic_commit_setup hook.
|
||||
*
|
||||
* To be able to use this support drivers need to use a few more helper
|
||||
* functions. drm_atomic_helper_wait_for_dependencies() must be called before
|
||||
* actually committing the hardware state, and for nonblocking commits this call
|
||||
@ -2083,8 +2086,11 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *old_plane_state, *new_plane_state;
|
||||
struct drm_crtc_commit *commit;
|
||||
const struct drm_mode_config_helper_funcs *funcs;
|
||||
int i, ret;
|
||||
|
||||
funcs = state->dev->mode_config.helper_private;
|
||||
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
commit = kzalloc(sizeof(*commit), GFP_KERNEL);
|
||||
if (!commit)
|
||||
@ -2169,6 +2175,9 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state,
|
||||
new_plane_state->commit = drm_crtc_commit_get(commit);
|
||||
}
|
||||
|
||||
if (funcs && funcs->atomic_commit_setup)
|
||||
return funcs->atomic_commit_setup(state);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_setup_commit);
|
||||
@ -3499,76 +3508,6 @@ fail:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_page_flip_target);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
|
||||
* @crtc: CRTC object
|
||||
* @red: red correction table
|
||||
* @green: green correction table
|
||||
* @blue: green correction table
|
||||
* @size: size of the tables
|
||||
* @ctx: lock acquire context
|
||||
*
|
||||
* Implements support for legacy gamma correction table for drivers
|
||||
* that support color management through the DEGAMMA_LUT/GAMMA_LUT
|
||||
* properties. See drm_crtc_enable_color_mgmt() and the containing chapter for
|
||||
* how the atomic color management and gamma tables work.
|
||||
*/
|
||||
int drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *red, u16 *green, u16 *blue,
|
||||
uint32_t size,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_property_blob *blob = NULL;
|
||||
struct drm_color_lut *blob_data;
|
||||
int i, ret = 0;
|
||||
bool replaced;
|
||||
|
||||
state = drm_atomic_state_alloc(crtc->dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
blob = drm_property_create_blob(dev,
|
||||
sizeof(struct drm_color_lut) * size,
|
||||
NULL);
|
||||
if (IS_ERR(blob)) {
|
||||
ret = PTR_ERR(blob);
|
||||
blob = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Prepare GAMMA_LUT with the legacy values. */
|
||||
blob_data = blob->data;
|
||||
for (i = 0; i < size; i++) {
|
||||
blob_data[i].red = red[i];
|
||||
blob_data[i].green = green[i];
|
||||
blob_data[i].blue = blue[i];
|
||||
}
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state)) {
|
||||
ret = PTR_ERR(crtc_state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Reset DEGAMMA_LUT and CTM properties. */
|
||||
replaced = drm_property_replace_blob(&crtc_state->degamma_lut, NULL);
|
||||
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
|
||||
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut, blob);
|
||||
crtc_state->color_mgmt_changed |= replaced;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
|
||||
fail:
|
||||
drm_atomic_state_put(state);
|
||||
drm_property_blob_put(blob);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to
|
||||
* the input end of a bridge
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
@ -89,9 +90,8 @@
|
||||
* modes) appropriately.
|
||||
*
|
||||
* There is also support for a legacy gamma table, which is set up by calling
|
||||
* drm_mode_crtc_set_gamma_size(). Drivers which support both should use
|
||||
* drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the
|
||||
* "GAMMA_LUT" property above.
|
||||
* drm_mode_crtc_set_gamma_size(). The DRM core will then alias the legacy gamma
|
||||
* ramp with "GAMMA_LUT" or, if that is unavailable, "DEGAMMA_LUT".
|
||||
*
|
||||
* Support for different non RGB color encodings is controlled through
|
||||
* &drm_plane specific COLOR_ENCODING and COLOR_RANGE properties. They
|
||||
@ -156,9 +156,6 @@ EXPORT_SYMBOL(drm_color_ctm_s31_32_to_qm_n);
|
||||
* optional. The gamma and degamma properties are only attached if
|
||||
* their size is not 0 and ctm_property is only attached if has_ctm is
|
||||
* true.
|
||||
*
|
||||
* Drivers should use drm_atomic_helper_legacy_gamma_set() to implement the
|
||||
* legacy &drm_crtc_funcs.gamma_set callback.
|
||||
*/
|
||||
void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
|
||||
uint degamma_lut_size,
|
||||
@ -231,6 +228,116 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
|
||||
|
||||
/**
|
||||
* drm_crtc_supports_legacy_gamma - does the crtc support legacy gamma correction table
|
||||
* @crtc: CRTC object
|
||||
*
|
||||
* Returns true/false if the given crtc supports setting the legacy gamma
|
||||
* correction table.
|
||||
*/
|
||||
static bool drm_crtc_supports_legacy_gamma(struct drm_crtc *crtc)
|
||||
{
|
||||
u32 gamma_id = crtc->dev->mode_config.gamma_lut_property->base.id;
|
||||
u32 degamma_id = crtc->dev->mode_config.degamma_lut_property->base.id;
|
||||
|
||||
if (!crtc->gamma_size)
|
||||
return false;
|
||||
|
||||
if (crtc->funcs->gamma_set)
|
||||
return true;
|
||||
|
||||
return !!(drm_mode_obj_find_prop_id(&crtc->base, gamma_id) ||
|
||||
drm_mode_obj_find_prop_id(&crtc->base, degamma_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_crtc_legacy_gamma_set - set the legacy gamma correction table
|
||||
* @crtc: CRTC object
|
||||
* @red: red correction table
|
||||
* @green: green correction table
|
||||
* @blue: green correction table
|
||||
* @size: size of the tables
|
||||
* @ctx: lock acquire context
|
||||
*
|
||||
* Implements support for legacy gamma correction table for drivers
|
||||
* that have set drm_crtc_funcs.gamma_set or that support color management
|
||||
* through the DEGAMMA_LUT/GAMMA_LUT properties. See
|
||||
* drm_crtc_enable_color_mgmt() and the containing chapter for
|
||||
* how the atomic color management and gamma tables work.
|
||||
*
|
||||
* This function sets the gamma using drm_crtc_funcs.gamma_set if set, or
|
||||
* alternatively using crtc color management properties.
|
||||
*/
|
||||
static int drm_crtc_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *red, u16 *green, u16 *blue,
|
||||
u32 size,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_property_blob *blob;
|
||||
struct drm_color_lut *blob_data;
|
||||
u32 gamma_id = dev->mode_config.gamma_lut_property->base.id;
|
||||
u32 degamma_id = dev->mode_config.degamma_lut_property->base.id;
|
||||
bool use_gamma_lut;
|
||||
int i, ret = 0;
|
||||
bool replaced;
|
||||
|
||||
if (crtc->funcs->gamma_set)
|
||||
return crtc->funcs->gamma_set(crtc, red, green, blue, size, ctx);
|
||||
|
||||
if (drm_mode_obj_find_prop_id(&crtc->base, gamma_id))
|
||||
use_gamma_lut = true;
|
||||
else if (drm_mode_obj_find_prop_id(&crtc->base, degamma_id))
|
||||
use_gamma_lut = false;
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
state = drm_atomic_state_alloc(crtc->dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
blob = drm_property_create_blob(dev,
|
||||
sizeof(struct drm_color_lut) * size,
|
||||
NULL);
|
||||
if (IS_ERR(blob)) {
|
||||
ret = PTR_ERR(blob);
|
||||
blob = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Prepare GAMMA_LUT with the legacy values. */
|
||||
blob_data = blob->data;
|
||||
for (i = 0; i < size; i++) {
|
||||
blob_data[i].red = red[i];
|
||||
blob_data[i].green = green[i];
|
||||
blob_data[i].blue = blue[i];
|
||||
}
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state)) {
|
||||
ret = PTR_ERR(crtc_state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set GAMMA_LUT and reset DEGAMMA_LUT and CTM */
|
||||
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
|
||||
use_gamma_lut ? NULL : blob);
|
||||
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
|
||||
replaced |= drm_property_replace_blob(&crtc_state->gamma_lut,
|
||||
use_gamma_lut ? blob : NULL);
|
||||
crtc_state->color_mgmt_changed |= replaced;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
|
||||
fail:
|
||||
drm_atomic_state_put(state);
|
||||
drm_property_blob_put(blob);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_gamma_set_ioctl - set the gamma table
|
||||
* @dev: DRM device
|
||||
@ -262,7 +369,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
|
||||
if (!crtc)
|
||||
return -ENOENT;
|
||||
|
||||
if (crtc->funcs->gamma_set == NULL)
|
||||
if (!drm_crtc_supports_legacy_gamma(crtc))
|
||||
return -ENOSYS;
|
||||
|
||||
/* memcpy into gamma store */
|
||||
@ -290,8 +397,8 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
|
||||
crtc->gamma_size, &ctx);
|
||||
ret = drm_crtc_legacy_gamma_set(crtc, r_base, g_base, b_base,
|
||||
crtc->gamma_size, &ctx);
|
||||
|
||||
out:
|
||||
DRM_MODESET_LOCK_ALL_END(dev, ctx, ret);
|
||||
|
@ -67,7 +67,7 @@
|
||||
* &drm_crtc_funcs.page_flip and &drm_crtc_funcs.cursor_set2, and other legacy
|
||||
* operations like &drm_crtc_funcs.gamma_set. For atomic drivers all these
|
||||
* features are controlled through &drm_property and
|
||||
* &drm_mode_config_funcs.atomic_check and &drm_mode_config_funcs.atomic_check.
|
||||
* &drm_mode_config_funcs.atomic_check.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -256,6 +256,9 @@ struct dma_fence *drm_crtc_create_fence(struct drm_crtc *crtc)
|
||||
* planes). For really simple hardware which has only 1 plane look at
|
||||
* drm_simple_display_pipe_init() instead.
|
||||
*
|
||||
* The @primary and @cursor planes are only relevant for legacy uAPI, see
|
||||
* &drm_crtc.primary and &drm_crtc.cursor.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
|
@ -675,11 +675,8 @@ static int devm_drm_dev_init(struct device *parent,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = devm_add_action(parent, devm_drm_dev_init_release, dev);
|
||||
if (ret)
|
||||
devm_drm_dev_init_release(dev);
|
||||
|
||||
return ret;
|
||||
return devm_add_action_or_reset(parent,
|
||||
devm_drm_dev_init_release, dev);
|
||||
}
|
||||
|
||||
void *__devm_drm_dev_alloc(struct device *parent,
|
||||
@ -897,8 +894,6 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
drm_modeset_register_all(dev);
|
||||
|
||||
ret = 0;
|
||||
|
||||
DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
|
||||
driver->name, driver->major, driver->minor,
|
||||
driver->patchlevel, driver->date,
|
||||
|
@ -946,11 +946,15 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
|
||||
drm_modeset_lock_all(fb_helper->dev);
|
||||
drm_client_for_each_modeset(modeset, &fb_helper->client) {
|
||||
crtc = modeset->crtc;
|
||||
if (!crtc->funcs->gamma_set || !crtc->gamma_size)
|
||||
return -EINVAL;
|
||||
if (!crtc->funcs->gamma_set || !crtc->gamma_size) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmap->start + cmap->len > crtc->gamma_size)
|
||||
return -EINVAL;
|
||||
if (cmap->start + cmap->len > crtc->gamma_size) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = crtc->gamma_store;
|
||||
g = r + crtc->gamma_size;
|
||||
@ -963,8 +967,9 @@ static int setcmap_legacy(struct fb_cmap *cmap, struct fb_info *info)
|
||||
ret = crtc->funcs->gamma_set(crtc, r, g, b,
|
||||
crtc->gamma_size, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
drm_modeset_unlock_all(fb_helper->dev);
|
||||
|
||||
return ret;
|
||||
@ -1054,6 +1059,11 @@ retry:
|
||||
goto out_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: This always uses gamma_lut. Some HW have only
|
||||
* degamma_lut, in which case we should reset gamma_lut and set
|
||||
* degamma_lut. See drm_crtc_legacy_gamma_set().
|
||||
*/
|
||||
replaced = drm_property_replace_blob(&crtc_state->degamma_lut,
|
||||
NULL);
|
||||
replaced |= drm_property_replace_blob(&crtc_state->ctm, NULL);
|
||||
|
@ -113,8 +113,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
|
||||
* The memory mapping implementation will vary depending on how the driver
|
||||
* manages memory. Legacy drivers will use the deprecated drm_legacy_mmap()
|
||||
* function, modern drivers should use one of the provided memory-manager
|
||||
* specific implementations. For GEM-based drivers this is drm_gem_mmap(), and
|
||||
* for drivers which use the CMA GEM helpers it's drm_gem_cma_mmap().
|
||||
* specific implementations. For GEM-based drivers this is drm_gem_mmap().
|
||||
*
|
||||
* No other file operations are supported by the DRM userspace API. Overall the
|
||||
* following is an example &file_operations structure::
|
||||
|
@ -36,8 +36,9 @@
|
||||
static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
|
||||
.free = drm_gem_cma_free_object,
|
||||
.print_info = drm_gem_cma_print_info,
|
||||
.get_sg_table = drm_gem_cma_prime_get_sg_table,
|
||||
.vmap = drm_gem_cma_prime_vmap,
|
||||
.get_sg_table = drm_gem_cma_get_sg_table,
|
||||
.vmap = drm_gem_cma_vmap,
|
||||
.mmap = drm_gem_cma_mmap,
|
||||
.vm_ops = &drm_gem_cma_vm_ops,
|
||||
};
|
||||
|
||||
@ -277,62 +278,6 @@ const struct vm_operations_struct drm_gem_cma_vm_ops = {
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
|
||||
|
||||
static int drm_gem_cma_mmap_obj(struct drm_gem_cma_object *cma_obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
|
||||
* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
|
||||
* the whole buffer.
|
||||
*/
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
vma->vm_pgoff = 0;
|
||||
|
||||
ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
|
||||
cma_obj->paddr, vma->vm_end - vma->vm_start);
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_gem_cma_mmap - memory-map a CMA GEM object
|
||||
* @filp: file object
|
||||
* @vma: VMA for the area to be mapped
|
||||
*
|
||||
* This function implements an augmented version of the GEM DRM file mmap
|
||||
* operation for CMA objects: In addition to the usual GEM VMA setup it
|
||||
* immediately faults in the entire object instead of using on-demaind
|
||||
* faulting. Drivers which employ the CMA helpers should use this function
|
||||
* as their ->mmap() handler in the DRM device file's file_operations
|
||||
* structure.
|
||||
*
|
||||
* Instead of directly referencing this function, drivers should use the
|
||||
* DEFINE_DRM_GEM_CMA_FOPS().macro.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret;
|
||||
|
||||
ret = drm_gem_mmap(filp, vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
gem_obj = vma->vm_private_data;
|
||||
cma_obj = to_drm_gem_cma_obj(gem_obj);
|
||||
|
||||
return drm_gem_cma_mmap_obj(cma_obj, vma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
/**
|
||||
* drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases
|
||||
@ -424,18 +369,18 @@ void drm_gem_cma_print_info(struct drm_printer *p, unsigned int indent,
|
||||
EXPORT_SYMBOL(drm_gem_cma_print_info);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_get_sg_table - provide a scatter/gather table of pinned
|
||||
* drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned
|
||||
* pages for a CMA GEM object
|
||||
* @obj: GEM object
|
||||
*
|
||||
* This function exports a scatter/gather table suitable for PRIME usage by
|
||||
* This function exports a scatter/gather table by
|
||||
* calling the standard DMA mapping API. Drivers using the CMA helpers should
|
||||
* set this as their &drm_gem_object_funcs.get_sg_table callback.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the scatter/gather table of pinned pages or NULL on failure.
|
||||
*/
|
||||
struct sg_table *drm_gem_cma_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
|
||||
struct sg_table *sgt;
|
||||
@ -456,7 +401,7 @@ out:
|
||||
kfree(sgt);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_get_sg_table);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another
|
||||
@ -501,40 +446,13 @@ drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_mmap - memory-map an exported CMA GEM object
|
||||
* @obj: GEM object
|
||||
* @vma: VMA for the area to be mapped
|
||||
*
|
||||
* This function maps a buffer imported via DRM PRIME into a userspace
|
||||
* process's address space. Drivers that use the CMA helpers should set this
|
||||
* as their &drm_driver.gem_prime_mmap callback.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_prime_mmap(struct drm_gem_object *obj,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
int ret;
|
||||
|
||||
ret = drm_gem_mmap_obj(obj, obj->size, vma);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
return drm_gem_cma_mmap_obj(cma_obj, vma);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_mmap);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_vmap - map a CMA GEM object into the kernel's virtual
|
||||
* drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual
|
||||
* address space
|
||||
* @obj: GEM object
|
||||
* @map: Returns the kernel virtual address of the CMA GEM object's backing
|
||||
* store.
|
||||
*
|
||||
* This function maps a buffer exported via DRM PRIME into the kernel's
|
||||
* This function maps a buffer into the kernel's
|
||||
* virtual address space. Since the CMA buffers are already mapped into the
|
||||
* kernel virtual address space this simply returns the cached virtual
|
||||
* address. Drivers using the CMA helpers should set this as their DRM
|
||||
@ -543,7 +461,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_prime_mmap);
|
||||
* Returns:
|
||||
* 0 on success, or a negative error code otherwise.
|
||||
*/
|
||||
int drm_gem_cma_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
|
||||
int drm_gem_cma_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(obj);
|
||||
|
||||
@ -551,7 +469,44 @@ int drm_gem_cma_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_vmap);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_vmap);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_mmap - memory-map an exported CMA GEM object
|
||||
* @obj: GEM object
|
||||
* @vma: VMA for the area to be mapped
|
||||
*
|
||||
* This function maps a buffer into a userspace process's address space.
|
||||
* In addition to the usual GEM VMA setup it immediately faults in the entire
|
||||
* object instead of using on-demand faulting. Drivers that use the CMA
|
||||
* helpers should set this as their &drm_gem_object_funcs.mmap callback.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Clear the VM_PFNMAP flag that was set by drm_gem_mmap(), and set the
|
||||
* vm_pgoff (used as a fake buffer offset by DRM) to 0 as we want to map
|
||||
* the whole buffer.
|
||||
*/
|
||||
vma->vm_pgoff -= drm_vma_node_start(&obj->vma_node);
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
|
||||
ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
|
||||
cma_obj->paddr, vma->vm_end - vma->vm_start);
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
|
||||
|
@ -214,6 +214,38 @@ int drm_irq_uninstall(struct drm_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_irq_uninstall);
|
||||
|
||||
static void devm_drm_irq_uninstall(void *data)
|
||||
{
|
||||
drm_irq_uninstall(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* devm_drm_irq_install - install IRQ handler
|
||||
* @dev: DRM device
|
||||
* @irq: IRQ number to install the handler for
|
||||
*
|
||||
* devm_drm_irq_install is a help function of drm_irq_install.
|
||||
*
|
||||
* if the driver uses devm_drm_irq_install, there is no need
|
||||
* to call drm_irq_uninstall when the drm module get unloaded,
|
||||
* as this will done automagically.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success or a negative error code on failure.
|
||||
*/
|
||||
int devm_drm_irq_install(struct drm_device *dev, int irq)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = drm_irq_install(dev, irq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev->dev,
|
||||
devm_drm_irq_uninstall, dev);
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_irq_install);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_LEGACY)
|
||||
int drm_legacy_irq_control(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
|
@ -625,6 +625,7 @@ static void validate_encoder_possible_crtcs(struct drm_encoder *encoder)
|
||||
void drm_mode_config_validate(struct drm_device *dev)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (!drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return;
|
||||
@ -636,4 +637,22 @@ void drm_mode_config_validate(struct drm_device *dev)
|
||||
validate_encoder_possible_clones(encoder);
|
||||
validate_encoder_possible_crtcs(encoder);
|
||||
}
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
WARN(!crtc->primary, "Missing primary plane on [CRTC:%d:%s]\n",
|
||||
crtc->base.id, crtc->name);
|
||||
|
||||
if (crtc->primary) {
|
||||
WARN(!(crtc->primary->possible_crtcs & drm_crtc_mask(crtc)),
|
||||
"Bogus primary plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n",
|
||||
crtc->primary->base.id, crtc->primary->name,
|
||||
crtc->base.id, crtc->name);
|
||||
}
|
||||
if (crtc->cursor) {
|
||||
WARN(!(crtc->cursor->possible_crtcs & drm_crtc_mask(crtc)),
|
||||
"Bogus cursor plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n",
|
||||
crtc->cursor->base.id, crtc->cursor->name,
|
||||
crtc->base.id, crtc->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
* A plane represents an image source that can be blended with or overlayed on
|
||||
* top of a CRTC during the scanout process. Planes take their input data from a
|
||||
* &drm_framebuffer object. The plane itself specifies the cropping and scaling
|
||||
* of that image, and where it is placed on the visible are of a display
|
||||
* of that image, and where it is placed on the visible area of a display
|
||||
* pipeline, represented by &drm_crtc. A plane can also have additional
|
||||
* properties that specify how the pixels are positioned and blended, like
|
||||
* rotation or Z-position. All these properties are stored in &drm_plane_state.
|
||||
@ -49,14 +49,16 @@
|
||||
* &struct drm_plane (possibly as part of a larger structure) and registers it
|
||||
* with a call to drm_universal_plane_init().
|
||||
*
|
||||
* Cursor and overlay planes are optional. All drivers should provide one
|
||||
* primary plane per CRTC to avoid surprising userspace too much. See enum
|
||||
* drm_plane_type for a more in-depth discussion of these special uapi-relevant
|
||||
* plane types. Special planes are associated with their CRTC by calling
|
||||
* drm_crtc_init_with_planes().
|
||||
*
|
||||
* The type of a plane is exposed in the immutable "type" enumeration property,
|
||||
* which has one of the following values: "Overlay", "Primary", "Cursor".
|
||||
* which has one of the following values: "Overlay", "Primary", "Cursor" (see
|
||||
* enum drm_plane_type). A plane can be compatible with multiple CRTCs, see
|
||||
* &drm_plane.possible_crtcs.
|
||||
*
|
||||
* Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core
|
||||
* relies on the driver to set the primary and optionally the cursor plane used
|
||||
* for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
|
||||
* drivers must provide one primary plane per CRTC to avoid surprising legacy
|
||||
* userspace too much.
|
||||
*/
|
||||
|
||||
static unsigned int drm_num_planes(struct drm_device *dev)
|
||||
|
@ -978,44 +978,58 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev,
|
||||
EXPORT_SYMBOL(drm_gem_prime_import);
|
||||
|
||||
/**
|
||||
* drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array
|
||||
* drm_prime_sg_to_page_array - convert an sg table into a page array
|
||||
* @sgt: scatter-gather table to convert
|
||||
* @pages: optional array of page pointers to store the page array in
|
||||
* @addrs: optional array to store the dma bus address of each page
|
||||
* @max_entries: size of both the passed-in arrays
|
||||
* @pages: array of page pointers to store the pages in
|
||||
* @max_entries: size of the passed-in array
|
||||
*
|
||||
* Exports an sg table into an array of pages and addresses. This is currently
|
||||
* required by the TTM driver in order to do correct fault handling.
|
||||
* Exports an sg table into an array of pages.
|
||||
*
|
||||
* Drivers can use this in their &drm_driver.gem_prime_import_sg_table
|
||||
* implementation.
|
||||
* This function is deprecated and strongly discouraged to be used.
|
||||
* The page array is only useful for page faults and those can corrupt fields
|
||||
* in the struct page if they are not handled by the exporting driver.
|
||||
*/
|
||||
int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages,
|
||||
dma_addr_t *addrs, int max_entries)
|
||||
int __deprecated drm_prime_sg_to_page_array(struct sg_table *sgt,
|
||||
struct page **pages,
|
||||
int max_entries)
|
||||
{
|
||||
struct sg_dma_page_iter dma_iter;
|
||||
struct sg_page_iter page_iter;
|
||||
struct page **p = pages;
|
||||
dma_addr_t *a = addrs;
|
||||
|
||||
if (pages) {
|
||||
for_each_sgtable_page(sgt, &page_iter, 0) {
|
||||
if (WARN_ON(p - pages >= max_entries))
|
||||
return -1;
|
||||
*p++ = sg_page_iter_page(&page_iter);
|
||||
}
|
||||
for_each_sgtable_page(sgt, &page_iter, 0) {
|
||||
if (WARN_ON(p - pages >= max_entries))
|
||||
return -1;
|
||||
*p++ = sg_page_iter_page(&page_iter);
|
||||
}
|
||||
if (addrs) {
|
||||
for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
|
||||
if (WARN_ON(a - addrs >= max_entries))
|
||||
return -1;
|
||||
*a++ = sg_page_iter_dma_address(&dma_iter);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays);
|
||||
EXPORT_SYMBOL(drm_prime_sg_to_page_array);
|
||||
|
||||
/**
|
||||
* drm_prime_sg_to_dma_addr_array - convert an sg table into a dma addr array
|
||||
* @sgt: scatter-gather table to convert
|
||||
* @addrs: array to store the dma bus address of each page
|
||||
* @max_entries: size of both the passed-in arrays
|
||||
*
|
||||
* Exports an sg table into an array of addresses.
|
||||
*
|
||||
* Drivers should use this in their &drm_driver.gem_prime_import_sg_table
|
||||
* implementation.
|
||||
*/
|
||||
int drm_prime_sg_to_dma_addr_array(struct sg_table *sgt, dma_addr_t *addrs,
|
||||
int max_entries)
|
||||
{
|
||||
struct sg_dma_page_iter dma_iter;
|
||||
dma_addr_t *a = addrs;
|
||||
|
||||
for_each_sgtable_dma_page(sgt, &dma_iter, 0) {
|
||||
if (WARN_ON(a - addrs >= max_entries))
|
||||
return -1;
|
||||
*a++ = sg_page_iter_dma_address(&dma_iter);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_prime_sg_to_dma_addr_array);
|
||||
|
||||
/**
|
||||
* drm_prime_gem_destroy - helper to clean up a PRIME-imported GEM object
|
||||
|
@ -135,8 +135,7 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = drm_prime_sg_to_page_addr_arrays(sgt, etnaviv_obj->pages,
|
||||
NULL, npages);
|
||||
ret = drm_prime_sg_to_page_array(sgt, etnaviv_obj->pages, npages);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
@ -279,11 +279,8 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev)
|
||||
hdmi_dev = pci_get_drvdata(dev);
|
||||
|
||||
i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
|
||||
if (i2c_dev == NULL) {
|
||||
DRM_ERROR("Can't allocate interface\n");
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
if (!i2c_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_dev->adap = &oaktrail_hdmi_i2c_adapter;
|
||||
i2c_dev->status = I2C_STAT_INIT;
|
||||
@ -300,16 +297,23 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev)
|
||||
oaktrail_hdmi_i2c_adapter.name, hdmi_dev);
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to request IRQ for I2C controller\n");
|
||||
goto err;
|
||||
goto free_dev;
|
||||
}
|
||||
|
||||
/* Adapter registration */
|
||||
ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter);
|
||||
return ret;
|
||||
if (ret) {
|
||||
DRM_ERROR("Failed to add I2C adapter\n");
|
||||
goto free_irq;
|
||||
}
|
||||
|
||||
err:
|
||||
return 0;
|
||||
|
||||
free_irq:
|
||||
free_irq(dev->irq, hdmi_dev);
|
||||
free_dev:
|
||||
kfree(i2c_dev);
|
||||
exit:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -312,6 +312,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
ret = -ENOMEM;
|
||||
|
||||
dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0);
|
||||
if (!dev_priv->mmu)
|
||||
goto out_err;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_ttm.o hibmc_drm_i2c.o
|
||||
hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_i2c.o
|
||||
|
||||
obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
|
||||
|
@ -499,7 +499,7 @@ static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = {
|
||||
|
||||
int hibmc_de_init(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = priv->dev;
|
||||
struct drm_device *dev = &priv->dev;
|
||||
struct drm_crtc *crtc = &priv->crtc;
|
||||
struct drm_plane *plane = &priv->primary_plane;
|
||||
int ret;
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_irq.h>
|
||||
#include <drm/drm_managed.h>
|
||||
@ -43,6 +44,12 @@ static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
return drm_gem_vram_fill_create_dumb(file, dev, 0, 128, args);
|
||||
}
|
||||
|
||||
static const struct drm_driver hibmc_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.fops = &hibmc_fops,
|
||||
@ -77,47 +84,48 @@ static const struct dev_pm_ops hibmc_pm_ops = {
|
||||
hibmc_pm_resume)
|
||||
};
|
||||
|
||||
static const struct drm_mode_config_funcs hibmc_mode_funcs = {
|
||||
.mode_valid = drm_vram_helper_mode_valid,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
.fb_create = drm_gem_fb_create,
|
||||
};
|
||||
|
||||
static int hibmc_kms_init(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = &priv->dev;
|
||||
int ret;
|
||||
|
||||
drm_mode_config_init(priv->dev);
|
||||
priv->mode_config_initialized = true;
|
||||
ret = drmm_mode_config_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->dev->mode_config.min_width = 0;
|
||||
priv->dev->mode_config.min_height = 0;
|
||||
priv->dev->mode_config.max_width = 1920;
|
||||
priv->dev->mode_config.max_height = 1200;
|
||||
dev->mode_config.min_width = 0;
|
||||
dev->mode_config.min_height = 0;
|
||||
dev->mode_config.max_width = 1920;
|
||||
dev->mode_config.max_height = 1200;
|
||||
|
||||
priv->dev->mode_config.fb_base = priv->fb_base;
|
||||
priv->dev->mode_config.preferred_depth = 32;
|
||||
priv->dev->mode_config.prefer_shadow = 1;
|
||||
dev->mode_config.fb_base = priv->fb_base;
|
||||
dev->mode_config.preferred_depth = 32;
|
||||
dev->mode_config.prefer_shadow = 1;
|
||||
|
||||
priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
|
||||
dev->mode_config.funcs = (void *)&hibmc_mode_funcs;
|
||||
|
||||
ret = hibmc_de_init(priv);
|
||||
if (ret) {
|
||||
drm_err(priv->dev, "failed to init de: %d\n", ret);
|
||||
drm_err(dev, "failed to init de: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = hibmc_vdac_init(priv);
|
||||
if (ret) {
|
||||
drm_err(priv->dev, "failed to init vdac: %d\n", ret);
|
||||
drm_err(dev, "failed to init vdac: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hibmc_kms_fini(struct hibmc_drm_private *priv)
|
||||
{
|
||||
if (priv->mode_config_initialized) {
|
||||
drm_mode_config_cleanup(priv->dev);
|
||||
priv->mode_config_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* It can operate in one of three modes: 0, 1 or Sleep.
|
||||
*/
|
||||
@ -202,7 +210,7 @@ static void hibmc_hw_config(struct hibmc_drm_private *priv)
|
||||
|
||||
static int hibmc_hw_map(struct hibmc_drm_private *priv)
|
||||
{
|
||||
struct drm_device *dev = priv->dev;
|
||||
struct drm_device *dev = &priv->dev;
|
||||
struct pci_dev *pdev = dev->pdev;
|
||||
resource_size_t addr, size, ioaddr, iosize;
|
||||
|
||||
@ -242,40 +250,31 @@ static int hibmc_hw_init(struct hibmc_drm_private *priv)
|
||||
|
||||
static int hibmc_unload(struct drm_device *dev)
|
||||
{
|
||||
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
|
||||
|
||||
drm_atomic_helper_shutdown(dev);
|
||||
|
||||
if (dev->irq_enabled)
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
pci_disable_msi(dev->pdev);
|
||||
hibmc_kms_fini(priv);
|
||||
hibmc_mm_fini(priv);
|
||||
dev->dev_private = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hibmc_load(struct drm_device *dev)
|
||||
{
|
||||
struct hibmc_drm_private *priv;
|
||||
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
|
||||
int ret;
|
||||
|
||||
priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv) {
|
||||
drm_err(dev, "no memory to allocate for hibmc_drm_private\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
dev->dev_private = priv;
|
||||
priv->dev = dev;
|
||||
|
||||
ret = hibmc_hw_init(priv);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = hibmc_mm_init(priv);
|
||||
if (ret)
|
||||
ret = drmm_vram_helper_init(dev, pci_resource_start(dev->pdev, 0),
|
||||
priv->fb_size);
|
||||
if (ret) {
|
||||
drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = hibmc_kms_init(priv);
|
||||
if (ret)
|
||||
@ -310,6 +309,7 @@ err:
|
||||
static int hibmc_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct hibmc_drm_private *priv;
|
||||
struct drm_device *dev;
|
||||
int ret;
|
||||
|
||||
@ -318,12 +318,14 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev = drm_dev_alloc(&hibmc_driver, &pdev->dev);
|
||||
if (IS_ERR(dev)) {
|
||||
priv = devm_drm_dev_alloc(&pdev->dev, &hibmc_driver,
|
||||
struct hibmc_drm_private, dev);
|
||||
if (IS_ERR(priv)) {
|
||||
DRM_ERROR("failed to allocate drm_device\n");
|
||||
return PTR_ERR(dev);
|
||||
return PTR_ERR(priv);
|
||||
}
|
||||
|
||||
dev = &priv->dev;
|
||||
dev->pdev = pdev;
|
||||
pci_set_drvdata(pdev, dev);
|
||||
|
||||
@ -366,7 +368,6 @@ static void hibmc_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
drm_dev_unregister(dev);
|
||||
hibmc_unload(dev);
|
||||
drm_dev_put(dev);
|
||||
}
|
||||
|
||||
static const struct pci_device_id hibmc_pci_table[] = {
|
||||
|
@ -37,12 +37,11 @@ struct hibmc_drm_private {
|
||||
resource_size_t fb_size;
|
||||
|
||||
/* drm */
|
||||
struct drm_device *dev;
|
||||
struct drm_device dev;
|
||||
struct drm_plane primary_plane;
|
||||
struct drm_crtc crtc;
|
||||
struct drm_encoder encoder;
|
||||
struct hibmc_connector connector;
|
||||
bool mode_config_initialized;
|
||||
};
|
||||
|
||||
static inline struct hibmc_connector *to_hibmc_connector(struct drm_connector *connector)
|
||||
@ -52,7 +51,7 @@ static inline struct hibmc_connector *to_hibmc_connector(struct drm_connector *c
|
||||
|
||||
static inline struct hibmc_drm_private *to_hibmc_drm_private(struct drm_device *dev)
|
||||
{
|
||||
return dev->dev_private;
|
||||
return container_of(dev, struct hibmc_drm_private, dev);
|
||||
}
|
||||
|
||||
void hibmc_set_power_mode(struct hibmc_drm_private *priv,
|
||||
@ -64,11 +63,6 @@ int hibmc_de_init(struct hibmc_drm_private *priv);
|
||||
int hibmc_vdac_init(struct hibmc_drm_private *priv);
|
||||
|
||||
int hibmc_mm_init(struct hibmc_drm_private *hibmc);
|
||||
void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
|
||||
int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args);
|
||||
int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_connector *connector);
|
||||
|
||||
extern const struct drm_mode_config_funcs hibmc_mode_funcs;
|
||||
|
||||
#endif
|
||||
|
@ -96,7 +96,7 @@ 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_device *dev = &priv->dev;
|
||||
struct hibmc_connector *hibmc_connector = &priv->connector;
|
||||
struct drm_encoder *encoder = &priv->encoder;
|
||||
struct drm_connector *connector = &hibmc_connector->base;
|
||||
|
@ -1,61 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/* Hisilicon Hibmc SoC drm driver
|
||||
*
|
||||
* Based on the bochs drm driver.
|
||||
*
|
||||
* Copyright (c) 2016 Huawei Limited.
|
||||
*
|
||||
* Author:
|
||||
* Rongrong Zou <zourongrong@huawei.com>
|
||||
* Rongrong Zou <zourongrong@gmail.com>
|
||||
* Jianhua Li <lijianhua@huawei.com>
|
||||
*/
|
||||
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "hibmc_drm_drv.h"
|
||||
|
||||
int hibmc_mm_init(struct hibmc_drm_private *hibmc)
|
||||
{
|
||||
struct drm_vram_mm *vmm;
|
||||
int ret;
|
||||
struct drm_device *dev = hibmc->dev;
|
||||
|
||||
vmm = drm_vram_helper_alloc_mm(dev,
|
||||
pci_resource_start(dev->pdev, 0),
|
||||
hibmc->fb_size);
|
||||
if (IS_ERR(vmm)) {
|
||||
ret = PTR_ERR(vmm);
|
||||
drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hibmc_mm_fini(struct hibmc_drm_private *hibmc)
|
||||
{
|
||||
if (!hibmc->dev->vram_mm)
|
||||
return;
|
||||
|
||||
drm_vram_helper_release_mm(hibmc->dev);
|
||||
}
|
||||
|
||||
int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
return drm_gem_vram_fill_create_dumb(file, dev, 0, 128, args);
|
||||
}
|
||||
|
||||
const struct drm_mode_config_funcs hibmc_mode_funcs = {
|
||||
.mode_valid = drm_vram_helper_mode_valid,
|
||||
.atomic_check = drm_atomic_helper_check,
|
||||
.atomic_commit = drm_atomic_helper_commit,
|
||||
.fb_create = drm_gem_fb_create,
|
||||
};
|
@ -17267,7 +17267,6 @@ fail:
|
||||
}
|
||||
|
||||
#define INTEL_CRTC_FUNCS \
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set, \
|
||||
.set_config = drm_atomic_helper_set_config, \
|
||||
.destroy = intel_crtc_destroy, \
|
||||
.page_flip = drm_atomic_helper_page_flip, \
|
||||
|
@ -4,6 +4,7 @@ config DRM_INGENIC
|
||||
depends on DRM
|
||||
depends on CMA
|
||||
depends on OF
|
||||
depends on COMMON_CLK
|
||||
select DRM_BRIDGE
|
||||
select DRM_PANEL_BRIDGE
|
||||
select DRM_KMS_HELPER
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
@ -190,15 +191,15 @@ static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv,
|
||||
{
|
||||
unsigned int vpe, vds, vde, vt, hpe, hds, hde, ht;
|
||||
|
||||
vpe = mode->vsync_end - mode->vsync_start;
|
||||
vds = mode->vtotal - mode->vsync_start;
|
||||
vde = vds + mode->vdisplay;
|
||||
vt = vde + mode->vsync_start - mode->vdisplay;
|
||||
vpe = mode->crtc_vsync_end - mode->crtc_vsync_start;
|
||||
vds = mode->crtc_vtotal - mode->crtc_vsync_start;
|
||||
vde = vds + mode->crtc_vdisplay;
|
||||
vt = vde + mode->crtc_vsync_start - mode->crtc_vdisplay;
|
||||
|
||||
hpe = mode->hsync_end - mode->hsync_start;
|
||||
hds = mode->htotal - mode->hsync_start;
|
||||
hde = hds + mode->hdisplay;
|
||||
ht = hde + mode->hsync_start - mode->hdisplay;
|
||||
hpe = mode->crtc_hsync_end - mode->crtc_hsync_start;
|
||||
hds = mode->crtc_htotal - mode->crtc_hsync_start;
|
||||
hde = hds + mode->crtc_hdisplay;
|
||||
ht = hde + mode->crtc_hsync_start - mode->crtc_hdisplay;
|
||||
|
||||
regmap_write(priv->map, JZ_REG_LCD_VSYNC,
|
||||
0 << JZ_LCD_VSYNC_VPS_OFFSET |
|
||||
@ -333,7 +334,7 @@ static void ingenic_drm_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_pending_vblank_event *event = crtc_state->event;
|
||||
|
||||
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
|
||||
ingenic_drm_crtc_update_timings(priv, &crtc_state->mode);
|
||||
ingenic_drm_crtc_update_timings(priv, &crtc_state->adjusted_mode);
|
||||
priv->update_clk_rate = true;
|
||||
}
|
||||
|
||||
@ -589,7 +590,7 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
|
||||
struct drm_connector *conn = conn_state->connector;
|
||||
struct drm_display_info *info = &conn->display_info;
|
||||
unsigned int cfg;
|
||||
unsigned int cfg, rgbcfg = 0;
|
||||
|
||||
priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS;
|
||||
|
||||
@ -626,6 +627,9 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
|
||||
case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
|
||||
rgbcfg = JZ_LCD_RGBC_EVEN_GBR | JZ_LCD_RGBC_ODD_RGB;
|
||||
fallthrough;
|
||||
case MEDIA_BUS_FMT_RGB888_3X8:
|
||||
cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL;
|
||||
break;
|
||||
@ -636,6 +640,7 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder,
|
||||
}
|
||||
|
||||
regmap_write(priv->map, JZ_REG_LCD_CFG, cfg);
|
||||
regmap_write(priv->map, JZ_REG_LCD_RGBC, rgbcfg);
|
||||
}
|
||||
|
||||
static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
@ -643,6 +648,7 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct drm_display_info *info = &conn_state->connector->display_info;
|
||||
struct drm_display_mode *mode = &crtc_state->adjusted_mode;
|
||||
|
||||
if (info->num_bus_formats != 1)
|
||||
return -EINVAL;
|
||||
@ -651,10 +657,23 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
return 0;
|
||||
|
||||
switch (*info->bus_formats) {
|
||||
case MEDIA_BUS_FMT_RGB888_3X8:
|
||||
case MEDIA_BUS_FMT_RGB888_3X8_DELTA:
|
||||
/*
|
||||
* The LCD controller expects timing values in dot-clock ticks,
|
||||
* which is 3x the timing values in pixels when using a 3x8-bit
|
||||
* display; but it will count the display area size in pixels
|
||||
* either way. Go figure.
|
||||
*/
|
||||
mode->crtc_clock = mode->clock * 3;
|
||||
mode->crtc_hsync_start = mode->hsync_start * 3 - mode->hdisplay * 2;
|
||||
mode->crtc_hsync_end = mode->hsync_end * 3 - mode->hdisplay * 2;
|
||||
mode->crtc_hdisplay = mode->hdisplay;
|
||||
mode->crtc_htotal = mode->htotal * 3 - mode->hdisplay * 2;
|
||||
return 0;
|
||||
case MEDIA_BUS_FMT_RGB565_1X16:
|
||||
case MEDIA_BUS_FMT_RGB666_1X18:
|
||||
case MEDIA_BUS_FMT_RGB888_1X24:
|
||||
case MEDIA_BUS_FMT_RGB888_3X8:
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -755,8 +774,6 @@ static const struct drm_crtc_funcs ingenic_drm_crtc_funcs = {
|
||||
|
||||
.enable_vblank = ingenic_drm_enable_vblank,
|
||||
.disable_vblank = ingenic_drm_disable_vblank,
|
||||
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
};
|
||||
|
||||
static const struct drm_plane_helper_funcs ingenic_drm_plane_helper_funcs = {
|
||||
@ -1167,6 +1184,22 @@ static int ingenic_drm_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused ingenic_drm_suspend(struct device *dev)
|
||||
{
|
||||
struct ingenic_drm *priv = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_suspend(&priv->drm);
|
||||
}
|
||||
|
||||
static int __maybe_unused ingenic_drm_resume(struct device *dev)
|
||||
{
|
||||
struct ingenic_drm *priv = dev_get_drvdata(dev);
|
||||
|
||||
return drm_mode_config_helper_resume(&priv->drm);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, ingenic_drm_suspend, ingenic_drm_resume);
|
||||
|
||||
static const u32 jz4740_formats[] = {
|
||||
DRM_FORMAT_XRGB1555,
|
||||
DRM_FORMAT_RGB565,
|
||||
@ -1246,6 +1279,7 @@ MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
|
||||
static struct platform_driver ingenic_drm_driver = {
|
||||
.driver = {
|
||||
.name = "ingenic-drm",
|
||||
.pm = pm_ptr(&ingenic_drm_pm_ops),
|
||||
.of_match_table = of_match_ptr(ingenic_drm_of_match),
|
||||
},
|
||||
.probe = ingenic_drm_probe,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#define JZ_REG_LCD_SA1 0x54
|
||||
#define JZ_REG_LCD_FID1 0x58
|
||||
#define JZ_REG_LCD_CMD1 0x5C
|
||||
#define JZ_REG_LCD_RGBC 0x90
|
||||
#define JZ_REG_LCD_OSDC 0x100
|
||||
#define JZ_REG_LCD_OSDCTRL 0x104
|
||||
#define JZ_REG_LCD_OSDS 0x108
|
||||
@ -138,6 +139,19 @@
|
||||
#define JZ_LCD_STATE_SOF_IRQ BIT(4)
|
||||
#define JZ_LCD_STATE_DISABLED BIT(0)
|
||||
|
||||
#define JZ_LCD_RGBC_ODD_RGB (0x0 << 4)
|
||||
#define JZ_LCD_RGBC_ODD_RBG (0x1 << 4)
|
||||
#define JZ_LCD_RGBC_ODD_GRB (0x2 << 4)
|
||||
#define JZ_LCD_RGBC_ODD_GBR (0x3 << 4)
|
||||
#define JZ_LCD_RGBC_ODD_BRG (0x4 << 4)
|
||||
#define JZ_LCD_RGBC_ODD_BGR (0x5 << 4)
|
||||
#define JZ_LCD_RGBC_EVEN_RGB (0x0 << 0)
|
||||
#define JZ_LCD_RGBC_EVEN_RBG (0x1 << 0)
|
||||
#define JZ_LCD_RGBC_EVEN_GRB (0x2 << 0)
|
||||
#define JZ_LCD_RGBC_EVEN_GBR (0x3 << 0)
|
||||
#define JZ_LCD_RGBC_EVEN_BRG (0x4 << 0)
|
||||
#define JZ_LCD_RGBC_EVEN_BGR (0x5 << 0)
|
||||
|
||||
#define JZ_LCD_OSDC_OSDEN BIT(0)
|
||||
#define JZ_LCD_OSDC_F0EN BIT(3)
|
||||
#define JZ_LCD_OSDC_F1EN BIT(4)
|
||||
|
@ -556,7 +556,7 @@ MODULE_DEVICE_TABLE(of, kmb_of_match);
|
||||
static int __maybe_unused kmb_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(dev);
|
||||
struct kmb_drm_private *kmb = drm ? to_kmb(drm) : NULL;
|
||||
struct kmb_drm_private *kmb = to_kmb(drm);
|
||||
|
||||
drm_kms_helper_poll_disable(drm);
|
||||
|
||||
|
@ -114,6 +114,9 @@ static void kmb_plane_atomic_disable(struct drm_plane *plane,
|
||||
|
||||
kmb = to_kmb(plane->dev);
|
||||
|
||||
if (WARN_ON(plane_id >= KMB_MAX_PLANES))
|
||||
return;
|
||||
|
||||
switch (plane_id) {
|
||||
case LAYER_0:
|
||||
kmb->plane_status[plane_id].ctrl = LCD_CTRL_VL1_ENABLE;
|
||||
|
@ -619,7 +619,6 @@ static const struct drm_crtc_funcs mtk_crtc_funcs = {
|
||||
.reset = mtk_drm_crtc_reset,
|
||||
.atomic_duplicate_state = mtk_drm_crtc_duplicate_state,
|
||||
.atomic_destroy_state = mtk_drm_crtc_destroy_state,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.enable_vblank = mtk_drm_crtc_enable_vblank,
|
||||
.disable_vblank = mtk_drm_crtc_disable_vblank,
|
||||
};
|
||||
|
@ -260,7 +260,7 @@ int mtk_drm_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
drm_prime_sg_to_page_addr_arrays(sgt, mtk_gem->pages, NULL, npages);
|
||||
drm_prime_sg_to_page_array(sgt, mtk_gem->pages, npages);
|
||||
|
||||
mtk_gem->kvaddr = vmap(mtk_gem->pages, npages, VM_MAP,
|
||||
pgprot_writecombine(PAGE_KERNEL));
|
||||
|
@ -1211,7 +1211,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);
|
||||
ret = drm_prime_sg_to_page_array(sgt, msm_obj->pages, npages);
|
||||
if (ret) {
|
||||
msm_gem_unlock(obj);
|
||||
goto fail;
|
||||
|
@ -503,7 +503,6 @@ nv50_head_destroy(struct drm_crtc *crtc)
|
||||
static const struct drm_crtc_funcs
|
||||
nv50_head_func = {
|
||||
.reset = nv50_head_reset,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = nv50_head_destroy,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
@ -518,7 +517,6 @@ nv50_head_func = {
|
||||
static const struct drm_crtc_funcs
|
||||
nvd9_head_func = {
|
||||
.reset = nv50_head_reset,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.destroy = nv50_head_destroy,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
|
@ -473,10 +473,10 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig)
|
||||
|
||||
switch (bo->mem.mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
drm->gem.vram_available -= bo->mem.size;
|
||||
drm->gem.vram_available -= bo->base.size;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
drm->gem.gart_available -= bo->mem.size;
|
||||
drm->gem.gart_available -= bo->base.size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -504,10 +504,10 @@ nouveau_bo_unpin(struct nouveau_bo *nvbo)
|
||||
if (!nvbo->bo.pin_count) {
|
||||
switch (bo->mem.mem_type) {
|
||||
case TTM_PL_VRAM:
|
||||
drm->gem.vram_available += bo->mem.size;
|
||||
drm->gem.vram_available += bo->base.size;
|
||||
break;
|
||||
case TTM_PL_TT:
|
||||
drm->gem.gart_available += bo->mem.size;
|
||||
drm->gem.gart_available += bo->base.size;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -774,7 +774,10 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
|
||||
if (drm_drv_uses_atomic_modeset(drm->dev))
|
||||
mutex_lock(&cli->mutex);
|
||||
else
|
||||
mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
|
||||
ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, ctx->interruptible);
|
||||
if (ret == 0) {
|
||||
ret = drm->ttm.move(chan, bo, &bo->mem, new_reg);
|
||||
@ -910,7 +913,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_resource *new_reg,
|
||||
return 0;
|
||||
|
||||
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
|
||||
*new_tile = nv10_bo_set_tiling(dev, offset, new_reg->size,
|
||||
*new_tile = nv10_bo_set_tiling(dev, offset, bo->base.size,
|
||||
nvbo->mode, nvbo->zeta);
|
||||
}
|
||||
|
||||
@ -1232,9 +1235,8 @@ nouveau_ttm_tt_populate(struct ttm_bo_device *bdev,
|
||||
return 0;
|
||||
|
||||
if (slave && ttm->sg) {
|
||||
/* make userspace faulting work */
|
||||
drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
|
||||
ttm_dma->dma_address, ttm->num_pages);
|
||||
drm_prime_sg_to_dma_addr_array(ttm->sg, ttm_dma->dma_address,
|
||||
ttm->num_pages);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -286,11 +286,11 @@ nouveau_check_bl_size(struct nouveau_drm *drm, struct nouveau_bo *nvbo,
|
||||
|
||||
bl_size = bw * bh * (1 << tile_mode) * gob_size;
|
||||
|
||||
DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%lu\n",
|
||||
DRM_DEBUG_KMS("offset=%u stride=%u h=%u tile_mode=0x%02x bw=%u bh=%u gob_size=%u bl_size=%llu size=%zu\n",
|
||||
offset, stride, h, tile_mode, bw, bh, gob_size, bl_size,
|
||||
nvbo->bo.mem.size);
|
||||
nvbo->bo.base.size);
|
||||
|
||||
if (bl_size + offset > nvbo->bo.mem.size)
|
||||
if (bl_size + offset > nvbo->bo.base.size)
|
||||
return -ERANGE;
|
||||
|
||||
return 0;
|
||||
@ -363,7 +363,7 @@ nouveau_framebuffer_new(struct drm_device *dev,
|
||||
} else {
|
||||
uint32_t size = mode_cmd->pitches[i] * height;
|
||||
|
||||
if (size + mode_cmd->offsets[i] > nvbo->bo.mem.size)
|
||||
if (size + mode_cmd->offsets[i] > nvbo->bo.base.size)
|
||||
return -ERANGE;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@
|
||||
#include <drm/ttm/ttm_bo_driver.h>
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
#include <drm/ttm/ttm_memory.h>
|
||||
#include <drm/ttm/ttm_module.h>
|
||||
|
||||
#include <drm/drm_audio_component.h>
|
||||
|
||||
|
@ -30,9 +30,9 @@
|
||||
struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *obj)
|
||||
{
|
||||
struct nouveau_bo *nvbo = nouveau_gem_object(obj);
|
||||
int npages = nvbo->bo.num_pages;
|
||||
|
||||
return drm_prime_pages_to_sg(obj->dev, nvbo->bo.ttm->pages, npages);
|
||||
return drm_prime_pages_to_sg(obj->dev, nvbo->bo.ttm->pages,
|
||||
nvbo->bo.ttm->num_pages);
|
||||
}
|
||||
|
||||
struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev,
|
||||
|
@ -84,7 +84,7 @@ nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags)
|
||||
if (!nvbe)
|
||||
return NULL;
|
||||
|
||||
if (ttm_dma_tt_init(&nvbe->ttm, bo, page_flags, caching)) {
|
||||
if (ttm_sg_tt_init(&nvbe->ttm, bo, page_flags, caching)) {
|
||||
kfree(nvbe);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ nv17_fence_context_new(struct nouveau_channel *chan)
|
||||
struct nv10_fence_chan *fctx;
|
||||
struct ttm_resource *reg = &priv->bo->bo.mem;
|
||||
u32 start = reg->start * PAGE_SIZE;
|
||||
u32 limit = start + reg->size - 1;
|
||||
u32 limit = start + priv->bo->bo.base.size - 1;
|
||||
int ret = 0;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
|
@ -39,7 +39,7 @@ nv50_fence_context_new(struct nouveau_channel *chan)
|
||||
struct nv10_fence_chan *fctx;
|
||||
struct ttm_resource *reg = &priv->bo->bo.mem;
|
||||
u32 start = reg->start * PAGE_SIZE;
|
||||
u32 limit = start + reg->size - 1;
|
||||
u32 limit = start + priv->bo->bo.base.size - 1;
|
||||
int ret;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
|
@ -5,13 +5,129 @@ config DRM_OMAP
|
||||
depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM
|
||||
select OMAP2_DSS
|
||||
select DRM_KMS_HELPER
|
||||
select VIDEOMODE_HELPERS
|
||||
select HDMI
|
||||
default n
|
||||
help
|
||||
DRM display driver for OMAP2/3/4 based boards.
|
||||
|
||||
if DRM_OMAP
|
||||
|
||||
source "drivers/gpu/drm/omapdrm/dss/Kconfig"
|
||||
source "drivers/gpu/drm/omapdrm/displays/Kconfig"
|
||||
config OMAP2_DSS_DEBUG
|
||||
bool "Debug support"
|
||||
default n
|
||||
help
|
||||
This enables printing of debug messages. Alternatively, debug messages
|
||||
can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
|
||||
appropriate flags in <debugfs>/dynamic_debug/control.
|
||||
|
||||
config OMAP2_DSS_DEBUGFS
|
||||
bool "Debugfs filesystem support"
|
||||
depends on DEBUG_FS
|
||||
default n
|
||||
help
|
||||
This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
|
||||
querying about clock configuration and register configuration of dss,
|
||||
dispc, dsi, hdmi and rfbi.
|
||||
|
||||
config OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
bool "Collect DSS IRQ statistics"
|
||||
depends on OMAP2_DSS_DEBUGFS
|
||||
default n
|
||||
help
|
||||
Collect DSS IRQ statistics, printable via debugfs.
|
||||
|
||||
The statistics can be found from
|
||||
<debugfs>/omapdss/dispc_irq for DISPC interrupts, and
|
||||
<debugfs>/omapdss/dsi_irq for DSI interrupts.
|
||||
|
||||
config OMAP2_DSS_DPI
|
||||
bool "DPI support"
|
||||
default y
|
||||
help
|
||||
DPI Interface. This is the Parallel Display Interface.
|
||||
|
||||
config OMAP2_DSS_VENC
|
||||
bool "VENC support"
|
||||
default y
|
||||
help
|
||||
OMAP Video Encoder support for S-Video and composite TV-out.
|
||||
|
||||
config OMAP2_DSS_HDMI_COMMON
|
||||
bool
|
||||
|
||||
config OMAP4_DSS_HDMI
|
||||
bool "HDMI support for OMAP4"
|
||||
default y
|
||||
select OMAP2_DSS_HDMI_COMMON
|
||||
help
|
||||
HDMI support for OMAP4 based SoCs.
|
||||
|
||||
config OMAP4_DSS_HDMI_CEC
|
||||
bool "Enable HDMI CEC support for OMAP4"
|
||||
depends on OMAP4_DSS_HDMI
|
||||
select CEC_CORE
|
||||
default y
|
||||
help
|
||||
When selected the HDMI transmitter will support the CEC feature.
|
||||
|
||||
config OMAP5_DSS_HDMI
|
||||
bool "HDMI support for OMAP5"
|
||||
default n
|
||||
select OMAP2_DSS_HDMI_COMMON
|
||||
help
|
||||
HDMI Interface for OMAP5 and similar cores. This adds the High
|
||||
Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
|
||||
specification.
|
||||
|
||||
config OMAP2_DSS_SDI
|
||||
bool "SDI support"
|
||||
default n
|
||||
help
|
||||
SDI (Serial Display Interface) support.
|
||||
|
||||
SDI is a high speed one-way display serial bus between the host
|
||||
processor and a display.
|
||||
|
||||
config OMAP2_DSS_DSI
|
||||
bool "DSI support"
|
||||
default n
|
||||
select DRM_MIPI_DSI
|
||||
help
|
||||
MIPI DSI (Display Serial Interface) support.
|
||||
|
||||
DSI is a high speed half-duplex serial interface between the host
|
||||
processor and a peripheral, such as a display or a framebuffer chip.
|
||||
|
||||
See http://www.mipi.org/ for DSI specifications.
|
||||
|
||||
config OMAP2_DSS_MIN_FCK_PER_PCK
|
||||
int "Minimum FCK/PCK ratio (for scaling)"
|
||||
range 0 32
|
||||
default 0
|
||||
help
|
||||
This can be used to adjust the minimum FCK/PCK ratio.
|
||||
|
||||
With this you can make sure that DISPC FCK is at least
|
||||
n x PCK. Video plane scaling requires higher FCK than
|
||||
normally.
|
||||
|
||||
If this is set to 0, there's no extra constraint on the
|
||||
DISPC FCK. However, the FCK will at minimum be
|
||||
2xPCK (if active matrix) or 3xPCK (if passive matrix).
|
||||
|
||||
Max FCK is 173MHz, so this doesn't work if your PCK
|
||||
is very high.
|
||||
|
||||
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
|
||||
bool "Sleep 20ms after VENC reset"
|
||||
default y
|
||||
help
|
||||
There is a 20ms sleep after VENC reset which seemed to fix the
|
||||
reset. The reason for the bug is unclear, and it's also unclear
|
||||
on what platforms this happens.
|
||||
|
||||
This option enables the sleep, and is enabled by default. You can
|
||||
disable the sleep if it doesn't cause problems on your platform.
|
||||
|
||||
endif
|
||||
|
@ -4,16 +4,12 @@
|
||||
# Direct Rendering Infrastructure (DRI)
|
||||
#
|
||||
|
||||
obj-y += dss/
|
||||
obj-y += displays/
|
||||
|
||||
omapdrm-y := omap_drv.o \
|
||||
omap_irq.o \
|
||||
omap_debugfs.o \
|
||||
omap_crtc.o \
|
||||
omap_plane.o \
|
||||
omap_encoder.o \
|
||||
omap_connector.o \
|
||||
omap_fb.o \
|
||||
omap_gem.o \
|
||||
omap_gem_dmabuf.o \
|
||||
@ -22,4 +18,17 @@ omapdrm-y := omap_drv.o \
|
||||
|
||||
omapdrm-$(CONFIG_DRM_FBDEV_EMULATION) += omap_fbdev.o
|
||||
|
||||
obj-$(CONFIG_DRM_OMAP) += omapdrm.o
|
||||
omapdrm-y += dss/base.o dss/output.o dss/dss.o dss/dispc.o \
|
||||
dss/dispc_coefs.o dss/pll.o dss/video-pll.o
|
||||
omapdrm-$(CONFIG_OMAP2_DSS_DPI) += dss/dpi.o
|
||||
omapdrm-$(CONFIG_OMAP2_DSS_VENC) += dss/venc.o
|
||||
omapdrm-$(CONFIG_OMAP2_DSS_SDI) += dss/sdi.o
|
||||
omapdrm-$(CONFIG_OMAP2_DSS_DSI) += dss/dsi.o
|
||||
omapdrm-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += dss/hdmi_common.o dss/hdmi_wp.o \
|
||||
dss/hdmi_pll.o dss/hdmi_phy.o
|
||||
omapdrm-$(CONFIG_OMAP4_DSS_HDMI) += dss/hdmi4.o dss/hdmi4_core.o
|
||||
omapdrm-$(CONFIG_OMAP4_DSS_HDMI_CEC) += dss/hdmi4_cec.o
|
||||
omapdrm-$(CONFIG_OMAP5_DSS_HDMI) += dss/hdmi5.o dss/hdmi5_core.o
|
||||
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
|
||||
|
||||
obj-$(CONFIG_DRM_OMAP) += omapdrm.o
|
||||
|
@ -1,10 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "OMAPDRM External Display Device Drivers"
|
||||
|
||||
config DRM_OMAP_PANEL_DSI_CM
|
||||
tristate "Generic DSI Command Mode Panel"
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
Driver for generic DSI command mode panels.
|
||||
|
||||
endmenu
|
@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_DRM_OMAP_PANEL_DSI_CM) += panel-dsi-cm.o
|
File diff suppressed because it is too large
Load Diff
@ -1,135 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config OMAP2_DSS_INIT
|
||||
bool
|
||||
|
||||
config OMAP_DSS_BASE
|
||||
tristate
|
||||
|
||||
menuconfig OMAP2_DSS
|
||||
tristate "OMAP2+ Display Subsystem support"
|
||||
select OMAP_DSS_BASE
|
||||
select VIDEOMODE_HELPERS
|
||||
select OMAP2_DSS_INIT
|
||||
select HDMI
|
||||
help
|
||||
OMAP2+ Display Subsystem support.
|
||||
|
||||
if OMAP2_DSS
|
||||
|
||||
config OMAP2_DSS_DEBUG
|
||||
bool "Debug support"
|
||||
default n
|
||||
help
|
||||
This enables printing of debug messages. Alternatively, debug messages
|
||||
can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
|
||||
appropriate flags in <debugfs>/dynamic_debug/control.
|
||||
|
||||
config OMAP2_DSS_DEBUGFS
|
||||
bool "Debugfs filesystem support"
|
||||
depends on DEBUG_FS
|
||||
default n
|
||||
help
|
||||
This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
|
||||
querying about clock configuration and register configuration of dss,
|
||||
dispc, dsi, hdmi and rfbi.
|
||||
|
||||
config OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
bool "Collect DSS IRQ statistics"
|
||||
depends on OMAP2_DSS_DEBUGFS
|
||||
default n
|
||||
help
|
||||
Collect DSS IRQ statistics, printable via debugfs.
|
||||
|
||||
The statistics can be found from
|
||||
<debugfs>/omapdss/dispc_irq for DISPC interrupts, and
|
||||
<debugfs>/omapdss/dsi_irq for DSI interrupts.
|
||||
|
||||
config OMAP2_DSS_DPI
|
||||
bool "DPI support"
|
||||
default y
|
||||
help
|
||||
DPI Interface. This is the Parallel Display Interface.
|
||||
|
||||
config OMAP2_DSS_VENC
|
||||
bool "VENC support"
|
||||
default y
|
||||
help
|
||||
OMAP Video Encoder support for S-Video and composite TV-out.
|
||||
|
||||
config OMAP2_DSS_HDMI_COMMON
|
||||
bool
|
||||
|
||||
config OMAP4_DSS_HDMI
|
||||
bool "HDMI support for OMAP4"
|
||||
default y
|
||||
select OMAP2_DSS_HDMI_COMMON
|
||||
help
|
||||
HDMI support for OMAP4 based SoCs.
|
||||
|
||||
config OMAP4_DSS_HDMI_CEC
|
||||
bool "Enable HDMI CEC support for OMAP4"
|
||||
depends on OMAP4_DSS_HDMI
|
||||
select CEC_CORE
|
||||
default y
|
||||
help
|
||||
When selected the HDMI transmitter will support the CEC feature.
|
||||
|
||||
config OMAP5_DSS_HDMI
|
||||
bool "HDMI support for OMAP5"
|
||||
default n
|
||||
select OMAP2_DSS_HDMI_COMMON
|
||||
help
|
||||
HDMI Interface for OMAP5 and similar cores. This adds the High
|
||||
Definition Multimedia Interface. See https://www.hdmi.org/ for HDMI
|
||||
specification.
|
||||
|
||||
config OMAP2_DSS_SDI
|
||||
bool "SDI support"
|
||||
default n
|
||||
help
|
||||
SDI (Serial Display Interface) support.
|
||||
|
||||
SDI is a high speed one-way display serial bus between the host
|
||||
processor and a display.
|
||||
|
||||
config OMAP2_DSS_DSI
|
||||
bool "DSI support"
|
||||
default n
|
||||
help
|
||||
MIPI DSI (Display Serial Interface) support.
|
||||
|
||||
DSI is a high speed half-duplex serial interface between the host
|
||||
processor and a peripheral, such as a display or a framebuffer chip.
|
||||
|
||||
See https://www.mipi.org/ for DSI specifications.
|
||||
|
||||
config OMAP2_DSS_MIN_FCK_PER_PCK
|
||||
int "Minimum FCK/PCK ratio (for scaling)"
|
||||
range 0 32
|
||||
default 0
|
||||
help
|
||||
This can be used to adjust the minimum FCK/PCK ratio.
|
||||
|
||||
With this you can make sure that DISPC FCK is at least
|
||||
n x PCK. Video plane scaling requires higher FCK than
|
||||
normally.
|
||||
|
||||
If this is set to 0, there's no extra constraint on the
|
||||
DISPC FCK. However, the FCK will at minimum be
|
||||
2xPCK (if active matrix) or 3xPCK (if passive matrix).
|
||||
|
||||
Max FCK is 173MHz, so this doesn't work if your PCK
|
||||
is very high.
|
||||
|
||||
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
|
||||
bool "Sleep 20ms after VENC reset"
|
||||
default y
|
||||
help
|
||||
There is a 20ms sleep after VENC reset which seemed to fix the
|
||||
reset. The reason for the bug is unclear, and it's also unclear
|
||||
on what platforms this happens.
|
||||
|
||||
This option enables the sleep, and is enabled by default. You can
|
||||
disable the sleep if it doesn't cause problems on your platform.
|
||||
|
||||
endif
|
@ -1,20 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o
|
||||
|
||||
obj-$(CONFIG_OMAP_DSS_BASE) += omapdss-base.o
|
||||
omapdss-base-y := base.o display.o output.o
|
||||
|
||||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
# Core DSS files
|
||||
omapdss-y := dss.o dispc.o dispc_coefs.o \
|
||||
pll.o video-pll.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \
|
||||
hdmi_phy.o
|
||||
omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o
|
||||
omapdss-$(CONFIG_OMAP4_DSS_HDMI_CEC) += hdmi4_cec.o
|
||||
omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o
|
||||
ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG
|
@ -16,32 +16,10 @@
|
||||
#include "dss.h"
|
||||
#include "omapdss.h"
|
||||
|
||||
static struct dss_device *dss_device;
|
||||
|
||||
struct dss_device *omapdss_get_dss(void)
|
||||
{
|
||||
return dss_device;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_get_dss);
|
||||
|
||||
void omapdss_set_dss(struct dss_device *dss)
|
||||
{
|
||||
dss_device = dss;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_set_dss);
|
||||
|
||||
struct dispc_device *dispc_get_dispc(struct dss_device *dss)
|
||||
{
|
||||
return dss->dispc;
|
||||
}
|
||||
EXPORT_SYMBOL(dispc_get_dispc);
|
||||
|
||||
const struct dispc_ops *dispc_get_ops(struct dss_device *dss)
|
||||
{
|
||||
return dss->dispc_ops;
|
||||
}
|
||||
EXPORT_SYMBOL(dispc_get_ops);
|
||||
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* OMAP DSS Devices Handling
|
||||
@ -56,7 +34,6 @@ void omapdss_device_register(struct omap_dss_device *dssdev)
|
||||
list_add_tail(&dssdev->list, &omapdss_devices_list);
|
||||
mutex_unlock(&omapdss_devices_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_register);
|
||||
|
||||
void omapdss_device_unregister(struct omap_dss_device *dssdev)
|
||||
{
|
||||
@ -64,7 +41,6 @@ void omapdss_device_unregister(struct omap_dss_device *dssdev)
|
||||
list_del(&dssdev->list);
|
||||
mutex_unlock(&omapdss_devices_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_unregister);
|
||||
|
||||
static bool omapdss_device_is_registered(struct device_node *node)
|
||||
{
|
||||
@ -86,24 +62,16 @@ static bool omapdss_device_is_registered(struct device_node *node)
|
||||
|
||||
struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (!try_module_get(dssdev->owner))
|
||||
if (get_device(dssdev->dev) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (get_device(dssdev->dev) == NULL) {
|
||||
module_put(dssdev->owner);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dssdev;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_device_get);
|
||||
|
||||
void omapdss_device_put(struct omap_dss_device *dssdev)
|
||||
{
|
||||
put_device(dssdev->dev);
|
||||
module_put(dssdev->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_device_put);
|
||||
|
||||
struct omap_dss_device *omapdss_find_device_by_node(struct device_node *node)
|
||||
{
|
||||
@ -149,7 +117,7 @@ struct omap_dss_device *omapdss_device_next_output(struct omap_dss_device *from)
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (dssdev->id && (dssdev->next || dssdev->bridge))
|
||||
if (dssdev->id && dssdev->bridge)
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -164,7 +132,6 @@ done:
|
||||
mutex_unlock(&omapdss_devices_lock);
|
||||
return dssdev;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_device_next_output);
|
||||
|
||||
static bool omapdss_device_is_connected(struct omap_dss_device *dssdev)
|
||||
{
|
||||
@ -175,8 +142,6 @@ int omapdss_device_connect(struct dss_device *dss,
|
||||
struct omap_dss_device *src,
|
||||
struct omap_dss_device *dst)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&dss->pdev->dev, "connect(%s, %s)\n",
|
||||
src ? dev_name(src->dev) : "NULL",
|
||||
dst ? dev_name(dst->dev) : "NULL");
|
||||
@ -195,17 +160,8 @@ int omapdss_device_connect(struct dss_device *dss,
|
||||
|
||||
dst->dss = dss;
|
||||
|
||||
if (dst->ops && dst->ops->connect) {
|
||||
ret = dst->ops->connect(src, dst);
|
||||
if (ret < 0) {
|
||||
dst->dss = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_connect);
|
||||
|
||||
void omapdss_device_disconnect(struct omap_dss_device *src,
|
||||
struct omap_dss_device *dst)
|
||||
@ -222,43 +178,12 @@ void omapdss_device_disconnect(struct omap_dss_device *src,
|
||||
}
|
||||
|
||||
if (!dst->id && !omapdss_device_is_connected(dst)) {
|
||||
WARN_ON(!dst->display);
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
|
||||
WARN_ON(dst->state != OMAP_DSS_DISPLAY_DISABLED);
|
||||
|
||||
if (dst->ops && dst->ops->disconnect)
|
||||
dst->ops->disconnect(src, dst);
|
||||
dst->dss = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_disconnect);
|
||||
|
||||
void omapdss_device_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
if (dssdev->ops && dssdev->ops->enable)
|
||||
dssdev->ops->enable(dssdev);
|
||||
|
||||
omapdss_device_enable(dssdev->next);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_enable);
|
||||
|
||||
void omapdss_device_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (!dssdev)
|
||||
return;
|
||||
|
||||
omapdss_device_disable(dssdev->next);
|
||||
|
||||
if (dssdev->ops && dssdev->ops->disable)
|
||||
dssdev->ops->disable(dssdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_device_disable);
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Components Handling
|
||||
@ -344,7 +269,6 @@ void omapdss_gather_components(struct device *dev)
|
||||
for_each_available_child_of_node(dev->of_node, child)
|
||||
omapdss_walk_device(dev, child, true);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_gather_components);
|
||||
|
||||
static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp)
|
||||
{
|
||||
@ -369,8 +293,3 @@ bool omapdss_stack_is_ready(void)
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_stack_is_ready);
|
||||
|
||||
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
|
||||
MODULE_DESCRIPTION("OMAP Display Subsystem Base");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -351,8 +351,6 @@ static unsigned long dispc_plane_pclk_rate(struct dispc_device *dispc,
|
||||
static unsigned long dispc_plane_lclk_rate(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane);
|
||||
|
||||
static void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask);
|
||||
|
||||
static inline void dispc_write_reg(struct dispc_device *dispc, u16 idx, u32 val)
|
||||
{
|
||||
__raw_writel(val, dispc->base + idx);
|
||||
@ -379,12 +377,12 @@ static void mgr_fld_write(struct dispc_device *dispc, enum omap_channel channel,
|
||||
REG_FLD_MOD(dispc, rfld->reg, val, rfld->high, rfld->low);
|
||||
}
|
||||
|
||||
static int dispc_get_num_ovls(struct dispc_device *dispc)
|
||||
int dispc_get_num_ovls(struct dispc_device *dispc)
|
||||
{
|
||||
return dispc->feat->num_ovls;
|
||||
}
|
||||
|
||||
static int dispc_get_num_mgrs(struct dispc_device *dispc)
|
||||
int dispc_get_num_mgrs(struct dispc_device *dispc)
|
||||
{
|
||||
return dispc->feat->num_mgrs;
|
||||
}
|
||||
@ -670,13 +668,13 @@ void dispc_runtime_put(struct dispc_device *dispc)
|
||||
WARN_ON(r < 0 && r != -ENOSYS);
|
||||
}
|
||||
|
||||
static u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc,
|
||||
u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
return mgr_desc[channel].vsync_irq;
|
||||
}
|
||||
|
||||
static u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
|
||||
u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc->feat->no_framedone_tv)
|
||||
@ -685,18 +683,18 @@ static u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
|
||||
return mgr_desc[channel].framedone_irq;
|
||||
}
|
||||
|
||||
static u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc,
|
||||
u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
return mgr_desc[channel].sync_lost_irq;
|
||||
}
|
||||
|
||||
static u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc)
|
||||
u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc)
|
||||
{
|
||||
return DISPC_IRQ_FRAMEDONEWB;
|
||||
}
|
||||
|
||||
static void dispc_mgr_enable(struct dispc_device *dispc,
|
||||
void dispc_mgr_enable(struct dispc_device *dispc,
|
||||
enum omap_channel channel, bool enable)
|
||||
{
|
||||
mgr_fld_write(dispc, channel, DISPC_MGR_FLD_ENABLE, enable);
|
||||
@ -710,13 +708,13 @@ static bool dispc_mgr_is_enabled(struct dispc_device *dispc,
|
||||
return !!mgr_fld_read(dispc, channel, DISPC_MGR_FLD_ENABLE);
|
||||
}
|
||||
|
||||
static bool dispc_mgr_go_busy(struct dispc_device *dispc,
|
||||
bool dispc_mgr_go_busy(struct dispc_device *dispc,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
return mgr_fld_read(dispc, channel, DISPC_MGR_FLD_GO) == 1;
|
||||
}
|
||||
|
||||
static void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
|
||||
void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
|
||||
{
|
||||
WARN_ON(!dispc_mgr_is_enabled(dispc, channel));
|
||||
WARN_ON(dispc_mgr_go_busy(dispc, channel));
|
||||
@ -726,12 +724,12 @@ static void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel)
|
||||
mgr_fld_write(dispc, channel, DISPC_MGR_FLD_GO, 1);
|
||||
}
|
||||
|
||||
static bool dispc_wb_go_busy(struct dispc_device *dispc)
|
||||
bool dispc_wb_go_busy(struct dispc_device *dispc)
|
||||
{
|
||||
return REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1;
|
||||
}
|
||||
|
||||
static void dispc_wb_go(struct dispc_device *dispc)
|
||||
void dispc_wb_go(struct dispc_device *dispc)
|
||||
{
|
||||
enum omap_plane_id plane = OMAP_DSS_WB;
|
||||
bool enable, go;
|
||||
@ -877,50 +875,62 @@ static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc,
|
||||
#undef CVAL
|
||||
}
|
||||
|
||||
static void dispc_wb_write_color_conv_coef(struct dispc_device *dispc,
|
||||
const struct csc_coef_rgb2yuv *ct)
|
||||
/* YUV -> RGB, ITU-R BT.601, full range */
|
||||
static const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt601_full = {
|
||||
256, 0, 358, /* ry, rcb, rcr |1.000 0.000 1.402|*/
|
||||
256, -88, -182, /* gy, gcb, gcr |1.000 -0.344 -0.714|*/
|
||||
256, 452, 0, /* by, bcb, bcr |1.000 1.772 0.000|*/
|
||||
true, /* full range */
|
||||
};
|
||||
|
||||
/* YUV -> RGB, ITU-R BT.601, limited range */
|
||||
static const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt601_lim = {
|
||||
298, 0, 409, /* ry, rcb, rcr |1.164 0.000 1.596|*/
|
||||
298, -100, -208, /* gy, gcb, gcr |1.164 -0.392 -0.813|*/
|
||||
298, 516, 0, /* by, bcb, bcr |1.164 2.017 0.000|*/
|
||||
false, /* limited range */
|
||||
};
|
||||
|
||||
/* YUV -> RGB, ITU-R BT.709, full range */
|
||||
static const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt709_full = {
|
||||
256, 0, 402, /* ry, rcb, rcr |1.000 0.000 1.570|*/
|
||||
256, -48, -120, /* gy, gcb, gcr |1.000 -0.187 -0.467|*/
|
||||
256, 475, 0, /* by, bcb, bcr |1.000 1.856 0.000|*/
|
||||
true, /* full range */
|
||||
};
|
||||
|
||||
/* YUV -> RGB, ITU-R BT.709, limited range */
|
||||
static const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt709_lim = {
|
||||
298, 0, 459, /* ry, rcb, rcr |1.164 0.000 1.793|*/
|
||||
298, -55, -136, /* gy, gcb, gcr |1.164 -0.213 -0.533|*/
|
||||
298, 541, 0, /* by, bcb, bcr |1.164 2.112 0.000|*/
|
||||
false, /* limited range */
|
||||
};
|
||||
|
||||
static void dispc_ovl_set_csc(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane,
|
||||
enum drm_color_encoding color_encoding,
|
||||
enum drm_color_range color_range)
|
||||
{
|
||||
const enum omap_plane_id plane = OMAP_DSS_WB;
|
||||
const struct csc_coef_yuv2rgb *csc;
|
||||
|
||||
#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
|
||||
switch (color_encoding) {
|
||||
default:
|
||||
case DRM_COLOR_YCBCR_BT601:
|
||||
if (color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
csc = &coefs_yuv2rgb_bt601_full;
|
||||
else
|
||||
csc = &coefs_yuv2rgb_bt601_lim;
|
||||
break;
|
||||
case DRM_COLOR_YCBCR_BT709:
|
||||
if (color_range == DRM_COLOR_YCBCR_FULL_RANGE)
|
||||
csc = &coefs_yuv2rgb_bt709_full;
|
||||
else
|
||||
csc = &coefs_yuv2rgb_bt709_lim;
|
||||
break;
|
||||
}
|
||||
|
||||
dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->yg, ct->yr));
|
||||
dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->crr, ct->yb));
|
||||
dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->crb, ct->crg));
|
||||
dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->cbg, ct->cbr));
|
||||
dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->cbb));
|
||||
|
||||
REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), ct->full_range, 11, 11);
|
||||
|
||||
#undef CVAL
|
||||
}
|
||||
|
||||
static void dispc_setup_color_conv_coef(struct dispc_device *dispc)
|
||||
{
|
||||
int i;
|
||||
int num_ovl = dispc_get_num_ovls(dispc);
|
||||
|
||||
/* YUV -> RGB, ITU-R BT.601, limited range */
|
||||
const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt601_lim = {
|
||||
298, 0, 409, /* ry, rcb, rcr */
|
||||
298, -100, -208, /* gy, gcb, gcr */
|
||||
298, 516, 0, /* by, bcb, bcr */
|
||||
false, /* limited range */
|
||||
};
|
||||
|
||||
/* RGB -> YUV, ITU-R BT.601, limited range */
|
||||
const struct csc_coef_rgb2yuv coefs_rgb2yuv_bt601_lim = {
|
||||
66, 129, 25, /* yr, yg, yb */
|
||||
-38, -74, 112, /* cbr, cbg, cbb */
|
||||
112, -94, -18, /* crr, crg, crb */
|
||||
false, /* limited range */
|
||||
};
|
||||
|
||||
for (i = 1; i < num_ovl; i++)
|
||||
dispc_ovl_write_color_conv_coef(dispc, i, &coefs_yuv2rgb_bt601_lim);
|
||||
|
||||
if (dispc->feat->has_writeback)
|
||||
dispc_wb_write_color_conv_coef(dispc, &coefs_rgb2yuv_bt601_lim);
|
||||
dispc_ovl_write_color_conv_coef(dispc, plane, csc);
|
||||
}
|
||||
|
||||
static void dispc_ovl_set_ba0(struct dispc_device *dispc,
|
||||
@ -1285,7 +1295,7 @@ static bool dispc_ovl_color_mode_supported(struct dispc_device *dispc,
|
||||
return false;
|
||||
}
|
||||
|
||||
static const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
|
||||
const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane)
|
||||
{
|
||||
return dispc->feat->supported_color_modes[plane];
|
||||
@ -2601,7 +2611,9 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
|
||||
u8 pre_mult_alpha, u8 global_alpha,
|
||||
enum omap_dss_rotation_type rotation_type,
|
||||
bool replication, const struct videomode *vm,
|
||||
bool mem_to_mem)
|
||||
bool mem_to_mem,
|
||||
enum drm_color_encoding color_encoding,
|
||||
enum drm_color_range color_range)
|
||||
{
|
||||
bool five_taps = true;
|
||||
bool fieldmode = false;
|
||||
@ -2750,6 +2762,9 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
|
||||
fieldmode, fourcc, rotation);
|
||||
dispc_ovl_set_output_size(dispc, plane, out_width, out_height);
|
||||
dispc_ovl_set_vid_color_conv(dispc, plane, cconv);
|
||||
|
||||
if (plane != OMAP_DSS_WB)
|
||||
dispc_ovl_set_csc(dispc, plane, color_encoding, color_range);
|
||||
}
|
||||
|
||||
dispc_ovl_set_rotation_attrs(dispc, plane, rotation, rotation_type,
|
||||
@ -2764,7 +2779,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dispc_ovl_setup(struct dispc_device *dispc,
|
||||
int dispc_ovl_setup(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane,
|
||||
const struct omap_overlay_info *oi,
|
||||
const struct videomode *vm, bool mem_to_mem,
|
||||
@ -2786,12 +2801,13 @@ static int dispc_ovl_setup(struct dispc_device *dispc,
|
||||
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
|
||||
oi->out_width, oi->out_height, oi->fourcc, oi->rotation,
|
||||
oi->zorder, oi->pre_mult_alpha, oi->global_alpha,
|
||||
oi->rotation_type, replication, vm, mem_to_mem);
|
||||
oi->rotation_type, replication, vm, mem_to_mem,
|
||||
oi->color_encoding, oi->color_range);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int dispc_wb_setup(struct dispc_device *dispc,
|
||||
int dispc_wb_setup(struct dispc_device *dispc,
|
||||
const struct omap_dss_writeback_info *wi,
|
||||
bool mem_to_mem, const struct videomode *vm,
|
||||
enum dss_writeback_channel channel_in)
|
||||
@ -2819,7 +2835,8 @@ static int dispc_wb_setup(struct dispc_device *dispc,
|
||||
wi->buf_width, pos_x, pos_y, in_width, in_height, wi->width,
|
||||
wi->height, wi->fourcc, wi->rotation, zorder,
|
||||
wi->pre_mult_alpha, global_alpha, wi->rotation_type,
|
||||
replication, vm, mem_to_mem);
|
||||
replication, vm, mem_to_mem, DRM_COLOR_YCBCR_BT601,
|
||||
DRM_COLOR_YCBCR_LIMITED_RANGE);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -2874,12 +2891,12 @@ static int dispc_wb_setup(struct dispc_device *dispc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool dispc_has_writeback(struct dispc_device *dispc)
|
||||
bool dispc_has_writeback(struct dispc_device *dispc)
|
||||
{
|
||||
return dispc->feat->has_writeback;
|
||||
}
|
||||
|
||||
static int dispc_ovl_enable(struct dispc_device *dispc,
|
||||
int dispc_ovl_enable(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane, bool enable)
|
||||
{
|
||||
DSSDBG("dispc_enable_plane %d, %d\n", plane, enable);
|
||||
@ -2970,7 +2987,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(struct dispc_device *dispc,
|
||||
REG_FLD_MOD(dispc, DISPC_CONFIG, enable, 19, 19);
|
||||
}
|
||||
|
||||
static void dispc_mgr_setup(struct dispc_device *dispc,
|
||||
void dispc_mgr_setup(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct omap_overlay_manager_info *info)
|
||||
{
|
||||
@ -3049,7 +3066,7 @@ static void dispc_mgr_enable_stallmode(struct dispc_device *dispc,
|
||||
mgr_fld_write(dispc, channel, DISPC_MGR_FLD_STALLMODE, enable);
|
||||
}
|
||||
|
||||
static void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
|
||||
void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config)
|
||||
{
|
||||
@ -3098,7 +3115,7 @@ static bool _dispc_mgr_pclk_ok(struct dispc_device *dispc,
|
||||
return pclk <= dispc->feat->max_tv_pclk;
|
||||
}
|
||||
|
||||
static int dispc_mgr_check_timings(struct dispc_device *dispc,
|
||||
int dispc_mgr_check_timings(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm)
|
||||
{
|
||||
@ -3191,7 +3208,7 @@ static int vm_flag_to_int(enum display_flags flags, enum display_flags high,
|
||||
}
|
||||
|
||||
/* change name to mode? */
|
||||
static void dispc_mgr_set_timings(struct dispc_device *dispc,
|
||||
void dispc_mgr_set_timings(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm)
|
||||
{
|
||||
@ -3735,17 +3752,17 @@ int dispc_mgr_get_clock_div(struct dispc_device *dispc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 dispc_read_irqstatus(struct dispc_device *dispc)
|
||||
u32 dispc_read_irqstatus(struct dispc_device *dispc)
|
||||
{
|
||||
return dispc_read_reg(dispc, DISPC_IRQSTATUS);
|
||||
}
|
||||
|
||||
static void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask)
|
||||
void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask)
|
||||
{
|
||||
dispc_write_reg(dispc, DISPC_IRQSTATUS, mask);
|
||||
}
|
||||
|
||||
static void dispc_write_irqenable(struct dispc_device *dispc, u32 mask)
|
||||
void dispc_write_irqenable(struct dispc_device *dispc, u32 mask)
|
||||
{
|
||||
u32 old_mask = dispc_read_reg(dispc, DISPC_IRQENABLE);
|
||||
|
||||
@ -3769,7 +3786,7 @@ void dispc_disable_sidle(struct dispc_device *dispc)
|
||||
REG_FLD_MOD(dispc, DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */
|
||||
}
|
||||
|
||||
static u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
|
||||
u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma;
|
||||
@ -3824,7 +3841,7 @@ static const struct drm_color_lut dispc_mgr_gamma_default_lut[] = {
|
||||
{ .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, },
|
||||
};
|
||||
|
||||
static void dispc_mgr_set_gamma(struct dispc_device *dispc,
|
||||
void dispc_mgr_set_gamma(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct drm_color_lut *lut,
|
||||
unsigned int length)
|
||||
@ -3930,8 +3947,6 @@ static void _omap_dispc_initial_config(struct dispc_device *dispc)
|
||||
dispc->feat->has_gamma_table)
|
||||
REG_FLD_MOD(dispc, DISPC_CONFIG, 1, 9, 9);
|
||||
|
||||
dispc_setup_color_conv_coef(dispc);
|
||||
|
||||
dispc_set_loadmode(dispc, OMAP_DSS_LOAD_FRAME_ONLY);
|
||||
|
||||
dispc_init_fifos(dispc);
|
||||
@ -4482,7 +4497,7 @@ static irqreturn_t dispc_irq_handler(int irq, void *arg)
|
||||
return dispc->user_handler(irq, dispc->user_data);
|
||||
}
|
||||
|
||||
static int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
|
||||
int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
|
||||
void *dev_id)
|
||||
{
|
||||
int r;
|
||||
@ -4506,7 +4521,7 @@ static int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
|
||||
void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
|
||||
{
|
||||
devm_free_irq(&dispc->pdev->dev, dispc->irq, dispc);
|
||||
|
||||
@ -4514,7 +4529,7 @@ static void dispc_free_irq(struct dispc_device *dispc, void *dev_id)
|
||||
dispc->user_data = NULL;
|
||||
}
|
||||
|
||||
static u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc)
|
||||
u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc)
|
||||
{
|
||||
u32 limit = 0;
|
||||
|
||||
@ -4684,47 +4699,6 @@ static void dispc_errata_i734_wa(struct dispc_device *dispc)
|
||||
REG_FLD_MOD(dispc, DISPC_CONFIG, gatestate, 8, 4);
|
||||
}
|
||||
|
||||
static const struct dispc_ops dispc_ops = {
|
||||
.read_irqstatus = dispc_read_irqstatus,
|
||||
.clear_irqstatus = dispc_clear_irqstatus,
|
||||
.write_irqenable = dispc_write_irqenable,
|
||||
|
||||
.request_irq = dispc_request_irq,
|
||||
.free_irq = dispc_free_irq,
|
||||
|
||||
.runtime_get = dispc_runtime_get,
|
||||
.runtime_put = dispc_runtime_put,
|
||||
|
||||
.get_num_ovls = dispc_get_num_ovls,
|
||||
.get_num_mgrs = dispc_get_num_mgrs,
|
||||
|
||||
.get_memory_bandwidth_limit = dispc_get_memory_bandwidth_limit,
|
||||
|
||||
.mgr_enable = dispc_mgr_enable,
|
||||
.mgr_is_enabled = dispc_mgr_is_enabled,
|
||||
.mgr_get_vsync_irq = dispc_mgr_get_vsync_irq,
|
||||
.mgr_get_framedone_irq = dispc_mgr_get_framedone_irq,
|
||||
.mgr_get_sync_lost_irq = dispc_mgr_get_sync_lost_irq,
|
||||
.mgr_go_busy = dispc_mgr_go_busy,
|
||||
.mgr_go = dispc_mgr_go,
|
||||
.mgr_set_lcd_config = dispc_mgr_set_lcd_config,
|
||||
.mgr_check_timings = dispc_mgr_check_timings,
|
||||
.mgr_set_timings = dispc_mgr_set_timings,
|
||||
.mgr_setup = dispc_mgr_setup,
|
||||
.mgr_gamma_size = dispc_mgr_gamma_size,
|
||||
.mgr_set_gamma = dispc_mgr_set_gamma,
|
||||
|
||||
.ovl_enable = dispc_ovl_enable,
|
||||
.ovl_setup = dispc_ovl_setup,
|
||||
.ovl_get_color_modes = dispc_ovl_get_color_modes,
|
||||
|
||||
.wb_get_framedone_irq = dispc_wb_get_framedone_irq,
|
||||
.wb_setup = dispc_wb_setup,
|
||||
.has_writeback = dispc_has_writeback,
|
||||
.wb_go_busy = dispc_wb_go_busy,
|
||||
.wb_go = dispc_wb_go,
|
||||
};
|
||||
|
||||
/* DISPC HW IP initialisation */
|
||||
static const struct of_device_id dispc_of_match[] = {
|
||||
{ .compatible = "ti,omap2-dispc", .data = &omap24xx_dispc_feats },
|
||||
@ -4826,7 +4800,6 @@ static int dispc_bind(struct device *dev, struct device *master, void *data)
|
||||
dispc_runtime_put(dispc);
|
||||
|
||||
dss->dispc = dispc;
|
||||
dss->dispc_ops = &dispc_ops;
|
||||
|
||||
dispc->debugfs = dss_debugfs_create_file(dss, "dispc", dispc_dump_regs,
|
||||
dispc);
|
||||
@ -4848,7 +4821,6 @@ static void dispc_unbind(struct device *dev, struct device *master, void *data)
|
||||
dss_debugfs_remove_file(dispc->debugfs);
|
||||
|
||||
dss->dispc = NULL;
|
||||
dss->dispc_ops = NULL;
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
|
@ -1,60 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "DISPLAY"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
#include "omapdss.h"
|
||||
|
||||
static int disp_num_counter;
|
||||
|
||||
void omapdss_display_init(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int id;
|
||||
|
||||
/*
|
||||
* Note: this presumes that all displays either have an DT alias, or
|
||||
* none has.
|
||||
*/
|
||||
id = of_alias_get_id(dssdev->dev->of_node, "display");
|
||||
if (id < 0)
|
||||
id = disp_num_counter++;
|
||||
|
||||
/* Use 'label' property for name, if it exists */
|
||||
of_property_read_string(dssdev->dev->of_node, "label", &dssdev->name);
|
||||
|
||||
if (dssdev->name == NULL)
|
||||
dssdev->name = devm_kasprintf(dssdev->dev, GFP_KERNEL,
|
||||
"display%u", id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_display_init);
|
||||
|
||||
int omapdss_display_get_modes(struct drm_connector *connector,
|
||||
const struct videomode *vm)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_create(connector->dev);
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
drm_display_mode_from_videomode(vm, mode);
|
||||
|
||||
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_probed_add(connector, mode);
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omapdss_display_get_modes);
|
@ -641,7 +641,6 @@ static int dpi_init_output_port(struct dpi_data *dpi, struct device_node *port)
|
||||
out->type = OMAP_DISPLAY_TYPE_DPI;
|
||||
out->dispc_channel = dpi_get_channel(dpi);
|
||||
out->of_port = port_num;
|
||||
out->owner = THIS_MODULE;
|
||||
|
||||
r = omapdss_device_init_output(out, &dpi->bridge);
|
||||
if (r < 0) {
|
||||
|
File diff suppressed because it is too large
Load Diff
456
drivers/gpu/drm/omapdrm/dss/dsi.h
Normal file
456
drivers/gpu/drm/omapdrm/dss/dsi.h
Normal file
@ -0,0 +1,456 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2016 Texas Instruments Incorporated - http://www.ti.com/
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef __OMAP_DRM_DSS_DSI_H
|
||||
#define __OMAP_DRM_DSS_DSI_H
|
||||
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
|
||||
struct dsi_reg {
|
||||
u16 module;
|
||||
u16 idx;
|
||||
};
|
||||
|
||||
#define DSI_REG(mod, idx) ((const struct dsi_reg) { mod, idx })
|
||||
|
||||
/* DSI Protocol Engine */
|
||||
|
||||
#define DSI_PROTO 0
|
||||
#define DSI_PROTO_SZ 0x200
|
||||
|
||||
#define DSI_REVISION DSI_REG(DSI_PROTO, 0x0000)
|
||||
#define DSI_SYSCONFIG DSI_REG(DSI_PROTO, 0x0010)
|
||||
#define DSI_SYSSTATUS DSI_REG(DSI_PROTO, 0x0014)
|
||||
#define DSI_IRQSTATUS DSI_REG(DSI_PROTO, 0x0018)
|
||||
#define DSI_IRQENABLE DSI_REG(DSI_PROTO, 0x001C)
|
||||
#define DSI_CTRL DSI_REG(DSI_PROTO, 0x0040)
|
||||
#define DSI_GNQ DSI_REG(DSI_PROTO, 0x0044)
|
||||
#define DSI_COMPLEXIO_CFG1 DSI_REG(DSI_PROTO, 0x0048)
|
||||
#define DSI_COMPLEXIO_IRQ_STATUS DSI_REG(DSI_PROTO, 0x004C)
|
||||
#define DSI_COMPLEXIO_IRQ_ENABLE DSI_REG(DSI_PROTO, 0x0050)
|
||||
#define DSI_CLK_CTRL DSI_REG(DSI_PROTO, 0x0054)
|
||||
#define DSI_TIMING1 DSI_REG(DSI_PROTO, 0x0058)
|
||||
#define DSI_TIMING2 DSI_REG(DSI_PROTO, 0x005C)
|
||||
#define DSI_VM_TIMING1 DSI_REG(DSI_PROTO, 0x0060)
|
||||
#define DSI_VM_TIMING2 DSI_REG(DSI_PROTO, 0x0064)
|
||||
#define DSI_VM_TIMING3 DSI_REG(DSI_PROTO, 0x0068)
|
||||
#define DSI_CLK_TIMING DSI_REG(DSI_PROTO, 0x006C)
|
||||
#define DSI_TX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0070)
|
||||
#define DSI_RX_FIFO_VC_SIZE DSI_REG(DSI_PROTO, 0x0074)
|
||||
#define DSI_COMPLEXIO_CFG2 DSI_REG(DSI_PROTO, 0x0078)
|
||||
#define DSI_RX_FIFO_VC_FULLNESS DSI_REG(DSI_PROTO, 0x007C)
|
||||
#define DSI_VM_TIMING4 DSI_REG(DSI_PROTO, 0x0080)
|
||||
#define DSI_TX_FIFO_VC_EMPTINESS DSI_REG(DSI_PROTO, 0x0084)
|
||||
#define DSI_VM_TIMING5 DSI_REG(DSI_PROTO, 0x0088)
|
||||
#define DSI_VM_TIMING6 DSI_REG(DSI_PROTO, 0x008C)
|
||||
#define DSI_VM_TIMING7 DSI_REG(DSI_PROTO, 0x0090)
|
||||
#define DSI_STOPCLK_TIMING DSI_REG(DSI_PROTO, 0x0094)
|
||||
#define DSI_VC_CTRL(n) DSI_REG(DSI_PROTO, 0x0100 + (n * 0x20))
|
||||
#define DSI_VC_TE(n) DSI_REG(DSI_PROTO, 0x0104 + (n * 0x20))
|
||||
#define DSI_VC_LONG_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0108 + (n * 0x20))
|
||||
#define DSI_VC_LONG_PACKET_PAYLOAD(n) DSI_REG(DSI_PROTO, 0x010C + (n * 0x20))
|
||||
#define DSI_VC_SHORT_PACKET_HEADER(n) DSI_REG(DSI_PROTO, 0x0110 + (n * 0x20))
|
||||
#define DSI_VC_IRQSTATUS(n) DSI_REG(DSI_PROTO, 0x0118 + (n * 0x20))
|
||||
#define DSI_VC_IRQENABLE(n) DSI_REG(DSI_PROTO, 0x011C + (n * 0x20))
|
||||
|
||||
/* DSIPHY_SCP */
|
||||
|
||||
#define DSI_PHY 1
|
||||
#define DSI_PHY_OFFSET 0x200
|
||||
#define DSI_PHY_SZ 0x40
|
||||
|
||||
#define DSI_DSIPHY_CFG0 DSI_REG(DSI_PHY, 0x0000)
|
||||
#define DSI_DSIPHY_CFG1 DSI_REG(DSI_PHY, 0x0004)
|
||||
#define DSI_DSIPHY_CFG2 DSI_REG(DSI_PHY, 0x0008)
|
||||
#define DSI_DSIPHY_CFG5 DSI_REG(DSI_PHY, 0x0014)
|
||||
#define DSI_DSIPHY_CFG10 DSI_REG(DSI_PHY, 0x0028)
|
||||
|
||||
/* DSI_PLL_CTRL_SCP */
|
||||
|
||||
#define DSI_PLL 2
|
||||
#define DSI_PLL_OFFSET 0x300
|
||||
#define DSI_PLL_SZ 0x20
|
||||
|
||||
#define DSI_PLL_CONTROL DSI_REG(DSI_PLL, 0x0000)
|
||||
#define DSI_PLL_STATUS DSI_REG(DSI_PLL, 0x0004)
|
||||
#define DSI_PLL_GO DSI_REG(DSI_PLL, 0x0008)
|
||||
#define DSI_PLL_CONFIGURATION1 DSI_REG(DSI_PLL, 0x000C)
|
||||
#define DSI_PLL_CONFIGURATION2 DSI_REG(DSI_PLL, 0x0010)
|
||||
|
||||
/* Global interrupts */
|
||||
#define DSI_IRQ_VC0 (1 << 0)
|
||||
#define DSI_IRQ_VC1 (1 << 1)
|
||||
#define DSI_IRQ_VC2 (1 << 2)
|
||||
#define DSI_IRQ_VC3 (1 << 3)
|
||||
#define DSI_IRQ_WAKEUP (1 << 4)
|
||||
#define DSI_IRQ_RESYNC (1 << 5)
|
||||
#define DSI_IRQ_PLL_LOCK (1 << 7)
|
||||
#define DSI_IRQ_PLL_UNLOCK (1 << 8)
|
||||
#define DSI_IRQ_PLL_RECALL (1 << 9)
|
||||
#define DSI_IRQ_COMPLEXIO_ERR (1 << 10)
|
||||
#define DSI_IRQ_HS_TX_TIMEOUT (1 << 14)
|
||||
#define DSI_IRQ_LP_RX_TIMEOUT (1 << 15)
|
||||
#define DSI_IRQ_TE_TRIGGER (1 << 16)
|
||||
#define DSI_IRQ_ACK_TRIGGER (1 << 17)
|
||||
#define DSI_IRQ_SYNC_LOST (1 << 18)
|
||||
#define DSI_IRQ_LDO_POWER_GOOD (1 << 19)
|
||||
#define DSI_IRQ_TA_TIMEOUT (1 << 20)
|
||||
#define DSI_IRQ_ERROR_MASK \
|
||||
(DSI_IRQ_HS_TX_TIMEOUT | DSI_IRQ_LP_RX_TIMEOUT | DSI_IRQ_SYNC_LOST | \
|
||||
DSI_IRQ_TA_TIMEOUT)
|
||||
#define DSI_IRQ_CHANNEL_MASK 0xf
|
||||
|
||||
/* Virtual channel interrupts */
|
||||
#define DSI_VC_IRQ_CS (1 << 0)
|
||||
#define DSI_VC_IRQ_ECC_CORR (1 << 1)
|
||||
#define DSI_VC_IRQ_PACKET_SENT (1 << 2)
|
||||
#define DSI_VC_IRQ_FIFO_TX_OVF (1 << 3)
|
||||
#define DSI_VC_IRQ_FIFO_RX_OVF (1 << 4)
|
||||
#define DSI_VC_IRQ_BTA (1 << 5)
|
||||
#define DSI_VC_IRQ_ECC_NO_CORR (1 << 6)
|
||||
#define DSI_VC_IRQ_FIFO_TX_UDF (1 << 7)
|
||||
#define DSI_VC_IRQ_PP_BUSY_CHANGE (1 << 8)
|
||||
#define DSI_VC_IRQ_ERROR_MASK \
|
||||
(DSI_VC_IRQ_CS | DSI_VC_IRQ_ECC_CORR | DSI_VC_IRQ_FIFO_TX_OVF | \
|
||||
DSI_VC_IRQ_FIFO_RX_OVF | DSI_VC_IRQ_ECC_NO_CORR | \
|
||||
DSI_VC_IRQ_FIFO_TX_UDF)
|
||||
|
||||
/* ComplexIO interrupts */
|
||||
#define DSI_CIO_IRQ_ERRSYNCESC1 (1 << 0)
|
||||
#define DSI_CIO_IRQ_ERRSYNCESC2 (1 << 1)
|
||||
#define DSI_CIO_IRQ_ERRSYNCESC3 (1 << 2)
|
||||
#define DSI_CIO_IRQ_ERRSYNCESC4 (1 << 3)
|
||||
#define DSI_CIO_IRQ_ERRSYNCESC5 (1 << 4)
|
||||
#define DSI_CIO_IRQ_ERRESC1 (1 << 5)
|
||||
#define DSI_CIO_IRQ_ERRESC2 (1 << 6)
|
||||
#define DSI_CIO_IRQ_ERRESC3 (1 << 7)
|
||||
#define DSI_CIO_IRQ_ERRESC4 (1 << 8)
|
||||
#define DSI_CIO_IRQ_ERRESC5 (1 << 9)
|
||||
#define DSI_CIO_IRQ_ERRCONTROL1 (1 << 10)
|
||||
#define DSI_CIO_IRQ_ERRCONTROL2 (1 << 11)
|
||||
#define DSI_CIO_IRQ_ERRCONTROL3 (1 << 12)
|
||||
#define DSI_CIO_IRQ_ERRCONTROL4 (1 << 13)
|
||||
#define DSI_CIO_IRQ_ERRCONTROL5 (1 << 14)
|
||||
#define DSI_CIO_IRQ_STATEULPS1 (1 << 15)
|
||||
#define DSI_CIO_IRQ_STATEULPS2 (1 << 16)
|
||||
#define DSI_CIO_IRQ_STATEULPS3 (1 << 17)
|
||||
#define DSI_CIO_IRQ_STATEULPS4 (1 << 18)
|
||||
#define DSI_CIO_IRQ_STATEULPS5 (1 << 19)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP0_1 (1 << 20)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_1 (1 << 21)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP0_2 (1 << 22)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_2 (1 << 23)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP0_3 (1 << 24)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_3 (1 << 25)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP0_4 (1 << 26)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_4 (1 << 27)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP0_5 (1 << 28)
|
||||
#define DSI_CIO_IRQ_ERRCONTENTIONLP1_5 (1 << 29)
|
||||
#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL0 (1 << 30)
|
||||
#define DSI_CIO_IRQ_ULPSACTIVENOT_ALL1 (1 << 31)
|
||||
#define DSI_CIO_IRQ_ERROR_MASK \
|
||||
(DSI_CIO_IRQ_ERRSYNCESC1 | DSI_CIO_IRQ_ERRSYNCESC2 | \
|
||||
DSI_CIO_IRQ_ERRSYNCESC3 | DSI_CIO_IRQ_ERRSYNCESC4 | \
|
||||
DSI_CIO_IRQ_ERRSYNCESC5 | \
|
||||
DSI_CIO_IRQ_ERRESC1 | DSI_CIO_IRQ_ERRESC2 | \
|
||||
DSI_CIO_IRQ_ERRESC3 | DSI_CIO_IRQ_ERRESC4 | \
|
||||
DSI_CIO_IRQ_ERRESC5 | \
|
||||
DSI_CIO_IRQ_ERRCONTROL1 | DSI_CIO_IRQ_ERRCONTROL2 | \
|
||||
DSI_CIO_IRQ_ERRCONTROL3 | DSI_CIO_IRQ_ERRCONTROL4 | \
|
||||
DSI_CIO_IRQ_ERRCONTROL5 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_1 | DSI_CIO_IRQ_ERRCONTENTIONLP1_1 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_2 | DSI_CIO_IRQ_ERRCONTENTIONLP1_2 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_3 | DSI_CIO_IRQ_ERRCONTENTIONLP1_3 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_4 | DSI_CIO_IRQ_ERRCONTENTIONLP1_4 | \
|
||||
DSI_CIO_IRQ_ERRCONTENTIONLP0_5 | DSI_CIO_IRQ_ERRCONTENTIONLP1_5)
|
||||
|
||||
enum omap_dss_dsi_mode {
|
||||
OMAP_DSS_DSI_CMD_MODE = 0,
|
||||
OMAP_DSS_DSI_VIDEO_MODE,
|
||||
};
|
||||
|
||||
enum omap_dss_dsi_trans_mode {
|
||||
/* Sync Pulses: both sync start and end packets sent */
|
||||
OMAP_DSS_DSI_PULSE_MODE,
|
||||
/* Sync Events: only sync start packets sent */
|
||||
OMAP_DSS_DSI_EVENT_MODE,
|
||||
/* Burst: only sync start packets sent, pixels are time compressed */
|
||||
OMAP_DSS_DSI_BURST_MODE,
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_videomode_timings {
|
||||
unsigned long hsclk;
|
||||
|
||||
unsigned int ndl;
|
||||
unsigned int bitspp;
|
||||
|
||||
/* pixels */
|
||||
u16 hact;
|
||||
/* lines */
|
||||
u16 vact;
|
||||
|
||||
/* DSI video mode blanking data */
|
||||
/* Unit: byte clock cycles */
|
||||
u16 hss;
|
||||
u16 hsa;
|
||||
u16 hse;
|
||||
u16 hfp;
|
||||
u16 hbp;
|
||||
/* Unit: line clocks */
|
||||
u16 vsa;
|
||||
u16 vfp;
|
||||
u16 vbp;
|
||||
|
||||
/* DSI blanking modes */
|
||||
int blanking_mode;
|
||||
int hsa_blanking_mode;
|
||||
int hbp_blanking_mode;
|
||||
int hfp_blanking_mode;
|
||||
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
|
||||
int window_sync;
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_config {
|
||||
enum omap_dss_dsi_mode mode;
|
||||
enum mipi_dsi_pixel_format pixel_format;
|
||||
const struct videomode *vm;
|
||||
|
||||
unsigned long hs_clk_min, hs_clk_max;
|
||||
unsigned long lp_clk_min, lp_clk_max;
|
||||
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
};
|
||||
|
||||
/* DSI PLL HSDIV indices */
|
||||
#define HSDIV_DISPC 0
|
||||
#define HSDIV_DSI 1
|
||||
|
||||
#define DSI_MAX_NR_ISRS 2
|
||||
#define DSI_MAX_NR_LANES 5
|
||||
|
||||
enum dsi_model {
|
||||
DSI_MODEL_OMAP3,
|
||||
DSI_MODEL_OMAP4,
|
||||
DSI_MODEL_OMAP5,
|
||||
};
|
||||
|
||||
enum dsi_lane_function {
|
||||
DSI_LANE_UNUSED = 0,
|
||||
DSI_LANE_CLK,
|
||||
DSI_LANE_DATA1,
|
||||
DSI_LANE_DATA2,
|
||||
DSI_LANE_DATA3,
|
||||
DSI_LANE_DATA4,
|
||||
};
|
||||
|
||||
struct dsi_lane_config {
|
||||
enum dsi_lane_function function;
|
||||
u8 polarity;
|
||||
};
|
||||
|
||||
typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
|
||||
|
||||
struct dsi_isr_data {
|
||||
omap_dsi_isr_t isr;
|
||||
void *arg;
|
||||
u32 mask;
|
||||
};
|
||||
|
||||
enum fifo_size {
|
||||
DSI_FIFO_SIZE_0 = 0,
|
||||
DSI_FIFO_SIZE_32 = 1,
|
||||
DSI_FIFO_SIZE_64 = 2,
|
||||
DSI_FIFO_SIZE_96 = 3,
|
||||
DSI_FIFO_SIZE_128 = 4,
|
||||
};
|
||||
|
||||
enum dsi_vc_source {
|
||||
DSI_VC_SOURCE_L4 = 0,
|
||||
DSI_VC_SOURCE_VP,
|
||||
};
|
||||
|
||||
struct dsi_irq_stats {
|
||||
unsigned long last_reset;
|
||||
unsigned int irq_count;
|
||||
unsigned int dsi_irqs[32];
|
||||
unsigned int vc_irqs[4][32];
|
||||
unsigned int cio_irqs[32];
|
||||
};
|
||||
|
||||
struct dsi_isr_tables {
|
||||
struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS];
|
||||
struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS];
|
||||
struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS];
|
||||
};
|
||||
|
||||
struct dsi_lp_clock_info {
|
||||
unsigned long lp_clk;
|
||||
u16 lp_clk_div;
|
||||
};
|
||||
|
||||
struct dsi_clk_calc_ctx {
|
||||
struct dsi_data *dsi;
|
||||
struct dss_pll *pll;
|
||||
|
||||
/* inputs */
|
||||
|
||||
const struct omap_dss_dsi_config *config;
|
||||
|
||||
unsigned long req_pck_min, req_pck_nom, req_pck_max;
|
||||
|
||||
/* outputs */
|
||||
|
||||
struct dss_pll_clock_info dsi_cinfo;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
struct dsi_lp_clock_info lp_cinfo;
|
||||
|
||||
struct videomode vm;
|
||||
struct omap_dss_dsi_videomode_timings dsi_vm;
|
||||
};
|
||||
|
||||
struct dsi_module_id_data {
|
||||
u32 address;
|
||||
int id;
|
||||
};
|
||||
|
||||
enum dsi_quirks {
|
||||
DSI_QUIRK_PLL_PWR_BUG = (1 << 0), /* DSI-PLL power command 0x3 is not working */
|
||||
DSI_QUIRK_DCS_CMD_CONFIG_VC = (1 << 1),
|
||||
DSI_QUIRK_VC_OCP_WIDTH = (1 << 2),
|
||||
DSI_QUIRK_REVERSE_TXCLKESC = (1 << 3),
|
||||
DSI_QUIRK_GNQ = (1 << 4),
|
||||
DSI_QUIRK_PHY_DCC = (1 << 5),
|
||||
};
|
||||
|
||||
struct dsi_of_data {
|
||||
enum dsi_model model;
|
||||
const struct dss_pll_hw *pll_hw;
|
||||
const struct dsi_module_id_data *modules;
|
||||
unsigned int max_fck_freq;
|
||||
unsigned int max_pll_lpdiv;
|
||||
enum dsi_quirks quirks;
|
||||
};
|
||||
|
||||
struct dsi_data {
|
||||
struct device *dev;
|
||||
void __iomem *proto_base;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *pll_base;
|
||||
|
||||
const struct dsi_of_data *data;
|
||||
int module_id;
|
||||
|
||||
int irq;
|
||||
|
||||
bool is_enabled;
|
||||
|
||||
struct clk *dss_clk;
|
||||
struct regmap *syscon;
|
||||
struct dss_device *dss;
|
||||
|
||||
struct mipi_dsi_host host;
|
||||
|
||||
struct dispc_clock_info user_dispc_cinfo;
|
||||
struct dss_pll_clock_info user_dsi_cinfo;
|
||||
|
||||
struct dsi_lp_clock_info user_lp_cinfo;
|
||||
struct dsi_lp_clock_info current_lp_cinfo;
|
||||
|
||||
struct dss_pll pll;
|
||||
|
||||
bool vdds_dsi_enabled;
|
||||
struct regulator *vdds_dsi_reg;
|
||||
|
||||
struct mipi_dsi_device *dsidev;
|
||||
|
||||
struct {
|
||||
enum dsi_vc_source source;
|
||||
enum fifo_size tx_fifo_size;
|
||||
enum fifo_size rx_fifo_size;
|
||||
} vc[4];
|
||||
|
||||
struct mutex lock;
|
||||
struct semaphore bus_lock;
|
||||
|
||||
spinlock_t irq_lock;
|
||||
struct dsi_isr_tables isr_tables;
|
||||
/* space for a copy used by the interrupt handler */
|
||||
struct dsi_isr_tables isr_tables_copy;
|
||||
|
||||
int update_vc;
|
||||
#ifdef DSI_PERF_MEASURE
|
||||
unsigned int update_bytes;
|
||||
#endif
|
||||
|
||||
/* external TE GPIO */
|
||||
struct gpio_desc *te_gpio;
|
||||
int te_irq;
|
||||
struct delayed_work te_timeout_work;
|
||||
atomic_t do_ext_te_update;
|
||||
|
||||
bool te_enabled;
|
||||
bool iface_enabled;
|
||||
bool video_enabled;
|
||||
|
||||
struct delayed_work framedone_timeout_work;
|
||||
|
||||
#ifdef DSI_CATCH_MISSING_TE
|
||||
struct timer_list te_timer;
|
||||
#endif
|
||||
|
||||
unsigned long cache_req_pck;
|
||||
unsigned long cache_clk_freq;
|
||||
struct dss_pll_clock_info cache_cinfo;
|
||||
|
||||
u32 errors;
|
||||
spinlock_t errors_lock;
|
||||
#ifdef DSI_PERF_MEASURE
|
||||
ktime_t perf_setup_time;
|
||||
ktime_t perf_start_time;
|
||||
#endif
|
||||
int debug_read;
|
||||
int debug_write;
|
||||
struct {
|
||||
struct dss_debugfs_entry *irqs;
|
||||
struct dss_debugfs_entry *regs;
|
||||
struct dss_debugfs_entry *clks;
|
||||
} debugfs;
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
spinlock_t irq_stats_lock;
|
||||
struct dsi_irq_stats irq_stats;
|
||||
#endif
|
||||
|
||||
unsigned int num_lanes_supported;
|
||||
unsigned int line_buffer_size;
|
||||
|
||||
struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
|
||||
unsigned int num_lanes_used;
|
||||
|
||||
unsigned int scp_clk_refcount;
|
||||
|
||||
struct omap_dss_dsi_config config;
|
||||
|
||||
struct dss_lcd_mgr_config mgr_config;
|
||||
struct videomode vm;
|
||||
enum mipi_dsi_pixel_format pix_fmt;
|
||||
enum omap_dss_dsi_mode mode;
|
||||
struct omap_dss_dsi_videomode_timings vm_timings;
|
||||
|
||||
struct omap_dss_device output;
|
||||
struct drm_bridge bridge;
|
||||
|
||||
struct delayed_work dsi_disable_work;
|
||||
};
|
||||
|
||||
struct dsi_packet_sent_handler_data {
|
||||
struct dsi_data *dsi;
|
||||
struct completion *completion;
|
||||
};
|
||||
|
||||
#endif /* __OMAP_DRM_DSS_DSI_H */
|
@ -1308,6 +1308,7 @@ static int dss_bind(struct device *dev)
|
||||
{
|
||||
struct dss_device *dss = dev_get_drvdata(dev);
|
||||
struct platform_device *drm_pdev;
|
||||
struct dss_pdata pdata;
|
||||
int r;
|
||||
|
||||
r = component_bind_all(dev, NULL);
|
||||
@ -1316,9 +1317,9 @@ static int dss_bind(struct device *dev)
|
||||
|
||||
pm_set_vt_switch(0);
|
||||
|
||||
omapdss_set_dss(dss);
|
||||
|
||||
drm_pdev = platform_device_register_simple("omapdrm", 0, NULL, 0);
|
||||
pdata.dss = dss;
|
||||
drm_pdev = platform_device_register_data(NULL, "omapdrm", 0,
|
||||
&pdata, sizeof(pdata));
|
||||
if (IS_ERR(drm_pdev)) {
|
||||
component_unbind_all(dev, NULL);
|
||||
return PTR_ERR(drm_pdev);
|
||||
@ -1335,8 +1336,6 @@ static void dss_unbind(struct device *dev)
|
||||
|
||||
platform_device_unregister(dss->drm_pdev);
|
||||
|
||||
omapdss_set_dss(NULL);
|
||||
|
||||
component_unbind_all(dev, NULL);
|
||||
}
|
||||
|
||||
@ -1569,15 +1568,7 @@ static int dss_remove(struct platform_device *pdev)
|
||||
|
||||
static void dss_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
|
||||
DSSDBG("shutdown\n");
|
||||
|
||||
for_each_dss_output(dssdev) {
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE &&
|
||||
dssdev->ops && dssdev->ops->disable)
|
||||
dssdev->ops->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
static int dss_runtime_suspend(struct device *dev)
|
||||
@ -1650,21 +1641,14 @@ static struct platform_driver * const omap_dss_drivers[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init omap_dss_init(void)
|
||||
int __init omap_dss_init(void)
|
||||
{
|
||||
return platform_register_drivers(omap_dss_drivers,
|
||||
ARRAY_SIZE(omap_dss_drivers));
|
||||
}
|
||||
|
||||
static void __exit omap_dss_exit(void)
|
||||
void omap_dss_exit(void)
|
||||
{
|
||||
platform_unregister_drivers(omap_dss_drivers,
|
||||
ARRAY_SIZE(omap_dss_drivers));
|
||||
}
|
||||
|
||||
module_init(omap_dss_init);
|
||||
module_exit(omap_dss_exit);
|
||||
|
||||
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
|
||||
MODULE_DESCRIPTION("OMAP2/3/4/5 Display Subsystem");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -257,8 +257,6 @@ struct dss_device {
|
||||
struct dss_pll *video2_pll;
|
||||
|
||||
struct dispc_device *dispc;
|
||||
const struct dispc_ops *dispc_ops;
|
||||
const struct dss_mgr_ops *mgr_ops;
|
||||
struct omap_drm_private *mgr_ops_priv;
|
||||
};
|
||||
|
||||
@ -393,6 +391,76 @@ void dispc_dump_clocks(struct dispc_device *dispc, struct seq_file *s);
|
||||
int dispc_runtime_get(struct dispc_device *dispc);
|
||||
void dispc_runtime_put(struct dispc_device *dispc);
|
||||
|
||||
int dispc_get_num_ovls(struct dispc_device *dispc);
|
||||
int dispc_get_num_mgrs(struct dispc_device *dispc);
|
||||
|
||||
const u32 *dispc_ovl_get_color_modes(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane);
|
||||
|
||||
u32 dispc_read_irqstatus(struct dispc_device *dispc);
|
||||
void dispc_clear_irqstatus(struct dispc_device *dispc, u32 mask);
|
||||
void dispc_write_irqenable(struct dispc_device *dispc, u32 mask);
|
||||
|
||||
int dispc_request_irq(struct dispc_device *dispc, irq_handler_t handler,
|
||||
void *dev_id);
|
||||
void dispc_free_irq(struct dispc_device *dispc, void *dev_id);
|
||||
|
||||
u32 dispc_mgr_get_vsync_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 dispc_mgr_get_framedone_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc);
|
||||
|
||||
u32 dispc_get_memory_bandwidth_limit(struct dispc_device *dispc);
|
||||
|
||||
void dispc_mgr_enable(struct dispc_device *dispc,
|
||||
enum omap_channel channel, bool enable);
|
||||
|
||||
bool dispc_mgr_go_busy(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
|
||||
void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel);
|
||||
|
||||
void dispc_mgr_set_lcd_config(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
void dispc_mgr_set_timings(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
void dispc_mgr_setup(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct omap_overlay_manager_info *info);
|
||||
|
||||
int dispc_mgr_check_timings(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
|
||||
u32 dispc_mgr_gamma_size(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
void dispc_mgr_set_gamma(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct drm_color_lut *lut,
|
||||
unsigned int length);
|
||||
|
||||
int dispc_ovl_setup(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane,
|
||||
const struct omap_overlay_info *oi,
|
||||
const struct videomode *vm, bool mem_to_mem,
|
||||
enum omap_channel channel);
|
||||
|
||||
int dispc_ovl_enable(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane, bool enable);
|
||||
|
||||
bool dispc_has_writeback(struct dispc_device *dispc);
|
||||
int dispc_wb_setup(struct dispc_device *dispc,
|
||||
const struct omap_dss_writeback_info *wi,
|
||||
bool mem_to_mem, const struct videomode *vm,
|
||||
enum dss_writeback_channel channel_in);
|
||||
bool dispc_wb_go_busy(struct dispc_device *dispc);
|
||||
void dispc_wb_go(struct dispc_device *dispc);
|
||||
|
||||
void dispc_enable_sidle(struct dispc_device *dispc);
|
||||
void dispc_disable_sidle(struct dispc_device *dispc);
|
||||
|
||||
|
@ -707,7 +707,6 @@ static int hdmi4_init_output(struct omap_hdmi *hdmi)
|
||||
out->type = OMAP_DISPLAY_TYPE_HDMI;
|
||||
out->name = "hdmi.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
out->owner = THIS_MODULE;
|
||||
out->of_port = 0;
|
||||
|
||||
r = omapdss_device_init_output(out, &hdmi->bridge);
|
||||
|
@ -681,7 +681,6 @@ static int hdmi5_init_output(struct omap_hdmi *hdmi)
|
||||
out->type = OMAP_DISPLAY_TYPE_HDMI;
|
||||
out->name = "hdmi.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
out->owner = THIS_MODULE;
|
||||
out->of_port = 0;
|
||||
|
||||
r = omapdss_device_init_output(out, &hdmi->bridge);
|
||||
|
@ -1,229 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* As omapdss panel drivers are omapdss specific, but we want to define the
|
||||
* DT-data in generic manner, we convert the compatible strings of the panel and
|
||||
* encoder nodes from "panel-foo" to "omapdss,panel-foo". This way we can have
|
||||
* both correct DT data and omapdss specific drivers.
|
||||
*
|
||||
* When we get generic panel drivers to the kernel, this file will be removed.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
static struct list_head dss_conv_list __initdata;
|
||||
|
||||
static const char prefix[] __initconst = "omapdss,";
|
||||
|
||||
struct dss_conv_node {
|
||||
struct list_head list;
|
||||
struct device_node *node;
|
||||
bool root;
|
||||
};
|
||||
|
||||
static int __init omapdss_count_strings(const struct property *prop)
|
||||
{
|
||||
const char *p = prop->value;
|
||||
int l = 0, total = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; total < prop->length; total += l, p += l, i++)
|
||||
l = strlen(p) + 1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void __init omapdss_update_prop(struct device_node *node, char *compat,
|
||||
int len)
|
||||
{
|
||||
struct property *prop;
|
||||
|
||||
prop = kzalloc(sizeof(*prop), GFP_KERNEL);
|
||||
if (!prop)
|
||||
return;
|
||||
|
||||
prop->name = "compatible";
|
||||
prop->value = compat;
|
||||
prop->length = len;
|
||||
|
||||
of_update_property(node, prop);
|
||||
}
|
||||
|
||||
static void __init omapdss_prefix_strcpy(char *dst, int dst_len,
|
||||
const char *src, int src_len)
|
||||
{
|
||||
size_t total = 0;
|
||||
|
||||
while (total < src_len) {
|
||||
size_t l = strlen(src) + 1;
|
||||
|
||||
strcpy(dst, prefix);
|
||||
dst += strlen(prefix);
|
||||
|
||||
strcpy(dst, src);
|
||||
dst += l;
|
||||
|
||||
src += l;
|
||||
total += l;
|
||||
}
|
||||
}
|
||||
|
||||
/* prepend compatible property strings with "omapdss," */
|
||||
static void __init omapdss_omapify_node(struct device_node *node)
|
||||
{
|
||||
struct property *prop;
|
||||
char *new_compat;
|
||||
int num_strs;
|
||||
int new_len;
|
||||
|
||||
prop = of_find_property(node, "compatible", NULL);
|
||||
|
||||
if (!prop || !prop->value)
|
||||
return;
|
||||
|
||||
if (strnlen(prop->value, prop->length) >= prop->length)
|
||||
return;
|
||||
|
||||
/* is it already prefixed? */
|
||||
if (strncmp(prefix, prop->value, strlen(prefix)) == 0)
|
||||
return;
|
||||
|
||||
num_strs = omapdss_count_strings(prop);
|
||||
|
||||
new_len = prop->length + strlen(prefix) * num_strs;
|
||||
new_compat = kmalloc(new_len, GFP_KERNEL);
|
||||
|
||||
omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
|
||||
|
||||
omapdss_update_prop(node, new_compat, new_len);
|
||||
}
|
||||
|
||||
static void __init omapdss_add_to_list(struct device_node *node, bool root)
|
||||
{
|
||||
struct dss_conv_node *n = kmalloc(sizeof(*n), GFP_KERNEL);
|
||||
if (n) {
|
||||
n->node = node;
|
||||
n->root = root;
|
||||
list_add(&n->list, &dss_conv_list);
|
||||
}
|
||||
}
|
||||
|
||||
static bool __init omapdss_list_contains(const struct device_node *node)
|
||||
{
|
||||
struct dss_conv_node *n;
|
||||
|
||||
list_for_each_entry(n, &dss_conv_list, list) {
|
||||
if (n->node == node)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void __init omapdss_walk_device(struct device_node *node, bool root)
|
||||
{
|
||||
struct device_node *n;
|
||||
|
||||
omapdss_add_to_list(node, root);
|
||||
|
||||
/*
|
||||
* of_graph_get_remote_port_parent() prints an error if there is no
|
||||
* port/ports node. To avoid that, check first that there's the node.
|
||||
*/
|
||||
n = of_get_child_by_name(node, "ports");
|
||||
if (!n)
|
||||
n = of_get_child_by_name(node, "port");
|
||||
if (!n)
|
||||
return;
|
||||
|
||||
of_node_put(n);
|
||||
|
||||
n = NULL;
|
||||
while ((n = of_graph_get_next_endpoint(node, n)) != NULL) {
|
||||
struct device_node *pn;
|
||||
|
||||
pn = of_graph_get_remote_port_parent(n);
|
||||
|
||||
if (!pn)
|
||||
continue;
|
||||
|
||||
if (!of_device_is_available(pn) || omapdss_list_contains(pn)) {
|
||||
of_node_put(pn);
|
||||
continue;
|
||||
}
|
||||
|
||||
omapdss_walk_device(pn, false);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct of_device_id omapdss_of_match[] __initconst = {
|
||||
{ .compatible = "ti,omap2-dss", },
|
||||
{ .compatible = "ti,omap3-dss", },
|
||||
{ .compatible = "ti,omap4-dss", },
|
||||
{ .compatible = "ti,omap5-dss", },
|
||||
{ .compatible = "ti,dra7-dss", },
|
||||
{},
|
||||
};
|
||||
|
||||
static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = {
|
||||
{ .compatible = "panel-dsi-cm" },
|
||||
{},
|
||||
};
|
||||
|
||||
static void __init omapdss_find_children(struct device_node *np)
|
||||
{
|
||||
struct device_node *child;
|
||||
|
||||
for_each_available_child_of_node(np, child) {
|
||||
if (!of_find_property(child, "compatible", NULL))
|
||||
continue;
|
||||
|
||||
omapdss_walk_device(child, true);
|
||||
|
||||
if (of_device_is_compatible(child, "ti,sysc"))
|
||||
omapdss_find_children(child);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init omapdss_boot_init(void)
|
||||
{
|
||||
struct device_node *dss;
|
||||
|
||||
INIT_LIST_HEAD(&dss_conv_list);
|
||||
|
||||
dss = of_find_matching_node(NULL, omapdss_of_match);
|
||||
|
||||
if (dss == NULL || !of_device_is_available(dss))
|
||||
goto put_node;
|
||||
|
||||
omapdss_walk_device(dss, true);
|
||||
omapdss_find_children(dss);
|
||||
|
||||
while (!list_empty(&dss_conv_list)) {
|
||||
struct dss_conv_node *n;
|
||||
|
||||
n = list_first_entry(&dss_conv_list, struct dss_conv_node,
|
||||
list);
|
||||
|
||||
if (of_match_node(omapdss_of_fixups_whitelist, n->node))
|
||||
omapdss_omapify_node(n->node);
|
||||
|
||||
list_del(&n->list);
|
||||
of_node_put(n->node);
|
||||
kfree(n);
|
||||
}
|
||||
|
||||
put_node:
|
||||
of_node_put(dss);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(omapdss_boot_init);
|
@ -7,13 +7,14 @@
|
||||
#ifndef __OMAP_DRM_DSS_H
|
||||
#define __OMAP_DRM_DSS_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <video/videomode.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/platform_data/omapdss.h>
|
||||
#include <uapi/drm/drm_mode.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#define DISPC_IRQ_FRAMEDONE (1 << 0)
|
||||
#define DISPC_IRQ_VSYNC (1 << 1)
|
||||
@ -116,28 +117,6 @@ enum omap_dss_venc_type {
|
||||
OMAP_DSS_VENC_TYPE_SVIDEO,
|
||||
};
|
||||
|
||||
enum omap_dss_dsi_pixel_format {
|
||||
OMAP_DSS_DSI_FMT_RGB888,
|
||||
OMAP_DSS_DSI_FMT_RGB666,
|
||||
OMAP_DSS_DSI_FMT_RGB666_PACKED,
|
||||
OMAP_DSS_DSI_FMT_RGB565,
|
||||
};
|
||||
|
||||
enum omap_dss_dsi_mode {
|
||||
OMAP_DSS_DSI_CMD_MODE = 0,
|
||||
OMAP_DSS_DSI_VIDEO_MODE,
|
||||
};
|
||||
|
||||
enum omap_display_caps {
|
||||
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1,
|
||||
};
|
||||
|
||||
enum omap_dss_display_state {
|
||||
OMAP_DSS_DISPLAY_DISABLED = 0,
|
||||
OMAP_DSS_DISPLAY_ACTIVE,
|
||||
};
|
||||
|
||||
enum omap_dss_rotation_type {
|
||||
OMAP_DSS_ROT_NONE = 0,
|
||||
OMAP_DSS_ROT_TILER = 1 << 0,
|
||||
@ -162,64 +141,6 @@ enum omap_dss_output_id {
|
||||
OMAP_DSS_OUTPUT_HDMI = 1 << 6,
|
||||
};
|
||||
|
||||
/* DSI */
|
||||
|
||||
enum omap_dss_dsi_trans_mode {
|
||||
/* Sync Pulses: both sync start and end packets sent */
|
||||
OMAP_DSS_DSI_PULSE_MODE,
|
||||
/* Sync Events: only sync start packets sent */
|
||||
OMAP_DSS_DSI_EVENT_MODE,
|
||||
/* Burst: only sync start packets sent, pixels are time compressed */
|
||||
OMAP_DSS_DSI_BURST_MODE,
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_videomode_timings {
|
||||
unsigned long hsclk;
|
||||
|
||||
unsigned int ndl;
|
||||
unsigned int bitspp;
|
||||
|
||||
/* pixels */
|
||||
u16 hact;
|
||||
/* lines */
|
||||
u16 vact;
|
||||
|
||||
/* DSI video mode blanking data */
|
||||
/* Unit: byte clock cycles */
|
||||
u16 hss;
|
||||
u16 hsa;
|
||||
u16 hse;
|
||||
u16 hfp;
|
||||
u16 hbp;
|
||||
/* Unit: line clocks */
|
||||
u16 vsa;
|
||||
u16 vfp;
|
||||
u16 vbp;
|
||||
|
||||
/* DSI blanking modes */
|
||||
int blanking_mode;
|
||||
int hsa_blanking_mode;
|
||||
int hbp_blanking_mode;
|
||||
int hfp_blanking_mode;
|
||||
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
|
||||
bool ddr_clk_always_on;
|
||||
int window_sync;
|
||||
};
|
||||
|
||||
struct omap_dss_dsi_config {
|
||||
enum omap_dss_dsi_mode mode;
|
||||
enum omap_dss_dsi_pixel_format pixel_format;
|
||||
const struct videomode *vm;
|
||||
|
||||
unsigned long hs_clk_min, hs_clk_max;
|
||||
unsigned long lp_clk_min, lp_clk_max;
|
||||
|
||||
bool ddr_clk_always_on;
|
||||
enum omap_dss_dsi_trans_mode trans_mode;
|
||||
};
|
||||
|
||||
struct omap_dss_cpr_coefs {
|
||||
s16 rr, rg, rb;
|
||||
s16 gr, gg, gb;
|
||||
@ -243,6 +164,9 @@ struct omap_overlay_info {
|
||||
u8 global_alpha;
|
||||
u8 pre_mult_alpha;
|
||||
u8 zorder;
|
||||
|
||||
enum drm_color_encoding color_encoding;
|
||||
enum drm_color_range color_range;
|
||||
};
|
||||
|
||||
struct omap_overlay_manager_info {
|
||||
@ -258,21 +182,6 @@ struct omap_overlay_manager_info {
|
||||
struct omap_dss_cpr_coefs cpr_coefs;
|
||||
};
|
||||
|
||||
/* 22 pins means 1 clk lane and 10 data lanes */
|
||||
#define OMAP_DSS_MAX_DSI_PINS 22
|
||||
|
||||
struct omap_dsi_pin_config {
|
||||
int num_pins;
|
||||
/*
|
||||
* pin numbers in the following order:
|
||||
* clk+, clk-
|
||||
* data1+, data1-
|
||||
* data2+, data2-
|
||||
* ...
|
||||
*/
|
||||
int pins[OMAP_DSS_MAX_DSI_PINS];
|
||||
};
|
||||
|
||||
struct omap_dss_writeback_info {
|
||||
u32 paddr;
|
||||
u32 p_uv_addr;
|
||||
@ -286,89 +195,14 @@ struct omap_dss_writeback_info {
|
||||
};
|
||||
|
||||
struct omapdss_dsi_ops {
|
||||
void (*disable)(struct omap_dss_device *dssdev, bool disconnect_lanes,
|
||||
bool enter_ulps);
|
||||
|
||||
/* bus configuration */
|
||||
int (*set_config)(struct omap_dss_device *dssdev,
|
||||
const struct omap_dss_dsi_config *cfg);
|
||||
int (*configure_pins)(struct omap_dss_device *dssdev,
|
||||
const struct omap_dsi_pin_config *pin_cfg);
|
||||
|
||||
void (*enable_hs)(struct omap_dss_device *dssdev, int channel,
|
||||
bool enable);
|
||||
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
int (*update)(struct omap_dss_device *dssdev, int channel,
|
||||
void (*callback)(int, void *), void *data);
|
||||
|
||||
void (*bus_lock)(struct omap_dss_device *dssdev);
|
||||
void (*bus_unlock)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*enable_video_output)(struct omap_dss_device *dssdev, int channel);
|
||||
void (*disable_video_output)(struct omap_dss_device *dssdev,
|
||||
int channel);
|
||||
|
||||
int (*request_vc)(struct omap_dss_device *dssdev, int *channel);
|
||||
int (*set_vc_id)(struct omap_dss_device *dssdev, int channel,
|
||||
int vc_id);
|
||||
void (*release_vc)(struct omap_dss_device *dssdev, int channel);
|
||||
|
||||
/* data transfer */
|
||||
int (*dcs_write)(struct omap_dss_device *dssdev, int channel,
|
||||
u8 *data, int len);
|
||||
int (*dcs_write_nosync)(struct omap_dss_device *dssdev, int channel,
|
||||
u8 *data, int len);
|
||||
int (*dcs_read)(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
|
||||
u8 *data, int len);
|
||||
|
||||
int (*gen_write)(struct omap_dss_device *dssdev, int channel,
|
||||
u8 *data, int len);
|
||||
int (*gen_write_nosync)(struct omap_dss_device *dssdev, int channel,
|
||||
u8 *data, int len);
|
||||
int (*gen_read)(struct omap_dss_device *dssdev, int channel,
|
||||
u8 *reqdata, int reqlen,
|
||||
u8 *data, int len);
|
||||
|
||||
int (*bta_sync)(struct omap_dss_device *dssdev, int channel);
|
||||
|
||||
int (*set_max_rx_packet_size)(struct omap_dss_device *dssdev,
|
||||
int channel, u16 plen);
|
||||
};
|
||||
|
||||
struct omap_dss_device_ops {
|
||||
int (*connect)(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_device *dst);
|
||||
void (*disconnect)(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_device *dst);
|
||||
|
||||
void (*enable)(struct omap_dss_device *dssdev);
|
||||
void (*disable)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*check_timings)(struct omap_dss_device *dssdev,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
int (*get_modes)(struct omap_dss_device *dssdev,
|
||||
struct drm_connector *connector);
|
||||
|
||||
const struct omapdss_dsi_ops dsi;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum omap_dss_device_ops_flag - Indicates which device ops are supported
|
||||
* @OMAP_DSS_DEVICE_OP_MODES: The device supports reading modes
|
||||
*/
|
||||
enum omap_dss_device_ops_flag {
|
||||
OMAP_DSS_DEVICE_OP_MODES = BIT(3),
|
||||
int (*update)(struct omap_dss_device *dssdev);
|
||||
bool (*is_video_mode)(struct omap_dss_device *dssdev);
|
||||
};
|
||||
|
||||
struct omap_dss_device {
|
||||
struct device *dev;
|
||||
|
||||
struct module *owner;
|
||||
|
||||
struct dss_device *dss;
|
||||
struct omap_dss_device *next;
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_bridge *next_bridge;
|
||||
struct drm_panel *panel;
|
||||
@ -382,23 +216,11 @@ struct omap_dss_device {
|
||||
*/
|
||||
enum omap_display_type type;
|
||||
|
||||
/*
|
||||
* True if the device is a display (panel or connector) at the end of
|
||||
* the pipeline, false otherwise.
|
||||
*/
|
||||
bool display;
|
||||
|
||||
const char *name;
|
||||
|
||||
const struct omap_dss_driver *driver;
|
||||
const struct omap_dss_device_ops *ops;
|
||||
unsigned long ops_flags;
|
||||
const struct omapdss_dsi_ops *dsi_ops;
|
||||
u32 bus_flags;
|
||||
|
||||
enum omap_display_caps caps;
|
||||
|
||||
enum omap_dss_display_state state;
|
||||
|
||||
/* OMAP DSS output specific fields */
|
||||
|
||||
/* DISPC channel for this output */
|
||||
@ -411,30 +233,10 @@ struct omap_dss_device {
|
||||
unsigned int of_port;
|
||||
};
|
||||
|
||||
struct omap_dss_driver {
|
||||
int (*update)(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
int (*sync)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
|
||||
int (*get_te)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*memory_read)(struct omap_dss_device *dssdev,
|
||||
void *buf, size_t size,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
struct dss_pdata {
|
||||
struct dss_device *dss;
|
||||
};
|
||||
|
||||
struct dss_device *omapdss_get_dss(void);
|
||||
void omapdss_set_dss(struct dss_device *dss);
|
||||
static inline bool omapdss_is_initialized(void)
|
||||
{
|
||||
return !!omapdss_get_dss();
|
||||
}
|
||||
|
||||
void omapdss_display_init(struct omap_dss_device *dssdev);
|
||||
int omapdss_display_get_modes(struct drm_connector *connector,
|
||||
const struct videomode *vm);
|
||||
|
||||
void omapdss_device_register(struct omap_dss_device *dssdev);
|
||||
void omapdss_device_unregister(struct omap_dss_device *dssdev);
|
||||
struct omap_dss_device *omapdss_device_get(struct omap_dss_device *dssdev);
|
||||
@ -445,8 +247,6 @@ int omapdss_device_connect(struct dss_device *dss,
|
||||
struct omap_dss_device *dst);
|
||||
void omapdss_device_disconnect(struct omap_dss_device *src,
|
||||
struct omap_dss_device *dst);
|
||||
void omapdss_device_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_device_disable(struct omap_dss_device *dssdev);
|
||||
|
||||
int omap_dss_get_num_overlay_managers(void);
|
||||
|
||||
@ -466,11 +266,6 @@ int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
int omapdss_compat_init(void);
|
||||
void omapdss_compat_uninit(void);
|
||||
|
||||
static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE;
|
||||
}
|
||||
|
||||
enum dss_writeback_channel {
|
||||
DSS_WB_LCD1_MGR = 0,
|
||||
DSS_WB_LCD2_MGR = 1,
|
||||
@ -482,31 +277,23 @@ enum dss_writeback_channel {
|
||||
DSS_WB_LCD3_MGR = 7,
|
||||
};
|
||||
|
||||
struct dss_mgr_ops {
|
||||
void (*start_update)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel);
|
||||
int (*enable)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel);
|
||||
void (*disable)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel);
|
||||
void (*set_timings)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
void (*set_lcd_config)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
int (*register_framedone_handler)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
void (*handler)(void *), void *data);
|
||||
void (*unregister_framedone_handler)(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
void (*handler)(void *), void *data);
|
||||
};
|
||||
|
||||
int dss_install_mgr_ops(struct dss_device *dss,
|
||||
const struct dss_mgr_ops *mgr_ops,
|
||||
struct omap_drm_private *priv);
|
||||
void dss_uninstall_mgr_ops(struct dss_device *dss);
|
||||
void omap_crtc_dss_start_update(struct omap_drm_private *priv,
|
||||
enum omap_channel channel);
|
||||
void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable);
|
||||
int omap_crtc_dss_enable(struct omap_drm_private *priv, enum omap_channel channel);
|
||||
void omap_crtc_dss_disable(struct omap_drm_private *priv, enum omap_channel channel);
|
||||
void omap_crtc_dss_set_timings(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
int omap_crtc_dss_register_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data);
|
||||
void omap_crtc_dss_unregister_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data);
|
||||
|
||||
void dss_mgr_set_timings(struct omap_dss_device *dssdev,
|
||||
const struct videomode *vm);
|
||||
@ -520,80 +307,12 @@ int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,
|
||||
void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,
|
||||
void (*handler)(void *), void *data);
|
||||
|
||||
/* dispc ops */
|
||||
|
||||
struct dispc_ops {
|
||||
u32 (*read_irqstatus)(struct dispc_device *dispc);
|
||||
void (*clear_irqstatus)(struct dispc_device *dispc, u32 mask);
|
||||
void (*write_irqenable)(struct dispc_device *dispc, u32 mask);
|
||||
|
||||
int (*request_irq)(struct dispc_device *dispc, irq_handler_t handler,
|
||||
void *dev_id);
|
||||
void (*free_irq)(struct dispc_device *dispc, void *dev_id);
|
||||
|
||||
int (*runtime_get)(struct dispc_device *dispc);
|
||||
void (*runtime_put)(struct dispc_device *dispc);
|
||||
|
||||
int (*get_num_ovls)(struct dispc_device *dispc);
|
||||
int (*get_num_mgrs)(struct dispc_device *dispc);
|
||||
|
||||
u32 (*get_memory_bandwidth_limit)(struct dispc_device *dispc);
|
||||
|
||||
void (*mgr_enable)(struct dispc_device *dispc,
|
||||
enum omap_channel channel, bool enable);
|
||||
bool (*mgr_is_enabled)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 (*mgr_get_vsync_irq)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 (*mgr_get_framedone_irq)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
u32 (*mgr_get_sync_lost_irq)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
bool (*mgr_go_busy)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
void (*mgr_go)(struct dispc_device *dispc, enum omap_channel channel);
|
||||
void (*mgr_set_lcd_config)(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config);
|
||||
int (*mgr_check_timings)(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
void (*mgr_set_timings)(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm);
|
||||
void (*mgr_setup)(struct dispc_device *dispc, enum omap_channel channel,
|
||||
const struct omap_overlay_manager_info *info);
|
||||
u32 (*mgr_gamma_size)(struct dispc_device *dispc,
|
||||
enum omap_channel channel);
|
||||
void (*mgr_set_gamma)(struct dispc_device *dispc,
|
||||
enum omap_channel channel,
|
||||
const struct drm_color_lut *lut,
|
||||
unsigned int length);
|
||||
|
||||
int (*ovl_enable)(struct dispc_device *dispc, enum omap_plane_id plane,
|
||||
bool enable);
|
||||
int (*ovl_setup)(struct dispc_device *dispc, enum omap_plane_id plane,
|
||||
const struct omap_overlay_info *oi,
|
||||
const struct videomode *vm, bool mem_to_mem,
|
||||
enum omap_channel channel);
|
||||
|
||||
const u32 *(*ovl_get_color_modes)(struct dispc_device *dispc,
|
||||
enum omap_plane_id plane);
|
||||
|
||||
u32 (*wb_get_framedone_irq)(struct dispc_device *dispc);
|
||||
int (*wb_setup)(struct dispc_device *dispc,
|
||||
const struct omap_dss_writeback_info *wi,
|
||||
bool mem_to_mem, const struct videomode *vm,
|
||||
enum dss_writeback_channel channel_in);
|
||||
bool (*has_writeback)(struct dispc_device *dispc);
|
||||
bool (*wb_go_busy)(struct dispc_device *dispc);
|
||||
void (*wb_go)(struct dispc_device *dispc);
|
||||
};
|
||||
|
||||
struct dispc_device *dispc_get_dispc(struct dss_device *dss);
|
||||
const struct dispc_ops *dispc_get_ops(struct dss_device *dss);
|
||||
|
||||
bool omapdss_stack_is_ready(void);
|
||||
void omapdss_gather_components(struct device *dev);
|
||||
|
||||
int omap_dss_init(void);
|
||||
void omap_dss_exit(void);
|
||||
|
||||
#endif /* __OMAP_DRM_DSS_H */
|
||||
|
@ -30,7 +30,6 @@ int omapdss_device_init_output(struct omap_dss_device *out,
|
||||
return 0;
|
||||
}
|
||||
|
||||
out->next = omapdss_find_device_by_node(remote_node);
|
||||
out->bridge = of_drm_find_bridge(remote_node);
|
||||
out->panel = of_drm_find_panel(remote_node);
|
||||
if (IS_ERR(out->panel))
|
||||
@ -38,12 +37,6 @@ int omapdss_device_init_output(struct omap_dss_device *out,
|
||||
|
||||
of_node_put(remote_node);
|
||||
|
||||
if (out->next && out->type != out->next->type) {
|
||||
dev_err(out->dev, "output type and display type don't match\n");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (out->panel) {
|
||||
struct drm_bridge *bridge;
|
||||
|
||||
@ -69,7 +62,7 @@ int omapdss_device_init_output(struct omap_dss_device *out,
|
||||
out->bridge = local_bridge;
|
||||
}
|
||||
|
||||
if (!out->next && !out->bridge) {
|
||||
if (!out->bridge) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto error;
|
||||
}
|
||||
@ -78,98 +71,64 @@ int omapdss_device_init_output(struct omap_dss_device *out,
|
||||
|
||||
error:
|
||||
omapdss_device_cleanup_output(out);
|
||||
out->next = NULL;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_device_init_output);
|
||||
|
||||
void omapdss_device_cleanup_output(struct omap_dss_device *out)
|
||||
{
|
||||
if (out->bridge && out->panel)
|
||||
drm_panel_bridge_remove(out->next_bridge ?
|
||||
out->next_bridge : out->bridge);
|
||||
|
||||
if (out->next)
|
||||
omapdss_device_put(out->next);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_device_cleanup_output);
|
||||
|
||||
int dss_install_mgr_ops(struct dss_device *dss,
|
||||
const struct dss_mgr_ops *mgr_ops,
|
||||
struct omap_drm_private *priv)
|
||||
{
|
||||
if (dss->mgr_ops)
|
||||
return -EBUSY;
|
||||
|
||||
dss->mgr_ops = mgr_ops;
|
||||
dss->mgr_ops_priv = priv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dss_install_mgr_ops);
|
||||
|
||||
void dss_uninstall_mgr_ops(struct dss_device *dss)
|
||||
{
|
||||
dss->mgr_ops = NULL;
|
||||
dss->mgr_ops_priv = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(dss_uninstall_mgr_ops);
|
||||
|
||||
void dss_mgr_set_timings(struct omap_dss_device *dssdev,
|
||||
const struct videomode *vm)
|
||||
{
|
||||
dssdev->dss->mgr_ops->set_timings(dssdev->dss->mgr_ops_priv,
|
||||
omap_crtc_dss_set_timings(dssdev->dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel, vm);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_set_timings);
|
||||
|
||||
void dss_mgr_set_lcd_config(struct omap_dss_device *dssdev,
|
||||
const struct dss_lcd_mgr_config *config)
|
||||
{
|
||||
dssdev->dss->mgr_ops->set_lcd_config(dssdev->dss->mgr_ops_priv,
|
||||
omap_crtc_dss_set_lcd_config(dssdev->dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel, config);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_set_lcd_config);
|
||||
|
||||
int dss_mgr_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return dssdev->dss->mgr_ops->enable(dssdev->dss->mgr_ops_priv,
|
||||
return omap_crtc_dss_enable(dssdev->dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_enable);
|
||||
|
||||
void dss_mgr_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->dss->mgr_ops->disable(dssdev->dss->mgr_ops_priv,
|
||||
omap_crtc_dss_disable(dssdev->dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_disable);
|
||||
|
||||
void dss_mgr_start_update(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->dss->mgr_ops->start_update(dssdev->dss->mgr_ops_priv,
|
||||
omap_crtc_dss_start_update(dssdev->dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_start_update);
|
||||
|
||||
int dss_mgr_register_framedone_handler(struct omap_dss_device *dssdev,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
struct dss_device *dss = dssdev->dss;
|
||||
|
||||
return dss->mgr_ops->register_framedone_handler(dss->mgr_ops_priv,
|
||||
return omap_crtc_dss_register_framedone(dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel,
|
||||
handler, data);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_register_framedone_handler);
|
||||
|
||||
void dss_mgr_unregister_framedone_handler(struct omap_dss_device *dssdev,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
struct dss_device *dss = dssdev->dss;
|
||||
|
||||
dss->mgr_ops->unregister_framedone_handler(dss->mgr_ops_priv,
|
||||
omap_crtc_dss_unregister_framedone(dss->mgr_ops_priv,
|
||||
dssdev->dispc_channel,
|
||||
handler, data);
|
||||
}
|
||||
EXPORT_SYMBOL(dss_mgr_unregister_framedone_handler);
|
||||
|
@ -222,6 +222,9 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
|
||||
n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
|
||||
n_inc = 1;
|
||||
|
||||
if (n_start > n_stop)
|
||||
return false;
|
||||
|
||||
if (hw->errata_i886) {
|
||||
swap(n_start, n_stop);
|
||||
n_inc = -1;
|
||||
@ -239,6 +242,9 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin,
|
||||
hw->m_max);
|
||||
m_inc = 1;
|
||||
|
||||
if (m_start > m_stop)
|
||||
continue;
|
||||
|
||||
if (hw->errata_i886) {
|
||||
swap(m_start, m_stop);
|
||||
m_inc = -1;
|
||||
|
@ -312,7 +312,6 @@ static int sdi_init_output(struct sdi_device *sdi)
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_LCD;
|
||||
/* We have SDI only on OMAP3, where it's on port 1 */
|
||||
out->of_port = 1;
|
||||
out->owner = THIS_MODULE;
|
||||
out->bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE /* 15.5.9.1.2 */
|
||||
| DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE;
|
||||
|
||||
|
@ -733,9 +733,7 @@ static int venc_init_output(struct venc_device *venc)
|
||||
out->type = OMAP_DISPLAY_TYPE_VENC;
|
||||
out->name = "venc.0";
|
||||
out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
out->owner = THIS_MODULE;
|
||||
out->of_port = 0;
|
||||
out->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
|
||||
|
||||
r = omapdss_device_init_output(out, &venc->bridge);
|
||||
if (r < 0) {
|
||||
|
@ -1,157 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (C) 2011 Texas Instruments Incorporated - https://www.ti.com/
|
||||
* Author: Rob Clark <rob@ti.com>
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "omap_drv.h"
|
||||
|
||||
/*
|
||||
* connector funcs
|
||||
*/
|
||||
|
||||
#define to_omap_connector(x) container_of(x, struct omap_connector, base)
|
||||
|
||||
struct omap_connector {
|
||||
struct drm_connector base;
|
||||
struct omap_dss_device *output;
|
||||
};
|
||||
|
||||
static enum drm_connector_status omap_connector_detect(
|
||||
struct drm_connector *connector, bool force)
|
||||
{
|
||||
return connector_status_connected;
|
||||
}
|
||||
|
||||
static void omap_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct omap_connector *omap_connector = to_omap_connector(connector);
|
||||
|
||||
DBG("%s", connector->name);
|
||||
|
||||
drm_connector_unregister(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
omapdss_device_put(omap_connector->output);
|
||||
|
||||
kfree(omap_connector);
|
||||
}
|
||||
|
||||
static int omap_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct omap_connector *omap_connector = to_omap_connector(connector);
|
||||
struct omap_dss_device *dssdev = NULL;
|
||||
struct omap_dss_device *d;
|
||||
|
||||
DBG("%s", connector->name);
|
||||
|
||||
/*
|
||||
* If the display pipeline reports modes (e.g. with a fixed resolution
|
||||
* panel or an analog TV output), query it.
|
||||
*/
|
||||
for (d = omap_connector->output; d; d = d->next) {
|
||||
if (d->ops_flags & OMAP_DSS_DEVICE_OP_MODES)
|
||||
dssdev = d;
|
||||
}
|
||||
|
||||
if (dssdev)
|
||||
return dssdev->ops->get_modes(dssdev, connector);
|
||||
|
||||
/* We can't retrieve modes. The KMS core will add the default modes. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
drm_mode_copy(adjusted_mode, mode);
|
||||
|
||||
for (; dssdev; dssdev = dssdev->next) {
|
||||
if (!dssdev->ops || !dssdev->ops->check_timings)
|
||||
continue;
|
||||
|
||||
ret = dssdev->ops->check_timings(dssdev, adjusted_mode);
|
||||
if (ret)
|
||||
return MODE_BAD;
|
||||
}
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_mode_status omap_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct omap_connector *omap_connector = to_omap_connector(connector);
|
||||
struct drm_display_mode new_mode = {};
|
||||
enum drm_mode_status status;
|
||||
|
||||
status = omap_connector_mode_fixup(omap_connector->output, mode,
|
||||
&new_mode);
|
||||
if (status != MODE_OK)
|
||||
goto done;
|
||||
|
||||
/* Check if vrefresh is still valid. */
|
||||
if (drm_mode_vrefresh(mode) != drm_mode_vrefresh(&new_mode))
|
||||
status = MODE_NOCLOCK;
|
||||
|
||||
done:
|
||||
DBG("connector: mode %s: " DRM_MODE_FMT,
|
||||
(status == MODE_OK) ? "valid" : "invalid",
|
||||
DRM_MODE_ARG(mode));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs omap_connector_funcs = {
|
||||
.reset = drm_atomic_helper_connector_reset,
|
||||
.detect = omap_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = omap_connector_destroy,
|
||||
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static const struct drm_connector_helper_funcs omap_connector_helper_funcs = {
|
||||
.get_modes = omap_connector_get_modes,
|
||||
.mode_valid = omap_connector_mode_valid,
|
||||
};
|
||||
|
||||
/* initialize connector */
|
||||
struct drm_connector *omap_connector_init(struct drm_device *dev,
|
||||
struct omap_dss_device *output,
|
||||
struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_connector *connector = NULL;
|
||||
struct omap_connector *omap_connector;
|
||||
|
||||
DBG("%s", output->name);
|
||||
|
||||
omap_connector = kzalloc(sizeof(*omap_connector), GFP_KERNEL);
|
||||
if (!omap_connector)
|
||||
goto fail;
|
||||
|
||||
omap_connector->output = omapdss_device_get(output);
|
||||
|
||||
connector = &omap_connector->base;
|
||||
connector->interlace_allowed = 1;
|
||||
connector->doublescan_allowed = 0;
|
||||
|
||||
drm_connector_init(dev, connector, &omap_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DSI);
|
||||
drm_connector_helper_add(connector, &omap_connector_helper_funcs);
|
||||
|
||||
return connector;
|
||||
|
||||
fail:
|
||||
if (connector)
|
||||
omap_connector_destroy(connector);
|
||||
|
||||
return NULL;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* omap_connector.h -- OMAP DRM Connector
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
* Author: Rob Clark <rob@ti.com>
|
||||
*/
|
||||
|
||||
#ifndef __OMAPDRM_CONNECTOR_H__
|
||||
#define __OMAPDRM_CONNECTOR_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum drm_mode_status;
|
||||
|
||||
struct drm_connector;
|
||||
struct drm_device;
|
||||
struct drm_encoder;
|
||||
struct omap_dss_device;
|
||||
|
||||
struct drm_connector *omap_connector_init(struct drm_device *dev,
|
||||
struct omap_dss_device *output,
|
||||
struct drm_encoder *encoder);
|
||||
enum drm_mode_status omap_connector_mode_fixup(struct omap_dss_device *dssdev,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
|
||||
#endif /* __OMAPDRM_CONNECTOR_H__ */
|
@ -100,14 +100,14 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc)
|
||||
* the upstream part of the video pipe.
|
||||
*/
|
||||
|
||||
static void omap_crtc_dss_start_update(struct omap_drm_private *priv,
|
||||
void omap_crtc_dss_start_update(struct omap_drm_private *priv,
|
||||
enum omap_channel channel)
|
||||
{
|
||||
priv->dispc_ops->mgr_enable(priv->dispc, channel, true);
|
||||
dispc_mgr_enable(priv->dispc, channel, true);
|
||||
}
|
||||
|
||||
/* Called only from the encoder enable/disable and suspend/resume handlers. */
|
||||
static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
{
|
||||
struct omap_crtc_state *omap_state = to_omap_crtc_state(crtc->state);
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -128,7 +128,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
}
|
||||
|
||||
if (omap_crtc->pipe->output->type == OMAP_DISPLAY_TYPE_HDMI) {
|
||||
priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
|
||||
dispc_mgr_enable(priv->dispc, channel, enable);
|
||||
omap_crtc->enabled = enable;
|
||||
return;
|
||||
}
|
||||
@ -141,9 +141,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
omap_crtc->ignore_digit_sync_lost = true;
|
||||
}
|
||||
|
||||
framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(priv->dispc,
|
||||
framedone_irq = dispc_mgr_get_framedone_irq(priv->dispc,
|
||||
channel);
|
||||
vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel);
|
||||
vsync_irq = dispc_mgr_get_vsync_irq(priv->dispc, channel);
|
||||
|
||||
if (enable) {
|
||||
wait = omap_irq_wait_init(dev, vsync_irq, 1);
|
||||
@ -163,7 +163,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
wait = omap_irq_wait_init(dev, vsync_irq, 2);
|
||||
}
|
||||
|
||||
priv->dispc_ops->mgr_enable(priv->dispc, channel, enable);
|
||||
dispc_mgr_enable(priv->dispc, channel, enable);
|
||||
omap_crtc->enabled = enable;
|
||||
|
||||
ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
|
||||
@ -180,21 +180,19 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable)
|
||||
}
|
||||
|
||||
|
||||
static int omap_crtc_dss_enable(struct omap_drm_private *priv,
|
||||
enum omap_channel channel)
|
||||
int omap_crtc_dss_enable(struct omap_drm_private *priv, enum omap_channel channel)
|
||||
{
|
||||
struct drm_crtc *crtc = priv->channels[channel]->crtc;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
||||
priv->dispc_ops->mgr_set_timings(priv->dispc, omap_crtc->channel,
|
||||
dispc_mgr_set_timings(priv->dispc, omap_crtc->channel,
|
||||
&omap_crtc->vm);
|
||||
omap_crtc_set_enabled(&omap_crtc->base, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_crtc_dss_disable(struct omap_drm_private *priv,
|
||||
enum omap_channel channel)
|
||||
void omap_crtc_dss_disable(struct omap_drm_private *priv, enum omap_channel channel)
|
||||
{
|
||||
struct drm_crtc *crtc = priv->channels[channel]->crtc;
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
@ -202,7 +200,7 @@ static void omap_crtc_dss_disable(struct omap_drm_private *priv,
|
||||
omap_crtc_set_enabled(&omap_crtc->base, false);
|
||||
}
|
||||
|
||||
static void omap_crtc_dss_set_timings(struct omap_drm_private *priv,
|
||||
void omap_crtc_dss_set_timings(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct videomode *vm)
|
||||
{
|
||||
@ -213,7 +211,7 @@ static void omap_crtc_dss_set_timings(struct omap_drm_private *priv,
|
||||
omap_crtc->vm = *vm;
|
||||
}
|
||||
|
||||
static void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv,
|
||||
void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv,
|
||||
enum omap_channel channel,
|
||||
const struct dss_lcd_mgr_config *config)
|
||||
{
|
||||
@ -221,11 +219,11 @@ static void omap_crtc_dss_set_lcd_config(struct omap_drm_private *priv,
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
||||
DBG("%s", omap_crtc->name);
|
||||
priv->dispc_ops->mgr_set_lcd_config(priv->dispc, omap_crtc->channel,
|
||||
dispc_mgr_set_lcd_config(priv->dispc, omap_crtc->channel,
|
||||
config);
|
||||
}
|
||||
|
||||
static int omap_crtc_dss_register_framedone(
|
||||
int omap_crtc_dss_register_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
@ -244,7 +242,7 @@ static int omap_crtc_dss_register_framedone(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_crtc_dss_unregister_framedone(
|
||||
void omap_crtc_dss_unregister_framedone(
|
||||
struct omap_drm_private *priv, enum omap_channel channel,
|
||||
void (*handler)(void *), void *data)
|
||||
{
|
||||
@ -261,16 +259,6 @@ static void omap_crtc_dss_unregister_framedone(
|
||||
omap_crtc->framedone_handler_data = NULL;
|
||||
}
|
||||
|
||||
static const struct dss_mgr_ops mgr_ops = {
|
||||
.start_update = omap_crtc_dss_start_update,
|
||||
.enable = omap_crtc_dss_enable,
|
||||
.disable = omap_crtc_dss_disable,
|
||||
.set_timings = omap_crtc_dss_set_timings,
|
||||
.set_lcd_config = omap_crtc_dss_set_lcd_config,
|
||||
.register_framedone_handler = omap_crtc_dss_register_framedone,
|
||||
.unregister_framedone_handler = omap_crtc_dss_unregister_framedone,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Setup, Flush and Page Flip
|
||||
*/
|
||||
@ -300,7 +288,7 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc)
|
||||
* If the dispc is busy we're racing the flush operation. Try again on
|
||||
* the next vblank interrupt.
|
||||
*/
|
||||
if (priv->dispc_ops->mgr_go_busy(priv->dispc, omap_crtc->channel)) {
|
||||
if (dispc_mgr_go_busy(priv->dispc, omap_crtc->channel)) {
|
||||
spin_unlock(&crtc->dev->event_lock);
|
||||
return;
|
||||
}
|
||||
@ -362,27 +350,14 @@ static void omap_crtc_manual_display_update(struct work_struct *data)
|
||||
{
|
||||
struct omap_crtc *omap_crtc =
|
||||
container_of(data, struct omap_crtc, update_work.work);
|
||||
struct drm_display_mode *mode = &omap_crtc->pipe->crtc->mode;
|
||||
struct omap_dss_device *dssdev = omap_crtc->pipe->output->next;
|
||||
struct omap_dss_device *dssdev = omap_crtc->pipe->output;
|
||||
struct drm_device *dev = omap_crtc->base.dev;
|
||||
const struct omap_dss_driver *dssdrv;
|
||||
int ret;
|
||||
|
||||
if (!dssdev) {
|
||||
dev_err_once(dev->dev, "missing display dssdev!");
|
||||
if (!dssdev || !dssdev->dsi_ops || !dssdev->dsi_ops->update)
|
||||
return;
|
||||
}
|
||||
|
||||
dssdrv = dssdev->driver;
|
||||
if (!dssdrv || !dssdrv->update) {
|
||||
dev_err_once(dev->dev, "missing or incorrect dssdrv!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dssdrv->sync)
|
||||
dssdrv->sync(dssdev);
|
||||
|
||||
ret = dssdrv->update(dssdev, 0, 0, mode->hdisplay, mode->vdisplay);
|
||||
ret = dssdev->dsi_ops->update(dssdev);
|
||||
if (ret < 0) {
|
||||
spin_lock_irq(&dev->event_lock);
|
||||
omap_crtc->pending = false;
|
||||
@ -391,6 +366,33 @@ static void omap_crtc_manual_display_update(struct work_struct *data)
|
||||
}
|
||||
}
|
||||
|
||||
static s16 omap_crtc_s31_32_to_s2_8(s64 coef)
|
||||
{
|
||||
u64 sign_bit = 1ULL << 63;
|
||||
u64 cbits = (u64)coef;
|
||||
|
||||
s16 ret = clamp_val(((cbits & ~sign_bit) >> 24), 0, 0x1ff);
|
||||
|
||||
if (cbits & sign_bit)
|
||||
ret = -ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void omap_crtc_cpr_coefs_from_ctm(const struct drm_color_ctm *ctm,
|
||||
struct omap_dss_cpr_coefs *cpr)
|
||||
{
|
||||
cpr->rr = omap_crtc_s31_32_to_s2_8(ctm->matrix[0]);
|
||||
cpr->rg = omap_crtc_s31_32_to_s2_8(ctm->matrix[1]);
|
||||
cpr->rb = omap_crtc_s31_32_to_s2_8(ctm->matrix[2]);
|
||||
cpr->gr = omap_crtc_s31_32_to_s2_8(ctm->matrix[3]);
|
||||
cpr->gg = omap_crtc_s31_32_to_s2_8(ctm->matrix[4]);
|
||||
cpr->gb = omap_crtc_s31_32_to_s2_8(ctm->matrix[5]);
|
||||
cpr->br = omap_crtc_s31_32_to_s2_8(ctm->matrix[6]);
|
||||
cpr->bg = omap_crtc_s31_32_to_s2_8(ctm->matrix[7]);
|
||||
cpr->bb = omap_crtc_s31_32_to_s2_8(ctm->matrix[8]);
|
||||
}
|
||||
|
||||
static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_drm_private *priv = crtc->dev->dev_private;
|
||||
@ -402,9 +404,17 @@ static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc)
|
||||
info.default_color = 0x000000;
|
||||
info.trans_enabled = false;
|
||||
info.partial_alpha_enabled = false;
|
||||
info.cpr_enable = false;
|
||||
|
||||
priv->dispc_ops->mgr_setup(priv->dispc, omap_crtc->channel, &info);
|
||||
if (crtc->state->ctm) {
|
||||
struct drm_color_ctm *ctm = crtc->state->ctm->data;
|
||||
|
||||
info.cpr_enable = true;
|
||||
omap_crtc_cpr_coefs_from_ctm(ctm, &info.cpr_coefs);
|
||||
} else {
|
||||
info.cpr_enable = false;
|
||||
}
|
||||
|
||||
dispc_mgr_setup(priv->dispc, omap_crtc->channel, &info);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
@ -445,7 +455,7 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
|
||||
DBG("%s", omap_crtc->name);
|
||||
|
||||
priv->dispc_ops->runtime_get(priv->dispc);
|
||||
dispc_runtime_get(priv->dispc);
|
||||
|
||||
/* manual updated display will not trigger vsync irq */
|
||||
if (omap_state->manually_updated)
|
||||
@ -484,7 +494,7 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
|
||||
drm_crtc_vblank_off(crtc);
|
||||
|
||||
priv->dispc_ops->runtime_put(priv->dispc);
|
||||
dispc_runtime_put(priv->dispc);
|
||||
}
|
||||
|
||||
static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
@ -502,9 +512,8 @@ static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
* valid DISPC mode. DSI will calculate and configure the
|
||||
* proper DISPC mode later.
|
||||
*/
|
||||
if (omap_crtc->pipe->output->next == NULL ||
|
||||
omap_crtc->pipe->output->next->type != OMAP_DISPLAY_TYPE_DSI) {
|
||||
r = priv->dispc_ops->mgr_check_timings(priv->dispc,
|
||||
if (omap_crtc->pipe->output->type != OMAP_DISPLAY_TYPE_DSI) {
|
||||
r = dispc_mgr_check_timings(priv->dispc,
|
||||
omap_crtc->channel,
|
||||
&vm);
|
||||
if (r)
|
||||
@ -555,17 +564,16 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
static bool omap_crtc_is_manually_updated(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
struct omap_dss_device *display = omap_crtc->pipe->output->next;
|
||||
struct omap_dss_device *dssdev = omap_crtc->pipe->output;
|
||||
|
||||
if (!display)
|
||||
if (!dssdev || !dssdev->dsi_ops || !dssdev->dsi_ops->is_video_mode)
|
||||
return false;
|
||||
|
||||
if (display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
DBG("detected manually updated display!");
|
||||
return true;
|
||||
}
|
||||
if (dssdev->dsi_ops->is_video_mode(dssdev))
|
||||
return false;
|
||||
|
||||
return false;
|
||||
DBG("detected manually updated display!");
|
||||
return true;
|
||||
}
|
||||
|
||||
static int omap_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
@ -575,8 +583,8 @@ static int omap_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
crtc);
|
||||
struct drm_plane_state *pri_state;
|
||||
|
||||
if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
|
||||
unsigned int length = crtc_state->gamma_lut->length /
|
||||
if (crtc_state->color_mgmt_changed && crtc_state->degamma_lut) {
|
||||
unsigned int length = crtc_state->degamma_lut->length /
|
||||
sizeof(struct drm_color_lut);
|
||||
|
||||
if (length < 2)
|
||||
@ -617,13 +625,13 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_color_lut *lut = NULL;
|
||||
unsigned int length = 0;
|
||||
|
||||
if (crtc->state->gamma_lut) {
|
||||
if (crtc->state->degamma_lut) {
|
||||
lut = (struct drm_color_lut *)
|
||||
crtc->state->gamma_lut->data;
|
||||
length = crtc->state->gamma_lut->length /
|
||||
crtc->state->degamma_lut->data;
|
||||
length = crtc->state->degamma_lut->length /
|
||||
sizeof(*lut);
|
||||
}
|
||||
priv->dispc_ops->mgr_set_gamma(priv->dispc, omap_crtc->channel,
|
||||
dispc_mgr_set_gamma(priv->dispc, omap_crtc->channel,
|
||||
lut, length);
|
||||
}
|
||||
|
||||
@ -648,7 +656,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
WARN_ON(ret != 0);
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
priv->dispc_ops->mgr_go(priv->dispc, omap_crtc->channel);
|
||||
dispc_mgr_go(priv->dispc, omap_crtc->channel);
|
||||
omap_crtc_arm_event(crtc);
|
||||
spin_unlock_irq(&crtc->dev->event_lock);
|
||||
}
|
||||
@ -741,7 +749,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = {
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.destroy = omap_crtc_destroy,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.gamma_set = drm_atomic_helper_legacy_gamma_set,
|
||||
.atomic_duplicate_state = omap_crtc_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
||||
.atomic_set_property = omap_crtc_atomic_set_property,
|
||||
@ -771,16 +778,6 @@ static const char *channel_names[] = {
|
||||
[OMAP_DSS_CHANNEL_LCD3] = "lcd3",
|
||||
};
|
||||
|
||||
void omap_crtc_pre_init(struct omap_drm_private *priv)
|
||||
{
|
||||
dss_install_mgr_ops(priv->dss, &mgr_ops, priv);
|
||||
}
|
||||
|
||||
void omap_crtc_pre_uninit(struct omap_drm_private *priv)
|
||||
{
|
||||
dss_uninstall_mgr_ops(priv->dss);
|
||||
}
|
||||
|
||||
/* initialize crtc */
|
||||
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
||||
struct omap_drm_pipeline *pipe,
|
||||
@ -839,10 +836,10 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
||||
* extracted with dispc_mgr_gamma_size(). If it returns 0
|
||||
* gamma table is not supported.
|
||||
*/
|
||||
if (priv->dispc_ops->mgr_gamma_size(priv->dispc, channel)) {
|
||||
if (dispc_mgr_gamma_size(priv->dispc, channel)) {
|
||||
unsigned int gamma_lut_size = 256;
|
||||
|
||||
drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size);
|
||||
drm_crtc_enable_color_mgmt(crtc, gamma_lut_size, true, 0);
|
||||
drm_mode_crtc_set_gamma_size(crtc, gamma_lut_size);
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,6 @@ struct videomode;
|
||||
|
||||
struct videomode *omap_crtc_timings(struct drm_crtc *crtc);
|
||||
enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
|
||||
void omap_crtc_pre_init(struct omap_drm_private *priv);
|
||||
void omap_crtc_pre_uninit(struct omap_drm_private *priv);
|
||||
struct drm_crtc *omap_crtc_init(struct drm_device *dev,
|
||||
struct omap_drm_pipeline *pipe,
|
||||
struct drm_plane *plane);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user