mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-11 13:52:02 -04:00
Merge tag 'drm-misc-next-2025-02-20' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next
drm-misc-next for v6.15: UAPI Changes: device-wedged events: - Let's drivers notify userspace of hung-up devices via uevent Cross-subsystem Changes: media: - cec: tda998x: Import driver from DRM Core Changes: - Cleanups atomic-helper: - async-flip: Support on arbitrary planes - writeback: Fix use-after-free error - Document atomic-state history - Pleanty of cleanups to callback parameter names doc: - Test for kernel-doc errors format-helper: - Support ARGB8888-to-ARGB4444 pixel-format conversion panel-orientation-quirks: - Add quirks for AYANEO 2S, AYA NEO Flip DS and KB, AYA NEO Slide, GPD Win 2, OneXPlayer Mini (Intel) sched: - Add parameter struct for init Driver Changes: amdgpu: - Support device-wedged event - Support async pageflips on overlay planes amdxdna: - Refactoring ast: - Refactor cursor handling bridge: - Pass full atomic state to various callbacks - analogix-dp: Cleanups - cdns-mhdp8546: Fix clock enable/disable - nwl-dsi: Set bridge type - panel: Cleanups - ti-sn65dsi83: Add error recovery; Set bridge type i2c: - tda998x: Drop unused platform_data; Split driver into separate media and bridge drivers - Remove the obsolete directory i915: - Support device-wedged event nouveau: - Fixes panel: - visionox-r66451: Use multi-style MIPI-DSI functions v3d: - Handle clock vkms: - Fix use-after-free error xe: - Support device-wedged event xlnx: - Use mutex guards - Cleanups Signed-off-by: Dave Airlie <airlied@redhat.com> From: Thomas Zimmermann <tzimmermann@suse.de> Link: https://patchwork.freedesktop.org/patch/msgid/20250220085321.GA184551@linux.fritz.box
This commit is contained in:
@@ -35,6 +35,9 @@ properties:
|
||||
vcc-supply:
|
||||
description: A 1.8V power supply (see regulator/regulator.yaml).
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
|
||||
@@ -371,9 +371,119 @@ Reporting causes of resets
|
||||
|
||||
Apart from propagating the reset through the stack so apps can recover, it's
|
||||
really useful for driver developers to learn more about what caused the reset in
|
||||
the first place. DRM devices should make use of devcoredump to store relevant
|
||||
information about the reset, so this information can be added to user bug
|
||||
reports.
|
||||
the first place. For this, drivers can make use of devcoredump to store relevant
|
||||
information about the reset and send device wedged event with ``none`` recovery
|
||||
method (as explained in "Device Wedging" chapter) to notify userspace, so this
|
||||
information can be collected and added to user bug reports.
|
||||
|
||||
Device Wedging
|
||||
==============
|
||||
|
||||
Drivers can optionally make use of device wedged event (implemented as
|
||||
drm_dev_wedged_event() in DRM subsystem), which notifies userspace of 'wedged'
|
||||
(hanged/unusable) state of the DRM device through a uevent. This is useful
|
||||
especially in cases where the device is no longer operating as expected and has
|
||||
become unrecoverable from driver context. Purpose of this implementation is to
|
||||
provide drivers a generic way to recover the device with the help of userspace
|
||||
intervention, without taking any drastic measures (like resetting or
|
||||
re-enumerating the full bus, on which the underlying physical device is sitting)
|
||||
in the driver.
|
||||
|
||||
A 'wedged' device is basically a device that is declared dead by the driver
|
||||
after exhausting all possible attempts to recover it from driver context. The
|
||||
uevent is the notification that is sent to userspace along with a hint about
|
||||
what could possibly be attempted to recover the device from userspace and bring
|
||||
it back to usable state. Different drivers may have different ideas of a
|
||||
'wedged' device depending on hardware implementation of the underlying physical
|
||||
device, and hence the vendor agnostic nature of the event. It is up to the
|
||||
drivers to decide when they see the need for device recovery and how they want
|
||||
to recover from the available methods.
|
||||
|
||||
Driver prerequisites
|
||||
--------------------
|
||||
|
||||
The driver, before opting for recovery, needs to make sure that the 'wedged'
|
||||
device doesn't harm the system as a whole by taking care of the prerequisites.
|
||||
Necessary actions must include disabling DMA to system memory as well as any
|
||||
communication channels with other devices. Further, the driver must ensure
|
||||
that all dma_fences are signalled and any device state that the core kernel
|
||||
might depend on is cleaned up. All existing mmaps should be invalidated and
|
||||
page faults should be redirected to a dummy page. Once the event is sent, the
|
||||
device must be kept in 'wedged' state until the recovery is performed. New
|
||||
accesses to the device (IOCTLs) should be rejected, preferably with an error
|
||||
code that resembles the type of failure the device has encountered. This will
|
||||
signify the reason for wedging, which can be reported to the application if
|
||||
needed.
|
||||
|
||||
Recovery
|
||||
--------
|
||||
|
||||
Current implementation defines three recovery methods, out of which, drivers
|
||||
can use any one, multiple or none. Method(s) of choice will be sent in the
|
||||
uevent environment as ``WEDGED=<method1>[,..,<methodN>]`` in order of less to
|
||||
more side-effects. If driver is unsure about recovery or method is unknown
|
||||
(like soft/hard system reboot, firmware flashing, physical device replacement
|
||||
or any other procedure which can't be attempted on the fly), ``WEDGED=unknown``
|
||||
will be sent instead.
|
||||
|
||||
Userspace consumers can parse this event and attempt recovery as per the
|
||||
following expectations.
|
||||
|
||||
=============== ========================================
|
||||
Recovery method Consumer expectations
|
||||
=============== ========================================
|
||||
none optional telemetry collection
|
||||
rebind unbind + bind driver
|
||||
bus-reset unbind + bus reset/re-enumeration + bind
|
||||
unknown consumer policy
|
||||
=============== ========================================
|
||||
|
||||
The only exception to this is ``WEDGED=none``, which signifies that the device
|
||||
was temporarily 'wedged' at some point but was recovered from driver context
|
||||
using device specific methods like reset. No explicit recovery is expected from
|
||||
the consumer in this case, but it can still take additional steps like gathering
|
||||
telemetry information (devcoredump, syslog). This is useful because the first
|
||||
hang is usually the most critical one which can result in consequential hangs or
|
||||
complete wedging.
|
||||
|
||||
Consumer prerequisites
|
||||
----------------------
|
||||
|
||||
It is the responsibility of the consumer to make sure that the device or its
|
||||
resources are not in use by any process before attempting recovery. With IOCTLs
|
||||
erroring out, all device memory should be unmapped and file descriptors should
|
||||
be closed to prevent leaks or undefined behaviour. The idea here is to clear the
|
||||
device of all user context beforehand and set the stage for a clean recovery.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
Udev rule::
|
||||
|
||||
SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]",
|
||||
RUN+="/path/to/rebind.sh $env{DEVPATH}"
|
||||
|
||||
Recovery script::
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
DEVPATH=$(readlink -f /sys/$1/device)
|
||||
DEVICE=$(basename $DEVPATH)
|
||||
DRIVER=$(readlink -f $DEVPATH/driver)
|
||||
|
||||
echo -n $DEVICE > $DRIVER/unbind
|
||||
echo -n $DEVICE > $DRIVER/bind
|
||||
|
||||
Customization
|
||||
-------------
|
||||
|
||||
Although basic recovery is possible with a simple script, consumers can define
|
||||
custom policies around recovery. For example, if the driver supports multiple
|
||||
recovery methods, consumers can opt for the suitable one depending on scenarios
|
||||
like repeat offences or vendor specific failures. Consumers can also choose to
|
||||
have the device available for debugging or telemetry collection and base their
|
||||
recovery decision on the findings. This is useful especially when the driver is
|
||||
unsure about recovery or method is unknown.
|
||||
|
||||
.. _drm_driver_ioctl:
|
||||
|
||||
|
||||
1
Kbuild
1
Kbuild
@@ -97,3 +97,4 @@ obj-$(CONFIG_SAMPLES) += samples/
|
||||
obj-$(CONFIG_NET) += net/
|
||||
obj-y += virt/
|
||||
obj-y += $(ARCH_DRIVERS)
|
||||
obj-$(CONFIG_DRM_HEADER_TEST) += include/
|
||||
|
||||
@@ -8007,6 +8007,8 @@ F: include/drm/drm_privacy_screen*
|
||||
DRM TTM SUBSYSTEM
|
||||
M: Christian Koenig <christian.koenig@amd.com>
|
||||
M: Huang Rui <ray.huang@amd.com>
|
||||
R: Matthew Auld <matthew.auld@intel.com>
|
||||
R: Matthew Brost <matthew.brost@intel.com>
|
||||
L: dri-devel@lists.freedesktop.org
|
||||
S: Maintained
|
||||
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
|
||||
@@ -17120,8 +17122,7 @@ M: Russell King <linux@armlinux.org.uk>
|
||||
S: Maintained
|
||||
T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-devel
|
||||
T: git git://git.armlinux.org.uk/~rmk/linux-arm.git drm-tda998x-fixes
|
||||
F: drivers/gpu/drm/i2c/tda998x_drv.c
|
||||
F: include/drm/i2c/tda998x.h
|
||||
F: drivers/gpu/drm/bridge/tda998x_drv.c
|
||||
F: include/dt-bindings/display/tda998x.h
|
||||
K: "nxp,tda998x"
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ static void aie2_job_release(struct kref *ref)
|
||||
|
||||
job = container_of(ref, struct amdxdna_sched_job, refcnt);
|
||||
amdxdna_sched_job_cleanup(job);
|
||||
atomic64_inc(&job->hwctx->job_free_cnt);
|
||||
wake_up(&job->hwctx->priv->job_free_wq);
|
||||
if (job->out_fence)
|
||||
dma_fence_put(job->out_fence);
|
||||
kfree(job);
|
||||
@@ -134,7 +136,8 @@ static void aie2_hwctx_wait_for_idle(struct amdxdna_hwctx *hwctx)
|
||||
if (!fence)
|
||||
return;
|
||||
|
||||
dma_fence_wait(fence, false);
|
||||
/* Wait up to 2 seconds for fw to finish all pending requests */
|
||||
dma_fence_wait_timeout(fence, false, msecs_to_jiffies(2000));
|
||||
dma_fence_put(fence);
|
||||
}
|
||||
|
||||
@@ -516,6 +519,14 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
||||
{
|
||||
struct amdxdna_client *client = hwctx->client;
|
||||
struct amdxdna_dev *xdna = client->xdna;
|
||||
const struct drm_sched_init_args args = {
|
||||
.ops = &sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = HWCTX_MAX_CMDS,
|
||||
.timeout = msecs_to_jiffies(HWCTX_MAX_TIMEOUT),
|
||||
.name = hwctx->name,
|
||||
.dev = xdna->ddev.dev,
|
||||
};
|
||||
struct drm_gpu_scheduler *sched;
|
||||
struct amdxdna_hwctx_priv *priv;
|
||||
struct amdxdna_gem_obj *heap;
|
||||
@@ -573,9 +584,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
||||
might_lock(&priv->io_lock);
|
||||
fs_reclaim_release(GFP_KERNEL);
|
||||
|
||||
ret = drm_sched_init(sched, &sched_ops, NULL, DRM_SCHED_PRIORITY_COUNT,
|
||||
HWCTX_MAX_CMDS, 0, msecs_to_jiffies(HWCTX_MAX_TIMEOUT),
|
||||
NULL, NULL, hwctx->name, xdna->ddev.dev);
|
||||
ret = drm_sched_init(sched, &args);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Failed to init DRM scheduler. ret %d", ret);
|
||||
goto free_cmd_bufs;
|
||||
@@ -616,6 +625,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx)
|
||||
hwctx->status = HWCTX_STAT_INIT;
|
||||
ndev = xdna->dev_handle;
|
||||
ndev->hwctx_num++;
|
||||
init_waitqueue_head(&priv->job_free_wq);
|
||||
|
||||
XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name);
|
||||
|
||||
@@ -652,24 +662,22 @@ void aie2_hwctx_fini(struct amdxdna_hwctx *hwctx)
|
||||
xdna = hwctx->client->xdna;
|
||||
ndev = xdna->dev_handle;
|
||||
ndev->hwctx_num--;
|
||||
drm_sched_wqueue_stop(&hwctx->priv->sched);
|
||||
|
||||
/* Now, scheduler will not send command to device. */
|
||||
aie2_release_resource(hwctx);
|
||||
|
||||
/*
|
||||
* All submitted commands are aborted.
|
||||
* Restart scheduler queues to cleanup jobs. The amdxdna_sched_job_run()
|
||||
* will return NODEV if it is called.
|
||||
*/
|
||||
drm_sched_wqueue_start(&hwctx->priv->sched);
|
||||
|
||||
aie2_hwctx_wait_for_idle(hwctx);
|
||||
drm_sched_entity_destroy(&hwctx->priv->entity);
|
||||
drm_sched_fini(&hwctx->priv->sched);
|
||||
aie2_ctx_syncobj_destroy(hwctx);
|
||||
|
||||
XDNA_DBG(xdna, "%s sequence number %lld", hwctx->name, hwctx->priv->seq);
|
||||
drm_sched_entity_destroy(&hwctx->priv->entity);
|
||||
|
||||
aie2_hwctx_wait_for_idle(hwctx);
|
||||
|
||||
/* Request fw to destroy hwctx and cancel the rest pending requests */
|
||||
aie2_release_resource(hwctx);
|
||||
|
||||
/* Wait for all submitted jobs to be completed or canceled */
|
||||
wait_event(hwctx->priv->job_free_wq,
|
||||
atomic64_read(&hwctx->job_submit_cnt) ==
|
||||
atomic64_read(&hwctx->job_free_cnt));
|
||||
|
||||
drm_sched_fini(&hwctx->priv->sched);
|
||||
aie2_ctx_syncobj_destroy(hwctx);
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(hwctx->priv->cmd_buf); idx++)
|
||||
drm_gem_object_put(to_gobj(hwctx->priv->cmd_buf[idx]));
|
||||
@@ -879,6 +887,7 @@ int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job,
|
||||
drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx);
|
||||
|
||||
aie2_job_put(job);
|
||||
atomic64_inc(&hwctx->job_submit_cnt);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -220,6 +220,8 @@ int amdxdna_drm_create_hwctx_ioctl(struct drm_device *dev, void *data, struct dr
|
||||
args->syncobj_handle = hwctx->syncobj_hdl;
|
||||
mutex_unlock(&xdna->dev_lock);
|
||||
|
||||
atomic64_set(&hwctx->job_submit_cnt, 0);
|
||||
atomic64_set(&hwctx->job_free_cnt, 0);
|
||||
XDNA_DBG(xdna, "PID %d create HW context %d, ret %d", client->pid, args->handle, ret);
|
||||
drm_dev_exit(idx);
|
||||
return 0;
|
||||
|
||||
@@ -87,6 +87,9 @@ struct amdxdna_hwctx {
|
||||
struct amdxdna_qos_info qos;
|
||||
struct amdxdna_hwctx_param_config_cu *cus;
|
||||
u32 syncobj_hdl;
|
||||
|
||||
atomic64_t job_submit_cnt;
|
||||
atomic64_t job_free_cnt ____cacheline_aligned_in_smp;
|
||||
};
|
||||
|
||||
#define drm_job_to_xdna_job(j) \
|
||||
|
||||
@@ -326,8 +326,6 @@ config DRM_SCHED
|
||||
tristate
|
||||
depends on DRM
|
||||
|
||||
source "drivers/gpu/drm/i2c/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/arm/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/radeon/Kconfig"
|
||||
@@ -494,6 +492,17 @@ config DRM_WERROR
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
config DRM_HEADER_TEST
|
||||
bool "Ensure DRM headers are self-contained and pass kernel-doc"
|
||||
depends on DRM && EXPERT
|
||||
default n
|
||||
help
|
||||
Ensure the DRM subsystem headers both under drivers/gpu/drm and
|
||||
include/drm compile, are self-contained, have header guards, and have
|
||||
no kernel-doc warnings.
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
endif
|
||||
|
||||
# Separate option because drm_panel_orientation_quirks.c is shared with fbdev
|
||||
|
||||
@@ -197,7 +197,6 @@ obj-$(CONFIG_DRM_INGENIC) += ingenic/
|
||||
obj-$(CONFIG_DRM_LOGICVC) += logicvc/
|
||||
obj-$(CONFIG_DRM_MEDIATEK) += mediatek/
|
||||
obj-$(CONFIG_DRM_MESON) += meson/
|
||||
obj-y += i2c/
|
||||
obj-y += panel/
|
||||
obj-y += bridge/
|
||||
obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/
|
||||
@@ -222,3 +221,21 @@ obj-y += solomon/
|
||||
obj-$(CONFIG_DRM_SPRD) += sprd/
|
||||
obj-$(CONFIG_DRM_LOONGSON) += loongson/
|
||||
obj-$(CONFIG_DRM_POWERVR) += imagination/
|
||||
|
||||
# Ensure drm headers are self-contained and pass kernel-doc
|
||||
hdrtest-files := \
|
||||
$(shell cd $(src) && find . -maxdepth 1 -name 'drm_*.h') \
|
||||
$(shell cd $(src) && find display lib -name '*.h')
|
||||
|
||||
always-$(CONFIG_DRM_HEADER_TEST) += \
|
||||
$(patsubst %.h,%.hdrtest, $(hdrtest-files))
|
||||
|
||||
# Include the header twice to detect missing include guard.
|
||||
quiet_cmd_hdrtest = HDRTEST $(patsubst %.hdrtest,%.h,$@)
|
||||
cmd_hdrtest = \
|
||||
$(CC) $(c_flags) -fsyntax-only -x c /dev/null -include $< -include $<; \
|
||||
$(srctree)/scripts/kernel-doc -none $(if $(CONFIG_WERROR)$(CONFIG_DRM_WERROR),-Werror) $<; \
|
||||
touch $@
|
||||
|
||||
$(obj)/%.hdrtest: $(src)/%.h FORCE
|
||||
$(call if_changed_dep,hdrtest)
|
||||
|
||||
@@ -2823,6 +2823,12 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
|
||||
|
||||
static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_sched_init_args args = {
|
||||
.ops = &amdgpu_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.timeout_wq = adev->reset_domain->wq,
|
||||
.dev = adev->dev,
|
||||
};
|
||||
long timeout;
|
||||
int r, i;
|
||||
|
||||
@@ -2848,12 +2854,12 @@ static int amdgpu_device_init_schedulers(struct amdgpu_device *adev)
|
||||
break;
|
||||
}
|
||||
|
||||
r = drm_sched_init(&ring->sched, &amdgpu_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
ring->num_hw_submission, 0,
|
||||
timeout, adev->reset_domain->wq,
|
||||
ring->sched_score, ring->name,
|
||||
adev->dev);
|
||||
args.timeout = timeout;
|
||||
args.credit_limit = ring->num_hw_submission;
|
||||
args.score = ring->sched_score;
|
||||
args.name = ring->name;
|
||||
|
||||
r = drm_sched_init(&ring->sched, &args);
|
||||
if (r) {
|
||||
DRM_ERROR("Failed to create scheduler on ring %s.\n",
|
||||
ring->name);
|
||||
@@ -6116,6 +6122,10 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
|
||||
dev_info(adev->dev, "GPU reset end with ret = %d\n", r);
|
||||
|
||||
atomic_set(&adev->reset_domain->reset_res, r);
|
||||
|
||||
if (!r)
|
||||
drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -1258,21 +1258,24 @@ static int amdgpu_dm_plane_atomic_check(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static int amdgpu_dm_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *state, bool flip)
|
||||
{
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_plane_state *new_plane_state;
|
||||
struct dm_crtc_state *dm_new_crtc_state;
|
||||
|
||||
/* Only support async updates on cursor planes. */
|
||||
if (plane->type != DRM_PLANE_TYPE_CURSOR)
|
||||
if (flip) {
|
||||
if (plane->type != DRM_PLANE_TYPE_OVERLAY)
|
||||
return -EINVAL;
|
||||
} else if (plane->type != DRM_PLANE_TYPE_CURSOR) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
|
||||
dm_new_crtc_state = to_dm_crtc_state(new_crtc_state);
|
||||
/* Reject overlay cursors for now*/
|
||||
if (dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
|
||||
if (!flip && dm_new_crtc_state->cursor_mode == DM_CURSOR_OVERLAY_MODE)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -9,6 +9,7 @@ config DRM_HDLCD
|
||||
select DRM_CLIENT_SELECTION
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_BRIDGE # for TDA998x
|
||||
help
|
||||
Choose this option if you have an ARM High Definition Colour LCD
|
||||
controller.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
ast-y := \
|
||||
ast_cursor.o \
|
||||
ast_ddc.o \
|
||||
ast_dp501.o \
|
||||
ast_dp.o \
|
||||
|
||||
309
drivers/gpu/drm/ast/ast_cursor.c
Normal file
309
drivers/gpu/drm/ast/ast_cursor.c
Normal file
@@ -0,0 +1,309 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
|
||||
/*
|
||||
* Hardware cursor
|
||||
*/
|
||||
|
||||
/* define for signature structure */
|
||||
#define AST_HWC_SIGNATURE_CHECKSUM 0x00
|
||||
#define AST_HWC_SIGNATURE_SizeX 0x04
|
||||
#define AST_HWC_SIGNATURE_SizeY 0x08
|
||||
#define AST_HWC_SIGNATURE_X 0x0C
|
||||
#define AST_HWC_SIGNATURE_Y 0x10
|
||||
#define AST_HWC_SIGNATURE_HOTSPOTX 0x14
|
||||
#define AST_HWC_SIGNATURE_HOTSPOTY 0x18
|
||||
|
||||
static u32 ast_cursor_calculate_checksum(const void *src, unsigned int width, unsigned int height)
|
||||
{
|
||||
u32 csum = 0;
|
||||
unsigned int one_pixel_copy = width & BIT(0);
|
||||
unsigned int two_pixel_copy = width - one_pixel_copy;
|
||||
unsigned int trailing_bytes = (AST_MAX_HWC_WIDTH - width) * sizeof(u16);
|
||||
unsigned int x, y;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < two_pixel_copy; x += 2) {
|
||||
const u32 *src32 = (const u32 *)src;
|
||||
|
||||
csum += *src32;
|
||||
src += SZ_4;
|
||||
}
|
||||
if (one_pixel_copy) {
|
||||
const u16 *src16 = (const u16 *)src;
|
||||
|
||||
csum += *src16;
|
||||
src += SZ_2;
|
||||
}
|
||||
src += trailing_bytes;
|
||||
}
|
||||
|
||||
return csum;
|
||||
}
|
||||
|
||||
static void ast_set_cursor_image(struct ast_device *ast, const u8 *src,
|
||||
unsigned int width, unsigned int height)
|
||||
{
|
||||
u8 __iomem *dst = ast->cursor_plane.base.vaddr;
|
||||
u32 csum;
|
||||
|
||||
csum = ast_cursor_calculate_checksum(src, width, height);
|
||||
|
||||
/* write pixel data */
|
||||
memcpy_toio(dst, src, AST_HWC_SIZE);
|
||||
|
||||
/* write checksum + signature */
|
||||
dst += AST_HWC_SIZE;
|
||||
writel(csum, dst);
|
||||
writel(width, dst + AST_HWC_SIGNATURE_SizeX);
|
||||
writel(height, dst + AST_HWC_SIGNATURE_SizeY);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_base(struct ast_device *ast, u64 address)
|
||||
{
|
||||
u8 addr0 = (address >> 3) & 0xff;
|
||||
u8 addr1 = (address >> 11) & 0xff;
|
||||
u8 addr2 = (address >> 19) & 0xff;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y,
|
||||
u8 x_offset, u8 y_offset)
|
||||
{
|
||||
u8 x0 = (x & 0x00ff);
|
||||
u8 x1 = (x & 0x0f00) >> 8;
|
||||
u8 y0 = (y & 0x00ff);
|
||||
u8 y1 = (y & 0x0700) >> 8;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled)
|
||||
{
|
||||
static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
|
||||
AST_IO_VGACRCB_HWC_ENABLED);
|
||||
|
||||
u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP;
|
||||
|
||||
if (enabled)
|
||||
vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED;
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cursor plane
|
||||
*/
|
||||
|
||||
static const uint32_t ast_cursor_plane_formats[] = {
|
||||
DRM_FORMAT_ARGB4444,
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_framebuffer *new_fb = new_plane_state->fb;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
int ret;
|
||||
|
||||
if (new_plane_state->crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
true, true);
|
||||
if (ret || !new_plane_state->visible)
|
||||
return ret;
|
||||
|
||||
if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane);
|
||||
struct ast_plane *ast_plane = to_ast_plane(plane);
|
||||
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct ast_device *ast = to_ast_device(plane->dev);
|
||||
struct drm_rect damage;
|
||||
u64 dst_off = ast_plane->offset;
|
||||
u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
|
||||
u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
|
||||
unsigned int offset_x, offset_y;
|
||||
u16 x, y;
|
||||
u8 x_offset, y_offset;
|
||||
|
||||
/*
|
||||
* Do data transfer to hardware buffer and point the scanout
|
||||
* engine to the offset.
|
||||
*/
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
|
||||
u8 *argb4444;
|
||||
|
||||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_ARGB4444:
|
||||
argb4444 = shadow_plane_state->data[0].vaddr;
|
||||
break;
|
||||
default:
|
||||
argb4444 = ast_cursor_plane->argb4444;
|
||||
{
|
||||
struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = {
|
||||
IOSYS_MAP_INIT_VADDR(argb4444),
|
||||
};
|
||||
unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
|
||||
AST_HWC_PITCH,
|
||||
};
|
||||
|
||||
drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch,
|
||||
shadow_plane_state->data, fb, &damage,
|
||||
&shadow_plane_state->fmtcnv_state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
ast_set_cursor_image(ast, argb4444, fb->width, fb->height);
|
||||
ast_set_cursor_base(ast, dst_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update location in HWC signature and registers.
|
||||
*/
|
||||
|
||||
writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
|
||||
writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
|
||||
|
||||
offset_x = AST_MAX_HWC_WIDTH - fb->width;
|
||||
offset_y = AST_MAX_HWC_HEIGHT - fb->height;
|
||||
|
||||
if (plane_state->crtc_x < 0) {
|
||||
x_offset = (-plane_state->crtc_x) + offset_x;
|
||||
x = 0;
|
||||
} else {
|
||||
x_offset = offset_x;
|
||||
x = plane_state->crtc_x;
|
||||
}
|
||||
if (plane_state->crtc_y < 0) {
|
||||
y_offset = (-plane_state->crtc_y) + offset_y;
|
||||
y = 0;
|
||||
} else {
|
||||
y_offset = offset_y;
|
||||
y = plane_state->crtc_y;
|
||||
}
|
||||
|
||||
ast_set_cursor_location(ast, x, y, x_offset, y_offset);
|
||||
|
||||
/* Dummy write to enable HWC and make the HW pick-up the changes. */
|
||||
ast_set_cursor_enabled(ast, true);
|
||||
}
|
||||
|
||||
static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(plane->dev);
|
||||
|
||||
ast_set_cursor_enabled(ast, false);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.atomic_check = ast_cursor_plane_helper_atomic_check,
|
||||
.atomic_update = ast_cursor_plane_helper_atomic_update,
|
||||
.atomic_disable = ast_cursor_plane_helper_atomic_disable,
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs ast_cursor_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = drm_plane_cleanup,
|
||||
DRM_GEM_SHADOW_PLANE_FUNCS,
|
||||
};
|
||||
|
||||
int ast_cursor_plane_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane;
|
||||
struct ast_plane *ast_plane = &ast_cursor_plane->base;
|
||||
struct drm_plane *cursor_plane = &ast_plane->base;
|
||||
size_t size;
|
||||
void __iomem *vaddr;
|
||||
u64 offset;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allocate backing storage for cursors. The BOs are permanently
|
||||
* pinned to the top end of the VRAM.
|
||||
*/
|
||||
|
||||
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
|
||||
if (ast->vram_fb_available < size)
|
||||
return -ENOMEM;
|
||||
|
||||
vaddr = ast->vram + ast->vram_fb_available - size;
|
||||
offset = ast->vram_fb_available - size;
|
||||
|
||||
ret = ast_plane_init(dev, ast_plane, vaddr, offset, size,
|
||||
0x01, &ast_cursor_plane_funcs,
|
||||
ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
|
||||
NULL, DRM_PLANE_TYPE_CURSOR);
|
||||
if (ret) {
|
||||
drm_err(dev, "ast_plane_init() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
|
||||
drm_plane_enable_fb_damage_clips(cursor_plane);
|
||||
|
||||
ast->vram_fb_available -= size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -113,17 +113,10 @@ enum ast_config_mode {
|
||||
#define AST_MAX_HWC_WIDTH 64
|
||||
#define AST_MAX_HWC_HEIGHT 64
|
||||
|
||||
#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2)
|
||||
#define AST_HWC_SIGNATURE_SIZE 32
|
||||
#define AST_HWC_PITCH (AST_MAX_HWC_WIDTH * SZ_2)
|
||||
#define AST_HWC_SIZE (AST_MAX_HWC_HEIGHT * AST_HWC_PITCH)
|
||||
|
||||
/* define for signature structure */
|
||||
#define AST_HWC_SIGNATURE_CHECKSUM 0x00
|
||||
#define AST_HWC_SIGNATURE_SizeX 0x04
|
||||
#define AST_HWC_SIGNATURE_SizeY 0x08
|
||||
#define AST_HWC_SIGNATURE_X 0x0C
|
||||
#define AST_HWC_SIGNATURE_Y 0x10
|
||||
#define AST_HWC_SIGNATURE_HOTSPOTX 0x14
|
||||
#define AST_HWC_SIGNATURE_HOTSPOTY 0x18
|
||||
#define AST_HWC_SIGNATURE_SIZE 32
|
||||
|
||||
/*
|
||||
* Planes
|
||||
@@ -142,6 +135,17 @@ static inline struct ast_plane *to_ast_plane(struct drm_plane *plane)
|
||||
return container_of(plane, struct ast_plane, base);
|
||||
}
|
||||
|
||||
struct ast_cursor_plane {
|
||||
struct ast_plane base;
|
||||
|
||||
u8 argb4444[AST_HWC_SIZE];
|
||||
};
|
||||
|
||||
static inline struct ast_cursor_plane *to_ast_cursor_plane(struct drm_plane *plane)
|
||||
{
|
||||
return container_of(to_ast_plane(plane), struct ast_cursor_plane, base);
|
||||
}
|
||||
|
||||
/*
|
||||
* Connector
|
||||
*/
|
||||
@@ -186,7 +190,7 @@ struct ast_device {
|
||||
enum ast_tx_chip tx_chip;
|
||||
|
||||
struct ast_plane primary_plane;
|
||||
struct ast_plane cursor_plane;
|
||||
struct ast_cursor_plane cursor_plane;
|
||||
struct drm_crtc crtc;
|
||||
union {
|
||||
struct {
|
||||
@@ -370,8 +374,6 @@ struct ast_crtc_state {
|
||||
|
||||
#define to_ast_crtc_state(state) container_of(state, struct ast_crtc_state, base)
|
||||
|
||||
int ast_mode_config_init(struct ast_device *ast);
|
||||
|
||||
#define AST_MM_ALIGN_SHIFT 4
|
||||
#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
|
||||
|
||||
@@ -437,6 +439,9 @@ void ast_patch_ahb_2500(void __iomem *regs);
|
||||
int ast_vga_output_init(struct ast_device *ast);
|
||||
int ast_sil164_output_init(struct ast_device *ast);
|
||||
|
||||
/* ast_cursor.c */
|
||||
int ast_cursor_plane_init(struct ast_device *ast);
|
||||
|
||||
/* ast dp501 */
|
||||
bool ast_backup_fw(struct ast_device *ast, u8 *addr, u32 size);
|
||||
void ast_init_3rdtx(struct ast_device *ast);
|
||||
@@ -446,4 +451,14 @@ int ast_dp501_output_init(struct ast_device *ast);
|
||||
int ast_dp_launch(struct ast_device *ast);
|
||||
int ast_astdp_output_init(struct ast_device *ast);
|
||||
|
||||
/* ast_mode.c */
|
||||
int ast_mode_config_init(struct ast_device *ast);
|
||||
int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
|
||||
void __iomem *vaddr, u64 offset, unsigned long size,
|
||||
uint32_t possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
const uint64_t *format_modifiers,
|
||||
enum drm_plane_type type);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -438,13 +438,13 @@ static void ast_wait_for_vretrace(struct ast_device *ast)
|
||||
* Planes
|
||||
*/
|
||||
|
||||
static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
|
||||
void __iomem *vaddr, u64 offset, unsigned long size,
|
||||
uint32_t possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
const uint64_t *format_modifiers,
|
||||
enum drm_plane_type type)
|
||||
int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
|
||||
void __iomem *vaddr, u64 offset, unsigned long size,
|
||||
uint32_t possible_crtcs,
|
||||
const struct drm_plane_funcs *funcs,
|
||||
const uint32_t *formats, unsigned int format_count,
|
||||
const uint64_t *format_modifiers,
|
||||
enum drm_plane_type type)
|
||||
{
|
||||
struct drm_plane *plane = &ast_plane->base;
|
||||
|
||||
@@ -628,263 +628,6 @@ static int ast_primary_plane_init(struct ast_device *ast)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Cursor plane
|
||||
*/
|
||||
|
||||
static void ast_update_cursor_image(u8 __iomem *dst, const u8 *src, int width, int height)
|
||||
{
|
||||
union {
|
||||
u32 ul;
|
||||
u8 b[4];
|
||||
} srcdata32[2], data32;
|
||||
union {
|
||||
u16 us;
|
||||
u8 b[2];
|
||||
} data16;
|
||||
u32 csum = 0;
|
||||
s32 alpha_dst_delta, last_alpha_dst_delta;
|
||||
u8 __iomem *dstxor;
|
||||
const u8 *srcxor;
|
||||
int i, j;
|
||||
u32 per_pixel_copy, two_pixel_copy;
|
||||
|
||||
alpha_dst_delta = AST_MAX_HWC_WIDTH << 1;
|
||||
last_alpha_dst_delta = alpha_dst_delta - (width << 1);
|
||||
|
||||
srcxor = src;
|
||||
dstxor = (u8 *)dst + last_alpha_dst_delta + (AST_MAX_HWC_HEIGHT - height) * alpha_dst_delta;
|
||||
per_pixel_copy = width & 1;
|
||||
two_pixel_copy = width >> 1;
|
||||
|
||||
for (j = 0; j < height; j++) {
|
||||
for (i = 0; i < two_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
srcdata32[1].ul = *((u32 *)(srcxor + 4)) & 0xf0f0f0f0;
|
||||
data32.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data32.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
data32.b[2] = srcdata32[1].b[1] | (srcdata32[1].b[0] >> 4);
|
||||
data32.b[3] = srcdata32[1].b[3] | (srcdata32[1].b[2] >> 4);
|
||||
|
||||
writel(data32.ul, dstxor);
|
||||
csum += data32.ul;
|
||||
|
||||
dstxor += 4;
|
||||
srcxor += 8;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < per_pixel_copy; i++) {
|
||||
srcdata32[0].ul = *((u32 *)srcxor) & 0xf0f0f0f0;
|
||||
data16.b[0] = srcdata32[0].b[1] | (srcdata32[0].b[0] >> 4);
|
||||
data16.b[1] = srcdata32[0].b[3] | (srcdata32[0].b[2] >> 4);
|
||||
writew(data16.us, dstxor);
|
||||
csum += (u32)data16.us;
|
||||
|
||||
dstxor += 2;
|
||||
srcxor += 4;
|
||||
}
|
||||
dstxor += last_alpha_dst_delta;
|
||||
}
|
||||
|
||||
/* write checksum + signature */
|
||||
dst += AST_HWC_SIZE;
|
||||
writel(csum, dst);
|
||||
writel(width, dst + AST_HWC_SIGNATURE_SizeX);
|
||||
writel(height, dst + AST_HWC_SIGNATURE_SizeY);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTX);
|
||||
writel(0, dst + AST_HWC_SIGNATURE_HOTSPOTY);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_base(struct ast_device *ast, u64 address)
|
||||
{
|
||||
u8 addr0 = (address >> 3) & 0xff;
|
||||
u8 addr1 = (address >> 11) & 0xff;
|
||||
u8 addr2 = (address >> 19) & 0xff;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc8, addr0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc9, addr1);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xca, addr2);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_location(struct ast_device *ast, u16 x, u16 y,
|
||||
u8 x_offset, u8 y_offset)
|
||||
{
|
||||
u8 x0 = (x & 0x00ff);
|
||||
u8 x1 = (x & 0x0f00) >> 8;
|
||||
u8 y0 = (y & 0x00ff);
|
||||
u8 y1 = (y & 0x0700) >> 8;
|
||||
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc2, x_offset);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc3, y_offset);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc4, x0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc5, x1);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc6, y0);
|
||||
ast_set_index_reg(ast, AST_IO_VGACRI, 0xc7, y1);
|
||||
}
|
||||
|
||||
static void ast_set_cursor_enabled(struct ast_device *ast, bool enabled)
|
||||
{
|
||||
static const u8 mask = (u8)~(AST_IO_VGACRCB_HWC_16BPP |
|
||||
AST_IO_VGACRCB_HWC_ENABLED);
|
||||
|
||||
u8 vgacrcb = AST_IO_VGACRCB_HWC_16BPP;
|
||||
|
||||
if (enabled)
|
||||
vgacrcb |= AST_IO_VGACRCB_HWC_ENABLED;
|
||||
|
||||
ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xcb, mask, vgacrcb);
|
||||
}
|
||||
|
||||
static const uint32_t ast_cursor_plane_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_framebuffer *new_fb = new_plane_state->fb;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
int ret;
|
||||
|
||||
if (new_plane_state->crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
true, true);
|
||||
if (ret || !new_plane_state->visible)
|
||||
return ret;
|
||||
|
||||
if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ast_plane *ast_plane = to_ast_plane(plane);
|
||||
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
|
||||
struct drm_framebuffer *fb = plane_state->fb;
|
||||
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct ast_device *ast = to_ast_device(plane->dev);
|
||||
struct iosys_map src_map = shadow_plane_state->data[0];
|
||||
struct drm_rect damage;
|
||||
const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
|
||||
u64 dst_off = ast_plane->offset;
|
||||
u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
|
||||
u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
|
||||
unsigned int offset_x, offset_y;
|
||||
u16 x, y;
|
||||
u8 x_offset, y_offset;
|
||||
|
||||
/*
|
||||
* Do data transfer to hardware buffer and point the scanout
|
||||
* engine to the offset.
|
||||
*/
|
||||
|
||||
if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
|
||||
ast_update_cursor_image(dst, src, fb->width, fb->height);
|
||||
ast_set_cursor_base(ast, dst_off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update location in HWC signature and registers.
|
||||
*/
|
||||
|
||||
writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
|
||||
writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
|
||||
|
||||
offset_x = AST_MAX_HWC_WIDTH - fb->width;
|
||||
offset_y = AST_MAX_HWC_HEIGHT - fb->height;
|
||||
|
||||
if (plane_state->crtc_x < 0) {
|
||||
x_offset = (-plane_state->crtc_x) + offset_x;
|
||||
x = 0;
|
||||
} else {
|
||||
x_offset = offset_x;
|
||||
x = plane_state->crtc_x;
|
||||
}
|
||||
if (plane_state->crtc_y < 0) {
|
||||
y_offset = (-plane_state->crtc_y) + offset_y;
|
||||
y = 0;
|
||||
} else {
|
||||
y_offset = offset_y;
|
||||
y = plane_state->crtc_y;
|
||||
}
|
||||
|
||||
ast_set_cursor_location(ast, x, y, x_offset, y_offset);
|
||||
|
||||
/* Dummy write to enable HWC and make the HW pick-up the changes. */
|
||||
ast_set_cursor_enabled(ast, true);
|
||||
}
|
||||
|
||||
static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ast_device *ast = to_ast_device(plane->dev);
|
||||
|
||||
ast_set_cursor_enabled(ast, false);
|
||||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
|
||||
DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
|
||||
.atomic_check = ast_cursor_plane_helper_atomic_check,
|
||||
.atomic_update = ast_cursor_plane_helper_atomic_update,
|
||||
.atomic_disable = ast_cursor_plane_helper_atomic_disable,
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs ast_cursor_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = drm_plane_cleanup,
|
||||
DRM_GEM_SHADOW_PLANE_FUNCS,
|
||||
};
|
||||
|
||||
static int ast_cursor_plane_init(struct ast_device *ast)
|
||||
{
|
||||
struct drm_device *dev = &ast->base;
|
||||
struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
|
||||
struct drm_plane *cursor_plane = &ast_cursor_plane->base;
|
||||
size_t size;
|
||||
void __iomem *vaddr;
|
||||
u64 offset;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allocate backing storage for cursors. The BOs are permanently
|
||||
* pinned to the top end of the VRAM.
|
||||
*/
|
||||
|
||||
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
|
||||
|
||||
if (ast->vram_fb_available < size)
|
||||
return -ENOMEM;
|
||||
|
||||
vaddr = ast->vram + ast->vram_fb_available - size;
|
||||
offset = ast->vram_fb_available - size;
|
||||
|
||||
ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
|
||||
0x01, &ast_cursor_plane_funcs,
|
||||
ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
|
||||
NULL, DRM_PLANE_TYPE_CURSOR);
|
||||
if (ret) {
|
||||
drm_err(dev, "ast_plane_init() failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
|
||||
drm_plane_enable_fb_damage_clips(cursor_plane);
|
||||
|
||||
ast->vram_fb_available -= size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CRTC
|
||||
*/
|
||||
@@ -1156,7 +899,7 @@ static int ast_crtc_init(struct ast_device *ast)
|
||||
int ret;
|
||||
|
||||
ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
|
||||
&ast->cursor_plane.base, &ast_crtc_funcs,
|
||||
&ast->cursor_plane.base.base, &ast_crtc_funcs,
|
||||
NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -90,6 +90,14 @@ config DRM_FSL_LDB
|
||||
help
|
||||
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
|
||||
|
||||
config DRM_I2C_NXP_TDA998X
|
||||
tristate "NXP Semiconductors TDA998X HDMI encoder"
|
||||
default m if DRM_TILCDC
|
||||
select CEC_CORE if CEC_NOTIFIER
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
help
|
||||
Support for NXP Semiconductors TDA998X HDMI encoders.
|
||||
|
||||
config DRM_ITE_IT6263
|
||||
tristate "ITE IT6263 LVDS/HDMI bridge"
|
||||
depends on OF
|
||||
|
||||
@@ -6,6 +6,10 @@ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
|
||||
obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
|
||||
obj-$(CONFIG_DRM_DISPLAY_CONNECTOR) += display-connector.o
|
||||
obj-$(CONFIG_DRM_FSL_LDB) += fsl-ldb.o
|
||||
|
||||
tda998x-y := tda998x_drv.o
|
||||
obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
|
||||
|
||||
obj-$(CONFIG_DRM_ITE_IT6263) += ite-it6263.o
|
||||
obj-$(CONFIG_DRM_ITE_IT6505) += ite-it6505.o
|
||||
obj-$(CONFIG_DRM_LONTIUM_LT8912B) += lontium-lt8912b.o
|
||||
|
||||
@@ -911,7 +911,7 @@ static struct adv7511 *bridge_to_adv7511(struct drm_bridge *bridge)
|
||||
}
|
||||
|
||||
static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
|
||||
@@ -919,7 +919,7 @@ static void adv7511_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void adv7511_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct adv7511 *adv = bridge_to_adv7511(bridge);
|
||||
|
||||
|
||||
@@ -1197,11 +1197,9 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
|
||||
return conn_state->crtc;
|
||||
}
|
||||
|
||||
static void
|
||||
analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_atomic_state *old_state = old_bridge_state->base.state;
|
||||
struct analogix_dp_device *dp = bridge->driver_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -1257,11 +1255,9 @@ static int analogix_dp_set_bridge(struct analogix_dp_device *dp)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_atomic_state *old_state = old_bridge_state->base.state;
|
||||
struct analogix_dp_device *dp = bridge->driver_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -1327,11 +1323,9 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
|
||||
dp->dpms_mode = DRM_MODE_DPMS_OFF;
|
||||
}
|
||||
|
||||
static void
|
||||
analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_atomic_state *old_state = old_bridge_state->base.state;
|
||||
struct analogix_dp_device *dp = bridge->driver_private;
|
||||
struct drm_crtc *old_crtc, *new_crtc;
|
||||
struct drm_crtc_state *old_crtc_state = NULL;
|
||||
@@ -1367,11 +1361,9 @@ analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
analogix_dp_bridge_disable(bridge);
|
||||
}
|
||||
|
||||
static void
|
||||
analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_atomic_state *old_state = old_bridge_state->base.state;
|
||||
struct analogix_dp_device *dp = bridge->driver_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
@@ -1553,7 +1545,6 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct analogix_dp_device *dp;
|
||||
struct resource *res;
|
||||
unsigned int irq_flags;
|
||||
int ret;
|
||||
|
||||
@@ -1605,9 +1596,7 @@ analogix_dp_probe(struct device *dev, struct analogix_dp_plat_data *plat_data)
|
||||
return ERR_CAST(dp->clock);
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||
dp->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(dp->reg_base)) {
|
||||
ret = PTR_ERR(dp->reg_base);
|
||||
goto err_disable_clk;
|
||||
|
||||
@@ -2380,7 +2380,7 @@ static int anx7625_bridge_atomic_check(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = ctx->dev;
|
||||
@@ -2389,7 +2389,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
|
||||
dev_dbg(dev, "drm atomic enable\n");
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state->base.state,
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
if (!connector)
|
||||
return;
|
||||
@@ -2401,7 +2401,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
|
||||
anx7625_dp_start(ctx);
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state->base.state, connector);
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
|
||||
if (WARN_ON(!conn_state))
|
||||
return;
|
||||
@@ -2419,7 +2419,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = ctx->dev;
|
||||
|
||||
@@ -1979,10 +1979,9 @@ static void cdns_mhdp_sst_enable(struct cdns_mhdp_device *mhdp,
|
||||
}
|
||||
|
||||
static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct cdns_mhdp_bridge_state *mhdp_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
@@ -2070,7 +2069,7 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void cdns_mhdp_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
|
||||
u32 resp;
|
||||
@@ -2463,9 +2462,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
if (!mhdp)
|
||||
return -ENOMEM;
|
||||
|
||||
clk = devm_clk_get(dev, NULL);
|
||||
clk = devm_clk_get_enabled(dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "couldn't get clk: %ld\n", PTR_ERR(clk));
|
||||
dev_err(dev, "couldn't get and enable clk: %ld\n", PTR_ERR(clk));
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
@@ -2504,14 +2503,12 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
|
||||
mhdp->info = of_device_get_match_data(dev);
|
||||
|
||||
clk_prepare_enable(clk);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = pm_runtime_resume_and_get(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "pm_runtime_resume_and_get failed\n");
|
||||
pm_runtime_disable(dev);
|
||||
goto clk_disable;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mhdp->info && mhdp->info->ops && mhdp->info->ops->init) {
|
||||
@@ -2590,8 +2587,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
|
||||
runtime_put:
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(mhdp->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2632,8 +2627,6 @@ static void cdns_mhdp_remove(struct platform_device *pdev)
|
||||
cancel_work_sync(&mhdp->modeset_retry_work);
|
||||
flush_work(&mhdp->hpd_work);
|
||||
/* Ignoring mhdp->hdcp.check_work and mhdp->hdcp.prop_work here. */
|
||||
|
||||
clk_disable_unprepare(mhdp->clk);
|
||||
}
|
||||
|
||||
static const struct of_device_id mhdp_ids[] = {
|
||||
|
||||
@@ -341,10 +341,9 @@ static void chipone_configure_pll(struct chipone *icn,
|
||||
}
|
||||
|
||||
static void chipone_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct drm_display_mode *mode = &icn->mode;
|
||||
const struct drm_bridge_state *bridge_state;
|
||||
u16 hfp, hbp, hsync;
|
||||
@@ -445,7 +444,7 @@ static void chipone_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void chipone_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
int ret;
|
||||
@@ -482,7 +481,7 @@ static void chipone_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void chipone_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
|
||||
|
||||
@@ -122,10 +122,9 @@ static int fsl_ldb_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
const struct drm_bridge_state *bridge_state;
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
const struct drm_display_mode *mode;
|
||||
@@ -224,7 +223,7 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void fsl_ldb_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct fsl_ldb *fsl_ldb = to_fsl_ldb(bridge);
|
||||
|
||||
|
||||
@@ -49,16 +49,17 @@ static int imx8mp_hdmi_pvi_bridge_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void imx8mp_hdmi_pvi_bridge_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_bridge_state *bridge_state;
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
u32 bus_flags = 0, val;
|
||||
|
||||
bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
|
||||
@@ -88,7 +89,7 @@ static void imx8mp_hdmi_pvi_bridge_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void imx8mp_hdmi_pvi_bridge_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct imx8mp_hdmi_pvi *pvi = to_imx8mp_hdmi_pvi(bridge);
|
||||
|
||||
|
||||
@@ -200,9 +200,8 @@ imx8qm_ldb_bridge_mode_set(struct drm_bridge *bridge,
|
||||
CH_HSYNC_M(chno), CH_PHSYNC(chno));
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ldb_channel *ldb_ch = bridge->driver_private;
|
||||
struct ldb *ldb = ldb_ch->ldb;
|
||||
@@ -247,9 +246,8 @@ imx8qm_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
ldb_bridge_enable_helper(bridge);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qm_ldb_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qm_ldb_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ldb_channel *ldb_ch = bridge->driver_private;
|
||||
struct ldb *ldb = ldb_ch->ldb;
|
||||
|
||||
@@ -203,9 +203,8 @@ imx8qxp_ldb_bridge_mode_set(struct drm_bridge *bridge,
|
||||
companion->funcs->mode_set(companion, mode, adjusted_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ldb_channel *ldb_ch = bridge->driver_private;
|
||||
struct ldb *ldb = ldb_ch->ldb;
|
||||
@@ -217,12 +216,11 @@ imx8qxp_ldb_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
clk_prepare_enable(imx8qxp_ldb->clk_bypass);
|
||||
|
||||
if (is_split && companion)
|
||||
companion->funcs->atomic_pre_enable(companion, old_bridge_state);
|
||||
companion->funcs->atomic_pre_enable(companion, state);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ldb_channel *ldb_ch = bridge->driver_private;
|
||||
struct ldb *ldb = ldb_ch->ldb;
|
||||
@@ -252,12 +250,11 @@ imx8qxp_ldb_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
DRM_DEV_ERROR(dev, "failed to power on PHY: %d\n", ret);
|
||||
|
||||
if (is_split && companion)
|
||||
companion->funcs->atomic_enable(companion, old_bridge_state);
|
||||
companion->funcs->atomic_enable(companion, state);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ldb_channel *ldb_ch = bridge->driver_private;
|
||||
struct ldb *ldb = ldb_ch->ldb;
|
||||
@@ -283,7 +280,7 @@ imx8qxp_ldb_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
clk_disable_unprepare(imx8qxp_ldb->clk_pixel);
|
||||
|
||||
if (is_split && companion)
|
||||
companion->funcs->atomic_disable(companion, old_bridge_state);
|
||||
companion->funcs->atomic_disable(companion, state);
|
||||
|
||||
ret = pm_runtime_put(dev);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -176,9 +176,8 @@ imx8qxp_pc_bridge_mode_set(struct drm_bridge *bridge,
|
||||
clk_disable_unprepare(pc->clk_apb);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_pc_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct imx8qxp_pc_channel *ch = bridge->driver_private;
|
||||
struct imx8qxp_pc *pc = ch->pc;
|
||||
|
||||
@@ -153,9 +153,8 @@ imx8qxp_pixel_link_bridge_mode_set(struct drm_bridge *bridge,
|
||||
imx8qxp_pixel_link_set_mst_addr(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct imx8qxp_pixel_link *pl = bridge->driver_private;
|
||||
|
||||
@@ -164,9 +163,8 @@ imx8qxp_pixel_link_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
imx8qxp_pixel_link_enable_sync(pl);
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_pixel_link_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_pixel_link_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct imx8qxp_pixel_link *pl = bridge->driver_private;
|
||||
|
||||
|
||||
@@ -122,9 +122,8 @@ imx8qxp_pxl2dpi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct imx8qxp_pxl2dpi *p2d = bridge->driver_private;
|
||||
int ret;
|
||||
@@ -134,8 +133,7 @@ imx8qxp_pxl2dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
DRM_DEV_ERROR(p2d->dev, "failed to put runtime PM: %d\n", ret);
|
||||
|
||||
if (p2d->companion)
|
||||
p2d->companion->funcs->atomic_disable(p2d->companion,
|
||||
old_bridge_state);
|
||||
p2d->companion->funcs->atomic_disable(p2d->companion, state);
|
||||
}
|
||||
|
||||
static const u32 imx8qxp_pxl2dpi_bus_output_fmts[] = {
|
||||
|
||||
@@ -569,9 +569,8 @@ static int it6263_read_edid(void *data, u8 *buf, unsigned int block, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
it6263_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void it6263_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
|
||||
@@ -581,11 +580,9 @@ it6263_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
AFE_DRV_RST | AFE_DRV_PWD);
|
||||
}
|
||||
|
||||
static void
|
||||
it6263_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void it6263_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct it6263 *it = bridge_to_it6263(bridge);
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
struct regmap *regmap = it->hdmi_regmap;
|
||||
|
||||
@@ -3183,11 +3183,10 @@ it6505_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it6505 *it6505 = bridge_to_it6505(bridge);
|
||||
struct device *dev = it6505->dev;
|
||||
struct drm_atomic_state *state = old_state->base.state;
|
||||
struct hdmi_avi_infoframe frame;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector_state *conn_state;
|
||||
@@ -3239,7 +3238,7 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it6505_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it6505 *it6505 = bridge_to_it6505(bridge);
|
||||
struct device *dev = it6505->dev;
|
||||
@@ -3254,7 +3253,7 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it6505 *it6505 = bridge_to_it6505(bridge);
|
||||
struct device *dev = it6505->dev;
|
||||
@@ -3265,7 +3264,7 @@ static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it6505 *it6505 = bridge_to_it6505(bridge);
|
||||
struct device *dev = it6505->dev;
|
||||
|
||||
@@ -721,10 +721,9 @@ static u32 *it66121_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it66121_bridge_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
|
||||
ctx->connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||
|
||||
@@ -732,7 +731,7 @@ static void it66121_bridge_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void it66121_bridge_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
|
||||
|
||||
|
||||
@@ -455,10 +455,9 @@ static int lt9211_configure_tx(struct lt9211 *ctx, bool jeida,
|
||||
}
|
||||
|
||||
static void lt9211_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9211 *ctx = bridge_to_lt9211(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
const struct drm_bridge_state *bridge_state;
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
const struct drm_display_mode *mode;
|
||||
@@ -553,7 +552,7 @@ static void lt9211_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void lt9211_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9211 *ctx = bridge_to_lt9211(bridge);
|
||||
int ret;
|
||||
|
||||
@@ -640,12 +640,10 @@ lt9611_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
|
||||
}
|
||||
|
||||
/* bridge funcs */
|
||||
static void
|
||||
lt9611_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void lt9611_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@@ -689,9 +687,8 @@ lt9611_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
regmap_write(lt9611->regmap, 0x8130, 0xea);
|
||||
}
|
||||
|
||||
static void
|
||||
lt9611_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void lt9611_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
|
||||
int ret;
|
||||
@@ -767,7 +764,7 @@ static enum drm_mode_status lt9611_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
|
||||
static const struct reg_sequence reg_cfg[] = {
|
||||
@@ -786,9 +783,8 @@ static void lt9611_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
lt9611->sleep = false;
|
||||
}
|
||||
|
||||
static void
|
||||
lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void lt9611_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct lt9611 *lt9611 = bridge_to_lt9611(bridge);
|
||||
|
||||
|
||||
@@ -736,9 +736,8 @@ static int nwl_dsi_disable(struct nwl_dsi *dsi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void nwl_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct nwl_dsi *dsi = bridge_to_dsi(bridge);
|
||||
int ret;
|
||||
@@ -898,9 +897,8 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
|
||||
static void
|
||||
nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void nwl_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct nwl_dsi *dsi = bridge_to_dsi(bridge);
|
||||
int ret;
|
||||
@@ -1184,6 +1182,7 @@ static int nwl_dsi_probe(struct platform_device *pdev)
|
||||
dsi->bridge.funcs = &nwl_dsi_bridge_funcs;
|
||||
dsi->bridge.of_node = dev->of_node;
|
||||
dsi->bridge.timings = &nwl_dsi_timings;
|
||||
dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
|
||||
|
||||
dev_set_drvdata(dev, dsi);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
@@ -109,10 +109,9 @@ static void panel_bridge_detach(struct drm_bridge *bridge)
|
||||
}
|
||||
|
||||
static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_encoder *encoder = bridge->encoder;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -129,10 +128,9 @@ static void panel_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void panel_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_encoder *encoder = bridge->encoder;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -149,10 +147,9 @@ static void panel_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void panel_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_encoder *encoder = bridge->encoder;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
@@ -169,10 +166,9 @@ static void panel_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void panel_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct panel_bridge *panel_bridge = drm_bridge_to_panel_bridge(bridge);
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_encoder *encoder = bridge->encoder;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
@@ -322,8 +318,10 @@ void drm_panel_bridge_remove(struct drm_bridge *bridge)
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
if (bridge->funcs != &panel_bridge_bridge_funcs)
|
||||
if (!drm_bridge_is_panel(bridge)) {
|
||||
drm_warn(bridge->dev, "%s: called on non-panel bridge!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
panel_bridge = drm_bridge_to_panel_bridge(bridge);
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ static const struct dev_pm_ops ps8640_pm_ops = {
|
||||
};
|
||||
|
||||
static void ps8640_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
|
||||
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
|
||||
@@ -472,7 +472,7 @@ static void ps8640_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void ps8640_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
|
||||
|
||||
|
||||
@@ -1457,7 +1457,7 @@ static int samsung_dsim_init(struct samsung_dsim *dsi)
|
||||
}
|
||||
|
||||
static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
int ret;
|
||||
@@ -1485,7 +1485,7 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@@ -1496,7 +1496,7 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@@ -1508,7 +1508,7 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void samsung_dsim_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
|
||||
@@ -325,7 +325,7 @@ static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs =
|
||||
};
|
||||
|
||||
static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
@@ -339,7 +339,7 @@ static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
|
||||
@@ -362,10 +362,9 @@ static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi,
|
||||
}
|
||||
|
||||
static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||
struct drm_atomic_state *state = old_state->base.state;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_connector *connector;
|
||||
unsigned int op_mode;
|
||||
@@ -396,7 +395,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||
|
||||
|
||||
@@ -2945,7 +2945,7 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
|
||||
@@ -2959,10 +2959,9 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_hdmi *hdmi = bridge->driver_private;
|
||||
struct drm_atomic_state *state = old_state->base.state;
|
||||
struct drm_connector *connector;
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
|
||||
@@ -934,7 +934,7 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
@@ -1022,7 +1022,7 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@@ -1043,7 +1043,7 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
|
||||
@@ -745,7 +745,7 @@ static int dw_mipi_dsi2_bridge_atomic_check(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_bridge_post_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge);
|
||||
const struct dw_mipi_dsi2_phy_ops *phy_ops = dsi2->plat_data->phy_ops;
|
||||
@@ -821,7 +821,7 @@ static void dw_mipi_dsi2_mode_set(struct dw_mipi_dsi2 *dsi2,
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge);
|
||||
|
||||
@@ -840,7 +840,7 @@ static void dw_mipi_dsi2_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = bridge_to_dsi2(bridge);
|
||||
|
||||
|
||||
@@ -149,7 +149,8 @@ static int tc358762_init(struct tc358762 *ctx)
|
||||
return tc358762_clear_error(ctx);
|
||||
}
|
||||
|
||||
static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_state *state)
|
||||
static void tc358762_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc358762 *ctx = bridge_to_tc358762(bridge);
|
||||
int ret;
|
||||
@@ -171,7 +172,8 @@ static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_s
|
||||
dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
|
||||
}
|
||||
|
||||
static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *state)
|
||||
static void tc358762_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc358762 *ctx = bridge_to_tc358762(bridge);
|
||||
int ret;
|
||||
@@ -188,7 +190,8 @@ static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_sta
|
||||
ctx->pre_enabled = true;
|
||||
}
|
||||
|
||||
static void tc358762_enable(struct drm_bridge *bridge, struct drm_bridge_state *state)
|
||||
static void tc358762_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc358762 *ctx = bridge_to_tc358762(bridge);
|
||||
int ret;
|
||||
|
||||
@@ -1548,9 +1548,8 @@ static int tc_edp_stream_disable(struct tc_data *tc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
|
||||
{
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
@@ -1564,9 +1563,8 @@ tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
int ret;
|
||||
@@ -1576,9 +1574,8 @@ tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
dev_err(tc->dev, "main link stream stop error: %d\n", ret);
|
||||
}
|
||||
|
||||
static void
|
||||
tc_edp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void tc_edp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
int ret;
|
||||
@@ -1603,9 +1600,8 @@ tc_edp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tc_edp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
static void tc_edp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tc_data *tc = bridge_to_tc(bridge);
|
||||
int ret;
|
||||
|
||||
@@ -21,10 +21,11 @@
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
#include <drm/i2c/tda998x.h>
|
||||
|
||||
#include <media/cec-notifier.h>
|
||||
|
||||
#include <dt-bindings/display/tda998x.h>
|
||||
|
||||
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
|
||||
|
||||
enum {
|
||||
@@ -1717,10 +1718,10 @@ static int tda998x_get_audio_ports(struct tda998x_priv *priv,
|
||||
u8 ena_ap = be32_to_cpup(&port_data[2*i+1]);
|
||||
|
||||
switch (afmt) {
|
||||
case AFMT_I2S:
|
||||
case TDA998x_I2S:
|
||||
route = AUDIO_ROUTE_I2S;
|
||||
break;
|
||||
case AFMT_SPDIF:
|
||||
case TDA998x_SPDIF:
|
||||
route = AUDIO_ROUTE_SPDIF;
|
||||
break;
|
||||
default:
|
||||
@@ -1746,44 +1747,6 @@ static int tda998x_get_audio_ports(struct tda998x_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tda998x_set_config(struct tda998x_priv *priv,
|
||||
const struct tda998x_encoder_params *p)
|
||||
{
|
||||
priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) |
|
||||
(p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) |
|
||||
VIP_CNTRL_0_SWAP_B(p->swap_b) |
|
||||
(p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0);
|
||||
priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) |
|
||||
(p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) |
|
||||
VIP_CNTRL_1_SWAP_D(p->swap_d) |
|
||||
(p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0);
|
||||
priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) |
|
||||
(p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) |
|
||||
VIP_CNTRL_2_SWAP_F(p->swap_f) |
|
||||
(p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0);
|
||||
|
||||
if (p->audio_params.format != AFMT_UNUSED) {
|
||||
unsigned int ratio, route;
|
||||
bool spdif = p->audio_params.format == AFMT_SPDIF;
|
||||
|
||||
route = AUDIO_ROUTE_I2S + spdif;
|
||||
|
||||
priv->audio.route = &tda998x_audio_route[route];
|
||||
priv->audio.cea = p->audio_params.cea;
|
||||
priv->audio.sample_rate = p->audio_params.sample_rate;
|
||||
memcpy(priv->audio.status, p->audio_params.status,
|
||||
min(sizeof(priv->audio.status),
|
||||
sizeof(p->audio_params.status)));
|
||||
priv->audio.ena_ap = p->audio_params.config;
|
||||
priv->audio.i2s_format = I2S_FORMAT_PHILIPS;
|
||||
|
||||
ratio = spdif ? 64 : p->audio_params.sample_width * 2;
|
||||
return tda998x_derive_cts_n(priv, &priv->audio, ratio);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tda998x_destroy(struct device *dev)
|
||||
{
|
||||
struct tda998x_priv *priv = dev_get_drvdata(dev);
|
||||
@@ -1982,10 +1945,6 @@ static int tda998x_create(struct device *dev)
|
||||
if (priv->audio_port_enable[AUDIO_ROUTE_I2S] ||
|
||||
priv->audio_port_enable[AUDIO_ROUTE_SPDIF])
|
||||
tda998x_audio_codec_init(priv, &client->dev);
|
||||
} else if (dev->platform_data) {
|
||||
ret = tda998x_set_config(priv, dev->platform_data);
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
priv->bridge.funcs = &tda998x_bridge_funcs;
|
||||
@@ -105,7 +105,7 @@ static const struct regmap_config dlpc_regmap_config = {
|
||||
};
|
||||
|
||||
static void dlpc_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dlpc *dlpc = bridge_to_dlpc(bridge);
|
||||
struct device *dev = dlpc->dev;
|
||||
@@ -170,7 +170,7 @@ static void dlpc_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dlpc_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dlpc *dlpc = bridge_to_dlpc(bridge);
|
||||
int ret;
|
||||
@@ -193,7 +193,7 @@ static void dlpc_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void dlpc_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dlpc *dlpc = bridge_to_dlpc(bridge);
|
||||
|
||||
|
||||
@@ -35,9 +35,12 @@
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_drv.h> /* DRM_MODESET_LOCK_ALL_BEGIN() needs drm_drv_uses_atomic_modeset() */
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
@@ -158,6 +161,9 @@ struct sn65dsi83 {
|
||||
bool lvds_dual_link_even_odd_swap;
|
||||
int lvds_vod_swing_conf[2];
|
||||
int lvds_term_conf[2];
|
||||
int irq;
|
||||
struct delayed_work monitor_work;
|
||||
struct work_struct reset_work;
|
||||
};
|
||||
|
||||
static const struct regmap_range sn65dsi83_readable_ranges[] = {
|
||||
@@ -362,11 +368,110 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
|
||||
return dsi_div - 1;
|
||||
}
|
||||
|
||||
static int sn65dsi83_reset_pipe(struct sn65dsi83 *sn65dsi83)
|
||||
{
|
||||
struct drm_device *dev = sn65dsi83->bridge.dev;
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Reset active outputs of the related CRTC.
|
||||
*
|
||||
* This way, drm core will reconfigure each components in the CRTC
|
||||
* outputs path. In our case, this will force the previous component to
|
||||
* go back in LP11 mode and so allow the reconfiguration of SN65DSI83
|
||||
* bridge.
|
||||
*
|
||||
* Keep the lock during the whole operation to be atomic.
|
||||
*/
|
||||
|
||||
DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, 0, err);
|
||||
|
||||
if (!sn65dsi83->bridge.encoder->crtc) {
|
||||
/*
|
||||
* No CRTC attached -> No CRTC active outputs to reset
|
||||
* This can happen when the SN65DSI83 is reset. Simply do
|
||||
* nothing without returning any errors.
|
||||
*/
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dev_warn(sn65dsi83->dev, "reset the pipe\n");
|
||||
|
||||
err = drm_atomic_helper_reset_crtc(sn65dsi83->bridge.encoder->crtc, &ctx);
|
||||
|
||||
end:
|
||||
DRM_MODESET_LOCK_ALL_END(dev, ctx, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void sn65dsi83_reset_work(struct work_struct *ws)
|
||||
{
|
||||
struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work);
|
||||
int ret;
|
||||
|
||||
/* Reset the pipe */
|
||||
ret = sn65dsi83_reset_pipe(ctx);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "reset pipe failed %pe\n", ERR_PTR(ret));
|
||||
return;
|
||||
}
|
||||
if (ctx->irq)
|
||||
enable_irq(ctx->irq);
|
||||
}
|
||||
|
||||
static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
|
||||
{
|
||||
unsigned int irq_stat;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Schedule a reset in case of:
|
||||
* - the bridge doesn't answer
|
||||
* - the bridge signals an error
|
||||
*/
|
||||
|
||||
ret = regmap_read(ctx->regmap, REG_IRQ_STAT, &irq_stat);
|
||||
if (ret || irq_stat) {
|
||||
/*
|
||||
* IRQ acknowledged is not always possible (the bridge can be in
|
||||
* a state where it doesn't answer anymore). To prevent an
|
||||
* interrupt storm, disable interrupt. The interrupt will be
|
||||
* after the reset.
|
||||
*/
|
||||
if (ctx->irq)
|
||||
disable_irq_nosync(ctx->irq);
|
||||
|
||||
schedule_work(&ctx->reset_work);
|
||||
}
|
||||
}
|
||||
|
||||
static void sn65dsi83_monitor_work(struct work_struct *work)
|
||||
{
|
||||
struct sn65dsi83 *ctx = container_of(to_delayed_work(work),
|
||||
struct sn65dsi83, monitor_work);
|
||||
|
||||
sn65dsi83_handle_errors(ctx);
|
||||
|
||||
schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static void sn65dsi83_monitor_start(struct sn65dsi83 *ctx)
|
||||
{
|
||||
schedule_delayed_work(&ctx->monitor_work, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
||||
static void sn65dsi83_monitor_stop(struct sn65dsi83 *ctx)
|
||||
{
|
||||
cancel_delayed_work_sync(&ctx->monitor_work);
|
||||
}
|
||||
|
||||
static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
const struct drm_bridge_state *bridge_state;
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
const struct drm_display_mode *mode;
|
||||
@@ -534,7 +639,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
unsigned int pval;
|
||||
@@ -548,14 +653,32 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
|
||||
if (pval)
|
||||
dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval);
|
||||
|
||||
if (ctx->irq) {
|
||||
/* Enable irq to detect errors */
|
||||
regmap_write(ctx->regmap, REG_IRQ_GLOBAL, REG_IRQ_GLOBAL_IRQ_EN);
|
||||
regmap_write(ctx->regmap, REG_IRQ_EN, 0xff);
|
||||
} else {
|
||||
/* Use the polling task */
|
||||
sn65dsi83_monitor_start(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
int ret;
|
||||
|
||||
if (ctx->irq) {
|
||||
/* Disable irq */
|
||||
regmap_write(ctx->regmap, REG_IRQ_EN, 0x0);
|
||||
regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0);
|
||||
} else {
|
||||
/* Stop the polling task */
|
||||
sn65dsi83_monitor_stop(ctx);
|
||||
}
|
||||
|
||||
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
|
||||
gpiod_set_value_cansleep(ctx->enable_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
@@ -805,6 +928,14 @@ static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t sn65dsi83_irq(int irq, void *data)
|
||||
{
|
||||
struct sn65dsi83 *ctx = data;
|
||||
|
||||
sn65dsi83_handle_errors(ctx);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int sn65dsi83_probe(struct i2c_client *client)
|
||||
{
|
||||
const struct i2c_device_id *id = i2c_client_get_device_id(client);
|
||||
@@ -818,6 +949,8 @@ static int sn65dsi83_probe(struct i2c_client *client)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->dev = dev;
|
||||
INIT_WORK(&ctx->reset_work, sn65dsi83_reset_work);
|
||||
INIT_DELAYED_WORK(&ctx->monitor_work, sn65dsi83_monitor_work);
|
||||
|
||||
if (dev->of_node) {
|
||||
model = (enum sn65dsi83_model)(uintptr_t)
|
||||
@@ -842,12 +975,21 @@ static int sn65dsi83_probe(struct i2c_client *client)
|
||||
if (IS_ERR(ctx->regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->regmap), "failed to get regmap\n");
|
||||
|
||||
if (client->irq) {
|
||||
ctx->irq = client->irq;
|
||||
ret = devm_request_threaded_irq(ctx->dev, ctx->irq, NULL, sn65dsi83_irq,
|
||||
IRQF_ONESHOT, dev_name(ctx->dev), ctx);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to request irq\n");
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, ctx);
|
||||
i2c_set_clientdata(client, ctx);
|
||||
|
||||
ctx->bridge.funcs = &sn65dsi83_funcs;
|
||||
ctx->bridge.of_node = dev->of_node;
|
||||
ctx->bridge.pre_enable_prev_first = true;
|
||||
ctx->bridge.type = DRM_MODE_CONNECTOR_LVDS;
|
||||
drm_bridge_add(&ctx->bridge);
|
||||
|
||||
ret = sn65dsi83_host_attach(ctx);
|
||||
|
||||
@@ -813,7 +813,7 @@ ti_sn_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
|
||||
@@ -1073,7 +1073,7 @@ static int ti_sn_link_training(struct ti_sn65dsi86 *pdata, int dp_rate_idx,
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
struct drm_connector *connector;
|
||||
@@ -1085,7 +1085,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
int max_dp_lanes;
|
||||
unsigned int bpp;
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state,
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
if (!connector) {
|
||||
dev_err_ratelimited(pdata->dev, "Could not get the connector\n");
|
||||
@@ -1164,7 +1164,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
|
||||
@@ -1178,7 +1178,7 @@ static void ti_sn_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void ti_sn_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ struct tdp158 {
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static void tdp158_enable(struct drm_bridge *bridge, struct drm_bridge_state *prev)
|
||||
static void tdp158_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
int err;
|
||||
struct tdp158 *tdp158 = bridge->driver_private;
|
||||
@@ -34,7 +35,8 @@ static void tdp158_enable(struct drm_bridge *bridge, struct drm_bridge_state *pr
|
||||
gpiod_set_value_cansleep(tdp158->enable, 1);
|
||||
}
|
||||
|
||||
static void tdp158_disable(struct drm_bridge *bridge, struct drm_bridge_state *prev)
|
||||
static void tdp158_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct tdp158 *tdp158 = bridge->driver_private;
|
||||
|
||||
|
||||
@@ -1160,7 +1160,7 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
|
||||
}
|
||||
|
||||
static void
|
||||
disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
disable_outputs(struct drm_device *dev, struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *old_conn_state, *new_conn_state;
|
||||
@@ -1168,7 +1168,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) {
|
||||
for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) {
|
||||
const struct drm_encoder_helper_funcs *funcs;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *bridge;
|
||||
@@ -1180,11 +1180,11 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
if (!old_conn_state->crtc)
|
||||
continue;
|
||||
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(old_state, old_conn_state->crtc);
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(state, old_conn_state->crtc);
|
||||
|
||||
if (new_conn_state->crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(
|
||||
old_state,
|
||||
state,
|
||||
new_conn_state->crtc);
|
||||
else
|
||||
new_crtc_state = NULL;
|
||||
@@ -1211,12 +1211,12 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
* it away), so we won't call disable hooks twice.
|
||||
*/
|
||||
bridge = drm_bridge_chain_get_first_bridge(encoder);
|
||||
drm_atomic_bridge_chain_disable(bridge, old_state);
|
||||
drm_atomic_bridge_chain_disable(bridge, state);
|
||||
|
||||
/* Right function depends upon target state. */
|
||||
if (funcs) {
|
||||
if (funcs->atomic_disable)
|
||||
funcs->atomic_disable(encoder, old_state);
|
||||
funcs->atomic_disable(encoder, state);
|
||||
else if (new_conn_state->crtc && funcs->prepare)
|
||||
funcs->prepare(encoder);
|
||||
else if (funcs->disable)
|
||||
@@ -1225,10 +1225,10 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
drm_atomic_bridge_chain_post_disable(bridge, old_state);
|
||||
drm_atomic_bridge_chain_post_disable(bridge, state);
|
||||
}
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
int ret;
|
||||
|
||||
@@ -1249,7 +1249,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
if (new_crtc_state->enable && funcs->prepare)
|
||||
funcs->prepare(crtc);
|
||||
else if (funcs->atomic_disable)
|
||||
funcs->atomic_disable(crtc, old_state);
|
||||
funcs->atomic_disable(crtc, state);
|
||||
else if (funcs->disable)
|
||||
funcs->disable(crtc);
|
||||
else if (funcs->dpms)
|
||||
@@ -1277,7 +1277,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
/**
|
||||
* drm_atomic_helper_update_legacy_modeset_state - update legacy modeset state
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function updates all the various legacy modeset state pointers in
|
||||
* connectors, encoders and CRTCs.
|
||||
@@ -1293,7 +1293,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
*/
|
||||
void
|
||||
drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *old_conn_state, *new_conn_state;
|
||||
@@ -1302,7 +1302,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
|
||||
int i;
|
||||
|
||||
/* clear out existing links and update dpms */
|
||||
for_each_oldnew_connector_in_state(old_state, connector, old_conn_state, new_conn_state, i) {
|
||||
for_each_oldnew_connector_in_state(state, connector, old_conn_state, new_conn_state, i) {
|
||||
if (connector->encoder) {
|
||||
WARN_ON(!connector->encoder->crtc);
|
||||
|
||||
@@ -1323,7 +1323,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
|
||||
}
|
||||
|
||||
/* set new links */
|
||||
for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
|
||||
for_each_new_connector_in_state(state, connector, new_conn_state, i) {
|
||||
if (!new_conn_state->crtc)
|
||||
continue;
|
||||
|
||||
@@ -1335,7 +1335,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
|
||||
}
|
||||
|
||||
/* set legacy state in the crtc structure */
|
||||
for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
struct drm_plane *primary = crtc->primary;
|
||||
struct drm_plane_state *new_plane_state;
|
||||
|
||||
@@ -1343,7 +1343,7 @@ drm_atomic_helper_update_legacy_modeset_state(struct drm_device *dev,
|
||||
crtc->enabled = new_crtc_state->enable;
|
||||
|
||||
new_plane_state =
|
||||
drm_atomic_get_new_plane_state(old_state, primary);
|
||||
drm_atomic_get_new_plane_state(state, primary);
|
||||
|
||||
if (new_plane_state && new_plane_state->crtc == crtc) {
|
||||
crtc->x = new_plane_state->src_x >> 16;
|
||||
@@ -1375,7 +1375,7 @@ void drm_atomic_helper_calc_timestamping_constants(struct drm_atomic_state *stat
|
||||
EXPORT_SYMBOL(drm_atomic_helper_calc_timestamping_constants);
|
||||
|
||||
static void
|
||||
crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
@@ -1383,7 +1383,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
struct drm_connector_state *new_conn_state;
|
||||
int i;
|
||||
|
||||
for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
|
||||
if (!new_crtc_state->mode_changed)
|
||||
@@ -1399,7 +1399,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
}
|
||||
}
|
||||
|
||||
for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
|
||||
for_each_new_connector_in_state(state, connector, new_conn_state, i) {
|
||||
const struct drm_encoder_helper_funcs *funcs;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_display_mode *mode, *adjusted_mode;
|
||||
@@ -1439,7 +1439,7 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
/**
|
||||
* drm_atomic_helper_commit_modeset_disables - modeset commit to disable outputs
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function shuts down all the outputs that need to be shut down and
|
||||
* prepares them (if required) with the new mode.
|
||||
@@ -1451,25 +1451,25 @@ crtc_set_mode(struct drm_device *dev, struct drm_atomic_state *old_state)
|
||||
* PM since planes updates then only happen when the CRTC is actually enabled.
|
||||
*/
|
||||
void drm_atomic_helper_commit_modeset_disables(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
disable_outputs(dev, old_state);
|
||||
disable_outputs(dev, state);
|
||||
|
||||
drm_atomic_helper_update_legacy_modeset_state(dev, old_state);
|
||||
drm_atomic_helper_calc_timestamping_constants(old_state);
|
||||
drm_atomic_helper_update_legacy_modeset_state(dev, state);
|
||||
drm_atomic_helper_calc_timestamping_constants(state);
|
||||
|
||||
crtc_set_mode(dev, old_state);
|
||||
crtc_set_mode(dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_disables);
|
||||
|
||||
static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *new_conn_state;
|
||||
int i;
|
||||
|
||||
for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
|
||||
for_each_new_connector_in_state(state, connector, new_conn_state, i) {
|
||||
const struct drm_connector_helper_funcs *funcs;
|
||||
|
||||
funcs = connector->helper_private;
|
||||
@@ -1478,7 +1478,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
|
||||
|
||||
if (new_conn_state->writeback_job && new_conn_state->writeback_job->fb) {
|
||||
WARN_ON(connector->connector_type != DRM_MODE_CONNECTOR_WRITEBACK);
|
||||
funcs->atomic_commit(connector, old_state);
|
||||
funcs->atomic_commit(connector, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1486,7 +1486,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
|
||||
/**
|
||||
* drm_atomic_helper_commit_modeset_enables - modeset commit to enable outputs
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function enables all the outputs with the new configuration which had to
|
||||
* be turned off for the update.
|
||||
@@ -1498,7 +1498,7 @@ static void drm_atomic_helper_commit_writebacks(struct drm_device *dev,
|
||||
* PM since planes updates then only happen when the CRTC is actually enabled.
|
||||
*/
|
||||
void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -1507,7 +1507,7 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
||||
struct drm_connector_state *new_conn_state;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
|
||||
/* Need to filter out CRTCs where only planes change. */
|
||||
@@ -1523,13 +1523,13 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
||||
drm_dbg_atomic(dev, "enabling [CRTC:%d:%s]\n",
|
||||
crtc->base.id, crtc->name);
|
||||
if (funcs->atomic_enable)
|
||||
funcs->atomic_enable(crtc, old_state);
|
||||
funcs->atomic_enable(crtc, state);
|
||||
else if (funcs->commit)
|
||||
funcs->commit(crtc);
|
||||
}
|
||||
}
|
||||
|
||||
for_each_new_connector_in_state(old_state, connector, new_conn_state, i) {
|
||||
for_each_new_connector_in_state(state, connector, new_conn_state, i) {
|
||||
const struct drm_encoder_helper_funcs *funcs;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *bridge;
|
||||
@@ -1552,21 +1552,21 @@ void drm_atomic_helper_commit_modeset_enables(struct drm_device *dev,
|
||||
* it away), so we won't call enable hooks twice.
|
||||
*/
|
||||
bridge = drm_bridge_chain_get_first_bridge(encoder);
|
||||
drm_atomic_bridge_chain_pre_enable(bridge, old_state);
|
||||
drm_atomic_bridge_chain_pre_enable(bridge, state);
|
||||
|
||||
if (funcs) {
|
||||
if (funcs->atomic_enable)
|
||||
funcs->atomic_enable(encoder, old_state);
|
||||
funcs->atomic_enable(encoder, state);
|
||||
else if (funcs->enable)
|
||||
funcs->enable(encoder);
|
||||
else if (funcs->commit)
|
||||
funcs->commit(encoder);
|
||||
}
|
||||
|
||||
drm_atomic_bridge_chain_enable(bridge, old_state);
|
||||
drm_atomic_bridge_chain_enable(bridge, state);
|
||||
}
|
||||
|
||||
drm_atomic_helper_commit_writebacks(dev, old_state);
|
||||
drm_atomic_helper_commit_writebacks(dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_modeset_enables);
|
||||
|
||||
@@ -1668,7 +1668,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
|
||||
/**
|
||||
* drm_atomic_helper_wait_for_vblanks - wait for vblank on CRTCs
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* Helper to, after atomic commit, wait for vblanks on all affected
|
||||
* CRTCs (ie. before cleaning up old framebuffers using
|
||||
@@ -1682,7 +1682,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences);
|
||||
*/
|
||||
void
|
||||
drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
@@ -1693,10 +1693,10 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||
* Legacy cursor ioctls are completely unsynced, and userspace
|
||||
* relies on that (by doing tons of cursor updates).
|
||||
*/
|
||||
if (old_state->legacy_cursor_update)
|
||||
if (state->legacy_cursor_update)
|
||||
return;
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
if (!new_crtc_state->active)
|
||||
continue;
|
||||
|
||||
@@ -1705,17 +1705,17 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||
continue;
|
||||
|
||||
crtc_mask |= drm_crtc_mask(crtc);
|
||||
old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc);
|
||||
state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc);
|
||||
}
|
||||
|
||||
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
||||
for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
|
||||
if (!(crtc_mask & drm_crtc_mask(crtc)))
|
||||
continue;
|
||||
|
||||
ret = wait_event_timeout(dev->vblank[i].queue,
|
||||
old_state->crtcs[i].last_vblank_count !=
|
||||
drm_crtc_vblank_count(crtc),
|
||||
msecs_to_jiffies(100));
|
||||
state->crtcs[i].last_vblank_count !=
|
||||
drm_crtc_vblank_count(crtc),
|
||||
msecs_to_jiffies(100));
|
||||
|
||||
WARN(!ret, "[CRTC:%d:%s] vblank wait timed out\n",
|
||||
crtc->base.id, crtc->name);
|
||||
@@ -1728,7 +1728,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
|
||||
/**
|
||||
* drm_atomic_helper_wait_for_flip_done - wait for all page flips to be done
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* Helper to, after atomic commit, wait for page flips on all affected
|
||||
* crtcs (ie. before cleaning up old framebuffers using
|
||||
@@ -1741,16 +1741,16 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks);
|
||||
* initialized using drm_atomic_helper_setup_commit().
|
||||
*/
|
||||
void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->mode_config.num_crtc; i++) {
|
||||
struct drm_crtc_commit *commit = old_state->crtcs[i].commit;
|
||||
struct drm_crtc_commit *commit = state->crtcs[i].commit;
|
||||
int ret;
|
||||
|
||||
crtc = old_state->crtcs[i].ptr;
|
||||
crtc = state->crtcs[i].ptr;
|
||||
|
||||
if (!crtc || !commit)
|
||||
continue;
|
||||
@@ -1761,14 +1761,14 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev,
|
||||
crtc->base.id, crtc->name);
|
||||
}
|
||||
|
||||
if (old_state->fake_commit)
|
||||
complete_all(&old_state->fake_commit->flip_done);
|
||||
if (state->fake_commit)
|
||||
complete_all(&state->fake_commit->flip_done);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_tail - commit atomic update to hardware
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This is the default implementation for the
|
||||
* &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers
|
||||
@@ -1779,29 +1779,29 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done);
|
||||
* Note that the default ordering of how the various stages are called is to
|
||||
* match the legacy modeset helper library closest.
|
||||
*/
|
||||
void drm_atomic_helper_commit_tail(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_commit_tail(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = old_state->dev;
|
||||
struct drm_device *dev = state->dev;
|
||||
|
||||
drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, old_state, 0);
|
||||
drm_atomic_helper_commit_planes(dev, state, 0);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
|
||||
drm_atomic_helper_fake_vblank(old_state);
|
||||
drm_atomic_helper_fake_vblank(state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
drm_atomic_helper_commit_hw_done(state);
|
||||
|
||||
drm_atomic_helper_wait_for_vblanks(dev, old_state);
|
||||
drm_atomic_helper_wait_for_vblanks(dev, state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||
drm_atomic_helper_cleanup_planes(dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_tail_rpm - commit atomic update to hardware
|
||||
* @old_state: new modeset state to be committed
|
||||
* @state: new modeset state to be committed
|
||||
*
|
||||
* This is an alternative implementation for the
|
||||
* &drm_mode_config_helper_funcs.atomic_commit_tail hook, for drivers
|
||||
@@ -1809,30 +1809,30 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_tail);
|
||||
* commit. Otherwise, one should use the default implementation
|
||||
* drm_atomic_helper_commit_tail().
|
||||
*/
|
||||
void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_commit_tail_rpm(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = old_state->dev;
|
||||
struct drm_device *dev = state->dev;
|
||||
|
||||
drm_atomic_helper_commit_modeset_disables(dev, old_state);
|
||||
drm_atomic_helper_commit_modeset_disables(dev, state);
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
drm_atomic_helper_commit_modeset_enables(dev, state);
|
||||
|
||||
drm_atomic_helper_commit_planes(dev, old_state,
|
||||
drm_atomic_helper_commit_planes(dev, state,
|
||||
DRM_PLANE_COMMIT_ACTIVE_ONLY);
|
||||
|
||||
drm_atomic_helper_fake_vblank(old_state);
|
||||
drm_atomic_helper_fake_vblank(state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
drm_atomic_helper_commit_hw_done(state);
|
||||
|
||||
drm_atomic_helper_wait_for_vblanks(dev, old_state);
|
||||
drm_atomic_helper_wait_for_vblanks(dev, state);
|
||||
|
||||
drm_atomic_helper_cleanup_planes(dev, old_state);
|
||||
drm_atomic_helper_cleanup_planes(dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_tail_rpm);
|
||||
|
||||
static void commit_tail(struct drm_atomic_state *old_state)
|
||||
static void commit_tail(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = old_state->dev;
|
||||
struct drm_device *dev = state->dev;
|
||||
const struct drm_mode_config_helper_funcs *funcs;
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_crtc *crtc;
|
||||
@@ -1854,33 +1854,33 @@ static void commit_tail(struct drm_atomic_state *old_state)
|
||||
*/
|
||||
start = ktime_get();
|
||||
|
||||
drm_atomic_helper_wait_for_fences(dev, old_state, false);
|
||||
drm_atomic_helper_wait_for_fences(dev, state, false);
|
||||
|
||||
drm_atomic_helper_wait_for_dependencies(old_state);
|
||||
drm_atomic_helper_wait_for_dependencies(state);
|
||||
|
||||
/*
|
||||
* We cannot safely access new_crtc_state after
|
||||
* drm_atomic_helper_commit_hw_done() so figure out which crtc's have
|
||||
* self-refresh active beforehand:
|
||||
*/
|
||||
for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i)
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i)
|
||||
if (new_crtc_state->self_refresh_active)
|
||||
new_self_refresh_mask |= BIT(i);
|
||||
|
||||
if (funcs && funcs->atomic_commit_tail)
|
||||
funcs->atomic_commit_tail(old_state);
|
||||
funcs->atomic_commit_tail(state);
|
||||
else
|
||||
drm_atomic_helper_commit_tail(old_state);
|
||||
drm_atomic_helper_commit_tail(state);
|
||||
|
||||
commit_time_ms = ktime_ms_delta(ktime_get(), start);
|
||||
if (commit_time_ms > 0)
|
||||
drm_self_refresh_helper_update_avg_times(old_state,
|
||||
drm_self_refresh_helper_update_avg_times(state,
|
||||
(unsigned long)commit_time_ms,
|
||||
new_self_refresh_mask);
|
||||
|
||||
drm_atomic_helper_commit_cleanup_done(old_state);
|
||||
drm_atomic_helper_commit_cleanup_done(state);
|
||||
|
||||
drm_atomic_state_put(old_state);
|
||||
drm_atomic_state_put(state);
|
||||
}
|
||||
|
||||
static void commit_work(struct work_struct *work)
|
||||
@@ -1966,7 +1966,7 @@ int drm_atomic_helper_async_check(struct drm_device *dev,
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
ret = funcs->atomic_async_check(plane, state);
|
||||
ret = funcs->atomic_async_check(plane, state, false);
|
||||
if (ret != 0)
|
||||
drm_dbg_atomic(dev,
|
||||
"[PLANE:%d:%s] driver async check failed\n",
|
||||
@@ -2423,17 +2423,17 @@ EXPORT_SYMBOL(drm_atomic_helper_setup_commit);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_wait_for_dependencies - wait for required preceding commits
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function waits for all preceding commits that touch the same CRTC as
|
||||
* @old_state to both be committed to the hardware (as signalled by
|
||||
* @state to both be committed to the hardware (as signalled by
|
||||
* drm_atomic_helper_commit_hw_done()) and executed by the hardware (as signalled
|
||||
* by calling drm_crtc_send_vblank_event() on the &drm_crtc_state.event).
|
||||
*
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
@@ -2444,7 +2444,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
|
||||
int i;
|
||||
long ret;
|
||||
|
||||
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
||||
for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
|
||||
ret = drm_crtc_commit_wait(old_crtc_state->commit);
|
||||
if (ret)
|
||||
drm_err(crtc->dev,
|
||||
@@ -2452,7 +2452,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
|
||||
crtc->base.id, crtc->name);
|
||||
}
|
||||
|
||||
for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
|
||||
for_each_old_connector_in_state(state, conn, old_conn_state, i) {
|
||||
ret = drm_crtc_commit_wait(old_conn_state->commit);
|
||||
if (ret)
|
||||
drm_err(conn->dev,
|
||||
@@ -2460,7 +2460,7 @@ void drm_atomic_helper_wait_for_dependencies(struct drm_atomic_state *old_state)
|
||||
conn->base.id, conn->name);
|
||||
}
|
||||
|
||||
for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
|
||||
for_each_old_plane_in_state(state, plane, old_plane_state, i) {
|
||||
ret = drm_crtc_commit_wait(old_plane_state->commit);
|
||||
if (ret)
|
||||
drm_err(plane->dev,
|
||||
@@ -2472,7 +2472,7 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_fake_vblank - fake VBLANK events if needed
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function walks all CRTCs and fakes VBLANK events on those with
|
||||
* &drm_crtc_state.no_vblank set to true and &drm_crtc_state.event != NULL.
|
||||
@@ -2488,32 +2488,32 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_dependencies);
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_fake_vblank(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_fake_vblank(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc_state *new_crtc_state;
|
||||
struct drm_crtc *crtc;
|
||||
int i;
|
||||
|
||||
for_each_new_crtc_in_state(old_state, crtc, new_crtc_state, i) {
|
||||
for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
|
||||
unsigned long flags;
|
||||
|
||||
if (!new_crtc_state->no_vblank)
|
||||
continue;
|
||||
|
||||
spin_lock_irqsave(&old_state->dev->event_lock, flags);
|
||||
spin_lock_irqsave(&state->dev->event_lock, flags);
|
||||
if (new_crtc_state->event) {
|
||||
drm_crtc_send_vblank_event(crtc,
|
||||
new_crtc_state->event);
|
||||
new_crtc_state->event = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&old_state->dev->event_lock, flags);
|
||||
spin_unlock_irqrestore(&state->dev->event_lock, flags);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_fake_vblank);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_hw_done - setup possible nonblocking commit
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function is used to signal completion of the hardware commit step. After
|
||||
* this step the driver is not allowed to read or change any permanent software
|
||||
@@ -2526,14 +2526,14 @@ EXPORT_SYMBOL(drm_atomic_helper_fake_vblank);
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state, *new_crtc_state;
|
||||
struct drm_crtc_commit *commit;
|
||||
int i;
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
commit = new_crtc_state->commit;
|
||||
if (!commit)
|
||||
continue;
|
||||
@@ -2553,32 +2553,32 @@ void drm_atomic_helper_commit_hw_done(struct drm_atomic_state *old_state)
|
||||
complete_all(&commit->hw_done);
|
||||
}
|
||||
|
||||
if (old_state->fake_commit) {
|
||||
complete_all(&old_state->fake_commit->hw_done);
|
||||
complete_all(&old_state->fake_commit->flip_done);
|
||||
if (state->fake_commit) {
|
||||
complete_all(&state->fake_commit->hw_done);
|
||||
complete_all(&state->fake_commit->flip_done);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_hw_done);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_commit_cleanup_done - signal completion of commit
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This signals completion of the atomic update @old_state, including any
|
||||
* This signals completion of the atomic update @state, including any
|
||||
* cleanup work. If used, it must be called right before calling
|
||||
* drm_atomic_state_put().
|
||||
*
|
||||
* This is part of the atomic helper support for nonblocking commits, see
|
||||
* drm_atomic_helper_setup_commit() for an overview.
|
||||
*/
|
||||
void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
|
||||
void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
struct drm_crtc_commit *commit;
|
||||
int i;
|
||||
|
||||
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) {
|
||||
for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
|
||||
commit = old_crtc_state->commit;
|
||||
if (WARN_ON(!commit))
|
||||
continue;
|
||||
@@ -2591,9 +2591,9 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state)
|
||||
spin_unlock(&crtc->commit_lock);
|
||||
}
|
||||
|
||||
if (old_state->fake_commit) {
|
||||
complete_all(&old_state->fake_commit->cleanup_done);
|
||||
WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done));
|
||||
if (state->fake_commit) {
|
||||
complete_all(&state->fake_commit->cleanup_done);
|
||||
WARN_ON(!try_wait_for_completion(&state->fake_commit->hw_done));
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done);
|
||||
@@ -2731,7 +2731,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state)
|
||||
/**
|
||||
* drm_atomic_helper_commit_planes - commit plane state
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
* @flags: flags for committing plane state
|
||||
*
|
||||
* This function commits the new plane state using the plane and atomic helper
|
||||
@@ -2739,7 +2739,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state)
|
||||
* been pushed into the relevant object state pointers, since this step can no
|
||||
* longer fail.
|
||||
*
|
||||
* It still requires the global state object @old_state to know which planes and
|
||||
* It still requires the global state object @state to know which planes and
|
||||
* crtcs need to be updated though.
|
||||
*
|
||||
* Note that this function does all plane updates across all CRTCs in one step.
|
||||
@@ -2770,7 +2770,7 @@ static bool plane_crtc_active(const struct drm_plane_state *state)
|
||||
* This should not be copied blindly by drivers.
|
||||
*/
|
||||
void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state,
|
||||
struct drm_atomic_state *state,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct drm_crtc *crtc;
|
||||
@@ -2781,7 +2781,7 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
bool active_only = flags & DRM_PLANE_COMMIT_ACTIVE_ONLY;
|
||||
bool no_disable = flags & DRM_PLANE_COMMIT_NO_DISABLE_AFTER_MODESET;
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
|
||||
funcs = crtc->helper_private;
|
||||
@@ -2792,10 +2792,10 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
if (active_only && !new_crtc_state->active)
|
||||
continue;
|
||||
|
||||
funcs->atomic_begin(crtc, old_state);
|
||||
funcs->atomic_begin(crtc, state);
|
||||
}
|
||||
|
||||
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
|
||||
for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
|
||||
const struct drm_plane_helper_funcs *funcs;
|
||||
bool disabling;
|
||||
|
||||
@@ -2833,18 +2833,18 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
no_disable)
|
||||
continue;
|
||||
|
||||
funcs->atomic_disable(plane, old_state);
|
||||
funcs->atomic_disable(plane, state);
|
||||
} else if (new_plane_state->crtc || disabling) {
|
||||
funcs->atomic_update(plane, old_state);
|
||||
funcs->atomic_update(plane, state);
|
||||
|
||||
if (!disabling && funcs->atomic_enable) {
|
||||
if (drm_atomic_plane_enabling(old_plane_state, new_plane_state))
|
||||
funcs->atomic_enable(plane, old_state);
|
||||
funcs->atomic_enable(plane, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||
const struct drm_crtc_helper_funcs *funcs;
|
||||
|
||||
funcs = crtc->helper_private;
|
||||
@@ -2855,14 +2855,14 @@ void drm_atomic_helper_commit_planes(struct drm_device *dev,
|
||||
if (active_only && !new_crtc_state->active)
|
||||
continue;
|
||||
|
||||
funcs->atomic_flush(crtc, old_state);
|
||||
funcs->atomic_flush(crtc, state);
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal end of framebuffer access here before hw_done. After hw_done,
|
||||
* a later commit might have already released the plane state.
|
||||
*/
|
||||
for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
|
||||
for_each_old_plane_in_state(state, plane, old_plane_state, i) {
|
||||
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
|
||||
|
||||
if (funcs->end_fb_access)
|
||||
@@ -2989,10 +2989,10 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
|
||||
/**
|
||||
* drm_atomic_helper_cleanup_planes - cleanup plane resources after commit
|
||||
* @dev: DRM device
|
||||
* @old_state: atomic state object with old state structures
|
||||
* @state: atomic state object being committed
|
||||
*
|
||||
* This function cleans up plane state, specifically framebuffers, from the old
|
||||
* configuration. Hence the old configuration must be perserved in @old_state to
|
||||
* configuration. Hence the old configuration must be perserved in @state to
|
||||
* be able to call this function.
|
||||
*
|
||||
* This function may not be called on the new state when the atomic update
|
||||
@@ -3000,13 +3000,13 @@ EXPORT_SYMBOL(drm_atomic_helper_disable_planes_on_crtc);
|
||||
* drm_atomic_helper_unprepare_planes() in this case.
|
||||
*/
|
||||
void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_state *old_plane_state;
|
||||
int i;
|
||||
|
||||
for_each_old_plane_in_state(old_state, plane, old_plane_state, i) {
|
||||
for_each_old_plane_in_state(state, plane, old_plane_state, i) {
|
||||
const struct drm_plane_helper_funcs *funcs = plane->helper_private;
|
||||
|
||||
if (funcs->cleanup_fb)
|
||||
@@ -3400,6 +3400,47 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_disable_all);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_reset_crtc - reset the active outputs of a CRTC
|
||||
* @crtc: DRM CRTC
|
||||
* @ctx: lock acquisition context
|
||||
*
|
||||
* Reset the active outputs by indicating that connectors have changed.
|
||||
* This implies a reset of all active components available between the CRTC and
|
||||
* connectors.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_atomic_helper_reset_crtc(struct drm_crtc *crtc,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int ret;
|
||||
|
||||
state = drm_atomic_state_alloc(crtc->dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state)) {
|
||||
ret = PTR_ERR(crtc_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
crtc_state->connectors_changed = true;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
out:
|
||||
drm_atomic_state_put(state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_reset_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_shutdown - shutdown all CRTC
|
||||
* @dev: DRM device
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_drv.h>
|
||||
@@ -1063,6 +1064,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane = obj_to_plane(obj);
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_mode_config *config = &plane->dev->mode_config;
|
||||
const struct drm_plane_helper_funcs *plane_funcs = plane->helper_private;
|
||||
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state)) {
|
||||
@@ -1070,15 +1072,30 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
|
||||
break;
|
||||
}
|
||||
|
||||
if (async_flip &&
|
||||
(plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY ||
|
||||
(prop != config->prop_fb_id &&
|
||||
prop != config->prop_in_fence_fd &&
|
||||
prop != config->prop_fb_damage_clips))) {
|
||||
ret = drm_atomic_plane_get_property(plane, plane_state,
|
||||
prop, &old_val);
|
||||
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
|
||||
break;
|
||||
if (async_flip) {
|
||||
/* check if the prop does a nop change */
|
||||
if ((prop != config->prop_fb_id &&
|
||||
prop != config->prop_in_fence_fd &&
|
||||
prop != config->prop_fb_damage_clips)) {
|
||||
ret = drm_atomic_plane_get_property(plane, plane_state,
|
||||
prop, &old_val);
|
||||
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
|
||||
}
|
||||
|
||||
/* ask the driver if this non-primary plane is supported */
|
||||
if (plane->type != DRM_PLANE_TYPE_PRIMARY) {
|
||||
ret = -EINVAL;
|
||||
|
||||
if (plane_funcs && plane_funcs->atomic_async_check)
|
||||
ret = plane_funcs->atomic_async_check(plane, state, true);
|
||||
|
||||
if (ret) {
|
||||
drm_dbg_atomic(prop->dev,
|
||||
"[PLANE:%d:%s] does not support async flips\n",
|
||||
obj->id, plane->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = drm_atomic_plane_set_property(plane,
|
||||
|
||||
@@ -550,7 +550,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
|
||||
/**
|
||||
* drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain
|
||||
* @bridge: bridge control structure
|
||||
* @old_state: old atomic state
|
||||
* @state: atomic state being committed
|
||||
*
|
||||
* Calls &drm_bridge_funcs.atomic_disable (falls back on
|
||||
* &drm_bridge_funcs.disable) op for all the bridges in the encoder chain,
|
||||
@@ -560,7 +560,7 @@ EXPORT_SYMBOL(drm_bridge_chain_mode_set);
|
||||
* Note: the bridge passed should be the one closest to the encoder
|
||||
*/
|
||||
void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *iter;
|
||||
@@ -571,15 +571,7 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
|
||||
encoder = bridge->encoder;
|
||||
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
|
||||
if (iter->funcs->atomic_disable) {
|
||||
struct drm_bridge_state *old_bridge_state;
|
||||
|
||||
old_bridge_state =
|
||||
drm_atomic_get_old_bridge_state(old_state,
|
||||
iter);
|
||||
if (WARN_ON(!old_bridge_state))
|
||||
return;
|
||||
|
||||
iter->funcs->atomic_disable(iter, old_bridge_state);
|
||||
iter->funcs->atomic_disable(iter, state);
|
||||
} else if (iter->funcs->disable) {
|
||||
iter->funcs->disable(iter);
|
||||
}
|
||||
@@ -591,29 +583,19 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
|
||||
EXPORT_SYMBOL(drm_atomic_bridge_chain_disable);
|
||||
|
||||
static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
if (old_state && bridge->funcs->atomic_post_disable) {
|
||||
struct drm_bridge_state *old_bridge_state;
|
||||
|
||||
old_bridge_state =
|
||||
drm_atomic_get_old_bridge_state(old_state,
|
||||
bridge);
|
||||
if (WARN_ON(!old_bridge_state))
|
||||
return;
|
||||
|
||||
bridge->funcs->atomic_post_disable(bridge,
|
||||
old_bridge_state);
|
||||
} else if (bridge->funcs->post_disable) {
|
||||
if (state && bridge->funcs->atomic_post_disable)
|
||||
bridge->funcs->atomic_post_disable(bridge, state);
|
||||
else if (bridge->funcs->post_disable)
|
||||
bridge->funcs->post_disable(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges
|
||||
* in the encoder chain
|
||||
* @bridge: bridge control structure
|
||||
* @old_state: old atomic state
|
||||
* @state: atomic state being committed
|
||||
*
|
||||
* Calls &drm_bridge_funcs.atomic_post_disable (falls back on
|
||||
* &drm_bridge_funcs.post_disable) op for all the bridges in the encoder chain,
|
||||
@@ -634,7 +616,7 @@ static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge,
|
||||
* Note: the bridge passed should be the one closest to the encoder
|
||||
*/
|
||||
void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *next, *limit;
|
||||
@@ -681,12 +663,12 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
|
||||
break;
|
||||
|
||||
drm_atomic_bridge_call_post_disable(next,
|
||||
old_state);
|
||||
state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drm_atomic_bridge_call_post_disable(bridge, old_state);
|
||||
drm_atomic_bridge_call_post_disable(bridge, state);
|
||||
|
||||
if (limit)
|
||||
/* Jump all bridges that we have already post_disabled */
|
||||
@@ -696,28 +678,19 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
|
||||
EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
|
||||
|
||||
static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
if (old_state && bridge->funcs->atomic_pre_enable) {
|
||||
struct drm_bridge_state *old_bridge_state;
|
||||
|
||||
old_bridge_state =
|
||||
drm_atomic_get_old_bridge_state(old_state,
|
||||
bridge);
|
||||
if (WARN_ON(!old_bridge_state))
|
||||
return;
|
||||
|
||||
bridge->funcs->atomic_pre_enable(bridge, old_bridge_state);
|
||||
} else if (bridge->funcs->pre_enable) {
|
||||
if (state && bridge->funcs->atomic_pre_enable)
|
||||
bridge->funcs->atomic_pre_enable(bridge, state);
|
||||
else if (bridge->funcs->pre_enable)
|
||||
bridge->funcs->pre_enable(bridge);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in
|
||||
* the encoder chain
|
||||
* @bridge: bridge control structure
|
||||
* @old_state: old atomic state
|
||||
* @state: atomic state being committed
|
||||
*
|
||||
* Calls &drm_bridge_funcs.atomic_pre_enable (falls back on
|
||||
* &drm_bridge_funcs.pre_enable) op for all the bridges in the encoder chain,
|
||||
@@ -737,7 +710,7 @@ static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge,
|
||||
* Note: the bridge passed should be the one closest to the encoder
|
||||
*/
|
||||
void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_bridge *iter, *next, *limit;
|
||||
@@ -776,11 +749,11 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
|
||||
*/
|
||||
break;
|
||||
|
||||
drm_atomic_bridge_call_pre_enable(next, old_state);
|
||||
drm_atomic_bridge_call_pre_enable(next, state);
|
||||
}
|
||||
}
|
||||
|
||||
drm_atomic_bridge_call_pre_enable(iter, old_state);
|
||||
drm_atomic_bridge_call_pre_enable(iter, state);
|
||||
|
||||
if (iter->pre_enable_prev_first)
|
||||
/* Jump all bridges that we have already pre_enabled */
|
||||
@@ -795,7 +768,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
|
||||
/**
|
||||
* drm_atomic_bridge_chain_enable - enables all bridges in the encoder chain
|
||||
* @bridge: bridge control structure
|
||||
* @old_state: old atomic state
|
||||
* @state: atomic state being committed
|
||||
*
|
||||
* Calls &drm_bridge_funcs.atomic_enable (falls back on
|
||||
* &drm_bridge_funcs.enable) op for all the bridges in the encoder chain,
|
||||
@@ -805,7 +778,7 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_pre_enable);
|
||||
* Note: the bridge passed should be the one closest to the encoder
|
||||
*/
|
||||
void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
|
||||
struct drm_atomic_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_encoder *encoder;
|
||||
|
||||
@@ -815,15 +788,7 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
|
||||
encoder = bridge->encoder;
|
||||
list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
|
||||
if (bridge->funcs->atomic_enable) {
|
||||
struct drm_bridge_state *old_bridge_state;
|
||||
|
||||
old_bridge_state =
|
||||
drm_atomic_get_old_bridge_state(old_state,
|
||||
bridge);
|
||||
if (WARN_ON(!old_bridge_state))
|
||||
return;
|
||||
|
||||
bridge->funcs->atomic_enable(bridge, old_bridge_state);
|
||||
bridge->funcs->atomic_enable(bridge, state);
|
||||
} else if (bridge->funcs->enable) {
|
||||
bridge->funcs->enable(bridge);
|
||||
}
|
||||
|
||||
@@ -748,7 +748,7 @@ static int bridges_show(struct seq_file *m, void *data)
|
||||
unsigned int idx = 0;
|
||||
|
||||
drm_for_each_bridge_in_chain(encoder, bridge) {
|
||||
drm_printf(&p, "bridge[%d]: %ps\n", idx++, bridge->funcs);
|
||||
drm_printf(&p, "bridge[%u]: %ps\n", idx++, bridge->funcs);
|
||||
drm_printf(&p, "\ttype: [%d] %s\n",
|
||||
bridge->type,
|
||||
drm_get_connector_type_name(bridge->type));
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/cgroup_dmem.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/fs.h>
|
||||
@@ -34,6 +35,7 @@
|
||||
#include <linux/mount.h>
|
||||
#include <linux/pseudo_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sprintf.h>
|
||||
#include <linux/srcu.h>
|
||||
#include <linux/xarray.h>
|
||||
|
||||
@@ -498,6 +500,72 @@ void drm_dev_unplug(struct drm_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dev_unplug);
|
||||
|
||||
/*
|
||||
* Available recovery methods for wedged device. To be sent along with device
|
||||
* wedged uevent.
|
||||
*/
|
||||
static const char *drm_get_wedge_recovery(unsigned int opt)
|
||||
{
|
||||
switch (BIT(opt)) {
|
||||
case DRM_WEDGE_RECOVERY_NONE:
|
||||
return "none";
|
||||
case DRM_WEDGE_RECOVERY_REBIND:
|
||||
return "rebind";
|
||||
case DRM_WEDGE_RECOVERY_BUS_RESET:
|
||||
return "bus-reset";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_dev_wedged_event - generate a device wedged uevent
|
||||
* @dev: DRM device
|
||||
* @method: method(s) to be used for recovery
|
||||
*
|
||||
* This generates a device wedged uevent for the DRM device specified by @dev.
|
||||
* Recovery @method\(s) of choice will be sent in the uevent environment as
|
||||
* ``WEDGED=<method1>[,..,<methodN>]`` in order of less to more side-effects.
|
||||
* If caller is unsure about recovery or @method is unknown (0),
|
||||
* ``WEDGED=unknown`` will be sent instead.
|
||||
*
|
||||
* Refer to "Device Wedging" chapter in Documentation/gpu/drm-uapi.rst for more
|
||||
* details.
|
||||
*
|
||||
* Returns: 0 on success, negative error code otherwise.
|
||||
*/
|
||||
int drm_dev_wedged_event(struct drm_device *dev, unsigned long method)
|
||||
{
|
||||
const char *recovery = NULL;
|
||||
unsigned int len, opt;
|
||||
/* Event string length up to 28+ characters with available methods */
|
||||
char event_string[32];
|
||||
char *envp[] = { event_string, NULL };
|
||||
|
||||
len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED=");
|
||||
|
||||
for_each_set_bit(opt, &method, BITS_PER_TYPE(method)) {
|
||||
recovery = drm_get_wedge_recovery(opt);
|
||||
if (drm_WARN_ONCE(dev, !recovery, "invalid recovery method %u\n", opt))
|
||||
break;
|
||||
|
||||
len += scnprintf(event_string + len, sizeof(event_string), "%s,", recovery);
|
||||
}
|
||||
|
||||
if (recovery)
|
||||
/* Get rid of trailing comma */
|
||||
event_string[len - 1] = '\0';
|
||||
else
|
||||
/* Caller is unsure about recovery, do the best we can at this point. */
|
||||
snprintf(event_string, sizeof(event_string), "%s", "WEDGED=unknown");
|
||||
|
||||
drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ?
|
||||
"but recovered through reset" : "needs recovery");
|
||||
|
||||
return kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dev_wedged_event);
|
||||
|
||||
/*
|
||||
* DRM internal mount
|
||||
* We want to be able to allocate our own "struct address_space" to control
|
||||
|
||||
@@ -978,6 +978,75 @@ void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pit
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
|
||||
|
||||
static void drm_fb_argb8888_to_argb4444_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
unsigned int pixels2 = pixels & ~GENMASK_ULL(0, 0);
|
||||
__le32 *dbuf32 = dbuf;
|
||||
__le16 *dbuf16 = dbuf + pixels2 * sizeof(*dbuf16);
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u32 val32;
|
||||
u16 val16;
|
||||
u32 pix[2];
|
||||
|
||||
for (x = 0; x < pixels2; x += 2, ++dbuf32) {
|
||||
pix[0] = le32_to_cpu(sbuf32[x]);
|
||||
pix[1] = le32_to_cpu(sbuf32[x + 1]);
|
||||
val32 = ((pix[0] & 0xf0000000) >> 16) |
|
||||
((pix[0] & 0x00f00000) >> 12) |
|
||||
((pix[0] & 0x0000f000) >> 8) |
|
||||
((pix[0] & 0x000000f0) >> 4) |
|
||||
((pix[1] & 0xf0000000) >> 0) |
|
||||
((pix[1] & 0x00f00000) << 4) |
|
||||
((pix[1] & 0x0000f000) << 8) |
|
||||
((pix[1] & 0x000000f0) << 12);
|
||||
*dbuf32 = cpu_to_le32(val32);
|
||||
}
|
||||
for (; x < pixels; x++) {
|
||||
pix[0] = le32_to_cpu(sbuf32[x]);
|
||||
val16 = ((pix[0] & 0xf0000000) >> 16) |
|
||||
((pix[0] & 0x00f00000) >> 12) |
|
||||
((pix[0] & 0x0000f000) >> 8) |
|
||||
((pix[0] & 0x000000f0) >> 4);
|
||||
dbuf16[x] = cpu_to_le16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_argb8888_to_argb4444 - Convert ARGB8888 to ARGB4444 clip buffer
|
||||
* @dst: Array of ARGB4444 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of ARGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
* @state: Transform and conversion state
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts
|
||||
* the color format during the process. The parameters @dst, @dst_pitch and
|
||||
* @src refer to arrays. Each array must have at least as many entries as
|
||||
* there are planes in @fb's format. Each entry stores the value for the
|
||||
* format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for ARGB4444 devices that don't support
|
||||
* ARGB8888 natively.
|
||||
*/
|
||||
void drm_fb_argb8888_to_argb4444(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, struct drm_format_conv_state *state)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
2,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state,
|
||||
drm_fb_argb8888_to_argb4444_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_argb8888_to_argb4444);
|
||||
|
||||
/**
|
||||
* drm_fb_blit - Copy parts of a framebuffer to display memory
|
||||
* @dst: Array of display-memory addresses to copy to
|
||||
|
||||
@@ -268,9 +268,9 @@ int drm_of_find_panel_or_bridge(const struct device_node *np,
|
||||
*panel = NULL;
|
||||
}
|
||||
|
||||
/* No panel found yet, check for a bridge next. */
|
||||
if (bridge) {
|
||||
if (ret) {
|
||||
/* No panel found yet, check for a bridge next. */
|
||||
*bridge = of_drm_find_bridge(remote);
|
||||
if (*bridge)
|
||||
ret = 0;
|
||||
|
||||
@@ -50,7 +50,7 @@ static LIST_HEAD(panel_list);
|
||||
* @dev: parent device of the panel
|
||||
* @funcs: panel operations
|
||||
* @connector_type: the connector type (DRM_MODE_CONNECTOR_*) corresponding to
|
||||
* the panel interface
|
||||
* the panel interface (must NOT be DRM_MODE_CONNECTOR_Unknown)
|
||||
*
|
||||
* Initialize the panel structure for subsequent registration with
|
||||
* drm_panel_add().
|
||||
@@ -58,6 +58,9 @@ static LIST_HEAD(panel_list);
|
||||
void drm_panel_init(struct drm_panel *panel, struct device *dev,
|
||||
const struct drm_panel_funcs *funcs, int connector_type)
|
||||
{
|
||||
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
|
||||
DRM_WARN("%s: %s: a valid connector type is required!\n", __func__, dev_name(dev));
|
||||
|
||||
INIT_LIST_HEAD(&panel->list);
|
||||
INIT_LIST_HEAD(&panel->followers);
|
||||
mutex_init(&panel->follower_lock);
|
||||
|
||||
@@ -93,6 +93,12 @@ static const struct drm_dmi_panel_orientation_data onegx1_pro = {
|
||||
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
|
||||
};
|
||||
|
||||
static const struct drm_dmi_panel_orientation_data lcd640x960_leftside_up = {
|
||||
.width = 640,
|
||||
.height = 960,
|
||||
.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
|
||||
};
|
||||
|
||||
static const struct drm_dmi_panel_orientation_data lcd720x1280_rightside_up = {
|
||||
.width = 720,
|
||||
.height = 1280,
|
||||
@@ -123,6 +129,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
|
||||
.orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
|
||||
};
|
||||
|
||||
static const struct drm_dmi_panel_orientation_data lcd1200x1920_leftside_up = {
|
||||
.width = 1200,
|
||||
.height = 1920,
|
||||
.orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
|
||||
};
|
||||
|
||||
static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
|
||||
.width = 1200,
|
||||
.height = 1920,
|
||||
@@ -184,10 +196,10 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T103HAF"),
|
||||
},
|
||||
.driver_data = (void *)&lcd800x1280_rightside_up,
|
||||
}, { /* AYA NEO AYANEO 2 */
|
||||
}, { /* AYA NEO AYANEO 2/2S */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "AYANEO 2"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1200x1920_rightside_up,
|
||||
}, { /* AYA NEO 2021 */
|
||||
@@ -202,6 +214,18 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "AIR"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1080x1920_leftside_up,
|
||||
}, { /* AYA NEO Flip DS Bottom Screen */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FLIP DS"),
|
||||
},
|
||||
.driver_data = (void *)&lcd640x960_leftside_up,
|
||||
}, { /* AYA NEO Flip KB/DS Top Screen */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "FLIP"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1080x1920_leftside_up,
|
||||
}, { /* AYA NEO Founder */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYA NEO"),
|
||||
@@ -226,6 +250,12 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_MATCH(DMI_BOARD_NAME, "KUN"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1600x2560_rightside_up,
|
||||
}, { /* AYA NEO SLIDE */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "SLIDE"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1080x1920_leftside_up,
|
||||
}, { /* AYN Loki Max */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ayn"),
|
||||
@@ -315,6 +345,12 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_EXACT_MATCH(DMI_BOARD_NAME, "Default string"),
|
||||
},
|
||||
.driver_data = (void *)&gpd_win2,
|
||||
}, { /* GPD Win 2 (correct DMI strings) */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WIN2")
|
||||
},
|
||||
.driver_data = (void *)&lcd720x1280_rightside_up,
|
||||
}, { /* GPD Win 3 */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
|
||||
@@ -443,6 +479,12 @@ static const struct dmi_system_id orientation_data[] = {
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1600x2560_leftside_up,
|
||||
}, { /* OneXPlayer Mini (Intel) */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ONE-NETBOOK TECHNOLOGY CO., LTD."),
|
||||
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ONE XPLAYER"),
|
||||
},
|
||||
.driver_data = (void *)&lcd1200x1920_leftside_up,
|
||||
}, { /* OrangePi Neo */
|
||||
.matches = {
|
||||
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "OrangePi"),
|
||||
|
||||
@@ -360,8 +360,8 @@ static void drm_writeback_connector_cleanup(struct drm_device *dev,
|
||||
|
||||
spin_lock_irqsave(&wb_connector->job_lock, flags);
|
||||
list_for_each_entry_safe(pos, n, &wb_connector->job_queue, list_entry) {
|
||||
drm_writeback_cleanup_job(pos);
|
||||
list_del(&pos->list_entry);
|
||||
drm_writeback_cleanup_job(pos);
|
||||
}
|
||||
spin_unlock_irqrestore(&wb_connector->job_lock, flags);
|
||||
}
|
||||
|
||||
@@ -144,17 +144,17 @@ int etnaviv_sched_push_job(struct etnaviv_gem_submit *submit)
|
||||
|
||||
int etnaviv_sched_init(struct etnaviv_gpu *gpu)
|
||||
{
|
||||
int ret;
|
||||
const struct drm_sched_init_args args = {
|
||||
.ops = &etnaviv_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = etnaviv_hw_jobs_limit,
|
||||
.hang_limit = etnaviv_job_hang_limit,
|
||||
.timeout = msecs_to_jiffies(500),
|
||||
.name = dev_name(gpu->dev),
|
||||
.dev = gpu->dev,
|
||||
};
|
||||
|
||||
ret = drm_sched_init(&gpu->sched, &etnaviv_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
etnaviv_hw_jobs_limit, etnaviv_job_hang_limit,
|
||||
msecs_to_jiffies(500), NULL, NULL,
|
||||
dev_name(gpu->dev), gpu->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
return drm_sched_init(&gpu->sched, &args);
|
||||
}
|
||||
|
||||
void etnaviv_sched_fini(struct etnaviv_gpu *gpu)
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
menu "I2C encoder or helper chips"
|
||||
depends on DRM && DRM_KMS_HELPER && I2C
|
||||
|
||||
config DRM_I2C_NXP_TDA998X
|
||||
tristate "NXP Semiconductors TDA998X HDMI encoder"
|
||||
default m if DRM_TILCDC
|
||||
select CEC_CORE if CEC_NOTIFIER
|
||||
select SND_SOC_HDMI_CODEC if SND_SOC
|
||||
help
|
||||
Support for NXP Semiconductors TDA998X HDMI encoders.
|
||||
|
||||
config DRM_I2C_NXP_TDA9950
|
||||
tristate "NXP Semiconductors TDA9950/TDA998X HDMI CEC"
|
||||
select CEC_NOTIFIER
|
||||
select CEC_CORE
|
||||
|
||||
endmenu
|
||||
@@ -1,4 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
tda998x-y := tda998x_drv.o
|
||||
obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o
|
||||
obj-$(CONFIG_DRM_I2C_NXP_TDA9950) += tda9950.o
|
||||
@@ -1422,6 +1422,9 @@ static void intel_gt_reset_global(struct intel_gt *gt,
|
||||
|
||||
if (!test_bit(I915_WEDGED, >->reset.flags))
|
||||
kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event);
|
||||
else
|
||||
drm_dev_wedged_event(>->i915->drm,
|
||||
DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1210,6 +1210,17 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx,
|
||||
},
|
||||
};
|
||||
struct pvr_device *pvr_dev = ctx->pvr_dev;
|
||||
const struct drm_sched_init_args sched_args = {
|
||||
.ops = &pvr_queue_sched_ops,
|
||||
.submit_wq = pvr_dev->sched_wq,
|
||||
.num_rqs = 1,
|
||||
.credit_limit = 64 * 1024,
|
||||
.hang_limit = 1,
|
||||
.timeout = msecs_to_jiffies(500),
|
||||
.timeout_wq = pvr_dev->sched_wq,
|
||||
.name = "pvr-queue",
|
||||
.dev = pvr_dev->base.dev,
|
||||
};
|
||||
struct drm_gpu_scheduler *sched;
|
||||
struct pvr_queue *queue;
|
||||
int ctx_state_size, err;
|
||||
@@ -1282,12 +1293,7 @@ struct pvr_queue *pvr_queue_create(struct pvr_context *ctx,
|
||||
|
||||
queue->timeline_ufo.value = cpu_map;
|
||||
|
||||
err = drm_sched_init(&queue->scheduler,
|
||||
&pvr_queue_sched_ops,
|
||||
pvr_dev->sched_wq, 1, 64 * 1024, 1,
|
||||
msecs_to_jiffies(500),
|
||||
pvr_dev->sched_wq, NULL, "pvr-queue",
|
||||
pvr_dev->base.dev);
|
||||
err = drm_sched_init(&queue->scheduler, &sched_args);
|
||||
if (err)
|
||||
goto err_release_ufo;
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ static int ingenic_drm_update_pixclk(struct notifier_block *nb,
|
||||
}
|
||||
|
||||
static void ingenic_drm_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(bridge->dev);
|
||||
|
||||
@@ -260,7 +260,7 @@ static void ingenic_drm_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
static void ingenic_drm_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct ingenic_drm *priv = drm_device_get_priv(bridge->dev);
|
||||
unsigned int var;
|
||||
|
||||
@@ -515,18 +515,22 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
|
||||
{
|
||||
unsigned int timeout = lima_sched_timeout_ms > 0 ?
|
||||
lima_sched_timeout_ms : 10000;
|
||||
const struct drm_sched_init_args args = {
|
||||
.ops = &lima_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = 1,
|
||||
.hang_limit = lima_job_hang_limit,
|
||||
.timeout = msecs_to_jiffies(timeout),
|
||||
.name = name,
|
||||
.dev = pipe->ldev->dev,
|
||||
};
|
||||
|
||||
pipe->fence_context = dma_fence_context_alloc(1);
|
||||
spin_lock_init(&pipe->fence_lock);
|
||||
|
||||
INIT_WORK(&pipe->recover_work, lima_sched_recover_work);
|
||||
|
||||
return drm_sched_init(&pipe->base, &lima_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
1,
|
||||
lima_job_hang_limit,
|
||||
msecs_to_jiffies(timeout), NULL,
|
||||
NULL, name, pipe->ldev->dev);
|
||||
return drm_sched_init(&pipe->base, &args);
|
||||
}
|
||||
|
||||
void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
|
||||
|
||||
@@ -171,7 +171,8 @@ static const struct drm_plane_helper_funcs lsdc_primary_helper_funcs = {
|
||||
};
|
||||
|
||||
static int lsdc_cursor_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *state,
|
||||
bool flip)
|
||||
{
|
||||
struct drm_plane_state *new_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
@@ -2350,12 +2350,12 @@ static void mtk_dp_bridge_detach(struct drm_bridge *bridge)
|
||||
}
|
||||
|
||||
static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
|
||||
int ret;
|
||||
|
||||
mtk_dp->conn = drm_atomic_get_new_connector_for_encoder(old_state->base.state,
|
||||
mtk_dp->conn = drm_atomic_get_new_connector_for_encoder(state,
|
||||
bridge->encoder);
|
||||
if (!mtk_dp->conn) {
|
||||
drm_err(mtk_dp->drm_dev,
|
||||
@@ -2400,7 +2400,7 @@ static void mtk_dp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_dp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dp *mtk_dp = mtk_dp_from_bridge(bridge);
|
||||
|
||||
|
||||
@@ -826,7 +826,7 @@ static void mtk_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@@ -834,7 +834,7 @@ static void mtk_dsi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@@ -845,7 +845,7 @@ static void mtk_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dsi *dsi = bridge_to_dsi(bridge);
|
||||
int ret;
|
||||
@@ -856,7 +856,7 @@ static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
|
||||
@@ -1309,7 +1309,7 @@ static bool mtk_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
|
||||
|
||||
@@ -1326,7 +1326,7 @@ static void mtk_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
|
||||
|
||||
@@ -1362,7 +1362,7 @@ static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void mtk_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
|
||||
|
||||
@@ -1383,9 +1383,8 @@ static void mtk_hdmi_send_infoframe(struct mtk_hdmi *hdmi,
|
||||
}
|
||||
|
||||
static void mtk_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_state->base.state;
|
||||
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
|
||||
|
||||
/* Retrieve the connector through the atomic state. */
|
||||
|
||||
@@ -101,7 +101,7 @@ static void mtk_plane_destroy_state(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static int mtk_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *state, bool flip)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
|
||||
@@ -139,10 +139,9 @@ static int meson_encoder_cvbs_atomic_check(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_cvbs *encoder_cvbs = bridge_to_meson_encoder_cvbs(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct meson_drm *priv = encoder_cvbs->priv;
|
||||
const struct meson_cvbs_mode *meson_mode;
|
||||
struct drm_connector_state *conn_state;
|
||||
@@ -191,7 +190,7 @@ static void meson_encoder_cvbs_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void meson_encoder_cvbs_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_cvbs *meson_encoder_cvbs =
|
||||
bridge_to_meson_encoder_cvbs(bridge);
|
||||
|
||||
@@ -42,10 +42,9 @@ static int meson_encoder_dsi_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_dsi *encoder_dsi = bridge_to_meson_encoder_dsi(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct meson_drm *priv = encoder_dsi->priv;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@@ -80,7 +79,7 @@ static void meson_encoder_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void meson_encoder_dsi_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_dsi *meson_encoder_dsi =
|
||||
bridge_to_meson_encoder_dsi(bridge);
|
||||
|
||||
@@ -186,10 +186,9 @@ static enum drm_mode_status meson_encoder_hdmi_mode_valid(struct drm_bridge *bri
|
||||
}
|
||||
|
||||
static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
|
||||
struct meson_drm *priv = encoder_hdmi->priv;
|
||||
struct drm_connector_state *conn_state;
|
||||
@@ -250,7 +249,7 @@ static void meson_encoder_hdmi_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void meson_encoder_hdmi_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct meson_encoder_hdmi *encoder_hdmi = bridge_to_meson_encoder_hdmi(bridge);
|
||||
struct meson_drm *priv = encoder_hdmi->priv;
|
||||
|
||||
@@ -368,7 +368,7 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static int mdp5_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *state, bool flip)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
|
||||
@@ -1491,13 +1491,13 @@ int msm_dp_modeset_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
|
||||
}
|
||||
|
||||
void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
|
||||
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
|
||||
int rc = 0;
|
||||
struct msm_dp_display_private *msm_dp_display;
|
||||
u32 state;
|
||||
u32 hpd_state;
|
||||
bool force_link_train = false;
|
||||
|
||||
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
|
||||
@@ -1516,8 +1516,8 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
return;
|
||||
}
|
||||
|
||||
state = msm_dp_display->hpd_state;
|
||||
if (state != ST_DISPLAY_OFF && state != ST_MAINLINK_READY) {
|
||||
hpd_state = msm_dp_display->hpd_state;
|
||||
if (hpd_state != ST_DISPLAY_OFF && hpd_state != ST_MAINLINK_READY) {
|
||||
mutex_unlock(&msm_dp_display->event_mutex);
|
||||
return;
|
||||
}
|
||||
@@ -1529,9 +1529,9 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
return;
|
||||
}
|
||||
|
||||
state = msm_dp_display->hpd_state;
|
||||
hpd_state = msm_dp_display->hpd_state;
|
||||
|
||||
if (state == ST_DISPLAY_OFF) {
|
||||
if (hpd_state == ST_DISPLAY_OFF) {
|
||||
msm_dp_display_host_phy_init(msm_dp_display);
|
||||
force_link_train = true;
|
||||
}
|
||||
@@ -1552,7 +1552,7 @@ void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
}
|
||||
|
||||
void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
|
||||
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
|
||||
@@ -1564,11 +1564,11 @@ void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
}
|
||||
|
||||
void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
|
||||
struct msm_dp *dp = msm_dp_bridge->msm_dp_display;
|
||||
u32 state;
|
||||
u32 hpd_state;
|
||||
struct msm_dp_display_private *msm_dp_display;
|
||||
|
||||
msm_dp_display = container_of(dp, struct msm_dp_display_private, msm_dp_display);
|
||||
@@ -1578,15 +1578,15 @@ void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
|
||||
|
||||
mutex_lock(&msm_dp_display->event_mutex);
|
||||
|
||||
state = msm_dp_display->hpd_state;
|
||||
if (state != ST_DISCONNECT_PENDING && state != ST_CONNECTED)
|
||||
hpd_state = msm_dp_display->hpd_state;
|
||||
if (hpd_state != ST_DISCONNECT_PENDING && hpd_state != ST_CONNECTED)
|
||||
drm_dbg_dp(dp->drm_dev, "type=%d wrong hpd_state=%d\n",
|
||||
dp->connector_type, state);
|
||||
dp->connector_type, hpd_state);
|
||||
|
||||
msm_dp_display_disable(msm_dp_display);
|
||||
|
||||
state = msm_dp_display->hpd_state;
|
||||
if (state == ST_DISCONNECT_PENDING) {
|
||||
hpd_state = msm_dp_display->hpd_state;
|
||||
if (hpd_state == ST_DISCONNECT_PENDING) {
|
||||
/* completed disconnection */
|
||||
msm_dp_display->hpd_state = ST_DISCONNECTED;
|
||||
} else {
|
||||
|
||||
@@ -137,9 +137,8 @@ static int msm_edp_bridge_atomic_check(struct drm_bridge *drm_bridge,
|
||||
}
|
||||
|
||||
static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
|
||||
@@ -151,25 +150,24 @@ static void msm_edp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
* If the panel is in psr, just exit psr state and skip the full
|
||||
* bridge enable sequence.
|
||||
*/
|
||||
crtc = drm_atomic_get_new_crtc_for_encoder(atomic_state,
|
||||
crtc = drm_atomic_get_new_crtc_for_encoder(state,
|
||||
drm_bridge->encoder);
|
||||
if (!crtc)
|
||||
return;
|
||||
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(atomic_state, crtc);
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
|
||||
|
||||
if (old_crtc_state && old_crtc_state->self_refresh_active) {
|
||||
msm_dp_display_set_psr(dp, false);
|
||||
return;
|
||||
}
|
||||
|
||||
msm_dp_bridge_atomic_enable(drm_bridge, old_bridge_state);
|
||||
msm_dp_bridge_atomic_enable(drm_bridge, state);
|
||||
}
|
||||
|
||||
static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL, *old_crtc_state = NULL;
|
||||
struct msm_dp_bridge *msm_dp_bridge = to_dp_bridge(drm_bridge);
|
||||
@@ -208,13 +206,12 @@ static void msm_edp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
}
|
||||
|
||||
out:
|
||||
msm_dp_bridge_atomic_disable(drm_bridge, old_bridge_state);
|
||||
msm_dp_bridge_atomic_disable(drm_bridge, atomic_state);
|
||||
}
|
||||
|
||||
static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *atomic_state)
|
||||
{
|
||||
struct drm_atomic_state *atomic_state = old_bridge_state->base.state;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
|
||||
@@ -233,7 +230,7 @@ static void msm_edp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
|
||||
if (new_crtc_state->self_refresh_active)
|
||||
return;
|
||||
|
||||
msm_dp_bridge_atomic_post_disable(drm_bridge, old_bridge_state);
|
||||
msm_dp_bridge_atomic_post_disable(drm_bridge, atomic_state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,11 +26,11 @@ int msm_dp_bridge_init(struct msm_dp *msm_dp_display, struct drm_device *dev,
|
||||
bool yuv_supported);
|
||||
|
||||
void msm_dp_bridge_atomic_enable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state);
|
||||
struct drm_atomic_state *state);
|
||||
void msm_dp_bridge_atomic_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state);
|
||||
struct drm_atomic_state *state);
|
||||
void msm_dp_bridge_atomic_post_disable(struct drm_bridge *drm_bridge,
|
||||
struct drm_bridge_state *old_bridge_state);
|
||||
struct drm_atomic_state *state);
|
||||
enum drm_mode_status msm_dp_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_info *info,
|
||||
const struct drm_display_mode *mode);
|
||||
|
||||
@@ -59,8 +59,14 @@ static const struct drm_sched_backend_ops msm_sched_ops = {
|
||||
struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
||||
void *memptrs, uint64_t memptrs_iova)
|
||||
{
|
||||
struct drm_sched_init_args args = {
|
||||
.ops = &msm_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = num_hw_submissions,
|
||||
.timeout = MAX_SCHEDULE_TIMEOUT,
|
||||
.dev = gpu->dev->dev,
|
||||
};
|
||||
struct msm_ringbuffer *ring;
|
||||
long sched_timeout;
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
@@ -87,6 +93,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
||||
}
|
||||
|
||||
msm_gem_object_set_name(ring->bo, "ring%d", id);
|
||||
args.name = to_msm_bo(ring->bo)->name,
|
||||
|
||||
ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2);
|
||||
ring->next = ring->start;
|
||||
@@ -95,13 +102,7 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id,
|
||||
ring->memptrs = memptrs;
|
||||
ring->memptrs_iova = memptrs_iova;
|
||||
|
||||
/* currently managing hangcheck ourselves: */
|
||||
sched_timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
|
||||
ret = drm_sched_init(&ring->sched, &msm_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
num_hw_submissions, 0, sched_timeout,
|
||||
NULL, NULL, to_msm_bo(ring->bo)->name, gpu->dev->dev);
|
||||
ret = drm_sched_init(&ring->sched, &args);
|
||||
if (ret) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -404,7 +404,14 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm,
|
||||
{
|
||||
struct drm_gpu_scheduler *drm_sched = &sched->base;
|
||||
struct drm_sched_entity *entity = &sched->entity;
|
||||
const long timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS);
|
||||
struct drm_sched_init_args args = {
|
||||
.ops = &nouveau_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = credit_limit,
|
||||
.timeout = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS),
|
||||
.name = "nouveau_sched",
|
||||
.dev = drm->dev->dev
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!wq) {
|
||||
@@ -416,10 +423,9 @@ nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm,
|
||||
sched->wq = wq;
|
||||
}
|
||||
|
||||
ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq,
|
||||
NOUVEAU_SCHED_PRIORITY_COUNT,
|
||||
credit_limit, 0, timeout,
|
||||
NULL, NULL, "nouveau_sched", drm->dev->dev);
|
||||
args.submit_wq = wq,
|
||||
|
||||
ret = drm_sched_init(drm_sched, &args);
|
||||
if (ret)
|
||||
goto fail_wq;
|
||||
|
||||
|
||||
@@ -348,6 +348,7 @@ r535_gsp_msgq_recv(struct nvkm_gsp *gsp, u32 gsp_rpc_len, int *retries)
|
||||
if (IS_ERR(buf)) {
|
||||
kvfree(info.gsp_rpc_buf);
|
||||
info.gsp_rpc_buf = NULL;
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (expected <= max_rpc_size)
|
||||
|
||||
@@ -341,10 +341,9 @@ static void hdmi4_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void hdmi4_bridge_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@@ -410,7 +409,7 @@ static void hdmi4_bridge_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void hdmi4_bridge_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
|
||||
unsigned long flags;
|
||||
|
||||
@@ -339,10 +339,9 @@ static void hdmi5_bridge_mode_set(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void hdmi5_bridge_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
|
||||
struct drm_atomic_state *state = bridge_state->base.state;
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
@@ -408,7 +407,7 @@ static void hdmi5_bridge_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void hdmi5_bridge_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge);
|
||||
unsigned long flags;
|
||||
|
||||
@@ -42,85 +42,84 @@ static void visionox_r66451_reset(struct visionox_r66451 *ctx)
|
||||
static int visionox_r66451_on(struct visionox_r66451 *ctx)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
dsi->mode_flags |= MIPI_DSI_MODE_LPM;
|
||||
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc2,
|
||||
0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x09, 0x3c);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd7,
|
||||
0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a,
|
||||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
|
||||
0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xde,
|
||||
0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18,
|
||||
0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xe8, 0x00, 0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x00, 0x08);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xc4,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xcf,
|
||||
0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x03);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd3,
|
||||
0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07,
|
||||
0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0,
|
||||
0x3c, 0x9c);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd7,
|
||||
0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a,
|
||||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
|
||||
0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xd8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a,
|
||||
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
|
||||
0x00, 0x32, 0x00, 0x0a, 0x00, 0x22);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xdf,
|
||||
0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf7, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x80);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39, 0x04, 0x09, 0x34);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xe6, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x40);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x11);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf4, 0x00, 0x02);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xf2, 0x19);
|
||||
mipi_dsi_dcs_write_seq(dsi, 0xdf, 0x50, 0x42);
|
||||
mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
mipi_dsi_dcs_set_column_address(dsi, 0, 1080 - 1);
|
||||
mipi_dsi_dcs_set_page_address(dsi, 0, 2340 - 1);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc2,
|
||||
0x09, 0x24, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
|
||||
0x09, 0x3c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7,
|
||||
0x00, 0xb9, 0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a,
|
||||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
|
||||
0x3c, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xde,
|
||||
0x40, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18,
|
||||
0x10, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x02, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe8, 0x00, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x00, 0x08);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xc4,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x32);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xcf,
|
||||
0x64, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
|
||||
0x00, 0x0b, 0x77, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x03);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd3,
|
||||
0x45, 0x00, 0x00, 0x01, 0x13, 0x15, 0x00, 0x15, 0x07,
|
||||
0x0f, 0x77, 0x77, 0x77, 0x37, 0xb2, 0x11, 0x00, 0xa0,
|
||||
0x3c, 0x9c);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd7,
|
||||
0x00, 0xb9, 0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a,
|
||||
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
|
||||
0x34, 0x00, 0x40, 0x04, 0x00, 0xa0, 0x0a);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xd8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a,
|
||||
0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x0a, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a,
|
||||
0x00, 0x32, 0x00, 0x0a, 0x00, 0x22);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf,
|
||||
0x50, 0x42, 0x58, 0x81, 0x2d, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x01, 0x0f, 0xff, 0xd4, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0xf1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf7, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x80);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe4, 0x34, 0xb4, 0x00, 0x00, 0x00, 0x39,
|
||||
0x04, 0x09, 0x34);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xe6, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xb0, 0x04);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x40);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x50, 0x00, 0x00, 0x00, 0x00);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x11);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf3, 0x01, 0x00, 0x00, 0x00, 0x01);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf4, 0x00, 0x02);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xf2, 0x19);
|
||||
mipi_dsi_dcs_write_seq_multi(&dsi_ctx, 0xdf, 0x50, 0x42);
|
||||
mipi_dsi_dcs_set_tear_on_multi(&dsi_ctx, MIPI_DSI_DCS_TEAR_MODE_VBLANK);
|
||||
mipi_dsi_dcs_set_column_address_multi(&dsi_ctx, 0, 1080 - 1);
|
||||
mipi_dsi_dcs_set_page_address_multi(&dsi_ctx, 0, 2340 - 1);
|
||||
|
||||
dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int visionox_r66451_off(struct visionox_r66451 *ctx)
|
||||
static void visionox_r66451_off(struct visionox_r66451 *ctx)
|
||||
{
|
||||
ctx->dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int visionox_r66451_prepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_r66451 *ctx = to_visionox_r66451(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies),
|
||||
@@ -132,7 +131,6 @@ static int visionox_r66451_prepare(struct drm_panel *panel)
|
||||
|
||||
ret = visionox_r66451_on(ctx);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to initialize panel: %d\n", ret);
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
return ret;
|
||||
@@ -146,12 +144,8 @@ static int visionox_r66451_prepare(struct drm_panel *panel)
|
||||
static int visionox_r66451_unprepare(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_r66451 *ctx = to_visionox_r66451(panel);
|
||||
struct device *dev = &ctx->dsi->dev;
|
||||
int ret;
|
||||
|
||||
ret = visionox_r66451_off(ctx);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Failed to un-initialize panel: %d\n", ret);
|
||||
visionox_r66451_off(ctx);
|
||||
|
||||
gpiod_set_value_cansleep(ctx->reset_gpio, 1);
|
||||
regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
|
||||
@@ -179,7 +173,7 @@ static int visionox_r66451_enable(struct drm_panel *panel)
|
||||
struct visionox_r66451 *ctx = to_visionox_r66451(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct drm_dsc_picture_parameter_set pps;
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
if (!dsi->dsc) {
|
||||
dev_err(&dsi->dev, "DSC not attached to DSI\n");
|
||||
@@ -187,51 +181,30 @@ static int visionox_r66451_enable(struct drm_panel *panel)
|
||||
}
|
||||
|
||||
drm_dsc_pps_payload_pack(&pps, dsi->dsc);
|
||||
ret = mipi_dsi_picture_parameter_set(dsi, &pps);
|
||||
if (ret) {
|
||||
dev_err(&dsi->dev, "Failed to set PPS\n");
|
||||
return ret;
|
||||
}
|
||||
mipi_dsi_picture_parameter_set_multi(&dsi_ctx, &pps);
|
||||
|
||||
ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(&dsi->dev, "Failed to exit sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
mipi_dsi_dcs_exit_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_on(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(&dsi->dev, "Failed on set display on: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
mipi_dsi_dcs_set_display_on_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int visionox_r66451_disable(struct drm_panel *panel)
|
||||
{
|
||||
struct visionox_r66451 *ctx = to_visionox_r66451(panel);
|
||||
struct mipi_dsi_device *dsi = ctx->dsi;
|
||||
struct device *dev = &dsi->dev;
|
||||
int ret;
|
||||
struct mipi_dsi_multi_context dsi_ctx = { .dsi = dsi };
|
||||
|
||||
ret = mipi_dsi_dcs_set_display_off(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set display off: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(20);
|
||||
mipi_dsi_dcs_set_display_off_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 20);
|
||||
|
||||
ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to enter sleep mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
msleep(120);
|
||||
mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx);
|
||||
mipi_dsi_msleep(&dsi_ctx, 120);
|
||||
|
||||
return 0;
|
||||
return dsi_ctx.accum_err;
|
||||
}
|
||||
|
||||
static int visionox_r66451_get_modes(struct drm_panel *panel,
|
||||
|
||||
@@ -836,8 +836,16 @@ static irqreturn_t panfrost_job_irq_handler(int irq, void *data)
|
||||
|
||||
int panfrost_job_init(struct panfrost_device *pfdev)
|
||||
{
|
||||
struct drm_sched_init_args args = {
|
||||
.ops = &panfrost_sched_ops,
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = 2,
|
||||
.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS),
|
||||
.timeout_wq = pfdev->reset.wq,
|
||||
.name = "pan_js",
|
||||
.dev = pfdev->dev,
|
||||
};
|
||||
struct panfrost_job_slot *js;
|
||||
unsigned int nentries = 2;
|
||||
int ret, j;
|
||||
|
||||
/* All GPUs have two entries per queue, but without jobchain
|
||||
@@ -845,7 +853,7 @@ int panfrost_job_init(struct panfrost_device *pfdev)
|
||||
* so let's just advertise one entry in that case.
|
||||
*/
|
||||
if (!panfrost_has_hw_feature(pfdev, HW_FEATURE_JOBCHAIN_DISAMBIGUATION))
|
||||
nentries = 1;
|
||||
args.credit_limit = 1;
|
||||
|
||||
pfdev->js = js = devm_kzalloc(pfdev->dev, sizeof(*js), GFP_KERNEL);
|
||||
if (!js)
|
||||
@@ -875,13 +883,7 @@ int panfrost_job_init(struct panfrost_device *pfdev)
|
||||
for (j = 0; j < NUM_JOB_SLOTS; j++) {
|
||||
js->queue[j].fence_context = dma_fence_context_alloc(1);
|
||||
|
||||
ret = drm_sched_init(&js->queue[j].sched,
|
||||
&panfrost_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
nentries, 0,
|
||||
msecs_to_jiffies(JOB_TIMEOUT_MS),
|
||||
pfdev->reset.wq,
|
||||
NULL, "pan_js", pfdev->dev);
|
||||
ret = drm_sched_init(&js->queue[j].sched, &args);
|
||||
if (ret) {
|
||||
dev_err(pfdev->dev, "Failed to create scheduler: %d.", ret);
|
||||
goto err_sched;
|
||||
|
||||
@@ -2311,6 +2311,16 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu,
|
||||
u64 full_va_range = 1ull << va_bits;
|
||||
struct drm_gem_object *dummy_gem;
|
||||
struct drm_gpu_scheduler *sched;
|
||||
const struct drm_sched_init_args sched_args = {
|
||||
.ops = &panthor_vm_bind_ops,
|
||||
.submit_wq = ptdev->mmu->vm.wq,
|
||||
.num_rqs = 1,
|
||||
.credit_limit = 1,
|
||||
/* Bind operations are synchronous for now, no timeout needed. */
|
||||
.timeout = MAX_SCHEDULE_TIMEOUT,
|
||||
.name = "panthor-vm-bind",
|
||||
.dev = ptdev->base.dev,
|
||||
};
|
||||
struct io_pgtable_cfg pgtbl_cfg;
|
||||
u64 mair, min_va, va_range;
|
||||
struct panthor_vm *vm;
|
||||
@@ -2368,11 +2378,7 @@ panthor_vm_create(struct panthor_device *ptdev, bool for_mcu,
|
||||
goto err_mm_takedown;
|
||||
}
|
||||
|
||||
/* Bind operations are synchronous for now, no timeout needed. */
|
||||
ret = drm_sched_init(&vm->sched, &panthor_vm_bind_ops, ptdev->mmu->vm.wq,
|
||||
1, 1, 0,
|
||||
MAX_SCHEDULE_TIMEOUT, NULL, NULL,
|
||||
"panthor-vm-bind", ptdev->base.dev);
|
||||
ret = drm_sched_init(&vm->sched, &sched_args);
|
||||
if (ret)
|
||||
goto err_free_io_pgtable;
|
||||
|
||||
|
||||
@@ -3289,6 +3289,22 @@ static struct panthor_queue *
|
||||
group_create_queue(struct panthor_group *group,
|
||||
const struct drm_panthor_queue_create *args)
|
||||
{
|
||||
const struct drm_sched_init_args sched_args = {
|
||||
.ops = &panthor_queue_sched_ops,
|
||||
.submit_wq = group->ptdev->scheduler->wq,
|
||||
.num_rqs = 1,
|
||||
/*
|
||||
* The credit limit argument tells us the total number of
|
||||
* instructions across all CS slots in the ringbuffer, with
|
||||
* some jobs requiring twice as many as others, depending on
|
||||
* their profiling status.
|
||||
*/
|
||||
.credit_limit = args->ringbuf_size / sizeof(u64),
|
||||
.timeout = msecs_to_jiffies(JOB_TIMEOUT_MS),
|
||||
.timeout_wq = group->ptdev->reset.wq,
|
||||
.name = "panthor-queue",
|
||||
.dev = group->ptdev->base.dev,
|
||||
};
|
||||
struct drm_gpu_scheduler *drm_sched;
|
||||
struct panthor_queue *queue;
|
||||
int ret;
|
||||
@@ -3359,17 +3375,7 @@ group_create_queue(struct panthor_group *group,
|
||||
if (ret)
|
||||
goto err_free_queue;
|
||||
|
||||
/*
|
||||
* Credit limit argument tells us the total number of instructions
|
||||
* across all CS slots in the ringbuffer, with some jobs requiring
|
||||
* twice as many as others, depending on their profiling status.
|
||||
*/
|
||||
ret = drm_sched_init(&queue->scheduler, &panthor_queue_sched_ops,
|
||||
group->ptdev->scheduler->wq, 1,
|
||||
args->ringbuf_size / sizeof(u64),
|
||||
0, msecs_to_jiffies(JOB_TIMEOUT_MS),
|
||||
group->ptdev->reset.wq,
|
||||
NULL, "panthor-queue", group->ptdev->base.dev);
|
||||
ret = drm_sched_init(&queue->scheduler, &sched_args);
|
||||
if (ret)
|
||||
goto err_free_queue;
|
||||
|
||||
|
||||
@@ -582,9 +582,8 @@ EXPORT_SYMBOL_GPL(rcar_lvds_pclk_disable);
|
||||
*/
|
||||
|
||||
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
@@ -596,7 +595,7 @@ static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
|
||||
|
||||
|
||||
@@ -808,7 +808,7 @@ static int rcar_mipi_dsi_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
|
||||
|
||||
@@ -816,7 +816,7 @@ static void rcar_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void rcar_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rcar_mipi_dsi *dsi = bridge_to_rcar_mipi_dsi(bridge);
|
||||
|
||||
|
||||
@@ -532,9 +532,8 @@ static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_connector *connector;
|
||||
@@ -568,7 +567,7 @@ static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
|
||||
|
||||
|
||||
@@ -1072,7 +1072,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane,
|
||||
}
|
||||
|
||||
static int vop_plane_atomic_async_check(struct drm_plane *plane,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *state, bool flip)
|
||||
{
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
|
||||
@@ -1244,40 +1244,24 @@ static void drm_sched_run_job_work(struct work_struct *w)
|
||||
* drm_sched_init - Init a gpu scheduler instance
|
||||
*
|
||||
* @sched: scheduler instance
|
||||
* @ops: backend operations for this scheduler
|
||||
* @submit_wq: workqueue to use for submission. If NULL, an ordered wq is
|
||||
* allocated and used
|
||||
* @num_rqs: number of runqueues, one for each priority, up to DRM_SCHED_PRIORITY_COUNT
|
||||
* @credit_limit: the number of credits this scheduler can hold from all jobs
|
||||
* @hang_limit: number of times to allow a job to hang before dropping it
|
||||
* @timeout: timeout value in jiffies for the scheduler
|
||||
* @timeout_wq: workqueue to use for timeout work. If NULL, the system_wq is
|
||||
* used
|
||||
* @score: optional score atomic shared with other schedulers
|
||||
* @name: name used for debugging
|
||||
* @dev: target &struct device
|
||||
* @args: scheduler initialization arguments
|
||||
*
|
||||
* Return 0 on success, otherwise error code.
|
||||
*/
|
||||
int drm_sched_init(struct drm_gpu_scheduler *sched,
|
||||
const struct drm_sched_backend_ops *ops,
|
||||
struct workqueue_struct *submit_wq,
|
||||
u32 num_rqs, u32 credit_limit, unsigned int hang_limit,
|
||||
long timeout, struct workqueue_struct *timeout_wq,
|
||||
atomic_t *score, const char *name, struct device *dev)
|
||||
int drm_sched_init(struct drm_gpu_scheduler *sched, const struct drm_sched_init_args *args)
|
||||
{
|
||||
int i;
|
||||
|
||||
sched->ops = ops;
|
||||
sched->credit_limit = credit_limit;
|
||||
sched->name = name;
|
||||
sched->timeout = timeout;
|
||||
sched->timeout_wq = timeout_wq ? : system_wq;
|
||||
sched->hang_limit = hang_limit;
|
||||
sched->score = score ? score : &sched->_score;
|
||||
sched->dev = dev;
|
||||
sched->ops = args->ops;
|
||||
sched->credit_limit = args->credit_limit;
|
||||
sched->name = args->name;
|
||||
sched->timeout = args->timeout;
|
||||
sched->hang_limit = args->hang_limit;
|
||||
sched->timeout_wq = args->timeout_wq ? args->timeout_wq : system_wq;
|
||||
sched->score = args->score ? args->score : &sched->_score;
|
||||
sched->dev = args->dev;
|
||||
|
||||
if (num_rqs > DRM_SCHED_PRIORITY_COUNT) {
|
||||
if (args->num_rqs > DRM_SCHED_PRIORITY_COUNT) {
|
||||
/* This is a gross violation--tell drivers what the problem is.
|
||||
*/
|
||||
drm_err(sched, "%s: num_rqs cannot be greater than DRM_SCHED_PRIORITY_COUNT\n",
|
||||
@@ -1292,16 +1276,16 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (submit_wq) {
|
||||
sched->submit_wq = submit_wq;
|
||||
if (args->submit_wq) {
|
||||
sched->submit_wq = args->submit_wq;
|
||||
sched->own_submit_wq = false;
|
||||
} else {
|
||||
#ifdef CONFIG_LOCKDEP
|
||||
sched->submit_wq = alloc_ordered_workqueue_lockdep_map(name,
|
||||
sched->submit_wq = alloc_ordered_workqueue_lockdep_map(args->name,
|
||||
WQ_MEM_RECLAIM,
|
||||
&drm_sched_lockdep_map);
|
||||
#else
|
||||
sched->submit_wq = alloc_ordered_workqueue(name, WQ_MEM_RECLAIM);
|
||||
sched->submit_wq = alloc_ordered_workqueue(args->name, WQ_MEM_RECLAIM);
|
||||
#endif
|
||||
if (!sched->submit_wq)
|
||||
return -ENOMEM;
|
||||
@@ -1309,11 +1293,11 @@ int drm_sched_init(struct drm_gpu_scheduler *sched,
|
||||
sched->own_submit_wq = true;
|
||||
}
|
||||
|
||||
sched->sched_rq = kmalloc_array(num_rqs, sizeof(*sched->sched_rq),
|
||||
sched->sched_rq = kmalloc_array(args->num_rqs, sizeof(*sched->sched_rq),
|
||||
GFP_KERNEL | __GFP_ZERO);
|
||||
if (!sched->sched_rq)
|
||||
goto Out_check_own;
|
||||
sched->num_rqs = num_rqs;
|
||||
sched->num_rqs = args->num_rqs;
|
||||
for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) {
|
||||
sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL);
|
||||
if (!sched->sched_rq[i])
|
||||
|
||||
@@ -980,9 +980,8 @@ static int lvds_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void lvds_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_bridge_state->base.state;
|
||||
struct stm_lvds *lvds = bridge_to_stm_lvds(bridge);
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_connector *connector;
|
||||
@@ -1017,7 +1016,7 @@ static void lvds_atomic_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void lvds_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct stm_lvds *lvds = bridge_to_stm_lvds(bridge);
|
||||
|
||||
|
||||
@@ -1025,7 +1025,8 @@ static void tegra_cursor_atomic_disable(struct drm_plane *plane,
|
||||
tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS);
|
||||
}
|
||||
|
||||
static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state)
|
||||
static int tegra_cursor_atomic_async_check(struct drm_plane *plane, struct drm_atomic_state *state,
|
||||
bool flip)
|
||||
{
|
||||
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
@@ -283,7 +283,7 @@ static void drm_test_check_valid_clones(struct kunit *test)
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
|
||||
KUNIT_ASSERT_NOT_NULL(test, crtc_state);
|
||||
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, crtc_state);
|
||||
|
||||
crtc_state->encoder_mask = param->encoder_mask;
|
||||
|
||||
|
||||
@@ -295,11 +295,21 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
v3d->clk = devm_clk_get_optional(dev, NULL);
|
||||
if (IS_ERR(v3d->clk))
|
||||
return dev_err_probe(dev, PTR_ERR(v3d->clk), "Failed to get V3D clock\n");
|
||||
|
||||
ret = clk_prepare_enable(v3d->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Couldn't enable the V3D clock\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
|
||||
mask = DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
|
||||
ret = dma_set_mask_and_coherent(dev, mask);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto clk_disable;
|
||||
|
||||
v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
|
||||
|
||||
@@ -319,28 +329,29 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
|
||||
ret = PTR_ERR(v3d->reset);
|
||||
|
||||
if (ret == -EPROBE_DEFER)
|
||||
return ret;
|
||||
goto clk_disable;
|
||||
|
||||
v3d->reset = NULL;
|
||||
ret = map_regs(v3d, &v3d->bridge_regs, "bridge");
|
||||
if (ret) {
|
||||
dev_err(dev,
|
||||
"Failed to get reset control or bridge regs\n");
|
||||
return ret;
|
||||
goto clk_disable;
|
||||
}
|
||||
}
|
||||
|
||||
if (v3d->ver < 41) {
|
||||
ret = map_regs(v3d, &v3d->gca_regs, "gca");
|
||||
if (ret)
|
||||
return ret;
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
v3d->mmu_scratch = dma_alloc_wc(dev, 4096, &v3d->mmu_scratch_paddr,
|
||||
GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO);
|
||||
if (!v3d->mmu_scratch) {
|
||||
dev_err(dev, "Failed to allocate MMU scratch page\n");
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
ret = v3d_gem_init(drm);
|
||||
@@ -369,6 +380,8 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
|
||||
v3d_gem_destroy(drm);
|
||||
dma_free:
|
||||
dma_free_wc(dev, 4096, v3d->mmu_scratch, v3d->mmu_scratch_paddr);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(v3d->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -386,6 +399,8 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
|
||||
|
||||
dma_free_wc(v3d->drm.dev, 4096, v3d->mmu_scratch,
|
||||
v3d->mmu_scratch_paddr);
|
||||
|
||||
clk_disable_unprepare(v3d->clk);
|
||||
}
|
||||
|
||||
static struct platform_driver v3d_platform_driver = {
|
||||
|
||||
@@ -820,67 +820,54 @@ static const struct drm_sched_backend_ops v3d_cpu_sched_ops = {
|
||||
.free_job = v3d_cpu_job_free
|
||||
};
|
||||
|
||||
static int
|
||||
v3d_queue_sched_init(struct v3d_dev *v3d, const struct drm_sched_backend_ops *ops,
|
||||
enum v3d_queue queue, const char *name)
|
||||
{
|
||||
struct drm_sched_init_args args = {
|
||||
.num_rqs = DRM_SCHED_PRIORITY_COUNT,
|
||||
.credit_limit = 1,
|
||||
.timeout = msecs_to_jiffies(500),
|
||||
.dev = v3d->drm.dev,
|
||||
};
|
||||
|
||||
args.ops = ops;
|
||||
args.name = name;
|
||||
|
||||
return drm_sched_init(&v3d->queue[queue].sched, &args);
|
||||
}
|
||||
|
||||
int
|
||||
v3d_sched_init(struct v3d_dev *v3d)
|
||||
{
|
||||
int hw_jobs_limit = 1;
|
||||
int job_hang_limit = 0;
|
||||
int hang_limit_ms = 500;
|
||||
int ret;
|
||||
|
||||
ret = drm_sched_init(&v3d->queue[V3D_BIN].sched,
|
||||
&v3d_bin_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
hw_jobs_limit, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_bin", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_bin_sched_ops, V3D_BIN, "v3d_bin");
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drm_sched_init(&v3d->queue[V3D_RENDER].sched,
|
||||
&v3d_render_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
hw_jobs_limit, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_render", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_render_sched_ops, V3D_RENDER,
|
||||
"v3d_render");
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_sched_init(&v3d->queue[V3D_TFU].sched,
|
||||
&v3d_tfu_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
hw_jobs_limit, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_tfu", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_tfu_sched_ops, V3D_TFU, "v3d_tfu");
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (v3d_has_csd(v3d)) {
|
||||
ret = drm_sched_init(&v3d->queue[V3D_CSD].sched,
|
||||
&v3d_csd_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
hw_jobs_limit, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_csd", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_csd_sched_ops, V3D_CSD,
|
||||
"v3d_csd");
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_sched_init(&v3d->queue[V3D_CACHE_CLEAN].sched,
|
||||
&v3d_cache_clean_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
hw_jobs_limit, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_cache_clean", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_cache_clean_sched_ops,
|
||||
V3D_CACHE_CLEAN, "v3d_cache_clean");
|
||||
if (ret)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = drm_sched_init(&v3d->queue[V3D_CPU].sched,
|
||||
&v3d_cpu_sched_ops, NULL,
|
||||
DRM_SCHED_PRIORITY_COUNT,
|
||||
1, job_hang_limit,
|
||||
msecs_to_jiffies(hang_limit_ms), NULL,
|
||||
NULL, "v3d_cpu", v3d->drm.dev);
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_cpu_sched_ops, V3D_CPU, "v3d_cpu");
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
|
||||
@@ -800,7 +800,7 @@ dsi_esc_timing(u32 ns)
|
||||
}
|
||||
|
||||
static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
|
||||
u32 disp0_ctrl;
|
||||
@@ -811,7 +811,7 @@ static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
|
||||
struct device *dev = &dsi->pdev->dev;
|
||||
@@ -873,9 +873,8 @@ static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_atomic_state *state = old_state->base.state;
|
||||
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
|
||||
const struct drm_crtc_state *crtc_state;
|
||||
struct device *dev = &dsi->pdev->dev;
|
||||
@@ -1143,7 +1142,7 @@ static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_state)
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
|
||||
bool debug_dump_regs = false;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user