drm-misc-next for v6.5:
UAPI Changes: Cross-subsystem Changes: * fbdev: * Add Kconfig options and initializer macros for file I/O, convert DRM fbdev emulation Core Changes: * Unify handling of struct file_operations.show_fdinfo * Use .probe in all i2c code (interface cleanup) * TTM: * Remove unused code Driver Changes: * amdgpu: * Use shared show_fdinfo code * Fix building without procfs * bridge: * display-conenctor: Add support for external power supply * samsung-dsim: Fix enabling; Support variable clocking * tc358767: Fixes * ti-sn65dsi83: Fix enabling * msm: * Use shared show_fdinfo code * msxfb: * Add support for i.MX93 LCDIF * panel: * Add support for Ampire AM-800480L1TMQW-T00H plus DT bindings * panel-edp: Convert .remove to return void * stm: * dsi: Use devm_ helper * ltdc: Fix potential invalid pointer deref -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEchf7rIzpz2NEoWjlaA3BHVMLeiMFAmR4fr0ACgkQaA3BHVML eiN8dwf/b0+w5eQORSAG/aQsc5nwLLYJwDLhSihtD3lMUa6EUCXQqTb7kqFWt3DY XQe6+tFIsF2WMxQL0mdtOS9kvSEbiHDN4k8OwKEnan2A9stEMitIiG32RCDGE5lH k7AvKNXS1cxPBKsoU+3hUzOihpMWCVhoxKK6KmrXdNIMbdmQLZxBv/53X1xaUHC+ vGEoqqCJ9Pgwx+BxJEXTq5j/g3Q9YDFzl0kkoMgQlrQ+MQCBkbrJK2s66Ro7WpY1 dzcCCj0JUHspjAHbQWx92rYSWtOUYlVjqUiEUkREKa8EJ6mi1hP68USBMEq4tyUN dhhNRotL1V1InAZ/mFI5vyG72LUjsQ== =f4pJ -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2023-06-01' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v6.5: UAPI Changes: Cross-subsystem Changes: * fbdev: * Add Kconfig options and initializer macros for file I/O, convert DRM fbdev emulation Core Changes: * Unify handling of struct file_operations.show_fdinfo * Use .probe in all i2c code (interface cleanup) * TTM: * Remove unused code Driver Changes: * amdgpu: * Use shared show_fdinfo code * Fix building without procfs * bridge: * display-conenctor: Add support for external power supply * samsung-dsim: Fix enabling; Support variable clocking * tc358767: Fixes * ti-sn65dsi83: Fix enabling * msm: * Use shared show_fdinfo code * msxfb: * Add support for i.MX93 LCDIF * panel: * Add support for Ampire AM-800480L1TMQW-T00H plus DT bindings * panel-edp: Convert .remove to return void * stm: * dsi: Use devm_ helper * ltdc: Fix potential invalid pointer deref Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20230601112246.GA10882@linux-uq9g
This commit is contained in:
commit
2e1492835e
@ -70,7 +70,9 @@ properties:
|
||||
samsung,burst-clock-frequency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
DSIM high speed burst mode frequency.
|
||||
DSIM high speed burst mode frequency. If absent,
|
||||
the pixel clock from the attached device or bridge
|
||||
will be used instead.
|
||||
|
||||
samsung,esc-clock-frequency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
@ -80,7 +82,8 @@ properties:
|
||||
samsung,pll-clock-frequency:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
description:
|
||||
DSIM oscillator clock frequency.
|
||||
DSIM oscillator clock frequency. If absent, the clock frequency
|
||||
of sclk_mipi will be used instead.
|
||||
|
||||
phys:
|
||||
maxItems: 1
|
||||
@ -100,7 +103,8 @@ properties:
|
||||
specified.
|
||||
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
DSI output port node to the panel or the next bridge
|
||||
in the chain.
|
||||
@ -134,9 +138,7 @@ required:
|
||||
- compatible
|
||||
- interrupts
|
||||
- reg
|
||||
- samsung,burst-clock-frequency
|
||||
- samsung,esc-clock-frequency
|
||||
- samsung,pll-clock-frequency
|
||||
|
||||
allOf:
|
||||
- $ref: ../dsi-controller.yaml#
|
||||
|
@ -36,6 +36,9 @@ properties:
|
||||
description: GPIO signal to enable DDC bus
|
||||
maxItems: 1
|
||||
|
||||
hdmi-pwr-supply:
|
||||
description: Power supply for the HDMI +5V Power pin
|
||||
|
||||
port:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Connection to controller providing HDMI signals
|
||||
|
@ -21,6 +21,7 @@ properties:
|
||||
- fsl,imx28-lcdif
|
||||
- fsl,imx6sx-lcdif
|
||||
- fsl,imx8mp-lcdif
|
||||
- fsl,imx93-lcdif
|
||||
- items:
|
||||
- enum:
|
||||
- fsl,imx6sl-lcdif
|
||||
@ -88,7 +89,9 @@ allOf:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: fsl,imx8mp-lcdif
|
||||
enum:
|
||||
- fsl,imx8mp-lcdif
|
||||
- fsl,imx93-lcdif
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
@ -107,6 +110,7 @@ allOf:
|
||||
enum:
|
||||
- fsl,imx6sx-lcdif
|
||||
- fsl,imx8mp-lcdif
|
||||
- fsl,imx93-lcdif
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
@ -123,6 +127,7 @@ allOf:
|
||||
- fsl,imx8mm-lcdif
|
||||
- fsl,imx8mn-lcdif
|
||||
- fsl,imx8mp-lcdif
|
||||
- fsl,imx93-lcdif
|
||||
then:
|
||||
required:
|
||||
- power-domains
|
||||
|
@ -33,6 +33,8 @@ properties:
|
||||
- ampire,am-1280800n3tzqw-t00h
|
||||
# Ampire AM-480272H3TMQW-T01H 4.3" WQVGA TFT LCD panel
|
||||
- ampire,am-480272h3tmqw-t01h
|
||||
# Ampire AM-800480L1TMQW-T00H 5" WVGA TFT LCD panel
|
||||
- ampire,am-800480l1tmqw-t00h
|
||||
# Ampire AM-800480R3TMQW-A1H 7.0" WVGA TFT LCD panel
|
||||
- ampire,am800480r3tmqwa1h
|
||||
# Ampire AM-800600P5TMQW-TB8H 8.0" SVGA TFT LCD panel
|
||||
|
@ -24,7 +24,7 @@ File format specification
|
||||
- All keys shall be prefixed with `drm-`.
|
||||
- Whitespace between the delimiter and first non-whitespace character shall be
|
||||
ignored when parsing.
|
||||
- Neither keys or values are allowed to contain whitespace characters.
|
||||
- Keys are not allowed to contain whitespace characters.
|
||||
- Numerical key value pairs can end with optional unit string.
|
||||
- Data type of the value is fixed as defined in the specification.
|
||||
|
||||
@ -39,12 +39,13 @@ Data types
|
||||
----------
|
||||
|
||||
- <uint> - Unsigned integer without defining the maximum value.
|
||||
- <str> - String excluding any above defined reserved characters or whitespace.
|
||||
- <keystr> - String excluding any above defined reserved characters or whitespace.
|
||||
- <valstr> - String.
|
||||
|
||||
Mandatory fully standardised keys
|
||||
---------------------------------
|
||||
|
||||
- drm-driver: <str>
|
||||
- drm-driver: <valstr>
|
||||
|
||||
String shall contain the name this driver registered as via the respective
|
||||
`struct drm_driver` data structure.
|
||||
@ -52,6 +53,9 @@ String shall contain the name this driver registered as via the respective
|
||||
Optional fully standardised keys
|
||||
--------------------------------
|
||||
|
||||
Identification
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
- drm-pdev: <aaaa:bb.cc.d>
|
||||
|
||||
For PCI devices this should contain the PCI slot address of the device in
|
||||
@ -69,10 +73,13 @@ scope of each device, in which case `drm-pdev` shall be present as well.
|
||||
Userspace should make sure to not double account any usage statistics by using
|
||||
the above described criteria in order to associate data to individual clients.
|
||||
|
||||
- drm-engine-<str>: <uint> ns
|
||||
Utilization
|
||||
^^^^^^^^^^^
|
||||
|
||||
- drm-engine-<keystr>: <uint> ns
|
||||
|
||||
GPUs usually contain multiple execution engines. Each shall be given a stable
|
||||
and unique name (str), with possible values documented in the driver specific
|
||||
and unique name (keystr), with possible values documented in the driver specific
|
||||
documentation.
|
||||
|
||||
Value shall be in specified time units which the respective GPU engine spent
|
||||
@ -84,31 +91,19 @@ larger value within a reasonable period. Upon observing a value lower than what
|
||||
was previously read, userspace is expected to stay with that larger previous
|
||||
value until a monotonic update is seen.
|
||||
|
||||
- drm-engine-capacity-<str>: <uint>
|
||||
- drm-engine-capacity-<keystr>: <uint>
|
||||
|
||||
Engine identifier string must be the same as the one specified in the
|
||||
drm-engine-<str> tag and shall contain a greater than zero number in case the
|
||||
drm-engine-<keystr> tag and shall contain a greater than zero number in case the
|
||||
exported engine corresponds to a group of identical hardware engines.
|
||||
|
||||
In the absence of this tag parser shall assume capacity of one. Zero capacity
|
||||
is not allowed.
|
||||
|
||||
- drm-memory-<str>: <uint> [KiB|MiB]
|
||||
|
||||
Each possible memory type which can be used to store buffer objects by the
|
||||
GPU in question shall be given a stable and unique name to be returned as the
|
||||
string here.
|
||||
|
||||
Value shall reflect the amount of storage currently consumed by the buffer
|
||||
object belong to this client, in the respective memory region.
|
||||
|
||||
Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
|
||||
indicating kibi- or mebi-bytes.
|
||||
|
||||
- drm-cycles-<str> <uint>
|
||||
- drm-cycles-<keystr>: <uint>
|
||||
|
||||
Engine identifier string must be the same as the one specified in the
|
||||
drm-engine-<str> tag and shall contain the number of busy cycles for the given
|
||||
drm-engine-<keystr> tag and shall contain the number of busy cycles for the given
|
||||
engine.
|
||||
|
||||
Values are not required to be constantly monotonic if it makes the driver
|
||||
@ -117,16 +112,60 @@ larger value within a reasonable period. Upon observing a value lower than what
|
||||
was previously read, userspace is expected to stay with that larger previous
|
||||
value until a monotonic update is seen.
|
||||
|
||||
- drm-maxfreq-<str> <uint> [Hz|MHz|KHz]
|
||||
- drm-maxfreq-<keystr>: <uint> [Hz|MHz|KHz]
|
||||
|
||||
Engine identifier string must be the same as the one specified in the
|
||||
drm-engine-<str> tag and shall contain the maximum frequency for the given
|
||||
engine. Taken together with drm-cycles-<str>, this can be used to calculate
|
||||
percentage utilization of the engine, whereas drm-engine-<str> only reflects
|
||||
drm-engine-<keystr> tag and shall contain the maximum frequency for the given
|
||||
engine. Taken together with drm-cycles-<keystr>, this can be used to calculate
|
||||
percentage utilization of the engine, whereas drm-engine-<keystr> only reflects
|
||||
time active without considering what frequency the engine is operating as a
|
||||
percentage of it's maximum frequency.
|
||||
|
||||
Memory
|
||||
^^^^^^
|
||||
|
||||
- drm-memory-<region>: <uint> [KiB|MiB]
|
||||
|
||||
Each possible memory type which can be used to store buffer objects by the
|
||||
GPU in question shall be given a stable and unique name to be returned as the
|
||||
string here. The name "memory" is reserved to refer to normal system memory.
|
||||
|
||||
Value shall reflect the amount of storage currently consumed by the buffer
|
||||
objects belong to this client, in the respective memory region.
|
||||
|
||||
Default unit shall be bytes with optional unit specifiers of 'KiB' or 'MiB'
|
||||
indicating kibi- or mebi-bytes.
|
||||
|
||||
- drm-shared-<region>: <uint> [KiB|MiB]
|
||||
|
||||
The total size of buffers that are shared with another file (ie. have more
|
||||
than a single handle).
|
||||
|
||||
- drm-total-<region>: <uint> [KiB|MiB]
|
||||
|
||||
The total size of buffers that including shared and private memory.
|
||||
|
||||
- drm-resident-<region>: <uint> [KiB|MiB]
|
||||
|
||||
The total size of buffers that are resident in the specified region.
|
||||
|
||||
- drm-purgeable-<region>: <uint> [KiB|MiB]
|
||||
|
||||
The total size of buffers that are purgeable.
|
||||
|
||||
- drm-active-<region>: <uint> [KiB|MiB]
|
||||
|
||||
The total size of buffers that are active on one or more engines.
|
||||
|
||||
Implementation Details
|
||||
======================
|
||||
|
||||
Drivers should use drm_show_fdinfo() in their `struct file_operations`, and
|
||||
implement &drm_driver.show_fdinfo if they wish to provide any stats which
|
||||
are not provided by drm_show_fdinfo(). But even driver specific stats should
|
||||
be documented above and where possible, aligned with other drivers.
|
||||
|
||||
Driver specific implementations
|
||||
===============================
|
||||
-------------------------------
|
||||
|
||||
:ref:`i915-usage-stats`
|
||||
|
@ -95,6 +95,7 @@ config DRM_KUNIT_TEST
|
||||
config DRM_KMS_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
select FB_SYS_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
|
||||
help
|
||||
CRTC helpers for KMS drivers.
|
||||
|
||||
@ -132,14 +133,6 @@ config DRM_FBDEV_EMULATION
|
||||
bool "Enable legacy fbdev support for your modesetting driver"
|
||||
depends on DRM_KMS_HELPER
|
||||
depends on FB=y || FB=DRM_KMS_HELPER
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
select FB_DEFERRED_IO
|
||||
select FB_SYS_FOPS
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
select FRAMEBUFFER_CONSOLE if !EXPERT
|
||||
select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
|
||||
default y
|
||||
@ -223,6 +216,7 @@ config DRM_TTM_HELPER
|
||||
config DRM_GEM_DMA_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
|
||||
help
|
||||
Choose this if you need the GEM DMA helper functions
|
||||
|
||||
|
@ -2747,7 +2747,7 @@ static const struct file_operations amdgpu_driver_kms_fops = {
|
||||
.compat_ioctl = amdgpu_kms_compat_ioctl,
|
||||
#endif
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show_fdinfo = amdgpu_show_fdinfo
|
||||
.show_fdinfo = drm_show_fdinfo,
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -2802,6 +2802,9 @@ static const struct drm_driver amdgpu_kms_driver = {
|
||||
.dumb_map_offset = amdgpu_mode_dumb_mmap,
|
||||
.fops = &amdgpu_driver_kms_fops,
|
||||
.release = &amdgpu_driver_release_kms,
|
||||
#ifdef CONFIG_PROC_FS
|
||||
.show_fdinfo = amdgpu_show_fdinfo,
|
||||
#endif
|
||||
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
|
||||
|
@ -53,9 +53,8 @@ static const char *amdgpu_ip_name[AMDGPU_HW_IP_NUM] = {
|
||||
[AMDGPU_HW_IP_VCN_JPEG] = "jpeg",
|
||||
};
|
||||
|
||||
void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
|
||||
void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
|
||||
{
|
||||
struct drm_file *file = f->private_data;
|
||||
struct amdgpu_device *adev = drm_to_adev(file->minor->dev);
|
||||
struct amdgpu_fpriv *fpriv = file->driver_priv;
|
||||
struct amdgpu_vm *vm = &fpriv->vm;
|
||||
@ -87,31 +86,30 @@ void amdgpu_show_fdinfo(struct seq_file *m, struct file *f)
|
||||
* ******************************************************************
|
||||
*/
|
||||
|
||||
seq_printf(m, "pasid:\t%u\n", fpriv->vm.pasid);
|
||||
seq_printf(m, "drm-driver:\t%s\n", file->minor->dev->driver->name);
|
||||
seq_printf(m, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
|
||||
seq_printf(m, "drm-client-id:\t%Lu\n", vm->immediate.fence_context);
|
||||
seq_printf(m, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
|
||||
seq_printf(m, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
|
||||
seq_printf(m, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
|
||||
seq_printf(m, "amd-memory-visible-vram:\t%llu KiB\n",
|
||||
drm_printf(p, "pasid:\t%u\n", fpriv->vm.pasid);
|
||||
drm_printf(p, "drm-driver:\t%s\n", file->minor->dev->driver->name);
|
||||
drm_printf(p, "drm-pdev:\t%04x:%02x:%02x.%d\n", domain, bus, dev, fn);
|
||||
drm_printf(p, "drm-client-id:\t%Lu\n", vm->immediate.fence_context);
|
||||
drm_printf(p, "drm-memory-vram:\t%llu KiB\n", stats.vram/1024UL);
|
||||
drm_printf(p, "drm-memory-gtt: \t%llu KiB\n", stats.gtt/1024UL);
|
||||
drm_printf(p, "drm-memory-cpu: \t%llu KiB\n", stats.cpu/1024UL);
|
||||
drm_printf(p, "amd-memory-visible-vram:\t%llu KiB\n",
|
||||
stats.visible_vram/1024UL);
|
||||
seq_printf(m, "amd-evicted-vram:\t%llu KiB\n",
|
||||
drm_printf(p, "amd-evicted-vram:\t%llu KiB\n",
|
||||
stats.evicted_vram/1024UL);
|
||||
seq_printf(m, "amd-evicted-visible-vram:\t%llu KiB\n",
|
||||
drm_printf(p, "amd-evicted-visible-vram:\t%llu KiB\n",
|
||||
stats.evicted_visible_vram/1024UL);
|
||||
seq_printf(m, "amd-requested-vram:\t%llu KiB\n",
|
||||
drm_printf(p, "amd-requested-vram:\t%llu KiB\n",
|
||||
stats.requested_vram/1024UL);
|
||||
seq_printf(m, "amd-requested-visible-vram:\t%llu KiB\n",
|
||||
drm_printf(p, "amd-requested-visible-vram:\t%llu KiB\n",
|
||||
stats.requested_visible_vram/1024UL);
|
||||
seq_printf(m, "amd-requested-gtt:\t%llu KiB\n",
|
||||
drm_printf(p, "amd-requested-gtt:\t%llu KiB\n",
|
||||
stats.requested_gtt/1024UL);
|
||||
|
||||
for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
|
||||
if (!usage[hw_ip])
|
||||
continue;
|
||||
|
||||
seq_printf(m, "drm-engine-%s:\t%Ld ns\n", amdgpu_ip_name[hw_ip],
|
||||
drm_printf(p, "drm-engine-%s:\t%Ld ns\n", amdgpu_ip_name[hw_ip],
|
||||
ktime_to_ns(usage[hw_ip]));
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,6 @@
|
||||
#include "amdgpu_ids.h"
|
||||
|
||||
uint32_t amdgpu_get_ip_count(struct amdgpu_device *adev, int id);
|
||||
void amdgpu_show_fdinfo(struct seq_file *m, struct file *f);
|
||||
void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file);
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,7 @@ config DRM_ARMADA
|
||||
tristate "DRM support for Marvell Armada SoCs"
|
||||
depends on DRM && HAVE_CLK && ARM && MMU
|
||||
select DRM_KMS_HELPER
|
||||
select FB_IO_HELPERS if DRM_FBDEV_EMULATION
|
||||
help
|
||||
Support the "LCD" controllers found on the Marvell Armada 510
|
||||
devices. There are two controllers on the device, each controller
|
||||
|
@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
@ -33,12 +34,8 @@ static void armada_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops armada_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
FB_DEFAULT_IO_OPS,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_read = drm_fb_helper_cfb_read,
|
||||
.fb_write = drm_fb_helper_cfb_write,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_destroy = armada_fbdev_fb_destroy,
|
||||
};
|
||||
|
||||
|
@ -227,6 +227,7 @@ config DRM_SAMSUNG_DSIM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_PANEL_BRIDGE
|
||||
select GENERIC_PHY_MIPI_DPHY
|
||||
help
|
||||
The Samsung MIPI DSIM bridge controller driver.
|
||||
This MIPI DSIM bridge can be found it on Exynos SoCs and
|
||||
|
@ -1393,7 +1393,7 @@ static struct i2c_driver adv7511_driver = {
|
||||
.of_match_table = adv7511_of_ids,
|
||||
},
|
||||
.id_table = adv7511_i2c_ids,
|
||||
.probe_new = adv7511_probe,
|
||||
.probe = adv7511_probe,
|
||||
.remove = adv7511_remove,
|
||||
};
|
||||
|
||||
|
@ -815,7 +815,7 @@ static struct i2c_driver anx6345_driver = {
|
||||
.name = "anx6345",
|
||||
.of_match_table = of_match_ptr(anx6345_match_table),
|
||||
},
|
||||
.probe_new = anx6345_i2c_probe,
|
||||
.probe = anx6345_i2c_probe,
|
||||
.remove = anx6345_i2c_remove,
|
||||
.id_table = anx6345_id,
|
||||
};
|
||||
|
@ -1389,7 +1389,7 @@ static struct i2c_driver anx78xx_driver = {
|
||||
.name = "anx7814",
|
||||
.of_match_table = of_match_ptr(anx78xx_match_table),
|
||||
},
|
||||
.probe_new = anx78xx_i2c_probe,
|
||||
.probe = anx78xx_i2c_probe,
|
||||
.remove = anx78xx_i2c_remove,
|
||||
.id_table = anx78xx_id,
|
||||
};
|
||||
|
@ -2800,7 +2800,7 @@ static struct i2c_driver anx7625_driver = {
|
||||
.of_match_table = anx_match_table,
|
||||
.pm = &anx7625_pm_ops,
|
||||
},
|
||||
.probe_new = anx7625_i2c_probe,
|
||||
.probe = anx7625_i2c_probe,
|
||||
.remove = anx7625_i2c_remove,
|
||||
|
||||
.id_table = anx7625_id,
|
||||
|
@ -795,7 +795,7 @@ static struct i2c_device_id chipone_i2c_id[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, chipone_i2c_id);
|
||||
|
||||
static struct i2c_driver chipone_i2c_driver = {
|
||||
.probe_new = chipone_i2c_probe,
|
||||
.probe = chipone_i2c_probe,
|
||||
.id_table = chipone_i2c_id,
|
||||
.driver = {
|
||||
.name = "chipone-icn6211-i2c",
|
||||
|
@ -603,7 +603,7 @@ static const struct i2c_device_id ch7033_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, ch7033_ids);
|
||||
|
||||
static struct i2c_driver ch7033_driver = {
|
||||
.probe_new = ch7033_probe,
|
||||
.probe = ch7033_probe,
|
||||
.remove = ch7033_remove,
|
||||
.driver = {
|
||||
.name = "ch7033",
|
||||
|
@ -173,7 +173,7 @@ static const struct of_device_id cros_ec_anx7688_bridge_match_table[] = {
|
||||
MODULE_DEVICE_TABLE(of, cros_ec_anx7688_bridge_match_table);
|
||||
|
||||
static struct i2c_driver cros_ec_anx7688_bridge_driver = {
|
||||
.probe_new = cros_ec_anx7688_bridge_probe,
|
||||
.probe = cros_ec_anx7688_bridge_probe,
|
||||
.remove = cros_ec_anx7688_bridge_remove,
|
||||
.driver = {
|
||||
.name = "cros-ec-anx7688-bridge",
|
||||
|
@ -24,7 +24,7 @@ struct display_connector {
|
||||
struct gpio_desc *hpd_gpio;
|
||||
int hpd_irq;
|
||||
|
||||
struct regulator *dp_pwr;
|
||||
struct regulator *supply;
|
||||
struct gpio_desc *ddc_en;
|
||||
};
|
||||
|
||||
@ -191,6 +191,18 @@ static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int display_connector_get_supply(struct platform_device *pdev,
|
||||
struct display_connector *conn,
|
||||
const char *name)
|
||||
{
|
||||
conn->supply = devm_regulator_get_optional(&pdev->dev, name);
|
||||
|
||||
if (conn->supply == ERR_PTR(-ENODEV))
|
||||
conn->supply = NULL;
|
||||
|
||||
return PTR_ERR_OR_ZERO(conn->supply);
|
||||
}
|
||||
|
||||
static int display_connector_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct display_connector *conn;
|
||||
@ -316,36 +328,15 @@ static int display_connector_probe(struct platform_device *pdev)
|
||||
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;
|
||||
}
|
||||
}
|
||||
ret = display_connector_get_supply(pdev, conn, "dp-pwr");
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n");
|
||||
}
|
||||
|
||||
/* enable DDC */
|
||||
if (type == DRM_MODE_CONNECTOR_HDMIA) {
|
||||
int ret;
|
||||
|
||||
conn->ddc_en = devm_gpiod_get_optional(&pdev->dev, "ddc-en",
|
||||
GPIOD_OUT_HIGH);
|
||||
|
||||
@ -353,6 +344,18 @@ static int display_connector_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n");
|
||||
return PTR_ERR(conn->ddc_en);
|
||||
}
|
||||
|
||||
ret = display_connector_get_supply(pdev, conn, "hdmi-pwr");
|
||||
if (ret < 0)
|
||||
return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n");
|
||||
}
|
||||
|
||||
if (conn->supply) {
|
||||
ret = regulator_enable(conn->supply);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
conn->bridge.funcs = &display_connector_bridge_funcs;
|
||||
@ -386,8 +389,8 @@ static void display_connector_remove(struct platform_device *pdev)
|
||||
if (conn->ddc_en)
|
||||
gpiod_set_value(conn->ddc_en, 0);
|
||||
|
||||
if (conn->dp_pwr)
|
||||
regulator_disable(conn->dp_pwr);
|
||||
if (conn->supply)
|
||||
regulator_disable(conn->supply);
|
||||
|
||||
drm_bridge_remove(&conn->bridge);
|
||||
|
||||
|
@ -3479,7 +3479,7 @@ static struct i2c_driver it6505_i2c_driver = {
|
||||
.of_match_table = it6505_of_match,
|
||||
.pm = &it6505_bridge_pm_ops,
|
||||
},
|
||||
.probe_new = it6505_i2c_probe,
|
||||
.probe = it6505_i2c_probe,
|
||||
.remove = it6505_i2c_remove,
|
||||
.shutdown = it6505_shutdown,
|
||||
.id_table = it6505_id,
|
||||
|
@ -1640,7 +1640,7 @@ static struct i2c_driver it66121_driver = {
|
||||
.name = "it66121",
|
||||
.of_match_table = it66121_dt_match,
|
||||
},
|
||||
.probe_new = it66121_probe,
|
||||
.probe = it66121_probe,
|
||||
.remove = it66121_remove,
|
||||
.id_table = it66121_id,
|
||||
};
|
||||
|
@ -773,7 +773,7 @@ static struct i2c_driver lt8912_i2c_driver = {
|
||||
.name = "lt8912",
|
||||
.of_match_table = lt8912_dt_match,
|
||||
},
|
||||
.probe_new = lt8912_probe,
|
||||
.probe = lt8912_probe,
|
||||
.remove = lt8912_remove,
|
||||
.id_table = lt8912_id,
|
||||
};
|
||||
|
@ -787,7 +787,7 @@ static const struct of_device_id lt9211_match_table[] = {
|
||||
MODULE_DEVICE_TABLE(of, lt9211_match_table);
|
||||
|
||||
static struct i2c_driver lt9211_driver = {
|
||||
.probe_new = lt9211_probe,
|
||||
.probe = lt9211_probe,
|
||||
.remove = lt9211_remove,
|
||||
.id_table = lt9211_id,
|
||||
.driver = {
|
||||
|
@ -1192,7 +1192,7 @@ static struct i2c_driver lt9611_driver = {
|
||||
.name = "lt9611",
|
||||
.of_match_table = lt9611_match_table,
|
||||
},
|
||||
.probe_new = lt9611_probe,
|
||||
.probe = lt9611_probe,
|
||||
.remove = lt9611_remove,
|
||||
.id_table = lt9611_id,
|
||||
};
|
||||
|
@ -1011,7 +1011,7 @@ static struct i2c_driver lt9611uxc_driver = {
|
||||
.of_match_table = lt9611uxc_match_table,
|
||||
.dev_groups = lt9611uxc_attr_groups,
|
||||
},
|
||||
.probe_new = lt9611uxc_probe,
|
||||
.probe = lt9611uxc_probe,
|
||||
.remove = lt9611uxc_remove,
|
||||
.id_table = lt9611uxc_id,
|
||||
};
|
||||
|
@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match);
|
||||
|
||||
static struct i2c_driver stdp4028_ge_b850v3_fw_driver = {
|
||||
.id_table = stdp4028_ge_b850v3_fw_i2c_table,
|
||||
.probe_new = stdp4028_ge_b850v3_fw_probe,
|
||||
.probe = stdp4028_ge_b850v3_fw_probe,
|
||||
.remove = stdp4028_ge_b850v3_fw_remove,
|
||||
.driver = {
|
||||
.name = "stdp4028-ge-b850v3-fw",
|
||||
@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match);
|
||||
|
||||
static struct i2c_driver stdp2690_ge_b850v3_fw_driver = {
|
||||
.id_table = stdp2690_ge_b850v3_fw_i2c_table,
|
||||
.probe_new = stdp2690_ge_b850v3_fw_probe,
|
||||
.probe = stdp2690_ge_b850v3_fw_probe,
|
||||
.remove = stdp2690_ge_b850v3_fw_remove,
|
||||
.driver = {
|
||||
.name = "stdp2690-ge-b850v3-fw",
|
||||
|
@ -335,7 +335,7 @@ MODULE_DEVICE_TABLE(of, ptn3460_match);
|
||||
|
||||
static struct i2c_driver ptn3460_driver = {
|
||||
.id_table = ptn3460_i2c_table,
|
||||
.probe_new = ptn3460_probe,
|
||||
.probe = ptn3460_probe,
|
||||
.remove = ptn3460_remove,
|
||||
.driver = {
|
||||
.name = "nxp,ptn3460",
|
||||
|
@ -538,7 +538,7 @@ MODULE_DEVICE_TABLE(i2c, ps8622_i2c_table);
|
||||
|
||||
static struct i2c_driver ps8622_driver = {
|
||||
.id_table = ps8622_i2c_table,
|
||||
.probe_new = ps8622_probe,
|
||||
.probe = ps8622_probe,
|
||||
.remove = ps8622_remove,
|
||||
.driver = {
|
||||
.name = "ps8622",
|
||||
|
@ -791,7 +791,7 @@ static const struct of_device_id ps8640_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, ps8640_match);
|
||||
|
||||
static struct i2c_driver ps8640_driver = {
|
||||
.probe_new = ps8640_probe,
|
||||
.probe = ps8640_probe,
|
||||
.remove = ps8640_remove,
|
||||
.driver = {
|
||||
.name = "ps8640",
|
||||
|
@ -220,6 +220,8 @@
|
||||
|
||||
#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
|
||||
|
||||
#define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL)
|
||||
|
||||
static const char *const clk_names[5] = {
|
||||
"bus_clk",
|
||||
"sclk_mipi",
|
||||
@ -407,6 +409,9 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
|
||||
.num_bits_resol = 11,
|
||||
.pll_p_offset = 13,
|
||||
.reg_values = reg_values,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
|
||||
@ -420,6 +425,9 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
|
||||
.num_bits_resol = 11,
|
||||
.pll_p_offset = 13,
|
||||
.reg_values = reg_values,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
|
||||
@ -431,6 +439,9 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
|
||||
.num_bits_resol = 11,
|
||||
.pll_p_offset = 13,
|
||||
.reg_values = reg_values,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
|
||||
@ -443,6 +454,9 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
|
||||
.num_bits_resol = 12,
|
||||
.pll_p_offset = 13,
|
||||
.reg_values = exynos5433_reg_values,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
|
||||
@ -455,6 +469,9 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
|
||||
.num_bits_resol = 12,
|
||||
.pll_p_offset = 13,
|
||||
.reg_values = exynos5422_reg_values,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
|
||||
@ -471,6 +488,9 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
|
||||
*/
|
||||
.pll_p_offset = 14,
|
||||
.reg_values = imx8mm_dsim_reg_values,
|
||||
.m_min = 64,
|
||||
.m_max = 1023,
|
||||
.min_freq = 1050,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data *
|
||||
@ -549,12 +569,12 @@ static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi,
|
||||
tmp = (u64)fout * (_p << _s);
|
||||
do_div(tmp, fin);
|
||||
_m = tmp;
|
||||
if (_m < 41 || _m > 125)
|
||||
if (_m < driver_data->m_min || _m > driver_data->m_max)
|
||||
continue;
|
||||
|
||||
tmp = (u64)_m * fin;
|
||||
do_div(tmp, _p);
|
||||
if (tmp < 500 * MHZ ||
|
||||
if (tmp < driver_data->min_freq * MHZ ||
|
||||
tmp > driver_data->max_freq * MHZ)
|
||||
continue;
|
||||
|
||||
@ -640,16 +660,28 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
|
||||
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
|
||||
} while ((reg & DSIM_PLL_STABLE) == 0);
|
||||
|
||||
dsi->hs_clock = fout;
|
||||
|
||||
return fout;
|
||||
}
|
||||
|
||||
static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
|
||||
{
|
||||
unsigned long hs_clk, byte_clk, esc_clk;
|
||||
unsigned long hs_clk, byte_clk, esc_clk, pix_clk;
|
||||
unsigned long esc_div;
|
||||
u32 reg;
|
||||
struct drm_display_mode *m = &dsi->mode;
|
||||
int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
|
||||
|
||||
/* m->clock is in KHz */
|
||||
pix_clk = m->clock * 1000;
|
||||
|
||||
/* Use burst_clk_rate if available, otherwise use the pix_clk */
|
||||
if (dsi->burst_clk_rate)
|
||||
hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
|
||||
else
|
||||
hs_clk = samsung_dsim_set_pll(dsi, DIV_ROUND_UP(pix_clk * bpp, dsi->lanes));
|
||||
|
||||
hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
|
||||
if (!hs_clk) {
|
||||
dev_err(dsi->dev, "failed to configure DSI PLL\n");
|
||||
return -EFAULT;
|
||||
@ -687,13 +719,47 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
const unsigned int *reg_values = driver_data->reg_values;
|
||||
u32 reg;
|
||||
struct phy_configure_opts_mipi_dphy cfg;
|
||||
int clk_prepare, lpx, clk_zero, clk_post, clk_trail;
|
||||
int hs_exit, hs_prepare, hs_zero, hs_trail;
|
||||
unsigned long long byte_clock = dsi->hs_clock / 8;
|
||||
|
||||
if (driver_data->has_freqband)
|
||||
return;
|
||||
|
||||
phy_mipi_dphy_get_default_config_for_hsclk(dsi->hs_clock,
|
||||
dsi->lanes, &cfg);
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* The tech Applications Processor manuals for i.MX8M Mini, Nano,
|
||||
* and Plus don't state what the definition of the PHYTIMING
|
||||
* bits are beyond their address and bit position.
|
||||
* After reviewing NXP's downstream code, it appears
|
||||
* that the various PHYTIMING registers take the number
|
||||
* of cycles and use various dividers on them. This
|
||||
* calculation does not result in an exact match to the
|
||||
* downstream code, but it is very close to the values
|
||||
* generated by their lookup table, and it appears
|
||||
* to sync at a variety of resolutions. If someone
|
||||
* can get a more accurate mathematical equation needed
|
||||
* for these registers, this should be updated.
|
||||
*/
|
||||
|
||||
lpx = PS_TO_CYCLE(cfg.lpx, byte_clock);
|
||||
hs_exit = PS_TO_CYCLE(cfg.hs_exit, byte_clock);
|
||||
clk_prepare = PS_TO_CYCLE(cfg.clk_prepare, byte_clock);
|
||||
clk_zero = PS_TO_CYCLE(cfg.clk_zero, byte_clock);
|
||||
clk_post = PS_TO_CYCLE(cfg.clk_post, byte_clock);
|
||||
clk_trail = PS_TO_CYCLE(cfg.clk_trail, byte_clock);
|
||||
hs_prepare = PS_TO_CYCLE(cfg.hs_prepare, byte_clock);
|
||||
hs_zero = PS_TO_CYCLE(cfg.hs_zero, byte_clock);
|
||||
hs_trail = PS_TO_CYCLE(cfg.hs_trail, byte_clock);
|
||||
|
||||
/* B D-PHY: D-PHY Master & Slave Analog Block control */
|
||||
reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] |
|
||||
reg_values[PHYCTRL_SLEW_UP];
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
|
||||
|
||||
/*
|
||||
@ -701,7 +767,9 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
|
||||
* T HS-EXIT: Time that the transmitter drives LP-11 following a HS
|
||||
* burst
|
||||
*/
|
||||
reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
|
||||
|
||||
reg = DSIM_PHYTIMING_LPX(lpx) | DSIM_PHYTIMING_HS_EXIT(hs_exit);
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
|
||||
|
||||
/*
|
||||
@ -717,10 +785,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
|
||||
* T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
|
||||
* the last payload clock bit of a HS transmission burst
|
||||
*/
|
||||
reg = reg_values[PHYTIMING_CLK_PREPARE] |
|
||||
reg_values[PHYTIMING_CLK_ZERO] |
|
||||
reg_values[PHYTIMING_CLK_POST] |
|
||||
reg_values[PHYTIMING_CLK_TRAIL];
|
||||
|
||||
reg = DSIM_PHYTIMING1_CLK_PREPARE(clk_prepare) |
|
||||
DSIM_PHYTIMING1_CLK_ZERO(clk_zero) |
|
||||
DSIM_PHYTIMING1_CLK_POST(clk_post) |
|
||||
DSIM_PHYTIMING1_CLK_TRAIL(clk_trail);
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
|
||||
|
||||
@ -733,8 +802,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
|
||||
* T HS-TRAIL: Time that the transmitter drives the flipped differential
|
||||
* state after last payload data bit of a HS transmission burst
|
||||
*/
|
||||
reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
|
||||
reg_values[PHYTIMING_HS_TRAIL];
|
||||
|
||||
reg = DSIM_PHYTIMING2_HS_PREPARE(hs_prepare) |
|
||||
DSIM_PHYTIMING2_HS_ZERO(hs_zero) |
|
||||
DSIM_PHYTIMING2_HS_TRAIL(hs_trail);
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg);
|
||||
}
|
||||
|
||||
@ -866,6 +938,10 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
|
||||
reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
|
||||
reg &= ~DSIM_STOP_STATE_CNT_MASK;
|
||||
reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]);
|
||||
|
||||
if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
|
||||
reg |= DSIM_FORCE_STOP_STATE;
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
|
||||
|
||||
reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
|
||||
@ -881,17 +957,29 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
|
||||
u32 reg;
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
int byte_clk_khz = dsi->hs_clock / 1000 / 8;
|
||||
int hfp = (m->hsync_start - m->hdisplay) * byte_clk_khz / m->clock;
|
||||
int hbp = (m->htotal - m->hsync_end) * byte_clk_khz / m->clock;
|
||||
int hsa = (m->hsync_end - m->hsync_start) * byte_clk_khz / m->clock;
|
||||
|
||||
/* remove packet overhead when possible */
|
||||
hfp = max(hfp - 6, 0);
|
||||
hbp = max(hbp - 6, 0);
|
||||
hsa = max(hsa - 6, 0);
|
||||
|
||||
dev_dbg(dsi->dev, "calculated hfp: %u, hbp: %u, hsa: %u",
|
||||
hfp, hbp, hsa);
|
||||
|
||||
reg = DSIM_CMD_ALLOW(0xf)
|
||||
| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
|
||||
| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
|
||||
samsung_dsim_write(dsi, DSIM_MVPORCH_REG, reg);
|
||||
|
||||
reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay)
|
||||
| DSIM_MAIN_HBP(m->htotal - m->hsync_end);
|
||||
reg = DSIM_MAIN_HFP(hfp) | DSIM_MAIN_HBP(hbp);
|
||||
samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
|
||||
|
||||
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
|
||||
| DSIM_MAIN_HSA(m->hsync_end - m->hsync_start);
|
||||
| DSIM_MAIN_HSA(hsa);
|
||||
samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg);
|
||||
}
|
||||
reg = DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) |
|
||||
@ -1347,6 +1435,9 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
ret = samsung_dsim_init(dsi);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
samsung_dsim_set_display_mode(dsi);
|
||||
samsung_dsim_set_display_enable(dsi, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1354,9 +1445,16 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
u32 reg;
|
||||
|
||||
samsung_dsim_set_display_mode(dsi);
|
||||
samsung_dsim_set_display_enable(dsi, true);
|
||||
if (samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
|
||||
samsung_dsim_set_display_mode(dsi);
|
||||
samsung_dsim_set_display_enable(dsi, true);
|
||||
} else {
|
||||
reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
|
||||
reg &= ~DSIM_FORCE_STOP_STATE;
|
||||
samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
|
||||
}
|
||||
|
||||
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
|
||||
}
|
||||
@ -1365,10 +1463,17 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
u32 reg;
|
||||
|
||||
if (!(dsi->state & DSIM_STATE_ENABLED))
|
||||
return;
|
||||
|
||||
if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
|
||||
reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
|
||||
reg |= DSIM_FORCE_STOP_STATE;
|
||||
samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
|
||||
}
|
||||
|
||||
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
|
||||
}
|
||||
|
||||
@ -1689,11 +1794,11 @@ static const struct mipi_dsi_host_ops samsung_dsim_ops = {
|
||||
};
|
||||
|
||||
static int samsung_dsim_of_read_u32(const struct device_node *np,
|
||||
const char *propname, u32 *out_value)
|
||||
const char *propname, u32 *out_value, bool optional)
|
||||
{
|
||||
int ret = of_property_read_u32(np, propname, out_value);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret < 0 && !optional)
|
||||
pr_err("%pOF: failed to get '%s' property\n", np, propname);
|
||||
|
||||
return ret;
|
||||
@ -1706,19 +1811,30 @@ static int samsung_dsim_parse_dt(struct samsung_dsim *dsi)
|
||||
u32 lane_polarities[5] = { 0 };
|
||||
struct device_node *endpoint;
|
||||
int i, nr_lanes, ret;
|
||||
struct clk *pll_clk;
|
||||
|
||||
ret = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency",
|
||||
&dsi->pll_clk_rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
&dsi->pll_clk_rate, 1);
|
||||
/* If it doesn't exist, read it from the clock instead of failing */
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev, "Using sclk_mipi for pll clock frequency\n");
|
||||
pll_clk = devm_clk_get(dev, "sclk_mipi");
|
||||
if (!IS_ERR(pll_clk))
|
||||
dsi->pll_clk_rate = clk_get_rate(pll_clk);
|
||||
else
|
||||
return PTR_ERR(pll_clk);
|
||||
}
|
||||
|
||||
/* If it doesn't exist, use pixel clock instead of failing */
|
||||
ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency",
|
||||
&dsi->burst_clk_rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
&dsi->burst_clk_rate, 1);
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev, "Using pixel clock for HS clock frequency\n");
|
||||
dsi->burst_clk_rate = 0;
|
||||
}
|
||||
|
||||
ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency",
|
||||
&dsi->esc_clk_rate);
|
||||
&dsi->esc_clk_rate, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ static const struct i2c_device_id sii902x_i2c_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, sii902x_i2c_ids);
|
||||
|
||||
static struct i2c_driver sii902x_driver = {
|
||||
.probe_new = sii902x_probe,
|
||||
.probe = sii902x_probe,
|
||||
.remove = sii902x_remove,
|
||||
.driver = {
|
||||
.name = "sii902x",
|
||||
|
@ -955,7 +955,7 @@ static struct i2c_driver sii9234_driver = {
|
||||
.name = "sii9234",
|
||||
.of_match_table = sii9234_dt_match,
|
||||
},
|
||||
.probe_new = sii9234_probe,
|
||||
.probe = sii9234_probe,
|
||||
.remove = sii9234_remove,
|
||||
.id_table = sii9234_id,
|
||||
};
|
||||
|
@ -2378,7 +2378,7 @@ static struct i2c_driver sii8620_driver = {
|
||||
.name = "sii8620",
|
||||
.of_match_table = of_match_ptr(sii8620_dt_match),
|
||||
},
|
||||
.probe_new = sii8620_probe,
|
||||
.probe = sii8620_probe,
|
||||
.remove = sii8620_remove,
|
||||
.id_table = sii8620_id,
|
||||
};
|
||||
|
@ -1781,7 +1781,200 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
|
||||
|
||||
static bool tc_readable_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg != SYSCTRL;
|
||||
switch (reg) {
|
||||
/* DSI D-PHY Layer */
|
||||
case 0x004:
|
||||
case 0x020:
|
||||
case 0x024:
|
||||
case 0x028:
|
||||
case 0x02c:
|
||||
case 0x030:
|
||||
case 0x038:
|
||||
case 0x040:
|
||||
case 0x044:
|
||||
case 0x048:
|
||||
case 0x04c:
|
||||
case 0x050:
|
||||
case 0x054:
|
||||
/* DSI PPI Layer */
|
||||
case PPI_STARTPPI:
|
||||
case 0x108:
|
||||
case 0x110:
|
||||
case PPI_LPTXTIMECNT:
|
||||
case PPI_LANEENABLE:
|
||||
case PPI_TX_RX_TA:
|
||||
case 0x140:
|
||||
case PPI_D0S_ATMR:
|
||||
case PPI_D1S_ATMR:
|
||||
case 0x14c:
|
||||
case 0x150:
|
||||
case PPI_D0S_CLRSIPOCOUNT:
|
||||
case PPI_D1S_CLRSIPOCOUNT:
|
||||
case PPI_D2S_CLRSIPOCOUNT:
|
||||
case PPI_D3S_CLRSIPOCOUNT:
|
||||
case 0x180:
|
||||
case 0x184:
|
||||
case 0x188:
|
||||
case 0x18c:
|
||||
case 0x190:
|
||||
case 0x1a0:
|
||||
case 0x1a4:
|
||||
case 0x1a8:
|
||||
case 0x1ac:
|
||||
case 0x1b0:
|
||||
case 0x1c0:
|
||||
case 0x1c4:
|
||||
case 0x1c8:
|
||||
case 0x1cc:
|
||||
case 0x1d0:
|
||||
case 0x1e0:
|
||||
case 0x1e4:
|
||||
case 0x1f0:
|
||||
case 0x1f4:
|
||||
/* DSI Protocol Layer */
|
||||
case DSI_STARTDSI:
|
||||
case 0x208:
|
||||
case DSI_LANEENABLE:
|
||||
case 0x214:
|
||||
case 0x218:
|
||||
case 0x220:
|
||||
case 0x224:
|
||||
case 0x228:
|
||||
case 0x230:
|
||||
/* DSI General */
|
||||
case 0x300:
|
||||
/* DSI Application Layer */
|
||||
case 0x400:
|
||||
case 0x404:
|
||||
/* DPI */
|
||||
case DPIPXLFMT:
|
||||
/* Parallel Output */
|
||||
case POCTRL:
|
||||
/* Video Path0 Configuration */
|
||||
case VPCTRL0:
|
||||
case HTIM01:
|
||||
case HTIM02:
|
||||
case VTIM01:
|
||||
case VTIM02:
|
||||
case VFUEN0:
|
||||
/* System */
|
||||
case TC_IDREG:
|
||||
case 0x504:
|
||||
case SYSSTAT:
|
||||
case SYSRSTENB:
|
||||
case SYSCTRL:
|
||||
/* I2C */
|
||||
case 0x520:
|
||||
/* GPIO */
|
||||
case GPIOM:
|
||||
case GPIOC:
|
||||
case GPIOO:
|
||||
case GPIOI:
|
||||
/* Interrupt */
|
||||
case INTCTL_G:
|
||||
case INTSTS_G:
|
||||
case 0x570:
|
||||
case 0x574:
|
||||
case INT_GP0_LCNT:
|
||||
case INT_GP1_LCNT:
|
||||
/* DisplayPort Control */
|
||||
case DP0CTL:
|
||||
/* DisplayPort Clock */
|
||||
case DP0_VIDMNGEN0:
|
||||
case DP0_VIDMNGEN1:
|
||||
case DP0_VMNGENSTATUS:
|
||||
case 0x628:
|
||||
case 0x62c:
|
||||
case 0x630:
|
||||
/* DisplayPort Main Channel */
|
||||
case DP0_SECSAMPLE:
|
||||
case DP0_VIDSYNCDELAY:
|
||||
case DP0_TOTALVAL:
|
||||
case DP0_STARTVAL:
|
||||
case DP0_ACTIVEVAL:
|
||||
case DP0_SYNCVAL:
|
||||
case DP0_MISC:
|
||||
/* DisplayPort Aux Channel */
|
||||
case DP0_AUXCFG0:
|
||||
case DP0_AUXCFG1:
|
||||
case DP0_AUXADDR:
|
||||
case 0x66c:
|
||||
case 0x670:
|
||||
case 0x674:
|
||||
case 0x678:
|
||||
case 0x67c:
|
||||
case 0x680:
|
||||
case 0x684:
|
||||
case 0x688:
|
||||
case DP0_AUXSTATUS:
|
||||
case DP0_AUXI2CADR:
|
||||
/* DisplayPort Link Training */
|
||||
case DP0_SRCCTRL:
|
||||
case DP0_LTSTAT:
|
||||
case DP0_SNKLTCHGREQ:
|
||||
case DP0_LTLOOPCTRL:
|
||||
case DP0_SNKLTCTRL:
|
||||
case 0x6e8:
|
||||
case 0x6ec:
|
||||
case 0x6f0:
|
||||
case 0x6f4:
|
||||
/* DisplayPort Audio */
|
||||
case 0x700:
|
||||
case 0x704:
|
||||
case 0x708:
|
||||
case 0x70c:
|
||||
case 0x710:
|
||||
case 0x714:
|
||||
case 0x718:
|
||||
case 0x71c:
|
||||
case 0x720:
|
||||
/* DisplayPort Source Control */
|
||||
case DP1_SRCCTRL:
|
||||
/* DisplayPort PHY */
|
||||
case DP_PHY_CTRL:
|
||||
case 0x810:
|
||||
case 0x814:
|
||||
case 0x820:
|
||||
case 0x840:
|
||||
/* I2S */
|
||||
case 0x880:
|
||||
case 0x888:
|
||||
case 0x88c:
|
||||
case 0x890:
|
||||
case 0x894:
|
||||
case 0x898:
|
||||
case 0x89c:
|
||||
case 0x8a0:
|
||||
case 0x8a4:
|
||||
case 0x8a8:
|
||||
case 0x8ac:
|
||||
case 0x8b0:
|
||||
case 0x8b4:
|
||||
/* PLL */
|
||||
case DP0_PLLCTRL:
|
||||
case DP1_PLLCTRL:
|
||||
case PXL_PLLCTRL:
|
||||
case PXL_PLLPARAM:
|
||||
case SYS_PLLPARAM:
|
||||
/* HDCP */
|
||||
case 0x980:
|
||||
case 0x984:
|
||||
case 0x988:
|
||||
case 0x98c:
|
||||
case 0x990:
|
||||
case 0x994:
|
||||
case 0x998:
|
||||
case 0x99c:
|
||||
case 0x9a0:
|
||||
case 0x9a4:
|
||||
case 0x9a8:
|
||||
case 0x9ac:
|
||||
/* Debug */
|
||||
case TSTCTL:
|
||||
case PLL_DBG:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static const struct regmap_range tc_volatile_ranges[] = {
|
||||
@ -2209,7 +2402,7 @@ static struct i2c_driver tc358767_driver = {
|
||||
.of_match_table = tc358767_of_ids,
|
||||
},
|
||||
.id_table = tc358767_i2c_ids,
|
||||
.probe_new = tc_probe,
|
||||
.probe = tc_probe,
|
||||
.remove = tc_remove,
|
||||
};
|
||||
module_i2c_driver(tc358767_driver);
|
||||
|
@ -1134,7 +1134,7 @@ static struct i2c_driver tc358768_driver = {
|
||||
.of_match_table = tc358768_of_ids,
|
||||
},
|
||||
.id_table = tc358768_i2c_ids,
|
||||
.probe_new = tc358768_i2c_probe,
|
||||
.probe = tc358768_i2c_probe,
|
||||
.remove = tc358768_i2c_remove,
|
||||
};
|
||||
module_i2c_driver(tc358768_driver);
|
||||
|
@ -728,7 +728,7 @@ static struct i2c_driver tc358775_driver = {
|
||||
.of_match_table = tc358775_of_ids,
|
||||
},
|
||||
.id_table = tc358775_i2c_ids,
|
||||
.probe_new = tc_probe,
|
||||
.probe = tc_probe,
|
||||
.remove = tc_remove,
|
||||
};
|
||||
module_i2c_driver(tc358775_driver);
|
||||
|
@ -400,7 +400,7 @@ static const struct of_device_id dlpc3433_match_table[] = {
|
||||
MODULE_DEVICE_TABLE(of, dlpc3433_match_table);
|
||||
|
||||
static struct i2c_driver dlpc3433_driver = {
|
||||
.probe_new = dlpc3433_probe,
|
||||
.probe = dlpc3433_probe,
|
||||
.remove = dlpc3433_remove,
|
||||
.id_table = dlpc3433_id,
|
||||
.driver = {
|
||||
|
@ -321,8 +321,8 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
|
||||
return dsi_div - 1;
|
||||
}
|
||||
|
||||
static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
@ -485,11 +485,22 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
/* Trigger reset after CSR register update. */
|
||||
regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET);
|
||||
|
||||
/* Wait for 10ms after soft reset as specified in datasheet */
|
||||
usleep_range(10000, 12000);
|
||||
}
|
||||
|
||||
static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
unsigned int pval;
|
||||
|
||||
/* Clear all errors that got asserted during initialization. */
|
||||
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
|
||||
regmap_write(ctx->regmap, REG_IRQ_STAT, pval);
|
||||
|
||||
usleep_range(10000, 12000);
|
||||
/* Wait for 1ms and check for errors in status register */
|
||||
usleep_range(1000, 1100);
|
||||
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
|
||||
if (pval)
|
||||
dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval);
|
||||
@ -556,6 +567,7 @@ static const struct drm_bridge_funcs sn65dsi83_funcs = {
|
||||
.attach = sn65dsi83_attach,
|
||||
.detach = sn65dsi83_detach,
|
||||
.atomic_enable = sn65dsi83_atomic_enable,
|
||||
.atomic_pre_enable = sn65dsi83_atomic_pre_enable,
|
||||
.atomic_disable = sn65dsi83_atomic_disable,
|
||||
.mode_valid = sn65dsi83_mode_valid,
|
||||
|
||||
@ -698,6 +710,7 @@ static int sn65dsi83_probe(struct i2c_client *client)
|
||||
|
||||
ctx->bridge.funcs = &sn65dsi83_funcs;
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
ctx->bridge.pre_enable_prev_first = true;
|
||||
drm_bridge_add(&ctx->bridge);
|
||||
|
||||
ret = sn65dsi83_host_attach(ctx);
|
||||
@ -735,7 +748,7 @@ static const struct of_device_id sn65dsi83_match_table[] = {
|
||||
MODULE_DEVICE_TABLE(of, sn65dsi83_match_table);
|
||||
|
||||
static struct i2c_driver sn65dsi83_driver = {
|
||||
.probe_new = sn65dsi83_probe,
|
||||
.probe = sn65dsi83_probe,
|
||||
.remove = sn65dsi83_remove,
|
||||
.id_table = sn65dsi83_id,
|
||||
.driver = {
|
||||
|
@ -1970,7 +1970,7 @@ static struct i2c_driver ti_sn65dsi86_driver = {
|
||||
.of_match_table = ti_sn65dsi86_match_table,
|
||||
.pm = &ti_sn65dsi86_pm_ops,
|
||||
},
|
||||
.probe_new = ti_sn65dsi86_probe,
|
||||
.probe = ti_sn65dsi86_probe,
|
||||
.id_table = ti_sn65dsi86_id,
|
||||
};
|
||||
|
||||
|
@ -408,7 +408,7 @@ static struct i2c_driver tfp410_i2c_driver = {
|
||||
.of_match_table = of_match_ptr(tfp410_match),
|
||||
},
|
||||
.id_table = tfp410_i2c_ids,
|
||||
.probe_new = tfp410_i2c_probe,
|
||||
.probe = tfp410_i2c_probe,
|
||||
.remove = tfp410_i2c_remove,
|
||||
};
|
||||
#endif /* IS_ENABLED(CONFIG_I2C) */
|
||||
|
@ -670,6 +670,28 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off,
|
||||
drm_rect_init(clip, x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
/* Don't use in new code. */
|
||||
void drm_fb_helper_damage_range(struct fb_info *info, off_t off, size_t len)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_rect damage_area;
|
||||
|
||||
drm_fb_helper_memory_range_to_clip(info, off, len, &damage_area);
|
||||
drm_fb_helper_damage(fb_helper, damage_area.x1, damage_area.y1,
|
||||
drm_rect_width(&damage_area),
|
||||
drm_rect_height(&damage_area));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_damage_range);
|
||||
|
||||
/* Don't use in new code. */
|
||||
void drm_fb_helper_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
|
||||
drm_fb_helper_damage(fb_helper, x, y, width, height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_damage_area);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_deferred_io() - fbdev deferred_io callback function
|
||||
* @info: fb_info struct pointer
|
||||
@ -714,220 +736,6 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_deferred_io);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_read - Implements struct &fb_ops.fb_read for system memory
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to read from framebuffer memory
|
||||
* @count: number of bytes to read from framebuffer memory
|
||||
* @ppos: read offset within framebuffer memory
|
||||
*
|
||||
* Returns:
|
||||
* The number of bytes read on success, or an error code otherwise.
|
||||
*/
|
||||
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return fb_sys_read(info, buf, count, ppos);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_read);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_write - Implements struct &fb_ops.fb_write for system memory
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to write to framebuffer memory
|
||||
* @count: number of bytes to write to framebuffer memory
|
||||
* @ppos: write offset within framebuffer memory
|
||||
*
|
||||
* Returns:
|
||||
* The number of bytes written on success, or an error code otherwise.
|
||||
*/
|
||||
ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
loff_t pos = *ppos;
|
||||
ssize_t ret;
|
||||
struct drm_rect damage_area;
|
||||
|
||||
ret = fb_sys_write(info, buf, count, ppos);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (helper->funcs->fb_dirty) {
|
||||
drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
|
||||
drm_fb_helper_damage(helper, damage_area.x1, damage_area.y1,
|
||||
drm_rect_width(&damage_area),
|
||||
drm_rect_height(&damage_area));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_write);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_fillrect - wrapper around sys_fillrect
|
||||
* @info: fbdev registered by the helper
|
||||
* @rect: info about rectangle to fill
|
||||
*
|
||||
* A wrapper around sys_fillrect implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
sys_fillrect(info, rect);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, rect->dx, rect->dy, rect->width, rect->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_copyarea - wrapper around sys_copyarea
|
||||
* @info: fbdev registered by the helper
|
||||
* @area: info about area to copy
|
||||
*
|
||||
* A wrapper around sys_copyarea implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
sys_copyarea(info, area);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, area->dx, area->dy, area->width, area->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_sys_imageblit - wrapper around sys_imageblit
|
||||
* @info: fbdev registered by the helper
|
||||
* @image: info about image to blit
|
||||
*
|
||||
* A wrapper around sys_imageblit implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
sys_imageblit(info, image);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, image->dx, image->dy, image->width, image->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_read - Implements struct &fb_ops.fb_read for I/O memory
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to read from framebuffer memory
|
||||
* @count: number of bytes to read from framebuffer memory
|
||||
* @ppos: read offset within framebuffer memory
|
||||
*
|
||||
* Returns:
|
||||
* The number of bytes read on success, or an error code otherwise.
|
||||
*/
|
||||
ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return fb_io_read(info, buf, count, ppos);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_read);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_write - Implements struct &fb_ops.fb_write for I/O memory
|
||||
* @info: fb_info struct pointer
|
||||
* @buf: userspace buffer to write to framebuffer memory
|
||||
* @count: number of bytes to write to framebuffer memory
|
||||
* @ppos: write offset within framebuffer memory
|
||||
*
|
||||
* Returns:
|
||||
* The number of bytes written on success, or an error code otherwise.
|
||||
*/
|
||||
ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
loff_t pos = *ppos;
|
||||
ssize_t ret;
|
||||
struct drm_rect damage_area;
|
||||
|
||||
ret = fb_io_write(info, buf, count, ppos);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (helper->funcs->fb_dirty) {
|
||||
drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
|
||||
drm_fb_helper_damage(helper, damage_area.x1, damage_area.y1,
|
||||
drm_rect_width(&damage_area),
|
||||
drm_rect_height(&damage_area));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_write);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_fillrect - wrapper around cfb_fillrect
|
||||
* @info: fbdev registered by the helper
|
||||
* @rect: info about rectangle to fill
|
||||
*
|
||||
* A wrapper around cfb_fillrect implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
cfb_fillrect(info, rect);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, rect->dx, rect->dy, rect->width, rect->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_copyarea - wrapper around cfb_copyarea
|
||||
* @info: fbdev registered by the helper
|
||||
* @area: info about area to copy
|
||||
*
|
||||
* A wrapper around cfb_copyarea implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
cfb_copyarea(info, area);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, area->dx, area->dy, area->width, area->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_cfb_imageblit - wrapper around cfb_imageblit
|
||||
* @info: fbdev registered by the helper
|
||||
* @image: info about image to blit
|
||||
*
|
||||
* A wrapper around cfb_imageblit implemented by fbdev core
|
||||
*/
|
||||
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
struct drm_fb_helper *helper = info->par;
|
||||
|
||||
cfb_imageblit(info, image);
|
||||
|
||||
if (helper->funcs->fb_dirty)
|
||||
drm_fb_helper_damage(helper, image->dx, image->dy, image->width, image->height);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
|
||||
|
||||
/**
|
||||
* drm_fb_helper_set_suspend - wrapper around fb_set_suspend
|
||||
* @fb_helper: driver-allocated fbdev helper, can be NULL
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -64,14 +66,11 @@ static const struct fb_ops drm_fbdev_dma_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = drm_fbdev_dma_fb_open,
|
||||
.fb_release = drm_fbdev_dma_fb_release,
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
__FB_DEFAULT_SYS_OPS_RDWR,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_destroy = drm_fbdev_dma_fb_destroy,
|
||||
__FB_DEFAULT_SYS_OPS_DRAW,
|
||||
.fb_mmap = drm_fbdev_dma_fb_mmap,
|
||||
.fb_destroy = drm_fbdev_dma_fb_destroy,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -34,6 +34,10 @@ static int drm_fbdev_generic_fb_release(struct fb_info *info, int user)
|
||||
return 0;
|
||||
}
|
||||
|
||||
FB_GEN_DEFAULT_DEFERRED_SYS_OPS(drm_fbdev_generic,
|
||||
drm_fb_helper_damage_range,
|
||||
drm_fb_helper_damage_area);
|
||||
|
||||
static void drm_fbdev_generic_fb_destroy(struct fb_info *info)
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
@ -56,13 +60,8 @@ static const struct fb_ops drm_fbdev_generic_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = drm_fbdev_generic_fb_open,
|
||||
.fb_release = drm_fbdev_generic_fb_release,
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
FB_DEFAULT_DEFERRED_OPS(drm_fbdev_generic),
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
.fb_mmap = fb_deferred_io_mmap,
|
||||
.fb_destroy = drm_fbdev_generic_fb_destroy,
|
||||
};
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <drm/drm_client.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
@ -148,6 +149,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
|
||||
*/
|
||||
struct drm_file *drm_file_alloc(struct drm_minor *minor)
|
||||
{
|
||||
static atomic64_t ident = ATOMIC_INIT(0);
|
||||
struct drm_device *dev = minor->dev;
|
||||
struct drm_file *file;
|
||||
int ret;
|
||||
@ -156,6 +158,8 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor)
|
||||
if (!file)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* Get a unique identifier for fdinfo: */
|
||||
file->client_id = atomic64_inc_return(&ident);
|
||||
file->pid = get_pid(task_tgid(current));
|
||||
file->minor = minor;
|
||||
|
||||
@ -868,6 +872,134 @@ void drm_send_event(struct drm_device *dev, struct drm_pending_event *e)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_send_event);
|
||||
|
||||
static void print_size(struct drm_printer *p, const char *stat,
|
||||
const char *region, u64 sz)
|
||||
{
|
||||
const char *units[] = {"", " KiB", " MiB"};
|
||||
unsigned u;
|
||||
|
||||
for (u = 0; u < ARRAY_SIZE(units) - 1; u++) {
|
||||
if (sz < SZ_1K)
|
||||
break;
|
||||
sz = div_u64(sz, SZ_1K);
|
||||
}
|
||||
|
||||
drm_printf(p, "drm-%s-%s:\t%llu%s\n", stat, region, sz, units[u]);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_print_memory_stats - A helper to print memory stats
|
||||
* @p: The printer to print output to
|
||||
* @stats: The collected memory stats
|
||||
* @supported_status: Bitmask of optional stats which are available
|
||||
* @region: The memory region
|
||||
*
|
||||
*/
|
||||
void drm_print_memory_stats(struct drm_printer *p,
|
||||
const struct drm_memory_stats *stats,
|
||||
enum drm_gem_object_status supported_status,
|
||||
const char *region)
|
||||
{
|
||||
print_size(p, "total", region, stats->private + stats->shared);
|
||||
print_size(p, "shared", region, stats->shared);
|
||||
print_size(p, "active", region, stats->active);
|
||||
|
||||
if (supported_status & DRM_GEM_OBJECT_RESIDENT)
|
||||
print_size(p, "resident", region, stats->resident);
|
||||
|
||||
if (supported_status & DRM_GEM_OBJECT_PURGEABLE)
|
||||
print_size(p, "purgeable", region, stats->purgeable);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_print_memory_stats);
|
||||
|
||||
/**
|
||||
* drm_show_memory_stats - Helper to collect and show standard fdinfo memory stats
|
||||
* @p: the printer to print output to
|
||||
* @file: the DRM file
|
||||
*
|
||||
* Helper to iterate over GEM objects with a handle allocated in the specified
|
||||
* file.
|
||||
*/
|
||||
void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file)
|
||||
{
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_memory_stats status = {};
|
||||
enum drm_gem_object_status supported_status;
|
||||
int id;
|
||||
|
||||
spin_lock(&file->table_lock);
|
||||
idr_for_each_entry (&file->object_idr, obj, id) {
|
||||
enum drm_gem_object_status s = 0;
|
||||
|
||||
if (obj->funcs && obj->funcs->status) {
|
||||
s = obj->funcs->status(obj);
|
||||
supported_status = DRM_GEM_OBJECT_RESIDENT |
|
||||
DRM_GEM_OBJECT_PURGEABLE;
|
||||
}
|
||||
|
||||
if (obj->handle_count > 1) {
|
||||
status.shared += obj->size;
|
||||
} else {
|
||||
status.private += obj->size;
|
||||
}
|
||||
|
||||
if (s & DRM_GEM_OBJECT_RESIDENT) {
|
||||
status.resident += obj->size;
|
||||
} else {
|
||||
/* If already purged or not yet backed by pages, don't
|
||||
* count it as purgeable:
|
||||
*/
|
||||
s &= ~DRM_GEM_OBJECT_PURGEABLE;
|
||||
}
|
||||
|
||||
if (!dma_resv_test_signaled(obj->resv, dma_resv_usage_rw(true))) {
|
||||
status.active += obj->size;
|
||||
|
||||
/* If still active, don't count as purgeable: */
|
||||
s &= ~DRM_GEM_OBJECT_PURGEABLE;
|
||||
}
|
||||
|
||||
if (s & DRM_GEM_OBJECT_PURGEABLE)
|
||||
status.purgeable += obj->size;
|
||||
}
|
||||
spin_unlock(&file->table_lock);
|
||||
|
||||
drm_print_memory_stats(p, &status, supported_status, "memory");
|
||||
}
|
||||
EXPORT_SYMBOL(drm_show_memory_stats);
|
||||
|
||||
/**
|
||||
* drm_show_fdinfo - helper for drm file fops
|
||||
* @m: output stream
|
||||
* @f: the device file instance
|
||||
*
|
||||
* Helper to implement fdinfo, for userspace to query usage stats, etc, of a
|
||||
* process using the GPU. See also &drm_driver.show_fdinfo.
|
||||
*
|
||||
* For text output format description please see Documentation/gpu/drm-usage-stats.rst
|
||||
*/
|
||||
void drm_show_fdinfo(struct seq_file *m, struct file *f)
|
||||
{
|
||||
struct drm_file *file = f->private_data;
|
||||
struct drm_device *dev = file->minor->dev;
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
drm_printf(&p, "drm-driver:\t%s\n", dev->driver->name);
|
||||
drm_printf(&p, "drm-client-id:\t%llu\n", file->client_id);
|
||||
|
||||
if (dev_is_pci(dev->dev)) {
|
||||
struct pci_dev *pdev = to_pci_dev(dev->dev);
|
||||
|
||||
drm_printf(&p, "drm-pdev:\t%04x:%02x:%02x.%d\n",
|
||||
pci_domain_nr(pdev->bus), pdev->bus->number,
|
||||
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
|
||||
}
|
||||
|
||||
if (dev->driver->show_fdinfo)
|
||||
dev->driver->show_fdinfo(&p, file);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_show_fdinfo);
|
||||
|
||||
/**
|
||||
* mock_drm_getfile - Create a new struct file for the drm device
|
||||
* @minor: drm minor to wrap (e.g. #drm_device.primary)
|
||||
|
@ -7,6 +7,7 @@ config DRM_EXYNOS
|
||||
select DRM_DISPLAY_HELPER if DRM_EXYNOS_DP
|
||||
select DRM_KMS_HELPER
|
||||
select VIDEOMODE_HELPERS
|
||||
select FB_IO_HELPERS if DRM_FBDEV_EMULATION
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
help
|
||||
Choose this option if you have a Samsung SoC Exynos chipset.
|
||||
|
@ -8,6 +8,8 @@
|
||||
* Seung-Woo Kim <sw0312.kim@samsung.com>
|
||||
*/
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -47,13 +49,10 @@ static void exynos_drm_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops exynos_drm_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
__FB_DEFAULT_IO_OPS_RDWR,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
__FB_DEFAULT_IO_OPS_DRAW,
|
||||
.fb_mmap = exynos_drm_fb_mmap,
|
||||
.fb_read = drm_fb_helper_cfb_read,
|
||||
.fb_write = drm_fb_helper_cfb_write,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_destroy = exynos_drm_fb_destroy,
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ config DRM_GMA500
|
||||
tristate "Intel GMA500/600/3600/3650 KMS Framebuffer"
|
||||
depends on DRM && PCI && X86 && MMU
|
||||
select DRM_KMS_HELPER
|
||||
select FB_IO_HELPERS if DRM_FBDEV_EMULATION
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
# GMA500 depends on ACPI_VIDEO when ACPI is enabled, just like i915
|
||||
|
@ -5,6 +5,7 @@
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/pfn_t.h>
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
@ -134,13 +135,10 @@ static void psb_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops psb_fbdev_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
__FB_DEFAULT_IO_OPS_RDWR,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_setcolreg = psb_fbdev_fb_setcolreg,
|
||||
.fb_read = drm_fb_helper_cfb_read,
|
||||
.fb_write = drm_fb_helper_cfb_write,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
__FB_DEFAULT_IO_OPS_DRAW,
|
||||
.fb_mmap = psb_fbdev_fb_mmap,
|
||||
.fb_destroy = psb_fbdev_fb_destroy,
|
||||
};
|
||||
|
@ -492,7 +492,7 @@ static struct i2c_device_id tda9950_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, tda9950_ids);
|
||||
|
||||
static struct i2c_driver tda9950_driver = {
|
||||
.probe_new = tda9950_probe,
|
||||
.probe = tda9950_probe,
|
||||
.remove = tda9950_remove,
|
||||
.driver = {
|
||||
.name = "tda9950",
|
||||
|
@ -2099,7 +2099,7 @@ static const struct i2c_device_id tda998x_ids[] = {
|
||||
MODULE_DEVICE_TABLE(i2c, tda998x_ids);
|
||||
|
||||
static struct i2c_driver tda998x_driver = {
|
||||
.probe_new = tda998x_probe,
|
||||
.probe = tda998x_probe,
|
||||
.remove = tda998x_remove,
|
||||
.driver = {
|
||||
.name = "tda998x",
|
||||
|
@ -17,6 +17,7 @@ config DRM_I915
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL
|
||||
select DRM_MIPI_DSI
|
||||
select FB_IO_HELPERS if DRM_FBDEV_EMULATION
|
||||
select RELAY
|
||||
select I2C
|
||||
select I2C_ALGOBIT
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
@ -84,6 +85,10 @@ static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
|
||||
intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
|
||||
}
|
||||
|
||||
FB_GEN_DEFAULT_DEFERRED_IO_OPS(intel_fbdev,
|
||||
drm_fb_helper_damage_range,
|
||||
drm_fb_helper_damage_area)
|
||||
|
||||
static int intel_fbdev_set_par(struct fb_info *info)
|
||||
{
|
||||
struct intel_fbdev *ifbdev = to_intel_fbdev(info->par);
|
||||
@ -132,15 +137,12 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
|
||||
static const struct fb_ops intelfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
__FB_DEFAULT_DEFERRED_OPS_RDWR(intel_fbdev),
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_set_par = intel_fbdev_set_par,
|
||||
.fb_read = drm_fb_helper_cfb_read,
|
||||
.fb_write = drm_fb_helper_cfb_write,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
.fb_pan_display = intel_fbdev_pan_display,
|
||||
.fb_blank = intel_fbdev_blank,
|
||||
.fb_pan_display = intel_fbdev_pan_display,
|
||||
__FB_DEFAULT_DEFERRED_OPS_DRAW(intel_fbdev),
|
||||
.fb_mmap = intel_fbdev_mmap,
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@ config DRM_MSM
|
||||
select DRM_BRIDGE
|
||||
select DRM_PANEL_BRIDGE
|
||||
select DRM_SCHED
|
||||
select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
|
||||
select SHMEM
|
||||
select TMPFS
|
||||
select QCOM_SCM
|
||||
|
@ -1057,23 +1057,23 @@ static const struct drm_ioctl_desc msm_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),
|
||||
};
|
||||
|
||||
static void msm_fop_show_fdinfo(struct seq_file *m, struct file *f)
|
||||
static void msm_show_fdinfo(struct drm_printer *p, struct drm_file *file)
|
||||
{
|
||||
struct drm_file *file = f->private_data;
|
||||
struct drm_device *dev = file->minor->dev;
|
||||
struct msm_drm_private *priv = dev->dev_private;
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
if (!priv->gpu)
|
||||
return;
|
||||
|
||||
msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, &p);
|
||||
msm_gpu_show_fdinfo(priv->gpu, file->driver_priv, p);
|
||||
|
||||
drm_show_memory_stats(p, file);
|
||||
}
|
||||
|
||||
static const struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_GEM_FOPS,
|
||||
.show_fdinfo = msm_fop_show_fdinfo,
|
||||
.show_fdinfo = drm_show_fdinfo,
|
||||
};
|
||||
|
||||
static const struct drm_driver msm_driver = {
|
||||
@ -1083,7 +1083,7 @@ static const struct drm_driver msm_driver = {
|
||||
DRIVER_MODESET |
|
||||
DRIVER_SYNCOBJ,
|
||||
.open = msm_open,
|
||||
.postclose = msm_postclose,
|
||||
.postclose = msm_postclose,
|
||||
.dumb_create = msm_gem_dumb_create,
|
||||
.dumb_map_offset = msm_gem_dumb_map_offset,
|
||||
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
|
||||
@ -1093,6 +1093,7 @@ static const struct drm_driver msm_driver = {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = msm_debugfs_init,
|
||||
#endif
|
||||
.show_fdinfo = msm_show_fdinfo,
|
||||
.ioctls = msm_ioctls,
|
||||
.num_ioctls = ARRAY_SIZE(msm_ioctls),
|
||||
.fops = &fops,
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*/
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -23,6 +25,10 @@ module_param(fbdev, bool, 0600);
|
||||
* fbdev funcs, to implement legacy fbdev interface on top of drm driver
|
||||
*/
|
||||
|
||||
FB_GEN_DEFAULT_DEFERRED_SYS_OPS(msm_fbdev,
|
||||
drm_fb_helper_damage_range,
|
||||
drm_fb_helper_damage_area)
|
||||
|
||||
static int msm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_fb_helper *helper = (struct drm_fb_helper *)info->par;
|
||||
@ -52,16 +58,9 @@ static void msm_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops msm_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
__FB_DEFAULT_DEFERRED_OPS_RDWR(msm_fbdev),
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
|
||||
/* Note: to properly handle manual update displays, we wrap the
|
||||
* basic fbdev ops which write to the framebuffer
|
||||
*/
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
__FB_DEFAULT_DEFERRED_OPS_DRAW(msm_fbdev),
|
||||
.fb_mmap = msm_fbdev_mmap,
|
||||
.fb_destroy = msm_fbdev_fb_destroy,
|
||||
};
|
||||
|
@ -1096,6 +1096,20 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum drm_gem_object_status msm_gem_status(struct drm_gem_object *obj)
|
||||
{
|
||||
struct msm_gem_object *msm_obj = to_msm_bo(obj);
|
||||
enum drm_gem_object_status status = 0;
|
||||
|
||||
if (msm_obj->pages)
|
||||
status |= DRM_GEM_OBJECT_RESIDENT;
|
||||
|
||||
if (msm_obj->madv == MSM_MADV_DONTNEED)
|
||||
status |= DRM_GEM_OBJECT_PURGEABLE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct vm_ops = {
|
||||
.fault = msm_gem_fault,
|
||||
.open = drm_gem_vm_open,
|
||||
@ -1110,6 +1124,7 @@ static const struct drm_gem_object_funcs msm_gem_object_funcs = {
|
||||
.vmap = msm_gem_prime_vmap,
|
||||
.vunmap = msm_gem_prime_vunmap,
|
||||
.mmap = msm_gem_object_mmap,
|
||||
.status = msm_gem_status,
|
||||
.vm_ops = &vm_ops,
|
||||
};
|
||||
|
||||
|
@ -151,8 +151,6 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
|
||||
void msm_gpu_show_fdinfo(struct msm_gpu *gpu, struct msm_file_private *ctx,
|
||||
struct drm_printer *p)
|
||||
{
|
||||
drm_printf(p, "drm-driver:\t%s\n", gpu->dev->driver->name);
|
||||
drm_printf(p, "drm-client-id:\t%u\n", ctx->seqno);
|
||||
drm_printf(p, "drm-engine-gpu:\t%llu ns\n", ctx->elapsed_ns);
|
||||
drm_printf(p, "drm-cycles-gpu:\t%llu\n", ctx->cycles);
|
||||
drm_printf(p, "drm-maxfreq-gpu:\t%u Hz\n", gpu->fast_rate);
|
||||
|
@ -9,13 +9,16 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_fbdev_dma.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
@ -38,21 +41,70 @@ static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = {
|
||||
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs lcdif_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
|
||||
{
|
||||
struct drm_device *drm = lcdif->drm;
|
||||
struct device *dev = lcdif->drm->dev;
|
||||
struct device_node *ep;
|
||||
struct drm_bridge *bridge;
|
||||
int ret;
|
||||
|
||||
bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
|
||||
if (IS_ERR(bridge))
|
||||
return PTR_ERR(bridge);
|
||||
for_each_endpoint_of_node(dev->of_node, ep) {
|
||||
struct device_node *remote;
|
||||
struct of_endpoint of_ep;
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
ret = drm_bridge_attach(&lcdif->encoder, bridge, NULL, 0);
|
||||
if (ret)
|
||||
return dev_err_probe(drm->dev, ret, "Failed to attach bridge\n");
|
||||
remote = of_graph_get_remote_port_parent(ep);
|
||||
if (!of_device_is_available(remote)) {
|
||||
of_node_put(remote);
|
||||
continue;
|
||||
}
|
||||
of_node_put(remote);
|
||||
|
||||
lcdif->bridge = bridge;
|
||||
ret = of_graph_parse_endpoint(ep, &of_ep);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
|
||||
of_node_put(ep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
|
||||
if (IS_ERR(bridge)) {
|
||||
of_node_put(ep);
|
||||
return dev_err_probe(dev, PTR_ERR(bridge),
|
||||
"Failed to get bridge for endpoint%u\n",
|
||||
of_ep.id);
|
||||
}
|
||||
|
||||
encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
|
||||
if (!encoder) {
|
||||
dev_err(dev, "Failed to allocate encoder for endpoint%u\n",
|
||||
of_ep.id);
|
||||
of_node_put(ep);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(&lcdif->crtc);
|
||||
ret = drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
|
||||
DRM_MODE_ENCODER_NONE, NULL);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to initialize encoder for endpoint%u: %d\n",
|
||||
of_ep.id, ret);
|
||||
of_node_put(ep);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
|
||||
if (ret) {
|
||||
of_node_put(ep);
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to attach bridge for endpoint%u\n",
|
||||
of_ep.id);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -199,6 +251,7 @@ static const struct drm_driver lcdif_driver = {
|
||||
|
||||
static const struct of_device_id lcdif_dt_ids[] = {
|
||||
{ .compatible = "fsl,imx8mp-lcdif" },
|
||||
{ .compatible = "fsl,imx93-lcdif" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lcdif_dt_ids);
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_plane.h>
|
||||
|
||||
struct clk;
|
||||
@ -30,8 +29,6 @@ struct lcdif_drm_private {
|
||||
/* i.MXRT does support overlay planes, add them here. */
|
||||
} planes;
|
||||
struct drm_crtc crtc;
|
||||
struct drm_encoder encoder;
|
||||
struct drm_bridge *bridge;
|
||||
};
|
||||
|
||||
static inline struct lcdif_drm_private *
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
@ -30,6 +31,18 @@
|
||||
#include "lcdif_drv.h"
|
||||
#include "lcdif_regs.h"
|
||||
|
||||
struct lcdif_crtc_state {
|
||||
struct drm_crtc_state base; /* always be the first member */
|
||||
u32 bus_format;
|
||||
u32 bus_flags;
|
||||
};
|
||||
|
||||
static inline struct lcdif_crtc_state *
|
||||
to_lcdif_crtc_state(struct drm_crtc_state *s)
|
||||
{
|
||||
return container_of(s, struct lcdif_crtc_state, base);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CRTC
|
||||
*/
|
||||
@ -385,48 +398,108 @@ static void lcdif_reset_block(struct lcdif_drm_private *lcdif)
|
||||
readl(lcdif->base + LCDC_V8_CTRL);
|
||||
}
|
||||
|
||||
static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
|
||||
struct drm_plane_state *plane_state,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
const u32 bus_format)
|
||||
static void lcdif_crtc_mode_set_nofb(struct drm_crtc_state *crtc_state,
|
||||
struct drm_plane_state *plane_state)
|
||||
{
|
||||
struct drm_device *drm = lcdif->crtc.dev;
|
||||
struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
|
||||
u32 bus_flags = 0;
|
||||
|
||||
if (lcdif->bridge && lcdif->bridge->timings)
|
||||
bus_flags = lcdif->bridge->timings->input_bus_flags;
|
||||
else if (bridge_state)
|
||||
bus_flags = bridge_state->input_bus_cfg.flags;
|
||||
struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
|
||||
struct drm_device *drm = crtc_state->crtc->dev;
|
||||
struct lcdif_drm_private *lcdif = to_lcdif_drm_private(drm);
|
||||
struct drm_display_mode *m = &crtc_state->adjusted_mode;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
|
||||
m->crtc_clock,
|
||||
(int)(clk_get_rate(lcdif->clk) / 1000));
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
|
||||
bus_flags);
|
||||
lcdif_crtc_state->bus_flags);
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
|
||||
|
||||
/* Mandatory eLCDIF reset as per the Reference Manual */
|
||||
lcdif_reset_block(lcdif);
|
||||
|
||||
lcdif_set_formats(lcdif, plane_state, bus_format);
|
||||
lcdif_set_formats(lcdif, plane_state, lcdif_crtc_state->bus_format);
|
||||
|
||||
lcdif_set_mode(lcdif, bus_flags);
|
||||
lcdif_set_mode(lcdif, lcdif_crtc_state->bus_flags);
|
||||
}
|
||||
|
||||
static int lcdif_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *drm = crtc->dev;
|
||||
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
|
||||
crtc);
|
||||
struct lcdif_crtc_state *lcdif_crtc_state = to_lcdif_crtc_state(crtc_state);
|
||||
bool has_primary = crtc_state->plane_mask &
|
||||
drm_plane_mask(crtc->primary);
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge_state *bridge_state;
|
||||
struct drm_bridge *bridge;
|
||||
u32 bus_format, bus_flags;
|
||||
bool format_set = false, flags_set = false;
|
||||
int ret, i;
|
||||
|
||||
/* The primary plane has to be enabled when the CRTC is active. */
|
||||
if (crtc_state->active && !has_primary)
|
||||
return -EINVAL;
|
||||
|
||||
return drm_atomic_add_affected_planes(state, crtc);
|
||||
ret = drm_atomic_add_affected_planes(state, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Try to find consistent bus format and flags across first bridges. */
|
||||
for_each_new_connector_in_state(state, connector, connector_state, i) {
|
||||
if (!connector_state->crtc)
|
||||
continue;
|
||||
|
||||
encoder = connector_state->best_encoder;
|
||||
|
||||
bridge = drm_bridge_chain_get_first_bridge(encoder);
|
||||
if (!bridge)
|
||||
continue;
|
||||
|
||||
bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
|
||||
if (!bridge_state)
|
||||
bus_format = MEDIA_BUS_FMT_FIXED;
|
||||
else
|
||||
bus_format = bridge_state->input_bus_cfg.format;
|
||||
|
||||
if (bus_format == MEDIA_BUS_FMT_FIXED) {
|
||||
dev_warn(drm->dev,
|
||||
"[ENCODER:%d:%s]'s bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
|
||||
"Please fix bridge driver by handling atomic_get_input_bus_fmts.\n",
|
||||
encoder->base.id, encoder->name);
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
} else if (!bus_format) {
|
||||
/* If all else fails, default to RGB888_1X24 */
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
}
|
||||
|
||||
if (!format_set) {
|
||||
lcdif_crtc_state->bus_format = bus_format;
|
||||
format_set = true;
|
||||
} else if (lcdif_crtc_state->bus_format != bus_format) {
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "inconsistent bus format\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (bridge->timings)
|
||||
bus_flags = bridge->timings->input_bus_flags;
|
||||
else if (bridge_state)
|
||||
bus_flags = bridge_state->input_bus_cfg.flags;
|
||||
else
|
||||
bus_flags = 0;
|
||||
|
||||
if (!flags_set) {
|
||||
lcdif_crtc_state->bus_flags = bus_flags;
|
||||
flags_set = true;
|
||||
} else if (lcdif_crtc_state->bus_flags != bus_flags) {
|
||||
DRM_DEV_DEBUG_DRIVER(drm->dev, "inconsistent bus flags\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lcdif_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
@ -458,41 +531,18 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
|
||||
struct drm_crtc_state *new_cstate = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
struct drm_plane_state *new_pstate = drm_atomic_get_new_plane_state(state,
|
||||
crtc->primary);
|
||||
struct drm_display_mode *m = &lcdif->crtc.state->adjusted_mode;
|
||||
struct drm_bridge_state *bridge_state = NULL;
|
||||
struct drm_device *drm = lcdif->drm;
|
||||
u32 bus_format = 0;
|
||||
dma_addr_t paddr;
|
||||
|
||||
/* If there is a bridge attached to the LCDIF, use its bus format */
|
||||
if (lcdif->bridge) {
|
||||
bridge_state =
|
||||
drm_atomic_get_new_bridge_state(state,
|
||||
lcdif->bridge);
|
||||
if (!bridge_state)
|
||||
bus_format = MEDIA_BUS_FMT_FIXED;
|
||||
else
|
||||
bus_format = bridge_state->input_bus_cfg.format;
|
||||
|
||||
if (bus_format == MEDIA_BUS_FMT_FIXED) {
|
||||
dev_warn_once(drm->dev,
|
||||
"Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
|
||||
"Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
}
|
||||
}
|
||||
|
||||
/* If all else fails, default to RGB888_1X24 */
|
||||
if (!bus_format)
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
|
||||
clk_set_rate(lcdif->clk, m->crtc_clock * 1000);
|
||||
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
|
||||
lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state, bus_format);
|
||||
lcdif_crtc_mode_set_nofb(new_cstate, new_pstate);
|
||||
|
||||
/* Write cur_buf as well to avoid an initial corrupt frame */
|
||||
paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
|
||||
@ -529,6 +579,48 @@ static void lcdif_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
}
|
||||
|
||||
static void lcdif_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
__drm_atomic_helper_crtc_destroy_state(state);
|
||||
kfree(to_lcdif_crtc_state(state));
|
||||
}
|
||||
|
||||
static void lcdif_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
struct lcdif_crtc_state *state;
|
||||
|
||||
if (crtc->state)
|
||||
lcdif_crtc_atomic_destroy_state(crtc, crtc->state);
|
||||
|
||||
crtc->state = NULL;
|
||||
|
||||
state = kzalloc(sizeof(*state), GFP_KERNEL);
|
||||
if (state)
|
||||
__drm_atomic_helper_crtc_reset(crtc, &state->base);
|
||||
}
|
||||
|
||||
static struct drm_crtc_state *
|
||||
lcdif_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
|
||||
{
|
||||
struct lcdif_crtc_state *old = to_lcdif_crtc_state(crtc->state);
|
||||
struct lcdif_crtc_state *new;
|
||||
|
||||
if (WARN_ON(!crtc->state))
|
||||
return NULL;
|
||||
|
||||
new = kzalloc(sizeof(*new), GFP_KERNEL);
|
||||
if (!new)
|
||||
return NULL;
|
||||
|
||||
__drm_atomic_helper_crtc_duplicate_state(crtc, &new->base);
|
||||
|
||||
new->bus_format = old->bus_format;
|
||||
new->bus_flags = old->bus_flags;
|
||||
|
||||
return &new->base;
|
||||
}
|
||||
|
||||
static int lcdif_crtc_enable_vblank(struct drm_crtc *crtc)
|
||||
{
|
||||
struct lcdif_drm_private *lcdif = to_lcdif_drm_private(crtc->dev);
|
||||
@ -557,24 +649,16 @@ static const struct drm_crtc_helper_funcs lcdif_crtc_helper_funcs = {
|
||||
};
|
||||
|
||||
static const struct drm_crtc_funcs lcdif_crtc_funcs = {
|
||||
.reset = drm_atomic_helper_crtc_reset,
|
||||
.reset = lcdif_crtc_reset,
|
||||
.destroy = drm_crtc_cleanup,
|
||||
.set_config = drm_atomic_helper_set_config,
|
||||
.page_flip = drm_atomic_helper_page_flip,
|
||||
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
|
||||
.atomic_duplicate_state = lcdif_crtc_atomic_duplicate_state,
|
||||
.atomic_destroy_state = lcdif_crtc_atomic_destroy_state,
|
||||
.enable_vblank = lcdif_crtc_enable_vblank,
|
||||
.disable_vblank = lcdif_crtc_disable_vblank,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Encoder
|
||||
*/
|
||||
|
||||
static const struct drm_encoder_funcs lcdif_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Planes
|
||||
*/
|
||||
@ -667,7 +751,6 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
|
||||
BIT(DRM_COLOR_YCBCR_BT2020);
|
||||
const u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
|
||||
BIT(DRM_COLOR_YCBCR_FULL_RANGE);
|
||||
struct drm_encoder *encoder = &lcdif->encoder;
|
||||
struct drm_crtc *crtc = &lcdif->crtc;
|
||||
int ret;
|
||||
|
||||
@ -691,13 +774,7 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
|
||||
return ret;
|
||||
|
||||
drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);
|
||||
ret = drm_crtc_init_with_planes(lcdif->drm, crtc,
|
||||
&lcdif->planes.primary, NULL,
|
||||
&lcdif_crtc_funcs, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
encoder->possible_crtcs = drm_crtc_mask(crtc);
|
||||
return drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
|
||||
DRM_MODE_ENCODER_NONE, NULL);
|
||||
return drm_crtc_init_with_planes(lcdif->drm, crtc,
|
||||
&lcdif->planes.primary, NULL,
|
||||
&lcdif_crtc_funcs, NULL);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ config DRM_OMAP
|
||||
depends on DRM && OF
|
||||
depends on ARCH_OMAP2PLUS
|
||||
select DRM_KMS_HELPER
|
||||
select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
|
||||
select VIDEOMODE_HELPERS
|
||||
select HDMI
|
||||
default n
|
||||
|
@ -4,6 +4,8 @@
|
||||
* Author: Rob Clark <rob@ti.com>
|
||||
*/
|
||||
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -95,20 +97,13 @@ static void omap_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops omap_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
||||
FB_DEFAULT_SYS_OPS,
|
||||
.fb_check_var = drm_fb_helper_check_var,
|
||||
.fb_set_par = drm_fb_helper_set_par,
|
||||
.fb_setcmap = drm_fb_helper_setcmap,
|
||||
.fb_blank = drm_fb_helper_blank,
|
||||
.fb_pan_display = omap_fbdev_pan_display,
|
||||
.fb_ioctl = drm_fb_helper_ioctl,
|
||||
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
|
||||
.fb_destroy = omap_fbdev_fb_destroy,
|
||||
};
|
||||
|
||||
|
@ -903,7 +903,7 @@ err_finished_ddc_init:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int panel_edp_remove(struct device *dev)
|
||||
static void panel_edp_remove(struct device *dev)
|
||||
{
|
||||
struct panel_edp *panel = dev_get_drvdata(dev);
|
||||
|
||||
@ -918,8 +918,6 @@ static int panel_edp_remove(struct device *dev)
|
||||
|
||||
kfree(panel->edid);
|
||||
panel->edid = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void panel_edp_shutdown(struct device *dev)
|
||||
@ -1934,9 +1932,9 @@ static int panel_edp_platform_probe(struct platform_device *pdev)
|
||||
return panel_edp_probe(&pdev->dev, id->data, NULL);
|
||||
}
|
||||
|
||||
static int panel_edp_platform_remove(struct platform_device *pdev)
|
||||
static void panel_edp_platform_remove(struct platform_device *pdev)
|
||||
{
|
||||
return panel_edp_remove(&pdev->dev);
|
||||
panel_edp_remove(&pdev->dev);
|
||||
}
|
||||
|
||||
static void panel_edp_platform_shutdown(struct platform_device *pdev)
|
||||
@ -1957,7 +1955,7 @@ static struct platform_driver panel_edp_platform_driver = {
|
||||
.pm = &panel_edp_pm_ops,
|
||||
},
|
||||
.probe = panel_edp_platform_probe,
|
||||
.remove = panel_edp_platform_remove,
|
||||
.remove_new = panel_edp_platform_remove,
|
||||
.shutdown = panel_edp_platform_shutdown,
|
||||
};
|
||||
|
||||
|
@ -308,7 +308,7 @@ static struct i2c_driver lcd_olinuxino_driver = {
|
||||
.name = "lcd_olinuxino",
|
||||
.of_match_table = lcd_olinuxino_of_ids,
|
||||
},
|
||||
.probe_new = lcd_olinuxino_probe,
|
||||
.probe = lcd_olinuxino_probe,
|
||||
.remove = lcd_olinuxino_remove,
|
||||
};
|
||||
|
||||
|
@ -489,7 +489,7 @@ static struct i2c_driver rpi_touchscreen_driver = {
|
||||
.name = "rpi_touchscreen",
|
||||
.of_match_table = rpi_touchscreen_of_ids,
|
||||
},
|
||||
.probe_new = rpi_touchscreen_probe,
|
||||
.probe = rpi_touchscreen_probe,
|
||||
.remove = rpi_touchscreen_remove,
|
||||
};
|
||||
|
||||
|
@ -759,8 +759,8 @@ static const struct panel_desc ampire_am_480272h3tmqw_t01h = {
|
||||
.num_modes = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 105,
|
||||
.height = 67,
|
||||
.width = 99,
|
||||
.height = 58,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
};
|
||||
@ -778,6 +778,36 @@ static const struct drm_display_mode ampire_am800480r3tmqwa1h_mode = {
|
||||
.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
|
||||
};
|
||||
|
||||
static const struct display_timing ampire_am_800480l1tmqw_t00h_timing = {
|
||||
.pixelclock = { 29930000, 33260000, 36590000 },
|
||||
.hactive = { 800, 800, 800 },
|
||||
.hfront_porch = { 1, 40, 168 },
|
||||
.hback_porch = { 88, 88, 88 },
|
||||
.hsync_len = { 1, 128, 128 },
|
||||
.vactive = { 480, 480, 480 },
|
||||
.vfront_porch = { 1, 35, 37 },
|
||||
.vback_porch = { 8, 8, 8 },
|
||||
.vsync_len = { 1, 2, 2 },
|
||||
.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW |
|
||||
DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
|
||||
DISPLAY_FLAGS_SYNC_POSEDGE,
|
||||
};
|
||||
|
||||
static const struct panel_desc ampire_am_800480l1tmqw_t00h = {
|
||||
.timings = &ire_am_800480l1tmqw_t00h_timing,
|
||||
.num_timings = 1,
|
||||
.bpc = 8,
|
||||
.size = {
|
||||
.width = 111,
|
||||
.height = 67,
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct panel_desc ampire_am800480r3tmqwa1h = {
|
||||
.modes = &ire_am800480r3tmqwa1h_mode,
|
||||
.num_modes = 1,
|
||||
@ -3993,6 +4023,9 @@ static const struct of_device_id platform_of_match[] = {
|
||||
}, {
|
||||
.compatible = "ampire,am-480272h3tmqw-t01h",
|
||||
.data = &ire_am_480272h3tmqw_t01h,
|
||||
}, {
|
||||
.compatible = "ampire,am-800480l1tmqw-t00h",
|
||||
.data = &ire_am_800480l1tmqw_t00h,
|
||||
}, {
|
||||
.compatible = "ampire,am800480r3tmqwa1h",
|
||||
.data = &ire_am800480r3tmqwa1h,
|
||||
|
@ -11,6 +11,7 @@ config DRM_RADEON
|
||||
select DRM_SUBALLOC_HELPER
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
select FB_IO_HELPERS if DRM_FBDEV_EMULATION
|
||||
select SND_HDA_COMPONENT if SND_HDA_CORE
|
||||
select POWER_SUPPLY
|
||||
select HWMON
|
||||
|
@ -24,6 +24,7 @@
|
||||
* David Airlie
|
||||
*/
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
@ -190,14 +191,10 @@ static void radeon_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops radeon_fbdev_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_open = radeon_fbdev_fb_open,
|
||||
.fb_release = radeon_fbdev_fb_release,
|
||||
.fb_read = drm_fb_helper_cfb_read,
|
||||
.fb_write = drm_fb_helper_cfb_write,
|
||||
.fb_fillrect = drm_fb_helper_cfb_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_cfb_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_cfb_imageblit,
|
||||
FB_DEFAULT_IO_OPS,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_destroy = radeon_fbdev_fb_destroy,
|
||||
};
|
||||
|
||||
|
@ -100,7 +100,7 @@ static struct i2c_driver ssd130x_i2c_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = ssd130x_of_match,
|
||||
},
|
||||
.probe_new = ssd130x_i2c_probe,
|
||||
.probe = ssd130x_i2c_probe,
|
||||
.remove = ssd130x_i2c_remove,
|
||||
.shutdown = ssd130x_i2c_shutdown,
|
||||
};
|
||||
|
@ -444,15 +444,13 @@ static int dw_mipi_dsi_stm_probe(struct platform_device *pdev)
|
||||
struct device *dev = &pdev->dev;
|
||||
struct dw_mipi_dsi_stm *dsi;
|
||||
struct clk *pclk;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
|
||||
if (!dsi)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
dsi->base = devm_ioremap_resource(dev, res);
|
||||
dsi->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(dsi->base)) {
|
||||
ret = PTR_ERR(dsi->base);
|
||||
DRM_ERROR("Unable to get dsi registers %d\n", ret);
|
||||
|
@ -1145,7 +1145,7 @@ static void ltdc_crtc_disable_vblank(struct drm_crtc *crtc)
|
||||
|
||||
static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
|
||||
{
|
||||
struct ltdc_device *ldev = crtc_to_ltdc(crtc);
|
||||
struct ltdc_device *ldev;
|
||||
int ret;
|
||||
|
||||
DRM_DEBUG_DRIVER("\n");
|
||||
@ -1153,6 +1153,8 @@ static int ltdc_crtc_set_crc_source(struct drm_crtc *crtc, const char *source)
|
||||
if (!crtc)
|
||||
return -ENODEV;
|
||||
|
||||
ldev = crtc_to_ltdc(crtc);
|
||||
|
||||
if (source && strcmp(source, "auto") == 0) {
|
||||
ldev->crc_active = true;
|
||||
ret = regmap_set_bits(ldev->regmap, LTDC_GCR, GCR_CRCEN);
|
||||
|
@ -12,6 +12,7 @@ config DRM_TEGRA
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_PANEL
|
||||
select FB_SYS_HELPERS if DRM_FBDEV_EMULATION
|
||||
select TEGRA_HOST1X
|
||||
select INTERCONNECT
|
||||
select IOMMU_IOVA
|
||||
|
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/console.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#include <drm/drm_drv.h>
|
||||
@ -58,12 +59,9 @@ static void tegra_fbdev_fb_destroy(struct fb_info *info)
|
||||
|
||||
static const struct fb_ops tegra_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
__FB_DEFAULT_SYS_OPS_RDWR,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
.fb_read = drm_fb_helper_sys_read,
|
||||
.fb_write = drm_fb_helper_sys_write,
|
||||
.fb_fillrect = drm_fb_helper_sys_fillrect,
|
||||
.fb_copyarea = drm_fb_helper_sys_copyarea,
|
||||
.fb_imageblit = drm_fb_helper_sys_imageblit,
|
||||
__FB_DEFAULT_SYS_OPS_DRAW,
|
||||
.fb_mmap = tegra_fb_mmap,
|
||||
.fb_destroy = tegra_fbdev_fb_destroy,
|
||||
};
|
||||
|
@ -137,7 +137,6 @@ static void ttm_tt_init_fields(struct ttm_tt *ttm,
|
||||
unsigned long extra_pages)
|
||||
{
|
||||
ttm->num_pages = (PAGE_ALIGN(bo->base.size) >> PAGE_SHIFT) + extra_pages;
|
||||
ttm->caching = ttm_cached;
|
||||
ttm->page_flags = page_flags;
|
||||
ttm->dma_address = NULL;
|
||||
ttm->swap_storage = NULL;
|
||||
|
@ -158,6 +158,27 @@ config FB_DEFERRED_IO
|
||||
bool
|
||||
depends on FB
|
||||
|
||||
config FB_IO_HELPERS
|
||||
bool
|
||||
depends on FB
|
||||
select FB_CFB_COPYAREA
|
||||
select FB_CFB_FILLRECT
|
||||
select FB_CFB_IMAGEBLIT
|
||||
|
||||
config FB_SYS_HELPERS
|
||||
bool
|
||||
depends on FB
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_FOPS
|
||||
select FB_SYS_IMAGEBLIT
|
||||
|
||||
config FB_SYS_HELPERS_DEFERRED
|
||||
bool
|
||||
depends on FB
|
||||
select FB_DEFERRED_IO
|
||||
select FB_SYS_HELPERS
|
||||
|
||||
config FB_HECUBA
|
||||
tristate
|
||||
depends on FB
|
||||
|
@ -54,11 +54,14 @@ struct samsung_dsim_driver_data {
|
||||
unsigned int has_freqband:1;
|
||||
unsigned int has_clklane_stop:1;
|
||||
unsigned int num_clks;
|
||||
unsigned int min_freq;
|
||||
unsigned int max_freq;
|
||||
unsigned int wait_for_reset;
|
||||
unsigned int num_bits_resol;
|
||||
unsigned int pll_p_offset;
|
||||
const unsigned int *reg_values;
|
||||
u16 m_min;
|
||||
u16 m_max;
|
||||
};
|
||||
|
||||
struct samsung_dsim_host_ops {
|
||||
@ -90,6 +93,7 @@ struct samsung_dsim {
|
||||
|
||||
u32 pll_clk_rate;
|
||||
u32 burst_clk_rate;
|
||||
u32 hs_clock;
|
||||
u32 esc_clk_rate;
|
||||
u32 lanes;
|
||||
u32 mode_flags;
|
||||
|
@ -401,6 +401,13 @@ struct drm_driver {
|
||||
struct drm_device *dev, uint32_t handle,
|
||||
uint64_t *offset);
|
||||
|
||||
/**
|
||||
* @show_fdinfo:
|
||||
*
|
||||
* Print device specific fdinfo. See Documentation/gpu/drm-usage-stats.rst.
|
||||
*/
|
||||
void (*show_fdinfo)(struct drm_printer *p, struct drm_file *f);
|
||||
|
||||
/** @major: driver major number */
|
||||
int major;
|
||||
/** @minor: driver minor number */
|
||||
|
@ -253,32 +253,11 @@ void drm_fb_helper_fill_info(struct fb_info *info,
|
||||
struct drm_fb_helper *fb_helper,
|
||||
struct drm_fb_helper_surface_size *sizes);
|
||||
|
||||
void drm_fb_helper_damage_range(struct fb_info *info, off_t off, size_t len);
|
||||
void drm_fb_helper_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height);
|
||||
|
||||
void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist);
|
||||
|
||||
ssize_t drm_fb_helper_sys_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
ssize_t drm_fb_helper_sys_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect);
|
||||
void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area);
|
||||
void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image);
|
||||
|
||||
ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect);
|
||||
void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area);
|
||||
void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image);
|
||||
|
||||
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend);
|
||||
void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
|
||||
bool suspend);
|
||||
@ -394,62 +373,6 @@ static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_sys_read(struct fb_info *info,
|
||||
char __user *buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_sys_write(struct fb_info *info,
|
||||
const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_sys_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_cfb_read(struct fb_info *info, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline ssize_t drm_fb_helper_cfb_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_fillrect(struct fb_info *info,
|
||||
const struct fb_fillrect *rect)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_copyarea(struct fb_info *info,
|
||||
const struct fb_copyarea *area)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_cfb_imageblit(struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
|
||||
bool suspend)
|
||||
{
|
||||
|
@ -41,6 +41,7 @@
|
||||
struct dma_fence;
|
||||
struct drm_file;
|
||||
struct drm_device;
|
||||
struct drm_printer;
|
||||
struct device;
|
||||
struct file;
|
||||
|
||||
@ -258,6 +259,9 @@ struct drm_file {
|
||||
/** @pid: Process that opened this file. */
|
||||
struct pid *pid;
|
||||
|
||||
/** @client_id: A unique id for fdinfo */
|
||||
u64 client_id;
|
||||
|
||||
/** @magic: Authentication magic, see @authenticated. */
|
||||
drm_magic_t magic;
|
||||
|
||||
@ -439,6 +443,34 @@ void drm_send_event_timestamp_locked(struct drm_device *dev,
|
||||
struct drm_pending_event *e,
|
||||
ktime_t timestamp);
|
||||
|
||||
/**
|
||||
* struct drm_memory_stats - GEM object stats associated
|
||||
* @shared: Total size of GEM objects shared between processes
|
||||
* @private: Total size of GEM objects
|
||||
* @resident: Total size of GEM objects backing pages
|
||||
* @purgeable: Total size of GEM objects that can be purged (resident and not active)
|
||||
* @active: Total size of GEM objects active on one or more engines
|
||||
*
|
||||
* Used by drm_print_memory_stats()
|
||||
*/
|
||||
struct drm_memory_stats {
|
||||
u64 shared;
|
||||
u64 private;
|
||||
u64 resident;
|
||||
u64 purgeable;
|
||||
u64 active;
|
||||
};
|
||||
|
||||
enum drm_gem_object_status;
|
||||
|
||||
void drm_print_memory_stats(struct drm_printer *p,
|
||||
const struct drm_memory_stats *stats,
|
||||
enum drm_gem_object_status supported_status,
|
||||
const char *region);
|
||||
|
||||
void drm_show_memory_stats(struct drm_printer *p, struct drm_file *file);
|
||||
void drm_show_fdinfo(struct seq_file *m, struct file *f);
|
||||
|
||||
struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags);
|
||||
|
||||
#endif /* _DRM_FILE_H_ */
|
||||
|
@ -42,6 +42,25 @@
|
||||
struct iosys_map;
|
||||
struct drm_gem_object;
|
||||
|
||||
/**
|
||||
* enum drm_gem_object_status - bitmask of object state for fdinfo reporting
|
||||
* @DRM_GEM_OBJECT_RESIDENT: object is resident in memory (ie. not unpinned)
|
||||
* @DRM_GEM_OBJECT_PURGEABLE: object marked as purgeable by userspace
|
||||
*
|
||||
* Bitmask of status used for fdinfo memory stats, see &drm_gem_object_funcs.status
|
||||
* and drm_show_fdinfo(). Note that an object can DRM_GEM_OBJECT_PURGEABLE if
|
||||
* it still active or not resident, in which case drm_show_fdinfo() will not
|
||||
* account for it as purgeable. So drivers do not need to check if the buffer
|
||||
* is idle and resident to return this bit. (Ie. userspace can mark a buffer
|
||||
* as purgeable even while it is still busy on the GPU.. it does not _actually_
|
||||
* become puregeable until it becomes idle. The status gem object func does
|
||||
* not need to consider this.)
|
||||
*/
|
||||
enum drm_gem_object_status {
|
||||
DRM_GEM_OBJECT_RESIDENT = BIT(0),
|
||||
DRM_GEM_OBJECT_PURGEABLE = BIT(1),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_gem_object_funcs - GEM object functions
|
||||
*/
|
||||
@ -174,6 +193,19 @@ struct drm_gem_object_funcs {
|
||||
*/
|
||||
int (*evict)(struct drm_gem_object *obj);
|
||||
|
||||
/**
|
||||
* @status:
|
||||
*
|
||||
* The optional status callback can return additional object state
|
||||
* which determines which stats the object is counted against. The
|
||||
* callback is called under table_lock. Racing against object status
|
||||
* change is "harmless", and the callback can expect to not race
|
||||
* against object destruction.
|
||||
*
|
||||
* Called by drm_show_memory_stats().
|
||||
*/
|
||||
enum drm_gem_object_status (*status)(struct drm_gem_object *obj);
|
||||
|
||||
/**
|
||||
* @vm_ops:
|
||||
*
|
||||
|
@ -538,9 +538,31 @@ extern ssize_t fb_io_read(struct fb_info *info, char __user *buf,
|
||||
extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
/*
|
||||
* Initializes struct fb_ops for framebuffers in I/O memory.
|
||||
*/
|
||||
|
||||
#define __FB_DEFAULT_IO_OPS_RDWR \
|
||||
.fb_read = fb_io_read, \
|
||||
.fb_write = fb_io_write
|
||||
|
||||
#define __FB_DEFAULT_IO_OPS_DRAW \
|
||||
.fb_fillrect = cfb_fillrect, \
|
||||
.fb_copyarea = cfb_copyarea, \
|
||||
.fb_imageblit = cfb_imageblit
|
||||
|
||||
#define __FB_DEFAULT_IO_OPS_MMAP \
|
||||
.fb_mmap = NULL // default implementation
|
||||
|
||||
#define FB_DEFAULT_IO_OPS \
|
||||
__FB_DEFAULT_IO_OPS_RDWR, \
|
||||
__FB_DEFAULT_IO_OPS_DRAW, \
|
||||
__FB_DEFAULT_IO_OPS_MMAP
|
||||
|
||||
/*
|
||||
* Drawing operations where framebuffer is in system RAM
|
||||
*/
|
||||
|
||||
extern void sys_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
|
||||
extern void sys_copyarea(struct fb_info *info, const struct fb_copyarea *area);
|
||||
extern void sys_imageblit(struct fb_info *info, const struct fb_image *image);
|
||||
@ -549,6 +571,27 @@ extern ssize_t fb_sys_read(struct fb_info *info, char __user *buf,
|
||||
extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
|
||||
size_t count, loff_t *ppos);
|
||||
|
||||
/*
|
||||
* Initializes struct fb_ops for framebuffers in system memory.
|
||||
*/
|
||||
|
||||
#define __FB_DEFAULT_SYS_OPS_RDWR \
|
||||
.fb_read = fb_sys_read, \
|
||||
.fb_write = fb_sys_write
|
||||
|
||||
#define __FB_DEFAULT_SYS_OPS_DRAW \
|
||||
.fb_fillrect = sys_fillrect, \
|
||||
.fb_copyarea = sys_copyarea, \
|
||||
.fb_imageblit = sys_imageblit
|
||||
|
||||
#define __FB_DEFAULT_SYS_OPS_MMAP \
|
||||
.fb_mmap = NULL // default implementation
|
||||
|
||||
#define FB_DEFAULT_SYS_OPS \
|
||||
__FB_DEFAULT_SYS_OPS_RDWR, \
|
||||
__FB_DEFAULT_SYS_OPS_DRAW, \
|
||||
__FB_DEFAULT_SYS_OPS_MMAP
|
||||
|
||||
/* drivers/video/fbmem.c */
|
||||
extern int register_framebuffer(struct fb_info *fb_info);
|
||||
extern void unregister_framebuffer(struct fb_info *fb_info);
|
||||
@ -604,6 +647,75 @@ extern void fb_deferred_io_cleanup(struct fb_info *info);
|
||||
extern int fb_deferred_io_fsync(struct file *file, loff_t start,
|
||||
loff_t end, int datasync);
|
||||
|
||||
/*
|
||||
* Generate callbacks for deferred I/O
|
||||
*/
|
||||
|
||||
#define __FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, __mode) \
|
||||
static ssize_t __prefix ## _defio_read(struct fb_info *info, char __user *buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
return fb_ ## __mode ## _read(info, buf, count, ppos); \
|
||||
} \
|
||||
static ssize_t __prefix ## _defio_write(struct fb_info *info, const char __user *buf, \
|
||||
size_t count, loff_t *ppos) \
|
||||
{ \
|
||||
unsigned long offset = *ppos; \
|
||||
ssize_t ret = fb_ ## __mode ## _write(info, buf, count, ppos); \
|
||||
if (ret > 0) \
|
||||
__damage_range(info, offset, ret); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define __FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, __mode) \
|
||||
static void __prefix ## _defio_fillrect(struct fb_info *info, \
|
||||
const struct fb_fillrect *rect) \
|
||||
{ \
|
||||
__mode ## _fillrect(info, rect); \
|
||||
__damage_area(info, rect->dx, rect->dy, rect->width, rect->height); \
|
||||
} \
|
||||
static void __prefix ## _defio_copyarea(struct fb_info *info, \
|
||||
const struct fb_copyarea *area) \
|
||||
{ \
|
||||
__mode ## _copyarea(info, area); \
|
||||
__damage_area(info, area->dx, area->dy, area->width, area->height); \
|
||||
} \
|
||||
static void __prefix ## _defio_imageblit(struct fb_info *info, \
|
||||
const struct fb_image *image) \
|
||||
{ \
|
||||
__mode ## _imageblit(info, image); \
|
||||
__damage_area(info, image->dx, image->dy, image->width, image->height); \
|
||||
}
|
||||
|
||||
#define FB_GEN_DEFAULT_DEFERRED_IO_OPS(__prefix, __damage_range, __damage_area) \
|
||||
__FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, io) \
|
||||
__FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, cfb)
|
||||
|
||||
#define FB_GEN_DEFAULT_DEFERRED_SYS_OPS(__prefix, __damage_range, __damage_area) \
|
||||
__FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, sys) \
|
||||
__FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, sys)
|
||||
|
||||
/*
|
||||
* Initializes struct fb_ops for deferred I/O.
|
||||
*/
|
||||
|
||||
#define __FB_DEFAULT_DEFERRED_OPS_RDWR(__prefix) \
|
||||
.fb_read = __prefix ## _defio_read, \
|
||||
.fb_write = __prefix ## _defio_write
|
||||
|
||||
#define __FB_DEFAULT_DEFERRED_OPS_DRAW(__prefix) \
|
||||
.fb_fillrect = __prefix ## _defio_fillrect, \
|
||||
.fb_copyarea = __prefix ## _defio_copyarea, \
|
||||
.fb_imageblit = __prefix ## _defio_imageblit
|
||||
|
||||
#define __FB_DEFAULT_DEFERRED_OPS_MMAP(__prefix) \
|
||||
.fb_mmap = fb_deferred_io_mmap
|
||||
|
||||
#define FB_DEFAULT_DEFERRED_OPS(__prefix) \
|
||||
__FB_DEFAULT_DEFERRED_OPS_RDWR(__prefix), \
|
||||
__FB_DEFAULT_DEFERRED_OPS_DRAW(__prefix), \
|
||||
__FB_DEFAULT_DEFERRED_OPS_MMAP(__prefix)
|
||||
|
||||
static inline bool fb_be_math(struct fb_info *info)
|
||||
{
|
||||
#ifdef CONFIG_FB_FOREIGN_ENDIAN
|
||||
|
Loading…
x
Reference in New Issue
Block a user