1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Filename: cfag12864bfb.c 4 * Version: 0.1.0 5 * Description: cfag12864b LCD framebuffer driver 6 * Depends: cfag12864b 7 * 8 * Author: Copyright (C) Miguel Ojeda <ojeda@kernel.org> 9 * Date: 2006-10-31 10 */ 11 12 #include <linux/init.h> 13 #include <linux/module.h> 14 #include <linux/kernel.h> 15 #include <linux/errno.h> 16 #include <linux/fb.h> 17 #include <linux/mm.h> 18 #include <linux/platform_device.h> 19 #include <linux/cfag12864b.h> 20 21 #define CFAG12864BFB_NAME "cfag12864bfb" 22 23 static const struct fb_fix_screeninfo cfag12864bfb_fix = { 24 .id = "cfag12864b", 25 .type = FB_TYPE_PACKED_PIXELS, 26 .visual = FB_VISUAL_MONO10, 27 .xpanstep = 0, 28 .ypanstep = 0, 29 .ywrapstep = 0, 30 .line_length = CFAG12864B_WIDTH / 8, 31 .accel = FB_ACCEL_NONE, 32 }; 33 34 static const struct fb_var_screeninfo cfag12864bfb_var = { 35 .xres = CFAG12864B_WIDTH, 36 .yres = CFAG12864B_HEIGHT, 37 .xres_virtual = CFAG12864B_WIDTH, 38 .yres_virtual = CFAG12864B_HEIGHT, 39 .bits_per_pixel = 1, 40 .red = { 0, 1, 0 }, 41 .green = { 0, 1, 0 }, 42 .blue = { 0, 1, 0 }, 43 .left_margin = 0, 44 .right_margin = 0, 45 .upper_margin = 0, 46 .lower_margin = 0, 47 .vmode = FB_VMODE_NONINTERLACED, 48 }; 49 50 static int cfag12864bfb_mmap(struct fb_info *info, struct vm_area_struct *vma) 51 { 52 struct page *pages = virt_to_page(cfag12864b_buffer); 53 54 return vm_map_pages_zero(vma, &pages, 1); 55 } 56 57 static const struct fb_ops cfag12864bfb_ops = { 58 .owner = THIS_MODULE, 59 .fb_read = fb_sys_read, 60 .fb_write = fb_sys_write, 61 .fb_fillrect = sys_fillrect, 62 .fb_copyarea = sys_copyarea, 63 .fb_imageblit = sys_imageblit, 64 .fb_mmap = cfag12864bfb_mmap, 65 }; 66 67 static int cfag12864bfb_probe(struct platform_device *device) 68 { 69 int ret = -EINVAL; 70 struct fb_info *info = framebuffer_alloc(0, &device->dev); 71 72 if (!info) 73 goto none; 74 75 info->screen_base = (char __iomem *) cfag12864b_buffer; 76 info->screen_size = CFAG12864B_SIZE; 77 info->fbops = &cfag12864bfb_ops; 78 info->fix = cfag12864bfb_fix; 79 info->var = cfag12864bfb_var; 80 info->pseudo_palette = NULL; 81 info->par = NULL; 82 info->flags = FBINFO_FLAG_DEFAULT; 83 84 if (register_framebuffer(info) < 0) 85 goto fballoced; 86 87 platform_set_drvdata(device, info); 88 89 fb_info(info, "%s frame buffer device\n", info->fix.id); 90 91 return 0; 92 93 fballoced: 94 framebuffer_release(info); 95 96 none: 97 return ret; 98 } 99 100 static int cfag12864bfb_remove(struct platform_device *device) 101 { 102 struct fb_info *info = platform_get_drvdata(device); 103 104 if (info) { 105 unregister_framebuffer(info); 106 framebuffer_release(info); 107 } 108 109 return 0; 110 } 111 112 static struct platform_driver cfag12864bfb_driver = { 113 .probe = cfag12864bfb_probe, 114 .remove = cfag12864bfb_remove, 115 .driver = { 116 .name = CFAG12864BFB_NAME, 117 }, 118 }; 119 120 static struct platform_device *cfag12864bfb_device; 121 122 static int __init cfag12864bfb_init(void) 123 { 124 int ret = -EINVAL; 125 126 /* cfag12864b_init() must be called first */ 127 if (!cfag12864b_isinited()) { 128 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 129 "cfag12864b is not initialized\n"); 130 goto none; 131 } 132 133 if (cfag12864b_enable()) { 134 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 135 "can't enable cfag12864b refreshing (being used)\n"); 136 return -ENODEV; 137 } 138 139 ret = platform_driver_register(&cfag12864bfb_driver); 140 141 if (!ret) { 142 cfag12864bfb_device = 143 platform_device_alloc(CFAG12864BFB_NAME, 0); 144 145 if (cfag12864bfb_device) 146 ret = platform_device_add(cfag12864bfb_device); 147 else 148 ret = -ENOMEM; 149 150 if (ret) { 151 platform_device_put(cfag12864bfb_device); 152 platform_driver_unregister(&cfag12864bfb_driver); 153 } 154 } 155 156 none: 157 return ret; 158 } 159 160 static void __exit cfag12864bfb_exit(void) 161 { 162 platform_device_unregister(cfag12864bfb_device); 163 platform_driver_unregister(&cfag12864bfb_driver); 164 cfag12864b_disable(); 165 } 166 167 module_init(cfag12864bfb_init); 168 module_exit(cfag12864bfb_exit); 169 170 MODULE_LICENSE("GPL v2"); 171 MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>"); 172 MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); 173