summaryrefslogtreecommitdiff
path: root/drivers/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/backlight/Kconfig9
-rw-r--r--drivers/video/backlight/Makefile1
-rw-r--r--drivers/video/backlight/aw99706.c471
-rw-r--r--drivers/video/backlight/led_bl.c13
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c8
-rw-r--r--drivers/video/fbdev/core/bitblit.c16
-rw-r--r--drivers/video/fbdev/core/fbcon.c28
-rw-r--r--drivers/video/fbdev/core/fbmem.c1
-rw-r--r--drivers/video/fbdev/gbefb.c5
-rw-r--r--drivers/video/fbdev/gxt4500.c2
-rw-r--r--drivers/video/fbdev/i810/i810_main.c46
-rw-r--r--drivers/video/fbdev/pvr2fb.c2
-rw-r--r--drivers/video/fbdev/pxafb.c12
-rw-r--r--drivers/video/fbdev/ssd1307fb.c4
-rw-r--r--drivers/video/fbdev/tcx.c2
-rw-r--r--drivers/video/fbdev/tridentfb.c4
-rw-r--r--drivers/video/fbdev/valkyriefb.c2
-rw-r--r--drivers/video/fbdev/vesafb.c29
-rw-r--r--drivers/video/fbdev/vga16fb.c21
19 files changed, 613 insertions, 63 deletions
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index d9374d208cee..a1422ddd1c22 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -156,6 +156,14 @@ config BACKLIGHT_ATMEL_LCDC
If in doubt, it's safe to enable this option; it doesn't kick
in unless the board's description says it's wired that way.
+config BACKLIGHT_AW99706
+ tristate "Backlight Driver for Awinic AW99706"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you have a LCD backlight connected to the WLED output of AW99706
+ WLED output, say Y here to enable this driver.
+
config BACKLIGHT_EP93XX
tristate "Cirrus EP93xx Backlight Driver"
depends on FB_EP93XX
@@ -185,6 +193,7 @@ config BACKLIGHT_KTD253
config BACKLIGHT_KTD2801
tristate "Backlight Driver for Kinetic KTD2801"
+ depends on GPIOLIB || COMPILE_TEST
select LEDS_EXPRESSWIRE
help
Say Y to enable the backlight driver for the Kinetic KTD2801 1-wire
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index dfbb169bf6ea..a5d62b018102 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_BACKLIGHT_ADP8870) += adp8870_bl.o
obj-$(CONFIG_BACKLIGHT_APPLE) += apple_bl.o
obj-$(CONFIG_BACKLIGHT_APPLE_DWI) += apple_dwi_bl.o
obj-$(CONFIG_BACKLIGHT_AS3711) += as3711_bl.o
+obj-$(CONFIG_BACKLIGHT_AW99706) += aw99706.o
obj-$(CONFIG_BACKLIGHT_BD6107) += bd6107.o
obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
diff --git a/drivers/video/backlight/aw99706.c b/drivers/video/backlight/aw99706.c
new file mode 100644
index 000000000000..df5b23b2f753
--- /dev/null
+++ b/drivers/video/backlight/aw99706.c
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * aw99706 - Backlight driver for the AWINIC AW99706
+ *
+ * Copyright (C) 2025 Junjie Cao <caojunjie650@gmail.com>
+ * Copyright (C) 2025 Pengyu Luo <mitltlatltl@gmail.com>
+ *
+ * Based on vendor driver:
+ * Copyright (c) 2023 AWINIC Technology CO., LTD
+ */
+
+#include <linux/backlight.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#define AW99706_MAX_BRT_LVL 4095
+#define AW99706_REG_MAX 0x1F
+#define AW99706_ID 0x07
+
+/* registers list */
+#define AW99706_CFG0_REG 0x00
+#define AW99706_DIM_MODE_MASK GENMASK(1, 0)
+
+#define AW99706_CFG1_REG 0x01
+#define AW99706_SW_FREQ_MASK GENMASK(3, 0)
+#define AW99706_SW_ILMT_MASK GENMASK(5, 4)
+
+#define AW99706_CFG2_REG 0x02
+#define AW99706_ILED_MAX_MASK GENMASK(6, 0)
+#define AW99706_UVLOSEL_MASK BIT(7)
+
+#define AW99706_CFG3_REG 0x03
+#define AW99706_CFG4_REG 0x04
+#define AW99706_BRT_MSB_MASK GENMASK(3, 0)
+
+#define AW99706_CFG5_REG 0x05
+#define AW99706_BRT_LSB_MASK GENMASK(7, 0)
+
+#define AW99706_CFG6_REG 0x06
+#define AW99706_RAMP_CTL_MASK GENMASK(7, 6)
+
+#define AW99706_CFG7_REG 0x07
+#define AW99706_CFG8_REG 0x08
+#define AW99706_CFG9_REG 0x09
+#define AW99706_CFGA_REG 0x0A
+#define AW99706_CFGB_REG 0x0B
+#define AW99706_CFGC_REG 0x0C
+#define AW99706_CFGD_REG 0x0D
+#define AW99706_FLAG_REG 0x10
+#define AW99706_BACKLIGHT_EN_MASK BIT(7)
+
+#define AW99706_CHIPID_REG 0x11
+#define AW99706_LED_OPEN_FLAG_REG 0x12
+#define AW99706_LED_SHORT_FLAG_REG 0x13
+#define AW99706_MTPLDOSEL_REG 0x1E
+#define AW99706_MTPRUN_REG 0x1F
+
+#define RESV 0
+
+/* Boost switching frequency table, in Hz */
+static const u32 aw99706_sw_freq_tbl[] = {
+ RESV, RESV, RESV, RESV, 300000, 400000, 500000, 600000,
+ 660000, 750000, 850000, 1000000, 1200000, 1330000, 1500000, 1700000
+};
+
+/* Switching current limitation table, in uA */
+static const u32 aw99706_sw_ilmt_tbl[] = {
+ 1500000, 2000000, 2500000, 3000000
+};
+
+/* ULVO threshold table, in uV */
+static const u32 aw99706_ulvo_thres_tbl[] = {
+ 2200000, 5000000
+};
+
+struct aw99706_dt_prop {
+ const char * const name;
+ int (*lookup)(const struct aw99706_dt_prop *prop, u32 dt_val, u8 *val);
+ const u32 * const lookup_tbl;
+ u8 tbl_size;
+ u8 reg;
+ u8 mask;
+ u32 def_val;
+};
+
+static int aw99706_dt_property_lookup(const struct aw99706_dt_prop *prop,
+ u32 dt_val, u8 *val)
+{
+ int i;
+
+ if (!prop->lookup_tbl) {
+ *val = dt_val;
+ return 0;
+ }
+
+ for (i = 0; i < prop->tbl_size; i++)
+ if (prop->lookup_tbl[i] == dt_val)
+ break;
+
+ *val = i;
+
+ return i == prop->tbl_size ? -1 : 0;
+}
+
+#define MIN_ILED_MAX 5000
+#define MAX_ILED_MAX 50000
+#define STEP_ILED_MAX 500
+
+static int
+aw99706_dt_property_iled_max_convert(const struct aw99706_dt_prop *prop,
+ u32 dt_val, u8 *val)
+{
+ if (dt_val > MAX_ILED_MAX || dt_val < MIN_ILED_MAX)
+ return -1;
+
+ *val = (dt_val - MIN_ILED_MAX) / STEP_ILED_MAX;
+
+ return (dt_val - MIN_ILED_MAX) % STEP_ILED_MAX;
+}
+
+static const struct aw99706_dt_prop aw99706_dt_props[] = {
+ {
+ "awinic,dim-mode", aw99706_dt_property_lookup,
+ NULL, 0,
+ AW99706_CFG0_REG, AW99706_DIM_MODE_MASK, 1,
+ },
+ {
+ "awinic,sw-freq", aw99706_dt_property_lookup,
+ aw99706_sw_freq_tbl, ARRAY_SIZE(aw99706_sw_freq_tbl),
+ AW99706_CFG1_REG, AW99706_SW_FREQ_MASK, 750000,
+ },
+ {
+ "awinic,sw-ilmt", aw99706_dt_property_lookup,
+ aw99706_sw_ilmt_tbl, ARRAY_SIZE(aw99706_sw_ilmt_tbl),
+ AW99706_CFG1_REG, AW99706_SW_ILMT_MASK, 3000000,
+ },
+ {
+ "awinic,iled-max", aw99706_dt_property_iled_max_convert,
+ NULL, 0,
+ AW99706_CFG2_REG, AW99706_ILED_MAX_MASK, 20000,
+
+ },
+ {
+ "awinic,uvlo-thres", aw99706_dt_property_lookup,
+ aw99706_ulvo_thres_tbl, ARRAY_SIZE(aw99706_ulvo_thres_tbl),
+ AW99706_CFG2_REG, AW99706_UVLOSEL_MASK, 2200000,
+ },
+ {
+ "awinic,ramp-ctl", aw99706_dt_property_lookup,
+ NULL, 0,
+ AW99706_CFG6_REG, AW99706_RAMP_CTL_MASK, 2,
+ }
+};
+
+struct reg_init_data {
+ u8 reg;
+ u8 mask;
+ u8 val;
+};
+
+struct aw99706_device {
+ struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
+ struct backlight_device *bl_dev;
+ struct gpio_desc *hwen_gpio;
+ struct reg_init_data init_tbl[ARRAY_SIZE(aw99706_dt_props)];
+ bool bl_enable;
+};
+
+enum reg_access {
+ REG_NONE_ACCESS = 0,
+ REG_RD_ACCESS = 1,
+ REG_WR_ACCESS = 2,
+};
+
+static const u8 aw99706_regs[AW99706_REG_MAX + 1] = {
+ [AW99706_CFG0_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG1_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG2_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG3_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG4_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG5_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG6_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG7_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG8_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFG9_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFGA_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFGB_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFGC_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_CFGD_REG] = REG_RD_ACCESS | REG_WR_ACCESS,
+ [AW99706_FLAG_REG] = REG_RD_ACCESS,
+ [AW99706_CHIPID_REG] = REG_RD_ACCESS,
+ [AW99706_LED_OPEN_FLAG_REG] = REG_RD_ACCESS,
+ [AW99706_LED_SHORT_FLAG_REG] = REG_RD_ACCESS,
+
+ /*
+ * Write bit is dropped here, writing BIT(0) to MTPLDOSEL will unlock
+ * Multi-time Programmable (MTP).
+ */
+ [AW99706_MTPLDOSEL_REG] = REG_RD_ACCESS,
+ [AW99706_MTPRUN_REG] = REG_NONE_ACCESS,
+};
+
+static bool aw99706_readable_reg(struct device *dev, unsigned int reg)
+{
+ return aw99706_regs[reg] & REG_RD_ACCESS;
+}
+
+static bool aw99706_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return aw99706_regs[reg] & REG_WR_ACCESS;
+}
+
+static inline int aw99706_i2c_read(struct aw99706_device *aw, u8 reg,
+ unsigned int *val)
+{
+ return regmap_read(aw->regmap, reg, val);
+}
+
+static inline int aw99706_i2c_write(struct aw99706_device *aw, u8 reg, u8 val)
+{
+ return regmap_write(aw->regmap, reg, val);
+}
+
+static inline int aw99706_i2c_update_bits(struct aw99706_device *aw, u8 reg,
+ u8 mask, u8 val)
+{
+ return regmap_update_bits(aw->regmap, reg, mask, val);
+}
+
+static void aw99706_dt_parse(struct aw99706_device *aw,
+ struct backlight_properties *bl_props)
+{
+ const struct aw99706_dt_prop *prop;
+ u32 dt_val;
+ int ret, i;
+ u8 val;
+
+ for (i = 0; i < ARRAY_SIZE(aw99706_dt_props); i++) {
+ prop = &aw99706_dt_props[i];
+ ret = device_property_read_u32(aw->dev, prop->name, &dt_val);
+ if (ret < 0)
+ dt_val = prop->def_val;
+
+ if (prop->lookup(prop, dt_val, &val)) {
+ dev_warn(aw->dev, "invalid value %d for property %s, using default value %d\n",
+ dt_val, prop->name, prop->def_val);
+
+ prop->lookup(prop, prop->def_val, &val);
+ }
+
+ aw->init_tbl[i].reg = prop->reg;
+ aw->init_tbl[i].mask = prop->mask;
+ aw->init_tbl[i].val = val << __ffs(prop->mask);
+ }
+
+ bl_props->brightness = AW99706_MAX_BRT_LVL >> 1;
+ bl_props->max_brightness = AW99706_MAX_BRT_LVL;
+ device_property_read_u32(aw->dev, "default-brightness",
+ &bl_props->brightness);
+ device_property_read_u32(aw->dev, "max-brightness",
+ &bl_props->max_brightness);
+
+ if (bl_props->max_brightness > AW99706_MAX_BRT_LVL)
+ bl_props->max_brightness = AW99706_MAX_BRT_LVL;
+
+ if (bl_props->brightness > bl_props->max_brightness)
+ bl_props->brightness = bl_props->max_brightness;
+}
+
+static int aw99706_hw_init(struct aw99706_device *aw)
+{
+ int ret, i;
+
+ gpiod_set_value_cansleep(aw->hwen_gpio, 1);
+
+ for (i = 0; i < ARRAY_SIZE(aw->init_tbl); i++) {
+ ret = aw99706_i2c_update_bits(aw, aw->init_tbl[i].reg,
+ aw->init_tbl[i].mask,
+ aw->init_tbl[i].val);
+ if (ret < 0) {
+ dev_err(aw->dev, "Failed to write init data %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int aw99706_bl_enable(struct aw99706_device *aw, bool en)
+{
+ int ret;
+ u8 val;
+
+ val = FIELD_PREP(AW99706_BACKLIGHT_EN_MASK, en);
+ ret = aw99706_i2c_update_bits(aw, AW99706_CFGD_REG,
+ AW99706_BACKLIGHT_EN_MASK, val);
+ if (ret)
+ dev_err(aw->dev, "Failed to enable backlight!\n");
+
+ return ret;
+}
+
+static int aw99706_update_brightness(struct aw99706_device *aw, u32 brt_lvl)
+{
+ bool bl_enable_now = !!brt_lvl;
+ int ret;
+
+ ret = aw99706_i2c_write(aw, AW99706_CFG4_REG,
+ (brt_lvl >> 8) & AW99706_BRT_MSB_MASK);
+ if (ret < 0)
+ return ret;
+
+ ret = aw99706_i2c_write(aw, AW99706_CFG5_REG,
+ brt_lvl & AW99706_BRT_LSB_MASK);
+ if (ret < 0)
+ return ret;
+
+ if (aw->bl_enable != bl_enable_now) {
+ ret = aw99706_bl_enable(aw, bl_enable_now);
+ if (!ret)
+ aw->bl_enable = bl_enable_now;
+ }
+
+ return ret;
+}
+
+static int aw99706_bl_update_status(struct backlight_device *bl)
+{
+ struct aw99706_device *aw = bl_get_data(bl);
+
+ return aw99706_update_brightness(aw, bl->props.brightness);
+}
+
+static const struct backlight_ops aw99706_bl_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = aw99706_bl_update_status,
+};
+
+static const struct regmap_config aw99706_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = AW99706_REG_MAX,
+ .writeable_reg = aw99706_writeable_reg,
+ .readable_reg = aw99706_readable_reg,
+};
+
+static int aw99706_chip_id_read(struct aw99706_device *aw)
+{
+ int ret;
+ unsigned int val;
+
+ ret = aw99706_i2c_read(aw, AW99706_CHIPID_REG, &val);
+ if (ret < 0)
+ return ret;
+
+ return val;
+}
+
+static int aw99706_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct aw99706_device *aw;
+ struct backlight_device *bl_dev;
+ struct backlight_properties props = {};
+ int ret = 0;
+
+ aw = devm_kzalloc(dev, sizeof(*aw), GFP_KERNEL);
+ if (!aw)
+ return -ENOMEM;
+
+ aw->client = client;
+ aw->dev = dev;
+ i2c_set_clientdata(client, aw);
+
+ aw->regmap = devm_regmap_init_i2c(client, &aw99706_regmap_config);
+ if (IS_ERR(aw->regmap))
+ return dev_err_probe(dev, PTR_ERR(aw->regmap),
+ "Failed to init regmap\n");
+
+ ret = aw99706_chip_id_read(aw);
+ if (ret != AW99706_ID)
+ return dev_err_probe(dev, -ENODEV,
+ "Unknown chip id 0x%02x\n", ret);
+
+ aw99706_dt_parse(aw, &props);
+
+ aw->hwen_gpio = devm_gpiod_get(aw->dev, "enable", GPIOD_OUT_LOW);
+ if (IS_ERR(aw->hwen_gpio))
+ return dev_err_probe(dev, PTR_ERR(aw->hwen_gpio),
+ "Failed to get enable gpio\n");
+
+ ret = aw99706_hw_init(aw);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "Failed to initialize the chip\n");
+
+ props.type = BACKLIGHT_RAW;
+ props.scale = BACKLIGHT_SCALE_LINEAR;
+
+ bl_dev = devm_backlight_device_register(dev, "aw99706-backlight", dev,
+ aw, &aw99706_bl_ops, &props);
+ if (IS_ERR(bl_dev))
+ return dev_err_probe(dev, PTR_ERR(bl_dev),
+ "Failed to register backlight!\n");
+
+ aw->bl_dev = bl_dev;
+
+ return 0;
+}
+
+static void aw99706_remove(struct i2c_client *client)
+{
+ struct aw99706_device *aw = i2c_get_clientdata(client);
+
+ aw99706_update_brightness(aw, 0);
+
+ msleep(50);
+
+ gpiod_set_value_cansleep(aw->hwen_gpio, 0);
+}
+
+static int aw99706_suspend(struct device *dev)
+{
+ struct aw99706_device *aw = dev_get_drvdata(dev);
+
+ return aw99706_update_brightness(aw, 0);
+}
+
+static int aw99706_resume(struct device *dev)
+{
+ struct aw99706_device *aw = dev_get_drvdata(dev);
+
+ return aw99706_hw_init(aw);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(aw99706_pm_ops, aw99706_suspend, aw99706_resume);
+
+static const struct i2c_device_id aw99706_ids[] = {
+ { "aw99706" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, aw99706_ids);
+
+static const struct of_device_id aw99706_match_table[] = {
+ { .compatible = "awinic,aw99706", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, aw99706_match_table);
+
+static struct i2c_driver aw99706_i2c_driver = {
+ .probe = aw99706_probe,
+ .remove = aw99706_remove,
+ .id_table = aw99706_ids,
+ .driver = {
+ .name = "aw99706",
+ .of_match_table = aw99706_match_table,
+ .pm = pm_ptr(&aw99706_pm_ops),
+ },
+};
+
+module_i2c_driver(aw99706_i2c_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("BackLight driver for aw99706");
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index efc5e380669a..f7ab9b360731 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -211,6 +211,19 @@ static int led_bl_probe(struct platform_device *pdev)
}
for (i = 0; i < priv->nb_leds; i++) {
+ struct device_link *link;
+
+ link = device_link_add(&pdev->dev, priv->leds[i]->dev->parent,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!link) {
+ dev_err(&pdev->dev, "Failed to add devlink (consumer %s, supplier %s)\n",
+ dev_name(&pdev->dev), dev_name(priv->leds[i]->dev->parent));
+ backlight_device_unregister(priv->bl_dev);
+ return -EINVAL;
+ }
+ }
+
+ for (i = 0; i < priv->nb_leds; i++) {
mutex_lock(&priv->leds[i]->led_access);
led_sysfs_disable(priv->leds[i]);
mutex_unlock(&priv->leds[i]->led_access);
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
index 210fd3ac18a4..56ef1d88e003 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -2614,8 +2614,12 @@ static int aty_init(struct fb_info *info)
pr_cont("\n");
}
#endif
- if (par->pll_ops->init_pll)
- par->pll_ops->init_pll(info, &par->pll);
+ if (par->pll_ops->init_pll) {
+ ret = par->pll_ops->init_pll(info, &par->pll);
+ if (ret)
+ return ret;
+ }
+
if (par->pll_ops->resume_pll)
par->pll_ops->resume_pll(info, &par->pll);
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 9d2e59796c3e..085ffb44c51a 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -79,12 +79,16 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
struct fb_image *image, u8 *buf, u8 *dst)
{
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ unsigned int charcnt = vc->vc_font.charcount;
u32 idx = vc->vc_font.width >> 3;
u8 *src;
while (cnt--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
+ u16 ch = scr_readw(s++) & charmask;
+
+ if (ch >= charcnt)
+ ch = 0;
+ src = vc->vc_font.data + (unsigned int)ch * cellsize;
if (attr) {
update_attr(buf, src, attr, vc);
@@ -112,14 +116,18 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
u8 *dst)
{
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ unsigned int charcnt = vc->vc_font.charcount;
u32 shift_low = 0, mod = vc->vc_font.width % 8;
u32 shift_high = 8;
u32 idx = vc->vc_font.width >> 3;
u8 *src;
while (cnt--) {
- src = vc->vc_font.data + (scr_readw(s++)&
- charmask)*cellsize;
+ u16 ch = scr_readw(s++) & charmask;
+
+ if (ch >= charcnt)
+ ch = 0;
+ src = vc->vc_font.data + (unsigned int)ch * cellsize;
if (attr) {
update_attr(buf, src, attr, vc);
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index e2e69aab6680..34ea14412ace 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -66,6 +66,7 @@
#include <linux/string.h>
#include <linux/kd.h>
#include <linux/panic.h>
+#include <linux/pci.h>
#include <linux/printk.h>
#include <linux/slab.h>
#include <linux/fb.h>
@@ -78,6 +79,7 @@
#include <linux/interrupt.h>
#include <linux/crc32.h> /* For counting font checksums */
#include <linux/uaccess.h>
+#include <linux/vga_switcheroo.h>
#include <asm/irq.h>
#include "fbcon.h"
@@ -2802,6 +2804,25 @@ int fbcon_mode_deleted(struct fb_info *info,
return found;
}
+static void fbcon_delete_mode(struct fb_videomode *m)
+{
+ struct fbcon_display *p;
+
+ for (int i = first_fb_vc; i <= last_fb_vc; i++) {
+ p = &fb_display[i];
+ if (p->mode == m)
+ p->mode = NULL;
+ }
+}
+
+void fbcon_delete_modelist(struct list_head *head)
+{
+ struct fb_modelist *modelist;
+
+ list_for_each_entry(modelist, head, list)
+ fbcon_delete_mode(&modelist->mode);
+}
+
#ifdef CONFIG_VT_HW_CONSOLE_BINDING
static void fbcon_unbind(void)
{
@@ -2872,6 +2893,9 @@ void fbcon_fb_unregistered(struct fb_info *info)
console_lock();
+ if (info->device && dev_is_pci(info->device))
+ vga_switcheroo_client_fb_set(to_pci_dev(info->device), NULL);
+
fbcon_registered_fb[info->node] = NULL;
fbcon_num_registered_fb--;
@@ -3005,6 +3029,10 @@ static int do_fb_registered(struct fb_info *info)
}
}
+ /* Set the fb info for vga_switcheroo clients. Does nothing otherwise. */
+ if (info->device && dev_is_pci(info->device))
+ vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
+
return ret;
}
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 53f1719b1ae1..eff757ebbed1 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -544,6 +544,7 @@ static void do_unregister_framebuffer(struct fb_info *fb_info)
fb_info->pixmap.addr = NULL;
}
+ fbcon_delete_modelist(&fb_info->modelist);
fb_destroy_modelist(&fb_info->modelist);
registered_fb[fb_info->node] = NULL;
num_registered_fb--;
diff --git a/drivers/video/fbdev/gbefb.c b/drivers/video/fbdev/gbefb.c
index 4c36a3e409be..cb6ff15a21db 100644
--- a/drivers/video/fbdev/gbefb.c
+++ b/drivers/video/fbdev/gbefb.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma-direct.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/fb.h>
@@ -65,7 +66,7 @@ struct gbefb_par {
static unsigned int gbe_mem_size = CONFIG_FB_GBE_MEM * 1024*1024;
static void *gbe_mem;
static dma_addr_t gbe_dma_addr;
-static unsigned long gbe_mem_phys;
+static phys_addr_t gbe_mem_phys;
static struct {
uint16_t *cpu;
@@ -1183,7 +1184,7 @@ static int gbefb_probe(struct platform_device *p_dev)
goto out_release_mem_region;
}
- gbe_mem_phys = (unsigned long) gbe_dma_addr;
+ gbe_mem_phys = dma_to_phys(&p_dev->dev, gbe_dma_addr);
}
par = info->par;
diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c
index 15a82c6b609e..1ee0a1efa18e 100644
--- a/drivers/video/fbdev/gxt4500.c
+++ b/drivers/video/fbdev/gxt4500.c
@@ -704,7 +704,7 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
info->var = var;
if (gxt4500_set_par(info)) {
- printk(KERN_ERR "gxt4500: cannot set video mode\n");
+ dev_err(&pdev->dev, "cannot set video mode\n");
goto err_free_cmap;
}
diff --git a/drivers/video/fbdev/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c
index d73a795fe1be..10b914a24114 100644
--- a/drivers/video/fbdev/i810/i810_main.c
+++ b/drivers/video/fbdev/i810/i810_main.c
@@ -1012,7 +1012,7 @@ static int i810_check_params(struct fb_var_screeninfo *var,
var->bits_per_pixel);
vidmem = line_length * info->var.yres;
if (vxres < var->xres) {
- printk("i810fb: required video memory, "
+ dev_info(&par->dev->dev, "required video memory, "
"%d bytes, for %dx%d-%d (virtual) "
"is out of range\n",
vidmem, vxres, vyres,
@@ -1067,9 +1067,9 @@ static int i810_check_params(struct fb_var_screeninfo *var,
|(info->monspecs.hfmax-HFMAX)
|(info->monspecs.vfmin-VFMIN)
|(info->monspecs.vfmax-VFMAX);
- printk("i810fb: invalid video mode%s\n",
- default_sync ? "" : ". Specifying "
- "vsyncN/hsyncN parameters may help");
+ dev_err(&par->dev->dev, "invalid video mode%s\n",
+ default_sync ? "" : ". Specifying "
+ "vsyncN/hsyncN parameters may help");
retval = -EINVAL;
}
}
@@ -1674,19 +1674,19 @@ static int i810_alloc_agp_mem(struct fb_info *info)
size = par->fb.size + par->iring.size;
if (!(bridge = agp_backend_acquire(par->dev))) {
- printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
+ dev_warn(&par->dev->dev, "cannot acquire agpgart\n");
return -ENODEV;
}
if (!(par->i810_gtt.i810_fb_memory =
agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
- printk("i810fb_alloc_fbmem: can't allocate framebuffer "
+ dev_warn(&par->dev->dev, "can't allocate framebuffer "
"memory\n");
agp_backend_release(bridge);
return -ENOMEM;
}
if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
par->fb.offset)) {
- printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
+ dev_warn(&par->dev->dev, "can't bind framebuffer memory\n");
agp_backend_release(bridge);
return -EBUSY;
}
@@ -1694,14 +1694,14 @@ static int i810_alloc_agp_mem(struct fb_info *info)
if (!(par->i810_gtt.i810_cursor_memory =
agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
AGP_PHYSICAL_MEMORY))) {
- printk("i810fb_alloc_cursormem: can't allocate "
+ dev_warn(&par->dev->dev, "can't allocate "
"cursor memory\n");
agp_backend_release(bridge);
return -ENOMEM;
}
if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
par->cursor_heap.offset)) {
- printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
+ dev_warn(&par->dev->dev, "cannot bind cursor memory\n");
agp_backend_release(bridge);
return -EBUSY;
}
@@ -1844,7 +1844,7 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
int err;
if ((err = pci_enable_device(par->dev))) {
- printk("i810fb_init: cannot enable device\n");
+ dev_err(&par->dev->dev, "cannot enable device\n");
return err;
}
par->res_flags |= PCI_DEVICE_ENABLED;
@@ -1859,14 +1859,14 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
par->mmio_start_phys = pci_resource_start(par->dev, 0);
}
if (!par->aperture.size) {
- printk("i810fb_init: device is disabled\n");
+ dev_warn(&par->dev->dev, "device is disabled\n");
return -ENOMEM;
}
if (!request_mem_region(par->aperture.physical,
par->aperture.size,
i810_pci_list[entry->driver_data])) {
- printk("i810fb_init: cannot request framebuffer region\n");
+ dev_warn(&par->dev->dev, "cannot request framebuffer region\n");
return -ENODEV;
}
par->res_flags |= FRAMEBUFFER_REQ;
@@ -1874,14 +1874,14 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
par->aperture.virtual = ioremap_wc(par->aperture.physical,
par->aperture.size);
if (!par->aperture.virtual) {
- printk("i810fb_init: cannot remap framebuffer region\n");
+ dev_warn(&par->dev->dev, "cannot remap framebuffer region\n");
return -ENODEV;
}
if (!request_mem_region(par->mmio_start_phys,
MMIO_SIZE,
i810_pci_list[entry->driver_data])) {
- printk("i810fb_init: cannot request mmio region\n");
+ dev_warn(&par->dev->dev, "cannot request mmio region\n");
return -ENODEV;
}
par->res_flags |= MMIO_REQ;
@@ -1889,7 +1889,7 @@ static int i810_allocate_pci_resource(struct i810fb_par *par,
par->mmio_start_virtual = ioremap(par->mmio_start_phys,
MMIO_SIZE);
if (!par->mmio_start_virtual) {
- printk("i810fb_init: cannot remap mmio region\n");
+ dev_warn(&par->dev->dev, "cannot remap mmio region\n");
return -ENODEV;
}
@@ -1921,12 +1921,12 @@ static void i810fb_find_init_mode(struct fb_info *info)
}
if (!err)
- printk("i810fb_init_pci: DDC probe successful\n");
+ dev_info(&par->dev->dev, "DDC probe successful\n");
fb_edid_to_monspecs(par->edid, specs);
if (specs->modedb == NULL)
- printk("i810fb_init_pci: Unable to get Mode Database\n");
+ dev_info(&par->dev->dev, "Unable to get Mode Database\n");
fb_videomode_to_modelist(specs->modedb, specs->modedb_len,
&info->modelist);
@@ -2072,7 +2072,7 @@ static int i810fb_init_pci(struct pci_dev *dev,
if (err < 0) {
i810fb_release_resource(info, par);
- printk("i810fb_init: cannot register framebuffer device\n");
+ dev_warn(&par->dev->dev, "cannot register framebuffer device\n");
return err;
}
@@ -2084,10 +2084,10 @@ static int i810fb_init_pci(struct pci_dev *dev,
vfreq = hfreq/(info->var.yres + info->var.upper_margin +
info->var.vsync_len + info->var.lower_margin);
- printk("I810FB: fb%d : %s v%d.%d.%d%s\n"
- "I810FB: Video RAM : %dK\n"
- "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n"
- "I810FB: Mode : %dx%d-%dbpp@%dHz\n",
+ dev_info(&par->dev->dev, "fb%d : %s v%d.%d.%d%s\n"
+ "Video RAM : %dK\n"
+ "Monitor : H: %d-%d KHz V: %d-%d Hz\n"
+ "Mode : %dx%d-%dbpp@%dHz\n",
info->node,
i810_pci_list[entry->driver_data],
VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION,
@@ -2137,7 +2137,7 @@ static void i810fb_remove_pci(struct pci_dev *dev)
unregister_framebuffer(info);
i810fb_release_resource(info, par);
- printk("cleanup_module: unloaded i810 framebuffer device\n");
+ dev_info(&par->dev->dev, "unloaded i810 framebuffer device\n");
}
#ifndef MODULE
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index cbdb1caf61bd..0b8d23c12b77 100644
--- a/drivers/video/fbdev/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -192,7 +192,7 @@ static unsigned long pvr2fb_map;
#ifdef CONFIG_PVR2_DMA
static unsigned int shdma = PVR2_CASCADE_CHAN;
-static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
+static unsigned int pvr2dma = CONFIG_NR_ONCHIP_DMA_CHANNELS;
#endif
static struct fb_videomode pvr2_modedb[] = {
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index b96a8a96bce8..e418eee825fb 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -419,12 +419,12 @@ static int pxafb_adjust_timing(struct pxafb_info *fbi,
var->yres = max_t(int, var->yres, MIN_YRES);
if (!(fbi->lccr0 & LCCR0_LCDT)) {
- clamp_val(var->hsync_len, 1, 64);
- clamp_val(var->vsync_len, 1, 64);
- clamp_val(var->left_margin, 1, 255);
- clamp_val(var->right_margin, 1, 255);
- clamp_val(var->upper_margin, 1, 255);
- clamp_val(var->lower_margin, 1, 255);
+ var->hsync_len = clamp(var->hsync_len, 1, 64);
+ var->vsync_len = clamp(var->vsync_len, 1, 64);
+ var->left_margin = clamp(var->left_margin, 1, 255);
+ var->right_margin = clamp(var->right_margin, 1, 255);
+ var->upper_margin = clamp(var->upper_margin, 1, 255);
+ var->lower_margin = clamp(var->lower_margin, 1, 255);
}
/* make sure each line is aligned on word boundary */
diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
index aa6cc0a8151a..83dd31fa1fab 100644
--- a/drivers/video/fbdev/ssd1307fb.c
+++ b/drivers/video/fbdev/ssd1307fb.c
@@ -680,7 +680,7 @@ static int ssd1307fb_probe(struct i2c_client *client)
if (!ssd1307fb_defio) {
dev_err(dev, "Couldn't allocate deferred io.\n");
ret = -ENOMEM;
- goto fb_alloc_error;
+ goto fb_defio_error;
}
ssd1307fb_defio->delay = HZ / refreshrate;
@@ -757,6 +757,8 @@ regulator_enable_error:
regulator_disable(par->vbat_reg);
reset_oled_error:
fb_deferred_io_cleanup(info);
+fb_defio_error:
+ __free_pages(vmem, get_order(vmem_size));
fb_alloc_error:
framebuffer_release(info);
return ret;
diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c
index f9a0085ad72b..ca9e84e8d860 100644
--- a/drivers/video/fbdev/tcx.c
+++ b/drivers/video/fbdev/tcx.c
@@ -428,7 +428,7 @@ static int tcx_probe(struct platform_device *op)
j = i;
break;
}
- par->mmap_map[i].poff = op->resource[j].start;
+ par->mmap_map[i].poff = op->resource[j].start - info->fix.smem_start;
}
info->fbops = &tcx_ops;
diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c
index 516cf2a18757..17b7253b8fbe 100644
--- a/drivers/video/fbdev/tridentfb.c
+++ b/drivers/video/fbdev/tridentfb.c
@@ -1631,7 +1631,7 @@ static int trident_pci_probe(struct pci_dev *dev,
}
if (noaccel) {
- printk(KERN_DEBUG "disabling acceleration\n");
+ dev_dbg(&dev->dev, "disabling acceleration\n");
info->flags |= FBINFO_HWACCEL_DISABLED;
info->pixmap.scan_align = 1;
}
@@ -1693,7 +1693,7 @@ static int trident_pci_probe(struct pci_dev *dev,
info->var.activate |= FB_ACTIVATE_NOW;
info->device = &dev->dev;
if (register_framebuffer(info) < 0) {
- printk(KERN_ERR "tridentfb: could not register framebuffer\n");
+ dev_err(&dev->dev, "could not register framebuffer\n");
fb_dealloc_cmap(&info->cmap);
err = -EINVAL;
goto out_unmap2;
diff --git a/drivers/video/fbdev/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c
index 91d070ef6989..6ff059ee1694 100644
--- a/drivers/video/fbdev/valkyriefb.c
+++ b/drivers/video/fbdev/valkyriefb.c
@@ -329,11 +329,13 @@ static int __init valkyriefb_init(void)
if (of_address_to_resource(dp, 0, &r)) {
printk(KERN_ERR "can't find address for valkyrie\n");
+ of_node_put(dp);
return 0;
}
frame_buffer_phys = r.start;
cmap_regs_phys = r.start + 0x304000;
+ of_node_put(dp);
}
#endif /* ppc (!CONFIG_MAC) */
diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
index a81df8865143..f135033c22fb 100644
--- a/drivers/video/fbdev/vesafb.c
+++ b/drivers/video/fbdev/vesafb.c
@@ -314,8 +314,8 @@ static int vesafb_probe(struct platform_device *dev)
#endif
if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
- printk(KERN_WARNING
- "vesafb: cannot reserve video memory at 0x%lx\n",
+ dev_warn(&dev->dev,
+ "cannot reserve video memory at 0x%lx\n",
vesafb_fix.smem_start);
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
@@ -333,12 +333,12 @@ static int vesafb_probe(struct platform_device *dev)
par->base = si->lfb_base;
par->size = size_total;
- printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+ dev_info(&dev->dev, "mode is %dx%dx%d, linelength=%d, pages=%d\n",
vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
vesafb_fix.line_length, si->pages);
if (si->vesapm_seg) {
- printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
+ dev_info(&dev->dev, "protected mode interface info at %04x:%04x\n",
si->vesapm_seg, si->vesapm_off);
}
@@ -352,9 +352,10 @@ static int vesafb_probe(struct platform_device *dev)
pmi_base = (unsigned short *)phys_to_virt(pmi_phys);
pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
pmi_pal = (void*)((char*)pmi_base + pmi_base[2]);
- printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+ dev_info(&dev->dev, "pmi: set display start = %p, set palette = %p\n",
+ pmi_start, pmi_pal);
if (pmi_base[3]) {
- printk(KERN_INFO "vesafb: pmi: ports = ");
+ dev_info(&dev->dev, "pmi: ports = ");
for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
printk("%x ", pmi_base[i]);
printk("\n");
@@ -365,14 +366,14 @@ static int vesafb_probe(struct platform_device *dev)
* Rules are: we have to set up a descriptor for the requested
* memory area and pass it in the ES register to the BIOS function.
*/
- printk(KERN_INFO "vesafb: can't handle memory requests, pmi disabled\n");
+ dev_info(&dev->dev, "can't handle memory requests, pmi disabled\n");
ypan = pmi_setpal = 0;
}
}
}
if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) {
- printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n"
+ dev_warn(&dev->dev, "hardware palette is unchangeable,\n"
" colors may be incorrect\n");
vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
}
@@ -380,10 +381,10 @@ static int vesafb_probe(struct platform_device *dev)
vesafb_defined.xres_virtual = vesafb_defined.xres;
vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length;
if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) {
- printk(KERN_INFO "vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
+ dev_info(&dev->dev, "scrolling: %s using protected mode interface, yres_virtual=%d\n",
(ypan > 1) ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
} else {
- printk(KERN_INFO "vesafb: scrolling: redraw\n");
+ dev_info(&dev->dev, "scrolling: redraw\n");
vesafb_defined.yres_virtual = vesafb_defined.yres;
ypan = 0;
}
@@ -410,7 +411,7 @@ static int vesafb_probe(struct platform_device *dev)
vesafb_defined.bits_per_pixel;
}
- printk(KERN_INFO "vesafb: %s: "
+ dev_info(&dev->dev, "%s: "
"size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
(vesafb_defined.bits_per_pixel > 8) ?
"Truecolor" : (vga_compat || pmi_setpal) ?
@@ -453,14 +454,14 @@ static int vesafb_probe(struct platform_device *dev)
}
if (!info->screen_base) {
- printk(KERN_ERR
- "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
+ dev_err(&dev->dev,
+ "abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
vesafb_fix.smem_len, vesafb_fix.smem_start);
err = -EIO;
goto err_release_region;
}
- printk(KERN_INFO "vesafb: framebuffer at 0x%lx, mapped to 0x%p, "
+ dev_info(&dev->dev, "framebuffer at 0x%lx, mapped to 0x%p, "
"using %dk, total %dk\n",
vesafb_fix.smem_start, info->screen_base,
size_remap/1024, size_total/1024);
diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c
index eedab14c7d51..6b81337a4909 100644
--- a/drivers/video/fbdev/vga16fb.c
+++ b/drivers/video/fbdev/vga16fb.c
@@ -1319,7 +1319,12 @@ static int vga16fb_probe(struct platform_device *dev)
if (ret)
return ret;
- printk(KERN_DEBUG "vga16fb: initializing\n");
+ dev_dbg(&dev->dev, "initializing\n");
+ if (!request_mem_region(vga16fb_fix.smem_start, vga16fb_fix.smem_len,
+ "vga16b")) {
+ dev_err(&dev->dev, "cannot reserve video memory at 0x%lx\n",
+ vga16fb_fix.smem_start);
+ }
info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);
if (!info) {
@@ -1331,12 +1336,12 @@ static int vga16fb_probe(struct platform_device *dev)
info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS_BASE, 0);
if (!info->screen_base) {
- printk(KERN_ERR "vga16fb: unable to map device\n");
+ dev_err(&dev->dev, "unable to map device\n");
ret = -ENOMEM;
goto err_ioremap;
}
- printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);
+ dev_info(&dev->dev, "mapped to 0x%p\n", info->screen_base);
par = info->par;
par->isVGA = screen_info_video_type(si) == VIDEO_TYPE_VGAC;
@@ -1364,13 +1369,13 @@ static int vga16fb_probe(struct platform_device *dev)
i = (info->var.bits_per_pixel == 8) ? 256 : 16;
ret = fb_alloc_cmap(&info->cmap, i, 0);
if (ret) {
- printk(KERN_ERR "vga16fb: unable to allocate colormap\n");
+ dev_err(&dev->dev, "unable to allocate colormap\n");
ret = -ENOMEM;
goto err_alloc_cmap;
}
if (vga16fb_check_var(&info->var, info)) {
- printk(KERN_ERR "vga16fb: unable to validate variable\n");
+ dev_err(&dev->dev, "unable to validate variable\n");
ret = -EINVAL;
goto err_check_var;
}
@@ -1381,7 +1386,7 @@ static int vga16fb_probe(struct platform_device *dev)
if (ret)
goto err_check_var;
if (register_framebuffer(info) < 0) {
- printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
+ dev_err(&dev->dev, "unable to register framebuffer\n");
ret = -EINVAL;
goto err_check_var;
}
@@ -1398,6 +1403,8 @@ static int vga16fb_probe(struct platform_device *dev)
err_ioremap:
framebuffer_release(info);
err_fb_alloc:
+ release_mem_region(vga16fb_fix.smem_start,
+ vga16fb_fix.smem_len);
return ret;
}
@@ -1407,6 +1414,8 @@ static void vga16fb_remove(struct platform_device *dev)
if (info)
unregister_framebuffer(info);
+ release_mem_region(vga16fb_fix.smem_start,
+ vga16fb_fix.smem_len);
}
static const struct platform_device_id vga16fb_driver_id_table[] = {