intel/display: enable panel self refresh support

Fixes #5339
This commit is contained in:
Alexander Boettcher 2024-09-02 14:03:36 +02:00 committed by Norman Feske
parent 3ba8ddc85c
commit 0414e4929f
4 changed files with 62 additions and 11 deletions

View File

@ -26,10 +26,6 @@ if {$use_fb_controller} {
set apply_on_hotplug "yes"
}
if {$use_usb} {
import_from_depot [depot_user]/src/pc_usb_host
}
import_from_depot [depot_user]/src/fs_rom \
[depot_user]/src/vfs \
[depot_user]/src/vfs_import \
@ -44,6 +40,7 @@ set build_components {
test/framebuffer
}
append_if $use_usb build_components { driver/usb_host }
append_if $use_gpu build_components { driver/gpu/intel }
append_if $use_top build_components { app/top }

View File

@ -105,9 +105,6 @@ int intel_root_gt_init_early(struct drm_i915_private * i915)
intel_uc_init_early(&gt->uc);
/* disable panel self refresh (required for FUJITSU S937/S938) */
i915->params.enable_psr = 0;
/*
* Tells driver that IOMMU, e.g. VT-d, is on, so that scratch page
* workaround is applied by Intel display driver:

View File

@ -28,6 +28,7 @@
enum { MAX_BRIGHTNESS = 100, INVALID_BRIGHTNESS = MAX_BRIGHTNESS + 1 };
struct task_struct * lx_update_task = NULL;
struct task_struct * lx_user_task = NULL;
static struct drm_client_dev * dev_client = NULL;
@ -473,11 +474,53 @@ static int configure_connectors(void * data)
}
void framebuffer_dirty(void)
{
struct drm_framebuffer *fb = NULL;
struct drm_clip_rect *clips = NULL;
struct drm_mode_fb_dirty_cmd r = { };
unsigned flags = 0;
int num_clips = 0;
int ret = 0;
if (!dev_client || !dumb_fb.fb_id)
return;
fb = drm_framebuffer_lookup(dev_client->dev, dev_client->file,
dumb_fb.fb_id);
if (!fb || !fb->funcs || !fb->funcs->dirty)
return;
ret = fb->funcs->dirty(fb, dev_client->file, flags, r.color, clips,
num_clips);
if (ret)
printk("%s failed %d\n", __func__, ret);
}
static int update_content(void *)
{
while (true) {
framebuffer_dirty();
lx_emul_task_schedule(true /* block task */);
}
return 0;
}
void lx_user_init(void)
{
int pid = kernel_thread(configure_connectors, NULL, "lx_user",
CLONE_FS | CLONE_FILES);
lx_user_task = find_task_by_pid_ns(pid, NULL);;
int pid = kernel_thread(configure_connectors, NULL, "lx_user",
CLONE_FS | CLONE_FILES);
int pid2 = kernel_thread(update_content, NULL, "lx_update",
CLONE_FS | CLONE_FILES);
lx_user_task = find_task_by_pid_ns(pid, NULL);;
lx_update_task = find_task_by_pid_ns(pid2, NULL);;
}
@ -598,11 +641,18 @@ static int fb_client_hotplug(struct drm_client_dev *client)
* commit the change.
*/
if (fb) {
bool mode_too_large = false;
mutex_lock(&client->modeset_mutex);
drm_client_for_each_modeset(modeset, client) {
if (!modeset || !modeset->num_connectors)
continue;
if (!mode_too_large && modeset->mode &&
(modeset->mode->hdisplay > fb->width ||
modeset->mode->vdisplay > fb->height))
mode_too_large = true;
modeset->fb = fb;
}
mutex_unlock(&client->modeset_mutex);
@ -610,7 +660,7 @@ static int fb_client_hotplug(struct drm_client_dev *client)
/* triggers disablement of encoders attached to disconnected ports */
result = drm_client_modeset_commit(client);
if (result) {
if (result && !(mode_too_large && result == -ENOSPC)) {
printk("%s: error on modeset commit %d%s\n", __func__, result,
(result == -ENOSPC) ? " - ENOSPC" : " - unknown error");
}

View File

@ -33,6 +33,7 @@ extern "C" {
extern struct task_struct * lx_user_task;
extern struct task_struct * lx_update_task;
namespace Framebuffer {
@ -88,6 +89,12 @@ struct Framebuffer::Driver
using Pixel = Capture::Pixel;
Surface<Pixel> surface((Pixel*)_base, _size_phys);
_captured_screen.apply_to_surface(surface);
if (!lx_update_task)
return;
lx_emul_task_unblock(lx_update_task);
Lx_kit::env().scheduler.execute();
}
Fb(Env & env, void * base, Capture::Area size,