From b8f77ca4830f287e8378d98191d735baacbd1c7f Mon Sep 17 00:00:00 2001 From: Eric Holland Date: Sun, 5 Feb 2017 21:02:33 -0800 Subject: [PATCH] [bcm][gfx] gfx driver for raspberry pi --- platform/bcm28xx/include/platform/bcm28xx.h | 11 ++ platform/bcm28xx/include/platform/mailbox.h | 93 +++++++++++ platform/bcm28xx/mailbox.c | 171 ++++++++++++++++++++ platform/bcm28xx/platform.c | 4 + platform/bcm28xx/rules.mk | 4 +- project/rpi3-test.mk | 6 + 6 files changed, 288 insertions(+), 1 deletion(-) create mode 100644 platform/bcm28xx/include/platform/mailbox.h create mode 100644 platform/bcm28xx/mailbox.c diff --git a/platform/bcm28xx/include/platform/bcm28xx.h b/platform/bcm28xx/include/platform/bcm28xx.h index 058a02d6..a0d33b32 100644 --- a/platform/bcm28xx/include/platform/bcm28xx.h +++ b/platform/bcm28xx/include/platform/bcm28xx.h @@ -36,6 +36,9 @@ #error Unknown BCM28XX Variant #endif +#define BCM_SDRAM_BUS_ADDR_BASE_NO_L2 0xc0000000 +#define BCM_SDRAM_BUS_ADDR_BASE (BCM_SDRAM_BUS_ADDR_BASE_NO_L2) + /* pointer to 'local' peripherals at 0x40000000 */ #define BCM_LOCAL_PERIPH_BASE_VIRT (BCM_PERIPH_BASE_VIRT + 0x01000000) @@ -66,6 +69,14 @@ #define ARMCTRL_TIMER0_1_BASE (ARM_BASE + 0x400) #define ARMCTRL_0_SBM_BASE (ARM_BASE + 0x800) +/* Videocore (GPU) mailbox registers for core0 */ +#define ARM0_MAILBOX_BASE (ARM_BASE + 0x0880) +#define ARM0_MAILBOX_READ (ARM0_MAILBOX_BASE + 0x00) +#define ARM0_MAILBOX_PEEK (ARM0_MAILBOX_BASE + 0x10) +#define ARM0_MAILBOX_CONFIG (ARM0_MAILBOX_BASE + 0x1C) +#define ARM0_MAILBOX_STATUS (ARM0_MAILBOX_BASE + 0x18) +#define ARM0_MAILBOX_WRITE (ARM0_MAILBOX_BASE + 0x20) + #define ARM_LOCAL_BASE (BCM_LOCAL_PERIPH_BASE_VIRT) /* interrupts */ diff --git a/platform/bcm28xx/include/platform/mailbox.h b/platform/bcm28xx/include/platform/mailbox.h new file mode 100644 index 00000000..1f9b411d --- /dev/null +++ b/platform/bcm28xx/include/platform/mailbox.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2017 Eric Holland + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include + + +#define VCORE_MAILBOX_PHYSICAL_ADDRESS (ARMCTRL_0_SBM_BASE + 0x80) + + +#define VCORE_TAG_REQUEST 0x00000000 +#define VCORE_ENDTAG 0x00000000 + +#define VCORE_TAG_GET_FIRMWARE_REV 0x00000001 +#define VCORE_TAG_GET_FIRMWARE_REV_REQ_LEN 0x00000000 +#define VCORE_TAG_GET_FIRMWARE_REV_RSP_LEN 0x00000004 + +#define VCORE_MAILBOX_FULL 0x80000000 +#define VCORE_MAILBOX_EMPTY 0x40000000 + +#define VC_FB_CHANNEL 0x01 +#define ARM_TO_VC_CHANNEL 0x08 +#define VC_TO_ARM_CHANNEL 0x09 + +#define VCORE_SUCCESS 0 +#define VCORE_ERR_MBOX_FULL 1 +#define VCORE_ERR_MBOX_TIMEOUT 2 + +#define VCORE_READ_ATTEMPTS 0xffffffff + + +#define MAILBOX_READ 0 +#define MAILBOX_PEEK 2 +#define MAILBOX_CONDIG 4 +#define MAILBOX_STATUS 6 +#define MAILBOX_WRITE 8 + + +#define MAILBOX_FULL 0x80000000 +#define MAILBOX_EMPTY 0x40000000 + +#define MAX_MAILBOX_READ_ATTEMPTS 8 + +enum mailbox_channel { + ch_power = 0, + ch_framebuffer = 1, + ch_vuart = 2, + ch_vchic = 3, + ch_leds = 4, + ch_buttons = 5, + ch_touchscreen = 6, + ch_unused = 7, + ch_propertytags_tovc = 8, + ch_propertytags_fromvc = 9, +}; + +typedef struct { + uint32_t phys_width; //request + uint32_t phys_height; //request + uint32_t virt_width; //request + uint32_t virt_height; //request + uint32_t pitch; //response + uint32_t depth; //request + uint32_t virt_x_offs; //request + uint32_t virt_y_offs; //request + uint32_t fb_p; //response + uint32_t fb_size; //response +} fb_mbox_t; + +uint32_t get_vcore_framebuffer(fb_mbox_t * fb_mbox); +status_t init_framebuffer(void); +uint32_t _get_vcore_single(uint32_t tag, uint32_t req_len, uint8_t * rsp, uint32_t rsp_len); + diff --git a/platform/bcm28xx/mailbox.c b/platform/bcm28xx/mailbox.c new file mode 100644 index 00000000..d0db1ba5 --- /dev/null +++ b/platform/bcm28xx/mailbox.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017 Eric Holland + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +static volatile uint32_t* mailbox_regs = (uint32_t*)ARM0_MAILBOX_BASE; +static fb_mbox_t fb_desc __ALIGNED(16); + +static inline void* vc_bus_to_kvaddr(uint32_t bus_addr) { + return (paddr_to_kvaddr(bus_addr & 0x3fffffff)); +} + +static inline uint32_t kvaddr_to_vc_bus(addr_t kvaddr) { + return (uint32_t)((kvaddr & 0x3fffffff)+BCM_SDRAM_BUS_ADDR_BASE); +} + +#define MAILBOX_WAIT_TIMEOUT_US 500000 +#define MAILBOX_MAX_READ_ATTEMPTS 20 + +static status_t mailbox_write(const enum mailbox_channel ch, uint32_t value) { + value = value | ch; + + lk_time_t now = current_time(); + + // Wait for there to be space in the FIFO. + while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_FULL) { + if ( (now + MAILBOX_WAIT_TIMEOUT_US) < current_time()) { + return ERR_TIMED_OUT; + } + } + + // Write the value to the mailbox. + mailbox_regs[MAILBOX_WRITE] = value; + + return NO_ERROR; +} + +static status_t mailbox_read(enum mailbox_channel ch, uint32_t* result) { + uint32_t local_result = 0; + uint32_t attempts = 0; + + lk_time_t deadline; + + do { + deadline = current_time() + MAILBOX_WAIT_TIMEOUT_US; + while (mailbox_regs[MAILBOX_STATUS] & MAILBOX_EMPTY) { + if (current_time() > deadline) + return ERR_TIMED_OUT; + } + + local_result = mailbox_regs[MAILBOX_READ]; + + attempts++; + + } while ((((local_result)&0xF) != ch) && (attempts < MAILBOX_MAX_READ_ATTEMPTS)); + + *result = (local_result); + + return attempts < MAX_MAILBOX_READ_ATTEMPTS ? NO_ERROR : ERR_IO; +} + + +static status_t mailbox_get_framebuffer(fb_mbox_t* fb_desc) { + status_t ret = NO_ERROR; + + arch_clean_cache_range((addr_t)fb_desc,sizeof(fb_mbox_t)); + + ret = mailbox_write(ch_framebuffer, kvaddr_to_vc_bus((addr_t)fb_desc)); + if (ret != NO_ERROR) + return ret; + + uint32_t ack = 0x0; + ret = mailbox_read(ch_framebuffer, &ack); + if (ret != NO_ERROR) + return ret; + + arch_invalidate_cache_range((addr_t)fb_desc,sizeof(fb_mbox_t)); + + return ret; +} + +status_t init_framebuffer(void) { + + fb_desc.phys_width = 800; + fb_desc.phys_height = 480; + fb_desc.virt_width = 800; + fb_desc.virt_height = 480; + fb_desc.pitch = 0; + fb_desc.depth = 32; + fb_desc.virt_x_offs = 0; + fb_desc.virt_y_offs = 0; + fb_desc.fb_p = 0; + fb_desc.fb_size = 0; + + status_t ret = mailbox_get_framebuffer(&fb_desc); + + return ret; +} + +void dispflush(void) { + + //arch_clean_cache_range(fb_desc,sizeof(fb_mbox_t)); + +} + +/* LK display (lib/gfx.h) calls this function */ +status_t display_get_framebuffer(struct display_framebuffer *fb) +{ + // VideoCore returns 32-bit bus address, which needs to be converted to kernel virtual + fb->image.pixels = paddr_to_kvaddr(fb_desc.fb_p & 0x3fffffff); + + fb->format = DISPLAY_FORMAT_ARGB_8888; + fb->image.format = IMAGE_FORMAT_ARGB_8888; + fb->image.rowbytes = fb_desc.phys_width * fb_desc.depth/8; + + fb->image.width = fb_desc.phys_width; + fb->image.height = fb_desc.phys_height; + fb->image.stride = fb_desc.phys_width; + fb->flush = NULL; + + return NO_ERROR; +} + +status_t display_get_info(struct display_info *info) +{ + info->format = DISPLAY_FORMAT_ARGB_8888; + info->width = fb_desc.phys_width; + info->height = fb_desc.phys_height; + + return NO_ERROR; +} + +status_t display_present(struct display_image *image, uint starty, uint endy) +{ + return NO_ERROR; +} + + + diff --git a/platform/bcm28xx/platform.c b/platform/bcm28xx/platform.c index 1f5ab52c..e2139077 100644 --- a/platform/bcm28xx/platform.c +++ b/platform/bcm28xx/platform.c @@ -76,6 +76,7 @@ struct mmu_initial_mapping mmu_initial_mappings[] = { #include #include #include +#include /* initial memory mappings. parsed by start.S */ struct mmu_initial_mapping mmu_initial_mappings[] = { @@ -213,6 +214,9 @@ void platform_early_init(void) void platform_init(void) { uart_init(); +#if BCM2837 + init_framebuffer(); +#endif } void platform_dputc(char c) diff --git a/platform/bcm28xx/rules.mk b/platform/bcm28xx/rules.mk index 07361f67..cab755e3 100644 --- a/platform/bcm28xx/rules.mk +++ b/platform/bcm28xx/rules.mk @@ -20,6 +20,8 @@ MODULE_SRCS += \ $(LOCAL_DIR)/gpio.c \ $(LOCAL_DIR)/intc.c \ $(LOCAL_DIR)/platform.c \ + $(LOCAL_DIR)/mailbox.c \ + MEMBASE := 0x00000000 @@ -47,7 +49,7 @@ else ifeq ($(TARGET),rpi3) ARCH := arm64 ARM_CPU := cortex-a53 -KERNEL_LOAD_OFFSET := 0x00080000 +KERNEL_LOAD_OFFSET := 0x00080000 MEMSIZE ?= 0x40000000 # 1GB GLOBAL_DEFINES += \ diff --git a/project/rpi3-test.mk b/project/rpi3-test.mk index 4e7991bc..8f93d9b0 100644 --- a/project/rpi3-test.mk +++ b/project/rpi3-test.mk @@ -8,4 +8,10 @@ MODULES += \ app/tests \ lib/cksum \ lib/debugcommands \ + lib/gfx \ + lib/gfxconsole \ + + + +