intel_fb_drv: consider aligned pitch value

* Align pitch value to 64 byte (thanks to cnuke for investigation)
* Get rid of extra dataspace retrival and attachment, now that we always buffer
* Consistently name all lx_emul helpers: lx_* (get rid of dde*)
* Add missing file headers

Fix #1997
This commit is contained in:
Stefan Kalkowski 2016-06-17 14:48:41 +02:00 committed by Christian Helmuth
parent 558cc8e00c
commit 101d052ddb
9 changed files with 165 additions and 133 deletions

View File

@ -8,9 +8,9 @@ index 32cf973..ec1d558 100644
}
+
+struct drm_framebuffer *
+dde_c_intel_framebuffer_create(struct drm_device *dev,
+lx_c_intel_framebuffer_create(struct drm_device *dev,
+ struct drm_mode_fb_cmd2 *mode_cmd,
+ struct drm_i915_gem_object *obj) {
+ return intel_framebuffer_create(dev, mode_cmd, obj);
+}
+EXPORT_SYMBOL(dde_c_intel_framebuffer_create);
+EXPORT_SYMBOL(lx_c_intel_framebuffer_create);

View File

@ -1 +1 @@
a226766f99897d980fa70f8bf24e09ad0c1d39ee
ccb3b82a7cc54d0beab20dcb4dcdc5edd0cb0385

View File

@ -1,5 +1,5 @@
#include "lx_emul_private.h"
#include <lx_emul.h>
#include <lx_emul_c.h>
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_dp_mst_helper.h>

View File

@ -1,3 +1,16 @@
/*
* \brief Linux emulation Intel i915 parameter struct definition
* \author Stefan Kalkowski
* \date 2016-03-22
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <../drivers/gpu/drm/i915/i915_drv.h>
struct i915_params i915 = {

View File

@ -27,9 +27,7 @@
#include <os/attached_rom_dataspace.h>
#include <blit/blit.h>
struct drm_display_mode;
struct drm_connector;
struct drm_framebuffer;
#include <lx_emul_c.h>
namespace Framebuffer {
class Driver;
@ -42,14 +40,10 @@ class Framebuffer::Driver
{
private:
struct Configuration {
int height = 16;
int width = 64;
unsigned bpp = 2;
Genode::Dataspace_capability cap;
void * addr = nullptr;
Genode::size_t size = 0;
drm_framebuffer * lx_obj = nullptr;
struct Configuration
{
struct lx_c_fb_config _lx = { 16, 64, 64, 2,
nullptr, 0, nullptr };
} _config;
Session_component &_session;
@ -67,11 +61,11 @@ class Framebuffer::Driver
: _session(session), _timer(env),
_poll_handler(env.ep(), *this, &Driver::_poll) {}
int width() const { return _config.width; }
int height() const { return _config.height; }
int bpp() const { return _config.bpp; }
Genode::Dataspace_capability dataspace() const {
return _config.cap; }
int width() const { return _config._lx.width; }
int height() const { return _config._lx.height; }
int bpp() const { return _config._lx.bpp; }
void * fb_addr() const { return _config._lx.addr; }
unsigned pitch() const { return _config._lx.pitch; }
void finish_initialization();
void set_polling(unsigned long poll);
@ -90,9 +84,8 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Genode::Attached_rom_dataspace &_config;
Genode::Signal_context_capability _mode_sigh;
Timer::Connection _timer;
Lazy<Genode::Attached_dataspace> _fb_ds;
Genode::Ram_session &_ram;
Genode::Attached_ram_dataspace _bb_ds;
Genode::Attached_ram_dataspace _ds;
bool _in_mode_change = true;
unsigned long _polling_from_config() {
@ -103,7 +96,7 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Session_component(Genode::Env &env,
Genode::Attached_rom_dataspace &config)
: _driver(env, *this), _config(config), _timer(env),
_ram(env.ram()), _bb_ds(env.ram(), env.rm(), 0) {}
_ram(env.ram()), _ds(env.ram(), env.rm(), 0) {}
Driver & driver() { return _driver; }
@ -118,11 +111,6 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
_driver.update_mode();
if (_driver.dataspace().valid())
_fb_ds.construct(_driver.dataspace());
else
_fb_ds.destruct();
if (_mode_sigh.valid())
Genode::Signal_transmitter(_mode_sigh).submit();
}
@ -136,9 +124,9 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
Genode::Dataspace_capability dataspace() override
{
_bb_ds.realloc(&_ram, _driver.width()*_driver.height()*_driver.bpp());
_ds.realloc(&_ram, _driver.width()*_driver.height()*_driver.bpp());
_in_mode_change = false;
return _bb_ds.cap();
return _ds.cap();
}
Mode mode() const override {
@ -157,13 +145,14 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
{
using namespace Genode;
if (!_fb_ds.constructed() ||
!_bb_ds.local_addr<void>() ||
if (!_driver.fb_addr() ||
!_ds.local_addr<void>() ||
_in_mode_change) return;
int width = _driver.width();
int height = _driver.height();
unsigned bpp = _driver.bpp();
int width = _driver.width();
int height = _driver.height();
unsigned bpp = _driver.bpp();
unsigned pitch = _driver.pitch();
/* clip specified coordinates against screen boundaries */
int x2 = min(x + w - 1, width - 1),
@ -173,10 +162,10 @@ class Framebuffer::Session_component : public Genode::Rpc_object<Session>
if (x1 > x2 || y1 > y2) return;
/* copy pixels from back buffer to physical frame buffer */
char *src = _bb_ds.local_addr<char>() + bpp*(width*y1 + x1),
*dst = _fb_ds->local_addr<char>() + bpp*(width*y1 + x1);
char *src = _ds.local_addr<char>() + bpp*(width*y1 + x1),
*dst = (char*)_driver.fb_addr() + pitch*y1 + bpp*x1;
blit(src, bpp*width, dst, bpp*width,
blit(src, bpp*width, dst, pitch,
bpp*(x2 - x1 + 1), y2 - y1 + 1);
}
};

