On Sat, May 21, 2016 at 6:54 AM, <ppisa4li...@pikron.com> wrote: > From: YANG Qiao <yangqiao0...@me.com> > > --- > c/src/lib/libbsp/arm/raspberrypi/Makefile.am | 2 + > c/src/lib/libbsp/arm/raspberrypi/console/fb.c | 385 > ++++++++++++++++++++++ > c/src/lib/libbsp/arm/raspberrypi/include/rpi-fb.h | 53 +++ > c/src/lib/libbsp/arm/raspberrypi/preinstall.am | 4 + > 4 files changed, 444 insertions(+) > create mode 100644 c/src/lib/libbsp/arm/raspberrypi/console/fb.c > create mode 100644 c/src/lib/libbsp/arm/raspberrypi/include/rpi-fb.h > > diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am > b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am > index 258f8a0..285da4f 100644 > --- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am > +++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am > @@ -50,6 +50,7 @@ include_bsp_HEADERS += include/i2c.h > include_bsp_HEADERS += include/spi.h > include_bsp_HEADERS += include/mailbox.h > include_bsp_HEADERS += include/vc.h > +include_bsp_HEADERS += include/rpi-fb.h > > include_libcpu_HEADERS = ../../../libcpu/arm/shared/include/cache_.h \ > ../../../libcpu/arm/shared/include/arm-cp15.h > @@ -114,6 +115,7 @@ libbsp_a_SOURCES += ../../shared/console_select.c > libbsp_a_SOURCES += ../../shared/console_write.c > libbsp_a_SOURCES += console/console-config.c > libbsp_a_SOURCES += console/usart.c > +libbsp_a_SOURCES += console/fb.c > > # Mailbox > libbsp_a_SOURCES += misc/mailbox.c > diff --git a/c/src/lib/libbsp/arm/raspberrypi/console/fb.c > b/c/src/lib/libbsp/arm/raspberrypi/console/fb.c > new file mode 100644 > index 0000000..ba285e7 > --- /dev/null > +++ b/c/src/lib/libbsp/arm/raspberrypi/console/fb.c > @@ -0,0 +1,385 @@ > +/** > + * @file > + * > + * @ingroup raspberrypi > + * > + * @brief framebuffer support. > + */ > + > +/* > + * Copyright (c) 2015 Yang Qiao > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * > + * http://www.rtems.org/license/LICENSE > + * > + */ > + > +#include <stdlib.h> > +#include <stdio.h> > +#include <errno.h> > +#include <sys/types.h> > + > +#include <bsp.h> > +#include <bsp/raspberrypi.h> > +#include <bsp/mailbox.h> > +#include <bsp/vc.h> > +#include <bsp/rpi-fb.h> > + > +#include <libcpu/arm-cp15.h> > + > +#include <rtems.h> > +#include <rtems/libio.h> > +#include <rtems/fb.h> > +#include <rtems/framebuffer.h> > +#include <rtems/score/atomic.h> > + > +#define SCREEN_WIDTH 1024 > +#define SCREEN_HEIGHT 768 > +#define BPP 32 > + > +/* flag to limit driver to protect against multiple opens */ > +static Atomic_Flag driver_mutex; > + > +/* > + * screen information for the driver (fb0). > + */ > + > +static struct fb_var_screeninfo fb_var_info = { > + .xres = SCREEN_WIDTH, > + .yres = SCREEN_HEIGHT, > + .bits_per_pixel = BPP > +}; > + > +static struct fb_fix_screeninfo fb_fix_info = { > + .smem_start = (void *) NULL, > + .smem_len = 0, > + .type = FB_TYPE_PACKED_PIXELS, > + .visual = FB_VISUAL_TRUECOLOR, > + .line_length = 0 > +}; > + > +typedef enum { > + NO_SUITABLE_MODE = -1, > + BAD_FORMAT = -2, > + AUTO_SELECT = -3, > + DONT_INIT = -4, > + NO_MODE_REQ = -5, > +} mode_err_ret_val; > + > +int raspberrypi_get_fix_screen_info( struct fb_fix_screeninfo *info ) > +{ > + *info = fb_fix_info; > + return 0; > +} > + > +int raspberrypi_get_var_screen_info( struct fb_var_screeninfo *info ) > +{ > + *info = fb_var_info; > + return 0; > +} > + > +/** > + * @brief Find mode given in string format. > + * > + * expected format > + * <resX>x<resY>[-<bpp>] > + * numbers <resX>, <resY> and <bpp> are decadic > + * > + * @param[out] fb_var_ptr pointer to variable mode part filled by function > + * @param[in] video_string string to be parsed > + * @retval video mode number to be set > + * @retval -1 no suitable mode found > + * @retval -2 bad format of the video_string > + * @retval -3 automatic mode selection requested > + * @retval -4 request to not initialize graphics > + * @retval -5 no mode requested/empty video string > + */ > + > +static int > +parse_mode_from_string(struct fb_var_screeninfo *fb_var_ptr, > + const char *video_string) > +{ > + const char* opt; > + char* endptr; > + uint32_t width; > + uint32_t height; > + uint32_t bpp = 0; > + > + opt = video_string; > + > + if (opt == NULL) > + return NO_MODE_REQ; > + if (strncmp(opt, "auto", 4) == 0) > + return AUTO_SELECT; > + if (strncmp(opt, "none", 4) == 0 || > + strncmp(opt, "off", 3) == 0) > + return DONT_INIT; > + > + width = strtol(opt, &endptr, 10); > + if (*endptr != 'x') > + { > + return BAD_FORMAT; > + } > + opt = endptr + 1; > + height = strtol(opt, &endptr, 10); > + switch (*endptr) > + { A minor issue is the inconsistent style in fb.c. mainly I saw that the opening { is sometimes on the next line and sometimes the same line as a conditional expression.
> + case '-': > + opt = endptr + 1; > + endptr = NULL; > + bpp = strtol(opt, &endptr, 10); > + if ((endptr == opt) || (endptr == NULL)) > + return BAD_FORMAT; > + if (*endptr && (*endptr != ' ')) > + return BAD_FORMAT; > + break; > + case ' ': > + case 0: > + break; > + default: > + return BAD_FORMAT; > + } > + > + fb_var_ptr->xres = width; > + fb_var_ptr->yres = height; > + if (bpp != 0) > + fb_var_ptr->bits_per_pixel = bpp; > + > + return 0; > +} > + > +static int > +find_mode_from_vc(void) > +{ > + bcm2835_get_display_size_entries entries; > + bcm2835_mailbox_get_display_size(&entries); > + unsigned int width = entries.width; > + unsigned int height = entries.height; > + > + if (width == 0 || height == 0) > + { > + fb_var_info.xres = SCREEN_WIDTH; > + fb_var_info.yres = SCREEN_HEIGHT; > + } > + else > + { > + fb_var_info.xres = width; > + fb_var_info.yres = height; > + } > + > + return 0; > +} > + > +static bool > +hdmi_is_present(void) > +{ > + bcm2835_get_display_size_entries entries; > + bcm2835_mailbox_get_display_size(&entries); > + if(entries.width == 0x290 && entries.height ==0x1A0 ) > + { > + return false; > + } > + else > + { > + return true; > + } > +} > + > +int > +raspberrypi_fb_init(void) > +{ > + int mode_from_cmdline; > + > + if (fb_fix_info.smem_start != NULL) > + { > + return RASPBERRYPI_FB_INIT_ALREADY_INITIALIZED; > + } > + > + if (hdmi_is_present() == false) > + { > + return RASPBERRYPI_FB_INIT_NO_DISPLAY; > + } > + > + mode_from_cmdline = parse_mode_from_string(&fb_var_info, > + > rpi_cmdline_get_arg("--video=")); > + switch (mode_from_cmdline) > + { > + case BAD_FORMAT: > + return RASPBERRYPI_FB_INIT_CMDLINE_BAD_FORMAT; > + case AUTO_SELECT: > + break; > + case DONT_INIT: > + return RASPBERRYPI_FB_INIT_CMDLINE_DONT_INIT; > + case NO_MODE_REQ: > + return RASPBERRYPI_FB_INIT_CMDLINE_NO_MODE_REQ; > + } > + > + if (mode_from_cmdline) > + { > + if(find_mode_from_vc()) > + return RASPBERRYPI_FB_INIT_MODE_PROBE_ERROR; > + } > + > + bcm2835_init_frame_buffer_entries init_frame_buffer_entries; > + init_frame_buffer_entries.xres = fb_var_info.xres; > + init_frame_buffer_entries.yres = fb_var_info.yres; > + init_frame_buffer_entries.xvirt = fb_var_info.xres; > + init_frame_buffer_entries.yvirt = fb_var_info.yres; > + init_frame_buffer_entries.depth = fb_var_info.bits_per_pixel; > + init_frame_buffer_entries.pixel_order = bcm2835_mailbox_pixel_order_rgb; > + init_frame_buffer_entries.alpha_mode = bcm2835_mailbox_alpha_mode_0_opaque; > + init_frame_buffer_entries.voffset_x = 0; > + init_frame_buffer_entries.voffset_y = 0; > + init_frame_buffer_entries.overscan_left = 0; > + init_frame_buffer_entries.overscan_right = 0; > + init_frame_buffer_entries.overscan_top = 0; > + init_frame_buffer_entries.overscan_bottom = 0; > + bcm2835_mailbox_init_frame_buffer(&init_frame_buffer_entries); > + > + bcm2835_get_pitch_entries get_pitch_entries; > + bcm2835_mailbox_get_pitch(&get_pitch_entries); > + > + fb_var_info.xres = init_frame_buffer_entries.xres; > + fb_var_info.yres = init_frame_buffer_entries.yres; > + fb_var_info.bits_per_pixel = init_frame_buffer_entries.depth; > + fb_fix_info.smem_start = (void *)init_frame_buffer_entries.base; > + fb_fix_info.smem_len = init_frame_buffer_entries.size; > + fb_fix_info.line_length = get_pitch_entries.pitch; > + > + if (fb_fix_info.smem_start == NULL) > + return RASPBERRYPI_FB_INIT_START_ADDR_UNKNOWN; > + > + arm_cp15_set_translation_table_entries((void *)fb_fix_info.smem_start, > + (void *)fb_fix_info.smem_start + > + fb_fix_info.smem_len, > + ARMV7_MMU_DATA_READ_WRITE_CACHED); > + > + return RASPBERRYPI_FB_INIT_OK; > +} > + > +/* > + * fbds device driver initialize entry point. > + */ > + > +rtems_device_driver > +frame_buffer_initialize (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + rtems_status_code status; > + > + /* register the devices */ > + status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0); > + if (status != RTEMS_SUCCESSFUL) { > + printk ("[!] error registering framebuffer\n"); > + rtems_fatal_error_occurred (status); > + } > + _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE); > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * fbds device driver open operation. > + */ > + > +rtems_device_driver > +frame_buffer_open (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) { > + printk( "FB_CIRRUS could not lock driver_mutex\n" ); > + return RTEMS_UNSATISFIED; > + } > + > + memset ((void *)fb_fix_info.smem_start, 0, fb_fix_info.smem_len); > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * fbds device driver close operation. > + */ > + > +rtems_device_driver > +frame_buffer_close (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + /* restore previous state. for VGA this means return to text mode. > + * leave out if graphics hardware has been initialized in > + * frame_buffer_initialize() */ > + _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE); > + memset ((void *)fb_fix_info.smem_start, 0, fb_fix_info.smem_len); I'm not sure about the mutex flag, but I suspect the memset should go before clearing the flag? > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * fbds device driver read operation. > + */ > + > +rtems_device_driver > +frame_buffer_read (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; > + rw_args->bytes_moved = > + ((rw_args->offset + rw_args->count) > fb_fix_info.smem_len ) ? > + (fb_fix_info.smem_len - rw_args->offset) :rw_args->count; > + memcpy( rw_args->buffer, > + (const void *) (fb_fix_info.smem_start + rw_args->offset), > + rw_args->bytes_moved); > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * fbds device driver write operation. > + */ > + > +rtems_device_driver > +frame_buffer_write (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg; > + rw_args->bytes_moved = > + ((rw_args->offset + rw_args->count) > fb_fix_info.smem_len ) ? > + (fb_fix_info.smem_len - rw_args->offset) : rw_args->count; > + memcpy( (void *) (fb_fix_info.smem_start + rw_args->offset), > + rw_args->buffer, > + rw_args->bytes_moved); > + return RTEMS_SUCCESSFUL; > +} > + > +/* > + * ioctl entry point. > + */ > + > +rtems_device_driver > +frame_buffer_control (rtems_device_major_number major, > + rtems_device_minor_number minor, void *arg) > +{ > + rtems_libio_ioctl_args_t *args = arg; > + > + /* XXX check minor */ > + > + switch (args->command) { > + case FBIOGET_VSCREENINFO: > + memcpy (args->buffer, &fb_var_info, sizeof (fb_var_info)); > + args->ioctl_return = 0; > + break; > + case FBIOGET_FSCREENINFO: > + memcpy (args->buffer, &fb_fix_info, sizeof (fb_fix_info)); > + args->ioctl_return = 0; > + break; > + case FBIOGETCMAP: > + args->ioctl_return = 0; > + break; > + case FBIOPUTCMAP: > + args->ioctl_return = 0; > + break; are these nops? should they return an "unimplemented" error? > + > + default: > + args->ioctl_return = 0; > + break; > + > + } > + return RTEMS_SUCCESSFUL; > +} > diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/rpi-fb.h > b/c/src/lib/libbsp/arm/raspberrypi/include/rpi-fb.h > new file mode 100644 > index 0000000..3d2e5e9 > --- /dev/null > +++ b/c/src/lib/libbsp/arm/raspberrypi/include/rpi-fb.h > @@ -0,0 +1,53 @@ > +/** > + * @file > + * > + * @ingroup raspberrypi_fb > + * > + * @brief framebuffer support and setup > + * > + */ > + > +/* > + * Copyright (c) 2015 Yang Qiao > + * > + * The license and distribution terms for this file may be > + * found in the file LICENSE in this distribution or at > + * > + * http://www.rtems.org/license/LICENSE > + * > + */ > + > +#ifndef LIBBSP_ARM_RASPBERRYPI_FB_H > +#define LIBBSP_ARM_RASPBERRYPI_FB_H > + > +#include <rtems/fb.h> > + > +/** > + * @defgroup raspberrypi_fb > + * > + * @ingroup arm_raspberrypi > + * > + * @brief Framebuffer support and setup > + * > + * @{ > + */ > + > +enum raspberrypi_fb_init_result { > + RASPBERRYPI_FB_INIT_OK = 0, > + RASPBERRYPI_FB_INIT_ALREADY_INITIALIZED = 1, > + RASPBERRYPI_FB_INIT_GENERIC_ERROR = -1, > + RASPBERRYPI_FB_INIT_NO_DISPLAY = -2, > + RASPBERRYPI_FB_INIT_CMDLINE_BAD_FORMAT = -3, > + RASPBERRYPI_FB_INIT_CMDLINE_DONT_INIT = -4, > + RASPBERRYPI_FB_INIT_CMDLINE_NO_MODE_REQ = -5, > + RASPBERRYPI_FB_INIT_MODE_PROBE_ERROR = -6, > + RASPBERRYPI_FB_INIT_START_ADDR_UNKNOWN = -7, > +}; > + > +int raspberrypi_fb_init(void); > +int raspberrypi_get_fix_screen_info( struct fb_fix_screeninfo *info ); > +int raspberrypi_get_var_screen_info( struct fb_var_screeninfo *info ); > + > +/** @} */ > + > +#endif /* LIBBSP_ARM_RASPBERRYPI_FB_H */ > diff --git a/c/src/lib/libbsp/arm/raspberrypi/preinstall.am > b/c/src/lib/libbsp/arm/raspberrypi/preinstall.am > index 979cba3..cbfa79f 100644 > --- a/c/src/lib/libbsp/arm/raspberrypi/preinstall.am > +++ b/c/src/lib/libbsp/arm/raspberrypi/preinstall.am > @@ -154,6 +154,10 @@ $(PROJECT_INCLUDE)/bsp/vc.h: include/vc.h > $(PROJECT_INCLUDE)/bsp/$(dirstamp) > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vc.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vc.h > > +$(PROJECT_INCLUDE)/bsp/rpi-fb.h: include/rpi-fb.h > $(PROJECT_INCLUDE)/bsp/$(dirstamp) > + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/rpi-fb.h > +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/rpi-fb.h > + > $(PROJECT_INCLUDE)/libcpu/cache_.h: > ../../../libcpu/arm/shared/include/cache_.h > $(PROJECT_INCLUDE)/libcpu/$(dirstamp) > $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/cache_.h > PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/cache_.h > -- > 1.9.1 > _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel