aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid/hid-picolcd.c
diff options
context:
space:
mode:
authorBruno Prémont <bonbons@linux-vserver.org>2010-06-28 16:30:29 -0400
committerJiri Kosina <jkosina@suse.cz>2010-07-12 12:07:35 -0400
commitb70884ff3a5314c2eb702f85599e722cccdd2f5b (patch)
treebc150912d161459336e9811909b7cbed4d4371a9 /drivers/hid/hid-picolcd.c
parenta7c9a0aa175aee8a66301264bff2a5ff014ca0e7 (diff)
HID: picolcd: Add minimal palette required by fbcon on 8bpp
Add a minimal palette so fbcon does not try to dereference a NULL point when fb is set to 8bpp. fbcon stores pixels the other way around in bytes for 1bpp than intially implemented, correct this. Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'drivers/hid/hid-picolcd.c')
-rw-r--r--drivers/hid/hid-picolcd.c62
1 files changed, 51 insertions, 11 deletions
diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
index 839a5ac0ad82..dc19501a786f 100644
--- a/drivers/hid/hid-picolcd.c
+++ b/drivers/hid/hid-picolcd.c
@@ -127,6 +127,26 @@ static const struct fb_var_screeninfo picolcdfb_var = {
127 .height = 26, 127 .height = 26,
128 .bits_per_pixel = 1, 128 .bits_per_pixel = 1,
129 .grayscale = 1, 129 .grayscale = 1,
130 .red = {
131 .offset = 0,
132 .length = 1,
133 .msb_right = 0,
134 },
135 .green = {
136 .offset = 0,
137 .length = 1,
138 .msb_right = 0,
139 },
140 .blue = {
141 .offset = 0,
142 .length = 1,
143 .msb_right = 0,
144 },
145 .transp = {
146 .offset = 0,
147 .length = 0,
148 .msb_right = 0,
149 },
130}; 150};
131#endif /* CONFIG_HID_PICOLCD_FB */ 151#endif /* CONFIG_HID_PICOLCD_FB */
132 152
@@ -188,6 +208,7 @@ struct picolcd_data {
188 /* Framebuffer stuff */ 208 /* Framebuffer stuff */
189 u8 fb_update_rate; 209 u8 fb_update_rate;
190 u8 fb_bpp; 210 u8 fb_bpp;
211 u8 fb_force;
191 u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */ 212 u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */
192 u8 *fb_bitmap; /* framebuffer */ 213 u8 *fb_bitmap; /* framebuffer */
193 struct fb_info *fb_info; 214 struct fb_info *fb_info;
@@ -346,7 +367,7 @@ static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp,
346 const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32; 367 const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32;
347 for (i = 0; i < 64; i++) { 368 for (i = 0; i < 64; i++) {
348 tdata[i] <<= 1; 369 tdata[i] <<= 1;
349 tdata[i] |= (bdata[i/8] >> (7 - i % 8)) & 0x01; 370 tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01;
350 } 371 }
351 } 372 }
352 } else if (bpp == 8) { 373 } else if (bpp == 8) {
@@ -399,13 +420,10 @@ static int picolcd_fb_reset(struct picolcd_data *data, int clear)
399 420
400 if (data->fb_bitmap) { 421 if (data->fb_bitmap) {
401 if (clear) { 422 if (clear) {
402 memset(data->fb_vbitmap, 0xff, PICOLCDFB_SIZE); 423 memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE);
403 memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp); 424 memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp);
404 } else {
405 /* invert 1 byte in each tile to force resend */
406 for (i = 0; i < PICOLCDFB_SIZE; i += 64)
407 data->fb_vbitmap[i] = ~data->fb_vbitmap[i];
408 } 425 }
426 data->fb_force = 1;
409 } 427 }
410 428
411 /* schedule first output of framebuffer */ 429 /* schedule first output of framebuffer */
@@ -440,7 +458,8 @@ static void picolcd_fb_update(struct picolcd_data *data)
440 for (chip = 0; chip < 4; chip++) 458 for (chip = 0; chip < 4; chip++)
441 for (tile = 0; tile < 8; tile++) 459 for (tile = 0; tile < 8; tile++)
442 if (picolcd_fb_update_tile(data->fb_vbitmap, 460 if (picolcd_fb_update_tile(data->fb_vbitmap,
443 data->fb_bitmap, data->fb_bpp, chip, tile)) { 461 data->fb_bitmap, data->fb_bpp, chip, tile) ||
462 data->fb_force) {
444 n += 2; 463 n += 2;
445 if (n >= HID_OUTPUT_FIFO_SIZE / 2) { 464 if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
446 usbhid_wait_io(data->hdev); 465 usbhid_wait_io(data->hdev);
@@ -448,6 +467,7 @@ static void picolcd_fb_update(struct picolcd_data *data)
448 } 467 }
449 picolcd_fb_send_tile(data->hdev, chip, tile); 468 picolcd_fb_send_tile(data->hdev, chip, tile);
450 } 469 }
470 data->fb_force = false;
451 if (n) 471 if (n)
452 usbhid_wait_io(data->hdev); 472 usbhid_wait_io(data->hdev);
453} 473}
@@ -526,10 +546,17 @@ static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *i
526 /* only allow 1/8 bit depth (8-bit is grayscale) */ 546 /* only allow 1/8 bit depth (8-bit is grayscale) */
527 *var = picolcdfb_var; 547 *var = picolcdfb_var;
528 var->activate = activate; 548 var->activate = activate;
529 if (bpp >= 8) 549 if (bpp >= 8) {
530 var->bits_per_pixel = 8; 550 var->bits_per_pixel = 8;
531 else 551 var->red.length = 8;
552 var->green.length = 8;
553 var->blue.length = 8;
554 } else {
532 var->bits_per_pixel = 1; 555 var->bits_per_pixel = 1;
556 var->red.length = 1;
557 var->green.length = 1;
558 var->blue.length = 1;
559 }
533 return 0; 560 return 0;
534} 561}
535 562
@@ -660,9 +687,10 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)
660{ 687{
661 struct device *dev = &data->hdev->dev; 688 struct device *dev = &data->hdev->dev;
662 struct fb_info *info = NULL; 689 struct fb_info *info = NULL;
663 int error = -ENOMEM; 690 int i, error = -ENOMEM;
664 u8 *fb_vbitmap = NULL; 691 u8 *fb_vbitmap = NULL;
665 u8 *fb_bitmap = NULL; 692 u8 *fb_bitmap = NULL;
693 u32 *palette;
666 694
667 fb_bitmap = vmalloc(PICOLCDFB_SIZE*picolcdfb_var.bits_per_pixel); 695 fb_bitmap = vmalloc(PICOLCDFB_SIZE*picolcdfb_var.bits_per_pixel);
668 if (fb_bitmap == NULL) { 696 if (fb_bitmap == NULL) {
@@ -678,12 +706,23 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)
678 706
679 data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT; 707 data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
680 data->fb_defio = picolcd_fb_defio; 708 data->fb_defio = picolcd_fb_defio;
681 info = framebuffer_alloc(0, dev); 709 /* The extra memory is:
710 * - struct picolcd_fb_cleanup_item
711 * - u32 for ref_count
712 * - 256*u32 for pseudo_palette
713 */
714 info = framebuffer_alloc(257 * sizeof(u32), dev);
682 if (info == NULL) { 715 if (info == NULL) {
683 dev_err(dev, "failed to allocate a framebuffer\n"); 716 dev_err(dev, "failed to allocate a framebuffer\n");
684 goto err_nomem; 717 goto err_nomem;
685 } 718 }
686 719
720 palette = info->par;
721 *palette = 1;
722 palette++;
723 for (i = 0; i < 256; i++)
724 palette[i] = i > 0 && i < 16 ? 0xff : 0;
725 info->pseudo_palette = palette;
687 info->fbdefio = &data->fb_defio; 726 info->fbdefio = &data->fb_defio;
688 info->screen_base = (char __force __iomem *)fb_bitmap; 727 info->screen_base = (char __force __iomem *)fb_bitmap;
689 info->fbops = &picolcdfb_ops; 728 info->fbops = &picolcdfb_ops;
@@ -715,6 +754,7 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)
715 goto err_sysfs; 754 goto err_sysfs;
716 } 755 }
717 /* schedule first output of framebuffer */ 756 /* schedule first output of framebuffer */
757 data->fb_force = 1;
718 schedule_delayed_work(&info->deferred_work, 0); 758 schedule_delayed_work(&info->deferred_work, 0);
719 return 0; 759 return 0;
720 760