0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <linux/module.h>
0031 #include <linux/kernel.h>
0032 #include <linux/errno.h>
0033 #include <linux/string.h>
0034 #include <linux/mm.h>
0035 #include <linux/vmalloc.h>
0036 #include <linux/delay.h>
0037 #include <linux/interrupt.h>
0038 #include <linux/fb.h>
0039 #include <linux/init.h>
0040 #include <linux/platform_device.h>
0041 #include <linux/list.h>
0042 #include <linux/uaccess.h>
0043
0044 #include <video/hecubafb.h>
0045
0046
0047 #define DPY_W 600
0048 #define DPY_H 800
0049
0050 static const struct fb_fix_screeninfo hecubafb_fix = {
0051 .id = "hecubafb",
0052 .type = FB_TYPE_PACKED_PIXELS,
0053 .visual = FB_VISUAL_MONO01,
0054 .xpanstep = 0,
0055 .ypanstep = 0,
0056 .ywrapstep = 0,
0057 .line_length = DPY_W,
0058 .accel = FB_ACCEL_NONE,
0059 };
0060
0061 static const struct fb_var_screeninfo hecubafb_var = {
0062 .xres = DPY_W,
0063 .yres = DPY_H,
0064 .xres_virtual = DPY_W,
0065 .yres_virtual = DPY_H,
0066 .bits_per_pixel = 1,
0067 .nonstd = 1,
0068 };
0069
0070
0071
0072 static void apollo_send_data(struct hecubafb_par *par, unsigned char data)
0073 {
0074
0075 par->board->set_data(par, data);
0076
0077
0078 par->board->set_ctl(par, HCB_DS_BIT, 0);
0079
0080
0081 par->board->wait_for_ack(par, 0);
0082
0083
0084 par->board->set_ctl(par, HCB_DS_BIT, 1);
0085
0086
0087 par->board->wait_for_ack(par, 1);
0088 }
0089
0090 static void apollo_send_command(struct hecubafb_par *par, unsigned char data)
0091 {
0092
0093 par->board->set_ctl(par, HCB_CD_BIT, 1);
0094
0095
0096 apollo_send_data(par, data);
0097
0098
0099 par->board->set_ctl(par, HCB_CD_BIT, 0);
0100 }
0101
0102 static void hecubafb_dpy_update(struct hecubafb_par *par)
0103 {
0104 int i;
0105 unsigned char *buf = (unsigned char __force *)par->info->screen_base;
0106
0107 apollo_send_command(par, APOLLO_START_NEW_IMG);
0108
0109 for (i=0; i < (DPY_W*DPY_H/8); i++) {
0110 apollo_send_data(par, *(buf++));
0111 }
0112
0113 apollo_send_command(par, APOLLO_STOP_IMG_DATA);
0114 apollo_send_command(par, APOLLO_DISPLAY_IMG);
0115 }
0116
0117
0118 static void hecubafb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist)
0119 {
0120 hecubafb_dpy_update(info->par);
0121 }
0122
0123 static void hecubafb_fillrect(struct fb_info *info,
0124 const struct fb_fillrect *rect)
0125 {
0126 struct hecubafb_par *par = info->par;
0127
0128 sys_fillrect(info, rect);
0129
0130 hecubafb_dpy_update(par);
0131 }
0132
0133 static void hecubafb_copyarea(struct fb_info *info,
0134 const struct fb_copyarea *area)
0135 {
0136 struct hecubafb_par *par = info->par;
0137
0138 sys_copyarea(info, area);
0139
0140 hecubafb_dpy_update(par);
0141 }
0142
0143 static void hecubafb_imageblit(struct fb_info *info,
0144 const struct fb_image *image)
0145 {
0146 struct hecubafb_par *par = info->par;
0147
0148 sys_imageblit(info, image);
0149
0150 hecubafb_dpy_update(par);
0151 }
0152
0153
0154
0155
0156
0157 static ssize_t hecubafb_write(struct fb_info *info, const char __user *buf,
0158 size_t count, loff_t *ppos)
0159 {
0160 struct hecubafb_par *par = info->par;
0161 unsigned long p = *ppos;
0162 void *dst;
0163 int err = 0;
0164 unsigned long total_size;
0165
0166 if (info->state != FBINFO_STATE_RUNNING)
0167 return -EPERM;
0168
0169 total_size = info->fix.smem_len;
0170
0171 if (p > total_size)
0172 return -EFBIG;
0173
0174 if (count > total_size) {
0175 err = -EFBIG;
0176 count = total_size;
0177 }
0178
0179 if (count + p > total_size) {
0180 if (!err)
0181 err = -ENOSPC;
0182
0183 count = total_size - p;
0184 }
0185
0186 dst = (void __force *) (info->screen_base + p);
0187
0188 if (copy_from_user(dst, buf, count))
0189 err = -EFAULT;
0190
0191 if (!err)
0192 *ppos += count;
0193
0194 hecubafb_dpy_update(par);
0195
0196 return (err) ? err : count;
0197 }
0198
0199 static const struct fb_ops hecubafb_ops = {
0200 .owner = THIS_MODULE,
0201 .fb_read = fb_sys_read,
0202 .fb_write = hecubafb_write,
0203 .fb_fillrect = hecubafb_fillrect,
0204 .fb_copyarea = hecubafb_copyarea,
0205 .fb_imageblit = hecubafb_imageblit,
0206 .fb_mmap = fb_deferred_io_mmap,
0207 };
0208
0209 static struct fb_deferred_io hecubafb_defio = {
0210 .delay = HZ,
0211 .deferred_io = hecubafb_dpy_deferred_io,
0212 };
0213
0214 static int hecubafb_probe(struct platform_device *dev)
0215 {
0216 struct fb_info *info;
0217 struct hecuba_board *board;
0218 int retval = -ENOMEM;
0219 int videomemorysize;
0220 unsigned char *videomemory;
0221 struct hecubafb_par *par;
0222
0223
0224 board = dev->dev.platform_data;
0225 if (!board)
0226 return -EINVAL;
0227
0228
0229 if (!try_module_get(board->owner))
0230 return -ENODEV;
0231
0232 videomemorysize = (DPY_W*DPY_H)/8;
0233
0234 videomemory = vzalloc(videomemorysize);
0235 if (!videomemory)
0236 goto err_videomem_alloc;
0237
0238 info = framebuffer_alloc(sizeof(struct hecubafb_par), &dev->dev);
0239 if (!info)
0240 goto err_fballoc;
0241
0242 info->screen_base = (char __force __iomem *)videomemory;
0243 info->fbops = &hecubafb_ops;
0244
0245 info->var = hecubafb_var;
0246 info->fix = hecubafb_fix;
0247 info->fix.smem_len = videomemorysize;
0248 par = info->par;
0249 par->info = info;
0250 par->board = board;
0251 par->send_command = apollo_send_command;
0252 par->send_data = apollo_send_data;
0253
0254 info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
0255
0256 info->fbdefio = &hecubafb_defio;
0257 fb_deferred_io_init(info);
0258
0259 retval = register_framebuffer(info);
0260 if (retval < 0)
0261 goto err_fbreg;
0262 platform_set_drvdata(dev, info);
0263
0264 fb_info(info, "Hecuba frame buffer device, using %dK of video memory\n",
0265 videomemorysize >> 10);
0266
0267
0268 retval = par->board->init(par);
0269 if (retval < 0)
0270 goto err_fbreg;
0271
0272 return 0;
0273 err_fbreg:
0274 framebuffer_release(info);
0275 err_fballoc:
0276 vfree(videomemory);
0277 err_videomem_alloc:
0278 module_put(board->owner);
0279 return retval;
0280 }
0281
0282 static int hecubafb_remove(struct platform_device *dev)
0283 {
0284 struct fb_info *info = platform_get_drvdata(dev);
0285
0286 if (info) {
0287 struct hecubafb_par *par = info->par;
0288 fb_deferred_io_cleanup(info);
0289 unregister_framebuffer(info);
0290 vfree((void __force *)info->screen_base);
0291 if (par->board->remove)
0292 par->board->remove(par);
0293 module_put(par->board->owner);
0294 framebuffer_release(info);
0295 }
0296 return 0;
0297 }
0298
0299 static struct platform_driver hecubafb_driver = {
0300 .probe = hecubafb_probe,
0301 .remove = hecubafb_remove,
0302 .driver = {
0303 .name = "hecubafb",
0304 },
0305 };
0306 module_platform_driver(hecubafb_driver);
0307
0308 MODULE_DESCRIPTION("fbdev driver for Hecuba/Apollo controller");
0309 MODULE_AUTHOR("Jaya Kumar");
0310 MODULE_LICENSE("GPL");