Module Name: src Committed By: macallan Date: Sun Sep 28 14:38:29 UTC 2014
Modified Files: src/sys/arch/evbarm/rpi: rpi_machdep.c vcprop.h Added Files: src/sys/arch/evbarm/rpi: vcprop_subr.c Log Message: add hardware cursor support To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 src/sys/arch/evbarm/rpi/rpi_machdep.c cvs rdiff -u -r1.12 -r1.13 src/sys/arch/evbarm/rpi/vcprop.h cvs rdiff -u -r0 -r1.1 src/sys/arch/evbarm/rpi/vcprop_subr.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbarm/rpi/rpi_machdep.c diff -u src/sys/arch/evbarm/rpi/rpi_machdep.c:1.47 src/sys/arch/evbarm/rpi/rpi_machdep.c:1.48 --- src/sys/arch/evbarm/rpi/rpi_machdep.c:1.47 Fri Sep 12 15:29:30 2014 +++ src/sys/arch/evbarm/rpi/rpi_machdep.c Sun Sep 28 14:38:29 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: rpi_machdep.c,v 1.47 2014/09/12 15:29:30 jmcneill Exp $ */ +/* $NetBSD: rpi_machdep.c,v 1.48 2014/09/28 14:38:29 macallan Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.47 2014/09/12 15:29:30 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.48 2014/09/28 14:38:29 macallan Exp $"); #include "opt_evbarm_boardtype.h" #include "opt_ddb.h" @@ -71,6 +71,7 @@ __KERNEL_RCSID(0, "$NetBSD: rpi_machdep. #include <arm/broadcom/bcm2835var.h> #include <arm/broadcom/bcm2835_pmvar.h> #include <arm/broadcom/bcm2835_mbox.h> +#include <arm/broadcom/bcm_amba.h> #include <evbarm/rpi/vcio.h> #include <evbarm/rpi/vcpm.h> @@ -376,16 +377,21 @@ static struct __aligned(16) { }, }; -int rpi_fb_set_video(int); -int rpi_video_on = WSDISPLAYIO_VIDEO_ON; - extern void bcmgenfb_set_console_dev(device_t dev); void bcmgenfb_set_ioctl(int(*)(void *, void *, u_long, void *, int, struct lwp *)); extern void bcmgenfb_ddb_trap_callback(int where); static int rpi_ioctl(void *, void *, u_long, void *, int, lwp_t *); +int rpi_video_on = WSDISPLAYIO_VIDEO_ON; +uint32_t hcursor = 0; +bus_addr_t pcursor = 0; +uint32_t *cmem = NULL; +int cursor_x = 0, cursor_y = 0, hot_x = 0, hot_y = 0, cursor_on = 0; +uint32_t cursor_cmap[4]; +uint8_t cursor_mask[8 * 64], cursor_bitmap[8 * 64]; #endif + static void rpi_bootparams(void) { @@ -731,8 +737,10 @@ rpi_fb_get_edid_mode(uint32_t *pwidth, u * - If "console=fb" is present, attach framebuffer to console. */ static bool -rpi_fb_init(prop_dictionary_t dict) +rpi_fb_init(prop_dictionary_t dict, void *aux) { + struct amba_attach_args *aaa = aux; + bus_space_handle_t hc; uint32_t width = 0, height = 0; uint32_t res; char *ptr; @@ -818,49 +826,105 @@ rpi_fb_init(prop_dictionary_t dict) prop_dictionary_set_uint32(dict, "wsdisplay_type", integer); } + hcursor = rpi_alloc_mem(64 * 64 * 4, PAGE_SIZE, + MEM_FLAG_L1_NONALLOCATING | MEM_FLAG_HINT_PERMALOCK); + pcursor = rpi_lock_mem(hcursor); +#ifdef RPI_IOCTL_DEBUG + printf("hcursor: %08x\n", hcursor); + printf("pcursor: %08x\n", (uint32_t)pcursor); + printf("fb: %08x\n", (uint32_t)vb_setfb.vbt_allocbuf.address); +#endif + if (bus_space_map(aaa->aaa_iot, pcursor, 64 * 64 * 4, + BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE, &hc) != 0) { + printf("couldn't map cursor memory\n"); + } else { + int i, j, k; + + cmem = bus_space_vaddr(aaa->aaa_iot, hc); + k = 0; + for (j = 0; j < 64; j++) { + for (i = 0; i < 64; i++) { + cmem[i + k] = + ((i & 8) ^ (j & 8)) ? 0xa0ff0000 : 0xa00000ff; + } + k += 64; + } + cpu_dcache_wb_range(cmem, 64 * 64 * 4); + rpi_fb_initcursor(pcursor, 0, 0); + } +#ifdef RPI_IOCTL_DEBUG + rpi_fb_movecursor(600, 400, 1); +#else + rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); +#endif return true; } -int -rpi_fb_set_video(int b) +static int +rpi_fb_do_cursor(struct wsdisplay_cursor *cur) { - int error; - uint32_t res; + int pos = 0; + int shape = 0; - /* - * might as well put it here since we need to re-init it every time - * and it's not like this is going to be called very often anyway - */ - struct __aligned(16) { - struct vcprop_buffer_hdr vb_hdr; - struct vcprop_tag_blankscreen vbt_blank; - struct vcprop_tag end; - } vb_setblank = - { - .vb_hdr = { - .vpb_len = sizeof(vb_setblank), - .vpb_rcode = VCPROP_PROCESS_REQUEST, - }, - .vbt_blank = { - .tag = { - .vpt_tag = VCPROPTAG_BLANK_SCREEN, - .vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank), - .vpt_rcode = VCPROPTAG_REQUEST, - }, - .state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON, - }, - .end = { - .vpt_tag = VCPROPTAG_NULL, - }, - }; + if (cur->which & WSDISPLAY_CURSOR_DOCUR) { + if (cursor_on != cur->enable) { + cursor_on = cur->enable; + pos = 1; + } + } + if (cur->which & WSDISPLAY_CURSOR_DOHOT) { - error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank, - sizeof(vb_setblank), &res); -#ifdef RPI_IOCTL_DEBUG - printf("%s: %d %d %d %08x %08x\n", __func__, b, - vb_setblank.vbt_blank.state, error, res, vb_setblank.vbt_blank.tag.vpt_rcode); -#endif - return (error == 0); + hot_x = cur->hot.x; + hot_y = cur->hot.y; + pos = 1; + shape = 1; + } + if (cur->which & WSDISPLAY_CURSOR_DOPOS) { + + cursor_x = cur->pos.x; + cursor_y = cur->pos.y; + pos = 1; + } + if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { + int i; + uint32_t val; + + for (i = 0; i < min(cur->cmap.count, 3); i++) { + val = (cur->cmap.red[i] << 16 ) | + (cur->cmap.green[i] << 8) | + (cur->cmap.blue[i] ) | + 0xff000000; + cursor_cmap[i + cur->cmap.index + 2] = val; + } + shape = 1; + } + if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { + + copyin(cur->mask, cursor_mask, 64 * 8); + copyin(cur->image, cursor_bitmap, 64 * 8); + shape = 1; + } + if (shape) { + int i, j, idx; + uint8_t mask; + + for (i = 0; i < 64 * 8; i++) { + mask = 0x01; + for (j = 0; j < 8; j++) { + idx = ((cursor_mask[i] & mask) ? 2 : 0) | + ((cursor_bitmap[i] & mask) ? 1 : 0); + cmem[i * 8 + j] = cursor_cmap[idx]; + mask = mask << 1; + } + } + /* just in case */ + cpu_dcache_wb_range(cmem, 64 * 64 * 4); + rpi_fb_initcursor(pcursor, hot_x, hot_y); + } + if (pos) { + rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); + } + return 0; } static int @@ -880,6 +944,37 @@ rpi_ioctl(void *v, void *vs, u_long cmd, case WSDISPLAYIO_GVIDEO: *(int *)data = rpi_video_on; return 0; + case WSDISPLAYIO_GCURPOS: + { + struct wsdisplay_curpos *cp = (void *)data; + + cp->x = cursor_x; + cp->y = cursor_y; + } + return 0; + case WSDISPLAYIO_SCURPOS: + { + struct wsdisplay_curpos *cp = (void *)data; + + cursor_x = cp->x; + cursor_y = cp->y; + rpi_fb_movecursor(cursor_x, cursor_y, cursor_on); + } + return 0; + case WSDISPLAYIO_GCURMAX: + { + struct wsdisplay_curpos *cp = (void *)data; + + cp->x = 64; + cp->y = 64; + } + return 0; + case WSDISPLAYIO_SCURSOR: + { + struct wsdisplay_cursor *cursor = (void *)data; + + return rpi_fb_do_cursor(cursor); + } default: return EPASSTHROUGH; } @@ -942,7 +1037,7 @@ rpi_device_register(device_t dev, void * db_trap_callback = bcmgenfb_ddb_trap_callback; #endif - if (rpi_fb_init(dict) == false) + if (rpi_fb_init(dict, aux) == false) return; if (get_bootconf_option(boot_args, "console", BOOTOPT_TYPE_STRING, &ptr) && strncmp(ptr, "fb", 2) == 0) { Index: src/sys/arch/evbarm/rpi/vcprop.h diff -u src/sys/arch/evbarm/rpi/vcprop.h:1.12 src/sys/arch/evbarm/rpi/vcprop.h:1.13 --- src/sys/arch/evbarm/rpi/vcprop.h:1.12 Sun Sep 28 12:57:22 2014 +++ src/sys/arch/evbarm/rpi/vcprop.h Sun Sep 28 14:38:29 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vcprop.h,v 1.12 2014/09/28 12:57:22 macallan Exp $ */ +/* $NetBSD: vcprop.h,v 1.13 2014/09/28 14:38:29 macallan Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. @@ -287,7 +287,7 @@ struct vcprop_tag_cursorinfo { struct vcprop_tag tag; uint32_t width; uint32_t height; - uint32_t __pad; /* unused */ + uint32_t format; uint32_t pixels; /* bus address in VC memory */ uint32_t hotspot_x; uint32_t hotspot_y; @@ -356,3 +356,13 @@ vcprop_tag_resplen(struct vcprop_tag *vp } #endif /* _EVBARM_RPI_VCPROP_H_ */ + +uint32_t rpi_alloc_mem(uint32_t, uint32_t, uint32_t); +bus_addr_t rpi_lock_mem(uint32_t); +int rpi_unlock_mem(uint32_t); +int rpi_release_mem(uint32_t); + +int rpi_fb_set_video(int); + +int rpi_fb_movecursor(int, int, int); +int rpi_fb_initcursor(bus_addr_t, int, int); Added files: Index: src/sys/arch/evbarm/rpi/vcprop_subr.c diff -u /dev/null src/sys/arch/evbarm/rpi/vcprop_subr.c:1.1 --- /dev/null Sun Sep 28 14:38:29 2014 +++ src/sys/arch/evbarm/rpi/vcprop_subr.c Sun Sep 28 14:38:29 2014 @@ -0,0 +1,343 @@ +/* $NetBSD: vcprop_subr.c,v 1.1 2014/09/28 14:38:29 macallan Exp $ */ + +/* + * Copyright (c) 2014 Michael Lorenz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Mailbox property interface wrapper functions + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/bus.h> + +#include <uvm/uvm_extern.h> + +#include <arm/arm32/machdep.h> + +#include <arm/broadcom/bcm2835reg.h> +#include <arm/broadcom/bcm2835var.h> +#include <arm/broadcom/bcm2835_pmvar.h> +#include <arm/broadcom/bcm2835_mbox.h> + +#include <evbarm/rpi/vcio.h> +#include <evbarm/rpi/vcpm.h> +#include <evbarm/rpi/vcprop.h> + +#include <evbarm/rpi/rpi.h> + +#include <dev/wscons/wsconsio.h> + +int +rpi_fb_set_video(int b) +{ + int error; + uint32_t res; + + /* + * might as well put it here since we need to re-init it every time + * and it's not like this is going to be called very often anyway + */ + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_blankscreen vbt_blank; + struct vcprop_tag end; + } vb_setblank = + { + .vb_hdr = { + .vpb_len = sizeof(vb_setblank), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_blank = { + .tag = { + .vpt_tag = VCPROPTAG_BLANK_SCREEN, + .vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank, + sizeof(vb_setblank), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %d %08x %08x\n", __func__, b, + vb_setblank.vbt_blank.state, error, res, + vb_setblank.vbt_blank.tag.vpt_rcode); +#endif + return (error == 0); +} + +uint32_t +rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags) +{ + int error; + uint32_t res; + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_allocmem vbt_am; + struct vcprop_tag end; + } vb_allocmem = + { + .vb_hdr = { + .vpb_len = sizeof(vb_allocmem), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_am = { + .tag = { + .vpt_tag = VCPROPTAG_ALLOCMEM, + .vpt_len = VCPROPTAG_LEN(vb_allocmem.vbt_am), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .size = size, + .align = align, + .flags = flags, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem, + sizeof(vb_allocmem), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %08x %08x\n", __func__, + vb_allocmem.vbt_am.size, error, res, + vb_allocmem.vbt_am.tag.vpt_rcode); +#endif + if (error == 0) + return vb_allocmem.vbt_am.size; + return 0; +} + +bus_addr_t +rpi_lock_mem(uint32_t handle) +{ + int error; + uint32_t res; + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_lockmem vbt_lm; + struct vcprop_tag end; + } vb_lockmem = + { + .vb_hdr = { + .vpb_len = sizeof(vb_lockmem), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_lm = { + .tag = { + .vpt_tag = VCPROPTAG_LOCKMEM, + .vpt_len = VCPROPTAG_LEN(vb_lockmem.vbt_lm), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .handle = handle, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem, + sizeof(vb_lockmem), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %08x %08x\n", __func__, + vb_lockmem.vbt_lm.handle, error, res, + vb_lockmem.vbt_lm.tag.vpt_rcode); +#endif + if (error == 0) + return (vb_lockmem.vbt_lm.handle /*& 0x3fffffff*/); + return 0; +} + +int +rpi_unlock_mem(uint32_t handle) +{ + int error; + uint32_t res; + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_lockmem vbt_lm; + struct vcprop_tag end; + } vb_unlockmem = + { + .vb_hdr = { + .vpb_len = sizeof(vb_unlockmem), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_lm = { + .tag = { + .vpt_tag = VCPROPTAG_UNLOCKMEM, + .vpt_len = VCPROPTAG_LEN(vb_unlockmem.vbt_lm), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .handle = handle, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem, + sizeof(vb_unlockmem), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %08x %08x\n", __func__, + vb_unlockmem.vbt_lm.handle, error, res, + vb_unlockmem.vbt_lm.tag.vpt_rcode); +#endif + return (error == 0); +} + +int +rpi_release_mem(uint32_t handle) +{ + int error; + uint32_t res; + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_lockmem vbt_lm; + struct vcprop_tag end; + } vb_releasemem = + { + .vb_hdr = { + .vpb_len = sizeof(vb_releasemem), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_lm = { + .tag = { + .vpt_tag = VCPROPTAG_RELEASEMEM, + .vpt_len = VCPROPTAG_LEN(vb_releasemem.vbt_lm), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .handle = handle, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem, + sizeof(vb_releasemem), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %08x %08x\n", __func__, + vb_releasemem.vbt_lm.handle, error, res, + vb_releasemem.vbt_lm.tag.vpt_rcode); +#endif + return (error == 0); +} + +int +rpi_fb_movecursor(int x, int y, int on) +{ + int error; + uint32_t res; + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_cursorstate vbt_cs; + struct vcprop_tag end; + } vb_cursorstate = + { + .vb_hdr = { + .vpb_len = sizeof(vb_cursorstate), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_cs = { + .tag = { + .vpt_tag = VCPROPTAG_SET_CURSOR_STATE, + .vpt_len = VCPROPTAG_LEN(vb_cursorstate.vbt_cs), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .enable = (on != 0) ? 1 : 0, + .x = x, + .y = y, + .flags = 1, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate, + sizeof(vb_cursorstate), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %08x %d %08x %08x\n", __func__, + vb_cursorstate.vbt_cs.enable, error, res, + vb_cursorstate.vbt_cs.tag.vpt_rcode); +#endif + return (error == 0); +} + +int +rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy) +{ + int error; + uint32_t res; + + + struct __aligned(16) { + struct vcprop_buffer_hdr vb_hdr; + struct vcprop_tag_cursorinfo vbt_ci; + struct vcprop_tag end; + } vb_cursorinfo = + { + .vb_hdr = { + .vpb_len = sizeof(vb_cursorinfo), + .vpb_rcode = VCPROP_PROCESS_REQUEST, + }, + .vbt_ci = { + .tag = { + .vpt_tag = VCPROPTAG_SET_CURSOR_INFO, + .vpt_len = VCPROPTAG_LEN(vb_cursorinfo.vbt_ci), + .vpt_rcode = VCPROPTAG_REQUEST, + }, + .width = 64, + .height = 64, + .format = 0, + .pixels = pixels, + .hotspot_x = hx, + .hotspot_y = hy, + }, + .end = { + .vpt_tag = VCPROPTAG_NULL, + }, + }; + + error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo, + sizeof(vb_cursorinfo), &res); +#ifdef RPI_IOCTL_DEBUG + printf("%s: %d %d %08x %08x\n", __func__, + vb_cursorinfo.vbt_ci.width, error, res, + vb_cursorinfo.vbt_ci.tag.vpt_rcode); +#endif + return (error == 0); +}