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_buffer = 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 83 if (register_framebuffer(info) < 0) 84 goto fballoced; 85 86 platform_set_drvdata(device, info); 87 88 fb_info(info, "%s frame buffer device\n", info->fix.id); 89 90 return 0; 91 92 fballoced: 93 framebuffer_release(info); 94 95 none: 96 return ret; 97 } 98 99 static int cfag12864bfb_remove(struct platform_device *device) 100 { 101 struct fb_info *info = platform_get_drvdata(device); 102 103 if (info) { 104 unregister_framebuffer(info); 105 framebuffer_release(info); 106 } 107 108 return 0; 109 } 110 111 static struct platform_driver cfag12864bfb_driver = { 112 .probe = cfag12864bfb_probe, 113 .remove = cfag12864bfb_remove, 114 .driver = { 115 .name = CFAG12864BFB_NAME, 116 }, 117 }; 118 119 static struct platform_device *cfag12864bfb_device; 120 121 static int __init cfag12864bfb_init(void) 122 { 123 int ret = -EINVAL; 124 125 /* cfag12864b_init() must be called first */ 126 if (!cfag12864b_isinited()) { 127 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 128 "cfag12864b is not initialized\n"); 129 goto none; 130 } 131 132 if (cfag12864b_enable()) { 133 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 134 "can't enable cfag12864b refreshing (being used)\n"); 135 return -ENODEV; 136 } 137 138 ret = platform_driver_register(&cfag12864bfb_driver); 139 140 if (!ret) { 141 cfag12864bfb_device = 142 platform_device_alloc(CFAG12864BFB_NAME, 0); 143 144 if (cfag12864bfb_device) 145 ret = platform_device_add(cfag12864bfb_device); 146 else 147 ret = -ENOMEM; 148 149 if (ret) { 150 platform_device_put(cfag12864bfb_device); 151 platform_driver_unregister(&cfag12864bfb_driver); 152 } 153 } 154 155 none: 156 return ret; 157 } 158 159 static void __exit cfag12864bfb_exit(void) 160 { 161 platform_device_unregister(cfag12864bfb_device); 162 platform_driver_unregister(&cfag12864bfb_driver); 163 cfag12864b_disable(); 164 } 165 166 module_init(cfag12864bfb_init); 167 module_exit(cfag12864bfb_exit); 168 169 MODULE_LICENSE("GPL v2"); 170 MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>"); 171 MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); 172