summaryrefslogtreecommitdiffstats
path: root/sys/arm/broadcom/bcm2835
diff options
context:
space:
mode:
authorgjb <gjb@FreeBSD.org>2015-05-06 11:50:30 +0000
committergjb <gjb@FreeBSD.org>2015-05-06 11:50:30 +0000
commite9b794a6dfdf28ce835f5730e5884b97bc62aa19 (patch)
tree759e7355bf352e43e4a156a773a28d3d9fdbcad7 /sys/arm/broadcom/bcm2835
parent55e5b36d38ff95ded004ed97fe9ed303abb36184 (diff)
parent462d48d659bae28be32c0d488ddeeaaf99d87bae (diff)
downloadFreeBSD-src-e9b794a6dfdf28ce835f5730e5884b97bc62aa19.zip
FreeBSD-src-e9b794a6dfdf28ce835f5730e5884b97bc62aa19.tar.gz
MFH: r282315-r282534
Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'sys/arm/broadcom/bcm2835')
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c59
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fb.c416
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_fbd.c263
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_mbox.c174
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h153
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_sdhci.c9
-rw-r--r--sys/arm/broadcom/bcm2835/bcm2835_vcbus.h12
7 files changed, 590 insertions, 496 deletions
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
index 2ea5b49..ab0f901 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_cpufreq.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (C) 2013-2014 Daisuke Aoyama <aoyama@peach.ne.jp>
+ * Copyright (C) 2013-2015 Daisuke Aoyama <aoyama@peach.ne.jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -60,21 +60,28 @@ __FBSDID("$FreeBSD$");
#define DPRINTF(fmt, ...)
#endif
-#define HZ2MHZ(freq) ((freq) / (1000 * 1000))
-#define MHZ2HZ(freq) ((freq) * (1000 * 1000))
-#define OFFSET2MVOLT(val) (1200 + ((val) * 25))
-#define MVOLT2OFFSET(val) (((val) - 1200) / 25)
-
-#define DEFAULT_ARM_FREQUENCY 700
-#define DEFAULT_CORE_FREQUENCY 250
-#define DEFAULT_SDRAM_FREQUENCY 400
-#define DEFAULT_LOWEST_FREQ 300
-#define TRANSITION_LATENCY 1000
-#define MIN_OVER_VOLTAGE -16
-#define MAX_OVER_VOLTAGE 6
-#define MSG_ERROR -999999999
-#define MHZSTEP 100
-#define HZSTEP (MHZ2HZ(MHZSTEP))
+#define HZ2MHZ(freq) ((freq) / (1000 * 1000))
+#define MHZ2HZ(freq) ((freq) * (1000 * 1000))
+
+#ifdef SOC_BCM2836
+#define OFFSET2MVOLT(val) (((val) / 1000))
+#define MVOLT2OFFSET(val) (((val) * 1000))
+#define DEFAULT_ARM_FREQUENCY 600
+#define DEFAULT_LOWEST_FREQ 600
+#else
+#define OFFSET2MVOLT(val) (1200 + ((val) * 25))
+#define MVOLT2OFFSET(val) (((val) - 1200) / 25)
+#define DEFAULT_ARM_FREQUENCY 700
+#define DEFAULT_LOWEST_FREQ 300
+#endif
+#define DEFAULT_CORE_FREQUENCY 250
+#define DEFAULT_SDRAM_FREQUENCY 400
+#define TRANSITION_LATENCY 1000
+#define MIN_OVER_VOLTAGE -16
+#define MAX_OVER_VOLTAGE 6
+#define MSG_ERROR -999999999
+#define MHZSTEP 100
+#define HZSTEP (MHZ2HZ(MHZSTEP))
#define TZ_ZEROC 2732
#define VC_LOCK(sc) do { \
@@ -1740,6 +1747,23 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
if (min_freq > cpufreq_lowest_freq)
min_freq = cpufreq_lowest_freq;
+#ifdef SOC_BCM2836
+ /* XXX RPi2 have only 900/600MHz */
+ idx = 0;
+ volts = sc->min_voltage_core;
+ sets[idx].freq = freq;
+ sets[idx].volts = volts;
+ sets[idx].lat = TRANSITION_LATENCY;
+ sets[idx].dev = dev;
+ idx++;
+ if (freq != min_freq) {
+ sets[idx].freq = min_freq;
+ sets[idx].volts = volts;
+ sets[idx].lat = TRANSITION_LATENCY;
+ sets[idx].dev = dev;
+ idx++;
+ }
+#else
/* from freq to min_freq */
for (idx = 0; idx < *count && freq >= min_freq; idx++) {
if (freq > sc->arm_min_freq)
@@ -1752,7 +1776,8 @@ bcm2835_cpufreq_make_freq_list(device_t dev, struct cf_setting *sets,
sets[idx].dev = dev;
freq -= MHZSTEP;
}
- *count = ++idx;
+#endif
+ *count = idx;
return (0);
}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fb.c b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
index 3270da1..6e6cfda 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fb.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fb.c
@@ -29,46 +29,27 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/bio.h>
#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
+#include <sys/consio.h>
+#include <sys/fbio.h>
+#include <sys/kdb.h>
#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/queue.h>
-#include <sys/resource.h>
-#include <sys/rman.h>
-#include <sys/time.h>
-#include <sys/timetc.h>
-#include <sys/fbio.h>
-#include <sys/consio.h>
-
-#include <sys/kdb.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/cpufunc.h>
-#include <machine/resource.h>
-#include <machine/intr.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <dev/fb/fbreg.h>
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-
-#include <dev/fb/fbreg.h>
#include <dev/syscons/syscons.h>
-#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
-#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
#include "mbox_if.h"
-#define BCMFB_FONT_HEIGHT 16
-
struct argb {
uint8_t a;
uint8_t r;
@@ -101,40 +82,15 @@ static u_char mouse_pointer[16] = {
0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
};
-#define FB_WIDTH 640
-#define FB_HEIGHT 480
-#define FB_DEPTH 24
-
-struct bcm_fb_config {
- uint32_t xres;
- uint32_t yres;
- uint32_t vxres;
- uint32_t vyres;
- uint32_t pitch;
- uint32_t bpp;
- uint32_t xoffset;
- uint32_t yoffset;
- /* Filled by videocore */
- uint32_t base;
- uint32_t screen_size;
-};
+#define BCMFB_FONT_HEIGHT 16
+#define BCMFB_FONT_WIDTH 8
+#define FB_WIDTH 640
+#define FB_HEIGHT 480
+#define FB_DEPTH 24
struct bcmsc_softc {
- device_t dev;
- struct cdev * cdev;
- struct mtx mtx;
- bus_dma_tag_t dma_tag;
- bus_dmamap_t dma_map;
- struct bcm_fb_config* fb_config;
- bus_addr_t fb_config_phys;
- struct intr_config_hook init_hook;
-
-};
-
-struct video_adapter_softc {
/* Videoadpater part */
video_adapter_t va;
- int console;
intptr_t fb_addr;
intptr_t fb_paddr;
@@ -149,199 +105,75 @@ struct video_adapter_softc {
unsigned int ymargin;
unsigned char *font;
+ int fbswap;
int initialized;
};
-static struct bcmsc_softc *bcmsc_softc;
-static struct video_adapter_softc va_softc;
-
-#define bcm_fb_lock(_sc) mtx_lock(&(_sc)->mtx)
-#define bcm_fb_unlock(_sc) mtx_unlock(&(_sc)->mtx)
-#define bcm_fb_lock_assert(sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
+static struct bcmsc_softc bcmsc;
static int bcm_fb_probe(device_t);
static int bcm_fb_attach(device_t);
-static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err);
static void bcmfb_update_margins(video_adapter_t *adp);
static int bcmfb_configure(int);
-static void
-bcm_fb_init(void *arg)
-{
- struct bcmsc_softc *sc = arg;
- struct video_adapter_softc *va_sc = &va_softc;
- int err;
- volatile struct bcm_fb_config* fb_config = sc->fb_config;
- phandle_t node;
- pcell_t cell;
- device_t mbox;
-
- node = ofw_bus_get_node(sc->dev);
-
- fb_config->xres = 0;
- fb_config->yres = 0;
- fb_config->bpp = 0;
-
- if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0)
- fb_config->xres = (int)fdt32_to_cpu(cell);
- if (fb_config->xres == 0)
- fb_config->xres = FB_WIDTH;
-
- if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0)
- fb_config->yres = (uint32_t)fdt32_to_cpu(cell);
- if (fb_config->yres == 0)
- fb_config->yres = FB_HEIGHT;
-
- if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0)
- fb_config->bpp = (uint32_t)fdt32_to_cpu(cell);
- if (fb_config->bpp == 0)
- fb_config->bpp = FB_DEPTH;
-
- fb_config->vxres = 0;
- fb_config->vyres = 0;
- fb_config->xoffset = 0;
- fb_config->yoffset = 0;
- fb_config->base = 0;
- fb_config->pitch = 0;
- fb_config->screen_size = 0;
-
- bus_dmamap_sync(sc->dma_tag, sc->dma_map,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- mbox = devclass_get_device(devclass_find("mbox"), 0);
- if (mbox) {
- MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys);
- MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err);
- }
- bus_dmamap_sync(sc->dma_tag, sc->dma_map,
- BUS_DMASYNC_POSTREAD);
-
- if (fb_config->base != 0) {
- device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n",
- fb_config->xres, fb_config->yres,
- fb_config->vxres, fb_config->vyres,
- fb_config->xoffset, fb_config->yoffset,
- fb_config->bpp);
-
-
- device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n",
- fb_config->pitch, fb_config->base,
- fb_config->screen_size);
-
- va_sc->fb_addr = (intptr_t)pmap_mapdev(fb_config->base, fb_config->screen_size);
- va_sc->fb_paddr = fb_config->base;
- va_sc->fb_size = fb_config->screen_size;
- va_sc->depth = fb_config->bpp;
- va_sc->stride = fb_config->pitch;
-
- va_sc->width = fb_config->xres;
- va_sc->height = fb_config->yres;
- bcmfb_update_margins(&va_sc->va);
- }
- else {
- device_printf(sc->dev, "Failed to set framebuffer info\n");
- }
-
- config_intrhook_disestablish(&sc->init_hook);
-}
-
static int
bcm_fb_probe(device_t dev)
{
- int error = 0;
+ int error;
if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-fb"))
return (ENXIO);
-
device_set_desc(dev, "BCM2835 framebuffer device");
-
error = sc_probe_unit(device_get_unit(dev),
device_get_flags(dev) | SC_AUTODETECT_KBD);
if (error != 0)
return (error);
-
return (BUS_PROBE_DEFAULT);
}
static int
bcm_fb_attach(device_t dev)
{
- struct bcmsc_softc *sc = device_get_softc(dev);
- int dma_size = sizeof(struct bcm_fb_config);
- int err;
-
- if (bcmsc_softc)
- return (ENXIO);
+ struct bcm2835_fb_config fb;
+ struct bcmsc_softc *sc;
- bcmsc_softc = sc;
-
- sc->dev = dev;
- mtx_init(&sc->mtx, "bcm2835fb", "fb", MTX_DEF);
-
- err = bus_dma_tag_create(
- bus_get_dma_tag(sc->dev),
- PAGE_SIZE, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- dma_size, 1, /* maxsize, nsegments */
- dma_size, 0, /* maxsegsize, flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->dma_tag);
-
- err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config,
- 0, &sc->dma_map);
- if (err) {
- device_printf(dev, "cannot allocate framebuffer\n");
- goto fail;
- }
-
- err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config,
- dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT);
-
- if (err) {
- device_printf(dev, "cannot load DMA map\n");
- goto fail;
- }
+ sc = (struct bcmsc_softc *)vid_get_adapter(vid_find_adapter(
+ "bcmfb", 0));
+ if (sc != NULL)
+ device_set_softc(dev, sc);
+ else
+ sc = device_get_softc(dev);
- err = (sc_attach_unit(device_get_unit(dev),
- device_get_flags(dev) | SC_AUTODETECT_KBD));
+ memset(&fb, 0, sizeof(fb));
+ if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0)
+ return (ENXIO);
+ fb.bpp = FB_DEPTH;
+ if (bcm2835_mbox_fb_init(dev, &fb) != 0)
+ return (ENXIO);
- if (err) {
+ sc->fb_addr = (intptr_t)pmap_mapdev(fb.base, fb.size);
+ sc->fb_paddr = fb.base;
+ sc->fb_size = fb.size;
+ sc->depth = fb.bpp;
+ sc->stride = fb.pitch;
+ sc->width = fb.xres;
+ sc->height = fb.yres;
+ bcmfb_update_margins(&sc->va);
+
+ if (sc_attach_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD) != 0) {
device_printf(dev, "failed to attach syscons\n");
- goto fail;
+ return (ENXIO);
}
- /*
- * We have to wait until interrupts are enabled.
- * Mailbox relies on it to get data from VideoCore
- */
- sc->init_hook.ich_func = bcm_fb_init;
- sc->init_hook.ich_arg = sc;
-
- if (config_intrhook_establish(&sc->init_hook) != 0) {
- device_printf(dev, "failed to establish intrhook\n");
- return (ENOMEM);
- }
+ 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",
+ sc->fbswap, fb.pitch, fb.base, fb.size);
return (0);
-
-fail:
- return (ENXIO);
-}
-
-
-static void
-bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
-{
- bus_addr_t *addr;
-
- if (err)
- return;
-
- addr = (bus_addr_t*)arg;
- *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
}
static device_method_t bcm_fb_methods[] = {
@@ -504,13 +336,13 @@ bcmrend_set_cursor(scr_stat* scp, int base, int height, int blink)
static void
bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip)
{
- video_adapter_t* adp = scp->sc->adp;
- struct video_adapter_softc *sc;
- int row, col;
+ int bytes, col, i, j, row;
+ struct bcmsc_softc *sc;
uint8_t *addr;
- int i, j, bytes;
+ video_adapter_t *adp;
- sc = (struct video_adapter_softc *)adp;
+ adp = scp->sc->adp;
+ sc = (struct bcmsc_softc *)adp;
if (scp->curs_attr.height <= 0)
return;
@@ -529,8 +361,7 @@ bcmrend_draw_cursor(scr_stat* scp, int off, int blink, int on, int flip)
+ (row + sc->ymargin)*(sc->stride)
+ (sc->depth/8) * (col + sc->xmargin);
- bytes = sc->depth/8;
-
+ bytes = sc->depth / 8;
/* our cursor consists of simply inverting the char under it */
for (i = 0; i < adp->va_info.vi_cheight; i++) {
for (j = 0; j < adp->va_info.vi_cwidth; j++) {
@@ -577,56 +408,80 @@ extern u_char dflt_font_16[];
static void
bcmfb_update_margins(video_adapter_t *adp)
{
- struct video_adapter_softc *sc;
+ struct bcmsc_softc *sc;
video_info_t *vi;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
vi = &adp->va_info;
sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
- sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2;
}
static int
bcmfb_configure(int flags)
{
- struct video_adapter_softc *va_sc;
-
- va_sc = &va_softc;
- phandle_t display, root;
+ char bootargs[2048], *n, *p, *v;
pcell_t cell;
+ phandle_t chosen, display, root;
+ struct bcmsc_softc *sc;
- if (va_sc->initialized)
+ sc = &bcmsc;
+ if (sc->initialized)
return (0);
- va_sc->width = 0;
- va_sc->height = 0;
+ sc->width = 0;
+ sc->height = 0;
/*
* It seems there is no way to let syscons framework know
* that framebuffer resolution has changed. So just try
- * to fetch data from FDT and go with defaults if failed
+ * to fetch data from FDT bootargs, FDT display data and
+ * finally go with defaults if everything else has failed.
*/
+ chosen = OF_finddevice("/chosen");
+ if (chosen != 0 &&
+ OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) {
+ p = bootargs;
+ while ((v = strsep(&p, " ")) != NULL) {
+ if (*v == '\0')
+ continue;
+ n = strsep(&v, "=");
+ if (strcmp(n, "bcm2708_fb.fbwidth") == 0 && v != NULL)
+ sc->width = (unsigned int)strtol(v, NULL, 0);
+ else if (strcmp(n, "bcm2708_fb.fbheight") == 0 &&
+ v != NULL)
+ sc->height = (unsigned int)strtol(v, NULL, 0);
+ else if (strcmp(n, "bcm2708_fb.fbswap") == 0 &&
+ v != NULL)
+ if (*v == '1')
+ sc->fbswap = 1;
+ }
+ }
+
root = OF_finddevice("/");
if ((root != 0) &&
(display = fdt_find_compatible(root, "broadcom,bcm2835-fb", 1))) {
- if ((OF_getprop(display, "broadcom,width",
- &cell, sizeof(cell))) > 0)
- va_sc->width = (int)fdt32_to_cpu(cell);
+ if (sc->width == 0) {
+ if ((OF_getprop(display, "broadcom,width",
+ &cell, sizeof(cell))) > 0)
+ sc->width = (int)fdt32_to_cpu(cell);
+ }
- if ((OF_getprop(display, "broadcom,height",
- &cell, sizeof(cell))) > 0)
- va_sc->height = (int)fdt32_to_cpu(cell);
+ if (sc->height == 0) {
+ if ((OF_getprop(display, "broadcom,height",
+ &cell, sizeof(cell))) > 0)
+ sc->height = (int)fdt32_to_cpu(cell);
+ }
}
- if (va_sc->width == 0)
- va_sc->width = FB_WIDTH;
- if (va_sc->height == 0)
- va_sc->height = FB_HEIGHT;
-
- bcmfb_init(0, &va_sc->va, 0);
+ if (sc->width == 0)
+ sc->width = FB_WIDTH;
+ if (sc->height == 0)
+ sc->height = FB_HEIGHT;
- va_sc->initialized = 1;
+ bcmfb_init(0, &sc->va, 0);
+ sc->initialized = 1;
return (0);
}
@@ -641,20 +496,19 @@ bcmfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
static int
bcmfb_init(int unit, video_adapter_t *adp, int flags)
{
- struct video_adapter_softc *sc;
+ struct bcmsc_softc *sc;
video_info_t *vi;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
vi = &adp->va_info;
vid_init_struct(adp, "bcmfb", -1, unit);
sc->font = dflt_font_16;
vi->vi_cheight = BCMFB_FONT_HEIGHT;
- vi->vi_cwidth = 8;
-
- vi->vi_width = sc->width/8;
- vi->vi_height = sc->height/vi->vi_cheight;
+ vi->vi_cwidth = BCMFB_FONT_WIDTH;
+ vi->vi_width = sc->width / vi->vi_cwidth;
+ vi->vi_height = sc->height / vi->vi_cheight;
/*
* Clamp width/height to syscons maximums
@@ -665,8 +519,7 @@ bcmfb_init(int unit, video_adapter_t *adp, int flags)
vi->vi_height = ROW;
sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
- sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
-
+ sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight)) / 2;
adp->va_window = (vm_offset_t) bcmfb_static_window;
adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
@@ -706,8 +559,9 @@ static int
bcmfb_load_font(video_adapter_t *adp, int page, int size, int width,
u_char *data, int c, int count)
{
- struct video_adapter_softc *sc = (struct video_adapter_softc *)adp;
+ struct bcmsc_softc *sc;
+ sc = (struct bcmsc_softc *)adp;
sc->font = data;
return (0);
@@ -780,9 +634,9 @@ static int
bcmfb_blank_display(video_adapter_t *adp, int mode)
{
- struct video_adapter_softc *sc;
+ struct bcmsc_softc *sc;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
if (sc && sc->fb_addr)
memset((void*)sc->fb_addr, 0, sc->fb_size);
@@ -793,9 +647,9 @@ static int
bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
int prot, vm_memattr_t *memattr)
{
- struct video_adapter_softc *sc;
+ struct bcmsc_softc *sc;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
/*
* This might be a legacy VGA mem request: if so, just point it at the
@@ -812,10 +666,10 @@ bcmfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
static int
bcmfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
{
- struct video_adapter_softc *sc;
+ struct bcmsc_softc *sc;
struct fbtype *fb;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
switch (cmd) {
case FBIOGTYPE:
@@ -897,16 +751,13 @@ bcmfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
static int
bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
{
- struct video_adapter_softc *sc;
- int row;
- int col;
- int i, j, k;
- uint8_t *addr;
+ int bytes, col, i, j, k, row;
+ struct bcmsc_softc *sc;
u_char *p;
- uint8_t fg, bg, color;
+ uint8_t *addr, fg, bg, color;
uint16_t rgb;
- sc = (struct video_adapter_softc *)adp;
+ sc = (struct bcmsc_softc *)adp;
if (sc->fb_addr == 0)
return (0);
@@ -921,6 +772,7 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
fg = a & 0xf ;
bg = (a >> 4) & 0xf;
+ bytes = sc->depth / 8;
for (i = 0; i < BCMFB_FONT_HEIGHT; i++) {
for (j = 0, k = 7; j < 8; j++, k--) {
if ((p[i] & (1 << k)) == 0)
@@ -930,22 +782,32 @@ bcmfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
switch (sc->depth) {
case 32:
- addr[4*j+0] = bcmfb_palette[color].r;
- addr[4*j+1] = bcmfb_palette[color].g;
- addr[4*j+2] = bcmfb_palette[color].b;
- addr[4*j+3] = bcmfb_palette[color].a;
- break;
case 24:
- addr[3*j] = bcmfb_palette[color].r;
- addr[3*j+1] = bcmfb_palette[color].g;
- addr[3*j+2] = bcmfb_palette[color].b;
+ if (sc->fbswap) {
+ addr[bytes * j + 0] =
+ bcmfb_palette[color].b;
+ addr[bytes * j + 1] =
+ bcmfb_palette[color].g;
+ addr[bytes * j + 2] =
+ bcmfb_palette[color].r;
+ } else {
+ addr[bytes * j + 0] =
+ bcmfb_palette[color].r;
+ addr[bytes * j + 1] =
+ bcmfb_palette[color].g;
+ addr[bytes * j + 2] =
+ bcmfb_palette[color].b;
+ }
+ if (sc->depth == 32)
+ addr[bytes * j + 3] =
+ bcmfb_palette[color].a;
break;
case 16:
rgb = (bcmfb_palette[color].r >> 3) << 11;
rgb |= (bcmfb_palette[color].g >> 2) << 5;
rgb |= (bcmfb_palette[color].b >> 3);
- addr[2*j] = rgb & 0xff;
- addr[2*j + 1] = (rgb >> 8) & 0xff;
+ addr[bytes * j] = rgb & 0xff;
+ addr[bytes * j + 1] = (rgb >> 8) & 0xff;
default:
/* Not supported yet */
break;
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
index f41e6e2..34a7af8 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_fbd.c
@@ -35,170 +35,35 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bio.h>
#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/endian.h>
+#include <sys/fbio.h>
#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/queue.h>
-#include <sys/resource.h>
-#include <sys/rman.h>
-#include <sys/time.h>
-#include <sys/timetc.h>
-#include <sys/fbio.h>
-#include <sys/consio.h>
-
-#include <sys/kdb.h>
#include <vm/vm.h>
#include <vm/pmap.h>
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/cpufunc.h>
-#include <machine/fdt.h>
-#include <machine/resource.h>
-#include <machine/intr.h>
-
#include <dev/fdt/fdt_common.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/fb/fbreg.h>
#include <dev/vt/vt.h>
+#include <dev/vt/colors/vt_termcolors.h>
-#include <arm/broadcom/bcm2835/bcm2835_mbox.h>
-#include <arm/broadcom/bcm2835/bcm2835_vcbus.h>
+#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
#include "fb_if.h"
#include "mbox_if.h"
-#define FB_WIDTH 640
-#define FB_HEIGHT 480
-#define FB_DEPTH 24
-
-struct bcm_fb_config {
- uint32_t xres;
- uint32_t yres;
- uint32_t vxres;
- uint32_t vyres;
- uint32_t pitch;
- uint32_t bpp;
- uint32_t xoffset;
- uint32_t yoffset;
- /* Filled by videocore */
- uint32_t base;
- uint32_t screen_size;
-};
+#define FB_DEPTH 24
struct bcmsc_softc {
- device_t dev;
struct fb_info *info;
- bus_dma_tag_t dma_tag;
- bus_dmamap_t dma_map;
- struct bcm_fb_config* fb_config;
- bus_addr_t fb_config_phys;
- struct intr_config_hook init_hook;
};
static int bcm_fb_probe(device_t);
static int bcm_fb_attach(device_t);
-static void bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg,
- int err);
-
-static void
-bcm_fb_init(void *arg)
-{
- volatile struct bcm_fb_config *fb_config;
- struct bcmsc_softc *sc;
- struct fb_info *info;
- phandle_t node;
- pcell_t cell;
- device_t mbox;
- device_t fbd;
- int err = 0;
-
- sc = arg;
- fb_config = sc->fb_config;
- node = ofw_bus_get_node(sc->dev);
-
- fb_config->xres = 0;
- fb_config->yres = 0;
- fb_config->bpp = 0;
- fb_config->vxres = 0;
- fb_config->vyres = 0;
- fb_config->xoffset = 0;
- fb_config->yoffset = 0;
- fb_config->base = 0;
- fb_config->pitch = 0;
- fb_config->screen_size = 0;
-
- if ((OF_getprop(node, "broadcom,width", &cell, sizeof(cell))) > 0)
- fb_config->xres = (int)fdt32_to_cpu(cell);
- if (fb_config->xres == 0)
- fb_config->xres = FB_WIDTH;
-
- if ((OF_getprop(node, "broadcom,height", &cell, sizeof(cell))) > 0)
- fb_config->yres = (uint32_t)fdt32_to_cpu(cell);
- if (fb_config->yres == 0)
- fb_config->yres = FB_HEIGHT;
-
- if ((OF_getprop(node, "broadcom,depth", &cell, sizeof(cell))) > 0)
- fb_config->bpp = (uint32_t)fdt32_to_cpu(cell);
- if (fb_config->bpp == 0)
- fb_config->bpp = FB_DEPTH;
-
- bus_dmamap_sync(sc->dma_tag, sc->dma_map,
- BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
-
- mbox = devclass_get_device(devclass_find("mbox"), 0);
- if (mbox) {
- MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_FB, sc->fb_config_phys);
- MBOX_READ(mbox, BCM2835_MBOX_CHAN_FB, &err);
- }
- bus_dmamap_sync(sc->dma_tag, sc->dma_map,
- BUS_DMASYNC_POSTREAD);
-
- if (fb_config->base != 0) {
- device_printf(sc->dev, "%dx%d(%dx%d@%d,%d) %dbpp\n",
- fb_config->xres, fb_config->yres,
- fb_config->vxres, fb_config->vyres,
- fb_config->xoffset, fb_config->yoffset,
- fb_config->bpp);
-
- device_printf(sc->dev, "pitch %d, base 0x%08x, screen_size %d\n",
- fb_config->pitch, fb_config->base,
- fb_config->screen_size);
-
- info = malloc(sizeof(struct fb_info), M_DEVBUF,
- M_WAITOK | M_ZERO);
- info->fb_name = device_get_nameunit(sc->dev);
- info->fb_vbase = (intptr_t)pmap_mapdev(fb_config->base,
- fb_config->screen_size);
- info->fb_pbase = fb_config->base;
- info->fb_size = fb_config->screen_size;
- info->fb_bpp = info->fb_depth = fb_config->bpp;
- info->fb_stride = fb_config->pitch;
- info->fb_width = fb_config->xres;
- info->fb_height = fb_config->yres;
-
- sc->info = info;
-
- 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");
- else if (device_probe_and_attach(fbd) != 0)
- device_printf(sc->dev, "Failed to attach fbd device\n");
- } else {
- device_printf(sc->dev, "Failed to set framebuffer info\n");
- }
-
- config_intrhook_disestablish(&sc->init_hook);
-}
static int
bcm_fb_probe(device_t dev)
@@ -214,66 +79,82 @@ bcm_fb_probe(device_t dev)
static int
bcm_fb_attach(device_t dev)
{
- struct bcmsc_softc *sc = device_get_softc(dev);
- int dma_size = sizeof(struct bcm_fb_config);
- int err;
-
- sc->dev = dev;
+ char bootargs[2048], *n, *p, *v;
+ device_t fbd;
+ int fbswap;
+ phandle_t chosen;
+ struct bcm2835_fb_config fb;
+ struct bcmsc_softc *sc;
+ struct fb_info *info;
- err = bus_dma_tag_create(
- bus_get_dma_tag(sc->dev),
- PAGE_SIZE, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- dma_size, 1, /* maxsize, nsegments */
- dma_size, 0, /* maxsegsize, flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->dma_tag);
+ sc = device_get_softc(dev);
+ memset(&fb, 0, sizeof(fb));
+ if (bcm2835_mbox_fb_get_w_h(dev, &fb) != 0)
+ return (ENXIO);
+ fb.bpp = FB_DEPTH;
+ if (bcm2835_mbox_fb_init(dev, &fb) != 0)
+ return (ENXIO);
- err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->fb_config, 0,
- &sc->dma_map);
- if (err) {
- device_printf(dev, "cannot allocate framebuffer\n");
- goto fail;
+ 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;
+
+ /* Newer firmware versions needs an inverted color palette. */
+ fbswap = 0;
+ chosen = OF_finddevice("/chosen");
+ if (chosen != 0 &&
+ OF_getprop(chosen, "bootargs", &bootargs, sizeof(bootargs)) > 0) {
+ p = bootargs;
+ while ((v = strsep(&p, " ")) != NULL) {
+ if (*v == '\0')
+ continue;
+ n = strsep(&v, "=");
+ if (strcmp(n, "bcm2708_fb.fbswap") == 0 && v != NULL)
+ if (*v == '1')
+ 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;
+ }
}
- err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->fb_config,
- dma_size, bcm_fb_dmamap_cb, &sc->fb_config_phys, BUS_DMA_NOWAIT);
-
- if (err) {
- device_printf(dev, "cannot load DMA map\n");
- goto fail;
+ 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);
}
- /*
- * We have to wait until interrupts are enabled.
- * Mailbox relies on it to get data from VideoCore
- */
- sc->init_hook.ich_func = bcm_fb_init;
- sc->init_hook.ich_arg = sc;
-
- if (config_intrhook_establish(&sc->init_hook) != 0) {
- device_printf(dev, "failed to establish intrhook\n");
- return (ENOMEM);
- }
+ 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);
return (0);
-
-fail:
- return (ENXIO);
-}
-
-static void
-bcm_fb_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
-{
- bus_addr_t *addr;
-
- if (err)
- return;
-
- addr = (bus_addr_t*)arg;
- *addr = PHYS_TO_VCBUS(segs[0].ds_addr);
}
static struct fb_info *
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
index af600ca..5940ad6 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox.c
@@ -318,6 +318,47 @@ bcm2835_mbox_init_dma(device_t dev, size_t len, bus_dma_tag_t *tag,
return (buf);
}
+static int
+bcm2835_mbox_err(device_t dev, bus_addr_t msg_phys, uint32_t resp_phys,
+ struct bcm2835_mbox_hdr *msg, size_t len)
+{
+ int idx;
+ struct bcm2835_mbox_tag_hdr *tag;
+ uint8_t *last;
+
+ if ((uint32_t)msg_phys != resp_phys) {
+ device_printf(dev, "response channel mismatch\n");
+ return (EIO);
+ }
+ if (msg->code != BCM2835_MBOX_CODE_RESP_SUCCESS) {
+ device_printf(dev, "mbox response error\n");
+ return (EIO);
+ }
+
+ /* Loop until the end tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)(msg + 1);
+ last = (uint8_t *)msg + len;
+ for (idx = 0; tag->tag != 0; idx++) {
+ if ((tag->val_len & BCM2835_MBOX_TAG_VAL_LEN_RESPONSE) == 0) {
+ device_printf(dev, "tag %d response error\n", idx);
+ return (EIO);
+ }
+ /* Clear the response bit. */
+ tag->val_len &= ~BCM2835_MBOX_TAG_VAL_LEN_RESPONSE;
+
+ /* Next tag. */
+ tag = (struct bcm2835_mbox_tag_hdr *)((uint8_t *)tag +
+ sizeof(*tag) + tag->val_buf_size);
+
+ if ((uint8_t *)tag > last) {
+ device_printf(dev, "mbox buffer size error\n");
+ return (EIO);
+ }
+ }
+
+ return (0);
+}
+
int
bcm2835_mbox_set_power_state(device_t dev, uint32_t device_id, boolean_t on)
{
@@ -413,3 +454,136 @@ bcm2835_mbox_get_clock_rate(device_t dev, uint32_t clock_id, uint32_t *hz)
return (0);
}
+
+int
+bcm2835_mbox_fb_get_w_h(device_t dev, struct bcm2835_fb_config *fb)
+{
+ device_t mbox;
+ int err;
+ bus_dma_tag_t msg_tag;
+ bus_dmamap_t msg_map;
+ bus_addr_t msg_phys;
+ struct msg_fb_get_w_h *msg;
+ uint32_t reg;
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL) {
+ device_printf(dev, "can't find mbox\n");
+ return (ENXIO);
+ }
+
+ /* Allocate memory for the message */
+ msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+ &msg_phys);
+ if (msg == NULL)
+ return (ENOMEM);
+
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, GET_PHYSICAL_W_H);
+ msg->physical_w_h.tag_hdr.val_len = 0;
+ BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, GET_VIRTUAL_W_H);
+ msg->virtual_w_h.tag_hdr.val_len = 0;
+ BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET);
+ msg->offset.tag_hdr.val_len = 0;
+ msg->end_tag = 0;
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE);
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &reg);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD);
+
+ err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg));
+ if (err == 0) {
+ fb->xres = msg->physical_w_h.body.resp.width;
+ fb->yres = msg->physical_w_h.body.resp.height;
+ fb->vxres = msg->virtual_w_h.body.resp.width;
+ fb->vyres = msg->virtual_w_h.body.resp.height;
+ fb->xoffset = msg->offset.body.resp.x;
+ fb->yoffset = msg->offset.body.resp.y;
+ }
+
+ bus_dmamap_unload(msg_tag, msg_map);
+ bus_dmamem_free(msg_tag, msg, msg_map);
+ bus_dma_tag_destroy(msg_tag);
+
+ return (err);
+}
+
+int
+bcm2835_mbox_fb_init(device_t dev, struct bcm2835_fb_config *fb)
+{
+ device_t mbox;
+ int err;
+ bus_dma_tag_t msg_tag;
+ bus_dmamap_t msg_map;
+ bus_addr_t msg_phys;
+ struct msg_fb_setup *msg;
+ uint32_t reg;
+
+ /* get mbox device */
+ mbox = devclass_get_device(devclass_find("mbox"), 0);
+ if (mbox == NULL) {
+ device_printf(dev, "can't find mbox\n");
+ return (ENXIO);
+ }
+
+ /* Allocate memory for the message */
+ msg = bcm2835_mbox_init_dma(dev, sizeof(*msg), &msg_tag, &msg_map,
+ &msg_phys);
+ if (msg == NULL)
+ return (ENOMEM);
+
+ memset(msg, 0, sizeof(*msg));
+ msg->hdr.buf_size = sizeof(*msg);
+ msg->hdr.code = BCM2835_MBOX_CODE_REQ;
+ BCM2835_MBOX_INIT_TAG(&msg->physical_w_h, SET_PHYSICAL_W_H);
+ msg->physical_w_h.body.req.width = fb->xres;
+ msg->physical_w_h.body.req.height = fb->yres;
+ BCM2835_MBOX_INIT_TAG(&msg->virtual_w_h, SET_VIRTUAL_W_H);
+ msg->virtual_w_h.body.req.width = fb->vxres;
+ msg->virtual_w_h.body.req.height = fb->vyres;
+ BCM2835_MBOX_INIT_TAG(&msg->offset, GET_VIRTUAL_OFFSET);
+ msg->offset.body.req.x = fb->xoffset;
+ msg->offset.body.req.y = fb->yoffset;
+ BCM2835_MBOX_INIT_TAG(&msg->depth, SET_DEPTH);
+ msg->depth.body.req.bpp = fb->bpp;
+ BCM2835_MBOX_INIT_TAG(&msg->alpha, SET_ALPHA_MODE);
+ msg->alpha.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED;
+ BCM2835_MBOX_INIT_TAG(&msg->buffer, ALLOCATE_BUFFER);
+ msg->buffer.body.req.alignment = PAGE_SIZE;
+ BCM2835_MBOX_INIT_TAG(&msg->pitch, GET_PITCH);
+ msg->end_tag = 0;
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREWRITE);
+ MBOX_WRITE(mbox, BCM2835_MBOX_CHAN_PROP, (uint32_t)msg_phys);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTWRITE);
+
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_PREREAD);
+ MBOX_READ(mbox, BCM2835_MBOX_CHAN_PROP, &reg);
+ bus_dmamap_sync(msg_tag, msg_map, BUS_DMASYNC_POSTREAD);
+
+ err = bcm2835_mbox_err(dev, msg_phys, reg, &msg->hdr, sizeof(*msg));
+ if (err == 0) {
+ fb->xres = msg->physical_w_h.body.resp.width;
+ fb->yres = msg->physical_w_h.body.resp.height;
+ fb->vxres = msg->virtual_w_h.body.resp.width;
+ fb->vyres = msg->virtual_w_h.body.resp.height;
+ fb->xoffset = msg->offset.body.resp.x;
+ fb->yoffset = msg->offset.body.resp.y;
+ fb->pitch = msg->pitch.body.resp.pitch;
+ fb->base = msg->buffer.body.resp.fb_address;
+ fb->size = msg->buffer.body.resp.fb_size;
+ }
+
+ bus_dmamap_unload(msg_tag, msg_map);
+ bus_dmamem_free(msg_tag, msg, msg_map);
+ bus_dma_tag_destroy(msg_tag);
+
+ return (err);
+}
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
index 76f2a16..a425f2a 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
+++ b/sys/arm/broadcom/bcm2835/bcm2835_mbox_prop.h
@@ -52,6 +52,12 @@ struct bcm2835_mbox_tag_hdr {
uint32_t val_len;
};
+#define BCM2835_MBOX_INIT_TAG(tag_, tagid_) do { \
+ (tag_)->tag_hdr.tag = BCM2835_MBOX_TAG_##tagid_; \
+ (tag_)->tag_hdr.val_buf_size = sizeof((tag_)->body); \
+ (tag_)->tag_hdr.val_len = sizeof((tag_)->body.req); \
+} while (0)
+
#define BCM2835_MBOX_POWER_ID_EMMC 0x00000000
#define BCM2835_MBOX_POWER_ID_UART0 0x00000001
#define BCM2835_MBOX_POWER_ID_UART1 0x00000002
@@ -322,4 +328,151 @@ struct msg_get_max_temperature {
uint32_t end_tag;
};
+#define BCM2835_MBOX_TAG_GET_PHYSICAL_W_H 0x00040003
+#define BCM2835_MBOX_TAG_SET_PHYSICAL_W_H 0x00048003
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_W_H 0x00040004
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_W_H 0x00048004
+
+struct bcm2835_mbox_tag_fb_w_h {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } req;
+ struct {
+ uint32_t width;
+ uint32_t height;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_DEPTH 0x00040005
+#define BCM2835_MBOX_TAG_SET_DEPTH 0x00048005
+
+struct bcm2835_mbox_tag_depth {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t bpp;
+ } req;
+ struct {
+ uint32_t bpp;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_ALPHA_MODE 0x00040007
+#define BCM2835_MBOX_TAG_SET_ALPHA_MODE 0x00048007
+
+#define BCM2835_MBOX_ALPHA_MODE_0_OPAQUE 0
+#define BCM2835_MBOX_ALPHA_MODE_0_TRANSPARENT 1
+#define BCM2835_MBOX_ALPHA_MODE_IGNORED 2
+
+struct bcm2835_mbox_tag_alpha_mode {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alpha;
+ } req;
+ struct {
+ uint32_t alpha;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_VIRTUAL_OFFSET 0x00040009
+#define BCM2835_MBOX_TAG_SET_VIRTUAL_OFFSET 0x00048009
+
+struct bcm2835_mbox_tag_virtual_offset {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } req;
+ struct {
+ uint32_t x;
+ uint32_t y;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_GET_PITCH 0x00040008
+
+struct bcm2835_mbox_tag_pitch {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ uint32_t pitch;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_ALLOCATE_BUFFER 0x00040001
+
+struct bcm2835_mbox_tag_allocate_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ uint32_t alignment;
+ } req;
+ struct {
+ uint32_t fb_address;
+ uint32_t fb_size;
+ } resp;
+ } body;
+};
+
+#define BCM2835_MBOX_TAG_RELEASE_BUFFER 0x00048001
+
+struct bcm2835_mbox_tag_release_buffer {
+ struct bcm2835_mbox_tag_hdr tag_hdr;
+ union {
+ struct {
+ } req;
+ struct {
+ } resp;
+ } body;
+};
+
+struct bcm2835_fb_config {
+ uint32_t xres;
+ uint32_t yres;
+ uint32_t vxres;
+ uint32_t vyres;
+ uint32_t xoffset;
+ uint32_t yoffset;
+ uint32_t bpp;
+ uint32_t pitch;
+ uint32_t base;
+ uint32_t size;
+};
+
+struct msg_fb_get_w_h {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ struct bcm2835_mbox_tag_fb_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_virtual_offset offset;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_get_w_h(device_t, struct bcm2835_fb_config *);
+
+struct msg_fb_setup {
+ struct bcm2835_mbox_hdr hdr;
+ struct bcm2835_mbox_tag_fb_w_h physical_w_h;
+ struct bcm2835_mbox_tag_fb_w_h virtual_w_h;
+ struct bcm2835_mbox_tag_virtual_offset offset;
+ struct bcm2835_mbox_tag_depth depth;
+ struct bcm2835_mbox_tag_alpha_mode alpha;
+ struct bcm2835_mbox_tag_allocate_buffer buffer;
+ struct bcm2835_mbox_tag_pitch pitch;
+ uint32_t end_tag;
+};
+
+int bcm2835_mbox_fb_init(device_t, struct bcm2835_fb_config *);
+
#endif /* _BCM2835_MBOX_PROP_H_ */
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
index 1024a48..e950ec6 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_sdhci.c
@@ -68,15 +68,8 @@ __FBSDID("$FreeBSD$");
#define dprintf(fmt, args...)
#endif
-/* DMA doesn't yet work with the bcm3826 */
-#ifdef SOC_BCM2836
-#define PIO_MODE 1
-#else
-#define PIO_MODE 0
-#endif
-
static int bcm2835_sdhci_hs = 1;
-static int bcm2835_sdhci_pio_mode = PIO_MODE;
+static int bcm2835_sdhci_pio_mode = 0;
TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs);
TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode);
diff --git a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
index cb871f2..7b79b1a 100644
--- a/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
+++ b/sys/arm/broadcom/bcm2835/bcm2835_vcbus.h
@@ -37,14 +37,20 @@
#define BCM2835_VCBUS_IO_BASE 0x7E000000
#define BCM2835_VCBUS_SDRAM_UNCACHED 0xC0000000
+#ifdef SOC_BCM2836
+#define BCM2835_ARM_IO_BASE 0x3f000000
+#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_UNCACHED
+#else
#define BCM2835_ARM_IO_BASE 0x20000000
-#define BCM2835_ARM_IO_SIZE 0x02000000
+#define BCM2835_VCBUS_SDRAM_BASE BCM2835_VCBUS_SDRAM_CACHED
+#endif
+#define BCM2835_ARM_IO_SIZE 0x01000000
/*
* Convert physical address to VC bus address. Should be used
* when submitting address over mailbox interface
*/
-#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_CACHED)
+#define PHYS_TO_VCBUS(pa) ((pa) + BCM2835_VCBUS_SDRAM_BASE)
/* Check whether pa bellong top IO window */
#define BCM2835_ARM_IS_IO(pa) (((pa) >= BCM2835_ARM_IO_BASE) && \
@@ -61,6 +67,6 @@
* when address is returned by VC over mailbox interface. e.g.
* framebuffer base
*/
-#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_CACHED)
+#define VCBUS_TO_PHYS(vca) ((vca) - BCM2835_VCBUS_SDRAM_BASE)
#endif /* _BCM2835_VCBUS_H_ */
OpenPOWER on IntegriCloud