From owner-svn-src-head@freebsd.org Sun Dec 20 00:58:23 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 7840CA4B171; Sun, 20 Dec 2015 00:58:23 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 554611AE0; Sun, 20 Dec 2015 00:58:23 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBK0wMw7019483; Sun, 20 Dec 2015 00:58:22 GMT (envelope-from gonzo@FreeBSD.org) Received: (from gonzo@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBK0wM5g019482; Sun, 20 Dec 2015 00:58:22 GMT (envelope-from gonzo@FreeBSD.org) Message-Id: <201512200058.tBK0wM5g019482@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gonzo set sender to gonzo@FreeBSD.org using -f From: Oleksandr Tymoshenko Date: Sun, 20 Dec 2015 00:58:22 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r292483 - head/sys/arm/broadcom/bcm2835 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 20 Dec 2015 00:58:23 -0000 Author: gonzo Date: Sun Dec 20 00:58:22 2015 New Revision: 292483 URL: https://svnweb.freebsd.org/changeset/base/292483 Log: Add dev.fb.X.resync sysctl to resync ARM framebuffer with VideoCore Some applications (e.g. Kodi) use tvservice APIs to manage HDMI modes, power state, EDID etc. directly through VideoCore. After these manipulations VideoCore may loose its state and needs to be resynced with ARM. Under Linux this problem is worked around using fbset utility that recreates framebuffer. Since there is no fbset utility in FreeBSD we provide sysctl for userland apps to get system back into normal mode. Modified: head/sys/arm/broadcom/bcm2835/bcm2835_fbd.c Modified: head/sys/arm/broadcom/bcm2835/bcm2835_fbd.c ============================================================================== --- head/sys/arm/broadcom/bcm2835/bcm2835_fbd.c Sun Dec 20 00:45:34 2015 (r292482) +++ head/sys/arm/broadcom/bcm2835/bcm2835_fbd.c Sun Dec 20 00:58:22 2015 (r292483) @@ -59,13 +59,130 @@ __FBSDID("$FreeBSD$"); #define FB_DEPTH 24 struct bcmsc_softc { - struct fb_info *info; + struct fb_info info; + int fbswap; + struct bcm2835_fb_config fb; + device_t dev; }; static int bcm_fb_probe(device_t); static int bcm_fb_attach(device_t); static int +bcm_fb_init(struct bcmsc_softc *sc, struct bcm2835_fb_config *fb) +{ + int err; + + err = 0; + + memset(fb, 0, sizeof(*fb)); + if (bcm2835_mbox_fb_get_w_h(fb) != 0) + return (ENXIO); + fb->bpp = FB_DEPTH; + + if ((err = bcm2835_mbox_fb_init(fb)) != 0) { + device_printf(sc->dev, "bcm2835_mbox_fb_init failed, err=%d\n", err); + return (ENXIO); + } + + return (0); +} + +static int +bcm_fb_setup_fbd(struct bcmsc_softc *sc) +{ + struct bcm2835_fb_config fb; + device_t fbd; + int err; + + err = bcm_fb_init(sc, &fb); + if (err) + return (err); + + memset(&sc->info, 0, sizeof(sc->info)); + sc->info.fb_name = device_get_nameunit(sc->dev); + + sc->info.fb_vbase = (intptr_t)pmap_mapdev(fb.base, fb.size); + sc->info.fb_pbase = fb.base; + sc->info.fb_size = fb.size; + sc->info.fb_bpp = sc->info.fb_depth = fb.bpp; + sc->info.fb_stride = fb.pitch; + sc->info.fb_width = fb.xres; + sc->info.fb_height = fb.yres; + + if (sc->fbswap) { + switch (sc->info.fb_bpp) { + case 24: + vt_generate_cons_palette(sc->info.fb_cmap, + COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16); + sc->info.fb_cmsize = 16; + break; + case 32: + vt_generate_cons_palette(sc->info.fb_cmap, + COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0); + sc->info.fb_cmsize = 16; + break; + } + } + + fbd = device_add_child(sc->dev, "fbd", device_get_unit(sc->dev)); + if (fbd == NULL) { + device_printf(sc->dev, "Failed to add fbd child\n"); + pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); + return (ENXIO); + } else if (device_probe_and_attach(fbd) != 0) { + device_printf(sc->dev, "Failed to attach fbd device\n"); + device_delete_child(sc->dev, fbd); + pmap_unmapdev(sc->info.fb_vbase, sc->info.fb_size); + return (ENXIO); + } + + device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, + fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); + device_printf(sc->dev, + "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", + sc->fbswap, fb.pitch, fb.base, fb.size); + + return (0); +} + +static int +bcm_fb_resync_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct bcmsc_softc *sc = arg1; + struct bcm2835_fb_config fb; + int val; + int err; + + val = 0; + err = sysctl_handle_int(oidp, &val, 0, req); + if (err || !req->newptr) /* error || read request */ + return (err); + + bcm_fb_init(sc, &fb); + + return (0); +} + +static void +bcm_fb_sysctl_init(struct bcmsc_softc *sc) +{ + struct sysctl_ctx_list *ctx; + struct sysctl_oid *tree_node; + struct sysctl_oid_list *tree; + + /* + * Add system sysctl tree/handlers. + */ + ctx = device_get_sysctl_ctx(sc->dev); + tree_node = device_get_sysctl_tree(sc->dev); + tree = SYSCTL_CHILDREN(tree_node); + SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "resync", + CTLFLAG_RW | CTLTYPE_UINT, sc, sizeof(*sc), + bcm_fb_resync_sysctl, "IU", "Set to resync framebuffer with VC"); +} + +static int bcm_fb_probe(device_t dev) { if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb")) @@ -80,36 +197,15 @@ static int bcm_fb_attach(device_t dev) { char bootargs[2048], *n, *p, *v; - device_t fbd; - int fbswap, err; + int err; phandle_t chosen; - struct bcm2835_fb_config fb; struct bcmsc_softc *sc; - struct fb_info *info; sc = device_get_softc(dev); - memset(&fb, 0, sizeof(fb)); - if (bcm2835_mbox_fb_get_w_h(&fb) != 0) - return (ENXIO); - fb.bpp = FB_DEPTH; - if ((err = bcm2835_mbox_fb_init(&fb)) != 0) { - device_printf(dev, "bcm2835_mbox_fb_init failed, err=%d\n", err); - return (ENXIO); - } - - info = malloc(sizeof(struct fb_info), M_DEVBUF, M_WAITOK | M_ZERO); - info->fb_name = device_get_nameunit(dev); - info->fb_vbase = (intptr_t)pmap_mapdev(fb.base, fb.size); - info->fb_pbase = fb.base; - info->fb_size = fb.size; - info->fb_bpp = info->fb_depth = fb.bpp; - info->fb_stride = fb.pitch; - info->fb_width = fb.xres; - info->fb_height = fb.yres; - sc->info = info; + sc->dev = dev; /* Newer firmware versions needs an inverted color palette. */ - fbswap = 0; + sc->fbswap = 0; chosen = OF_finddevice("/chosen"); if (chosen != 0 && OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) { @@ -120,41 +216,15 @@ bcm_fb_attach(device_t dev) n = strsep(&v, "="); if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL) if (*v == '1') - fbswap = 1; + sc->fbswap = 1; } } - if (fbswap) { - switch (info->fb_bpp) { - case 24: - vt_generate_cons_palette(info->fb_cmap, - COLOR_FORMAT_RGB, 0xff, 0, 0xff, 8, 0xff, 16); - info->fb_cmsize = 16; - break; - case 32: - vt_generate_cons_palette(info->fb_cmap, - COLOR_FORMAT_RGB, 0xff, 16, 0xff, 8, 0xff, 0); - info->fb_cmsize = 16; - break; - } - } - fbd = device_add_child(dev, "fbd", device_get_unit(dev)); - if (fbd == NULL) { - device_printf(dev, "Failed to add fbd child\n"); - free(info, M_DEVBUF); - return (ENXIO); - } else if (device_probe_and_attach(fbd) != 0) { - device_printf(dev, "Failed to attach fbd device\n"); - device_delete_child(dev, fbd); - free(info, M_DEVBUF); - return (ENXIO); - } + bcm_fb_sysctl_init(sc); - device_printf(dev, "%dx%d(%dx%d@%d,%d) %dbpp\n", fb.xres, fb.yres, - fb.vxres, fb.vyres, fb.xoffset, fb.yoffset, fb.bpp); - device_printf(dev, - "fbswap: %d, pitch %d, base 0x%08x, screen_size %d\n", - fbswap, fb.pitch, fb.base, fb.size); + err = bcm_fb_setup_fbd(sc); + if (err) + return (err); return (0); } @@ -166,7 +236,7 @@ bcm_fb_helper_getinfo(device_t dev) sc = device_get_softc(dev); - return (sc->info); + return (&sc->info); } static device_method_t bcm_fb_methods[] = {