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:
Daniel Vetter 2021-01-07 10:46:32 +01:00
commit 18589d74f4
239 changed files with 5357 additions and 5437 deletions

View File

@ -18,6 +18,7 @@ properties:
compatible:
enum:
- brcm,bcm2711-dsi1
- brcm,bcm2835-dsi0
- brcm,bcm2835-dsi1

View File

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

View File

@ -20,6 +20,7 @@ properties:
compatible:
enum:
- mantix,mlaf057we51-x
- ys,ys57pss36bh5gq
port: true
reg:

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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[] = {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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