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 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 55 56 return vm_map_pages_zero(vma, &pages, 1); 57 } 58 59 static const struct fb_ops cfag12864bfb_ops = { 60 .owner = THIS_MODULE, 61 __FB_DEFAULT_SYSMEM_OPS_RDWR, 62 __FB_DEFAULT_SYSMEM_OPS_DRAW, 63 .fb_mmap = cfag12864bfb_mmap, 64 }; 65 66 static int cfag12864bfb_probe(struct platform_device *device) 67 { 68 int ret = -EINVAL; 69 struct fb_info *info = framebuffer_alloc(0, &device->dev); 70 71 if (!info) 72 goto none; 73 74 info->flags = FBINFO_VIRTFB; 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 void 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 109 static struct platform_driver cfag12864bfb_driver = { 110 .probe = cfag12864bfb_probe, 111 .remove_new = cfag12864bfb_remove, 112 .driver = { 113 .name = CFAG12864BFB_NAME, 114 }, 115 }; 116 117 static struct platform_device *cfag12864bfb_device; 118 119 static int __init cfag12864bfb_init(void) 120 { 121 int ret = -EINVAL; 122 123 /* cfag12864b_init() must be called first */ 124 if (!cfag12864b_isinited()) { 125 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 126 "cfag12864b is not initialized\n"); 127 goto none; 128 } 129 130 if (cfag12864b_enable()) { 131 printk(KERN_ERR CFAG12864BFB_NAME ": ERROR: " 132 "can't enable cfag12864b refreshing (being used)\n"); 133 return -ENODEV; 134 } 135 136 ret = platform_driver_register(&cfag12864bfb_driver); 137 138 if (!ret) { 139 cfag12864bfb_device = 140 platform_device_alloc(CFAG12864BFB_NAME, 0); 141 142 if (cfag12864bfb_device) 143 ret = platform_device_add(cfag12864bfb_device); 144 else 145 ret = -ENOMEM; 146 147 if (ret) { 148 platform_device_put(cfag12864bfb_device); 149 platform_driver_unregister(&cfag12864bfb_driver); 150 } 151 } 152 153 none: 154 return ret; 155 } 156 157 static void __exit cfag12864bfb_exit(void) 158 { 159 platform_device_unregister(cfag12864bfb_device); 160 platform_driver_unregister(&cfag12864bfb_driver); 161 cfag12864b_disable(); 162 } 163 164 module_init(cfag12864bfb_init); 165 module_exit(cfag12864bfb_exit); 166 167 MODULE_LICENSE("GPL v2"); 168 MODULE_AUTHOR("Miguel Ojeda <ojeda@kernel.org>"); 169 MODULE_DESCRIPTION("cfag12864b LCD framebuffer driver"); 170