View File

@ -0,0 +1,60 @@
/*
* \brief C-declarations needed for device driver environment
* \author Stefan Kalkowski
* \author Norman Feske
* \date 2016-06-17
*/
#ifndef _LX_EMUL_C_H_
#define _LX_EMUL_C_H_
#if 0
#define TRACE \
do { \
lx_printf("%s not implemented\n", __func__); \
} while (0)
#else
#define TRACE do { ; } while (0)
#endif
#define TRACE_AND_STOP \
do { \
lx_printf("%s not implemented\n", __func__); \
BUG(); \
} while (0)
#define ASSERT(x) \
do { \
if (!(x)) { \
lx_printf("%s:%u assertion failed\n", __func__, __LINE__); \
BUG(); \
} \
} while (0)
#include <lx_emul/extern_c_begin.h>
struct drm_device;
struct drm_framebuffer;
struct drm_display_mode;
struct drm_connector;
struct lx_c_fb_config {
int height;
int width;
unsigned pitch;
unsigned bpp;
void * addr;
unsigned long size;
struct drm_framebuffer * lx_fb;
};
void lx_c_allocate_framebuffer(struct drm_device *,
struct lx_c_fb_config *);
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 *);
#include <lx_emul/extern_c_end.h>
#endif /* _LX_EMUL_C_H_ */

View File

@ -5,6 +5,13 @@
* \date 2015-08-19
*/
/*
* Copyright (C) 2015-2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <util/bit_allocator.h>
#include <base/log.h>
@ -16,8 +23,8 @@
/* DRM-specific includes */
#include <lx_emul.h>
#include <lx_emul_c.h>
#include <lx_emul/extern_c_begin.h>
#include "lx_emul_private.h"
#include <drm/drmP.h>
#include <drm/drm_gem.h>
#include <lx_emul/extern_c_end.h>
@ -36,16 +43,7 @@
#include <lx_emul/impl/completion.h>
#include <lx_emul/impl/wait.h>
static struct drm_device * dde_drm_device = nullptr;
extern "C" struct drm_framebuffer*
dde_c_allocate_framebuffer(int width, int height, void ** base,
uint64_t * size, struct drm_device * dev);
extern "C" void
dde_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
struct drm_framebuffer *fb, struct drm_display_mode *mode);
extern "C" void dde_c_set_driver(struct drm_device * dev, void * driver);
extern "C" void* dde_c_get_driver(struct drm_device * dev);
static struct drm_device * lx_drm_device = nullptr;
struct Drm_guard
@ -73,7 +71,7 @@ struct Drm_guard
template <typename FUNCTOR>
static inline void dde_for_each_connector(drm_device * dev, FUNCTOR f)
static inline void lx_for_each_connector(drm_device * dev, FUNCTOR f)
{
struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
@ -135,7 +133,7 @@ Framebuffer::Driver::_preferred_mode(drm_connector *connector)
void Framebuffer::Driver::finish_initialization()
{
dde_c_set_driver(dde_drm_device, (void*)this);
lx_c_set_driver(lx_drm_device, (void*)this);
generate_report();
_session.config_changed();
}
@ -145,7 +143,7 @@ void Framebuffer::Driver::finish_initialization()
void Framebuffer::Driver::_poll()
{
Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) dde_drm_device->pdev->bus;
Lx::Pci_dev * pci_dev = (Lx::Pci_dev*) lx_drm_device->pdev->bus;
Lx::Irq::irq().inject_irq(pci_dev->client());
}
@ -172,39 +170,35 @@ void Framebuffer::Driver::update_mode()
Configuration old = _config;
_config = Configuration();
dde_for_each_connector(dde_drm_device, [&] (drm_connector *c) {
lx_for_each_connector(lx_drm_device, [&] (drm_connector *c) {
drm_display_mode * mode = _preferred_mode(c);
if (!mode) return;
if (mode->hdisplay > _config.width) _config.width = mode->hdisplay;
if (mode->vdisplay > _config.height) _config.height = mode->vdisplay;
if (mode->hdisplay > _config._lx.width) _config._lx.width = mode->hdisplay;
if (mode->vdisplay > _config._lx.height) _config._lx.height = mode->vdisplay;
});
_config.lx_obj =
dde_c_allocate_framebuffer(_config.width, _config.height, &_config.addr,
(uint64_t*)&_config.size, dde_drm_device);
_config.cap = _config.addr ? Lx::ioremap_lookup((addr_t)_config.addr, _config.size)
: Genode::Dataspace_capability();
lx_c_allocate_framebuffer(lx_drm_device, &_config._lx);
{
Drm_guard guard(dde_drm_device);
dde_for_each_connector(dde_drm_device, [&] (drm_connector *c) {
dde_c_set_mode(dde_drm_device, c, _config.lx_obj,
Drm_guard guard(lx_drm_device);
lx_for_each_connector(lx_drm_device, [&] (drm_connector *c) {
lx_c_set_mode(lx_drm_device, c, _config._lx.lx_fb,
_preferred_mode(c)); });
}
if (old.addr) Lx::iounmap(old.addr);
if (old.lx_obj) old.lx_obj->funcs->destroy(old.lx_obj);
if (old._lx.addr) Lx::iounmap(old._lx.addr);
if (old._lx.lx_fb) old._lx.lx_fb->funcs->destroy(old._lx.lx_fb);
}
void Framebuffer::Driver::generate_report()
{
Drm_guard guard(dde_drm_device);
Drm_guard guard(lx_drm_device);
/* detect mode information per connector */
{
struct drm_connector *c;
list_for_each_entry(c, &dde_drm_device->mode_config.connector_list,
list_for_each_entry(c, &lx_drm_device->mode_config.connector_list,
head)
if (list_empty(&c->modes)) c->funcs->fill_modes(c, 0, 0);
}
@ -224,7 +218,7 @@ void Framebuffer::Driver::generate_report()
Genode::Reporter::Xml_generator xml(reporter, [&] ()
{
struct drm_connector *c;
list_for_each_entry(c, &dde_drm_device->mode_config.connector_list,
list_for_each_entry(c, &lx_drm_device->mode_config.connector_list,
head) {
xml.node("connector", [&] ()
{
@ -871,8 +865,8 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
{
drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
ASSERT(!dde_drm_device);
dde_drm_device = dev;
ASSERT(!lx_drm_device);
lx_drm_device = dev;
return dev->driver->load(dev, flags);
}
@ -1546,7 +1540,7 @@ void local_irq_enable()
void drm_sysfs_hotplug_event(struct drm_device *dev)
{
Framebuffer::Driver * driver = (Framebuffer::Driver*)
dde_c_get_driver(dde_drm_device);
lx_c_get_driver(lx_drm_device);
if (driver) {
DRM_DEBUG("generating hotplug event\n");

View File

@ -1,10 +1,24 @@
#include "lx_emul_private.h"
/*
* \brief Linux emulation C helper functions
* \author Stefan Kalkowski
* \date 2016-03-22
*/
/*
* Copyright (C) 2016 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <lx_emul_c.h>
#include <../drivers/gpu/drm/i915/i915_drv.h>
#include <../drivers/gpu/drm/i915/intel_drv.h>
#include <drm/drm_atomic_helper.h>
extern struct drm_framebuffer *
dde_c_intel_framebuffer_create(struct drm_device *dev,
lx_c_intel_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_i915_gem_object *obj);
@ -18,56 +32,55 @@ int intel_sanitize_enable_execlists(struct drm_device *dev,
}
struct drm_framebuffer*
dde_c_allocate_framebuffer(int width, int height, void ** base,
uint64_t * size, struct drm_device * dev)
void lx_c_allocate_framebuffer(struct drm_device * dev,
struct lx_c_fb_config *c)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_framebuffer * fb = NULL;
struct drm_mode_fb_cmd2 * r;
struct drm_i915_gem_object * obj = NULL;
mutex_lock(&dev->struct_mutex);
*size = roundup(width * height * 2, PAGE_SIZE);
if (*size * 2 < dev_priv->gtt.stolen_usable_size)
obj = i915_gem_object_create_stolen(dev, *size);
/* 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);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, *size);
obj = i915_gem_alloc_object(dev, c->size);
if (obj == NULL) goto out2;
r = (struct drm_mode_fb_cmd2*) kzalloc(sizeof(struct drm_mode_fb_cmd2), 0);
if (!r) goto err2;
r->width = width;
r->height = height;
r->width = c->width;
r->height = c->height;
r->pixel_format = DRM_FORMAT_RGB565;
r->pitches[0] = width * 2;
fb = dde_c_intel_framebuffer_create(dev, r, obj);
if (IS_ERR(fb)) goto err2;
r->pitches[0] = c->pitch;
c->lx_fb = lx_c_intel_framebuffer_create(dev, r, obj);
if (IS_ERR(c->lx_fb)) goto err2;
if (intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL))
if (intel_pin_and_fence_fb_obj(NULL, c->lx_fb, NULL, NULL, NULL))
goto err1;
*base = ioremap_wc(dev_priv->gtt.mappable_base
+ i915_gem_obj_ggtt_offset(obj), *size);
c->addr = ioremap_wc(dev_priv->gtt.mappable_base
+ i915_gem_obj_ggtt_offset(obj), c->size);
memset_io(*base, 0, *size);
memset_io(c->addr, 0, c->size);
goto out1;
err1:
drm_framebuffer_remove(fb);
drm_framebuffer_remove(c->lx_fb);
err2:
fb = NULL;
c->lx_fb = NULL;
drm_gem_object_unreference(&obj->base);
out1:
kfree(r);
out2:
mutex_unlock(&dev->struct_mutex);
return fb;
}
void dde_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
void lx_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
struct drm_framebuffer *fb, struct drm_display_mode *mode)
{
struct drm_crtc *crtc = NULL;
@ -131,7 +144,7 @@ void dde_c_set_mode(struct drm_device * dev, struct drm_connector * connector,
}
void dde_c_set_driver(struct drm_device * dev, void * driver)
void lx_c_set_driver(struct drm_device * dev, void * driver)
{
struct drm_i915_private *dev_priv = dev->dev_private;
ASSERT(!dev_priv->audio_component);
@ -139,7 +152,7 @@ void dde_c_set_driver(struct drm_device * dev, void * driver)
}
void* dde_c_get_driver(struct drm_device * dev)
void* lx_c_get_driver(struct drm_device * dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
return (void*) dev_priv->audio_component;

View File

@ -1,37 +0,0 @@
/*
* \brief Local definitions of the Linux kernel API implementation
* \author Norman Feske
* \date 2015-08-24
*/
#ifndef _LX_EMUL_PRIVATE_H_
#define _LX_EMUL_PRIVATE_H_
/* Linux kernel API */
#include <stdarg.h>
#include <lx_emul/printf.h>
#if 0
#define TRACE \
do { \
lx_printf("%s not implemented\n", __func__); \
} while (0)
#else
#define TRACE do { ; } while (0)
#endif
#define TRACE_AND_STOP \
do { \
lx_printf("%s not implemented\n", __func__); \
BUG(); \
} while (0)
#define ASSERT(x) \
do { \
if (!(x)) { \
lx_printf("%s:%u assertion failed\n", __func__, __LINE__); \
BUG(); \
} \
} while (0)
#endif /* _LX_EMUL_PRIVATE_H_ */