lkml.org 
[lkml]   [2010]   [Jun]   [28]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH 2/4] 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>
    ---
    drivers/hid/hid-picolcd.c | 62 +++++++++++++++++++++++++++++++++++++--------
    1 files changed, 51 insertions(+), 11 deletions(-)

    diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c
    index 883d720..ac7aece 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 = {
    .height = 26,
    .bits_per_pixel = 1,
    .grayscale = 1,
    + .red = {
    + .offset = 0,
    + .length = 1,
    + .msb_right = 0,
    + },
    + .green = {
    + .offset = 0,
    + .length = 1,
    + .msb_right = 0,
    + },
    + .blue = {
    + .offset = 0,
    + .length = 1,
    + .msb_right = 0,
    + },
    + .transp = {
    + .offset = 0,
    + .length = 0,
    + .msb_right = 0,
    + },
    };
    #endif /* CONFIG_HID_PICOLCD_FB */

    @@ -188,6 +208,7 @@ struct picolcd_data {
    /* Framebuffer stuff */
    u8 fb_update_rate;
    u8 fb_bpp;
    + u8 fb_force;
    u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */
    u8 *fb_bitmap; /* framebuffer */
    struct fb_info *fb_info;
    @@ -346,7 +367,7 @@ static int picolcd_fb_update_tile(u8 *vbitmap, const u8 *bitmap, int bpp,
    const u8 *bdata = bitmap + tile * 256 + chip * 8 + b * 32;
    for (i = 0; i < 64; i++) {
    tdata[i] <<= 1;
    - tdata[i] |= (bdata[i/8] >> (7 - i % 8)) & 0x01;
    + tdata[i] |= (bdata[i/8] >> (i % 8)) & 0x01;
    }
    }
    } else if (bpp == 8) {
    @@ -399,13 +420,10 @@ static int picolcd_fb_reset(struct picolcd_data *data, int clear)

    if (data->fb_bitmap) {
    if (clear) {
    - memset(data->fb_vbitmap, 0xff, PICOLCDFB_SIZE);
    + memset(data->fb_vbitmap, 0, PICOLCDFB_SIZE);
    memset(data->fb_bitmap, 0, PICOLCDFB_SIZE*data->fb_bpp);
    - } else {
    - /* invert 1 byte in each tile to force resend */
    - for (i = 0; i < PICOLCDFB_SIZE; i += 64)
    - data->fb_vbitmap[i] = ~data->fb_vbitmap[i];
    }
    + data->fb_force = 1;
    }

    /* schedule first output of framebuffer */
    @@ -440,7 +458,8 @@ static void picolcd_fb_update(struct picolcd_data *data)
    for (chip = 0; chip < 4; chip++)
    for (tile = 0; tile < 8; tile++)
    if (picolcd_fb_update_tile(data->fb_vbitmap,
    - data->fb_bitmap, data->fb_bpp, chip, tile)) {
    + data->fb_bitmap, data->fb_bpp, chip, tile) ||
    + data->fb_force) {
    n += 2;
    if (n >= HID_OUTPUT_FIFO_SIZE / 2) {
    usbhid_wait_io(data->hdev);
    @@ -448,6 +467,7 @@ static void picolcd_fb_update(struct picolcd_data *data)
    }
    picolcd_fb_send_tile(data->hdev, chip, tile);
    }
    + data->fb_force = false;
    if (n)
    usbhid_wait_io(data->hdev);
    }
    @@ -526,10 +546,17 @@ static int picolcd_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *i
    /* only allow 1/8 bit depth (8-bit is grayscale) */
    *var = picolcdfb_var;
    var->activate = activate;
    - if (bpp >= 8)
    + if (bpp >= 8) {
    var->bits_per_pixel = 8;
    - else
    + var->red.length = 8;
    + var->green.length = 8;
    + var->blue.length = 8;
    + } else {
    var->bits_per_pixel = 1;
    + var->red.length = 1;
    + var->green.length = 1;
    + var->blue.length = 1;
    + }
    return 0;
    }

    @@ -660,9 +687,10 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)
    {
    struct device *dev = &data->hdev->dev;
    struct fb_info *info = NULL;
    - int error = -ENOMEM;
    + int i, error = -ENOMEM;
    u8 *fb_vbitmap = NULL;
    u8 *fb_bitmap = NULL;
    + u32 *palette;

    fb_bitmap = vmalloc(PICOLCDFB_SIZE*picolcdfb_var.bits_per_pixel);
    if (fb_bitmap == NULL) {
    @@ -678,12 +706,23 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)

    data->fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT;
    data->fb_defio = picolcd_fb_defio;
    - info = framebuffer_alloc(0, dev);
    + /* The extra memory is:
    + * - struct picolcd_fb_cleanup_item
    + * - u32 for ref_count
    + * - 256*u32 for pseudo_palette
    + */
    + info = framebuffer_alloc(257 * sizeof(u32), dev);
    if (info == NULL) {
    dev_err(dev, "failed to allocate a framebuffer\n");
    goto err_nomem;
    }

    + palette = info->par;
    + *palette = 1;
    + palette++;
    + for (i = 0; i < 256; i++)
    + palette[i] = i > 0 && i < 16 ? 0xff : 0;
    + info->pseudo_palette = palette;
    info->fbdefio = &data->fb_defio;
    info->screen_base = (char __force __iomem *)fb_bitmap;
    info->fbops = &picolcdfb_ops;
    @@ -715,6 +754,7 @@ static int picolcd_init_framebuffer(struct picolcd_data *data)
    goto err_sysfs;
    }
    /* schedule first output of framebuffer */
    + data->fb_force = 1;
    schedule_delayed_work(&info->deferred_work, 0);
    return 0;

    --
    1.7.1
    --
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2010-06-28 22:37    [W:0.029 / U:65.768 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site