Message ID | 20201225190048.776de55443fd4c953e797d8e@gmx.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [1/6] Revert "MIPS: Remove unused R4300 CPU support" | expand |
在 2020/12/26 上午1:00, Lauri Kasanen 写道: > I'm aware of the drm-fbdev resolution, but CONFIG_DRM adds 100kb, which > is a complete blocker on a system with 8mb RAM. Hi Lauri, AFAIK it's impossible to have a new fbdev driver. However you can workaround it by setup fb memory in platform code or even bootloader and register a simplefb platform driver. Thanks. - Jiaxun > > Signed-off-by: Lauri Kasanen <cand@gmx.com> > --- > arch/mips/n64/init.c | 10 +++ > drivers/video/fbdev/Kconfig | 9 ++ > drivers/video/fbdev/Makefile | 1 + > drivers/video/fbdev/n64rdp.c | 190 +++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 210 insertions(+) > create mode 100644 drivers/video/fbdev/n64rdp.c > > diff --git a/arch/mips/n64/init.c b/arch/mips/n64/init.c > index 6fb622d..635e9ef 100644 > --- a/arch/mips/n64/init.c > +++ b/arch/mips/n64/init.c > @@ -8,6 +8,7 @@ > #include <linux/ioport.h> > #include <linux/irq.h> > #include <linux/memblock.h> > +#include <linux/platform_device.h> > #include <linux/string.h> > > #include <asm/bootinfo.h> > @@ -46,6 +47,15 @@ void __init prom_free_prom_memory(void) > { > } > > +static int __init n64_platform_init(void) > +{ > + platform_device_register_simple("n64rdp", -1, NULL, 0); > + > + return 0; > +} > + > +arch_initcall(n64_platform_init); > + > void __init plat_mem_setup(void) > { > iomem_resource_init(); > diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig > index cfb7f56..4dde2c7 100644 > --- a/drivers/video/fbdev/Kconfig > +++ b/drivers/video/fbdev/Kconfig > @@ -2206,6 +2206,15 @@ config FB_SIMPLE > Configuration re: surface address, size, and format must be provided > through device tree, or plain old platform data. > > +config FB_N64RDP > + bool "Nintendo 64 RDP support" > + depends on (FB = y) && MIPS_N64 > + select FB_CFB_FILLRECT > + select FB_CFB_COPYAREA > + select FB_CFB_IMAGEBLIT > + help > + Driver for the N64's display. > + > config FB_SSD1307 > tristate "Solomon SSD1307 framebuffer support" > depends on FB && I2C > diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile > index 477b962..86f1e22 100644 > --- a/drivers/video/fbdev/Makefile > +++ b/drivers/video/fbdev/Makefile > @@ -129,6 +129,7 @@ obj-$(CONFIG_FB_MX3) += mx3fb.o > obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o > obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o > obj-$(CONFIG_FB_SIMPLE) += simplefb.o > +obj-$(CONFIG_FB_N64RDP) += n64rdp.o > > # the test framebuffer is last > obj-$(CONFIG_FB_VIRTUAL) += vfb.o > diff --git a/drivers/video/fbdev/n64rdp.c b/drivers/video/fbdev/n64rdp.c > new file mode 100644 > index 0000000..e5456b6 > --- /dev/null > +++ b/drivers/video/fbdev/n64rdp.c > @@ -0,0 +1,190 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * DRM driver for the N64's RDP > + * > + * Copyright (c) 2020 Lauri Kasanen > + * > + * Based on simplefb.c, which was: > + * Copyright (c) 2013, Stephen Warren > + * > + * Based on q40fb.c, which was: > + * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org> > + * > + * Also based on offb.c, which was: > + * Copyright (C) 1997 Geert Uytterhoeven > + * Copyright (C) 1996 Paul Mackerras > + */ > + > +#include <linux/dma-mapping.h> > +#include <linux/errno.h> > +#include <linux/fb.h> > +#include <linux/io.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/parser.h> > + > +#include <asm/addrspace.h> > + > +static const struct fb_fix_screeninfo n64rdp_fix = { > + .id = "default", > + .type = FB_TYPE_PACKED_PIXELS, > + .visual = FB_VISUAL_TRUECOLOR, > + .accel = FB_ACCEL_NONE, > +}; > + > +static const struct fb_var_screeninfo n64rdp_var = { > + .height = -1, > + .width = -1, > + .activate = FB_ACTIVATE_NOW, > + .vmode = FB_VMODE_NONINTERLACED, > +}; > + > +#define PSEUDO_PALETTE_SIZE 16 > + > +static int n64rdp_setcolreg(u_int regno, u_int red, u_int green, u_int blue, > + u_int transp, struct fb_info *info) > +{ > + u32 *pal = info->pseudo_palette; > + u32 cr = red >> (16 - info->var.red.length); > + u32 cg = green >> (16 - info->var.green.length); > + u32 cb = blue >> (16 - info->var.blue.length); > + u32 value; > + > + if (regno >= PSEUDO_PALETTE_SIZE) > + return -EINVAL; > + > + value = (cr << info->var.red.offset) | > + (cg << info->var.green.offset) | > + (cb << info->var.blue.offset); > + if (info->var.transp.length > 0) { > + u32 mask = (1 << info->var.transp.length) - 1; > + mask <<= info->var.transp.offset; > + value |= mask; > + } > + pal[regno] = value; > + > + return 0; > +} > + > +static const struct fb_ops n64rdp_ops = { > + .owner = THIS_MODULE, > + .fb_setcolreg = n64rdp_setcolreg, > + .fb_fillrect = cfb_fillrect, > + .fb_copyarea = cfb_copyarea, > + .fb_imageblit = cfb_imageblit, > +}; > + > +struct n64rdp_par { > + u32 palette[PSEUDO_PALETTE_SIZE]; > + dma_addr_t physaddr; > +}; > + > +#define REG_BASE ((u32 *) CKSEG1ADDR(0xA4400000)) > + > +static void n64rdp_write_reg(const u8 reg, const u32 value) > +{ > + __raw_writel(value, REG_BASE + reg); > +} > + > +#define W 320 > +#define H 240 > + > +static const u32 ntsc_320[] __initconst = { > + 0x00013212, 0x00000000, 0x00000140, 0x00000200, > + 0x00000000, 0x03e52239, 0x0000020d, 0x00000c15, > + 0x0c150c15, 0x006c02ec, 0x002501ff, 0x000e0204, > + 0x00000200, 0x00000400 > +}; > + > +static int __init n64rdp_probe(struct platform_device *pdev) > +{ > + int ret; > + u32 i; > + struct fb_info *info; > + struct n64rdp_par *par; > + dma_addr_t addr; > + > + info = framebuffer_alloc(sizeof(struct n64rdp_par), &pdev->dev); > + if (!info) > + return -ENOMEM; > + platform_set_drvdata(pdev, info); > + > + par = info->par; > + > + info->fix = n64rdp_fix; > + info->screen_base = dma_alloc_coherent(&pdev->dev, W * H * 2, &addr, > + GFP_DMA | GFP_KERNEL); > + if (!info->screen_base) > + return -ENOMEM; > + > + info->fix.smem_start = par->physaddr = addr; > + info->fix.smem_len = W * H * 2; > + info->fix.line_length = W * 2; > + > + info->var = n64rdp_var; > + info->var.xres = W; > + info->var.yres = H; > + info->var.xres_virtual = W; > + info->var.yres_virtual = H; > + info->var.bits_per_pixel = 16; > + info->var.red = (struct fb_bitfield) {11, 5}; > + info->var.green = (struct fb_bitfield) {6, 5}; > + info->var.blue = (struct fb_bitfield) {1, 5}; > + info->var.transp = (struct fb_bitfield) {0, 1}; > + > + info->apertures = alloc_apertures(1); > + if (!info->apertures) { > + ret = -ENOMEM; > + goto error_fb_release; > + } > + info->apertures->ranges[0].base = info->fix.smem_start; > + info->apertures->ranges[0].size = info->fix.smem_len; > + > + info->fbops = &n64rdp_ops; > + info->flags = FBINFO_DEFAULT; > + info->pseudo_palette = par->palette; > + > + dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", > + info->fix.smem_start, info->fix.smem_len, > + info->screen_base); > + > + ret = register_framebuffer(info); > + if (ret < 0) { > + dev_err(&pdev->dev, "Unable to register n64rdp: %d\n", ret); > + goto error_fb_release; > + } > + > + for (i = 0; i < ARRAY_SIZE(ntsc_320); i++) { > + if (i == 1) > + n64rdp_write_reg(i, par->physaddr); > + else > + n64rdp_write_reg(i, ntsc_320[i]); > + } > + > + return 0; > + > +error_fb_release: > + framebuffer_release(info); > + return ret; > +} > + > +static struct platform_driver n64rdp_driver = { > + .driver = { > + .name = "n64rdp", > + }, > +}; > + > +static int __init n64rdp_init(void) > +{ > + int ret; > + > + ret = platform_driver_probe(&n64rdp_driver, n64rdp_probe); > + > + return ret; > +} > + > +fs_initcall(n64rdp_init); > + > +MODULE_AUTHOR("Lauri Kasanen <cand@gmx.com>"); > +MODULE_DESCRIPTION("Driver for the N64's display"); > +MODULE_LICENSE("GPL v2"); > -- > 2.6.2 >
On Sat, 26 Dec 2020 11:20:36 +0800 Jiaxun Yang <jiaxun.yang@flygoat.com> wrote: > 在 2020/12/26 上午1:00, Lauri Kasanen 写道: > > I'm aware of the drm-fbdev resolution, but CONFIG_DRM adds 100kb, which > > is a complete blocker on a system with 8mb RAM. > > Hi Lauri, > > AFAIK it's impossible to have a new fbdev driver. > However you can workaround it by setup fb memory in platform code or even > bootloader and register a simplefb platform driver. It may be that way, but that would preclude adding acceleration (clears, blits...). With this driver, if someone finds it too slow, it'd be easy to hook up gpu accel. So let's try at least, given DRM is way too large. - Lauri
On Fri, Dec 25, 2020 at 07:00:48PM +0200, Lauri Kasanen wrote: > I'm aware of the drm-fbdev resolution, but CONFIG_DRM adds 100kb, which > is a complete blocker on a system with 8mb RAM. > > Signed-off-by: Lauri Kasanen <cand@gmx.com> > --- > arch/mips/n64/init.c | 10 +++ > drivers/video/fbdev/Kconfig | 9 ++ > drivers/video/fbdev/Makefile | 1 + > drivers/video/fbdev/n64rdp.c | 190 +++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 210 insertions(+) > create mode 100644 drivers/video/fbdev/n64rdp.c > > diff --git a/arch/mips/n64/init.c b/arch/mips/n64/init.c > index 6fb622d..635e9ef 100644 > --- a/arch/mips/n64/init.c > +++ b/arch/mips/n64/init.c > @@ -8,6 +8,7 @@ > #include <linux/ioport.h> > #include <linux/irq.h> > #include <linux/memblock.h> > +#include <linux/platform_device.h> > #include <linux/string.h> > > #include <asm/bootinfo.h> > @@ -46,6 +47,15 @@ void __init prom_free_prom_memory(void) > { > } > > +static int __init n64_platform_init(void) > +{ > + platform_device_register_simple("n64rdp", -1, NULL, 0); > + > + return 0; > +} > + > +arch_initcall(n64_platform_init); > + > void __init plat_mem_setup(void) > { > iomem_resource_init(); IMHO it would be better to add the platform device creatioasn to the MIPS patch. This way there is no dependeny when applying patches by different maintainers. Thomas.
Hi Thomas, Do I understand correctly that this is a "yes" to the "is it worth it to upstream a port for a platform this ancient"? You being the MIPS maintainer. - Lauri
On Mon, Dec 28, 2020 at 08:24:16PM +0200, Lauri Kasanen wrote: > Do I understand correctly that this is a "yes" to the "is it worth it > to upstream a port for a platform this ancient"? yes it is ;-) As long as hardware is available and someone cares I'll include support for ancient platforms. Thomas.
diff --git a/arch/mips/n64/init.c b/arch/mips/n64/init.c index 6fb622d..635e9ef 100644 --- a/arch/mips/n64/init.c +++ b/arch/mips/n64/init.c @@ -8,6 +8,7 @@ #include <linux/ioport.h> #include <linux/irq.h> #include <linux/memblock.h> +#include <linux/platform_device.h> #include <linux/string.h> #include <asm/bootinfo.h> @@ -46,6 +47,15 @@ void __init prom_free_prom_memory(void) { } +static int __init n64_platform_init(void) +{ + platform_device_register_simple("n64rdp", -1, NULL, 0); + + return 0; +} + +arch_initcall(n64_platform_init); + void __init plat_mem_setup(void) { iomem_resource_init(); diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index cfb7f56..4dde2c7 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -2206,6 +2206,15 @@ config FB_SIMPLE Configuration re: surface address, size, and format must be provided through device tree, or plain old platform data. +config FB_N64RDP + bool "Nintendo 64 RDP support" + depends on (FB = y) && MIPS_N64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Driver for the N64's display. + config FB_SSD1307 tristate "Solomon SSD1307 framebuffer support" depends on FB && I2C diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 477b962..86f1e22 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -129,6 +129,7 @@ obj-$(CONFIG_FB_MX3) += mx3fb.o obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o +obj-$(CONFIG_FB_N64RDP) += n64rdp.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/drivers/video/fbdev/n64rdp.c b/drivers/video/fbdev/n64rdp.c new file mode 100644 index 0000000..e5456b6 --- /dev/null +++ b/drivers/video/fbdev/n64rdp.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * DRM driver for the N64's RDP + * + * Copyright (c) 2020 Lauri Kasanen + * + * Based on simplefb.c, which was: + * Copyright (c) 2013, Stephen Warren + * + * Based on q40fb.c, which was: + * Copyright (C) 2001 Richard Zidlicky <rz@linux-m68k.org> + * + * Also based on offb.c, which was: + * Copyright (C) 1997 Geert Uytterhoeven + * Copyright (C) 1996 Paul Mackerras + */ + +#include <linux/dma-mapping.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/parser.h> + +#include <asm/addrspace.h> + +static const struct fb_fix_screeninfo n64rdp_fix = { + .id = "default", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .accel = FB_ACCEL_NONE, +}; + +static const struct fb_var_screeninfo n64rdp_var = { + .height = -1, + .width = -1, + .activate = FB_ACTIVATE_NOW, + .vmode = FB_VMODE_NONINTERLACED, +}; + +#define PSEUDO_PALETTE_SIZE 16 + +static int n64rdp_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + u32 *pal = info->pseudo_palette; + u32 cr = red >> (16 - info->var.red.length); + u32 cg = green >> (16 - info->var.green.length); + u32 cb = blue >> (16 - info->var.blue.length); + u32 value; + + if (regno >= PSEUDO_PALETTE_SIZE) + return -EINVAL; + + value = (cr << info->var.red.offset) | + (cg << info->var.green.offset) | + (cb << info->var.blue.offset); + if (info->var.transp.length > 0) { + u32 mask = (1 << info->var.transp.length) - 1; + mask <<= info->var.transp.offset; + value |= mask; + } + pal[regno] = value; + + return 0; +} + +static const struct fb_ops n64rdp_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = n64rdp_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +struct n64rdp_par { + u32 palette[PSEUDO_PALETTE_SIZE]; + dma_addr_t physaddr; +}; + +#define REG_BASE ((u32 *) CKSEG1ADDR(0xA4400000)) + +static void n64rdp_write_reg(const u8 reg, const u32 value) +{ + __raw_writel(value, REG_BASE + reg); +} + +#define W 320 +#define H 240 + +static const u32 ntsc_320[] __initconst = { + 0x00013212, 0x00000000, 0x00000140, 0x00000200, + 0x00000000, 0x03e52239, 0x0000020d, 0x00000c15, + 0x0c150c15, 0x006c02ec, 0x002501ff, 0x000e0204, + 0x00000200, 0x00000400 +}; + +static int __init n64rdp_probe(struct platform_device *pdev) +{ + int ret; + u32 i; + struct fb_info *info; + struct n64rdp_par *par; + dma_addr_t addr; + + info = framebuffer_alloc(sizeof(struct n64rdp_par), &pdev->dev); + if (!info) + return -ENOMEM; + platform_set_drvdata(pdev, info); + + par = info->par; + + info->fix = n64rdp_fix; + info->screen_base = dma_alloc_coherent(&pdev->dev, W * H * 2, &addr, + GFP_DMA | GFP_KERNEL); + if (!info->screen_base) + return -ENOMEM; + + info->fix.smem_start = par->physaddr = addr; + info->fix.smem_len = W * H * 2; + info->fix.line_length = W * 2; + + info->var = n64rdp_var; + info->var.xres = W; + info->var.yres = H; + info->var.xres_virtual = W; + info->var.yres_virtual = H; + info->var.bits_per_pixel = 16; + info->var.red = (struct fb_bitfield) {11, 5}; + info->var.green = (struct fb_bitfield) {6, 5}; + info->var.blue = (struct fb_bitfield) {1, 5}; + info->var.transp = (struct fb_bitfield) {0, 1}; + + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto error_fb_release; + } + info->apertures->ranges[0].base = info->fix.smem_start; + info->apertures->ranges[0].size = info->fix.smem_len; + + info->fbops = &n64rdp_ops; + info->flags = FBINFO_DEFAULT; + info->pseudo_palette = par->palette; + + dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", + info->fix.smem_start, info->fix.smem_len, + info->screen_base); + + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to register n64rdp: %d\n", ret); + goto error_fb_release; + } + + for (i = 0; i < ARRAY_SIZE(ntsc_320); i++) { + if (i == 1) + n64rdp_write_reg(i, par->physaddr); + else + n64rdp_write_reg(i, ntsc_320[i]); + } + + return 0; + +error_fb_release: + framebuffer_release(info); + return ret; +} + +static struct platform_driver n64rdp_driver = { + .driver = { + .name = "n64rdp", + }, +}; + +static int __init n64rdp_init(void) +{ + int ret; + + ret = platform_driver_probe(&n64rdp_driver, n64rdp_probe); + + return ret; +} + +fs_initcall(n64rdp_init); + +MODULE_AUTHOR("Lauri Kasanen <cand@gmx.com>"); +MODULE_DESCRIPTION("Driver for the N64's display"); +MODULE_LICENSE("GPL v2");
I'm aware of the drm-fbdev resolution, but CONFIG_DRM adds 100kb, which is a complete blocker on a system with 8mb RAM. Signed-off-by: Lauri Kasanen <cand@gmx.com> --- arch/mips/n64/init.c | 10 +++ drivers/video/fbdev/Kconfig | 9 ++ drivers/video/fbdev/Makefile | 1 + drivers/video/fbdev/n64rdp.c | 190 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+) create mode 100644 drivers/video/fbdev/n64rdp.c -- 2.6.2