cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sunxvr1000.c (4133B)


      1/* sunxvr1000.c: Sun XVR-1000 fb driver for sparc64 systems
      2 *
      3 * License: GPL
      4 *
      5 * Copyright (C) 2010 David S. Miller (davem@davemloft.net)
      6 */
      7
      8#include <linux/kernel.h>
      9#include <linux/fb.h>
     10#include <linux/init.h>
     11#include <linux/of_device.h>
     12
     13struct gfb_info {
     14	struct fb_info		*info;
     15
     16	char __iomem		*fb_base;
     17	unsigned long		fb_base_phys;
     18
     19	struct device_node	*of_node;
     20
     21	unsigned int		width;
     22	unsigned int		height;
     23	unsigned int		depth;
     24	unsigned int		fb_size;
     25
     26	u32			pseudo_palette[16];
     27};
     28
     29static int gfb_get_props(struct gfb_info *gp)
     30{
     31	gp->width = of_getintprop_default(gp->of_node, "width", 0);
     32	gp->height = of_getintprop_default(gp->of_node, "height", 0);
     33	gp->depth = of_getintprop_default(gp->of_node, "depth", 32);
     34
     35	if (!gp->width || !gp->height) {
     36		printk(KERN_ERR "gfb: Critical properties missing for %pOF\n",
     37		       gp->of_node);
     38		return -EINVAL;
     39	}
     40
     41	return 0;
     42}
     43
     44static int gfb_setcolreg(unsigned regno,
     45			 unsigned red, unsigned green, unsigned blue,
     46			 unsigned transp, struct fb_info *info)
     47{
     48	u32 value;
     49
     50	if (regno < 16) {
     51		red >>= 8;
     52		green >>= 8;
     53		blue >>= 8;
     54
     55		value = (blue << 16) | (green << 8) | red;
     56		((u32 *)info->pseudo_palette)[regno] = value;
     57	}
     58
     59	return 0;
     60}
     61
     62static const struct fb_ops gfb_ops = {
     63	.owner			= THIS_MODULE,
     64	.fb_setcolreg		= gfb_setcolreg,
     65	.fb_fillrect		= cfb_fillrect,
     66	.fb_copyarea		= cfb_copyarea,
     67	.fb_imageblit		= cfb_imageblit,
     68};
     69
     70static int gfb_set_fbinfo(struct gfb_info *gp)
     71{
     72	struct fb_info *info = gp->info;
     73	struct fb_var_screeninfo *var = &info->var;
     74
     75	info->flags = FBINFO_DEFAULT;
     76	info->fbops = &gfb_ops;
     77	info->screen_base = gp->fb_base;
     78	info->screen_size = gp->fb_size;
     79
     80	info->pseudo_palette = gp->pseudo_palette;
     81
     82	/* Fill fix common fields */
     83	strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
     84        info->fix.smem_start = gp->fb_base_phys;
     85        info->fix.smem_len = gp->fb_size;
     86        info->fix.type = FB_TYPE_PACKED_PIXELS;
     87	if (gp->depth == 32 || gp->depth == 24)
     88		info->fix.visual = FB_VISUAL_TRUECOLOR;
     89	else
     90		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
     91
     92	var->xres = gp->width;
     93	var->yres = gp->height;
     94	var->xres_virtual = var->xres;
     95	var->yres_virtual = var->yres;
     96	var->bits_per_pixel = gp->depth;
     97
     98	var->red.offset = 0;
     99	var->red.length = 8;
    100	var->green.offset = 8;
    101	var->green.length = 8;
    102	var->blue.offset = 16;
    103	var->blue.length = 8;
    104	var->transp.offset = 0;
    105	var->transp.length = 0;
    106
    107	if (fb_alloc_cmap(&info->cmap, 256, 0)) {
    108		printk(KERN_ERR "gfb: Cannot allocate color map.\n");
    109		return -ENOMEM;
    110	}
    111
    112        return 0;
    113}
    114
    115static int gfb_probe(struct platform_device *op)
    116{
    117	struct device_node *dp = op->dev.of_node;
    118	struct fb_info *info;
    119	struct gfb_info *gp;
    120	int err;
    121
    122	info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev);
    123	if (!info) {
    124		err = -ENOMEM;
    125		goto err_out;
    126	}
    127
    128	gp = info->par;
    129	gp->info = info;
    130	gp->of_node = dp;
    131
    132	gp->fb_base_phys = op->resource[6].start;
    133
    134	err = gfb_get_props(gp);
    135	if (err)
    136		goto err_release_fb;
    137
    138	/* Framebuffer length is the same regardless of resolution. */
    139	info->fix.line_length = 16384;
    140	gp->fb_size = info->fix.line_length * gp->height;
    141
    142	gp->fb_base = of_ioremap(&op->resource[6], 0,
    143				 gp->fb_size, "gfb fb");
    144	if (!gp->fb_base) {
    145		err = -ENOMEM;
    146		goto err_release_fb;
    147	}
    148
    149	err = gfb_set_fbinfo(gp);
    150	if (err)
    151		goto err_unmap_fb;
    152
    153	printk("gfb: Found device at %pOF\n", dp);
    154
    155	err = register_framebuffer(info);
    156	if (err < 0) {
    157		printk(KERN_ERR "gfb: Could not register framebuffer %pOF\n",
    158		       dp);
    159		goto err_unmap_fb;
    160	}
    161
    162	dev_set_drvdata(&op->dev, info);
    163
    164	return 0;
    165
    166err_unmap_fb:
    167	of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size);
    168
    169err_release_fb:
    170        framebuffer_release(info);
    171
    172err_out:
    173	return err;
    174}
    175
    176static const struct of_device_id gfb_match[] = {
    177	{
    178		.name = "SUNW,gfb",
    179	},
    180	{},
    181};
    182
    183static struct platform_driver gfb_driver = {
    184	.probe		= gfb_probe,
    185	.driver = {
    186		.name			= "gfb",
    187		.of_match_table		= gfb_match,
    188		.suppress_bind_attrs	= true,
    189	},
    190};
    191
    192static int __init gfb_init(void)
    193{
    194	if (fb_get_options("gfb", NULL))
    195		return -ENODEV;
    196
    197	return platform_driver_register(&gfb_driver);
    198}
    199device_initcall(gfb_init);