From 184c61ddcedb6e1a52a059b02c028e4269722eb0 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Tue, 17 Dec 2013 22:51:13 +0100 Subject: [PATCH] Add Radeon Yeeloong 3A support. --- ChangeLog | 4 + grub-core/Makefile.core.def | 1 + grub-core/kern/mips/loongson/init.c | 1 + grub-core/loader/i386/linux.c | 1 + grub-core/video/radeon_yeeloong3a.c | 237 ++++++++++++++++++++++++++++ include/grub/video.h | 5 +- 6 files changed, 248 insertions(+), 1 deletion(-) create mode 100644 grub-core/video/radeon_yeeloong3a.c diff --git a/ChangeLog b/ChangeLog index 6314dfb36..e79697cc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2013-12-17 Vladimir Serbinenko + + Add Radeon Yeeloong 3A support. + 2013-12-17 Vladimir Serbinenko Add bonito 3A support. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 286ea98a4..f320981dc 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -248,6 +248,7 @@ kernel = { mips_loongson = video/sm712.c; mips_loongson = video/sis315pro.c; mips_loongson = video/radeon_fuloong2e.c; + mips_loongson = video/radeon_yeeloong3a.c; extra_dist = video/sm712_init.c; extra_dist = video/sis315_init.c; mips_loongson = commands/keylayouts.c; diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index b9cbcec27..65158702f 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -210,6 +210,7 @@ grub_machine_init (void) grub_video_sm712_init (); grub_video_sis315pro_init (); grub_video_radeon_fuloong2e_init (); + grub_video_radeon_yeeloong3a_init (); grub_font_init (); grub_gfxterm_init (); diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index a32c88e97..31fb91e2c 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -341,6 +341,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) case GRUB_VIDEO_DRIVER_CIRRUS: case GRUB_VIDEO_DRIVER_BOCHS: case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E: + case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A: case GRUB_VIDEO_DRIVER_IEEE1275: case GRUB_VIDEO_DRIVER_COREBOOT: /* Make gcc happy. */ diff --git a/grub-core/video/radeon_yeeloong3a.c b/grub-core/video/radeon_yeeloong3a.c new file mode 100644 index 000000000..52614feb6 --- /dev/null +++ b/grub-core/video/radeon_yeeloong3a.c @@ -0,0 +1,237 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010,2011,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GRUB_RADEON_YEELOONG3A_TOTAL_MEMORY_SPACE 1048576 + +static struct +{ + struct grub_video_mode_info mode_info; + struct grub_video_render_target *render_target; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +static grub_err_t +grub_video_radeon_yeeloong3a_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_radeon_yeeloong3a_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + GRUB_RADEON_YEELOONG3A_TOTAL_MEMORY_SPACE); + return grub_video_fb_fini (); +} + +#ifndef TEST +/* Helper for grub_video_radeon_yeeloong3a_setup. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + int *found = data; + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != 0x96151002) + return 0; + + *found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + framebuffer.dev = dev; + + return 1; +} +#endif + +static grub_err_t +grub_video_radeon_yeeloong3a_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) +{ + int depth; + grub_err_t err; + int found = 0; + +#ifndef TEST + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if ((width != 800 && width != 0) || (height != 600 && height != 0) + || (depth != 16 && depth != 0)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Only 640x480x16 is supported"); + + grub_pci_iterate (find_card, &found); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); +#endif + /* Fill mode info details. */ + framebuffer.mode_info.width = 800; + framebuffer.mode_info.height = 600; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = 16; + framebuffer.mode_info.bytes_per_pixel = 2; + framebuffer.mode_info.pitch = 800 * 2; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; +#ifndef TEST + framebuffer.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.mode_info); +#endif + + /* We can safely discard volatile attribute. */ +#ifndef TEST + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + GRUB_RADEON_YEELOONG3A_TOTAL_MEMORY_SPACE); + framebuffer.mapped = 1; +#endif + + /* Prevent garbage from appearing on the screen. */ + grub_memset (framebuffer.ptr, 0, + framebuffer.mode_info.height * framebuffer.mode_info.pitch); + +#ifndef TEST + err = grub_video_fb_create_render_target_from_pointer (&framebuffer + .render_target, + &framebuffer.mode_info, + framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); +#endif + return err; +} + +static grub_err_t +grub_video_radeon_yeeloong3a_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_radeon_yeeloong3a_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_radeon_yeeloong3a_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); + *framebuf = (char *) framebuffer.ptr; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + +static struct grub_video_adapter grub_video_radeon_yeeloong3a_adapter = + { + .name = "RADEON (Yeeloong3a) Video Driver", + .id = GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_radeon_yeeloong3a_video_init, + .fini = grub_video_radeon_yeeloong3a_video_fini, + .setup = grub_video_radeon_yeeloong3a_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_radeon_yeeloong3a_get_info_and_fini, + .set_palette = grub_video_fb_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .set_region = grub_video_fb_set_region, + .get_region = grub_video_fb_get_region, + .set_area_status = grub_video_fb_set_area_status, + .get_area_status = grub_video_fb_get_area_status, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_radeon_yeeloong3a_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_radeon_yeeloong3a_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_radeon_yeeloong3a) +{ + grub_video_register (&grub_video_radeon_yeeloong3a_adapter); +} + +GRUB_MOD_FINI(video_radeon_yeeloong3a) +{ + grub_video_unregister (&grub_video_radeon_yeeloong3a_adapter); +} diff --git a/include/grub/video.h b/include/grub/video.h index 14e7054e8..778012e08 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -291,7 +291,8 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_COREBOOT, GRUB_VIDEO_DRIVER_IEEE1275, GRUB_VIDEO_ADAPTER_CAPTURE, - GRUB_VIDEO_DRIVER_XEN + GRUB_VIDEO_DRIVER_XEN, + GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A } grub_video_driver_id_t; typedef enum grub_video_adapter_prio @@ -578,6 +579,8 @@ extern void grub_video_sis315pro_init (void); extern void grub_video_radeon_fuloong2e_init (void); extern void grub_video_sis315pro_fini (void); extern void grub_video_radeon_fuloong2e_fini (void); +extern void grub_video_radeon_yeeloong3a_init (void); +extern void grub_video_radeon_yeeloong3a_fini (void); #endif void