From patchwork Sun Aug 12 14:53:24 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Herrmann X-Patchwork-Id: 1309741 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 5195BDFF7B for ; Sun, 12 Aug 2012 14:53:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752111Ab2HLOxO (ORCPT ); Sun, 12 Aug 2012 10:53:14 -0400 Received: from mail-wi0-f172.google.com ([209.85.212.172]:62191 "EHLO mail-wi0-f172.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751890Ab2HLOwp (ORCPT ); Sun, 12 Aug 2012 10:52:45 -0400 Received: by wicr5 with SMTP id r5so1820244wic.1 for ; Sun, 12 Aug 2012 07:52:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=kruxLqP7OnJapdi4CpXBTxEBPLFnaQhciJ9Qm5jxx9o=; b=H0zUmx0JhXN5jf4AaFESUI8ALkr61hNLReK6WiDSGsztIOLoBVCHnhL4oGEdnO9ThN VLVkPLuZ/9N8xnhPea4WjORS/eamWfrlf8v/a0S4x/Mk5fLP/gDy2yUM9l/Hojhg5wtB r0Vb2B2JuRvJKrX3FpyK38a98td1/FFy4mCPtc1KRv99xcdk1baDV1qmYbhjATrlZPWO goYBTN/rnpfrXqRLhZnyHkMDtoavjeg3aPEGf23GLQJm3uLkoAn5SyKW6e5sIFvx+0iK uYz54EC8y56gsFJVcxeZK7d6qA49vfg5QBQkw9KApAStbzBy6KAYml3LY8DDipYyAS0k TFOA== Received: by 10.180.106.97 with SMTP id gt1mr11121951wib.5.1344783163644; Sun, 12 Aug 2012 07:52:43 -0700 (PDT) Received: from localhost.localdomain (stgt-5f71bba7.pool.mediaWays.net. [95.113.187.167]) by mx.google.com with ESMTPS id k20sm10803202wiv.11.2012.08.12.07.52.42 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 12 Aug 2012 07:52:43 -0700 (PDT) From: David Herrmann To: linux-fbdev@vger.kernel.org Cc: Florian Tobias Schandinat , Greg Kroah-Hartman , linux-serial@vger.kernel.org, Alan Cox , linux-kernel@vger.kernel.org, Geert Uytterhoeven , David Herrmann Subject: [PATCH 10/11] fblog: draw console to framebuffers Date: Sun, 12 Aug 2012 16:53:24 +0200 Message-Id: <1344783205-2384-11-git-send-email-dh.herrmann@googlemail.com> X-Mailer: git-send-email 1.7.11.4 In-Reply-To: <1344783205-2384-1-git-send-email-dh.herrmann@googlemail.com> References: <1344783205-2384-1-git-send-email-dh.herrmann@googlemail.com> Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org If not disabled or suspended, we now blit the console data to each framebuffer. We only redraw on changes to avoid consuming too much CPU power. This isn't optimized for speed, currently. However, fblog is mainly used for debugging purposes so this can be optimized later. Signed-off-by: David Herrmann --- drivers/video/console/fblog.c | 110 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/fblog.c b/drivers/video/console/fblog.c index 2e39577..25bb63d 100644 --- a/drivers/video/console/fblog.c +++ b/drivers/video/console/fblog.c @@ -28,8 +28,11 @@ #include #include #include +#include +#include #include #include +#include "fbdraw.h" /** * struct fblog_buf: Console text buffer @@ -66,6 +69,7 @@ struct fblog_fb { struct device dev; struct mutex lock; struct fblog_buf buf; + struct console_font font; }; static DEFINE_MUTEX(fblog_registration_lock); @@ -176,6 +180,61 @@ static void fblog_buf_write(struct fblog_buf *buf, const char *str, size_t len) } } +static void fblog_redraw_clear(struct fblog_fb *fb) +{ + struct fb_fillrect region; + struct fb_info *info = fb->info; + + region.color = 0; + region.dx = 0; + region.dy = 0; + region.width = info->var.xres; + region.height = info->var.yres; + region.rop = ROP_COPY; + + info->fbops->fb_fillrect(info, ®ion); +} + +static void fblog_redraw(struct fblog_fb *fb) +{ + size_t i; + + if (!active) + return; + + mutex_lock(&fb->lock); + if (!test_bit(FBLOG_OPEN, &fb->flags) || + test_bit(FBLOG_SUSPENDED, &fb->flags) || + test_bit(FBLOG_BLANKED, &fb->flags)) { + mutex_unlock(&fb->lock); + return; + } + + fblog_redraw_clear(fb); + + for (i = 0; i < fb->buf.height; ++i) { + fbdraw_font(fb->info, &fb->font, false, 0, i, 7, 0, 0, + fb->buf.lines[i], fb->buf.width); + } + + mutex_unlock(&fb->lock); +} + +static void fblog_refresh(struct fblog_fb *fb) +{ + unsigned int width, height; + + mutex_lock(&fb->lock); + if (test_bit(FBLOG_OPEN, &fb->flags)) { + width = fb->info->var.xres / fb->font.width; + height = fb->info->var.yres / fb->font.height; + fblog_buf_resize(&fb->buf, width, height); + } + mutex_unlock(&fb->lock); + + fblog_redraw(fb); +} + /* * fblog_open/close() * These functions manage access to the underlying framebuffer. While opened, we @@ -192,6 +251,10 @@ static int fblog_open(struct fblog_fb *fb) { static const char init_str[] = "Framebuffer log initialized\n"; int ret; + struct fb_var_screeninfo var; + const struct fb_videomode *mode; + unsigned int width, height; + const struct font_desc *font; if (!active) return -EPERM; @@ -208,6 +271,13 @@ static int fblog_open(struct fblog_fb *fb) goto unlock; } + font = get_default_font(var.xres, var.yres, fb->info->pixmap.blit_x, + fb->info->pixmap.blit_y); + if (!font) { + ret = -ENODEV; + goto unlock; + } + if (!try_module_get(fb->info->fbops->owner)) { ret = -ENODEV; goto out_killed; @@ -218,10 +288,22 @@ static int fblog_open(struct fblog_fb *fb) goto out_unref; } - fblog_buf_resize(&fb->buf, 80, 24); + var = fb->info->var; + mode = fb_find_best_mode(&var, &fb->info->modelist); + var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; + fb_set_var(fb->info, &var); + + fb->font.width = font->width; + fb->font.height = font->height; + fb->font.data = (void*)font->data; + + width = var.xres / fb->font.width; + height = var.yres / fb->font.height; + fblog_buf_resize(&fb->buf, width, height); fblog_buf_write(&fb->buf, init_str, sizeof(init_str) - 1); set_bit(FBLOG_OPEN, &fb->flags); mutex_unlock(&fb->lock); + fblog_redraw(fb); return 0; out_unref: @@ -460,6 +542,31 @@ static int fblog_event(struct notifier_block *self, unsigned long action, else set_bit(FBLOG_BLANKED, &fb->flags); break; + case FB_EVENT_MODE_DELETE: + /* This is sent when a video mode is removed. The current video + * mode is never removed! The console lock is held while this is + * called. */ + /* fallthrough */ + case FB_EVENT_NEW_MODELIST: + /* This is sent when the modelist got changed. The console-lock + * is held and we should reset the mode. */ + /* fallthrough */ + case FB_EVENT_MODE_CHANGE_ALL: + /* This is the same as below but notifies us that the user used + * the FB_ACTIVATE_ALL flag when setting the video mode. */ + /* fallthrough */ + case FB_EVENT_MODE_CHANGE: + /* This is called when the _user_ changes the video mode via + * ioctls. It is not sent, when the kernel changes the mode + * internally. This callback is called inside fb_set_var() so + * the console lock is held. */ + mutex_lock(&fblog_registration_lock); + fb = fblog_fbs[info->node]; + mutex_unlock(&fblog_registration_lock); + + if (fb) + fblog_refresh(fb); + break; } return 0; @@ -516,6 +623,7 @@ static void fblog_con_write(struct console *con, const char *buf, for (i = 0; i < FB_MAX; ++i) { if (fblog_fbs[i]) { fblog_buf_write(&fblog_fbs[i]->buf, buf, len); + fblog_redraw(fblog_fbs[i]); } } mutex_unlock(&fblog_registration_lock);