diff --git a/drivers/video/backlight-pwm.c b/drivers/video/backlight-pwm.c index ba6f9bc..91435f8 100644 --- a/drivers/video/backlight-pwm.c +++ b/drivers/video/backlight-pwm.c @@ -39,6 +39,7 @@ int enable_active_high; int max_value; int enabled; + unsigned int scale; }; static int backlight_pwm_enable(struct pwm_backlight *pwm_backlight) @@ -87,18 +88,26 @@ return 0; } +static int compute_duty_cycle(struct pwm_backlight *pwm_backlight, int brightness) +{ + int duty_cycle; + + if (pwm_backlight->levels) + duty_cycle = pwm_backlight->levels[brightness]; + else + duty_cycle = brightness; + + return duty_cycle * pwm_backlight->period / pwm_backlight->scale; +} + static int backlight_pwm_set(struct backlight_device *backlight, int brightness) { struct pwm_backlight *pwm_backlight = container_of(backlight, struct pwm_backlight, backlight); - unsigned long long duty = pwm_backlight->period; - unsigned int max = pwm_backlight->backlight.brightness_max; - duty *= brightness; - do_div(duty, max); - - pwm_config(pwm_backlight->pwm, duty, pwm_backlight->period); + pwm_config(pwm_backlight->pwm, compute_duty_cycle(pwm_backlight, brightness), + pwm_backlight->period); if (brightness) return backlight_pwm_enable(pwm_backlight); @@ -113,7 +122,7 @@ struct property *prop; int length; u32 value; - int ret; + int ret, i; enum of_gpio_flags flags; if (!node) @@ -141,6 +150,10 @@ if (ret < 0) return ret; + for (i = 0; i <= pwm_backlight->backlight.brightness_max; i++) + if (pwm_backlight->levels[i] > pwm_backlight->scale) + pwm_backlight->scale = pwm_backlight->levels[i]; + ret = of_property_read_u32(node, "default-brightness-level", &value); if (ret < 0) diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index c38d13c..693c21f 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -22,8 +22,8 @@ struct param_d *par_font; int par_font_val; - int font_width, font_height; - const u8 *fontdata; + const struct font_desc *font; + unsigned int cols, rows; unsigned int x, y; /* cursor position */ @@ -84,7 +84,7 @@ { 255, 255, 255 }, }; -static void drawchar(struct fbc_priv *priv, int x, int y, char c) +static void drawchar(struct fbc_priv *priv, int x, int y, int c) { void *buf; int bpp = priv->fb->bits_per_pixel >> 3; @@ -97,7 +97,8 @@ buf = gui_screen_render_buffer(priv->sc); - inbuf = &priv->fontdata[c * priv->font_height]; + i = find_font_index(priv->font, c); + inbuf = priv->font->data + i; line_length = priv->fb->line_length; @@ -113,13 +114,13 @@ rgb = &colors[bgcolor]; bgcolor = gu_rgb_to_pixel(priv->fb, rgb->r, rgb->g, rgb->b, 0xff); - for (i = 0; i < priv->font_height; i++) { + for (i = 0; i < priv->font->height; i++) { uint8_t t = inbuf[i]; int j; - adr = buf + line_length * (y * priv->font_height + i) + x * priv->font_width * bpp; + adr = buf + line_length * (y * priv->font->height + i) + x * priv->font->width * bpp; - for (j = 0; j < priv->font_width; j++) { + for (j = 0; j < priv->font->width; j++) { if (t & 0x80) gu_set_pixel(priv->fb, adr, color); else @@ -137,10 +138,10 @@ buf = gui_screen_render_buffer(priv->sc); - gu_invert_area(priv->fb, buf, x * priv->font_width, y * priv->font_height, - priv->font_width, priv->font_height); - gu_screen_blit_area(priv->sc, x * priv->font_width, y * priv->font_height, - priv->font_width, priv->font_height); + gu_invert_area(priv->fb, buf, x * priv->font->width, y * priv->font->height, + priv->font->width, priv->font->height); + gu_screen_blit_area(priv->sc, x * priv->font->width, y * priv->font->height, + priv->font->width, priv->font->height); } static void printchar(struct fbc_priv *priv, int c) @@ -174,9 +175,9 @@ default: drawchar(priv, priv->x, priv->y, c); - gu_screen_blit_area(priv->sc, priv->x * priv->font_width, - priv->y * priv->font_height, - priv->font_width, priv->font_height); + gu_screen_blit_area(priv->sc, priv->x * priv->font->width, + priv->y * priv->font->height, + priv->font->width, priv->font->height); priv->x++; if (priv->x > priv->cols) { @@ -188,7 +189,7 @@ if (priv->y > priv->rows) { void *buf; u32 line_length = priv->fb->line_length; - int line_height = line_length * priv->font_height; + int line_height = line_length * priv->font->height; buf = gui_screen_render_buffer(priv->sc); @@ -356,12 +357,10 @@ return -ENOENT; } - priv->font_width = font->width; - priv->font_height = font->height; - priv->fontdata = font->data; + priv->font = font; - priv->rows = fb->yres / priv->font_height - 1; - priv->cols = fb->xres / priv->font_width - 1; + priv->rows = fb->yres / priv->font->height - 1; + priv->cols = fb->xres / priv->font->width - 1; return 0; } diff --git a/include/linux/font.h b/include/linux/font.h index 62b1879..feeab97 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -12,24 +12,31 @@ #define _VIDEO_FONT_H #include +#include +struct font_index { + wchar_t wc; /* code of the char. */ + short index; /* offset of the char in the bitmap. */ +}; struct font_desc { const char *name; int width, height; + struct font_index *index; const void *data; + int num_chars; + struct list_head list; }; -extern const struct font_desc font_vga_8x16, - font_7x14, - font_mini_4x6; - /* Max. length for the name of a predefined font */ #define MAX_FONT_NAME 32 +extern int find_font_index(const struct font_desc *font, int ch); extern const struct font_desc *find_font_enum(int n); extern struct param_d *add_param_font(struct device_d *dev, int (*set)(struct param_d *p, void *priv), int (*get)(struct param_d *p, void *priv), int *value, void *priv); +int font_register(struct font_desc *font); + #endif /* _VIDEO_FONT_H */ diff --git a/lib/fonts/Kconfig b/lib/fonts/Kconfig index 715d5e5..d23b283 100644 --- a/lib/fonts/Kconfig +++ b/lib/fonts/Kconfig @@ -20,6 +20,11 @@ config FONT_MINI_4x6 bool "Mini 4x6 font" +config FONT_CUSTOM_16X + bool "Custom 16x16 font" + help + This font is useful for Chinese and other non ascii chars. + config FONT_AUTOSELECT def_bool y depends on !FONT_MINI_4x6 diff --git a/lib/fonts/Makefile b/lib/fonts/Makefile index b7d4765..98245b3 100644 --- a/lib/fonts/Makefile +++ b/lib/fonts/Makefile @@ -5,6 +5,7 @@ font-objs-$(CONFIG_FONT_8x16) += font_8x16.o font-objs-$(CONFIG_FONT_7x14) += font_7x14.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o +font-objs-$(CONFIG_FONT_CUSTOM_16X)+= font_custom_16x.o font-objs += $(font-objs-y) diff --git a/lib/fonts/font_7x14.c b/lib/fonts/font_7x14.c index fe99871..384ba39 100644 --- a/lib/fonts/font_7x14.c +++ b/lib/fonts/font_7x14.c @@ -3,6 +3,7 @@ /* by Jurriaan Kalkman 05-2005 */ /**************************************/ +#include #include #define FONTDATAMAX 3584 @@ -4108,9 +4109,15 @@ }; -const struct font_desc font_7x14 = { +static struct font_desc font_7x14 = { .name = "7x14", .width = 7, .height = 14, .data = fontdata_7x14, }; + +static int font_7x14_register(void) +{ + return font_register(&font_7x14); +} +postcore_initcall(font_7x14_register); diff --git a/lib/fonts/font_8x16.c b/lib/fonts/font_8x16.c index 4717ead..c5c14fc 100644 --- a/lib/fonts/font_8x16.c +++ b/lib/fonts/font_8x16.c @@ -4,6 +4,7 @@ /* */ /**********************************************/ +#include #include #include @@ -4621,10 +4622,15 @@ }; -const struct font_desc font_vga_8x16 = { +static struct font_desc font_vga_8x16 = { .name = "VGA8x16", .width = 8, .height = 16, .data = fontdata_8x16, }; -EXPORT_SYMBOL(font_vga_8x16); + +static int font_vga_8x16_register(void) +{ + return font_register(&font_vga_8x16); +} +postcore_initcall(font_vga_8x16_register); diff --git a/lib/fonts/font_custom_16x.c b/lib/fonts/font_custom_16x.c new file mode 100644 index 0000000..2666e1f --- /dev/null +++ b/lib/fonts/font_custom_16x.c @@ -0,0 +1,50 @@ +/* + * by Du Huanpeng + */ + +#include +#include +#include +#include + +/* place real font data here or set fontdata_custom_16x points to + * the address of font data and also setup the index. + */ + +static const unsigned char fontdata_custom_16x[] = { + 0xFF, 0xFF, /*OOOOOOOOOOOOOOOO*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0x80, 0x01, /*O______________O*/ + 0xFF, 0xFF, /*OOOOOOOOOOOOOOOO*/ +}; + +static struct font_index fontdata_custom_16x_index[] = { + { 0x0000, 0x0000 }, +}; + +static struct font_desc font_custom_16x = { + .name = "CUSTOM-16x", + .width = 16, + .height = 16, + .data = fontdata_custom_16x, + .index = fontdata_custom_16x_index, + .num_chars = ARRAY_SIZE(fontdata_custom_16x_index), +}; + +static int font_custom_16x_register(void) +{ + return font_register(&font_custom_16x); +} +postcore_initcall(font_custom_16x_register); diff --git a/lib/fonts/font_mini_4x6.c b/lib/fonts/font_mini_4x6.c index 3ecb4fb..4a1de13 100644 --- a/lib/fonts/font_mini_4x6.c +++ b/lib/fonts/font_mini_4x6.c @@ -39,6 +39,7 @@ MSBit to LSBit = left to right. */ +#include #include #define FONTDATAMAX 1536 @@ -2147,9 +2148,15 @@ /*}*/ }; -const struct font_desc font_mini_4x6 = { +static struct font_desc font_mini_4x6 = { .name = "MINI4x6", .width = 4, .height = 6, .data = fontdata_mini_4x6, }; + +static int font_mini_4x6_register(void) +{ + return font_register(&font_mini_4x6); +} +postcore_initcall(font_mini_4x6_register); diff --git a/lib/fonts/fonts.c b/lib/fonts/fonts.c index 5a9d3f1..926f880 100644 --- a/lib/fonts/fonts.c +++ b/lib/fonts/fonts.c @@ -18,37 +18,55 @@ #include #include -#define NO_FONTS - -static const struct font_desc *fonts[] = { -#ifdef CONFIG_FONT_8x16 -#undef NO_FONTS - &font_vga_8x16, -#endif -#ifdef CONFIG_FONT_7x14 -#undef NO_FONTS - &font_7x14, -#endif -#ifdef CONFIG_FONT_MINI_4x6 -#undef NO_FONTS - &font_mini_4x6, -#endif -}; - -#define num_fonts ARRAY_SIZE(fonts) - -#ifdef NO_FONTS -#error No fonts configured. -#endif - static char *font_names; +static LIST_HEAD(fonts_list); + +int font_register(struct font_desc *font) +{ + if (font_names) + return -EBUSY; + + list_add_tail(&font->list, &fonts_list); + + return 0; +} +int find_font_index(const struct font_desc *font, int ch) +{ + int index; + if (font->index == NULL) { + index = font->width + 7; + index /= 8; + index *= font->height; + index *= ch; + } else { + /* + * FIXME: use binary search instead! + */ + index = font->num_chars - 1; + + while (index && font->index[index].wc != ch) + index--; + + /* return 0 if not found. */ + index = font->index->index; + } + + return index; +} + const struct font_desc *find_font_enum(int n) { - if (n > num_fonts) - return NULL; + struct font_desc *f; + int i = 0; - return fonts[n]; + list_for_each_entry(f, &fonts_list, list) { + if (i == n) + return f; + i++; + } + + return NULL; } struct param_d *add_param_font(struct device_d *dev, @@ -56,13 +74,21 @@ int (*get)(struct param_d *p, void *priv), int *value, void *priv) { - unsigned int i; + struct font_desc *f; + int num_fonts = 0; + + list_for_each_entry(f, &fonts_list, list) + num_fonts++; if (!font_names) { + int i = 0; + font_names = xmalloc(sizeof(char *) * num_fonts); - for (i = 0; i < num_fonts; i++) - ((const char **)font_names)[i] = fonts[i]->name; + list_for_each_entry(f, &fonts_list, list) { + ((const char **)font_names)[i] = f->name; + i++; + } } return dev_add_param_enum(dev, "font",