mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-18 23:28:29 +00:00
committed by
Christian Helmuth
parent
80104f5192
commit
eb62d9cc04
@ -18,7 +18,7 @@ Each of the connector can be configured explicitly in terms of resolution and
|
||||
whether it should be enabled or not. This looks like the following:
|
||||
|
||||
! <config>
|
||||
! <connector name="LVDS-11" width="1280" height="800" enabled="true"/>
|
||||
! <connector name="LVDS-11" width="1280" height="800" hz="60" brightness="75" enabled="true"/>
|
||||
! </config>
|
||||
|
||||
When the configuration changes during run-time, the driver will adapt to it. In
|
||||
@ -26,6 +26,9 @@ this case it will also change the current virtual resolution to the maximum of
|
||||
the configured resolutions in width and height, and it will inform its client
|
||||
about the change in resolution.
|
||||
|
||||
The brightness value is in percentage and takes effect only if supported by
|
||||
the hardware.
|
||||
|
||||
If you experience problems like hotplugging of connectors does not work, you
|
||||
can force the driver to poll frequently for hotplug events by defining a period
|
||||
in milliseconds like this:
|
||||
@ -46,10 +49,13 @@ configured too, like in the following:
|
||||
The exported report has the following format:
|
||||
|
||||
! <connectors>
|
||||
! <connector name="LVDS-11" connected="1">
|
||||
! <connector name="LVDS-11" connected="1" brightness="50">
|
||||
! <mode width="1280" height="800" hz="60"/>
|
||||
! ...
|
||||
! </connector>
|
||||
! ...
|
||||
! <connector name="HDMI-A-1" connected="false"/>
|
||||
! <connector name="DP-1" connected="false"/>
|
||||
! </connectors>
|
||||
|
||||
The brightness attribute is soley reported if the hardware supports it.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,37 +12,40 @@
|
||||
*/
|
||||
|
||||
#include <../drivers/gpu/drm/i915/i915_drv.h>
|
||||
|
||||
struct i915_params i915 = {
|
||||
struct i915_params i915_modparams = {
|
||||
.vbt_firmware = NULL,
|
||||
.modeset = -1,
|
||||
.panel_ignore_lid = 1,
|
||||
.semaphores = -1,
|
||||
.lvds_channel_mode = 0,
|
||||
.panel_use_ssc = -1,
|
||||
.vbt_sdvo_panel_type = -1,
|
||||
.enable_rc6 = -1,
|
||||
.enable_dc = -1,
|
||||
.enable_fbc = -1,
|
||||
.enable_execlists = -1,
|
||||
.enable_hangcheck = false,
|
||||
.enable_ppgtt = -1,
|
||||
.enable_ppgtt = 0,
|
||||
.enable_psr = 0,
|
||||
.preliminary_hw_support = true,
|
||||
.disable_power_well = -1,
|
||||
.enable_ips = 1,
|
||||
.fastboot = 0,
|
||||
.prefault_disable = 0,
|
||||
.load_detect_test = 0,
|
||||
.reset = true,
|
||||
.enable_ips = true,
|
||||
.invert_brightness = 0,
|
||||
.disable_display = 0,
|
||||
.enable_cmd_parser = 1,
|
||||
.disable_vtd_wa = 0,
|
||||
.use_mmio_flip = 0,
|
||||
.mmio_debug = 0,
|
||||
.verbose_state_checks = 1,
|
||||
.nuclear_pageflip = 0,
|
||||
.edp_vswing = 0,
|
||||
.enable_guc_submission = false,
|
||||
.guc_log_level = -1,
|
||||
.guc_firmware_path = NULL,
|
||||
.huc_firmware_path = NULL,
|
||||
.mmio_debug = 0,
|
||||
.edp_vswing = 0,
|
||||
.enable_guc = 0,
|
||||
.reset = 0,
|
||||
.inject_load_failure = 0,
|
||||
.alpha_support = IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT),
|
||||
.enable_cmd_parser = true,
|
||||
.enable_hangcheck = false,
|
||||
.fastboot = false,
|
||||
.prefault_disable = false,
|
||||
.load_detect_test = false,
|
||||
.force_reset_modeset_test = false,
|
||||
.error_capture = true,
|
||||
.disable_display = false,
|
||||
.verbose_state_checks = true,
|
||||
.nuclear_pageflip = false,
|
||||
.enable_dp_mst = false,
|
||||
.enable_dpcd_backlight = false,
|
||||
.enable_gvt = false
|
||||
};
|
||||
|
||||
|
@ -53,7 +53,10 @@ class Framebuffer::Driver
|
||||
Genode::Signal_handler<Driver> _poll_handler;
|
||||
unsigned long _poll_ms = 0;
|
||||
|
||||
drm_display_mode * _preferred_mode(drm_connector *connector);
|
||||
Genode::Signal_context_capability _config_sigh;
|
||||
|
||||
drm_display_mode * _preferred_mode(drm_connector *connector,
|
||||
unsigned &brightness);
|
||||
|
||||
void _poll();
|
||||
|
||||
@ -74,6 +77,29 @@ class Framebuffer::Driver
|
||||
void set_polling(unsigned long poll);
|
||||
void update_mode();
|
||||
void generate_report();
|
||||
|
||||
/**
|
||||
* Register signal handler used for config updates
|
||||
*
|
||||
* The signal handler is artificially triggered as a side effect
|
||||
* of connector changes.
|
||||
*/
|
||||
void config_sigh(Genode::Signal_context_capability sigh)
|
||||
{
|
||||
_config_sigh = sigh;
|
||||
}
|
||||
|
||||
void trigger_reconfiguration()
|
||||
{
|
||||
/*
|
||||
* Trigger the reprocessing of the configuration following the
|
||||
* same ontrol flow as used for external config changes.
|
||||
*/
|
||||
if (_config_sigh.valid())
|
||||
Genode::Signal_transmitter(_config_sigh).submit();
|
||||
else
|
||||
Genode::warning("config signal handler unexpectedly undefined");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -54,6 +54,8 @@ void lx_c_set_mode(struct drm_device *, struct drm_connector *,
|
||||
struct drm_framebuffer *, struct drm_display_mode *);
|
||||
void lx_c_set_driver(struct drm_device *, void *);
|
||||
void * lx_c_get_driver(struct drm_device *);
|
||||
void lx_c_set_brightness(struct drm_connector *, unsigned, unsigned);
|
||||
unsigned lx_c_get_brightness(struct drm_connector * const, unsigned);
|
||||
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,23 +17,14 @@
|
||||
#include <../drivers/gpu/drm/i915/intel_drv.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
|
||||
|
||||
extern struct drm_framebuffer *
|
||||
lx_c_intel_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_i915_gem_object *obj);
|
||||
|
||||
|
||||
int intel_sanitize_enable_execlists(struct drm_device *dev,
|
||||
int enable_execlists)
|
||||
{
|
||||
if (INTEL_INFO(dev)->gen >= 9)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void lx_c_allocate_framebuffer(struct drm_device * dev,
|
||||
struct lx_c_fb_config *c)
|
||||
struct lx_c_fb_config *c)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_mode_fb_cmd2 * r;
|
||||
@ -44,10 +35,12 @@ void lx_c_allocate_framebuffer(struct drm_device * dev,
|
||||
/* for linear buffers the pitch needs to be 64 byte aligned */
|
||||
c->pitch = roundup(c->width * c->bpp, 64);
|
||||
c->size = roundup(c->pitch * c->height, PAGE_SIZE);
|
||||
if (c->size * 2 < dev_priv->gtt.stolen_usable_size)
|
||||
obj = i915_gem_object_create_stolen(dev, c->size);
|
||||
|
||||
obj = i915_gem_object_create_stolen(dev_priv, c->size);
|
||||
|
||||
if (obj == NULL)
|
||||
obj = i915_gem_alloc_object(dev, c->size);
|
||||
obj = i915_gem_object_create(dev_priv, c->size);
|
||||
|
||||
if (obj == NULL) goto out2;
|
||||
|
||||
r = (struct drm_mode_fb_cmd2*) kzalloc(sizeof(struct drm_mode_fb_cmd2), 0);
|
||||
@ -56,37 +49,41 @@ void lx_c_allocate_framebuffer(struct drm_device * dev,
|
||||
r->height = c->height;
|
||||
r->pixel_format = DRM_FORMAT_RGB565;
|
||||
r->pitches[0] = c->pitch;
|
||||
c->lx_fb = lx_c_intel_framebuffer_create(dev, r, obj);
|
||||
c->lx_fb = intel_framebuffer_create(obj, r);
|
||||
if (IS_ERR(c->lx_fb)) goto err2;
|
||||
|
||||
if (intel_pin_and_fence_fb_obj(NULL, c->lx_fb, NULL, NULL, NULL))
|
||||
/* XXX rotation info missing */
|
||||
struct i915_vma * vma = intel_pin_and_fence_fb_obj(c->lx_fb, DRM_MODE_ROTATE_0);
|
||||
if (IS_ERR(vma))
|
||||
goto err1;
|
||||
|
||||
c->addr = ioremap_wc(dev_priv->gtt.mappable_base
|
||||
+ i915_gem_obj_ggtt_offset(obj), c->size);
|
||||
c->addr = ioremap_wc(dev_priv->ggtt.gmadr.start + i915_ggtt_offset(vma),
|
||||
c->size);
|
||||
|
||||
memset_io(c->addr, 0, c->size);
|
||||
|
||||
/* intel_framebuffer_create inc ref, so dec since obj ptr is dropped now */
|
||||
i915_gem_object_put(obj);
|
||||
|
||||
goto out1;
|
||||
|
||||
err1:
|
||||
DRM_ERROR("could not allocate framebuffer %ld", (long)vma);
|
||||
drm_framebuffer_remove(c->lx_fb);
|
||||
err2:
|
||||
c->lx_fb = NULL;
|
||||
drm_gem_object_unreference(&obj->base);
|
||||
i915_gem_object_put(obj);
|
||||
out1:
|
||||
kfree(r);
|
||||
out2:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
|
||||
void lx_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
|
||||
struct drm_framebuffer *fb, struct drm_display_mode *mode)
|
||||
struct drm_framebuffer *fb, struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_crtc *crtc = NULL;
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
|
||||
if (!mode) return;
|
||||
struct drm_crtc * crtc = NULL;
|
||||
struct drm_encoder * encoder = connector->encoder;
|
||||
|
||||
if (!encoder) {
|
||||
struct drm_encoder *enc;
|
||||
@ -109,28 +106,36 @@ void lx_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
|
||||
}
|
||||
|
||||
if (!encoder) {
|
||||
DRM_DEBUG("Found no encoder for the connector %s\n", connector->name);
|
||||
lx_printf("Found no encoder for the connector %s\n", connector->name);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned used_crtc = 0;
|
||||
|
||||
crtc = encoder->crtc;
|
||||
if (!crtc) {
|
||||
unsigned i = 0;
|
||||
struct drm_crtc *c;
|
||||
list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
|
||||
if (!(encoder->possible_crtcs & (1 << i))) continue;
|
||||
if (c->state->enable) continue;
|
||||
if (c->state->enable) {
|
||||
used_crtc ++;
|
||||
continue;
|
||||
}
|
||||
crtc = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!crtc) {
|
||||
DRM_DEBUG("Found no crtc for the connector %s\n", connector->name);
|
||||
if (mode)
|
||||
lx_printf("Found no crtc for the connector %s used/max %u+1/%u\n",
|
||||
connector->name, used_crtc, dev->mode_config.num_crtc);
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_DEBUG("set mode %s for connector %s\n", mode->name, connector->name);
|
||||
DRM_DEBUG("%s%s for connector %s\n", mode ? "set mode " : "no mode",
|
||||
mode ? mode->name : "", connector->name);
|
||||
|
||||
struct drm_mode_set set;
|
||||
set.crtc = crtc;
|
||||
@ -138,11 +143,15 @@ void lx_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
|
||||
set.y = 0;
|
||||
set.mode = mode;
|
||||
set.connectors = &connector;
|
||||
set.num_connectors = 1;
|
||||
set.fb = fb;
|
||||
drm_atomic_helper_set_config(&set);
|
||||
}
|
||||
set.num_connectors = mode ? 1 : 0;
|
||||
set.fb = mode ? fb : 0;
|
||||
|
||||
uint32_t const ref_cnt_before = drm_framebuffer_read_refcount(fb);
|
||||
int ret = drm_atomic_helper_set_config(&set, dev->mode_config.acquire_ctx);
|
||||
if (ret)
|
||||
lx_printf("Error: set config failed ret=%d refcnt before=%u after=%u\n",
|
||||
ret, ref_cnt_before, drm_framebuffer_read_refcount(fb));
|
||||
}
|
||||
|
||||
void lx_c_set_driver(struct drm_device * dev, void * driver)
|
||||
{
|
||||
@ -157,3 +166,33 @@ void* lx_c_get_driver(struct drm_device * dev)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
return (void*) dev_priv->audio_component;
|
||||
}
|
||||
|
||||
void lx_c_set_brightness(struct drm_connector * const connector,
|
||||
unsigned const bn_set, unsigned const bn_max)
|
||||
{
|
||||
struct intel_connector * const c = to_intel_connector(connector);
|
||||
|
||||
intel_panel_set_backlight_acpi(c->base.state, bn_set, bn_max);
|
||||
}
|
||||
|
||||
unsigned lx_c_get_brightness(struct drm_connector * const connector, unsigned error)
|
||||
{
|
||||
if (!connector)
|
||||
return error;
|
||||
|
||||
struct intel_connector * const intel_c = to_intel_connector(connector);
|
||||
if (!intel_c)
|
||||
return error;
|
||||
|
||||
struct intel_panel *panel = &intel_c->panel;
|
||||
|
||||
if (!panel || !panel->backlight.device || !panel->backlight.device->ops ||
|
||||
!panel->backlight.device->ops->get_brightness)
|
||||
return error;
|
||||
|
||||
panel->backlight.device->connector = intel_c;
|
||||
unsigned ret = panel->backlight.device->ops->get_brightness(panel->backlight.device);
|
||||
panel->backlight.device->connector = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -33,8 +33,10 @@
|
||||
#include <lx_kit/work.h>
|
||||
|
||||
/* Linux module functions */
|
||||
extern "C" int postcore_i2c_init(); /* i2c-core.c */
|
||||
extern "C" void postcore_i2c_init(void); /* i2c-core-base.c */
|
||||
extern "C" int module_i915_init(); /* i915_drv.c */
|
||||
extern "C" void radix_tree_init(); /* called by start_kernel(void) normally */
|
||||
extern "C" void drm_connector_ida_init(); /* called by drm_core_init(void) normally */
|
||||
|
||||
static void run_linux(void * m);
|
||||
|
||||
@ -89,16 +91,25 @@ struct Main
|
||||
struct Policy_agent
|
||||
{
|
||||
Main &main;
|
||||
Genode::Signal_handler<Policy_agent> sd;
|
||||
Genode::Signal_handler<Policy_agent> handler;
|
||||
bool _pending = false;
|
||||
|
||||
void handle()
|
||||
{
|
||||
_pending = true;
|
||||
main.linux_task().unblock();
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
bool pending()
|
||||
{
|
||||
bool ret = _pending;
|
||||
_pending = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Policy_agent(Main &m)
|
||||
: main(m), sd(main.ep, *this, &Policy_agent::handle) {}
|
||||
: main(m), handler(main.ep, *this, &Policy_agent::handle) {}
|
||||
};
|
||||
|
||||
|
||||
@ -106,17 +117,23 @@ static void run_linux(void * m)
|
||||
{
|
||||
Main * main = reinterpret_cast<Main*>(m);
|
||||
|
||||
system_wq = alloc_workqueue("system_wq", 0, 0);
|
||||
|
||||
radix_tree_init();
|
||||
drm_connector_ida_init();
|
||||
postcore_i2c_init();
|
||||
module_i915_init();
|
||||
main->root.session.driver().finish_initialization();
|
||||
main->announce();
|
||||
|
||||
static Policy_agent pa(*main);
|
||||
main->config.sigh(pa.sd);
|
||||
Policy_agent pa(*main);
|
||||
main->root.session.driver().config_sigh(pa.handler);
|
||||
main->config.sigh(pa.handler);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
main->root.session.config_changed();
|
||||
while (pa.pending())
|
||||
main->root.session.config_changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,3 +22,4 @@ vpath %.cc $(PRG_DIR)
|
||||
vpath %.cc $(REP_DIR)/src/lx_kit
|
||||
|
||||
CC_CXX_WARN_STRICT =
|
||||
CC_OPT += -Wno-narrowing
|
||||
|
@ -26,12 +26,15 @@ extern unsigned long jiffies;
|
||||
enum {
|
||||
JIFFIES_TICK_MS = 1000/HZ,
|
||||
JIFFIES_TICK_US = 1000*1000/HZ,
|
||||
JIFFIES_TICK_NS = 1000ULL*1000*1000/HZ,
|
||||
};
|
||||
|
||||
static inline unsigned long msecs_to_jiffies(const unsigned int m) { return m / JIFFIES_TICK_MS; }
|
||||
static inline unsigned int jiffies_to_msecs(const unsigned long j) { return j * JIFFIES_TICK_MS; }
|
||||
static inline unsigned long usecs_to_jiffies(const unsigned int u) { return u / JIFFIES_TICK_US; }
|
||||
|
||||
static inline unsigned int jiffies_to_msecs(const unsigned long j) { return j * JIFFIES_TICK_MS; }
|
||||
static inline u64 jiffies_to_nsecs(const unsigned long j) { return (u64)j * JIFFIES_TICK_NS; }
|
||||
|
||||
clock_t jiffies_to_clock_t(unsigned long x);
|
||||
static inline clock_t jiffies_delta_to_clock_t(long delta)
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <util/xml_generator.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -31,19 +32,32 @@ struct Framebuffer_controller
|
||||
Heap heap;
|
||||
Allocator_avl fs_alloc;
|
||||
File_system::Connection fs;
|
||||
Timer::Connection timer;
|
||||
Signal_handler<Framebuffer_controller> timer_handler;
|
||||
|
||||
void update_connector_config(Xml_generator & xml, Xml_node & node);
|
||||
void update_fb_config(Xml_node & report);
|
||||
void report_changed();
|
||||
void handle_timer();
|
||||
|
||||
Framebuffer_controller(Env &env)
|
||||
: rom(env, "connectors"),
|
||||
rom_sigh(env.ep(), *this, &Framebuffer_controller::report_changed),
|
||||
heap(env.ram(), env.rm()),
|
||||
fs_alloc(&heap),
|
||||
fs(env, fs_alloc, "", "/", true, 128*1024)
|
||||
fs(env, fs_alloc, "", "/", true, 128*1024),
|
||||
timer(env),
|
||||
timer_handler(env.ep(), *this, &Framebuffer_controller::handle_timer)
|
||||
{
|
||||
Attached_rom_dataspace config(env, "config");
|
||||
unsigned long const period_ms = config.xml().attribute_value("artifical_update_ms", 0UL);
|
||||
|
||||
rom.sigh(rom_sigh);
|
||||
|
||||
if (period_ms) {
|
||||
timer.sigh(timer_handler);
|
||||
timer.trigger_periodic(period_ms * 1000 /* in us */);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -59,20 +73,25 @@ void Framebuffer_controller::update_connector_config(Xml_generator & xml,
|
||||
bool connected = node.attribute_value("connected", false);
|
||||
xml.attribute("enabled", connected ? "true" : "false");
|
||||
|
||||
unsigned long width = 0, height = 0;
|
||||
unsigned long width = 0, height = 0, hz = 0;
|
||||
node.for_each_sub_node("mode", [&] (Xml_node &mode) {
|
||||
unsigned long w, h;
|
||||
unsigned long w, h, z;
|
||||
w = mode.attribute_value<unsigned long>("width", 0);
|
||||
h = mode.attribute_value<unsigned long>("height", 0);
|
||||
if (w > width) {
|
||||
z = mode.attribute_value<unsigned long>("hz", 0);
|
||||
if (w >= width) {
|
||||
width = w;
|
||||
height = h;
|
||||
if (z > hz)
|
||||
hz = z;
|
||||
}
|
||||
});
|
||||
|
||||
if (width && height) {
|
||||
xml.attribute("width", width);
|
||||
xml.attribute("height", height);
|
||||
xml.attribute("hz", hz);
|
||||
xml.attribute("brightness", 73);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -84,6 +103,7 @@ void Framebuffer_controller::update_fb_config(Xml_node & report)
|
||||
static char buf[4096];
|
||||
|
||||
Xml_generator xml(buf, sizeof(buf), "config", [&] {
|
||||
// xml.attribute("poll", "5000");
|
||||
xml.node("report", [&] {
|
||||
xml.attribute("connectors", "yes");
|
||||
});
|
||||
@ -115,6 +135,17 @@ void Framebuffer_controller::report_changed()
|
||||
}
|
||||
|
||||
|
||||
void Framebuffer_controller::handle_timer()
|
||||
{
|
||||
if (!rom.is_valid())
|
||||
return;
|
||||
|
||||
/* artificial update */
|
||||
Xml_node report(rom.local_addr<char>(), rom.size());
|
||||
update_fb_config(report);
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
log("--- Framebuffer controller ---\n");
|
||||
|
Reference in New Issue
Block a user