diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/README b/repos/dde_linux/src/drivers/framebuffer/intel/README
index 87b0791381..4f15246e4f 100644
--- a/repos/dde_linux/src/drivers/framebuffer/intel/README
+++ b/repos/dde_linux/src/drivers/framebuffer/intel/README
@@ -35,6 +35,15 @@ configuration like this:
!
+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:
+
+!
+
+If you define a period of zero, the driver won't poll at all, which is the
+default value.
+
To present all available connectors and their possible resolutions to the user
the driver is able to export a corresponding report ROM. This has to be
configured too, like in the following:
diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h b/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h
index ebbbb85a4d..d3e935a522 100644
--- a/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h
+++ b/repos/dde_linux/src/drivers/framebuffer/intel/include/component.h
@@ -15,6 +15,7 @@
#define __COMPONENT_H__
/* Genode includes */
+#include
#include
#include
#include
@@ -41,21 +42,28 @@ class Framebuffer::Driver
{
private:
- Session_component &_session;
- int _height = 0;
- int _width = 0;
- static constexpr unsigned _bytes_per_pixel = 2;
- void *_new_fb_ds_base = nullptr;
- void *_cur_fb_ds_base = nullptr;
- Genode::uint64_t _cur_fb_ds_size = 0;
- drm_framebuffer *_new_fb = nullptr;
- drm_framebuffer *_cur_fb = nullptr;
+ Session_component &_session;
+ Timer::Connection _timer;
+ Genode::Signal_handler _poll_handler;
+ int _height = 0;
+ int _width = 0;
+ static constexpr unsigned _bytes_per_pixel = 2;
+ void *_new_fb_ds_base = nullptr;
+ void *_cur_fb_ds_base = nullptr;
+ Genode::uint64_t _cur_fb_ds_size = 0;
+ drm_framebuffer *_new_fb = nullptr;
+ drm_framebuffer *_cur_fb = nullptr;
+ unsigned long _poll_ms = false;
drm_display_mode * _preferred_mode(drm_connector *connector);
+ void _poll();
+
public:
- Driver(Session_component &session) : _session(session) {}
+ Driver(Genode::Env & env, Session_component &session)
+ : _session(session), _timer(env),
+ _poll_handler(env.ep(), *this, &Driver::_poll) {}
int width() const { return _width; }
int height() const { return _height; }
@@ -65,6 +73,7 @@ class Framebuffer::Driver
return _width * _height * _bytes_per_pixel; }
void finish_initialization();
+ void set_polling(unsigned long poll);
bool mode_changed();
void generate_report();
void free_framebuffer();
@@ -90,6 +99,9 @@ class Framebuffer::Session_component : public Genode::Rpc_object
bool _buffered_from_config() {
return _config.xml().attribute_value("buffered", false); }
+ unsigned long _polling_from_config() {
+ return _config.xml().attribute_value("poll", 0); }
+
void _refresh_buffered(int x, int y, int w, int h)
{
using namespace Genode;
@@ -114,8 +126,9 @@ class Framebuffer::Session_component : public Genode::Rpc_object
public:
- Session_component(Genode::Attached_rom_dataspace &config)
- : _driver(*this), _config(config),
+ Session_component(Genode::Env &env,
+ Genode::Attached_rom_dataspace &config)
+ : _driver(env, *this), _config(config), _timer(env),
_buffered(_buffered_from_config()) {}
Driver & driver() { return _driver; }
@@ -127,6 +140,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object
_in_update = true;
_buffered = _buffered_from_config();
+ _driver.set_polling(_polling_from_config());
if (_driver.mode_changed() && _mode_sigh.valid())
Genode::Signal_transmitter(_mode_sigh).submit();
else
@@ -191,11 +205,11 @@ struct Framebuffer::Root
Session_component *_create_session(const char *args) override {
return &session; }
- Root(Genode::Entrypoint &ep, Genode::Allocator &alloc,
+ Root(Genode::Env &env, Genode::Allocator &alloc,
Genode::Attached_rom_dataspace &config)
: Genode::Root_component(ep, alloc),
- session(config) { }
+ Genode::Single_client>(env.ep(), alloc),
+ session(env, config) { }
};
#endif /* __COMPONENT_H__ */
diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc
index 010bf29d5b..dc3410b040 100644
--- a/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc
+++ b/repos/dde_linux/src/drivers/framebuffer/intel/lx_emul.cc
@@ -137,9 +137,34 @@ void Framebuffer::Driver::finish_initialization()
{
dde_c_set_driver(dde_drm_device, (void*)this);
generate_report();
- mode_changed();
+ _session.config_changed();
}
+
+#include
+
+void Framebuffer::Driver::_poll()
+{
+ Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) dde_drm_device->pdev->bus;
+ Lx::Irq::irq().inject_irq(pci_dev->client());
+}
+
+
+void Framebuffer::Driver::set_polling(unsigned long poll)
+{
+ if (poll == _poll_ms) return;
+
+ _poll_ms = poll;
+
+ if (_poll_ms) {
+ _timer.sigh(_poll_handler);
+ _timer.trigger_periodic(_poll_ms * 1000);
+ } else {
+ _timer.sigh(Genode::Signal_context_capability());
+ }
+}
+
+
bool Framebuffer::Driver::mode_changed()
{
using namespace Genode;
@@ -920,8 +945,6 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
}
-#include
-
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
{
diff --git a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc
index cb384d7d57..1ac034b086 100644
--- a/repos/dde_linux/src/drivers/framebuffer/intel/main.cc
+++ b/repos/dde_linux/src/drivers/framebuffer/intel/main.cc
@@ -41,11 +41,11 @@ unsigned long jiffies;
struct Main
{
- Genode::Entrypoint &ep;
- Genode::Attached_rom_dataspace config;
- Genode::Heap heap;
-
- Framebuffer::Root root { ep, heap, config };
+ Genode::Env &env;
+ Genode::Entrypoint &ep { env.ep() };
+ Genode::Attached_rom_dataspace config { env, "config" };
+ Genode::Heap heap { env.ram(), env.rm() };
+ Framebuffer::Root root { env, heap, config };
/* init singleton Lx::Timer */
Lx::Timer &timer = Lx::timer(&ep, &jiffies);
@@ -60,8 +60,7 @@ struct Main
Lx::Task linux { run_linux, reinterpret_cast(this), "linux",
Lx::Task::PRIORITY_0, Lx::scheduler() };
- Main(Genode::Env &env)
- : ep(env.ep()), config(env, "config"), heap(env.ram(), env.rm())
+ Main(Genode::Env &env) : env(env)
{
Genode::log("--- intel framebuffer driver ---");
diff --git a/repos/dde_linux/src/include/lx_kit/irq.h b/repos/dde_linux/src/include/lx_kit/irq.h
index 98b232f53a..02ccadba26 100644
--- a/repos/dde_linux/src/include/lx_kit/irq.h
+++ b/repos/dde_linux/src/include/lx_kit/irq.h
@@ -35,6 +35,8 @@ class Lx::Irq
*/
virtual void request_irq(Platform::Device &dev, irq_handler_t handler,
void *dev_id, irq_handler_t thread_fn = 0) = 0;
+
+ virtual void inject_irq(Platform::Device &dev) = 0;
};
#endif /* _LX_KIT__IRQ_H_ */
diff --git a/repos/dde_linux/src/lx_kit/irq.cc b/repos/dde_linux/src/lx_kit/irq.cc
index 20cc20dd9f..9aa5cc1ddd 100644
--- a/repos/dde_linux/src/lx_kit/irq.cc
+++ b/repos/dde_linux/src/lx_kit/irq.cc
@@ -96,18 +96,7 @@ class Lx_kit::Irq : public Lx::Irq
Lx_kit::List _handler;
Lx::Task _task;
- Genode::Signal_rpc_member _dispatcher;
-
- /**
- * Signal handler
- */
- void _handle(unsigned)
- {
- _task.unblock();
-
- /* kick off scheduling */
- Lx::scheduler().schedule();
- }
+ Genode::Signal_handler _dispatcher;
static void _run_irq(void *args)
{
@@ -131,7 +120,7 @@ class Lx_kit::Irq : public Lx::Irq
_dev(dev),
_irq_sess(dev.irq(0)),
_task(_run_irq, this, _name.name, Lx::Task::PRIORITY_3, Lx::scheduler()),
- _dispatcher(ep, *this, &Context::_handle)
+ _dispatcher(ep, *this, &Context::unblock)
{
_irq_sess.sigh(_dispatcher);
@@ -139,6 +128,17 @@ class Lx_kit::Irq : public Lx::Irq
_irq_sess.ack_irq();
}
+ /**
+ * Unblock this context, e.g., as result of an IRQ signal
+ */
+ void unblock()
+ {
+ _task.unblock();
+
+ /* kick off scheduling */
+ Lx::scheduler().schedule();
+ }
+
/**
* Handle IRQ
*/
@@ -214,6 +214,12 @@ class Lx_kit::Irq : public Lx::Irq
Handler(dev_id, handler, thread_fn);
ctx->add_handler(h);
}
+
+ void inject_irq(Platform::Device &dev)
+ {
+ Context *ctx = _find_context(dev);
+ if (ctx) ctx->unblock();
+ }
};