diff options
Diffstat (limited to 'drivers/video')
227 files changed, 3057 insertions, 5496 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 44c9ef1435a2..5df981920a94 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -39,6 +39,7 @@ source "drivers/gpu/vga/Kconfig" source "drivers/gpu/host1x/Kconfig" source "drivers/gpu/ipu-v3/Kconfig" +source "drivers/gpu/nova-core/Kconfig" source "drivers/gpu/drm/Kconfig" diff --git a/drivers/video/aperture.c b/drivers/video/aperture.c index 561be8feca96..2b5a1e666e9b 100644 --- a/drivers/video/aperture.c +++ b/drivers/video/aperture.c @@ -293,7 +293,7 @@ int aperture_remove_conflicting_devices(resource_size_t base, resource_size_t si * ask for this, so let's assume that a real driver for the display * was already probed and prevent sysfb to register devices later. */ - sysfb_disable(); + sysfb_disable(NULL); aperture_detach_devices(base, size); @@ -346,15 +346,10 @@ EXPORT_SYMBOL(__aperture_remove_legacy_vga_devices); */ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name) { - bool primary = false; resource_size_t base, size; int bar, ret = 0; - if (pdev == vga_default_device()) - primary = true; - - if (primary) - sysfb_disable(); + sysfb_disable(&pdev->dev); for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) @@ -370,7 +365,7 @@ int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *na * that consumes the VGA framebuffer I/O range. Remove this * device as well. */ - if (primary) + if (pdev == vga_default_device()) ret = __aperture_remove_legacy_vga_devices(pdev); return ret; diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 25e409bbb1a2..0a1db2824076 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c @@ -11,7 +11,6 @@ #include <linux/of.h> #include <linux/platform_device.h> #include <linux/slab.h> -#include <linux/fb.h> #include <linux/i2c.h> #include <linux/backlight.h> #include <linux/mfd/88pm860x.h> @@ -151,7 +150,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, struct pm860x_backlight_data *data, char *name) { - struct device_node *nproot, *np; + struct device_node *nproot; int iset = 0; nproot = of_get_child_by_name(pdev->dev.parent->of_node, "backlights"); @@ -159,14 +158,13 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev, dev_err(&pdev->dev, "failed to find backlights node\n"); return -ENODEV; } - for_each_child_of_node(nproot, np) { + for_each_child_of_node_scoped(nproot, np) { if (of_node_name_eq(np, name)) { of_property_read_u32(np, "marvell,88pm860x-iset", &iset); data->iset = PM8606_WLED_CURRENT(iset); of_property_read_u32(np, "marvell,88pm860x-pwm", &data->pwm); - of_node_put(np); break; } } diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 230bca07b09d..d9374d208cee 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig @@ -70,7 +70,7 @@ config LCD_ILI9320 then say y to include a power driver for it. config LCD_TDO24M - tristate "Toppoly TDO24M and TDO35S LCD Panels support" + tristate "Toppoly TDO24M and TDO35S LCD Panels support" depends on SPI_MASTER help If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to @@ -290,6 +290,17 @@ config BACKLIGHT_APPLE If you have an Intel-based Apple say Y to enable a driver for its backlight. +config BACKLIGHT_APPLE_DWI + tristate "Apple DWI 2-Wire Interface Backlight Driver" + depends on ARCH_APPLE || COMPILE_TEST + help + Say Y to enable the backlight driver for backlight controllers + attached via the Apple DWI 2-wire interface which is found in some + Apple iPhones, iPads and iPod touches. + + To compile this driver as a module, choose M here: the module will + be called apple_dwi_bl. + config BACKLIGHT_QCOM_WLED tristate "Qualcomm PMIC WLED Driver" select REGMAP @@ -359,13 +370,6 @@ config BACKLIGHT_88PM860X help Say Y to enable the backlight driver for Marvell 88PM8606. -config BACKLIGHT_PCF50633 - tristate "Backlight driver for NXP PCF50633 MFD" - depends on MFD_PCF50633 - help - If you have a backlight driven by a NXP PCF50633 MFD, say Y here to - enable its driver. - config BACKLIGHT_AAT2870 tristate "AnalogicTech AAT2870 Backlight" depends on MFD_AAT2870_CORE @@ -373,6 +377,13 @@ config BACKLIGHT_AAT2870 If you have a AnalogicTech AAT2870 say Y to enable the backlight driver. +config BACKLIGHT_LM3509 + tristate "Backlight Driver for LM3509" + depends on I2C + select REGMAP_I2C + help + This supports TI LM3509 Backlight Driver + config BACKLIGHT_LM3630A tristate "Backlight Driver for LM3630A" depends on I2C && PWM diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 8d2cb252042d..dfbb169bf6ea 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o 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_BD6107) += bd6107.o obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o @@ -36,6 +37,7 @@ obj-$(CONFIG_BACKLIGHT_IPAQ_MICRO) += ipaq_micro_bl.o obj-$(CONFIG_BACKLIGHT_KTD253) += ktd253-backlight.o obj-$(CONFIG_BACKLIGHT_KTD2801) += ktd2801-backlight.o obj-$(CONFIG_BACKLIGHT_KTZ8866) += ktz8866.o +obj-$(CONFIG_BACKLIGHT_LM3509) += lm3509_bl.o obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_bl.o obj-$(CONFIG_BACKLIGHT_LM3630A) += lm3630a_bl.o obj-$(CONFIG_BACKLIGHT_LM3639) += lm3639_bl.o @@ -48,7 +50,6 @@ obj-$(CONFIG_BACKLIGHT_MP3309C) += mp3309c.o obj-$(CONFIG_BACKLIGHT_MT6370) += mt6370-backlight.o obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o obj-$(CONFIG_BACKLIGHT_PANDORA) += pandora_bl.o -obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o obj-$(CONFIG_BACKLIGHT_QCOM_WLED) += qcom-wled.o obj-$(CONFIG_BACKLIGHT_RT4831) += rt4831-backlight.o diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c index 81fde3abb92c..8b790df1e842 100644 --- a/drivers/video/backlight/aat2870_bl.c +++ b/drivers/video/backlight/aat2870_bl.c @@ -12,7 +12,6 @@ #include <linux/platform_device.h> #include <linux/mutex.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/mfd/aat2870.h> @@ -90,15 +89,9 @@ static int aat2870_bl_update_status(struct backlight_device *bd) return 0; } -static int aat2870_bl_check_fb(struct backlight_device *bd, struct fb_info *fi) -{ - return 1; -} - static const struct backlight_ops aat2870_bl_ops = { .options = BL_CORE_SUSPENDRESUME, .update_status = aat2870_bl_update_status, - .check_fb = aat2870_bl_check_fb, }; static int aat2870_bl_probe(struct platform_device *pdev) @@ -163,7 +156,7 @@ static int aat2870_bl_probe(struct platform_device *pdev) bd->props.max_brightness = 255; aat2870_bl->brightness = 0; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; bd->props.brightness = bd->props.max_brightness; ret = aat2870_bl_update_status(bd); @@ -183,7 +176,7 @@ static void aat2870_bl_remove(struct platform_device *pdev) struct aat2870_bl_driver_data *aat2870_bl = platform_get_drvdata(pdev); struct backlight_device *bd = aat2870_bl->bd; - bd->props.power = FB_BLANK_POWERDOWN; + bd->props.power = BACKLIGHT_POWER_OFF; bd->props.brightness = 0; backlight_update_status(bd); } @@ -193,7 +186,7 @@ static struct platform_driver aat2870_bl_driver = { .name = "aat2870-backlight", }, .probe = aat2870_bl_probe, - .remove_new = aat2870_bl_remove, + .remove = aat2870_bl_remove, }; static int __init aat2870_bl_init(void) diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c index 8e0e9cfe5fe9..81c40d355aae 100644 --- a/drivers/video/backlight/adp5520_bl.c +++ b/drivers/video/backlight/adp5520_bl.c @@ -8,7 +8,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/mfd/adp5520.h> #include <linux/slab.h> @@ -375,7 +374,7 @@ static struct platform_driver adp5520_bl_driver = { .pm = &adp5520_bl_pm_ops, }, .probe = adp5520_bl_probe, - .remove_new = adp5520_bl_remove, + .remove = adp5520_bl_remove, }; module_platform_driver(adp5520_bl_driver); diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index f51ada4795e8..d4bbd7a7406b 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -11,7 +11,6 @@ #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/i2c.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/leds.h> #include <linux/slab.h> diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 6bb18dc970e9..e09e20492e7c 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -11,7 +11,6 @@ #include <linux/pm.h> #include <linux/platform_device.h> #include <linux/i2c.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/leds.h> #include <linux/workqueue.h> @@ -963,7 +962,7 @@ static SIMPLE_DEV_PM_OPS(adp8870_i2c_pm_ops, adp8870_i2c_suspend, adp8870_i2c_resume); static const struct i2c_device_id adp8870_id[] = { - { "adp8870", 0 }, + { "adp8870" }, { } }; MODULE_DEVICE_TABLE(i2c, adp8870_id); diff --git a/drivers/video/backlight/ams369fg06.c b/drivers/video/backlight/ams369fg06.c index 522dd81110b8..f8442689ac43 100644 --- a/drivers/video/backlight/ams369fg06.c +++ b/drivers/video/backlight/ams369fg06.c @@ -10,7 +10,6 @@ #include <linux/backlight.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/lcd.h> #include <linux/module.h> #include <linux/spi/spi.h> @@ -300,7 +299,7 @@ static int ams369fg06_ldi_disable(struct ams369fg06 *lcd) static int ams369fg06_power_is_on(int power) { - return power <= FB_BLANK_NORMAL; + return power <= BACKLIGHT_POWER_REDUCED; } static int ams369fg06_power_on(struct ams369fg06 *lcd) @@ -396,8 +395,8 @@ static int ams369fg06_set_power(struct lcd_device *ld, int power) { struct ams369fg06 *lcd = lcd_get_data(ld); - if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && - power != FB_BLANK_NORMAL) { + if (power != BACKLIGHT_POWER_ON && power != BACKLIGHT_POWER_OFF && + power != BACKLIGHT_POWER_REDUCED) { dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); return -EINVAL; } @@ -427,7 +426,7 @@ static int ams369fg06_set_brightness(struct backlight_device *bd) return ret; } -static struct lcd_ops ams369fg06_lcd_ops = { +static const struct lcd_ops ams369fg06_lcd_ops = { .get_power = ams369fg06_get_power, .set_power = ams369fg06_set_power, }; @@ -492,11 +491,11 @@ static int ams369fg06_probe(struct spi_device *spi) * current lcd status is powerdown and then * it enables lcd panel. */ - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = BACKLIGHT_POWER_OFF; - ams369fg06_power(lcd, FB_BLANK_UNBLANK); + ams369fg06_power(lcd, BACKLIGHT_POWER_ON); } else { - lcd->power = FB_BLANK_UNBLANK; + lcd->power = BACKLIGHT_POWER_ON; } spi_set_drvdata(spi, lcd); @@ -510,7 +509,7 @@ static void ams369fg06_remove(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); - ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } #ifdef CONFIG_PM_SLEEP @@ -524,16 +523,16 @@ static int ams369fg06_suspend(struct device *dev) * when lcd panel is suspend, lcd panel becomes off * regardless of status. */ - return ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + return ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } static int ams369fg06_resume(struct device *dev) { struct ams369fg06 *lcd = dev_get_drvdata(dev); - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = BACKLIGHT_POWER_OFF; - return ams369fg06_power(lcd, FB_BLANK_UNBLANK); + return ams369fg06_power(lcd, BACKLIGHT_POWER_ON); } #endif @@ -544,7 +543,7 @@ static void ams369fg06_shutdown(struct spi_device *spi) { struct ams369fg06 *lcd = spi_get_drvdata(spi); - ams369fg06_power(lcd, FB_BLANK_POWERDOWN); + ams369fg06_power(lcd, BACKLIGHT_POWER_OFF); } static struct spi_driver ams369fg06_driver = { diff --git a/drivers/video/backlight/apple_dwi_bl.c b/drivers/video/backlight/apple_dwi_bl.c new file mode 100644 index 000000000000..93bd744972d6 --- /dev/null +++ b/drivers/video/backlight/apple_dwi_bl.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Driver for backlight controllers attached via Apple DWI 2-wire interface + * + * Copyright (c) 2024 Nick Chan <towinchenmi@gmail.com> + */ + +#include <linux/backlight.h> +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#define DWI_BL_CTL 0x0 +#define DWI_BL_CTL_SEND1 BIT(0) +#define DWI_BL_CTL_SEND2 BIT(4) +#define DWI_BL_CTL_SEND3 BIT(5) +#define DWI_BL_CTL_LE_DATA BIT(6) +/* Only used on Apple A9 and later */ +#define DWI_BL_CTL_SEND4 BIT(12) + +#define DWI_BL_CMD 0x4 +#define DWI_BL_CMD_TYPE GENMASK(31, 28) +#define DWI_BL_CMD_TYPE_SET_BRIGHTNESS 0xa +#define DWI_BL_CMD_DATA GENMASK(10, 0) + +#define DWI_BL_CTL_SEND (DWI_BL_CTL_SEND1 | \ + DWI_BL_CTL_SEND2 | \ + DWI_BL_CTL_SEND3 | \ + DWI_BL_CTL_LE_DATA | \ + DWI_BL_CTL_SEND4) + +#define DWI_BL_MAX_BRIGHTNESS 2047 + +struct apple_dwi_bl { + void __iomem *base; +}; + +static int dwi_bl_update_status(struct backlight_device *bl) +{ + struct apple_dwi_bl *dwi_bl = bl_get_data(bl); + + int brightness = backlight_get_brightness(bl); + + u32 cmd = 0; + + cmd |= FIELD_PREP(DWI_BL_CMD_DATA, brightness); + cmd |= FIELD_PREP(DWI_BL_CMD_TYPE, DWI_BL_CMD_TYPE_SET_BRIGHTNESS); + + writel(cmd, dwi_bl->base + DWI_BL_CMD); + writel(DWI_BL_CTL_SEND, dwi_bl->base + DWI_BL_CTL); + + return 0; +} + +static int dwi_bl_get_brightness(struct backlight_device *bl) +{ + struct apple_dwi_bl *dwi_bl = bl_get_data(bl); + + u32 cmd = readl(dwi_bl->base + DWI_BL_CMD); + + return FIELD_GET(DWI_BL_CMD_DATA, cmd); +} + +static const struct backlight_ops dwi_bl_ops = { + .options = BL_CORE_SUSPENDRESUME, + .get_brightness = dwi_bl_get_brightness, + .update_status = dwi_bl_update_status +}; + +static int dwi_bl_probe(struct platform_device *dev) +{ + struct apple_dwi_bl *dwi_bl; + struct backlight_device *bl; + struct backlight_properties props; + struct resource *res; + + dwi_bl = devm_kzalloc(&dev->dev, sizeof(*dwi_bl), GFP_KERNEL); + if (!dwi_bl) + return -ENOMEM; + + dwi_bl->base = devm_platform_get_and_ioremap_resource(dev, 0, &res); + if (IS_ERR(dwi_bl->base)) + return PTR_ERR(dwi_bl->base); + + memset(&props, 0, sizeof(struct backlight_properties)); + props.type = BACKLIGHT_PLATFORM; + props.max_brightness = DWI_BL_MAX_BRIGHTNESS; + props.scale = BACKLIGHT_SCALE_LINEAR; + + bl = devm_backlight_device_register(&dev->dev, dev->name, &dev->dev, + dwi_bl, &dwi_bl_ops, &props); + if (IS_ERR(bl)) + return PTR_ERR(bl); + + platform_set_drvdata(dev, dwi_bl); + + bl->props.brightness = dwi_bl_get_brightness(bl); + + return 0; +} + +static const struct of_device_id dwi_bl_of_match[] = { + { .compatible = "apple,dwi-bl" }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dwi_bl_of_match); + +static struct platform_driver dwi_bl_driver = { + .driver = { + .name = "apple-dwi-bl", + .of_match_table = dwi_bl_of_match + }, + .probe = dwi_bl_probe, +}; + +module_platform_driver(dwi_bl_driver); + +MODULE_DESCRIPTION("Apple DWI Backlight Driver"); +MODULE_AUTHOR("Nick Chan <towinchenmi@gmail.com>"); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c index e6f66bb35ef5..9f89eb19894e 100644 --- a/drivers/video/backlight/as3711_bl.c +++ b/drivers/video/backlight/as3711_bl.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/kernel.h> #include <linux/mfd/as3711.h> #include <linux/module.h> diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index 86e1cdc8e369..f699e5827ccb 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -65,7 +65,6 @@ static struct list_head backlight_dev_list; static struct mutex backlight_dev_list_mutex; -static struct blocking_notifier_head backlight_notifier; static const char *const backlight_types[] = { [BACKLIGHT_RAW] = "raw", @@ -98,7 +97,9 @@ static int fb_notifier_callback(struct notifier_block *self, { struct backlight_device *bd; struct fb_event *evdata = data; - int node = evdata->info->node; + struct fb_info *info = evdata->info; + struct backlight_device *fb_bd = fb_bl_device(info); + int node = info->node; int fb_blank = 0; /* If we aren't interested in this event, skip it immediately ... */ @@ -110,7 +111,9 @@ static int fb_notifier_callback(struct notifier_block *self, if (!bd->ops) goto out; - if (bd->ops->check_fb && !bd->ops->check_fb(bd, evdata->info)) + if (bd->ops->controls_device && !bd->ops->controls_device(bd, info->device)) + goto out; + if (fb_bd && fb_bd != bd) goto out; fb_blank = *(int *)evdata->data; @@ -118,14 +121,12 @@ static int fb_notifier_callback(struct notifier_block *self, bd->fb_bl_on[node] = true; if (!bd->use_count++) { bd->props.state &= ~BL_CORE_FBBLANK; - bd->props.fb_blank = FB_BLANK_UNBLANK; backlight_update_status(bd); } } else if (fb_blank != FB_BLANK_UNBLANK && bd->fb_bl_on[node]) { bd->fb_bl_on[node] = false; if (!(--bd->use_count)) { bd->props.state |= BL_CORE_FBBLANK; - bd->props.fb_blank = fb_blank; backlight_update_status(bd); } } @@ -317,8 +318,6 @@ static ssize_t scale_show(struct device *dev, } static DEVICE_ATTR_RO(scale); -static struct class *backlight_class; - #ifdef CONFIG_PM_SLEEP static int backlight_suspend(struct device *dev) { @@ -369,6 +368,12 @@ static struct attribute *bl_device_attrs[] = { }; ATTRIBUTE_GROUPS(bl_device); +static const struct class backlight_class = { + .name = "backlight", + .dev_groups = bl_device_groups, + .pm = &backlight_class_dev_pm_ops, +}; + /** * backlight_force_update - tell the backlight subsystem that hardware state * has changed @@ -418,7 +423,7 @@ struct backlight_device *backlight_device_register(const char *name, mutex_init(&new_bd->update_lock); mutex_init(&new_bd->ops_lock); - new_bd->dev.class = backlight_class; + new_bd->dev.class = &backlight_class; new_bd->dev.parent = parent; new_bd->dev.release = bl_device_release; dev_set_name(&new_bd->dev, "%s", name); @@ -461,9 +466,6 @@ struct backlight_device *backlight_device_register(const char *name, list_add(&new_bd->entry, &backlight_dev_list); mutex_unlock(&backlight_dev_list_mutex); - blocking_notifier_call_chain(&backlight_notifier, - BACKLIGHT_REGISTERED, new_bd); - return new_bd; } EXPORT_SYMBOL(backlight_device_register); @@ -510,7 +512,7 @@ struct backlight_device *backlight_device_get_by_name(const char *name) { struct device *dev; - dev = class_find_device_by_name(backlight_class, name); + dev = class_find_device_by_name(&backlight_class, name); return dev ? to_backlight_device(dev) : NULL; } @@ -533,9 +535,6 @@ void backlight_device_unregister(struct backlight_device *bd) mutex_unlock(&pmac_backlight_mutex); #endif - blocking_notifier_call_chain(&backlight_notifier, - BACKLIGHT_UNREGISTERED, bd); - mutex_lock(&bd->ops_lock); bd->ops = NULL; mutex_unlock(&bd->ops_lock); @@ -561,40 +560,6 @@ static int devm_backlight_device_match(struct device *dev, void *res, } /** - * backlight_register_notifier - get notified of backlight (un)registration - * @nb: notifier block with the notifier to call on backlight (un)registration - * - * Register a notifier to get notified when backlight devices get registered - * or unregistered. - * - * RETURNS: - * - * 0 on success, otherwise a negative error code - */ -int backlight_register_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&backlight_notifier, nb); -} -EXPORT_SYMBOL(backlight_register_notifier); - -/** - * backlight_unregister_notifier - unregister a backlight notifier - * @nb: notifier block to unregister - * - * Register a notifier to get notified when backlight devices get registered - * or unregistered. - * - * RETURNS: - * - * 0 on success, otherwise a negative error code - */ -int backlight_unregister_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&backlight_notifier, nb); -} -EXPORT_SYMBOL(backlight_unregister_notifier); - -/** * devm_backlight_device_register - register a new backlight device * @dev: the device to register * @name: the name of the device @@ -678,7 +643,7 @@ struct backlight_device *of_find_backlight_by_node(struct device_node *node) { struct device *dev; - dev = class_find_device(backlight_class, NULL, node, of_parent_match); + dev = class_find_device(&backlight_class, NULL, node, of_parent_match); return dev ? to_backlight_device(dev) : NULL; } @@ -746,23 +711,21 @@ EXPORT_SYMBOL(devm_of_find_backlight); static void __exit backlight_class_exit(void) { - class_destroy(backlight_class); + class_unregister(&backlight_class); } static int __init backlight_class_init(void) { - backlight_class = class_create("backlight"); - if (IS_ERR(backlight_class)) { - pr_warn("Unable to create backlight class; errno = %ld\n", - PTR_ERR(backlight_class)); - return PTR_ERR(backlight_class); + int ret; + + ret = class_register(&backlight_class); + if (ret) { + pr_warn("Unable to create backlight class; errno = %d\n", ret); + return ret; } - backlight_class->dev_groups = bl_device_groups; - backlight_class->pm = &backlight_class_dev_pm_ops; INIT_LIST_HEAD(&backlight_dev_list); mutex_init(&backlight_dev_list_mutex); - BLOCKING_INIT_NOTIFIER_HEAD(&backlight_notifier); return 0; } diff --git a/drivers/video/backlight/bd6107.c b/drivers/video/backlight/bd6107.c index b1e7126380ef..74567af84e97 100644 --- a/drivers/video/backlight/bd6107.c +++ b/drivers/video/backlight/bd6107.c @@ -10,7 +10,6 @@ #include <linux/backlight.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> @@ -99,18 +98,18 @@ static int bd6107_backlight_update_status(struct backlight_device *backlight) return 0; } -static int bd6107_backlight_check_fb(struct backlight_device *backlight, - struct fb_info *info) +static bool bd6107_backlight_controls_device(struct backlight_device *backlight, + struct device *display_dev) { struct bd6107 *bd = bl_get_data(backlight); - return !bd->pdata->dev || bd->pdata->dev == info->device; + return !bd->pdata->dev || bd->pdata->dev == display_dev; } static const struct backlight_ops bd6107_backlight_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = bd6107_backlight_update_status, - .check_fb = bd6107_backlight_check_fb, + .options = BL_CORE_SUSPENDRESUME, + .update_status = bd6107_backlight_update_status, + .controls_device = bd6107_backlight_controls_device, }; static int bd6107_probe(struct i2c_client *client) @@ -180,7 +179,7 @@ static void bd6107_remove(struct i2c_client *client) } static const struct i2c_device_id bd6107_ids[] = { - { "bd6107", 0 }, + { "bd6107" }, { } }; MODULE_DEVICE_TABLE(i2c, bd6107_ids); diff --git a/drivers/video/backlight/corgi_lcd.c b/drivers/video/backlight/corgi_lcd.c index dd765098ad98..69f49371ea35 100644 --- a/drivers/video/backlight/corgi_lcd.c +++ b/drivers/video/backlight/corgi_lcd.c @@ -17,14 +17,13 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> -#include <linux/fb.h> #include <linux/lcd.h> #include <linux/spi/spi.h> #include <linux/spi/corgi_lcd.h> #include <linux/slab.h> #include <asm/mach/sharpsl_param.h> -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) /* Register Addresses */ #define RESCTL_ADRS 0x00 @@ -332,12 +331,12 @@ static void corgi_lcd_power_off(struct corgi_lcd *lcd) POWER1_VW_OFF | POWER1_GVSS_OFF | POWER1_VDD_OFF); } -static int corgi_lcd_set_mode(struct lcd_device *ld, struct fb_videomode *m) +static int corgi_lcd_set_mode(struct lcd_device *ld, u32 xres, u32 yres) { struct corgi_lcd *lcd = lcd_get_data(ld); int mode = CORGI_LCD_MODE_QVGA; - if (m->xres == 640 || m->xres == 480) + if (xres == 640 || xres == 480) mode = CORGI_LCD_MODE_VGA; if (lcd->mode == mode) @@ -380,7 +379,7 @@ static int corgi_lcd_get_power(struct lcd_device *ld) return lcd->power; } -static struct lcd_ops corgi_lcd_ops = { +static const struct lcd_ops corgi_lcd_ops = { .get_power = corgi_lcd_get_power, .set_power = corgi_lcd_set_power, .set_mode = corgi_lcd_set_mode, @@ -455,7 +454,7 @@ static int corgi_lcd_suspend(struct device *dev) corgibl_flags |= CORGIBL_SUSPENDED; corgi_bl_set_intensity(lcd, 0); - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); + corgi_lcd_set_power(lcd->lcd_dev, LCD_POWER_OFF); return 0; } @@ -464,7 +463,7 @@ static int corgi_lcd_resume(struct device *dev) struct corgi_lcd *lcd = dev_get_drvdata(dev); corgibl_flags &= ~CORGIBL_SUSPENDED; - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); + corgi_lcd_set_power(lcd->lcd_dev, LCD_POWER_ON); backlight_update_status(lcd->bl_dev); return 0; } @@ -513,7 +512,7 @@ static int corgi_lcd_probe(struct spi_device *spi) if (IS_ERR(lcd->lcd_dev)) return PTR_ERR(lcd->lcd_dev); - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = LCD_POWER_OFF; lcd->mode = (pdata) ? pdata->init_mode : CORGI_LCD_MODE_VGA; memset(&props, 0, sizeof(struct backlight_properties)); @@ -526,7 +525,7 @@ static int corgi_lcd_probe(struct spi_device *spi) return PTR_ERR(lcd->bl_dev); lcd->bl_dev->props.brightness = pdata->default_intensity; - lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + lcd->bl_dev->props.power = BACKLIGHT_POWER_ON; ret = setup_gpio_backlight(lcd, pdata); if (ret) @@ -535,7 +534,7 @@ static int corgi_lcd_probe(struct spi_device *spi) lcd->kick_battery = pdata->kick_battery; spi_set_drvdata(spi, lcd); - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_UNBLANK); + corgi_lcd_set_power(lcd->lcd_dev, LCD_POWER_ON); backlight_update_status(lcd->bl_dev); lcd->limit_mask = pdata->limit_mask; @@ -547,10 +546,10 @@ static void corgi_lcd_remove(struct spi_device *spi) { struct corgi_lcd *lcd = spi_get_drvdata(spi); - lcd->bl_dev->props.power = FB_BLANK_UNBLANK; + lcd->bl_dev->props.power = BACKLIGHT_POWER_ON; lcd->bl_dev->props.brightness = 0; backlight_update_status(lcd->bl_dev); - corgi_lcd_set_power(lcd->lcd_dev, FB_BLANK_POWERDOWN); + corgi_lcd_set_power(lcd->lcd_dev, LCD_POWER_OFF); } static struct spi_driver corgi_lcd_driver = { diff --git a/drivers/video/backlight/da903x_bl.c b/drivers/video/backlight/da903x_bl.c index 71f21bbc7a9f..81ff42bec0ad 100644 --- a/drivers/video/backlight/da903x_bl.c +++ b/drivers/video/backlight/da903x_bl.c @@ -12,7 +12,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/mfd/da903x.h> #include <linux/slab.h> diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c index b8ff7046510e..f41523d78121 100644 --- a/drivers/video/backlight/da9052_bl.c +++ b/drivers/video/backlight/da9052_bl.c @@ -9,7 +9,6 @@ #include <linux/backlight.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -165,7 +164,7 @@ MODULE_DEVICE_TABLE(platform, da9052_wled_ids); static struct platform_driver da9052_wled_driver = { .probe = da9052_backlight_probe, - .remove_new = da9052_backlight_remove, + .remove = da9052_backlight_remove, .id_table = da9052_wled_ids, .driver = { .name = "da9052-wled", diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c index 2387009d452d..f59effc02352 100644 --- a/drivers/video/backlight/ep93xx_bl.c +++ b/drivers/video/backlight/ep93xx_bl.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/io.h> -#include <linux/fb.h> #include <linux/backlight.h> #define EP93XX_MAX_COUNT 255 diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c index e0c8c2a3f5dc..728a546904b0 100644 --- a/drivers/video/backlight/gpio_backlight.c +++ b/drivers/video/backlight/gpio_backlight.c @@ -5,7 +5,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/kernel.h> @@ -30,18 +29,18 @@ static int gpio_backlight_update_status(struct backlight_device *bl) return 0; } -static int gpio_backlight_check_fb(struct backlight_device *bl, - struct fb_info *info) +static bool gpio_backlight_controls_device(struct backlight_device *bl, + struct device *display_dev) { struct gpio_backlight *gbl = bl_get_data(bl); - return !gbl->dev || gbl->dev == info->device; + return !gbl->dev || gbl->dev == display_dev; } static const struct backlight_ops gpio_backlight_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = gpio_backlight_update_status, - .check_fb = gpio_backlight_check_fb, + .options = BL_CORE_SUSPENDRESUME, + .update_status = gpio_backlight_update_status, + .controls_device = gpio_backlight_controls_device, }; static int gpio_backlight_probe(struct platform_device *pdev) @@ -81,12 +80,12 @@ static int gpio_backlight_probe(struct platform_device *pdev) /* Set the initial power state */ if (!of_node || !of_node->phandle) /* Not booted with device tree or no phandle link to the node */ - bl->props.power = def_value ? FB_BLANK_UNBLANK - : FB_BLANK_POWERDOWN; + bl->props.power = def_value ? BACKLIGHT_POWER_ON + : BACKLIGHT_POWER_OFF; else if (gpiod_get_value_cansleep(gbl->gpiod) == 0) - bl->props.power = FB_BLANK_POWERDOWN; + bl->props.power = BACKLIGHT_POWER_OFF; else - bl->props.power = FB_BLANK_UNBLANK; + bl->props.power = BACKLIGHT_POWER_ON; bl->props.brightness = 1; diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index ddb7ab4df77e..d8c2e4ada384 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -15,7 +15,6 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/spinlock.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <cpu/dac.h> @@ -130,7 +129,7 @@ static void hp680bl_remove(struct platform_device *pdev) static struct platform_driver hp680bl_driver = { .probe = hp680bl_probe, - .remove_new = hp680bl_remove, + .remove = hp680bl_remove, .driver = { .name = "hp680-bl", .pm = &hp680bl_pm_ops, diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c index 339d9128fbde..61a57d38700f 100644 --- a/drivers/video/backlight/hx8357.c +++ b/drivers/video/backlight/hx8357.c @@ -532,7 +532,7 @@ static int hx8369_lcd_init(struct lcd_device *lcdev) return 0; } -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) static int hx8357_set_power(struct lcd_device *lcdev, int power) { @@ -559,7 +559,7 @@ static int hx8357_get_power(struct lcd_device *lcdev) return lcd->state; } -static struct lcd_ops hx8357_ops = { +static const struct lcd_ops hx8357_ops = { .set_power = hx8357_set_power, .get_power = hx8357_get_power, }; diff --git a/drivers/video/backlight/ili922x.c b/drivers/video/backlight/ili922x.c index c8e0e655dc86..5e1bf0c5831f 100644 --- a/drivers/video/backlight/ili922x.c +++ b/drivers/video/backlight/ili922x.c @@ -8,7 +8,6 @@ * memory is cyclically updated over the RGB interface. */ -#include <linux/fb.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/init.h> @@ -119,7 +118,7 @@ #define CMD_BUFSIZE 16 -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) #define set_tx_byte(b) (tx_invert ? ~(b) : b) @@ -472,7 +471,7 @@ static int ili922x_get_power(struct lcd_device *ld) return ili->power; } -static struct lcd_ops ili922x_ops = { +static const struct lcd_ops ili922x_ops = { .get_power = ili922x_get_power, .set_power = ili922x_set_power, }; @@ -513,7 +512,7 @@ static int ili922x_probe(struct spi_device *spi) ili922x_display_init(spi); - ili->power = FB_BLANK_POWERDOWN; + ili->power = LCD_POWER_OFF; lcd = devm_lcd_device_register(&spi->dev, "ili922xlcd", &spi->dev, ili, &ili922x_ops); @@ -525,7 +524,7 @@ static int ili922x_probe(struct spi_device *spi) ili->ld = lcd; spi_set_drvdata(spi, ili); - ili922x_lcd_power(ili, FB_BLANK_UNBLANK); + ili922x_lcd_power(ili, LCD_POWER_ON); return 0; } diff --git a/drivers/video/backlight/ili9320.c b/drivers/video/backlight/ili9320.c index 2acd2708f8ca..2df96a882119 100644 --- a/drivers/video/backlight/ili9320.c +++ b/drivers/video/backlight/ili9320.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/lcd.h> #include <linux/module.h> @@ -121,7 +120,7 @@ static inline int ili9320_power_off(struct ili9320 *lcd) return 0; } -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) static int ili9320_power(struct ili9320 *lcd, int power) { @@ -161,7 +160,7 @@ static int ili9320_get_power(struct lcd_device *ld) return lcd->power; } -static struct lcd_ops ili9320_ops = { +static const struct lcd_ops ili9320_ops = { .get_power = ili9320_get_power, .set_power = ili9320_set_power, }; @@ -223,7 +222,7 @@ int ili9320_probe_spi(struct spi_device *spi, ili->dev = dev; ili->client = client; - ili->power = FB_BLANK_POWERDOWN; + ili->power = LCD_POWER_OFF; ili->platdata = cfg; spi_set_drvdata(spi, ili); @@ -241,7 +240,7 @@ int ili9320_probe_spi(struct spi_device *spi, dev_info(dev, "initialising %s\n", client->name); - ret = ili9320_power(ili, FB_BLANK_UNBLANK); + ret = ili9320_power(ili, LCD_POWER_ON); if (ret != 0) { dev_err(dev, "failed to set lcd power state\n"); return ret; @@ -253,7 +252,7 @@ EXPORT_SYMBOL_GPL(ili9320_probe_spi); void ili9320_remove(struct ili9320 *ili) { - ili9320_power(ili, FB_BLANK_POWERDOWN); + ili9320_power(ili, LCD_POWER_OFF); } EXPORT_SYMBOL_GPL(ili9320_remove); @@ -262,7 +261,7 @@ int ili9320_suspend(struct ili9320 *lcd) { int ret; - ret = ili9320_power(lcd, FB_BLANK_POWERDOWN); + ret = ili9320_power(lcd, LCD_POWER_OFF); if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) { ili9320_write(lcd, ILI9320_POWER1, lcd->power1 | @@ -282,7 +281,7 @@ int ili9320_resume(struct ili9320 *lcd) if (lcd->platdata->suspend == ILI9320_SUSPEND_DEEP) ili9320_write(lcd, ILI9320_POWER1, 0x00); - return ili9320_power(lcd, FB_BLANK_UNBLANK); + return ili9320_power(lcd, LCD_POWER_ON); } EXPORT_SYMBOL_GPL(ili9320_resume); #endif @@ -290,7 +289,7 @@ EXPORT_SYMBOL_GPL(ili9320_resume); /* Power down all displays on reboot, poweroff or halt */ void ili9320_shutdown(struct ili9320 *lcd) { - ili9320_power(lcd, FB_BLANK_POWERDOWN); + ili9320_power(lcd, LCD_POWER_OFF); } EXPORT_SYMBOL_GPL(ili9320_shutdown); diff --git a/drivers/video/backlight/ipaq_micro_bl.c b/drivers/video/backlight/ipaq_micro_bl.c index f595b8c8cbb2..19ff66e444bc 100644 --- a/drivers/video/backlight/ipaq_micro_bl.c +++ b/drivers/video/backlight/ipaq_micro_bl.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/mfd/ipaq-micro.h> #include <linux/module.h> @@ -42,7 +41,7 @@ static const struct backlight_ops micro_bl_ops = { static const struct backlight_properties micro_bl_props = { .type = BACKLIGHT_RAW, .max_brightness = 255, - .power = FB_BLANK_UNBLANK, + .power = BACKLIGHT_POWER_ON, .brightness = 64, }; diff --git a/drivers/video/backlight/jornada720_bl.c b/drivers/video/backlight/jornada720_bl.c index 066d0dc98f60..e28d2c071798 100644 --- a/drivers/video/backlight/jornada720_bl.c +++ b/drivers/video/backlight/jornada720_bl.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/device.h> -#include <linux/fb.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -121,7 +120,7 @@ static int jornada_bl_probe(struct platform_device *pdev) return ret; } - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; bd->props.brightness = BL_DEF_BRIGHT; /* * note. make sure max brightness is set otherwise diff --git a/drivers/video/backlight/jornada720_lcd.c b/drivers/video/backlight/jornada720_lcd.c index 6796a7c2db25..31a52dee9060 100644 --- a/drivers/video/backlight/jornada720_lcd.c +++ b/drivers/video/backlight/jornada720_lcd.c @@ -6,7 +6,7 @@ */ #include <linux/device.h> -#include <linux/fb.h> +#include <linux/io.h> #include <linux/kernel.h> #include <linux/lcd.h> #include <linux/module.h> @@ -23,14 +23,14 @@ static int jornada_lcd_get_power(struct lcd_device *ld) { - return PPSR & PPC_LDD2 ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN; + return PPSR & PPC_LDD2 ? LCD_POWER_ON : LCD_POWER_OFF; } static int jornada_lcd_get_contrast(struct lcd_device *ld) { int ret; - if (jornada_lcd_get_power(ld) != FB_BLANK_UNBLANK) + if (jornada_lcd_get_power(ld) != LCD_POWER_ON) return 0; jornada_ssp_start(); @@ -71,7 +71,7 @@ success: static int jornada_lcd_set_power(struct lcd_device *ld, int power) { - if (power != FB_BLANK_UNBLANK) { + if (power != LCD_POWER_ON) { PPSR &= ~PPC_LDD2; PPDR |= PPC_LDD2; } else { @@ -81,7 +81,7 @@ static int jornada_lcd_set_power(struct lcd_device *ld, int power) return 0; } -static struct lcd_ops jornada_lcd_props = { +static const struct lcd_ops jornada_lcd_props = { .get_contrast = jornada_lcd_get_contrast, .set_contrast = jornada_lcd_set_contrast, .get_power = jornada_lcd_get_power, @@ -106,7 +106,7 @@ static int jornada_lcd_probe(struct platform_device *pdev) /* lets set our default values */ jornada_lcd_set_contrast(lcd_device, LCD_DEF_CONTRAST); - jornada_lcd_set_power(lcd_device, FB_BLANK_UNBLANK); + jornada_lcd_set_power(lcd_device, LCD_POWER_ON); /* give it some time to startup */ msleep(100); diff --git a/drivers/video/backlight/kb3886_bl.c b/drivers/video/backlight/kb3886_bl.c index 55794b239cff..050b5c21f4a8 100644 --- a/drivers/video/backlight/kb3886_bl.c +++ b/drivers/video/backlight/kb3886_bl.c @@ -10,9 +10,9 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> +#include <linux/io.h> #include <linux/platform_device.h> #include <linux/mutex.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/delay.h> #include <linux/dmi.h> @@ -151,7 +151,7 @@ static int kb3886bl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, kb3886_backlight_device); - kb3886_backlight_device->props.power = FB_BLANK_UNBLANK; + kb3886_backlight_device->props.power = BACKLIGHT_POWER_ON; kb3886_backlight_device->props.brightness = machinfo->default_intensity; backlight_update_status(kb3886_backlight_device); diff --git a/drivers/video/backlight/ktd253-backlight.c b/drivers/video/backlight/ktd253-backlight.c index d7d43454f64a..327b4ee75254 100644 --- a/drivers/video/backlight/ktd253-backlight.c +++ b/drivers/video/backlight/ktd253-backlight.c @@ -7,7 +7,6 @@ #include <linux/backlight.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/gpio/consumer.h> #include <linux/init.h> #include <linux/kernel.h> @@ -190,10 +189,10 @@ static int ktd253_backlight_probe(struct platform_device *pdev) /* When we just enable the GPIO line we set max brightness */ if (brightness) { bl->props.brightness = brightness; - bl->props.power = FB_BLANK_UNBLANK; + bl->props.power = BACKLIGHT_POWER_ON; } else { bl->props.brightness = 0; - bl->props.power = FB_BLANK_POWERDOWN; + bl->props.power = BACKLIGHT_POWER_OFF; } ktd253->bl = bl; diff --git a/drivers/video/backlight/ktd2801-backlight.c b/drivers/video/backlight/ktd2801-backlight.c index d295c2766025..0489b0615ceb 100644 --- a/drivers/video/backlight/ktd2801-backlight.c +++ b/drivers/video/backlight/ktd2801-backlight.c @@ -122,7 +122,7 @@ static struct platform_driver ktd2801_backlight_driver = { }; module_platform_driver(ktd2801_backlight_driver); -MODULE_IMPORT_NS(EXPRESSWIRE); +MODULE_IMPORT_NS("EXPRESSWIRE"); MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>"); MODULE_DESCRIPTION("Kinetic KTD2801 Backlight Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/ktz8866.c b/drivers/video/backlight/ktz8866.c index 014877b5a984..351c2b4d63ed 100644 --- a/drivers/video/backlight/ktz8866.c +++ b/drivers/video/backlight/ktz8866.c @@ -179,8 +179,8 @@ static void ktz8866_remove(struct i2c_client *client) } static const struct i2c_device_id ktz8866_ids[] = { - { "ktz8866", 0 }, - {}, + { "ktz8866" }, + {} }; MODULE_DEVICE_TABLE(i2c, ktz8866_ids); @@ -190,6 +190,7 @@ static const struct of_device_id ktz8866_match_table[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, ktz8866_match_table); static struct i2c_driver ktz8866_driver = { .driver = { diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index bd5137ee203b..d04d2256306e 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c @@ -112,40 +112,40 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) const u16 slpin = 0x10; const u16 disoff = 0x28; - if (power <= FB_BLANK_NORMAL) { - if (priv->lcd_state <= FB_BLANK_NORMAL) { + if (power <= LCD_POWER_REDUCED) { + if (priv->lcd_state <= LCD_POWER_REDUCED) { /* Do nothing, the LCD is running */ - } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { + } else if (priv->lcd_state < LCD_POWER_OFF) { dev_dbg(&spi->dev, "Resuming LCD\n"); spi_write(spi, (const u8 *)&slpout, sizeof(u16)); msleep(60); spi_write(spi, (const u8 *)&dison, sizeof(u16)); } else { - /* priv->lcd_state == FB_BLANK_POWERDOWN */ + /* priv->lcd_state == LCD_POWER_OFF */ l4f00242t03_lcd_init(spi); - priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; + priv->lcd_state = LCD_POWER_REDUCED_VSYNC_SUSPEND; l4f00242t03_lcd_power_set(priv->ld, power); } - } else if (power < FB_BLANK_POWERDOWN) { - if (priv->lcd_state <= FB_BLANK_NORMAL) { + } else if (power < LCD_POWER_OFF) { + if (priv->lcd_state <= LCD_POWER_REDUCED) { /* Send the display in standby */ dev_dbg(&spi->dev, "Standby the LCD\n"); spi_write(spi, (const u8 *)&disoff, sizeof(u16)); msleep(60); spi_write(spi, (const u8 *)&slpin, sizeof(u16)); - } else if (priv->lcd_state < FB_BLANK_POWERDOWN) { + } else if (priv->lcd_state < LCD_POWER_OFF) { /* Do nothing, the LCD is already in standby */ } else { - /* priv->lcd_state == FB_BLANK_POWERDOWN */ + /* priv->lcd_state == LCD_POWER_OFF */ l4f00242t03_lcd_init(spi); - priv->lcd_state = FB_BLANK_UNBLANK; + priv->lcd_state = LCD_POWER_ON; l4f00242t03_lcd_power_set(ld, power); } } else { - /* power == FB_BLANK_POWERDOWN */ - if (priv->lcd_state != FB_BLANK_POWERDOWN) { + /* power == LCD_POWER_OFF */ + if (priv->lcd_state != LCD_POWER_OFF) { /* Clear the screen before shutting down */ spi_write(spi, (const u8 *)&disoff, sizeof(u16)); msleep(60); @@ -158,7 +158,7 @@ static int l4f00242t03_lcd_power_set(struct lcd_device *ld, int power) return 0; } -static struct lcd_ops l4f_ops = { +static const struct lcd_ops l4f_ops = { .set_power = l4f00242t03_lcd_power_set, .get_power = l4f00242t03_lcd_power_get, }; @@ -166,6 +166,7 @@ static struct lcd_ops l4f_ops = { static int l4f00242t03_probe(struct spi_device *spi) { struct l4f00242t03_priv *priv; + int ret; priv = devm_kzalloc(&spi->dev, sizeof(struct l4f00242t03_priv), GFP_KERNEL); @@ -174,7 +175,9 @@ static int l4f00242t03_probe(struct spi_device *spi) spi_set_drvdata(spi, priv); spi->bits_per_word = 9; - spi_setup(spi); + ret = spi_setup(spi); + if (ret < 0) + return dev_err_probe(&spi->dev, ret, "Unable to setup spi.\n"); priv->spi = spi; @@ -209,8 +212,8 @@ static int l4f00242t03_probe(struct spi_device *spi) /* Init the LCD */ l4f00242t03_lcd_init(spi); - priv->lcd_state = FB_BLANK_VSYNC_SUSPEND; - l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_UNBLANK); + priv->lcd_state = LCD_POWER_REDUCED_VSYNC_SUSPEND; + l4f00242t03_lcd_power_set(priv->ld, LCD_POWER_ON); dev_info(&spi->dev, "Epson l4f00242t03 lcd probed.\n"); @@ -221,7 +224,7 @@ static void l4f00242t03_remove(struct spi_device *spi) { struct l4f00242t03_priv *priv = spi_get_drvdata(spi); - l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); + l4f00242t03_lcd_power_set(priv->ld, LCD_POWER_OFF); } static void l4f00242t03_shutdown(struct spi_device *spi) @@ -229,7 +232,7 @@ static void l4f00242t03_shutdown(struct spi_device *spi) struct l4f00242t03_priv *priv = spi_get_drvdata(spi); if (priv) - l4f00242t03_lcd_power_set(priv->ld, FB_BLANK_POWERDOWN); + l4f00242t03_lcd_power_set(priv->ld, LCD_POWER_OFF); } diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 77c5cb2a44e2..3267acf8dc5b 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -20,6 +20,24 @@ #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) +static int to_lcd_power(int fb_blank) +{ + switch (fb_blank) { + case FB_BLANK_UNBLANK: + return LCD_POWER_ON; + /* deprecated; TODO: should become 'off' */ + case FB_BLANK_NORMAL: + return LCD_POWER_REDUCED; + case FB_BLANK_VSYNC_SUSPEND: + return LCD_POWER_REDUCED_VSYNC_SUSPEND; + /* 'off' */ + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + default: + return LCD_POWER_OFF; + } +} + /* This callback gets called when something important happens inside a * framebuffer driver. We're looking if that important event is blanking, * and if it is, we're switching lcd power as well ... @@ -27,24 +45,32 @@ static int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) { - struct lcd_device *ld; + struct lcd_device *ld = container_of(self, struct lcd_device, fb_notif); struct fb_event *evdata = data; + struct fb_info *info = evdata->info; + struct lcd_device *fb_lcd = fb_lcd_device(info); + + guard(mutex)(&ld->ops_lock); - ld = container_of(self, struct lcd_device, fb_notif); if (!ld->ops) return 0; + if (ld->ops->controls_device && !ld->ops->controls_device(ld, info->device)) + return 0; + if (fb_lcd && fb_lcd != ld) + return 0; - mutex_lock(&ld->ops_lock); - if (!ld->ops->check_fb || ld->ops->check_fb(ld, evdata->info)) { - if (event == FB_EVENT_BLANK) { - if (ld->ops->set_power) - ld->ops->set_power(ld, *(int *)evdata->data); - } else { - if (ld->ops->set_mode) - ld->ops->set_mode(ld, evdata->data); - } + if (event == FB_EVENT_BLANK) { + int power = to_lcd_power(*(int *)evdata->data); + + if (ld->ops->set_power) + ld->ops->set_power(ld, power); + } else { + const struct fb_videomode *videomode = evdata->data; + + if (ld->ops->set_mode) + ld->ops->set_mode(ld, videomode->xres, videomode->yres); } - mutex_unlock(&ld->ops_lock); + return 0; } @@ -159,8 +185,6 @@ static ssize_t max_contrast_show(struct device *dev, } static DEVICE_ATTR_RO(max_contrast); -static struct class *lcd_class; - static void lcd_device_release(struct device *dev) { struct lcd_device *ld = to_lcd_device(dev); @@ -175,6 +199,11 @@ static struct attribute *lcd_device_attrs[] = { }; ATTRIBUTE_GROUPS(lcd_device); +static const struct class lcd_class = { + .name = "lcd", + .dev_groups = lcd_device_groups, +}; + /** * lcd_device_register - register a new object of lcd_device class. * @name: the name of the new object(must be the same as the name of the @@ -188,7 +217,7 @@ ATTRIBUTE_GROUPS(lcd_device); * or a pointer to the newly allocated device. */ struct lcd_device *lcd_device_register(const char *name, struct device *parent, - void *devdata, struct lcd_ops *ops) + void *devdata, const struct lcd_ops *ops) { struct lcd_device *new_ld; int rc; @@ -202,7 +231,7 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, mutex_init(&new_ld->ops_lock); mutex_init(&new_ld->update_lock); - new_ld->dev.class = lcd_class; + new_ld->dev.class = &lcd_class; new_ld->dev.parent = parent; new_ld->dev.release = lcd_device_release; dev_set_name(&new_ld->dev, "%s", name); @@ -276,7 +305,7 @@ static int devm_lcd_device_match(struct device *dev, void *res, void *data) */ struct lcd_device *devm_lcd_device_register(struct device *dev, const char *name, struct device *parent, - void *devdata, struct lcd_ops *ops) + void *devdata, const struct lcd_ops *ops) { struct lcd_device **ptr, *lcd; @@ -318,19 +347,19 @@ EXPORT_SYMBOL(devm_lcd_device_unregister); static void __exit lcd_class_exit(void) { - class_destroy(lcd_class); + class_unregister(&lcd_class); } static int __init lcd_class_init(void) { - lcd_class = class_create("lcd"); - if (IS_ERR(lcd_class)) { - pr_warn("Unable to create backlight class; errno = %ld\n", - PTR_ERR(lcd_class)); - return PTR_ERR(lcd_class); + int ret; + + ret = class_register(&lcd_class); + if (ret) { + pr_warn("Unable to create backlight class; errno = %d\n", ret); + return ret; } - lcd_class->dev_groups = lcd_device_groups; return 0; } diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c index 032f8bddf872..d2db157b2c29 100644 --- a/drivers/video/backlight/led_bl.c +++ b/drivers/video/backlight/led_bl.c @@ -200,8 +200,8 @@ static int led_bl_probe(struct platform_device *pdev) props.type = BACKLIGHT_RAW; props.max_brightness = priv->max_brightness; props.brightness = priv->default_brightness; - props.power = (priv->default_brightness > 0) ? FB_BLANK_POWERDOWN : - FB_BLANK_UNBLANK; + props.power = (priv->default_brightness > 0) ? BACKLIGHT_POWER_OFF : + BACKLIGHT_POWER_ON; priv->bl_dev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, priv, &led_bl_ops, &props); if (IS_ERR(priv->bl_dev)) { @@ -229,8 +229,11 @@ static void led_bl_remove(struct platform_device *pdev) backlight_device_unregister(bl); led_bl_power_off(priv); - for (i = 0; i < priv->nb_leds; i++) + for (i = 0; i < priv->nb_leds; i++) { + mutex_lock(&priv->leds[i]->led_access); led_sysfs_enable(priv->leds[i]); + mutex_unlock(&priv->leds[i]->led_access); + } } static const struct of_device_id led_bl_of_match[] = { @@ -246,7 +249,7 @@ static struct platform_driver led_bl_driver = { .of_match_table = led_bl_of_match, }, .probe = led_bl_probe, - .remove_new = led_bl_remove, + .remove = led_bl_remove, }; module_platform_driver(led_bl_driver); diff --git a/drivers/video/backlight/lm3509_bl.c b/drivers/video/backlight/lm3509_bl.c new file mode 100644 index 000000000000..24e1a19ff72d --- /dev/null +++ b/drivers/video/backlight/lm3509_bl.c @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/regmap.h> + +#define LM3509_NAME "lm3509_bl" + +#define LM3509_SINK_MAIN 0 +#define LM3509_SINK_SUB 1 +#define LM3509_NUM_SINKS 2 + +#define LM3509_DEF_BRIGHTNESS 0x12 +#define LM3509_MAX_BRIGHTNESS 0x1F + +#define REG_GP 0x10 +#define REG_BMAIN 0xA0 +#define REG_BSUB 0xB0 +#define REG_MAX 0xFF + +enum { + REG_GP_ENM_BIT = 0, + REG_GP_ENS_BIT, + REG_GP_UNI_BIT, + REG_GP_RMP0_BIT, + REG_GP_RMP1_BIT, + REG_GP_OLED_BIT, +}; + +struct lm3509_bl { + struct regmap *regmap; + struct backlight_device *bl_main; + struct backlight_device *bl_sub; + struct gpio_desc *reset_gpio; +}; + +struct lm3509_bl_led_data { + const char *label; + int led_sources; + u32 brightness; + u32 max_brightness; +}; + +static void lm3509_reset(struct lm3509_bl *data) +{ + if (data->reset_gpio) { + gpiod_set_value(data->reset_gpio, 1); + udelay(1); + gpiod_set_value(data->reset_gpio, 0); + udelay(10); + } +} + +static int lm3509_update_status(struct backlight_device *bl, + unsigned int en_mask, unsigned int br_reg) +{ + struct lm3509_bl *data = bl_get_data(bl); + int ret; + bool en; + + ret = regmap_write(data->regmap, br_reg, backlight_get_brightness(bl)); + if (ret < 0) + return ret; + + en = !backlight_is_blank(bl); + return regmap_update_bits(data->regmap, REG_GP, en_mask, + en ? en_mask : 0); +} + +static int lm3509_main_update_status(struct backlight_device *bl) +{ + return lm3509_update_status(bl, BIT(REG_GP_ENM_BIT), REG_BMAIN); +} + +static const struct backlight_ops lm3509_main_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3509_main_update_status, +}; + +static int lm3509_sub_update_status(struct backlight_device *bl) +{ + return lm3509_update_status(bl, BIT(REG_GP_ENS_BIT), REG_BSUB); +} + +static const struct backlight_ops lm3509_sub_ops = { + .options = BL_CORE_SUSPENDRESUME, + .update_status = lm3509_sub_update_status, +}; + +static struct backlight_device * +lm3509_backlight_register(struct device *dev, const char *name_suffix, + struct lm3509_bl *data, + const struct backlight_ops *ops, + const struct lm3509_bl_led_data *led_data) + +{ + struct backlight_device *bd; + struct backlight_properties props; + const char *label = led_data->label; + char name[64]; + + memset(&props, 0, sizeof(props)); + props.type = BACKLIGHT_RAW; + props.brightness = led_data->brightness; + props.max_brightness = led_data->max_brightness; + props.scale = BACKLIGHT_SCALE_NON_LINEAR; + + if (!label) { + snprintf(name, sizeof(name), "lm3509-%s-%s", dev_name(dev), + name_suffix); + label = name; + } + + bd = devm_backlight_device_register(dev, label, dev, data, ops, &props); + if (IS_ERR(bd)) + return bd; + + backlight_update_status(bd); + return bd; +} + +static const struct regmap_config lm3509_regmap = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_MAX, +}; + +static int lm3509_parse_led_sources(struct device_node *node, + int default_led_sources) +{ + u32 sources[LM3509_NUM_SINKS]; + int ret, num_sources, i; + + num_sources = of_property_count_u32_elems(node, "led-sources"); + if (num_sources < 0) + return default_led_sources; + else if (num_sources > ARRAY_SIZE(sources)) + return -EINVAL; + + ret = of_property_read_u32_array(node, "led-sources", sources, + num_sources); + if (ret) + return ret; + + for (i = 0; i < num_sources; i++) { + if (sources[i] >= LM3509_NUM_SINKS) + return -EINVAL; + + ret |= BIT(sources[i]); + } + + return ret; +} + +static int lm3509_parse_dt_node(struct device *dev, + struct lm3509_bl_led_data *led_data) +{ + int seen_led_sources = 0; + + for_each_child_of_node_scoped(dev->of_node, child) { + struct lm3509_bl_led_data *ld; + int ret; + u32 reg; + int valid_led_sources; + + ret = of_property_read_u32(child, "reg", ®); + if (ret < 0) + return ret; + if (reg >= LM3509_NUM_SINKS) + return -EINVAL; + ld = &led_data[reg]; + + ld->led_sources = lm3509_parse_led_sources(child, BIT(reg)); + if (ld->led_sources < 0) + return ld->led_sources; + + if (reg == 0) + valid_led_sources = BIT(LM3509_SINK_MAIN) | + BIT(LM3509_SINK_SUB); + else + valid_led_sources = BIT(LM3509_SINK_SUB); + + if (ld->led_sources != (ld->led_sources & valid_led_sources)) + return -EINVAL; + + if (seen_led_sources & ld->led_sources) + return -EINVAL; + + seen_led_sources |= ld->led_sources; + + ld->label = NULL; + of_property_read_string(child, "label", &ld->label); + + ld->max_brightness = LM3509_MAX_BRIGHTNESS; + of_property_read_u32(child, "max-brightness", + &ld->max_brightness); + ld->max_brightness = + min_t(u32, ld->max_brightness, LM3509_MAX_BRIGHTNESS); + + ld->brightness = LM3509_DEF_BRIGHTNESS; + of_property_read_u32(child, "default-brightness", + &ld->brightness); + ld->brightness = min_t(u32, ld->brightness, ld->max_brightness); + } + + return 0; +} + +static int lm3509_probe(struct i2c_client *client) +{ + struct lm3509_bl *data; + struct device *dev = &client->dev; + int ret; + bool oled_mode = false; + unsigned int reg_gp_val = 0; + struct lm3509_bl_led_data led_data[LM3509_NUM_SINKS]; + u32 rate_of_change = 0; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(dev, "i2c functionality check failed\n"); + return -EOPNOTSUPP; + } + + data = devm_kzalloc(dev, sizeof(struct lm3509_bl), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->regmap = devm_regmap_init_i2c(client, &lm3509_regmap); + if (IS_ERR(data->regmap)) + return PTR_ERR(data->regmap); + i2c_set_clientdata(client, data); + + data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(data->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(data->reset_gpio), + "Failed to get 'reset' gpio\n"); + + lm3509_reset(data); + + memset(led_data, 0, sizeof(led_data)); + ret = lm3509_parse_dt_node(dev, led_data); + if (ret) + return ret; + + oled_mode = of_property_read_bool(dev->of_node, "ti,oled-mode"); + + if (!of_property_read_u32(dev->of_node, + "ti,brightness-rate-of-change-us", + &rate_of_change)) { + switch (rate_of_change) { + case 51: + reg_gp_val = 0; + break; + case 13000: + reg_gp_val = BIT(REG_GP_RMP1_BIT); + break; + case 26000: + reg_gp_val = BIT(REG_GP_RMP0_BIT); + break; + case 52000: + reg_gp_val = BIT(REG_GP_RMP0_BIT) | + BIT(REG_GP_RMP1_BIT); + break; + default: + dev_warn(dev, "invalid rate of change %u\n", + rate_of_change); + break; + } + } + + if (led_data[0].led_sources == + (BIT(LM3509_SINK_MAIN) | BIT(LM3509_SINK_SUB))) + reg_gp_val |= BIT(REG_GP_UNI_BIT); + if (oled_mode) + reg_gp_val |= BIT(REG_GP_OLED_BIT); + + ret = regmap_write(data->regmap, REG_GP, reg_gp_val); + if (ret < 0) + return dev_err_probe(dev, ret, "failed to write register\n"); + + if (led_data[0].led_sources) { + data->bl_main = lm3509_backlight_register( + dev, "main", data, &lm3509_main_ops, &led_data[0]); + if (IS_ERR(data->bl_main)) { + return dev_err_probe( + dev, PTR_ERR(data->bl_main), + "failed to register main backlight\n"); + } + } + + if (led_data[1].led_sources) { + data->bl_sub = lm3509_backlight_register( + dev, "sub", data, &lm3509_sub_ops, &led_data[1]); + if (IS_ERR(data->bl_sub)) { + return dev_err_probe( + dev, PTR_ERR(data->bl_sub), + "failed to register secondary backlight\n"); + } + } + + return 0; +} + +static void lm3509_remove(struct i2c_client *client) +{ + struct lm3509_bl *data = i2c_get_clientdata(client); + + regmap_write(data->regmap, REG_GP, 0x00); +} + +static const struct i2c_device_id lm3509_id[] = { + { LM3509_NAME }, + {} +}; + +MODULE_DEVICE_TABLE(i2c, lm3509_id); + +static const struct of_device_id lm3509_match_table[] = { + { + .compatible = "ti,lm3509", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, lm3509_match_table); + +static struct i2c_driver lm3509_i2c_driver = { + .driver = { + .name = LM3509_NAME, + .of_match_table = lm3509_match_table, + }, + .probe = lm3509_probe, + .remove = lm3509_remove, + .id_table = lm3509_id, +}; + +module_i2c_driver(lm3509_i2c_driver); + +MODULE_DESCRIPTION("Texas Instruments Backlight driver for LM3509"); +MODULE_AUTHOR("Patrick Gansterer <paroga@paroga.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c index 3e10d480cb7f..babfd3ceec86 100644 --- a/drivers/video/backlight/lm3533_bl.c +++ b/drivers/video/backlight/lm3533_bl.c @@ -11,7 +11,6 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/backlight.h> -#include <linux/fb.h> #include <linux/slab.h> #include <linux/mfd/lm3533.h> @@ -344,7 +343,7 @@ static void lm3533_bl_remove(struct platform_device *pdev) dev_dbg(&bd->dev, "%s\n", __func__); - bd->props.power = FB_BLANK_POWERDOWN; + bd->props.power = BACKLIGHT_POWER_OFF; bd->props.brightness = 0; lm3533_ctrlbank_disable(&bl->cb); @@ -388,7 +387,7 @@ static struct platform_driver lm3533_bl_driver = { .pm = &lm3533_bl_pm_ops, }, .probe = lm3533_bl_probe, - .remove_new = lm3533_bl_remove, + .remove = lm3533_bl_remove, .shutdown = lm3533_bl_shutdown, }; module_platform_driver(lm3533_bl_driver); diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index 76d47e2e8242..37651c2b9393 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -596,7 +596,7 @@ static void lm3630a_remove(struct i2c_client *client) } static const struct i2c_device_id lm3630a_id[] = { - {LM3630A_NAME, 0}, + { LM3630A_NAME }, {} }; diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c index 564f62acd721..37ccc631c498 100644 --- a/drivers/video/backlight/lm3639_bl.c +++ b/drivers/video/backlight/lm3639_bl.c @@ -403,7 +403,7 @@ static void lm3639_remove(struct i2c_client *client) } static const struct i2c_device_id lm3639_id[] = { - {LM3639_NAME, 0}, + { LM3639_NAME }, {} }; diff --git a/drivers/video/backlight/lms283gf05.c b/drivers/video/backlight/lms283gf05.c index 36856962ed83..c8b7eeeb333e 100644 --- a/drivers/video/backlight/lms283gf05.c +++ b/drivers/video/backlight/lms283gf05.c @@ -126,7 +126,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power) struct lms283gf05_state *st = lcd_get_data(ld); struct spi_device *spi = st->spi; - if (power <= FB_BLANK_NORMAL) { + if (power <= LCD_POWER_REDUCED) { if (st->reset) lms283gf05_reset(st->reset); lms283gf05_toggle(spi, disp_initseq, ARRAY_SIZE(disp_initseq)); @@ -139,7 +139,7 @@ static int lms283gf05_power_set(struct lcd_device *ld, int power) return 0; } -static struct lcd_ops lms_ops = { +static const struct lcd_ops lms_ops = { .set_power = lms283gf05_power_set, .get_power = NULL, }; diff --git a/drivers/video/backlight/lms501kf03.c b/drivers/video/backlight/lms501kf03.c index 5c46df8022bf..28721b48b4c7 100644 --- a/drivers/video/backlight/lms501kf03.c +++ b/drivers/video/backlight/lms501kf03.c @@ -6,9 +6,7 @@ * Author: Jingoo Han <jg1.han@samsung.com> */ -#include <linux/backlight.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/lcd.h> #include <linux/module.h> #include <linux/spi/spi.h> @@ -206,7 +204,7 @@ static int lms501kf03_ldi_disable(struct lms501kf03 *lcd) static int lms501kf03_power_is_on(int power) { - return (power) <= FB_BLANK_NORMAL; + return (power) <= LCD_POWER_REDUCED; } static int lms501kf03_power_on(struct lms501kf03 *lcd) @@ -295,8 +293,8 @@ static int lms501kf03_set_power(struct lcd_device *ld, int power) { struct lms501kf03 *lcd = lcd_get_data(ld); - if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && - power != FB_BLANK_NORMAL) { + if (power != LCD_POWER_ON && power != LCD_POWER_OFF && + power != LCD_POWER_REDUCED) { dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); return -EINVAL; } @@ -304,7 +302,7 @@ static int lms501kf03_set_power(struct lcd_device *ld, int power) return lms501kf03_power(lcd, power); } -static struct lcd_ops lms501kf03_lcd_ops = { +static const struct lcd_ops lms501kf03_lcd_ops = { .get_power = lms501kf03_get_power, .set_power = lms501kf03_set_power, }; @@ -350,11 +348,11 @@ static int lms501kf03_probe(struct spi_device *spi) * current lcd status is powerdown and then * it enables lcd panel. */ - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = LCD_POWER_OFF; - lms501kf03_power(lcd, FB_BLANK_UNBLANK); + lms501kf03_power(lcd, LCD_POWER_ON); } else { - lcd->power = FB_BLANK_UNBLANK; + lcd->power = LCD_POWER_ON; } spi_set_drvdata(spi, lcd); @@ -368,7 +366,7 @@ static void lms501kf03_remove(struct spi_device *spi) { struct lms501kf03 *lcd = spi_get_drvdata(spi); - lms501kf03_power(lcd, FB_BLANK_POWERDOWN); + lms501kf03_power(lcd, LCD_POWER_OFF); } #ifdef CONFIG_PM_SLEEP @@ -382,16 +380,16 @@ static int lms501kf03_suspend(struct device *dev) * when lcd panel is suspend, lcd panel becomes off * regardless of status. */ - return lms501kf03_power(lcd, FB_BLANK_POWERDOWN); + return lms501kf03_power(lcd, LCD_POWER_OFF); } static int lms501kf03_resume(struct device *dev) { struct lms501kf03 *lcd = dev_get_drvdata(dev); - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = LCD_POWER_OFF; - return lms501kf03_power(lcd, FB_BLANK_UNBLANK); + return lms501kf03_power(lcd, LCD_POWER_ON); } #endif @@ -402,7 +400,7 @@ static void lms501kf03_shutdown(struct spi_device *spi) { struct lms501kf03 *lcd = spi_get_drvdata(spi); - lms501kf03_power(lcd, FB_BLANK_POWERDOWN); + lms501kf03_power(lcd, LCD_POWER_OFF); } static struct spi_driver lms501kf03_driver = { diff --git a/drivers/video/backlight/locomolcd.c b/drivers/video/backlight/locomolcd.c index 346d3e29a843..1b493fb0516d 100644 --- a/drivers/video/backlight/locomolcd.c +++ b/drivers/video/backlight/locomolcd.c @@ -16,7 +16,6 @@ #include <linux/delay.h> #include <linux/device.h> #include <linux/interrupt.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <asm/hardware/locomo.h> diff --git a/drivers/video/backlight/lp8788_bl.c b/drivers/video/backlight/lp8788_bl.c index 31f97230ee50..f61a64905a02 100644 --- a/drivers/video/backlight/lp8788_bl.c +++ b/drivers/video/backlight/lp8788_bl.c @@ -12,7 +12,6 @@ #include <linux/mfd/lp8788.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/pwm.h> #include <linux/slab.h> /* Register address */ @@ -31,149 +30,40 @@ #define MAX_BRIGHTNESS 127 #define DEFAULT_BL_NAME "lcd-backlight" -struct lp8788_bl_config { - enum lp8788_bl_ctrl_mode bl_mode; - enum lp8788_bl_dim_mode dim_mode; - enum lp8788_bl_full_scale_current full_scale; - enum lp8788_bl_ramp_step rise_time; - enum lp8788_bl_ramp_step fall_time; - enum pwm_polarity pwm_pol; -}; - struct lp8788_bl { struct lp8788 *lp; struct backlight_device *bl_dev; - struct lp8788_backlight_platform_data *pdata; - enum lp8788_bl_ctrl_mode mode; - struct pwm_device *pwm; -}; - -static struct lp8788_bl_config default_bl_config = { - .bl_mode = LP8788_BL_REGISTER_ONLY, - .dim_mode = LP8788_DIM_EXPONENTIAL, - .full_scale = LP8788_FULLSCALE_1900uA, - .rise_time = LP8788_RAMP_8192us, - .fall_time = LP8788_RAMP_8192us, - .pwm_pol = PWM_POLARITY_NORMAL, }; -static inline bool is_brightness_ctrl_by_pwm(enum lp8788_bl_ctrl_mode mode) -{ - return mode == LP8788_BL_COMB_PWM_BASED; -} - -static inline bool is_brightness_ctrl_by_register(enum lp8788_bl_ctrl_mode mode) -{ - return mode == LP8788_BL_REGISTER_ONLY || - mode == LP8788_BL_COMB_REGISTER_BASED; -} - static int lp8788_backlight_configure(struct lp8788_bl *bl) { - struct lp8788_backlight_platform_data *pdata = bl->pdata; - struct lp8788_bl_config *cfg = &default_bl_config; int ret; u8 val; - /* - * Update chip configuration if platform data exists, - * otherwise use the default settings. - */ - if (pdata) { - cfg->bl_mode = pdata->bl_mode; - cfg->dim_mode = pdata->dim_mode; - cfg->full_scale = pdata->full_scale; - cfg->rise_time = pdata->rise_time; - cfg->fall_time = pdata->fall_time; - cfg->pwm_pol = pdata->pwm_pol; - } - /* Brightness ramp up/down */ - val = (cfg->rise_time << LP8788_BL_RAMP_RISE_SHIFT) | cfg->fall_time; + val = (LP8788_RAMP_8192us << LP8788_BL_RAMP_RISE_SHIFT) | LP8788_RAMP_8192us; ret = lp8788_write_byte(bl->lp, LP8788_BL_RAMP, val); if (ret) return ret; /* Fullscale current setting */ - val = (cfg->full_scale << LP8788_BL_FULLSCALE_SHIFT) | - (cfg->dim_mode << LP8788_BL_DIM_MODE_SHIFT); + val = (LP8788_FULLSCALE_1900uA << LP8788_BL_FULLSCALE_SHIFT) | + (LP8788_DIM_EXPONENTIAL << LP8788_BL_DIM_MODE_SHIFT); /* Brightness control mode */ - switch (cfg->bl_mode) { - case LP8788_BL_REGISTER_ONLY: - val |= LP8788_BL_EN; - break; - case LP8788_BL_COMB_PWM_BASED: - case LP8788_BL_COMB_REGISTER_BASED: - val |= LP8788_BL_EN | LP8788_BL_PWM_INPUT_EN | - (cfg->pwm_pol << LP8788_BL_PWM_POLARITY_SHIFT); - break; - default: - dev_err(bl->lp->dev, "invalid mode: %d\n", cfg->bl_mode); - return -EINVAL; - } - - bl->mode = cfg->bl_mode; + val |= LP8788_BL_EN; return lp8788_write_byte(bl->lp, LP8788_BL_CONFIG, val); } -static void lp8788_pwm_ctrl(struct lp8788_bl *bl, int br, int max_br) -{ - unsigned int period; - unsigned int duty; - struct device *dev; - struct pwm_device *pwm; - - if (!bl->pdata) - return; - - period = bl->pdata->period_ns; - duty = br * period / max_br; - dev = bl->lp->dev; - - /* request PWM device with the consumer name */ - if (!bl->pwm) { - pwm = devm_pwm_get(dev, LP8788_DEV_BACKLIGHT); - if (IS_ERR(pwm)) { - dev_err(dev, "can not get PWM device\n"); - return; - } - - bl->pwm = pwm; - - /* - * FIXME: pwm_apply_args() should be removed when switching to - * the atomic PWM API. - */ - pwm_apply_args(pwm); - } - - pwm_config(bl->pwm, duty, period); - if (duty) - pwm_enable(bl->pwm); - else - pwm_disable(bl->pwm); -} - static int lp8788_bl_update_status(struct backlight_device *bl_dev) { struct lp8788_bl *bl = bl_get_data(bl_dev); - enum lp8788_bl_ctrl_mode mode = bl->mode; if (bl_dev->props.state & BL_CORE_SUSPENDED) bl_dev->props.brightness = 0; - if (is_brightness_ctrl_by_pwm(mode)) { - int brt = bl_dev->props.brightness; - int max = bl_dev->props.max_brightness; - - lp8788_pwm_ctrl(bl, brt, max); - } else if (is_brightness_ctrl_by_register(mode)) { - u8 brt = bl_dev->props.brightness; - - lp8788_write_byte(bl->lp, LP8788_BL_BRIGHTNESS, brt); - } + lp8788_write_byte(bl->lp, LP8788_BL_BRIGHTNESS, bl_dev->props.brightness); return 0; } @@ -187,30 +77,16 @@ static int lp8788_backlight_register(struct lp8788_bl *bl) { struct backlight_device *bl_dev; struct backlight_properties props; - struct lp8788_backlight_platform_data *pdata = bl->pdata; - int init_brt; - char *name; memset(&props, 0, sizeof(struct backlight_properties)); props.type = BACKLIGHT_PLATFORM; props.max_brightness = MAX_BRIGHTNESS; /* Initial brightness */ - if (pdata) - init_brt = min_t(int, pdata->initial_brightness, - props.max_brightness); - else - init_brt = 0; - - props.brightness = init_brt; + props.brightness = 0; /* Backlight device name */ - if (!pdata || !pdata->name) - name = DEFAULT_BL_NAME; - else - name = pdata->name; - - bl_dev = backlight_device_register(name, bl->lp->dev, bl, + bl_dev = backlight_device_register(DEFAULT_BL_NAME, bl->lp->dev, bl, &lp8788_bl_ops, &props); if (IS_ERR(bl_dev)) return PTR_ERR(bl_dev); @@ -230,16 +106,7 @@ static void lp8788_backlight_unregister(struct lp8788_bl *bl) static ssize_t lp8788_get_bl_ctl_mode(struct device *dev, struct device_attribute *attr, char *buf) { - struct lp8788_bl *bl = dev_get_drvdata(dev); - enum lp8788_bl_ctrl_mode mode = bl->mode; - char *strmode; - - if (is_brightness_ctrl_by_pwm(mode)) - strmode = "PWM based"; - else if (is_brightness_ctrl_by_register(mode)) - strmode = "Register based"; - else - strmode = "Invalid mode"; + const char *strmode = "Register based"; return scnprintf(buf, PAGE_SIZE, "%s\n", strmode); } @@ -266,8 +133,6 @@ static int lp8788_backlight_probe(struct platform_device *pdev) return -ENOMEM; bl->lp = lp; - if (lp->pdata) - bl->pdata = lp->pdata->bl_pdata; platform_set_drvdata(pdev, bl); @@ -312,7 +177,7 @@ static void lp8788_backlight_remove(struct platform_device *pdev) static struct platform_driver lp8788_bl_driver = { .probe = lp8788_backlight_probe, - .remove_new = lp8788_backlight_remove, + .remove = lp8788_backlight_remove, .driver = { .name = LP8788_DEV_BACKLIGHT, }, diff --git a/drivers/video/backlight/ltv350qv.c b/drivers/video/backlight/ltv350qv.c index d54f501e4285..c919b0fe4cd9 100644 --- a/drivers/video/backlight/ltv350qv.c +++ b/drivers/video/backlight/ltv350qv.c @@ -6,7 +6,6 @@ */ #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/lcd.h> #include <linux/module.h> @@ -15,7 +14,7 @@ #include "ltv350qv.h" -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) struct ltv350qv { struct spi_device *spi; @@ -217,7 +216,7 @@ static int ltv350qv_get_power(struct lcd_device *ld) return lcd->power; } -static struct lcd_ops ltv_ops = { +static const struct lcd_ops ltv_ops = { .get_power = ltv350qv_get_power, .set_power = ltv350qv_set_power, }; @@ -233,7 +232,7 @@ static int ltv350qv_probe(struct spi_device *spi) return -ENOMEM; lcd->spi = spi; - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = LCD_POWER_OFF; lcd->buffer = devm_kzalloc(&spi->dev, 8, GFP_KERNEL); if (!lcd->buffer) return -ENOMEM; @@ -245,7 +244,7 @@ static int ltv350qv_probe(struct spi_device *spi) lcd->ld = ld; - ret = ltv350qv_power(lcd, FB_BLANK_UNBLANK); + ret = ltv350qv_power(lcd, LCD_POWER_ON); if (ret) return ret; @@ -258,7 +257,7 @@ static void ltv350qv_remove(struct spi_device *spi) { struct ltv350qv *lcd = spi_get_drvdata(spi); - ltv350qv_power(lcd, FB_BLANK_POWERDOWN); + ltv350qv_power(lcd, LCD_POWER_OFF); } #ifdef CONFIG_PM_SLEEP @@ -266,14 +265,14 @@ static int ltv350qv_suspend(struct device *dev) { struct ltv350qv *lcd = dev_get_drvdata(dev); - return ltv350qv_power(lcd, FB_BLANK_POWERDOWN); + return ltv350qv_power(lcd, LCD_POWER_OFF); } static int ltv350qv_resume(struct device *dev) { struct ltv350qv *lcd = dev_get_drvdata(dev); - return ltv350qv_power(lcd, FB_BLANK_UNBLANK); + return ltv350qv_power(lcd, LCD_POWER_ON); } #endif @@ -284,7 +283,7 @@ static void ltv350qv_shutdown(struct spi_device *spi) { struct ltv350qv *lcd = spi_get_drvdata(spi); - ltv350qv_power(lcd, FB_BLANK_POWERDOWN); + ltv350qv_power(lcd, LCD_POWER_OFF); } static struct spi_driver ltv350qv_driver = { diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c index 1f1d06b4e119..a205f004eab2 100644 --- a/drivers/video/backlight/lv5207lp.c +++ b/drivers/video/backlight/lv5207lp.c @@ -9,7 +9,6 @@ #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/platform_data/lv5207lp.h> @@ -62,18 +61,18 @@ static int lv5207lp_backlight_update_status(struct backlight_device *backlight) return 0; } -static int lv5207lp_backlight_check_fb(struct backlight_device *backlight, - struct fb_info *info) +static bool lv5207lp_backlight_controls_device(struct backlight_device *backlight, + struct device *display_dev) { struct lv5207lp *lv = bl_get_data(backlight); - return !lv->pdata->dev || lv->pdata->dev == info->device; + return !lv->pdata->dev || lv->pdata->dev == display_dev; } static const struct backlight_ops lv5207lp_backlight_ops = { - .options = BL_CORE_SUSPENDRESUME, - .update_status = lv5207lp_backlight_update_status, - .check_fb = lv5207lp_backlight_check_fb, + .options = BL_CORE_SUSPENDRESUME, + .update_status = lv5207lp_backlight_update_status, + .controls_device = lv5207lp_backlight_controls_device, }; static int lv5207lp_probe(struct i2c_client *client) @@ -132,7 +131,7 @@ static void lv5207lp_remove(struct i2c_client *client) } static const struct i2c_device_id lv5207lp_ids[] = { - { "lv5207lp", 0 }, + { "lv5207lp" }, { } }; MODULE_DEVICE_TABLE(i2c, lv5207lp_ids); diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index e607ec6fd4bf..4ac20a59e007 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/kernel.h> #include <linux/platform_device.h> -#include <linux/fb.h> #include <linux/i2c.h> #include <linux/backlight.h> #include <linux/mfd/max8925.h> diff --git a/drivers/video/backlight/mp3309c.c b/drivers/video/backlight/mp3309c.c index c80a1481e742..372058e26129 100644 --- a/drivers/video/backlight/mp3309c.c +++ b/drivers/video/backlight/mp3309c.c @@ -97,15 +97,10 @@ static int mp3309c_enable_device(struct mp3309c_chip *chip) /* * I2C register #1 - Set working mode: - * - set one of the two dimming mode: - * - PWM dimming using an external PWM dimming signal - * - analog dimming using I2C commands * - enable/disable synchronous mode * - set overvoltage protection (OVP) */ reg_val = 0x00; - if (chip->pdata->dimming_mode == DIMMING_PWM) - reg_val |= REG_I2C_1_DIMS; if (chip->pdata->sync_mode) reg_val |= REG_I2C_1_SYNC; reg_val |= chip->pdata->over_voltage_protection; @@ -205,8 +200,9 @@ static int mp3309c_parse_fwnode(struct mp3309c_chip *chip, struct mp3309c_platform_data *pdata) { int ret, i; - unsigned int num_levels, tmp_value; + unsigned int tmp_value; struct device *dev = chip->dev; + int num_levels; if (!dev_fwnode(dev)) return dev_err_probe(dev, -ENODEV, "failed to get firmware node\n"); @@ -362,8 +358,7 @@ static int mp3309c_probe(struct i2c_client *client) props.max_brightness = pdata->max_brightness; props.scale = BACKLIGHT_SCALE_LINEAR; props.type = BACKLIGHT_RAW; - props.power = FB_BLANK_UNBLANK; - props.fb_blank = FB_BLANK_UNBLANK; + props.power = BACKLIGHT_POWER_ON; chip->bl = devm_backlight_device_register(dev, "mp3309c", dev, chip, &mp3309c_bl_ops, &props); if (IS_ERR(chip->bl)) @@ -393,7 +388,7 @@ static void mp3309c_remove(struct i2c_client *client) struct mp3309c_chip *chip = i2c_get_clientdata(client); struct backlight_device *bl = chip->bl; - bl->props.power = FB_BLANK_POWERDOWN; + bl->props.power = BACKLIGHT_POWER_OFF; bl->props.brightness = 0; backlight_update_status(chip->bl); } @@ -405,7 +400,7 @@ static const struct of_device_id mp3309c_match_table[] = { MODULE_DEVICE_TABLE(of, mp3309c_match_table); static const struct i2c_device_id mp3309c_id[] = { - { "mp3309c", 0 }, + { "mp3309c" }, { } }; MODULE_DEVICE_TABLE(i2c, mp3309c_id); diff --git a/drivers/video/backlight/mt6370-backlight.c b/drivers/video/backlight/mt6370-backlight.c index 94422c956453..e55f26888d0f 100644 --- a/drivers/video/backlight/mt6370-backlight.c +++ b/drivers/video/backlight/mt6370-backlight.c @@ -340,7 +340,7 @@ static struct platform_driver mt6370_bl_driver = { .of_match_table = mt6370_bl_of_match, }, .probe = mt6370_bl_probe, - .remove_new = mt6370_bl_remove, + .remove = mt6370_bl_remove, }; module_platform_driver(mt6370_bl_driver); diff --git a/drivers/video/backlight/omap1_bl.c b/drivers/video/backlight/omap1_bl.c index 69a49384b3de..e461e19231ae 100644 --- a/drivers/video/backlight/omap1_bl.c +++ b/drivers/video/backlight/omap1_bl.c @@ -9,7 +9,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/slab.h> #include <linux/platform_data/omap1_bl.h> @@ -20,7 +19,7 @@ #define OMAPBL_MAX_INTENSITY 0xff struct omap_backlight { - int powermode; + bool enabled; int current_intensity; struct device *dev; @@ -37,24 +36,14 @@ static inline void omapbl_send_enable(int enable) omap_writeb(enable, OMAP_PWL_CLK_ENABLE); } -static void omapbl_blank(struct omap_backlight *bl, int mode) +static void omapbl_enable(struct omap_backlight *bl, bool enable) { - if (bl->pdata->set_power) - bl->pdata->set_power(bl->dev, mode); - - switch (mode) { - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - omapbl_send_intensity(0); - omapbl_send_enable(0); - break; - - case FB_BLANK_UNBLANK: + if (enable) { omapbl_send_intensity(bl->current_intensity); omapbl_send_enable(1); - break; + } else { + omapbl_send_intensity(0); + omapbl_send_enable(0); } } @@ -64,7 +53,7 @@ static int omapbl_suspend(struct device *dev) struct backlight_device *bl_dev = dev_get_drvdata(dev); struct omap_backlight *bl = bl_get_data(bl_dev); - omapbl_blank(bl, FB_BLANK_POWERDOWN); + omapbl_enable(bl, false); return 0; } @@ -73,33 +62,34 @@ static int omapbl_resume(struct device *dev) struct backlight_device *bl_dev = dev_get_drvdata(dev); struct omap_backlight *bl = bl_get_data(bl_dev); - omapbl_blank(bl, bl->powermode); + omapbl_enable(bl, bl->enabled); return 0; } #endif -static int omapbl_set_power(struct backlight_device *dev, int state) +static void omapbl_set_enabled(struct backlight_device *dev, bool enable) { struct omap_backlight *bl = bl_get_data(dev); - omapbl_blank(bl, state); - bl->powermode = state; - - return 0; + omapbl_enable(bl, enable); + bl->enabled = enable; } static int omapbl_update_status(struct backlight_device *dev) { struct omap_backlight *bl = bl_get_data(dev); + bool enable; if (bl->current_intensity != dev->props.brightness) { - if (bl->powermode == FB_BLANK_UNBLANK) + if (bl->enabled) omapbl_send_intensity(dev->props.brightness); bl->current_intensity = dev->props.brightness; } - if (dev->props.fb_blank != bl->powermode) - omapbl_set_power(dev, dev->props.fb_blank); + enable = !backlight_is_blank(dev); + + if (enable != bl->enabled) + omapbl_set_enabled(dev, enable); return 0; } @@ -139,7 +129,7 @@ static int omapbl_probe(struct platform_device *pdev) if (IS_ERR(dev)) return PTR_ERR(dev); - bl->powermode = FB_BLANK_POWERDOWN; + bl->enabled = false; bl->current_intensity = 0; bl->pdata = pdata; @@ -149,7 +139,6 @@ static int omapbl_probe(struct platform_device *pdev) omap_cfg_reg(PWL); /* Conflicts with UART3 */ - dev->props.fb_blank = FB_BLANK_UNBLANK; dev->props.brightness = pdata->default_intensity; omapbl_update_status(dev); diff --git a/drivers/video/backlight/otm3225a.c b/drivers/video/backlight/otm3225a.c index 2472e2167aae..5c6575f23ea8 100644 --- a/drivers/video/backlight/otm3225a.c +++ b/drivers/video/backlight/otm3225a.c @@ -189,7 +189,7 @@ static int otm3225a_set_power(struct lcd_device *ld, int power) if (power == dd->power) return 0; - if (power > FB_BLANK_UNBLANK) + if (power > LCD_POWER_ON) otm3225a_write(dd->spi, display_off, ARRAY_SIZE(display_off)); else otm3225a_write(dd->spi, display_on, ARRAY_SIZE(display_on)); @@ -205,7 +205,7 @@ static int otm3225a_get_power(struct lcd_device *ld) return dd->power; } -static struct lcd_ops otm3225a_ops = { +static const struct lcd_ops otm3225a_ops = { .set_power = otm3225a_set_power, .get_power = otm3225a_get_power, }; @@ -239,7 +239,6 @@ static int otm3225a_probe(struct spi_device *spi) static struct spi_driver otm3225a_driver = { .driver = { .name = "otm3225a", - .owner = THIS_MODULE, }, .probe = otm3225a_probe, }; diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c index 51faa889e01f..8a63ded0fa90 100644 --- a/drivers/video/backlight/pandora_bl.c +++ b/drivers/video/backlight/pandora_bl.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/platform_device.h> #include <linux/delay.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/mfd/twl.h> #include <linux/err.h> @@ -43,7 +42,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl) struct pandora_private *priv = bl_get_data(bl); u8 r; - if (bl->props.power != FB_BLANK_UNBLANK) + if (bl->props.power != BACKLIGHT_POWER_ON) brightness = 0; if (bl->props.state & BL_CORE_FBBLANK) brightness = 0; diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c deleted file mode 100644 index 540dd3380c81..000000000000 --- a/drivers/video/backlight/pcf50633-backlight.c +++ /dev/null @@ -1,155 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> - * PCF50633 backlight device driver - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> - -#include <linux/backlight.h> -#include <linux/fb.h> - -#include <linux/mfd/pcf50633/core.h> -#include <linux/mfd/pcf50633/backlight.h> - -struct pcf50633_bl { - struct pcf50633 *pcf; - struct backlight_device *bl; - - unsigned int brightness; - unsigned int brightness_limit; -}; - -/* - * pcf50633_bl_set_brightness_limit - * - * Update the brightness limit for the pc50633 backlight. The actual brightness - * will not go above the limit. This is useful to limit power drain for example - * on low battery. - * - * @dev: Pointer to a pcf50633 device - * @limit: The brightness limit. Valid values are 0-63 - */ -int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) -{ - struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev); - - if (!pcf_bl) - return -ENODEV; - - pcf_bl->brightness_limit = limit & 0x3f; - backlight_update_status(pcf_bl->bl); - - return 0; -} - -static int pcf50633_bl_update_status(struct backlight_device *bl) -{ - struct pcf50633_bl *pcf_bl = bl_get_data(bl); - unsigned int new_brightness; - - - if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) || - bl->props.power != FB_BLANK_UNBLANK) - new_brightness = 0; - else if (bl->props.brightness < pcf_bl->brightness_limit) - new_brightness = bl->props.brightness; - else - new_brightness = pcf_bl->brightness_limit; - - - if (pcf_bl->brightness == new_brightness) - return 0; - - if (new_brightness) { - pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT, - new_brightness); - if (!pcf_bl->brightness) - pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1); - } else { - pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0); - } - - pcf_bl->brightness = new_brightness; - - return 0; -} - -static int pcf50633_bl_get_brightness(struct backlight_device *bl) -{ - struct pcf50633_bl *pcf_bl = bl_get_data(bl); - - return pcf_bl->brightness; -} - -static const struct backlight_ops pcf50633_bl_ops = { - .get_brightness = pcf50633_bl_get_brightness, - .update_status = pcf50633_bl_update_status, - .options = BL_CORE_SUSPENDRESUME, -}; - -static int pcf50633_bl_probe(struct platform_device *pdev) -{ - struct pcf50633_bl *pcf_bl; - struct device *parent = pdev->dev.parent; - struct pcf50633_platform_data *pcf50633_data = dev_get_platdata(parent); - struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data; - struct backlight_properties bl_props; - - pcf_bl = devm_kzalloc(&pdev->dev, sizeof(*pcf_bl), GFP_KERNEL); - if (!pcf_bl) - return -ENOMEM; - - memset(&bl_props, 0, sizeof(bl_props)); - bl_props.type = BACKLIGHT_RAW; - bl_props.max_brightness = 0x3f; - bl_props.power = FB_BLANK_UNBLANK; - - if (pdata) { - bl_props.brightness = pdata->default_brightness; - pcf_bl->brightness_limit = pdata->default_brightness_limit; - } else { - bl_props.brightness = 0x3f; - pcf_bl->brightness_limit = 0x3f; - } - - pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent); - - pcf_bl->bl = devm_backlight_device_register(&pdev->dev, pdev->name, - &pdev->dev, pcf_bl, - &pcf50633_bl_ops, &bl_props); - - if (IS_ERR(pcf_bl->bl)) - return PTR_ERR(pcf_bl->bl); - - platform_set_drvdata(pdev, pcf_bl); - - pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); - - /* - * Should be different from bl_props.brightness, so we do not exit - * update_status early the first time it's called - */ - pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; - - backlight_update_status(pcf_bl->bl); - - return 0; -} - -static struct platform_driver pcf50633_bl_driver = { - .probe = pcf50633_bl_probe, - .driver = { - .name = "pcf50633-backlight", - }, -}; - -module_platform_driver(pcf50633_bl_driver); - -MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); -MODULE_DESCRIPTION("PCF50633 backlight driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pcf50633-backlight"); diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c index dc37494baf42..c9fe50f4d8ed 100644 --- a/drivers/video/backlight/platform_lcd.c +++ b/drivers/video/backlight/platform_lcd.c @@ -9,8 +9,6 @@ #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/fb.h> -#include <linux/backlight.h> #include <linux/lcd.h> #include <linux/slab.h> @@ -42,7 +40,7 @@ static int platform_lcd_set_power(struct lcd_device *lcd, int power) struct platform_lcd *plcd = to_our_lcd(lcd); int lcd_power = 1; - if (power == FB_BLANK_POWERDOWN || plcd->suspended) + if (power == LCD_POWER_OFF || plcd->suspended) lcd_power = 0; plcd->pdata->set_power(plcd->pdata, lcd_power); @@ -51,21 +49,17 @@ static int platform_lcd_set_power(struct lcd_device *lcd, int power) return 0; } -static int platform_lcd_match(struct lcd_device *lcd, struct fb_info *info) +static bool platform_lcd_controls_device(struct lcd_device *lcd, struct device *display_device) { struct platform_lcd *plcd = to_our_lcd(lcd); - struct plat_lcd_data *pdata = plcd->pdata; - if (pdata->match_fb) - return pdata->match_fb(pdata, info); - - return plcd->us->parent == info->device; + return plcd->us->parent == display_device; } -static struct lcd_ops platform_lcd_ops = { - .get_power = platform_lcd_get_power, - .set_power = platform_lcd_set_power, - .check_fb = platform_lcd_match, +static const struct lcd_ops platform_lcd_ops = { + .get_power = platform_lcd_get_power, + .set_power = platform_lcd_set_power, + .controls_device = platform_lcd_controls_device, }; static int platform_lcd_probe(struct platform_device *pdev) @@ -102,7 +96,7 @@ static int platform_lcd_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, plcd); - platform_lcd_set_power(plcd->lcd, FB_BLANK_NORMAL); + platform_lcd_set_power(plcd->lcd, LCD_POWER_REDUCED); return 0; } @@ -143,5 +137,6 @@ static struct platform_driver platform_lcd_driver = { module_platform_driver(platform_lcd_driver); MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>"); +MODULE_DESCRIPTION("Generic platform-device LCD power control interface"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:platform-lcd"); diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c index ffcebf6aa76a..237d3d3f3bb1 100644 --- a/drivers/video/backlight/pwm_bl.c +++ b/drivers/video/backlight/pwm_bl.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/err.h> #include <linux/pwm.h> @@ -34,7 +33,6 @@ struct pwm_bl_data { int brightness); void (*notify_after)(struct device *, int brightness); - int (*check_fb)(struct device *, struct fb_info *); void (*exit)(struct device *); }; @@ -129,17 +127,8 @@ static int pwm_backlight_update_status(struct backlight_device *bl) return 0; } -static int pwm_backlight_check_fb(struct backlight_device *bl, - struct fb_info *info) -{ - struct pwm_bl_data *pb = bl_get_data(bl); - - return !pb->check_fb || pb->check_fb(pb->dev, info); -} - static const struct backlight_ops pwm_backlight_ops = { .update_status = pwm_backlight_update_status, - .check_fb = pwm_backlight_check_fb, }; #ifdef CONFIG_OF @@ -437,7 +426,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) /* Not booted with device tree or no phandle link to the node */ if (!node || !node->phandle) - return FB_BLANK_UNBLANK; + return BACKLIGHT_POWER_ON; /* * If the driver is probed from the device tree and there is a @@ -445,7 +434,7 @@ static int pwm_backlight_initial_power_state(const struct pwm_bl_data *pb) * assume that another driver will enable the backlight at the * appropriate time. Therefore, if it is disabled, keep it so. */ - return active ? FB_BLANK_UNBLANK: FB_BLANK_POWERDOWN; + return active ? BACKLIGHT_POWER_ON : BACKLIGHT_POWER_OFF; } static int pwm_backlight_probe(struct platform_device *pdev) @@ -482,7 +471,6 @@ static int pwm_backlight_probe(struct platform_device *pdev) pb->notify = data->notify; pb->notify_after = data->notify_after; - pb->check_fb = data->check_fb; pb->exit = data->exit; pb->dev = &pdev->dev; pb->enabled = false; @@ -709,7 +697,7 @@ static struct platform_driver pwm_backlight_driver = { .of_match_table = of_match_ptr(pwm_backlight_of_match), }, .probe = pwm_backlight_probe, - .remove_new = pwm_backlight_remove, + .remove = pwm_backlight_remove, .shutdown = pwm_backlight_shutdown, }; diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c index 10129095a4c1..9afe701b2a1b 100644 --- a/drivers/video/backlight/qcom-wled.c +++ b/drivers/video/backlight/qcom-wled.c @@ -1741,7 +1741,7 @@ MODULE_DEVICE_TABLE(of, wled_match_table); static struct platform_driver wled_driver = { .probe = wled_probe, - .remove_new = wled_remove, + .remove = wled_remove, .driver = { .name = "qcom,wled", .of_match_table = wled_match_table, diff --git a/drivers/video/backlight/rave-sp-backlight.c b/drivers/video/backlight/rave-sp-backlight.c index 05b5f003a3d1..e708a060a6e4 100644 --- a/drivers/video/backlight/rave-sp-backlight.c +++ b/drivers/video/backlight/rave-sp-backlight.c @@ -19,7 +19,7 @@ static int rave_sp_backlight_update_status(struct backlight_device *bd) { const struct backlight_properties *p = &bd->props; const u8 intensity = - (p->power == FB_BLANK_UNBLANK) ? p->brightness : 0; + (p->power == BACKLIGHT_POWER_ON) ? p->brightness : 0; struct rave_sp *sp = dev_get_drvdata(&bd->dev); u8 cmd[] = { [0] = RAVE_SP_CMD_SET_BACKLIGHT, diff --git a/drivers/video/backlight/rt4831-backlight.c b/drivers/video/backlight/rt4831-backlight.c index 7d1af4c2ca67..7ead75929a43 100644 --- a/drivers/video/backlight/rt4831-backlight.c +++ b/drivers/video/backlight/rt4831-backlight.c @@ -224,9 +224,10 @@ static struct platform_driver rt4831_bl_driver = { .of_match_table = rt4831_bl_of_match, }, .probe = rt4831_bl_probe, - .remove_new = rt4831_bl_remove, + .remove = rt4831_bl_remove, }; module_platform_driver(rt4831_bl_driver); MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>"); +MODULE_DESCRIPTION("Richtek RT4831 Backlight Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c index eb18c6eb0ff0..2749231f0385 100644 --- a/drivers/video/backlight/sky81452-backlight.c +++ b/drivers/video/backlight/sky81452-backlight.c @@ -182,7 +182,7 @@ static const struct attribute_group sky81452_bl_attr_group = { static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( struct device *dev) { - struct device_node *np = of_node_get(dev->of_node); + struct device_node *np = dev->of_node; struct sky81452_bl_platform_data *pdata; int num_entry; unsigned int sources[6]; @@ -194,10 +194,8 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( } pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) { - of_node_put(np); + if (!pdata) return ERR_PTR(-ENOMEM); - } of_property_read_string(np, "name", &pdata->name); pdata->ignore_pwm = of_property_read_bool(np, "skyworks,ignore-pwm"); @@ -217,7 +215,6 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( num_entry); if (ret < 0) { dev_err(dev, "led-sources node is invalid.\n"); - of_node_put(np); return ERR_PTR(-EINVAL); } @@ -237,7 +234,6 @@ static struct sky81452_bl_platform_data *sky81452_bl_parse_dt( if (ret < 0) pdata->boost_current_limit = 2750; - of_node_put(np); return pdata; } #else @@ -319,7 +315,7 @@ static void sky81452_bl_remove(struct platform_device *pdev) sysfs_remove_group(&bd->dev.kobj, &sky81452_bl_attr_group); - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; bd->props.brightness = 0; backlight_update_status(bd); @@ -341,7 +337,7 @@ static struct platform_driver sky81452_bl_driver = { .of_match_table = of_match_ptr(sky81452_bl_of_match), }, .probe = sky81452_bl_probe, - .remove_new = sky81452_bl_remove, + .remove = sky81452_bl_remove, }; module_platform_driver(sky81452_bl_driver); diff --git a/drivers/video/backlight/tdo24m.c b/drivers/video/backlight/tdo24m.c index fc6fbaf85594..c04ee3d04d87 100644 --- a/drivers/video/backlight/tdo24m.c +++ b/drivers/video/backlight/tdo24m.c @@ -12,11 +12,10 @@ #include <linux/device.h> #include <linux/spi/spi.h> #include <linux/spi/tdo24m.h> -#include <linux/fb.h> #include <linux/lcd.h> #include <linux/slab.h> -#define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) +#define POWER_IS_ON(pwr) ((pwr) <= LCD_POWER_REDUCED) #define TDO24M_SPI_BUFF_SIZE (4) #define MODE_QVGA 0 @@ -308,12 +307,12 @@ static int tdo24m_get_power(struct lcd_device *ld) return lcd->power; } -static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m) +static int tdo24m_set_mode(struct lcd_device *ld, u32 xres, u32 yres) { struct tdo24m *lcd = lcd_get_data(ld); int mode = MODE_QVGA; - if (m->xres == 640 || m->xres == 480) + if (xres == 640 || xres == 480) mode = MODE_VGA; if (lcd->mode == mode) @@ -322,7 +321,7 @@ static int tdo24m_set_mode(struct lcd_device *ld, struct fb_videomode *m) return lcd->adj_mode(lcd, mode); } -static struct lcd_ops tdo24m_ops = { +static const struct lcd_ops tdo24m_ops = { .get_power = tdo24m_get_power, .set_power = tdo24m_set_power, .set_mode = tdo24m_set_mode, @@ -354,7 +353,7 @@ static int tdo24m_probe(struct spi_device *spi) return -ENOMEM; lcd->spi_dev = spi; - lcd->power = FB_BLANK_POWERDOWN; + lcd->power = LCD_POWER_OFF; lcd->mode = MODE_VGA; /* default to VGA */ lcd->buf = devm_kzalloc(&spi->dev, TDO24M_SPI_BUFF_SIZE, GFP_KERNEL); @@ -390,7 +389,7 @@ static int tdo24m_probe(struct spi_device *spi) return PTR_ERR(lcd->lcd_dev); spi_set_drvdata(spi, lcd); - err = tdo24m_power(lcd, FB_BLANK_UNBLANK); + err = tdo24m_power(lcd, LCD_POWER_ON); if (err) return err; @@ -401,7 +400,7 @@ static void tdo24m_remove(struct spi_device *spi) { struct tdo24m *lcd = spi_get_drvdata(spi); - tdo24m_power(lcd, FB_BLANK_POWERDOWN); + tdo24m_power(lcd, LCD_POWER_OFF); } #ifdef CONFIG_PM_SLEEP @@ -409,14 +408,14 @@ static int tdo24m_suspend(struct device *dev) { struct tdo24m *lcd = dev_get_drvdata(dev); - return tdo24m_power(lcd, FB_BLANK_POWERDOWN); + return tdo24m_power(lcd, LCD_POWER_OFF); } static int tdo24m_resume(struct device *dev) { struct tdo24m *lcd = dev_get_drvdata(dev); - return tdo24m_power(lcd, FB_BLANK_UNBLANK); + return tdo24m_power(lcd, LCD_POWER_ON); } #endif @@ -427,7 +426,7 @@ static void tdo24m_shutdown(struct spi_device *spi) { struct tdo24m *lcd = spi_get_drvdata(spi); - tdo24m_power(lcd, FB_BLANK_POWERDOWN); + tdo24m_power(lcd, LCD_POWER_OFF); } static struct spi_driver tdo24m_driver = { diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c index d96d713fe7db..8aa860350644 100644 --- a/drivers/video/backlight/tps65217_bl.c +++ b/drivers/video/backlight/tps65217_bl.c @@ -11,7 +11,6 @@ #include <linux/kernel.h> #include <linux/backlight.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/mfd/tps65217.h> #include <linux/module.h> #include <linux/platform_device.h> diff --git a/drivers/video/backlight/vgg2432a4.c b/drivers/video/backlight/vgg2432a4.c index bfc1913e8b55..3005eba6c82c 100644 --- a/drivers/video/backlight/vgg2432a4.c +++ b/drivers/video/backlight/vgg2432a4.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/init.h> #include <linux/lcd.h> #include <linux/module.h> diff --git a/drivers/video/backlight/wm831x_bl.c b/drivers/video/backlight/wm831x_bl.c index c5aaee205bdf..49027f04a1ec 100644 --- a/drivers/video/backlight/wm831x_bl.c +++ b/drivers/video/backlight/wm831x_bl.c @@ -9,7 +9,6 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/module.h> -#include <linux/fb.h> #include <linux/backlight.h> #include <linux/slab.h> diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index bc31db6ef7d2..12f54480f57f 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -24,7 +24,7 @@ config VGA_CONSOLE Say Y. config MDA_CONSOLE - depends on !M68K && !PARISC && ISA + depends on VGA_CONSOLE && ISA tristate "MDA text console (dual-headed)" help Say Y here if you have an old MDA or monochrome Hercules graphics @@ -47,12 +47,11 @@ config SGI_NEWPORT_CONSOLE card of your Indy. Most people say Y here. config DUMMY_CONSOLE - bool - default y + def_bool VT || VGA_CONSOLE || FRAMEBUFFER_CONSOLE config DUMMY_CONSOLE_COLUMNS int "Initial number of console screen columns" - depends on DUMMY_CONSOLE && !ARCH_FOOTBRIDGE + depends on DUMMY_CONSOLE && !(ARCH_FOOTBRIDGE && VGA_CONSOLE) default 160 if PARISC default 80 help @@ -62,7 +61,7 @@ config DUMMY_CONSOLE_COLUMNS config DUMMY_CONSOLE_ROWS int "Initial number of console screen rows" - depends on DUMMY_CONSOLE && !ARCH_FOOTBRIDGE + depends on DUMMY_CONSOLE && !(ARCH_FOOTBRIDGE && VGA_CONSOLE) default 64 if PARISC default 30 if ARM default 25 diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index c0e1f4554a44..d52cd99cd18b 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -561,5 +561,6 @@ static void __exit mda_console_exit(void) module_init(mda_console_init); module_exit(mda_console_exit); +MODULE_DESCRIPTION("MDA based console driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index a51cfc1d560e..242415366074 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -744,4 +744,5 @@ static struct gio_driver newport_driver = { }; module_driver(newport_driver, gio_register_driver, gio_unregister_driver); +MODULE_DESCRIPTION("SGI Newport console driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 4c7b4959a1aa..f1f3ee8e5e8a 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -391,4 +391,5 @@ static int __init sticonsole_init(void) } module_init(sticonsole_init); +MODULE_DESCRIPTION("HP STI console driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 7597f04b0dc7..f9cdbf8c53e3 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1168,7 +1168,7 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_end - c->vc_screenbuf_size; vga_rolled_over = 0; - } else + } else if (oldo - delta >= (unsigned long)c->vc_screenbuf) c->vc_origin -= delta; c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; scr_memsetw((u16 *) (c->vc_origin), c->vc_video_erase_char, @@ -1222,4 +1222,5 @@ void vgacon_register_screen(struct screen_info *si) vga_si = si; } +MODULE_DESCRIPTION("VGA based console driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 197b6d5268e9..55c6686f091e 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -157,7 +157,7 @@ config FB_IMX config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" - depends on FB && PCI && (BROKEN || !SPARC64) + depends on FB && PCI && HAS_IOPORT && (BROKEN || !SPARC64) select FB_IOMEM_HELPERS help This enables support for the Integraphics CyberPro 20x0 and 5000 @@ -245,7 +245,7 @@ config FB_FM2 config FB_ARC tristate "Arc Monochrome LCD board support" - depends on FB && (X86 || COMPILE_TEST) + depends on FB && HAS_IOPORT && (X86 || COMPILE_TEST) select FB_SYSMEM_HELPERS_DEFERRED help This enables support for the Arc Monochrome LCD board. The board @@ -649,6 +649,7 @@ config FB_S1D13XXX config FB_ATMEL tristate "AT91 LCD Controller support" depends on FB && OF && HAVE_CLK && HAS_IOMEM + depends on BACKLIGHT_CLASS_DEVICE depends on HAVE_FB_ATMEL || COMPILE_TEST select FB_BACKLIGHT select FB_IOMEM_HELPERS @@ -660,7 +661,6 @@ config FB_ATMEL config FB_NVIDIA tristate "nVidia Framebuffer Support" depends on FB && PCI - select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -700,6 +700,8 @@ config FB_NVIDIA_DEBUG config FB_NVIDIA_BACKLIGHT bool "Support for backlight control" depends on FB_NVIDIA + depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_NVIDIA + select FB_BACKLIGHT default y help Say Y here if you want to control the backlight of your display. @@ -707,7 +709,6 @@ config FB_NVIDIA_BACKLIGHT config FB_RIVA tristate "nVidia Riva support" depends on FB && PCI - select FB_BACKLIGHT if FB_RIVA_BACKLIGHT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -747,6 +748,8 @@ config FB_RIVA_DEBUG config FB_RIVA_BACKLIGHT bool "Support for backlight control" depends on FB_RIVA + depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_RIVA + select FB_BACKLIGHT default y help Say Y here if you want to control the backlight of your display. @@ -934,7 +937,6 @@ config FB_MATROX_MAVEN config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI - select FB_BACKLIGHT if FB_RADEON_BACKLIGHT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -960,6 +962,8 @@ config FB_RADEON_I2C config FB_RADEON_BACKLIGHT bool "Support for backlight control" depends on FB_RADEON + depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_RADEON + select FB_BACKLIGHT default y help Say Y here if you want to control the backlight of your display. @@ -975,7 +979,6 @@ config FB_RADEON_DEBUG config FB_ATY128 tristate "ATI Rage128 display support" depends on FB && PCI - select FB_BACKLIGHT if FB_ATY128_BACKLIGHT select FB_IOMEM_HELPERS select FB_MACMODES if PPC_PMAC help @@ -989,6 +992,8 @@ config FB_ATY128 config FB_ATY128_BACKLIGHT bool "Support for backlight control" depends on FB_ATY128 + depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_ATY128 + select FB_BACKLIGHT default y help Say Y here if you want to control the backlight of your display. @@ -999,7 +1004,6 @@ config FB_ATY select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_BACKLIGHT if FB_ATY_BACKLIGHT select FB_IOMEM_FOPS select FB_MACMODES if PPC select FB_ATY_CT if SPARC64 && PCI @@ -1040,13 +1044,15 @@ config FB_ATY_GX config FB_ATY_BACKLIGHT bool "Support for backlight control" depends on FB_ATY + depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_ATY + select FB_BACKLIGHT default y help Say Y here if you want to control the backlight of your display. config FB_S3 tristate "S3 Trio/Virge support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1107,7 +1113,7 @@ config FB_SAVAGE_ACCEL config FB_SIS tristate "SiS/XGI display support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select BOOT_VESA_SUPPORT if FB_SIS = y select FB_CFB_FILLRECT select FB_CFB_COPYAREA @@ -1138,7 +1144,7 @@ config FB_SIS_315 config FB_VIA tristate "VIA UniChrome (Pro) and Chrome9 display support" - depends on FB && PCI && GPIOLIB && I2C && (X86 || COMPILE_TEST) + depends on FB && PCI && GPIOLIB && I2C && HAS_IOPORT && (X86 || COMPILE_TEST) select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1177,7 +1183,7 @@ endif config FB_NEOMAGIC tristate "NeoMagic display support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1204,7 +1210,7 @@ config FB_KYRO config FB_3DFX tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1236,7 +1242,6 @@ config FB_3DFX_I2C config FB_VOODOO1 tristate "3Dfx Voodoo Graphics (sst1) support" depends on FB && PCI - depends on FB_DEVICE select FB_IOMEM_HELPERS help Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or @@ -1252,7 +1257,7 @@ config FB_VOODOO1 config FB_VT8623 tristate "VIA VT8623 support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1267,7 +1272,7 @@ config FB_VT8623 config FB_TRIDENT tristate "Trident/CyberXXX/CyberBlade support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1290,7 +1295,7 @@ config FB_TRIDENT config FB_ARK tristate "ARK 2000PV support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT @@ -1374,6 +1379,7 @@ config FB_VT8500 config FB_WM8505 bool "Wondermedia WM8xxx-series frame buffer support" depends on (FB = y) && HAS_IOMEM && (ARCH_VT8500 || COMPILE_TEST) + select FB_IOMEM_FOPS select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) select FB_SYS_IMAGEBLIT @@ -1528,6 +1534,7 @@ config FB_SH_MOBILE_LCDC depends on FB && HAVE_CLK && HAS_IOMEM depends on SUPERH || COMPILE_TEST depends on FB_DEVICE + depends on BACKLIGHT_CLASS_DEVICE select FB_BACKLIGHT select FB_DEFERRED_IO select FB_DMAMEM_HELPERS @@ -1648,8 +1655,8 @@ config FB_COBALT select FB_IOMEM_HELPERS config FB_SH7760 - bool "SH7760/SH7763/SH7720/SH7721 LCDC support" - depends on FB=y && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ + tristate "SH7760/SH7763/SH7720/SH7721 LCDC support" + depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721) select FB_IOMEM_HELPERS help @@ -1660,19 +1667,6 @@ config FB_SH7760 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for panels <= 320 pixel horizontal resolution. -config FB_DA8XX - tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" - depends on FB && HAVE_CLK && HAS_IOMEM - depends on ARCH_DAVINCI_DA8XX || SOC_AM33XX || COMPILE_TEST - select FB_CFB_REV_PIXELS_IN_BYTE - select FB_IOMEM_HELPERS - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - This is the frame buffer device driver for the TI LCD controller - found on DA8xx/OMAP-L1xx/AM335x SoCs. - If unsure, say N. - config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB @@ -1806,6 +1800,7 @@ config FB_SSD1307 tristate "Solomon SSD1307 framebuffer support" depends on FB && I2C depends on GPIOLIB || COMPILE_TEST + depends on BACKLIGHT_CLASS_DEVICE select FB_BACKLIGHT select FB_SYSMEM_HELPERS_DEFERRED help @@ -1814,7 +1809,7 @@ config FB_SSD1307 config FB_SM712 tristate "Silicon Motion SM712 framebuffer support" - depends on FB && PCI + depends on FB && PCI && HAS_IOPORT select FB_IOMEM_HELPERS help Frame buffer driver for the Silicon Motion SM710, SM712, SM721 diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 3eecd51267fa..b3d12f977c06 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -121,7 +121,6 @@ obj-$(CONFIG_FB_VESA) += vesafb.o obj-$(CONFIG_FB_EFI) += efifb.o obj-$(CONFIG_FB_VGA16) += vga16fb.o obj-$(CONFIG_FB_OF) += offb.o -obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o obj-$(CONFIG_FB_SIMPLE) += simplefb.o diff --git a/drivers/video/fbdev/amifb.c b/drivers/video/fbdev/amifb.c index 305f396c764c..1116a0789ca4 100644 --- a/drivers/video/fbdev/amifb.c +++ b/drivers/video/fbdev/amifb.c @@ -3774,13 +3774,14 @@ static void __exit amifb_remove(struct platform_device *pdev) * triggers a section mismatch warning. */ static struct platform_driver amifb_driver __refdata = { - .remove_new = __exit_p(amifb_remove), - .driver = { + .remove = __exit_p(amifb_remove), + .driver = { .name = "amiga-video", }, }; module_platform_driver_probe(amifb_driver, amifb_probe); +MODULE_DESCRIPTION("Amiga builtin chipset frame buffer driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:amiga-video"); diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c index b2408543277c..b807cf07522d 100644 --- a/drivers/video/fbdev/arcfb.c +++ b/drivers/video/fbdev/arcfb.c @@ -548,7 +548,7 @@ static void arcfb_remove(struct platform_device *dev) static struct platform_driver arcfb_driver = { .probe = arcfb_probe, - .remove_new = arcfb_remove, + .remove = arcfb_remove, .driver = { .name = "arcfb", }, diff --git a/drivers/video/fbdev/arkfb.c b/drivers/video/fbdev/arkfb.c index 082501feceb9..ec084323115f 100644 --- a/drivers/video/fbdev/arkfb.c +++ b/drivers/video/fbdev/arkfb.c @@ -431,9 +431,10 @@ static struct dac_ops ics5342_ops = { static struct dac_info * ics5342_init(dac_read_regs_t drr, dac_write_regs_t dwr, void *data) { - struct dac_info *info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL); + struct ics5342_info *ics_info = kzalloc(sizeof(struct ics5342_info), GFP_KERNEL); + struct dac_info *info = &ics_info->dac; - if (! info) + if (!ics_info) return NULL; info->dacops = &ics5342_ops; diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c index 9e391e5eaf9d..9dfbc5310210 100644 --- a/drivers/video/fbdev/atmel_lcdfb.c +++ b/drivers/video/fbdev/atmel_lcdfb.c @@ -152,8 +152,7 @@ static void init_backlight(struct atmel_lcdfb_info *sinfo) } sinfo->backlight = bl; - bl->props.power = FB_BLANK_UNBLANK; - bl->props.fb_blank = FB_BLANK_UNBLANK; + bl->props.power = BACKLIGHT_POWER_ON; bl->props.brightness = atmel_bl_get_brightness(bl); } @@ -163,7 +162,7 @@ static void exit_backlight(struct atmel_lcdfb_info *sinfo) return; if (sinfo->backlight->ops) { - sinfo->backlight->props.power = FB_BLANK_POWERDOWN; + sinfo->backlight->props.power = BACKLIGHT_POWER_OFF; sinfo->backlight->ops->update_status(sinfo->backlight); } backlight_device_unregister(sinfo->backlight); @@ -1300,7 +1299,7 @@ static int atmel_lcdfb_resume(struct platform_device *pdev) static struct platform_driver atmel_lcdfb_driver = { .probe = atmel_lcdfb_probe, - .remove_new = atmel_lcdfb_remove, + .remove = atmel_lcdfb_remove, .suspend = atmel_lcdfb_suspend, .resume = atmel_lcdfb_resume, .driver = { diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c index f4de11f19235..f55b4c7609a8 100644 --- a/drivers/video/fbdev/aty/aty128fb.c +++ b/drivers/video/fbdev/aty/aty128fb.c @@ -1299,11 +1299,11 @@ static void aty128_set_lcd_enable(struct aty128fb_par *par, int on) reg &= ~LVDS_DISPLAY_DIS; aty_st_le32(LVDS_GEN_CNTL, reg); #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_UNBLANK); + aty128_bl_set_power(info, BACKLIGHT_POWER_ON); #endif } else { #ifdef CONFIG_FB_ATY128_BACKLIGHT - aty128_bl_set_power(info, FB_BLANK_POWERDOWN); + aty128_bl_set_power(info, BACKLIGHT_POWER_OFF); #endif reg = aty_ld_le32(LVDS_GEN_CNTL); reg |= LVDS_DISPLAY_DIS; @@ -1858,7 +1858,7 @@ static void aty128_bl_init(struct aty128fb_par *par) 219 * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("aty128: Backlight initialized (%s)\n", name); diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index a6dd1cd27125..210fd3ac18a4 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -2272,7 +2272,7 @@ static void aty_bl_init(struct atyfb_par *par) 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("aty: Backlight initialized (%s)\n", name); diff --git a/drivers/video/fbdev/aty/mach64_accel.c b/drivers/video/fbdev/aty/mach64_accel.c index e4b2c89baee2..826fb04de64c 100644 --- a/drivers/video/fbdev/aty/mach64_accel.c +++ b/drivers/video/fbdev/aty/mach64_accel.c @@ -5,7 +5,7 @@ */ #include <linux/delay.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <linux/fb.h> #include <video/mach64.h> #include "atyfb.h" diff --git a/drivers/video/fbdev/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c index 971355c2cd7e..e826cb7dd55d 100644 --- a/drivers/video/fbdev/aty/mach64_cursor.c +++ b/drivers/video/fbdev/aty/mach64_cursor.c @@ -6,7 +6,6 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/string.h> -#include "../core/fb_draw.h" #include <asm/io.h> @@ -57,6 +56,12 @@ * definitation and CUR_VERT_POSN must be saturated to zero. */ +/* compose pixels based on mask */ +static inline unsigned long comp(unsigned long set, unsigned long unset, unsigned long mask) +{ + return ((set ^ unset) & mask) ^ unset; +} + /* * Hardware Cursor support. */ diff --git a/drivers/video/fbdev/aty/radeon_backlight.c b/drivers/video/fbdev/aty/radeon_backlight.c index 23a38c3f3977..bf764c92bcf1 100644 --- a/drivers/video/fbdev/aty/radeon_backlight.c +++ b/drivers/video/fbdev/aty/radeon_backlight.c @@ -59,7 +59,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) */ level = backlight_get_brightness(bd); - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); radeon_engine_idle(); lvds_gen_cntl = INREG(LVDS_GEN_CNTL); @@ -179,7 +179,7 @@ void radeonfb_bl_init(struct radeonfb_info *rinfo) 217 * FB_BACKLIGHT_MAX / MAX_RADEON_LEVEL); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("radeonfb: Backlight initialized (%s)\n", name); diff --git a/drivers/video/fbdev/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c index 36bfb6deb8ab..c6c4753f6415 100644 --- a/drivers/video/fbdev/aty/radeon_base.c +++ b/drivers/video/fbdev/aty/radeon_base.c @@ -1082,7 +1082,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) } break; case MT_LCD: - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); val = INREG(LVDS_GEN_CNTL); if (unblank) { u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON @@ -2199,7 +2199,7 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = kobj_to_dev(kobj); @@ -2211,7 +2211,7 @@ static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj, static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, + const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { struct device *dev = kobj_to_dev(kobj); @@ -2227,7 +2227,7 @@ static const struct bin_attribute edid1_attr = { .mode = 0444, }, .size = EDID_LENGTH, - .read = radeon_show_edid1, + .read_new = radeon_show_edid1, }; static const struct bin_attribute edid2_attr = { @@ -2236,7 +2236,7 @@ static const struct bin_attribute edid2_attr = { .mode = 0444, }, .size = EDID_LENGTH, - .read = radeon_show_edid2, + .read_new = radeon_show_edid2, }; static int radeonfb_pci_register(struct pci_dev *pdev, @@ -2516,7 +2516,7 @@ static void radeonfb_pci_unregister(struct pci_dev *pdev) if (rinfo->mon2_EDID) sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr); - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); arch_phys_wc_del(rinfo->wc_cookie); radeonfb_bl_exit(rinfo); unregister_framebuffer(info); diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index 97a5972f5b1f..5ff4a964055a 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c @@ -2650,7 +2650,7 @@ static int radeonfb_pci_suspend_late(struct device *dev, pm_message_t mesg) /* Sleep */ rinfo->asleep = 1; rinfo->lock_blank = 1; - del_timer_sync(&rinfo->lvds_timer); + timer_delete_sync(&rinfo->lvds_timer); #ifdef CONFIG_PPC_PMAC /* On powermac, we have hooks to properly suspend/resume AGP now, diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c index 08109ce535cd..6251a6b07b3a 100644 --- a/drivers/video/fbdev/au1100fb.c +++ b/drivers/video/fbdev/au1100fb.c @@ -137,13 +137,15 @@ static int au1100fb_fb_blank(int blank_mode, struct fb_info *fbi) */ int au1100fb_setmode(struct au1100fb_device *fbdev) { - struct fb_info *info = &fbdev->info; + struct fb_info *info; u32 words; int index; if (!fbdev) return -EINVAL; + info = &fbdev->info; + /* Update var-dependent FB info */ if (panel_is_active(fbdev->panel) || panel_is_color(fbdev->panel)) { if (info->var.bits_per_pixel <= 8) { @@ -588,7 +590,7 @@ static struct platform_driver au1100fb_driver = { .name = "au1100-lcd", }, .probe = au1100fb_drv_probe, - .remove_new = au1100fb_drv_remove, + .remove = au1100fb_drv_remove, .suspend = au1100fb_drv_suspend, .resume = au1100fb_drv_resume, }; diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index 6f20efc663d7..ed770222660b 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1557,7 +1557,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) return ret; } - strncpy(fbi->fix.id, "AU1200", sizeof(fbi->fix.id)); + strscpy(fbi->fix.id, "AU1200"); fbi->fix.smem_start = fbdev->fb_phys; fbi->fix.smem_len = fbdev->fb_len; fbi->fix.type = FB_TYPE_PACKED_PIXELS; @@ -1833,7 +1833,7 @@ static struct platform_driver au1200fb_driver = { .pm = AU1200FB_PMOPS, }, .probe = au1200fb_drv_probe, - .remove_new = au1200fb_drv_remove, + .remove = au1200fb_drv_remove, }; module_platform_driver(au1200fb_driver); diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c index e857b15e9f5d..c8ba098a8c42 100644 --- a/drivers/video/fbdev/broadsheetfb.c +++ b/drivers/video/fbdev/broadsheetfb.c @@ -1151,7 +1151,7 @@ static void broadsheetfb_remove(struct platform_device *dev) static struct platform_driver broadsheetfb_driver = { .probe = broadsheetfb_probe, - .remove_new = broadsheetfb_remove, + .remove = broadsheetfb_remove, .driver = { .name = "broadsheetfb", }, diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c index eaab51be74f8..e757462af0a6 100644 --- a/drivers/video/fbdev/bw2.c +++ b/drivers/video/fbdev/bw2.c @@ -147,7 +147,7 @@ bw2_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map bw2_mmap_map[] = { +static const struct sbus_mmap_map bw2_mmap_map[] = { { .size = SBUS_MMAP_FBSIZE(1) }, @@ -372,7 +372,7 @@ static struct platform_driver bw2_driver = { .of_match_table = bw2_match, }, .probe = bw2_probe, - .remove_new = bw2_remove, + .remove = bw2_remove, }; static int __init bw2_init(void) diff --git a/drivers/video/fbdev/c2p_iplan2.c b/drivers/video/fbdev/c2p_iplan2.c index 19156dc6158c..cfd2361f24b1 100644 --- a/drivers/video/fbdev/c2p_iplan2.c +++ b/drivers/video/fbdev/c2p_iplan2.c @@ -11,7 +11,7 @@ #include <linux/module.h> #include <linux/string.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "c2p.h" #include "c2p_core.h" diff --git a/drivers/video/fbdev/c2p_planar.c b/drivers/video/fbdev/c2p_planar.c index ec7ac8526f06..819c82a98ac0 100644 --- a/drivers/video/fbdev/c2p_planar.c +++ b/drivers/video/fbdev/c2p_planar.c @@ -11,7 +11,7 @@ #include <linux/module.h> #include <linux/string.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include "c2p.h" #include "c2p_core.h" @@ -153,4 +153,5 @@ void c2p_planar(void *dst, const void *src, u32 dx, u32 dy, u32 width, } EXPORT_SYMBOL_GPL(c2p_planar); +MODULE_DESCRIPTION("Fast C2P (Chunky-to-Planar) Conversion"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/carminefb.c b/drivers/video/fbdev/carminefb.c index e56065cdba97..2bdd67595891 100644 --- a/drivers/video/fbdev/carminefb.c +++ b/drivers/video/fbdev/carminefb.c @@ -649,13 +649,13 @@ static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent) * is required for that largest resolution to avoid remaps at run * time */ - if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM) - carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM; + if (carminefb_fix.smem_len > CARMINE_TOTAL_DISPLAY_MEM) + carminefb_fix.smem_len = CARMINE_TOTAL_DISPLAY_MEM; - else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) { + else if (carminefb_fix.smem_len < CARMINE_TOTAL_DISPLAY_MEM) { printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d " "are required.", carminefb_fix.smem_len, - CARMINE_TOTAL_DIPLAY_MEM); + CARMINE_TOTAL_DISPLAY_MEM); goto err_unmap_vregs; } diff --git a/drivers/video/fbdev/carminefb.h b/drivers/video/fbdev/carminefb.h index 297688eba469..c9825481d96b 100644 --- a/drivers/video/fbdev/carminefb.h +++ b/drivers/video/fbdev/carminefb.h @@ -7,7 +7,7 @@ #define MAX_DISPLAY 2 #define CARMINE_DISPLAY_MEM (800 * 600 * 4) -#define CARMINE_TOTAL_DIPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY) +#define CARMINE_TOTAL_DISPLAY_MEM (CARMINE_DISPLAY_MEM * MAX_DISPLAY) #define CARMINE_USE_DISPLAY0 (1 << 0) #define CARMINE_USE_DISPLAY1 (1 << 1) diff --git a/drivers/video/fbdev/cg14.c b/drivers/video/fbdev/cg14.c index c161b2af8933..5389f8f07346 100644 --- a/drivers/video/fbdev/cg14.c +++ b/drivers/video/fbdev/cg14.c @@ -360,7 +360,7 @@ static void cg14_init_fix(struct fb_info *info, int linebytes, info->fix.accel = FB_ACCEL_SUN_CG14; } -static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = { +static const struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] = { { .voff = CG14_REGS, .poff = 0x80000000, @@ -590,7 +590,7 @@ static struct platform_driver cg14_driver = { .of_match_table = cg14_match, }, .probe = cg14_probe, - .remove_new = cg14_remove, + .remove = cg14_remove, }; static int __init cg14_init(void) diff --git a/drivers/video/fbdev/cg3.c b/drivers/video/fbdev/cg3.c index 5e1f1b9a81b6..a58a483014e6 100644 --- a/drivers/video/fbdev/cg3.c +++ b/drivers/video/fbdev/cg3.c @@ -209,7 +209,7 @@ static int cg3_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map cg3_mmap_map[] = { +static const struct sbus_mmap_map cg3_mmap_map[] = { { .voff = CG3_MMAP_OFFSET, .poff = CG3_RAM_OFFSET, @@ -458,7 +458,7 @@ static struct platform_driver cg3_driver = { .of_match_table = cg3_match, }, .probe = cg3_probe, - .remove_new = cg3_remove, + .remove = cg3_remove, }; static int __init cg3_init(void) diff --git a/drivers/video/fbdev/cg6.c b/drivers/video/fbdev/cg6.c index 69d3ce50948d..56d74468040a 100644 --- a/drivers/video/fbdev/cg6.c +++ b/drivers/video/fbdev/cg6.c @@ -545,7 +545,7 @@ static int cg6_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map cg6_mmap_map[] = { +static const struct sbus_mmap_map cg6_mmap_map[] = { { .voff = CG6_FBC, .poff = CG6_FBC_OFFSET, @@ -858,7 +858,7 @@ static struct platform_driver cg6_driver = { .of_match_table = cg6_match, }, .probe = cg6_probe, - .remove_new = cg6_remove, + .remove = cg6_remove, }; static int __init cg6_init(void) diff --git a/drivers/video/fbdev/chipsfb.c b/drivers/video/fbdev/chipsfb.c index b16a905588fe..33caf0b99a45 100644 --- a/drivers/video/fbdev/chipsfb.c +++ b/drivers/video/fbdev/chipsfb.c @@ -399,7 +399,7 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent) /* turn on the backlight */ mutex_lock(&pmac_backlight_mutex); if (pmac_backlight) { - pmac_backlight->props.power = FB_BLANK_UNBLANK; + pmac_backlight->props.power = BACKLIGHT_POWER_ON; backlight_update_status(pmac_backlight); } mutex_unlock(&pmac_backlight_mutex); diff --git a/drivers/video/fbdev/clps711x-fb.c b/drivers/video/fbdev/clps711x-fb.c index dcfd1fbbc7e1..5e61a349a4ab 100644 --- a/drivers/video/fbdev/clps711x-fb.c +++ b/drivers/video/fbdev/clps711x-fb.c @@ -162,22 +162,15 @@ static const struct fb_ops clps711x_fb_ops = { .fb_blank = clps711x_fb_blank, }; -static int clps711x_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi) -{ - struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev); - - return (!fi || fi->par == cfb) ? 1 : 0; -} - static int clps711x_lcd_get_power(struct lcd_device *lcddev) { struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev); if (!IS_ERR_OR_NULL(cfb->lcd_pwr)) if (!regulator_is_enabled(cfb->lcd_pwr)) - return FB_BLANK_NORMAL; + return LCD_POWER_REDUCED; - return FB_BLANK_UNBLANK; + return LCD_POWER_ON; } static int clps711x_lcd_set_power(struct lcd_device *lcddev, int blank) @@ -185,7 +178,7 @@ static int clps711x_lcd_set_power(struct lcd_device *lcddev, int blank) struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev); if (!IS_ERR_OR_NULL(cfb->lcd_pwr)) { - if (blank == FB_BLANK_UNBLANK) { + if (blank == LCD_POWER_ON) { if (!regulator_is_enabled(cfb->lcd_pwr)) return regulator_enable(cfb->lcd_pwr); } else { @@ -197,8 +190,7 @@ static int clps711x_lcd_set_power(struct lcd_device *lcddev, int blank) return 0; } -static struct lcd_ops clps711x_lcd_ops = { - .check_fb = clps711x_lcd_check_fb, +static const struct lcd_ops clps711x_lcd_ops = { .get_power = clps711x_lcd_get_power, .set_power = clps711x_lcd_set_power, }; @@ -325,16 +317,21 @@ static int clps711x_fb_probe(struct platform_device *pdev) if (ret) goto out_fb_dealloc_cmap; + lcd = devm_lcd_device_register(dev, "clps711x-lcd", dev, cfb, + &clps711x_lcd_ops); + if (IS_ERR(lcd)) { + ret = PTR_ERR(lcd); + goto out_fb_dealloc_cmap; + } + + info->lcd_dev = lcd; + ret = register_framebuffer(info); if (ret) goto out_fb_dealloc_cmap; - lcd = devm_lcd_device_register(dev, "clps711x-lcd", dev, cfb, - &clps711x_lcd_ops); - if (!IS_ERR(lcd)) - return 0; + return 0; - ret = PTR_ERR(lcd); unregister_framebuffer(info); out_fb_dealloc_cmap: @@ -371,7 +368,7 @@ static struct platform_driver clps711x_fb_driver = { .of_match_table = clps711x_fb_dt_ids, }, .probe = clps711x_fb_probe, - .remove_new = clps711x_fb_remove, + .remove = clps711x_fb_remove, }; module_platform_driver(clps711x_fb_driver); diff --git a/drivers/video/fbdev/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c index c2b8f894799c..308967b5096a 100644 --- a/drivers/video/fbdev/cobalt_lcdfb.c +++ b/drivers/video/fbdev/cobalt_lcdfb.c @@ -344,7 +344,7 @@ static void cobalt_lcdfb_remove(struct platform_device *dev) static struct platform_driver cobalt_lcdfb_driver = { .probe = cobalt_lcdfb_probe, - .remove_new = cobalt_lcdfb_remove, + .remove = cobalt_lcdfb_remove, .driver = { .name = "cobalt-lcd", }, diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig index db09fe87fcd4..4abe12db7594 100644 --- a/drivers/video/fbdev/core/Kconfig +++ b/drivers/video/fbdev/core/Kconfig @@ -69,7 +69,7 @@ config FB_CFB_REV_PIXELS_IN_BYTE bool depends on FB_CORE help - Allow generic frame-buffer functions to work on displays with 1, 2 + Allow I/O memory frame-buffer functions to work on displays with 1, 2 and 4 bits per pixel depths which has opposite order of pixels in byte order to bytes in long order. @@ -97,6 +97,14 @@ config FB_SYS_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version and the framebuffer is in system RAM. +config FB_SYS_REV_PIXELS_IN_BYTE + bool + depends on FB_CORE + help + Allow virtual memory frame-buffer functions to work on displays with 1, 2 + and 4 bits per pixel depths which has opposite order of pixels in + byte order to bytes in long order. + config FB_PROVIDE_GET_FB_UNMAPPED_AREA bool depends on FB @@ -144,6 +152,12 @@ config FB_DMAMEM_HELPERS select FB_SYS_IMAGEBLIT select FB_SYSMEM_FOPS +config FB_DMAMEM_HELPERS_DEFERRED + bool + depends on FB_CORE + select FB_DEFERRED_IO + select FB_DMAMEM_HELPERS + config FB_IOMEM_FOPS tristate depends on FB_CORE @@ -177,9 +191,8 @@ config FB_SYSMEM_HELPERS_DEFERRED select FB_SYSMEM_HELPERS config FB_BACKLIGHT - tristate + bool depends on FB - select BACKLIGHT_CLASS_DEVICE config FB_MODE_HELPERS bool "Enable Video Mode Handling Helpers" diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 3ff1b2a8659e..f9475c14f733 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -59,12 +59,11 @@ static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy, } static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width) + int sx, int height, int width, int fg, int bg) { - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; struct fb_fillrect region; - region.color = attr_bgcol_ec(bgshift, vc, info); + region.color = bg; region.dx = sx * vc->vc_font.width; region.dy = sy * vc->vc_font.height; region.width = width * vc->vc_font.width; diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c index a271f57d9c6c..23fbf3a8df7c 100644 --- a/drivers/video/fbdev/core/cfbcopyarea.c +++ b/drivers/video/fbdev/core/cfbcopyarea.c @@ -1,440 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic function for frame buffer with packed pixels of any depth. - * - * Copyright (C) 1999-2005 James Simmons <jsimmons@www.infradead.org> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * NOTES: - * - * This is for cfb packed pixels. Iplan and such are incorporated in the - * drivers that need them. - * - * FIXME - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. - * - * The two functions or copying forward and backward could be split up like - * the ones for filling, i.e. in aligned and unaligned versions. This would - * help moving some redundant computations and branches out of the loop, too. + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ - #include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#include <asm/io.h> -#include "fb_draw.h" - -#if BITS_PER_LONG == 32 -# define FB_WRITEL fb_writel -# define FB_READL fb_readl -#else -# define FB_WRITEL fb_writeq -# define FB_READL fb_readq -#endif - - /* - * Generic bitwise copy algorithm - */ - -static void -bitcpy(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, - const unsigned long __iomem *src, unsigned src_idx, int bits, - unsigned n, u32 bswapmask) -{ - unsigned long first, last; - int const shift = dst_idx-src_idx; -#if 0 - /* - * If you suspect bug in this function, compare it with this simple - * memmove implementation. - */ - memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); - return; +#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE #endif - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (!shift) { - // Same alignment for source and dest - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first != ~0UL) { - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - dst++; - src++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - FB_WRITEL(FB_READL(src++), dst++); - n -= 8; - } - while (n--) - FB_WRITEL(FB_READL(src++), dst++); - - // Trailing bits - if (last) - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } - } else { - /* Different alignment for source and dest */ - unsigned long d0, d1; - int m; - - int const left = shift & (bits - 1); - int const right = -shift & (bits - 1); - - if (dst_idx+n <= bits) { - // Single destination word - if (last) - first &= last; - d0 = FB_READL(src); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - if (shift > 0) { - // Single source word - d0 <<= left; - } else if (src_idx+n <= bits) { - // Single source word - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src + 1); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 >> right | d1 << left; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - } else { - // Multiple destination words - /** We must always remember the last value read, because in case - SRC and DST overlap bitwise (e.g. when moving just one pixel in - 1bpp), we always collect one full long for DST and that might - overlap with the current long from SRC. We store this value in - 'd0'. */ - d0 = FB_READL(src++); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - // Leading bits - if (shift > 0) { - // Single source word - d1 = d0; - d0 <<= left; - n -= bits - dst_idx; - } else { - // 2 source words - d1 = FB_READL(src++); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - - d0 = d0 >> right | d1 << left; - n -= bits - dst_idx; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - d0 = d1; - dst++; - - // Main chunk - m = n % bits; - n /= bits; - while ((n >= 4) && !bswapmask) { - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - d1 = FB_READL(src++); - FB_WRITEL(d0 >> right | d1 << left, dst++); - d0 = d1; - n -= 4; - } - while (n--) { - d1 = FB_READL(src++); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 >> right | d1 << left; - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(d0, dst++); - d0 = d1; - } - - // Trailing bits - if (m) { - if (m <= bits - right) { - // Single source word - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src); - d1 = fb_rev_pixels_in_long(d1, - bswapmask); - d0 = d0 >> right | d1 << left; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } - } - } -} - - /* - * Generic bitwise copy algorithm, operating backward - */ - -static void -bitcpy_rev(struct fb_info *p, unsigned long __iomem *dst, unsigned dst_idx, - const unsigned long __iomem *src, unsigned src_idx, int bits, - unsigned n, u32 bswapmask) -{ - unsigned long first, last; - int shift; - -#if 0 - /* - * If you suspect bug in this function, compare it with this simple - * memmove implementation. - */ - memmove((char *)dst + ((dst_idx & (bits - 1))) / 8, - (char *)src + ((src_idx & (bits - 1))) / 8, n / 8); - return; -#endif - - dst += (dst_idx + n - 1) / bits; - src += (src_idx + n - 1) / bits; - dst_idx = (dst_idx + n - 1) % bits; - src_idx = (src_idx + n - 1) % bits; - - shift = dst_idx-src_idx; - - first = ~fb_shifted_pixels_mask_long(p, (dst_idx + 1) % bits, bswapmask); - last = fb_shifted_pixels_mask_long(p, (bits + dst_idx + 1 - n) % bits, bswapmask); - - if (!shift) { - // Same alignment for source and dest - - if ((unsigned long)dst_idx+1 >= n) { - // Single word - if (first) - last &= first; - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } else { - // Multiple destination words - - // Leading bits - if (first) { - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst); - dst--; - src--; - n -= dst_idx+1; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - FB_WRITEL(FB_READL(src--), dst--); - n -= 8; - } - while (n--) - FB_WRITEL(FB_READL(src--), dst--); - - // Trailing bits - if (last != -1UL) - FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst); - } - } else { - // Different alignment for source and dest - unsigned long d0, d1; - int m; - - int const left = shift & (bits-1); - int const right = -shift & (bits-1); - - if ((unsigned long)dst_idx+1 >= n) { - // Single destination word - if (first) - last &= first; - d0 = FB_READL(src); - if (shift < 0) { - // Single source word - d0 >>= right; - } else if (1+(unsigned long)src_idx >= n) { - // Single source word - d0 <<= left; - } else { - // 2 source words - d1 = FB_READL(src - 1); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } else { - // Multiple destination words - /** We must always remember the last value read, because in case - SRC and DST overlap bitwise (e.g. when moving just one pixel in - 1bpp), we always collect one full long for DST and that might - overlap with the current long from SRC. We store this value in - 'd0'. */ - - d0 = FB_READL(src--); - d0 = fb_rev_pixels_in_long(d0, bswapmask); - // Leading bits - if (shift < 0) { - // Single source word - d1 = d0; - d0 >>= right; - } else { - // 2 source words - d1 = FB_READL(src--); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - if (!first) - FB_WRITEL(d0, dst); - else - FB_WRITEL(comp(d0, FB_READL(dst), first), dst); - d0 = d1; - dst--; - n -= dst_idx+1; - - // Main chunk - m = n % bits; - n /= bits; - while ((n >= 4) && !bswapmask) { - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - d1 = FB_READL(src--); - FB_WRITEL(d0 << left | d1 >> right, dst--); - d0 = d1; - n -= 4; - } - while (n--) { - d1 = FB_READL(src--); - d1 = fb_rev_pixels_in_long(d1, bswapmask); - d0 = d0 << left | d1 >> right; - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(d0, dst--); - d0 = d1; - } - - // Trailing bits - if (m) { - if (m <= bits - left) { - // Single source word - d0 <<= left; - } else { - // 2 source words - d1 = FB_READL(src); - d1 = fb_rev_pixels_in_long(d1, - bswapmask); - d0 = d0 << left | d1 >> right; - } - d0 = fb_rev_pixels_in_long(d0, bswapmask); - FB_WRITEL(comp(d0, FB_READL(dst), last), dst); - } - } - } -} +#include "cfbmem.h" +#include "fb_copyarea.h" void cfb_copyarea(struct fb_info *p, const struct fb_copyarea *area) { - u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; - u32 height = area->height, width = area->width; - unsigned int const bits_per_line = p->fix.line_length * 8u; - unsigned long __iomem *base = NULL; - int bits = BITS_PER_LONG, bytes = bits >> 3; - unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; - u32 bswapmask = fb_compute_bswapmask(p); - if (p->state != FBINFO_STATE_RUNNING) return; if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - /* if the beginning of the target area might overlap with the end of - the source area, be have to copy the area reverse. */ - if ((dy == sy && dx > sx) || (dy > sy)) { - dy += height; - sy += height; - rev_copy = 1; - } - - // split the base of the framebuffer into a long-aligned address and the - // index of the first bit - base = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); - // add offset of source and target area - dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; - src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; + fb_warn_once(p, "%s: framebuffer is not in I/O address space.\n", __func__); if (p->fbops->fb_sync) p->fbops->fb_sync(p); - if (rev_copy) { - while (height--) { - dst_idx -= bits_per_line; - src_idx -= bits_per_line; - bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel, bswapmask); - } - } else { - while (height--) { - bitcpy(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel, bswapmask); - dst_idx += bits_per_line; - src_idx += bits_per_line; - } - } + fb_copyarea(p, area); } - EXPORT_SYMBOL(cfb_copyarea); -MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); -MODULE_DESCRIPTION("Generic software accelerated copyarea"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("I/O memory packed pixel framebuffer area copy"); MODULE_LICENSE("GPL"); - diff --git a/drivers/video/fbdev/core/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c index cbaa4c9e2355..615de89256d5 100644 --- a/drivers/video/fbdev/core/cfbfillrect.c +++ b/drivers/video/fbdev/core/cfbfillrect.c @@ -1,374 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic fillrect for frame buffers with packed pixels of any depth. - * - * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * NOTES: - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. - * + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ #include <linux/module.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#include "fb_draw.h" -#if BITS_PER_LONG == 32 -# define FB_WRITEL fb_writel -# define FB_READL fb_readl -#else -# define FB_WRITEL fb_writeq -# define FB_READL fb_readq +#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE #endif - /* - * Aligned pattern fill using 32/64-bit memory accesses - */ - -static void -bitfill_aligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, - unsigned long pat, unsigned n, int bits, u32 bswapmask) -{ - unsigned long first, last; - - if (!n) - return; - - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first!= ~0UL) { - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - dst++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - FB_WRITEL(pat, dst++); - n -= 8; - } - while (n--) - FB_WRITEL(pat, dst++); - - // Trailing bits - if (last) - FB_WRITEL(comp(pat, FB_READL(dst), last), dst); - } -} - - - /* - * Unaligned generic pattern fill using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned(struct fb_info *p, unsigned long __iomem *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - } else { - // Multiple destination words - // Leading bits - if (first) { - FB_WRITEL(comp(pat, FB_READL(dst), first), dst); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 4) { - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - FB_WRITEL(pat, dst++); - pat = pat << left | pat >> right; - } - - // Trailing bits - if (last) - FB_WRITEL(comp(pat, FB_READL(dst), last), dst); - } -} - - /* - * Aligned pattern invert using 32/64-bit memory accesses - */ -static void -bitfill_aligned_rev(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, unsigned n, int bits, - u32 bswapmask) -{ - unsigned long val = pat, dat; - unsigned long first, last; - - if (!n) - return; - - first = fb_shifted_pixels_mask_long(p, dst_idx, bswapmask); - last = ~fb_shifted_pixels_mask_long(p, (dst_idx+n) % bits, bswapmask); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, first), dst); - } else { - // Multiple destination words - // Leading bits - if (first!=0UL) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, first), dst); - dst++; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 8) { - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - n -= 8; - } - while (n--) { - FB_WRITEL(FB_READL(dst) ^ val, dst); - dst++; - } - // Trailing bits - if (last) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ val, dat, last), dst); - } - } -} - - - /* - * Unaligned generic pattern invert using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned_rev(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, int left, int right, - unsigned n, int bits) -{ - unsigned long first, last, dat; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - // Single word - if (last) - first &= last; - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, first), dst); - } else { - // Multiple destination words - - // Leading bits - if (first != 0UL) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, first), dst); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - // Main chunk - n /= bits; - while (n >= 4) { - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - FB_WRITEL(FB_READL(dst) ^ pat, dst); - dst++; - pat = pat << left | pat >> right; - } - - // Trailing bits - if (last) { - dat = FB_READL(dst); - FB_WRITEL(comp(dat ^ pat, dat, last), dst); - } - } -} +#include "cfbmem.h" +#include "fb_fillrect.h" void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long pat, pat2, fg; - unsigned long width = rect->width, height = rect->height; - int bits = BITS_PER_LONG, bytes = bits >> 3; - u32 bpp = p->var.bits_per_pixel; - unsigned long __iomem *dst; - int dst_idx, left; - if (p->state != FBINFO_STATE_RUNNING) return; if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - fg = ((u32 *) (p->pseudo_palette))[rect->color]; - else - fg = rect->color; - - pat = pixel_to_pat(bpp, fg); + fb_warn_once(p, "%s: framebuffer is not in I/O address space.\n", __func__); - dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; - dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; - /* FIXME For now we support 1-32 bpp only */ - left = bits % bpp; if (p->fbops->fb_sync) p->fbops->fb_sync(p); - if (!left) { - u32 bswapmask = fb_compute_bswapmask(p); - void (*fill_op32)(struct fb_info *p, - unsigned long __iomem *dst, int dst_idx, - unsigned long pat, unsigned n, int bits, - u32 bswapmask) = NULL; - switch (rect->rop) { - case ROP_XOR: - fill_op32 = bitfill_aligned_rev; - break; - case ROP_COPY: - fill_op32 = bitfill_aligned; - break; - default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); - fill_op32 = bitfill_aligned; - break; - } - while (height--) { - dst += dst_idx >> (ffs(bits) - 1); - dst_idx &= (bits - 1); - fill_op32(p, dst, dst_idx, pat, width*bpp, bits, - bswapmask); - dst_idx += p->fix.line_length*8; - } - } else { - int right, r; - void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst, - int dst_idx, unsigned long pat, int left, - int right, unsigned n, int bits) = NULL; -#ifdef __LITTLE_ENDIAN - right = left; - left = bpp - right; -#else - right = bpp - left; -#endif - switch (rect->rop) { - case ROP_XOR: - fill_op = bitfill_unaligned_rev; - break; - case ROP_COPY: - fill_op = bitfill_unaligned; - break; - default: - printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n"); - fill_op = bitfill_unaligned; - break; - } - while (height--) { - dst += dst_idx / bits; - dst_idx &= (bits - 1); - r = dst_idx % bpp; - /* rotate pattern to the correct start position */ - pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); - fill_op(p, dst, dst_idx, pat2, left, right, - width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } + fb_fillrect(p, rect); } - EXPORT_SYMBOL(cfb_fillrect); -MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); -MODULE_DESCRIPTION("Generic software accelerated fill rectangle"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("I/O memory packed pixel framebuffer area fill"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c index 7d1d2f1a627d..bcec4e32c0e7 100644 --- a/drivers/video/fbdev/core/cfbimgblt.c +++ b/drivers/video/fbdev/core/cfbimgblt.c @@ -1,369 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic BitBLT function for frame buffer with packed pixels of any depth. - * - * Copyright (C) June 1999 James Simmons - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * NOTES: - * - * This function copys a image from system memory to video memory. The - * image can be a bitmap where each 0 represents the background color and - * each 1 represents the foreground color. Great for font handling. It can - * also be a color image. This is determined by image_depth. The color image - * must be laid out exactly in the same format as the framebuffer. Yes I know - * their are cards with hardware that coverts images of various depths to the - * framebuffer depth. But not every card has this. All images must be rounded - * up to the nearest byte. For example a bitmap 12 bits wide must be two - * bytes width. - * - * Tony: - * Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds - * up the code significantly. - * - * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is - * still processed a bit at a time. - * - * Also need to add code to deal with cards endians that are different than - * the native cpu endians. I also need to deal with MSB position in the word. + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ #include <linux/module.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#include "fb_draw.h" -#define DEBUG - -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args) -#else -#define DPRINTK(fmt, args...) +#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE #endif -static const u32 cfb_tab8_be[] = { - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -}; - -static const u32 cfb_tab8_le[] = { - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -}; - -static const u32 cfb_tab16_be[] = { - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -}; - -static const u32 cfb_tab16_le[] = { - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -}; - -static const u32 cfb_tab32[] = { - 0x00000000, 0xffffffff -}; - -#define FB_WRITEL fb_writel -#define FB_READL fb_readl - -static inline void color_imageblit(const struct fb_image *image, - struct fb_info *p, u8 __iomem *dst1, - u32 start_index, - u32 pitch_index) -{ - /* Draw the penguin */ - u32 __iomem *dst, *dst2; - u32 color = 0, val, shift; - int i, n, bpp = p->var.bits_per_pixel; - u32 null_bits = 32 - bpp; - u32 *palette = (u32 *) p->pseudo_palette; - const u8 *src = image->data; - u32 bswapmask = fb_compute_bswapmask(p); - - dst2 = (u32 __iomem *) dst1; - for (i = image->height; i--; ) { - n = image->width; - dst = (u32 __iomem *) dst1; - shift = 0; - val = 0; - - if (start_index) { - u32 start_mask = ~fb_shifted_pixels_mask_u32(p, - start_index, bswapmask); - val = FB_READL(dst) & start_mask; - shift = start_index; - } - while (n--) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - color = palette[*src]; - else - color = *src; - color <<= FB_LEFT_POS(p, bpp); - val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); - if (shift >= null_bits) { - FB_WRITEL(val, dst++); - - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - src++; - } - if (shift) { - u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, - bswapmask); - - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); - } - dst1 += p->fix.line_length; - if (pitch_index) { - dst2 += p->fix.line_length; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); - - start_index += pitch_index; - start_index &= 32 - 1; - } - } -} - -static inline void slow_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, - u32 bgcolor, - u32 start_index, - u32 pitch_index) -{ - u32 shift, color = 0, bpp = p->var.bits_per_pixel; - u32 __iomem *dst, *dst2; - u32 val, pitch = p->fix.line_length; - u32 null_bits = 32 - bpp; - u32 spitch = (image->width+7)/8; - const u8 *src = image->data, *s; - u32 i, j, l; - u32 bswapmask = fb_compute_bswapmask(p); - - dst2 = (u32 __iomem *) dst1; - fgcolor <<= FB_LEFT_POS(p, bpp); - bgcolor <<= FB_LEFT_POS(p, bpp); - - for (i = image->height; i--; ) { - shift = val = 0; - l = 8; - j = image->width; - dst = (u32 __iomem *) dst1; - s = src; - - /* write leading bits */ - if (start_index) { - u32 start_mask = ~fb_shifted_pixels_mask_u32(p, - start_index, bswapmask); - val = FB_READL(dst) & start_mask; - shift = start_index; - } - - while (j--) { - l--; - color = (*s & (1 << l)) ? fgcolor : bgcolor; - val |= FB_SHIFT_HIGH(p, color, shift ^ bswapmask); - - /* Did the bitshift spill bits to the next long? */ - if (shift >= null_bits) { - FB_WRITEL(val, dst++); - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - if (!l) { l = 8; s++; } - } - - /* write trailing bits */ - if (shift) { - u32 end_mask = fb_shifted_pixels_mask_u32(p, shift, - bswapmask); - - FB_WRITEL((FB_READL(dst) & end_mask) | val, dst); - } - - dst1 += pitch; - src += spitch; - if (pitch_index) { - dst2 += pitch; - dst1 = (u8 __iomem *)((long __force)dst2 & ~(sizeof(u32) - 1)); - start_index += pitch_index; - start_index &= 32 - 1; - } - - } -} - -/* - * fast_imageblit - optimized monochrome color expansion - * - * Only if: bits_per_pixel == 8, 16, or 32 - * image->width is divisible by pixel/dword (ppw); - * fix->line_legth is divisible by 4; - * beginning and end of a scanline is dword aligned - */ -static inline void fast_imageblit(const struct fb_image *image, struct fb_info *p, - u8 __iomem *dst1, u32 fgcolor, - u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; - u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx, shift; - const char *s = image->data, *src; - u32 __iomem *dst; - const u32 *tab = NULL; - size_t tablen; - u32 colortab[16]; - int i, j, k; - - switch (bpp) { - case 8: - tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; - tablen = 16; - break; - case 16: - tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; - tablen = 4; - break; - case 32: - tab = cfb_tab32; - tablen = 2; - break; - default: - return; - } - - for (i = ppw-1; i--; ) { - fgx <<= bpp; - bgx <<= bpp; - fgx |= fgcolor; - bgx |= bgcolor; - } - - bit_mask = (1 << ppw) - 1; - eorx = fgx ^ bgx; - k = image->width/ppw; - - for (i = 0; i < tablen; ++i) - colortab[i] = (tab[i] & eorx) ^ bgx; - - for (i = image->height; i--; ) { - dst = (u32 __iomem *)dst1; - shift = 8; - src = s; - - /* - * Manually unroll the per-line copying loop for better - * performance. This works until we processed the last - * completely filled source byte (inclusive). - */ - switch (ppw) { - case 4: /* 8 bpp */ - for (j = k; j >= 2; j -= 2, ++src) { - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - case 2: /* 16 bpp */ - for (j = k; j >= 4; j -= 4, ++src) { - FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - case 1: /* 32 bpp */ - for (j = k; j >= 8; j -= 8, ++src) { - FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 3) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 1) & bit_mask], dst++); - FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); - } - break; - } - - /* - * For image widths that are not a multiple of 8, there - * are trailing pixels left on the current line. Print - * them as well. - */ - for (; j--; ) { - shift -= ppw; - FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++); - if (!shift) { - shift = 8; - ++src; - } - } - - dst1 += p->fix.line_length; - s += spitch; - } -} +#include "cfbmem.h" +#include "fb_imageblit.h" void cfb_imageblit(struct fb_info *p, const struct fb_image *image) { - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; - u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width; - u32 dx = image->dx, dy = image->dy; - u8 __iomem *dst1; - if (p->state != FBINFO_STATE_RUNNING) return; if (p->flags & FBINFO_VIRTFB) - fb_warn_once(p, "Framebuffer is not in I/O address space."); - - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); - start_index = bitstart & (32 - 1); - pitch_index = (p->fix.line_length & (bpl - 1)) * 8; - - bitstart /= 8; - bitstart &= ~(bpl - 1); - dst1 = p->screen_base + bitstart; + fb_warn_once(p, "%s: framebuffer is not in I/O address space.\n", __func__); if (p->fbops->fb_sync) p->fbops->fb_sync(p); - if (image->depth == 1) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; - bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; - } else { - fgcolor = image->fg_color; - bgcolor = image->bg_color; - } - - if (32 % bpp == 0 && !start_index && !pitch_index && - ((width & (32/bpp-1)) == 0) && - bpp >= 8 && bpp <= 32) - fast_imageblit(image, p, dst1, fgcolor, bgcolor); - else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - color_imageblit(image, p, dst1, start_index, pitch_index); + fb_imageblit(p, image); } - EXPORT_SYMBOL(cfb_imageblit); -MODULE_AUTHOR("James Simmons <jsimmons@users.sf.net>"); -MODULE_DESCRIPTION("Generic software accelerated imaging drawing"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("I/O memory packed pixel framebuffer image draw"); MODULE_LICENSE("GPL"); - diff --git a/drivers/video/fbdev/core/cfbmem.h b/drivers/video/fbdev/core/cfbmem.h new file mode 100644 index 000000000000..ce2f5f751ea1 --- /dev/null +++ b/drivers/video/fbdev/core/cfbmem.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * I/O memory framebuffer access for drawing routines + * + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + */ + +/* keeps track of a bit address in framebuffer memory */ +struct fb_address { + void __iomem *address; + int bits; +}; + +/* initialize the bit address pointer to the beginning of the frame buffer */ +static inline struct fb_address fb_address_init(struct fb_info *p) +{ + void __iomem *base = p->screen_base; + struct fb_address ptr; + + ptr.address = PTR_ALIGN_DOWN(base, BITS_PER_LONG / BITS_PER_BYTE); + ptr.bits = (base - ptr.address) * BITS_PER_BYTE; + return ptr; +} + +/* framebuffer write access */ +static inline void fb_write_offset(unsigned long val, int offset, const struct fb_address *dst) +{ +#if BITS_PER_LONG == 32 + fb_writel(val, dst->address + offset * (BITS_PER_LONG / BITS_PER_BYTE)); +#else + fb_writeq(val, dst->address + offset * (BITS_PER_LONG / BITS_PER_BYTE)); +#endif +} + +/* framebuffer read access */ +static inline unsigned long fb_read_offset(int offset, const struct fb_address *src) +{ +#if BITS_PER_LONG == 32 + return fb_readl(src->address + offset * (BITS_PER_LONG / BITS_PER_BYTE)); +#else + return fb_readq(src->address + offset * (BITS_PER_LONG / BITS_PER_BYTE)); +#endif +} diff --git a/drivers/video/fbdev/core/fb_backlight.c b/drivers/video/fbdev/core/fb_backlight.c index e2d3b3adc870..6fdaa9f81be9 100644 --- a/drivers/video/fbdev/core/fb_backlight.c +++ b/drivers/video/fbdev/core/fb_backlight.c @@ -30,4 +30,10 @@ void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max) mutex_unlock(&fb_info->bl_curve_mutex); } EXPORT_SYMBOL_GPL(fb_bl_default_curve); + +struct backlight_device *fb_bl_device(struct fb_info *info) +{ + return info->bl_dev; +} +EXPORT_SYMBOL(fb_bl_device); #endif diff --git a/drivers/video/fbdev/core/fb_copyarea.h b/drivers/video/fbdev/core/fb_copyarea.h new file mode 100644 index 000000000000..53f1d5385c6e --- /dev/null +++ b/drivers/video/fbdev/core/fb_copyarea.h @@ -0,0 +1,405 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Generic bit area copy and twister engine for packed pixel framebuffers + * + * Rewritten by: + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + * + * Based on previous work of: + * Copyright (C) 1999-2005 James Simmons <jsimmons@www.infradead.org> + * Anton Vorontsov <avorontsov@ru.mvista.com> + * Pavel Pisa <pisa@cmp.felk.cvut.cz> + * Antonino Daplas <adaplas@hotpop.com> + * Geert Uytterhoeven + * and others + * + * NOTES: + * + * Handles native and foreign byte order on both endians, standard and + * reverse pixel order in a byte (<8 BPP), word length of 32/64 bits, + * bits per pixel from 1 to the word length. Handles line lengths at byte + * granularity while maintaining aligned accesses. + * + * Optimized routines for word aligned copying and byte aligned copying + * on reverse pixel framebuffers. + */ +#include "fb_draw.h" + +/* used when no reversing is necessary */ +static inline unsigned long fb_no_reverse(unsigned long val, struct fb_reverse reverse) +{ + return val; +} + +/* modifies the masked area in a word */ +static inline void fb_copy_offset_masked(unsigned long mask, int offset, + const struct fb_address *dst, + const struct fb_address *src) +{ + fb_modify_offset(fb_read_offset(offset, src), mask, offset, dst); +} + +/* copies the whole word */ +static inline void fb_copy_offset(int offset, const struct fb_address *dst, + const struct fb_address *src) +{ + fb_write_offset(fb_read_offset(offset, src), offset, dst); +} + +/* forward aligned copy */ +static inline void fb_copy_aligned_fwd(const struct fb_address *dst, + const struct fb_address *src, + int end, struct fb_reverse reverse) +{ + unsigned long first, last; + + first = fb_pixel_mask(dst->bits, reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), reverse); + + /* Same alignment for source and dest */ + if (end <= BITS_PER_LONG) { + /* Single word */ + last = last ? (last & first) : first; + + /* Trailing bits */ + if (last == ~0UL) + fb_copy_offset(0, dst, src); + else + fb_copy_offset_masked(last, 0, dst, src); + } else { + /* Multiple destination words */ + int offset = first != ~0UL; + + /* Leading bits */ + if (offset) + fb_copy_offset_masked(first, 0, dst, src); + + /* Main chunk */ + end /= BITS_PER_LONG; + while (offset + 4 <= end) { + fb_copy_offset(offset + 0, dst, src); + fb_copy_offset(offset + 1, dst, src); + fb_copy_offset(offset + 2, dst, src); + fb_copy_offset(offset + 3, dst, src); + offset += 4; + } + while (offset < end) + fb_copy_offset(offset++, dst, src); + + /* Trailing bits */ + if (last) + fb_copy_offset_masked(last, offset, dst, src); + } +} + +/* reverse aligned copy */ +static inline void fb_copy_aligned_rev(const struct fb_address *dst, + const struct fb_address *src, + int end, struct fb_reverse reverse) +{ + unsigned long first, last; + + first = fb_pixel_mask(dst->bits, reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), reverse); + + if (end <= BITS_PER_LONG) { + /* Single word */ + if (last) + first &= last; + if (first == ~0UL) + fb_copy_offset(0, dst, src); + else + fb_copy_offset_masked(first, 0, dst, src); + } else { + /* Multiple destination words */ + int offset = first != ~0UL; + + /* Trailing bits */ + end /= BITS_PER_LONG; + + if (last) + fb_copy_offset_masked(last, end, dst, src); + + /* Main chunk */ + while (end >= offset + 4) { + fb_copy_offset(end - 1, dst, src); + fb_copy_offset(end - 2, dst, src); + fb_copy_offset(end - 3, dst, src); + fb_copy_offset(end - 4, dst, src); + end -= 4; + } + while (end > offset) + fb_copy_offset(--end, dst, src); + + /* Leading bits */ + if (offset) + fb_copy_offset_masked(first, 0, dst, src); + } +} + +static inline void fb_copy_aligned(struct fb_address *dst, struct fb_address *src, + int width, u32 height, unsigned int bits_per_line, + struct fb_reverse reverse, bool rev_copy) +{ + if (rev_copy) + while (height--) { + fb_copy_aligned_rev(dst, src, width + dst->bits, reverse); + fb_address_backward(dst, bits_per_line); + fb_address_backward(src, bits_per_line); + } + else + while (height--) { + fb_copy_aligned_fwd(dst, src, width + dst->bits, reverse); + fb_address_forward(dst, bits_per_line); + fb_address_forward(src, bits_per_line); + } +} + +static __always_inline void fb_copy_fwd(const struct fb_address *dst, + const struct fb_address *src, int width, + unsigned long (*reorder)(unsigned long val, + struct fb_reverse reverse), + struct fb_reverse reverse) +{ + unsigned long first, last; + unsigned long d0, d1; + int end = dst->bits + width; + int shift, left, right; + + first = fb_pixel_mask(dst->bits, reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), reverse); + + shift = dst->bits - src->bits; + right = shift & (BITS_PER_LONG - 1); + left = -shift & (BITS_PER_LONG - 1); + + if (end <= BITS_PER_LONG) { + /* Single destination word */ + last = last ? (last & first) : first; + if (shift < 0) { + d0 = fb_left(reorder(fb_read_offset(-1, src), reverse), left); + if (src->bits + width > BITS_PER_LONG) + d0 |= fb_right(reorder(fb_read_offset(0, src), reverse), right); + + if (last == ~0UL) + fb_write_offset(reorder(d0, reverse), 0, dst); + else + fb_modify_offset(reorder(d0, reverse), last, 0, dst); + } else { + d0 = fb_right(reorder(fb_read_offset(0, src), reverse), right); + fb_modify_offset(reorder(d0, reverse), last, 0, dst); + } + } else { + /* Multiple destination words */ + int offset = first != ~0UL; + + /* Leading bits */ + if (shift < 0) + d0 = reorder(fb_read_offset(-1, src), reverse); + else + d0 = 0; + + /* 2 source words */ + if (offset) { + d1 = reorder(fb_read_offset(0, src), reverse); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_modify_offset(reorder(d0, reverse), first, 0, dst); + d0 = d1; + } + + /* Main chunk */ + end /= BITS_PER_LONG; + if (reorder == fb_no_reverse) + while (offset + 4 <= end) { + d1 = fb_read_offset(offset + 0, src); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_write_offset(d0, offset + 0, dst); + d0 = d1; + d1 = fb_read_offset(offset + 1, src); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_write_offset(d0, offset + 1, dst); + d0 = d1; + d1 = fb_read_offset(offset + 2, src); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_write_offset(d0, offset + 2, dst); + d0 = d1; + d1 = fb_read_offset(offset + 3, src); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_write_offset(d0, offset + 3, dst); + d0 = d1; + offset += 4; + } + + while (offset < end) { + d1 = reorder(fb_read_offset(offset, src), reverse); + d0 = fb_left(d0, left) | fb_right(d1, right); + fb_write_offset(reorder(d0, reverse), offset, dst); + d0 = d1; + offset++; + } + + /* Trailing bits */ + if (last) { + d0 = fb_left(d0, left); + if (src->bits + width + > offset * BITS_PER_LONG + ((shift < 0) ? BITS_PER_LONG : 0)) + d0 |= fb_right(reorder(fb_read_offset(offset, src), reverse), + right); + fb_modify_offset(reorder(d0, reverse), last, offset, dst); + } + } +} + +static __always_inline void fb_copy_rev(const struct fb_address *dst, + const struct fb_address *src, int end, + unsigned long (*reorder)(unsigned long val, + struct fb_reverse reverse), + struct fb_reverse reverse) +{ + unsigned long first, last; + unsigned long d0, d1; + int shift, left, right; + + first = fb_pixel_mask(dst->bits, reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), reverse); + + shift = dst->bits - src->bits; + right = shift & (BITS_PER_LONG-1); + left = -shift & (BITS_PER_LONG-1); + + if (end <= BITS_PER_LONG) { + /* Single destination word */ + if (last) + first &= last; + + if (shift > 0) { + d0 = fb_right(reorder(fb_read_offset(1, src), reverse), right); + if (src->bits > left) + d0 |= fb_left(reorder(fb_read_offset(0, src), reverse), left); + fb_modify_offset(reorder(d0, reverse), first, 0, dst); + } else { + d0 = fb_left(reorder(fb_read_offset(0, src), reverse), left); + if (src->bits + end - dst->bits > BITS_PER_LONG) + d0 |= fb_right(reorder(fb_read_offset(1, src), reverse), right); + if (first == ~0UL) + fb_write_offset(reorder(d0, reverse), 0, dst); + else + fb_modify_offset(reorder(d0, reverse), first, 0, dst); + } + } else { + /* Multiple destination words */ + int offset = first != ~0UL; + + end /= BITS_PER_LONG; + + /* 2 source words */ + if (fb_right(~0UL, right) & last) + d0 = fb_right(reorder(fb_read_offset(end + 1, src), reverse), right); + else + d0 = 0; + + /* Trailing bits */ + d1 = reorder(fb_read_offset(end, src), reverse); + if (last) + fb_modify_offset(reorder(fb_left(d1, left) | d0, reverse), + last, end, dst); + d0 = d1; + + /* Main chunk */ + if (reorder == fb_no_reverse) + while (end >= offset + 4) { + d1 = fb_read_offset(end - 1, src); + d0 = fb_left(d1, left) | fb_right(d0, right); + fb_write_offset(d0, end - 1, dst); + d0 = d1; + d1 = fb_read_offset(end - 2, src); + d0 = fb_left(d1, left) | fb_right(d0, right); + fb_write_offset(d0, end - 2, dst); + d0 = d1; + d1 = fb_read_offset(end - 3, src); + d0 = fb_left(d1, left) | fb_right(d0, right); + fb_write_offset(d0, end - 3, dst); + d0 = d1; + d1 = fb_read_offset(end - 4, src); + d0 = fb_left(d1, left) | fb_right(d0, right); + fb_write_offset(d0, end - 4, dst); + d0 = d1; + end -= 4; + } + + while (end > offset) { + end--; + d1 = reorder(fb_read_offset(end, src), reverse); + d0 = fb_left(d1, left) | fb_right(d0, right); + fb_write_offset(reorder(d0, reverse), end, dst); + d0 = d1; + } + + /* Leading bits */ + if (offset) { + d0 = fb_right(d0, right); + if (src->bits > left) + d0 |= fb_left(reorder(fb_read_offset(0, src), reverse), left); + fb_modify_offset(reorder(d0, reverse), first, 0, dst); + } + } +} + +static __always_inline void fb_copy(struct fb_address *dst, struct fb_address *src, + int width, u32 height, unsigned int bits_per_line, + unsigned long (*reorder)(unsigned long val, + struct fb_reverse reverse), + struct fb_reverse reverse, bool rev_copy) +{ + if (rev_copy) + while (height--) { + int move = src->bits < dst->bits ? -1 : 0; + + fb_address_move_long(src, move); + fb_copy_rev(dst, src, width + dst->bits, reorder, reverse); + fb_address_backward(dst, bits_per_line); + fb_address_backward(src, bits_per_line); + fb_address_move_long(src, -move); + } + else + while (height--) { + int move = src->bits > dst->bits ? 1 : 0; + + fb_address_move_long(src, move); + fb_copy_fwd(dst, src, width, reorder, reverse); + fb_address_forward(dst, bits_per_line); + fb_address_forward(src, bits_per_line); + fb_address_move_long(src, -move); + } +} + +static inline void fb_copyarea(struct fb_info *p, const struct fb_copyarea *area) +{ + int bpp = p->var.bits_per_pixel; + u32 dy = area->dy; + u32 sy = area->sy; + u32 height = area->height; + int width = area->width * bpp; + unsigned int bits_per_line = BYTES_TO_BITS(p->fix.line_length); + struct fb_reverse reverse = fb_reverse_init(p); + struct fb_address dst = fb_address_init(p); + struct fb_address src = dst; + bool rev_copy = (dy > sy) || (dy == sy && area->dx > area->sx); + + if (rev_copy) { + dy += height - 1; + sy += height - 1; + } + fb_address_forward(&dst, dy*bits_per_line + area->dx*bpp); + fb_address_forward(&src, sy*bits_per_line + area->sx*bpp); + + if (src.bits == dst.bits) + fb_copy_aligned(&dst, &src, width, height, bits_per_line, reverse, rev_copy); + else if (!reverse.byte && (!reverse.pixel || + !((src.bits ^ dst.bits) & (BITS_PER_BYTE-1)))) { + fb_copy(&dst, &src, width, height, bits_per_line, + fb_no_reverse, reverse, rev_copy); + } else + fb_copy(&dst, &src, width, height, bits_per_line, + fb_reverse_long, reverse, rev_copy); +} diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 806ecd32219b..4fc93f253e06 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -23,33 +23,63 @@ #include <linux/rmap.h> #include <linux/pagemap.h> -static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs) +static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs) { - void *screen_base = (void __force *) info->screen_base; - struct page *page; + struct fb_deferred_io *fbdefio = info->fbdefio; + const void *screen_buffer = info->screen_buffer; + struct page *page = NULL; + + if (fbdefio->get_page) + return fbdefio->get_page(info, offs); - if (is_vmalloc_addr(screen_base + offs)) - page = vmalloc_to_page(screen_base + offs); - else + if (is_vmalloc_addr(screen_buffer + offs)) + page = vmalloc_to_page(screen_buffer + offs); + else if (info->fix.smem_start) page = pfn_to_page((info->fix.smem_start + offs) >> PAGE_SHIFT); + if (page) + get_page(page); + return page; } +static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info, + unsigned long offset, + struct page *page) +{ + unsigned long pgoff = offset >> PAGE_SHIFT; + struct fb_deferred_io_pageref *pageref; + + if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs)) + return NULL; /* incorrect allocation size */ + + /* 1:1 mapping between pageref and page offset */ + pageref = &info->pagerefs[pgoff]; + + if (pageref->page) + goto out; + + pageref->page = page; + pageref->offset = pgoff << PAGE_SHIFT; + INIT_LIST_HEAD(&pageref->list); + +out: + if (fb_WARN_ON_ONCE(info, pageref->page != page)) + return NULL; /* inconsistent state */ + return pageref; +} + static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info *info, unsigned long offset, struct page *page) { struct fb_deferred_io *fbdefio = info->fbdefio; struct list_head *pos = &fbdefio->pagereflist; - unsigned long pgoff = offset >> PAGE_SHIFT; struct fb_deferred_io_pageref *pageref, *cur; - if (WARN_ON_ONCE(pgoff >= info->npagerefs)) - return NULL; /* incorrect allocation size */ - - /* 1:1 mapping between pageref and page offset */ - pageref = &info->pagerefs[pgoff]; + pageref = fb_deferred_io_pageref_lookup(info, offset, page); + if (!pageref) + return NULL; /* * This check is to catch the case where a new process could start @@ -60,9 +90,6 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info if (!list_empty(&pageref->list)) goto pageref_already_added; - pageref->page = page; - pageref->offset = pgoff << PAGE_SHIFT; - if (unlikely(fbdefio->sort_pagereflist)) { /* * We loop through the list of pagerefs before adding in @@ -101,19 +128,14 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf) if (offset >= info->fix.smem_len) return VM_FAULT_SIGBUS; - page = fb_deferred_io_page(info, offset); + page = fb_deferred_io_get_page(info, offset); if (!page) return VM_FAULT_SIGBUS; - get_page(page); + if (!vmf->vma->vm_file) + fb_err(info, "no mapping available\n"); - if (vmf->vma->vm_file) - page->mapping = vmf->vma->vm_file->f_mapping; - else - printk(KERN_ERR "no mapping available\n"); - - BUG_ON(!page->mapping); - page->index = vmf->pgoff; /* for page_mkclean() */ + BUG_ON(!info->fbdefio->mapping); vmf->page = page; return 0; @@ -161,9 +183,9 @@ static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long /* * We want the page to remain locked from ->page_mkwrite until - * the PTE is marked dirty to avoid page_mkclean() being called - * before the PTE is updated, which would leave the page ignored - * by defio. + * the PTE is marked dirty to avoid mapping_wrprotect_range() + * being called before the PTE is updated, which would leave + * the page ignored by defio. * Do this by locking the page here and informing the caller * about it with VM_FAULT_LOCKED. */ @@ -241,14 +263,17 @@ static void fb_deferred_io_work(struct work_struct *work) struct fb_deferred_io_pageref *pageref, *next; struct fb_deferred_io *fbdefio = info->fbdefio; - /* here we mkclean the pages, then do all deferred IO */ + /* here we wrprotect the page's mappings, then do all deferred IO. */ mutex_lock(&fbdefio->lock); +#ifdef CONFIG_MMU list_for_each_entry(pageref, &fbdefio->pagereflist, list) { - struct page *cur = pageref->page; - lock_page(cur); - page_mkclean(cur); - unlock_page(cur); + struct page *page = pageref->page; + pgoff_t pgoff = pageref->offset >> PAGE_SHIFT; + + mapping_wrprotect_range(fbdefio->mapping, pgoff, + page_to_pfn(page), 1); } +#endif /* driver's callback with pagereflist */ fbdefio->deferred_io(info, &fbdefio->pagereflist); @@ -264,7 +289,7 @@ int fb_deferred_io_init(struct fb_info *info) { struct fb_deferred_io *fbdefio = info->fbdefio; struct fb_deferred_io_pageref *pagerefs; - unsigned long npagerefs, i; + unsigned long npagerefs; int ret; BUG_ON(!fbdefio); @@ -286,8 +311,6 @@ int fb_deferred_io_init(struct fb_info *info) ret = -ENOMEM; goto err; } - for (i = 0; i < npagerefs; ++i) - INIT_LIST_HEAD(&pagerefs[i].list); info->npagerefs = npagerefs; info->pagerefs = pagerefs; @@ -305,6 +328,7 @@ void fb_deferred_io_open(struct fb_info *info, { struct fb_deferred_io *fbdefio = info->fbdefio; + fbdefio->mapping = file->f_mapping; file->f_mapping->a_ops = &fb_deferred_io_aops; fbdefio->open_count++; } @@ -312,16 +336,7 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_open); static void fb_deferred_io_lastclose(struct fb_info *info) { - struct page *page; - int i; - flush_delayed_work(&info->deferred_work); - - /* clear out the mapping that we setup */ - for (i = 0 ; i < info->fix.smem_len; i += PAGE_SIZE) { - page = fb_deferred_io_page(info, i); - page->mapping = NULL; - } } void fb_deferred_io_release(struct fb_info *info) @@ -341,5 +356,6 @@ void fb_deferred_io_cleanup(struct fb_info *info) kvfree(info->pagerefs); mutex_destroy(&fbdefio->lock); + fbdefio->mapping = NULL; } EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup); diff --git a/drivers/video/fbdev/core/fb_draw.h b/drivers/video/fbdev/core/fb_draw.h index e0d829873930..8eb13f7b3972 100644 --- a/drivers/video/fbdev/core/fb_draw.h +++ b/drivers/video/fbdev/core/fb_draw.h @@ -1,187 +1,163 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0 + * + * Various common functions used by the framebuffer drawing code + * + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + */ #ifndef _FB_DRAW_H #define _FB_DRAW_H -#include <asm/types.h> -#include <linux/fb.h> -#include <linux/bug.h> +/* swap bytes in a long, independent of word size */ +#define swab_long _swab_long(BITS_PER_LONG) +#define _swab_long(x) __swab_long(x) +#define __swab_long(x) swab##x - /* - * Compose two values, using a bitmask as decision value - * This is equivalent to (a & mask) | (b & ~mask) - */ - -static inline unsigned long -comp(unsigned long a, unsigned long b, unsigned long mask) +/* move the address pointer by the number of words */ +static inline void fb_address_move_long(struct fb_address *adr, int offset) { - return ((a ^ b) & mask) ^ b; + adr->address += offset * (BITS_PER_LONG / BITS_PER_BYTE); } - /* - * Create a pattern with the given pixel's color - */ +/* move the address pointer forward with the number of bits */ +static inline void fb_address_forward(struct fb_address *adr, unsigned int offset) +{ + unsigned int bits = (unsigned int)adr->bits + offset; + + adr->bits = bits & (BITS_PER_LONG - 1u); + adr->address += (bits & ~(BITS_PER_LONG - 1u)) / BITS_PER_BYTE; +} -#if BITS_PER_LONG == 64 -static inline unsigned long -pixel_to_pat( u32 bpp, u32 pixel) +/* move the address pointer backwards with the number of bits */ +static inline void fb_address_backward(struct fb_address *adr, unsigned int offset) { - switch (bpp) { - case 1: - return 0xfffffffffffffffful*pixel; - case 2: - return 0x5555555555555555ul*pixel; - case 4: - return 0x1111111111111111ul*pixel; - case 8: - return 0x0101010101010101ul*pixel; - case 12: - return 0x1001001001001001ul*pixel; - case 16: - return 0x0001000100010001ul*pixel; - case 24: - return 0x0001000001000001ul*pixel; - case 32: - return 0x0000000100000001ul*pixel; - default: - WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp); - return 0; - } + int bits = adr->bits - (int)offset; + + adr->bits = bits & (BITS_PER_LONG - 1); + if (bits < 0) + adr->address -= (adr->bits - bits) / BITS_PER_BYTE; + else + adr->address += (bits - adr->bits) / BITS_PER_BYTE; } -#else -static inline unsigned long -pixel_to_pat( u32 bpp, u32 pixel) + +/* compose pixels based on mask */ +static inline unsigned long fb_comp(unsigned long set, unsigned long unset, unsigned long mask) { - switch (bpp) { - case 1: - return 0xfffffffful*pixel; - case 2: - return 0x55555555ul*pixel; - case 4: - return 0x11111111ul*pixel; - case 8: - return 0x01010101ul*pixel; - case 12: - return 0x01001001ul*pixel; - case 16: - return 0x00010001ul*pixel; - case 24: - return 0x01000001ul*pixel; - case 32: - return 0x00000001ul*pixel; - default: - WARN(1, "pixel_to_pat(): unsupported pixelformat %d\n", bpp); - return 0; - } + return ((set ^ unset) & mask) ^ unset; } -#endif -#ifdef CONFIG_FB_CFB_REV_PIXELS_IN_BYTE -#if BITS_PER_LONG == 64 -#define REV_PIXELS_MASK1 0x5555555555555555ul -#define REV_PIXELS_MASK2 0x3333333333333333ul -#define REV_PIXELS_MASK4 0x0f0f0f0f0f0f0f0ful -#else -#define REV_PIXELS_MASK1 0x55555555ul -#define REV_PIXELS_MASK2 0x33333333ul -#define REV_PIXELS_MASK4 0x0f0f0f0ful -#endif +/* framebuffer read-modify-write access for replacing bits in the mask */ +static inline void fb_modify_offset(unsigned long val, unsigned long mask, + int offset, const struct fb_address *dst) +{ + fb_write_offset(fb_comp(val, fb_read_offset(offset, dst), mask), offset, dst); +} -static inline unsigned long fb_rev_pixels_in_long(unsigned long val, - u32 bswapmask) +/* + * get current palette, if applicable for visual + * + * The pseudo color table entries (and colors) are right justified and in the + * same byte order as it's expected to be placed into a native ordered + * framebuffer memory. What that means: + * + * Expected bytes in framebuffer memory (in native order): + * RR GG BB RR GG BB RR GG BB ... + * + * Pseudo palette entry on little endian arch: + * RR | GG << 8 | BB << 16 + * + * Pseudo palette entry on a big endian arch: + * RR << 16 | GG << 8 | BB + */ +static inline const u32 *fb_palette(struct fb_info *info) { - if (bswapmask & 1) - val = comp(val >> 1, val << 1, REV_PIXELS_MASK1); - if (bswapmask & 2) - val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); - if (bswapmask & 3) - val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); - return val; + return (info->fix.visual == FB_VISUAL_TRUECOLOR || + info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? info->pseudo_palette : NULL; } -static inline u32 fb_shifted_pixels_mask_u32(struct fb_info *p, u32 index, - u32 bswapmask) +/* move pixels right on screen when framebuffer is in native order */ +static inline unsigned long fb_right(unsigned long value, int index) { - u32 mask; - - if (!bswapmask) { - mask = FB_SHIFT_HIGH(p, ~(u32)0, index); - } else { - mask = 0xff << FB_LEFT_POS(p, 8); - mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask; - mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask)); -#if defined(__i386__) || defined(__x86_64__) - /* Shift argument is limited to 0 - 31 on x86 based CPU's */ - if(index + bswapmask < 32) +#ifdef __LITTLE_ENDIAN + return value << index; +#else + return value >> index; #endif - mask |= FB_SHIFT_HIGH(p, ~(u32)0, - (index + bswapmask) & ~(bswapmask)); - } - return mask; } -static inline unsigned long fb_shifted_pixels_mask_long(struct fb_info *p, - u32 index, - u32 bswapmask) +/* move pixels left on screen when framebuffer is in native order */ +static inline unsigned long fb_left(unsigned long value, int index) { - unsigned long mask; - - if (!bswapmask) { - mask = FB_SHIFT_HIGH(p, ~0UL, index); - } else { - mask = 0xff << FB_LEFT_POS(p, 8); - mask = FB_SHIFT_LOW(p, mask, index & (bswapmask)) & mask; - mask = FB_SHIFT_HIGH(p, mask, index & ~(bswapmask)); -#if defined(__i386__) || defined(__x86_64__) - /* Shift argument is limited to 0 - 31 on x86 based CPU's */ - if(index + bswapmask < BITS_PER_LONG) +#ifdef __LITTLE_ENDIAN + return value >> index; +#else + return value << index; #endif - mask |= FB_SHIFT_HIGH(p, ~0UL, - (index + bswapmask) & ~(bswapmask)); - } - return mask; } +/* reversal options */ +struct fb_reverse { + bool byte, pixel; +}; -static inline u32 fb_compute_bswapmask(struct fb_info *info) +/* reverse bits of each byte in a long */ +static inline unsigned long fb_reverse_bits_long(unsigned long val) { - u32 bswapmask = 0; - unsigned bpp = info->var.bits_per_pixel; - - if ((bpp < 8) && (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B)) { - /* - * Reversed order of pixel layout in bytes - * works only for 1, 2 and 4 bpp - */ - bswapmask = 7 - bpp + 1; - } - return bswapmask; +#if defined(CONFIG_HAVE_ARCH_BITREVERSE) && BITS_PER_LONG == 32 + return bitrev8x4(val); +#else + val = fb_comp(val >> 1, val << 1, ~0UL / 3); + val = fb_comp(val >> 2, val << 2, ~0UL / 5); + return fb_comp(val >> 4, val << 4, ~0UL / 17); +#endif } -#else /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ - -static inline unsigned long fb_rev_pixels_in_long(unsigned long val, - u32 bswapmask) +/* apply byte and bit reversals as necessary */ +static inline unsigned long fb_reverse_long(unsigned long val, + struct fb_reverse reverse) { - return val; + if (reverse.pixel) + val = fb_reverse_bits_long(val); + return reverse.byte ? swab_long(val) : val; } -#define fb_shifted_pixels_mask_u32(p, i, b) FB_SHIFT_HIGH((p), ~(u32)0, (i)) -#define fb_shifted_pixels_mask_long(p, i, b) FB_SHIFT_HIGH((p), ~0UL, (i)) -#define fb_compute_bswapmask(...) 0 - -#endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */ - -#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG) -#define _cpu_to_le_long(x) __cpu_to_le_long(x) -#define __cpu_to_le_long(x) cpu_to_le##x +/* calculate a pixel mask for the given reversal */ +static inline unsigned long fb_pixel_mask(int index, struct fb_reverse reverse) +{ +#ifdef FB_REV_PIXELS_IN_BYTE + if (reverse.byte) + return reverse.pixel ? fb_left(~0UL, index) : swab_long(fb_right(~0UL, index)); + else + return reverse.pixel ? swab_long(fb_left(~0UL, index)) : fb_right(~0UL, index); +#else + return reverse.byte ? swab_long(fb_right(~0UL, index)) : fb_right(~0UL, index); +#endif +} -#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG) -#define _le_long_to_cpu(x) __le_long_to_cpu(x) -#define __le_long_to_cpu(x) le##x##_to_cpu -static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x) +/* + * initialise reversals based on info + * + * Normally the first byte is the low byte on little endian and in the high + * on big endian. If it's the other way around then that's reverse byte order. + * + * Normally the first pixel is the LSB on little endian and the MSB on big + * endian. If that's not the case that's reverse pixel order. + */ +static inline struct fb_reverse fb_reverse_init(struct fb_info *info) { - return (word << shift) | (word >> (x - shift)); + struct fb_reverse reverse; +#ifdef __LITTLE_ENDIAN + reverse.byte = fb_be_math(info) != 0; +#else + reverse.byte = fb_be_math(info) == 0; +#endif +#ifdef FB_REV_PIXELS_IN_BYTE + reverse.pixel = info->var.bits_per_pixel < BITS_PER_BYTE + && (info->var.nonstd & FB_NONSTD_REV_PIX_IN_B); +#else + reverse.pixel = false; +#endif + return reverse; } #endif /* FB_DRAW_H */ diff --git a/drivers/video/fbdev/core/fb_fillrect.h b/drivers/video/fbdev/core/fb_fillrect.h new file mode 100644 index 000000000000..66042e534de7 --- /dev/null +++ b/drivers/video/fbdev/core/fb_fillrect.h @@ -0,0 +1,280 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Generic bit area filler and twister engine for packed pixel framebuffers + * + * Rewritten by: + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + * + * Based on earlier work of: + * Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org) + * Michal Januszewski <spock@gentoo.org> + * Anton Vorontsov <avorontsov@ru.mvista.com> + * Pavel Pisa <pisa@cmp.felk.cvut.cz> + * Antonino A. Daplas <adaplas@gmail.com> + * Geert Uytterhoeven + * and others + * + * NOTES: + * + * Handles native and foreign byte order on both endians, standard and + * reverse pixel order in a byte (<8 BPP), word length of 32/64 bits, + * bits per pixel from 1 to the word length. Handles line lengths at byte + * granularity while maintaining aligned accesses. + * + * Optimized path for power of two bits per pixel modes. + */ +#include "fb_draw.h" + +/* inverts bits at a given offset */ +static inline void fb_invert_offset(unsigned long pat, int offset, const struct fb_address *dst) +{ + fb_write_offset(fb_read_offset(offset, dst) ^ pat, offset, dst); +} + +/* state for pattern generator and whether swapping is necessary */ +struct fb_pattern { + unsigned long pixels; + int left, right; + struct fb_reverse reverse; +}; + +/* used to get the pattern in native order */ +static unsigned long fb_pattern_get(struct fb_pattern *pattern) +{ + return pattern->pixels; +} + +/* used to get the pattern in reverse order */ +static unsigned long fb_pattern_get_reverse(struct fb_pattern *pattern) +{ + return swab_long(pattern->pixels); +} + +/* next static pattern */ +static void fb_pattern_static(struct fb_pattern *pattern) +{ + /* nothing to do */ +} + +/* next rotating pattern */ +static void fb_pattern_rotate(struct fb_pattern *pattern) +{ + pattern->pixels = fb_left(pattern->pixels, pattern->left) + | fb_right(pattern->pixels, pattern->right); +} + +#define FB_PAT(i) (((1UL<<(BITS_PER_LONG-1)/(i)*(i))/((1<<(i))-1)<<(i))|1) + +/* create the filling pattern from a given color */ +static unsigned long pixel_to_pat(int bpp, u32 color) +{ + static const unsigned long mulconst[BITS_PER_LONG/4] = { + 0, ~0UL, FB_PAT(2), FB_PAT(3), + FB_PAT(4), FB_PAT(5), FB_PAT(6), FB_PAT(7), +#if BITS_PER_LONG == 64 + FB_PAT(8), FB_PAT(9), FB_PAT(10), FB_PAT(11), + FB_PAT(12), FB_PAT(13), FB_PAT(14), FB_PAT(15), +#endif + }; + unsigned long pattern; + + switch (bpp) { + case 0 ... BITS_PER_LONG/4-1: + pattern = mulconst[bpp] * color; + break; + case BITS_PER_LONG/4 ... BITS_PER_LONG/2-1: + pattern = color; + pattern = pattern | pattern << bpp; + pattern = pattern | pattern << bpp*2; + break; + case BITS_PER_LONG/2 ... BITS_PER_LONG-1: + pattern = color; + pattern = pattern | pattern << bpp; + break; + default: + pattern = color; + break; + } +#ifndef __LITTLE_ENDIAN + pattern <<= (BITS_PER_LONG % bpp); + pattern |= pattern >> bpp; +#endif + return pattern; +} + +/* overwrite bits according to a pattern in a line */ +static __always_inline void bitfill(const struct fb_address *dst, + struct fb_pattern *pattern, + unsigned long (*get)(struct fb_pattern *pattern), + void (*rotate)(struct fb_pattern *pattern), + int end) +{ + unsigned long first, last; + + end += dst->bits; + first = fb_pixel_mask(dst->bits, pattern->reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), pattern->reverse); + + if (end <= BITS_PER_LONG) { + last = last ? (last & first) : first; + first = get(pattern); + if (last == ~0UL) + fb_write_offset(first, 0, dst); + else if (last) + fb_modify_offset(first, last, 0, dst); + } else { + int offset = first != ~0UL; + + if (offset) { + fb_modify_offset(get(pattern), first, 0, dst); + rotate(pattern); + } + end /= BITS_PER_LONG; + for (; offset + 4 <= end; offset += 4) { + fb_write_offset(get(pattern), offset + 0, dst); + rotate(pattern); + fb_write_offset(get(pattern), offset + 1, dst); + rotate(pattern); + fb_write_offset(get(pattern), offset + 2, dst); + rotate(pattern); + fb_write_offset(get(pattern), offset + 3, dst); + rotate(pattern); + } + while (offset < end) { + fb_write_offset(get(pattern), offset++, dst); + rotate(pattern); + } + + if (last) + fb_modify_offset(get(pattern), last, offset, dst); + } +} + +/* inverts bits according to a pattern in a line */ +static __always_inline void bitinvert(const struct fb_address *dst, + struct fb_pattern *pattern, + unsigned long (*get)(struct fb_pattern *pattern), + void (*rotate)(struct fb_pattern *pattern), + int end) +{ + unsigned long first, last; + int offset; + + end += dst->bits; + first = fb_pixel_mask(dst->bits, pattern->reverse); + last = ~fb_pixel_mask(end & (BITS_PER_LONG-1), pattern->reverse); + + if (end <= BITS_PER_LONG) { + offset = 0; + last = last ? (last & first) : first; + } else { + offset = first != ~0UL; + + if (offset) { + first &= get(pattern); + if (first) + fb_invert_offset(first, 0, dst); + rotate(pattern); + } + + end /= BITS_PER_LONG; + for (; offset + 4 <= end; offset += 4) { + fb_invert_offset(get(pattern), offset + 0, dst); + rotate(pattern); + fb_invert_offset(get(pattern), offset + 1, dst); + rotate(pattern); + fb_invert_offset(get(pattern), offset + 2, dst); + rotate(pattern); + fb_invert_offset(get(pattern), offset + 3, dst); + rotate(pattern); + } + while (offset < end) { + fb_invert_offset(get(pattern), offset++, dst); + rotate(pattern); + } + } + + last &= get(pattern); + if (last) + fb_invert_offset(last, offset, dst); +} + +/* pattern doesn't change. 1, 2, 4, 8, 16, 32, 64 bpp */ +static inline void fb_fillrect_static(const struct fb_fillrect *rect, int bpp, + struct fb_address *dst, struct fb_pattern *pattern, + unsigned int bits_per_line) +{ + u32 height = rect->height; + int width = rect->width * bpp; + + if (bpp > 8 && pattern->reverse.byte) + pattern->pixels = swab_long(pattern->pixels); + + if (rect->rop == ROP_XOR) + while (height--) { + bitinvert(dst, pattern, fb_pattern_get, fb_pattern_static, width); + fb_address_forward(dst, bits_per_line); + } + else + while (height--) { + bitfill(dst, pattern, fb_pattern_get, fb_pattern_static, width); + fb_address_forward(dst, bits_per_line); + } +} + +/* rotate pattern to the correct position */ +static inline unsigned long fb_rotate(unsigned long pattern, int shift, int bpp) +{ + shift %= bpp; + return fb_right(pattern, shift) | fb_left(pattern, bpp - shift); +} + +/* rotating pattern, for example 24 bpp */ +static __always_inline void fb_fillrect_rotating(const struct fb_fillrect *rect, + int bpp, struct fb_address *dst, + struct fb_pattern *pattern, + unsigned long (*get)(struct fb_pattern *pattern), + unsigned int bits_per_line) +{ + unsigned long pat = pattern->pixels; + u32 height = rect->height; + int width = rect->width * bpp; + + if (rect->rop == ROP_XOR) + while (height--) { + pattern->pixels = fb_rotate(pat, dst->bits, bpp); + bitinvert(dst, pattern, get, fb_pattern_rotate, width); + fb_address_forward(dst, bits_per_line); + } + else + while (height--) { + pattern->pixels = fb_rotate(pat, dst->bits, bpp); + bitfill(dst, pattern, get, fb_pattern_rotate, width); + fb_address_forward(dst, bits_per_line); + } +} + +static inline void fb_fillrect(struct fb_info *p, const struct fb_fillrect *rect) +{ + int bpp = p->var.bits_per_pixel; + unsigned int bits_per_line = BYTES_TO_BITS(p->fix.line_length); + const u32 *palette = fb_palette(p); + struct fb_address dst = fb_address_init(p); + struct fb_pattern pattern; + + fb_address_forward(&dst, rect->dy * bits_per_line + rect->dx * bpp); + + pattern.pixels = pixel_to_pat(bpp, palette ? palette[rect->color] : rect->color); + pattern.reverse = fb_reverse_init(p); + pattern.left = BITS_PER_LONG % bpp; + if (pattern.left) { + pattern.right = bpp - pattern.left; + if (pattern.reverse.byte) + fb_fillrect_rotating(rect, bpp, &dst, &pattern, + fb_pattern_get_reverse, bits_per_line); + else + fb_fillrect_rotating(rect, bpp, &dst, &pattern, + fb_pattern_get, bits_per_line); + } else + fb_fillrect_static(rect, bpp, &dst, &pattern, bits_per_line); +} diff --git a/drivers/video/fbdev/core/fb_imageblit.h b/drivers/video/fbdev/core/fb_imageblit.h new file mode 100644 index 000000000000..3b2bb4946505 --- /dev/null +++ b/drivers/video/fbdev/core/fb_imageblit.h @@ -0,0 +1,495 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Generic bitmap / 8 bpp image bitstreamer for packed pixel framebuffers + * + * Rewritten by: + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + * + * Based on previous work of: + * Copyright (C) June 1999 James Simmons + * Anton Vorontsov <avorontsov@ru.mvista.com> + * Pavel Pisa <pisa@cmp.felk.cvut.cz> + * Antonino A. Daplas <adaplas@gmail.com> + * and others + * + * NOTES: + * + * Handles native and foreign byte order on both endians, standard and + * reverse pixel order in a byte (<8 BPP), word length of 32/64 bits, + * bits per pixel from 1 to the word length. Handles line lengths at byte + * granularity while maintaining aligned accesses. + * + * Optimized routines for word aligned 1, 2, 4 pixel per word for high + * bpp modes and 4 pixel at a time operation for low bpp. + * + * The color image is expected to be one byte per pixel, and values should + * not exceed the bitdepth or the pseudo palette (if used). + */ +#include "fb_draw.h" + +/* bitmap image iterator, one pixel at a time */ +struct fb_bitmap_iter { + const u8 *data; + unsigned long colors[2]; + int width, i; +}; + +static bool fb_bitmap_image(void *iterator, unsigned long *pixels, int *bits) +{ + struct fb_bitmap_iter *iter = iterator; + + if (iter->i < iter->width) { + int bit = ~iter->i & (BITS_PER_BYTE-1); + int byte = iter->i++ / BITS_PER_BYTE; + + *pixels = iter->colors[(iter->data[byte] >> bit) & 1]; + return true; + } + iter->data += BITS_TO_BYTES(iter->width); + iter->i = 0; + return false; +} + +/* color image iterator, one pixel at a time */ +struct fb_color_iter { + const u8 *data; + const u32 *palette; + struct fb_reverse reverse; + int shift; + int width, i; +}; + +static bool fb_color_image(void *iterator, unsigned long *pixels, int *bits) +{ + struct fb_color_iter *iter = iterator; + + if (iter->i < iter->width) { + unsigned long color = iter->data[iter->i++]; + + if (iter->palette) + color = iter->palette[color]; + *pixels = color << iter->shift; + if (iter->reverse.pixel) + *pixels = fb_reverse_bits_long(*pixels); + return true; + } + iter->data += iter->width; + iter->i = 0; + return false; +} + +/* bitmap image iterator, 4 pixels at a time */ +struct fb_bitmap4x_iter { + const u8 *data; + u32 fgxcolor, bgcolor; + int width, i; + const u32 *expand; + int bpp; + bool top; +}; + +static bool fb_bitmap4x_image(void *iterator, unsigned long *pixels, int *bits) +{ + struct fb_bitmap4x_iter *iter = iterator; + u8 data; + + if (iter->i >= BITS_PER_BYTE/2) { + iter->i -= BITS_PER_BYTE/2; + iter->top = !iter->top; + if (iter->top) + data = *iter->data++ >> BITS_PER_BYTE/2; + else + data = iter->data[-1] & ((1 << BITS_PER_BYTE/2)-1); + } else if (iter->i != 0) { + *bits = iter->bpp * iter->i; + if (iter->top) + data = iter->data[-1] & ((1 << BITS_PER_BYTE/2)-1); + else + data = *iter->data++ >> BITS_PER_BYTE/2; +#ifndef __LITTLE_ENDIAN + data >>= BITS_PER_BYTE/2 - iter->i; +#endif + iter->i = 0; + } else { + *bits = iter->bpp * BITS_PER_BYTE/2; + iter->i = iter->width; + iter->top = false; + return false; + } + *pixels = (iter->fgxcolor & iter->expand[data]) ^ iter->bgcolor; +#ifndef __LITTLE_ENDIAN + *pixels <<= BITS_PER_LONG - *bits; +#endif + return true; +} + +/* draw a line a group of pixels at a time */ +static __always_inline void fb_bitblit(bool (*get)(void *iter, unsigned long *pixels, + int *bits), + void *iter, int bits, struct fb_address *dst, + struct fb_reverse reverse) +{ + unsigned long pixels, val, mask, old; + int offset = 0; + int shift = dst->bits; + + if (shift) { + old = fb_read_offset(0, dst); + val = fb_reverse_long(old, reverse); + val &= ~fb_right(~0UL, shift); + } else { + old = 0; + val = 0; + } + + while (get(iter, &pixels, &bits)) { + val |= fb_right(pixels, shift); + shift += bits; + + if (shift < BITS_PER_LONG) + continue; + + val = fb_reverse_long(val, reverse); + fb_write_offset(val, offset++, dst); + shift &= BITS_PER_LONG - 1; + val = !shift ? 0 : fb_left(pixels, bits - shift); + } + + if (shift) { + mask = ~fb_pixel_mask(shift, reverse); + val = fb_reverse_long(val, reverse); + if (offset || !dst->bits) + old = fb_read_offset(offset, dst); + fb_write_offset(fb_comp(val, old, mask), offset, dst); + } +} + +/* draw a color image a pixel at a time */ +static inline void fb_color_imageblit(const struct fb_image *image, struct fb_address *dst, + unsigned int bits_per_line, const u32 *palette, int bpp, + struct fb_reverse reverse) +{ + struct fb_color_iter iter; + u32 height; + + iter.data = (const u8 *)image->data; + iter.palette = palette; + iter.reverse = reverse; +#ifdef __LITTLE_ENDIAN + if (reverse.pixel) + iter.shift = BITS_PER_BYTE - bpp; + else + iter.shift = 0; +#else + if (reverse.pixel) + iter.shift = BITS_PER_LONG - BITS_PER_BYTE; + else + iter.shift = BITS_PER_LONG - bpp; +#endif + iter.width = image->width; + iter.i = 0; + + height = image->height; + while (height--) { + fb_bitblit(fb_color_image, &iter, bpp, dst, reverse); + fb_address_forward(dst, bits_per_line); + } +} + +#ifdef __LITTLE_ENDIAN +#define FB_GEN(a, b) (((a)/8+(((a)&4)<<((b)-2)) \ + +(((a)&2)<<((b)*2-1))+(((a)&1u)<<((b)*3)))*((1<<(b))-1)) +#define FB_GEN1(a) ((a)/8+((a)&4)/2+((a)&2)*2+((a)&1)*8) +#else +#define FB_GEN(a, b) (((((a)/8)<<((b)*3))+(((a)&4)<<((b)*2-2)) \ + +(((a)&2)<<(b-1))+((a)&1u))*((1<<(b))-1)) +#define FB_GEN1(a) (a) +#endif + +#define FB_GENx(a) { FB_GEN(0, (a)), FB_GEN(1, (a)), FB_GEN(2, (a)), FB_GEN(3, (a)), \ + FB_GEN(4, (a)), FB_GEN(5, (a)), FB_GEN(6, (a)), FB_GEN(7, (a)), \ + FB_GEN(8, (a)), FB_GEN(9, (a)), FB_GEN(10, (a)), FB_GEN(11, (a)), \ + FB_GEN(12, (a)), FB_GEN(13, (a)), FB_GEN(14, (a)), FB_GEN(15, (a)) } + +/* draw a 2 color image four pixels at a time (for 1-8 bpp only) */ +static inline void fb_bitmap4x_imageblit(const struct fb_image *image, struct fb_address *dst, + unsigned long fgcolor, unsigned long bgcolor, int bpp, + unsigned int bits_per_line, struct fb_reverse reverse) +{ + static const u32 mul[BITS_PER_BYTE] = { + 0xf, 0x55, 0x249, 0x1111, 0x8421, 0x41041, 0x204081, 0x01010101 + }; + static const u32 expand[BITS_PER_BYTE][1 << 4] = { + { + FB_GEN1(0), FB_GEN1(1), FB_GEN1(2), FB_GEN1(3), + FB_GEN1(4), FB_GEN1(5), FB_GEN1(6), FB_GEN1(7), + FB_GEN1(8), FB_GEN1(9), FB_GEN1(10), FB_GEN1(11), + FB_GEN1(12), FB_GEN1(13), FB_GEN1(14), FB_GEN1(15) + }, + FB_GENx(2), FB_GENx(3), FB_GENx(4), + FB_GENx(5), FB_GENx(6), FB_GENx(7), FB_GENx(8), + }; + struct fb_bitmap4x_iter iter; + u32 height; + + iter.data = (const u8 *)image->data; + if (reverse.pixel) { + fgcolor = fb_reverse_bits_long(fgcolor << (BITS_PER_BYTE - bpp)); + bgcolor = fb_reverse_bits_long(bgcolor << (BITS_PER_BYTE - bpp)); + } + iter.fgxcolor = (fgcolor ^ bgcolor) * mul[bpp-1]; + iter.bgcolor = bgcolor * mul[bpp-1]; + iter.width = image->width; + iter.i = image->width; + iter.expand = expand[bpp-1]; + iter.bpp = bpp; + iter.top = false; + + height = image->height; + while (height--) { + fb_bitblit(fb_bitmap4x_image, &iter, bpp * BITS_PER_BYTE/2, dst, reverse); + fb_address_forward(dst, bits_per_line); + } +} + +/* draw a bitmap image 1 pixel at a time (for >8 bpp) */ +static inline void fb_bitmap1x_imageblit(const struct fb_image *image, struct fb_address *dst, + unsigned long fgcolor, unsigned long bgcolor, int bpp, + unsigned int bits_per_line, struct fb_reverse reverse) +{ + struct fb_bitmap_iter iter; + u32 height; + + iter.colors[0] = bgcolor; + iter.colors[1] = fgcolor; +#ifndef __LITTLE_ENDIAN + iter.colors[0] <<= BITS_PER_LONG - bpp; + iter.colors[1] <<= BITS_PER_LONG - bpp; +#endif + iter.data = (const u8 *)image->data; + iter.width = image->width; + iter.i = 0; + + height = image->height; + while (height--) { + fb_bitblit(fb_bitmap_image, &iter, bpp, dst, reverse); + fb_address_forward(dst, bits_per_line); + } +} + +/* one pixel per word, 64/32 bpp blitting */ +static inline void fb_bitmap_1ppw(const struct fb_image *image, struct fb_address *dst, + unsigned long fgcolor, unsigned long bgcolor, + int words_per_line, struct fb_reverse reverse) +{ + unsigned long tab[2]; + const u8 *src = (u8 *)image->data; + int width = image->width; + int offset; + u32 height; + + if (reverse.byte) { + tab[0] = swab_long(bgcolor); + tab[1] = swab_long(fgcolor); + } else { + tab[0] = bgcolor; + tab[1] = fgcolor; + } + + height = image->height; + while (height--) { + for (offset = 0; offset + 8 <= width; offset += 8) { + unsigned int srcbyte = *src++; + + fb_write_offset(tab[(srcbyte >> 7) & 1], offset + 0, dst); + fb_write_offset(tab[(srcbyte >> 6) & 1], offset + 1, dst); + fb_write_offset(tab[(srcbyte >> 5) & 1], offset + 2, dst); + fb_write_offset(tab[(srcbyte >> 4) & 1], offset + 3, dst); + fb_write_offset(tab[(srcbyte >> 3) & 1], offset + 4, dst); + fb_write_offset(tab[(srcbyte >> 2) & 1], offset + 5, dst); + fb_write_offset(tab[(srcbyte >> 1) & 1], offset + 6, dst); + fb_write_offset(tab[(srcbyte >> 0) & 1], offset + 7, dst); + } + + if (offset < width) { + unsigned int srcbyte = *src++; + + while (offset < width) { + fb_write_offset(tab[(srcbyte >> 7) & 1], offset, dst); + srcbyte <<= 1; + offset++; + } + } + fb_address_move_long(dst, words_per_line); + } +} + +static inline unsigned long fb_pack(unsigned long left, unsigned long right, int bits) +{ +#ifdef __LITTLE_ENDIAN + return left | right << bits; +#else + return right | left << bits; +#endif +} + +/* aligned 32/16 bpp blitting */ +static inline void fb_bitmap_2ppw(const struct fb_image *image, struct fb_address *dst, + unsigned long fgcolor, unsigned long bgcolor, + int words_per_line, struct fb_reverse reverse) +{ + unsigned long tab[4]; + const u8 *src = (u8 *)image->data; + int width = image->width / 2; + int offset; + u32 height; + + tab[0] = fb_pack(bgcolor, bgcolor, BITS_PER_LONG/2); + tab[1] = fb_pack(bgcolor, fgcolor, BITS_PER_LONG/2); + tab[2] = fb_pack(fgcolor, bgcolor, BITS_PER_LONG/2); + tab[3] = fb_pack(fgcolor, fgcolor, BITS_PER_LONG/2); + + if (reverse.byte) { + tab[0] = swab_long(tab[0]); + tab[1] = swab_long(tab[1]); + tab[2] = swab_long(tab[2]); + tab[3] = swab_long(tab[3]); + } + + height = image->height; + while (height--) { + for (offset = 0; offset + 4 <= width; offset += 4) { + unsigned int srcbyte = *src++; + + fb_write_offset(tab[(srcbyte >> 6) & 3], offset + 0, dst); + fb_write_offset(tab[(srcbyte >> 4) & 3], offset + 1, dst); + fb_write_offset(tab[(srcbyte >> 2) & 3], offset + 2, dst); + fb_write_offset(tab[(srcbyte >> 0) & 3], offset + 3, dst); + } + + if (offset < width) { + unsigned int srcbyte = *src++; + + while (offset < width) { + fb_write_offset(tab[(srcbyte >> 6) & 3], offset, dst); + srcbyte <<= 2; + offset++; + } + } + fb_address_move_long(dst, words_per_line); + } +} + +#define FB_PATP(a, b) (((a)<<((b)*BITS_PER_LONG/4))*((1UL<<BITS_PER_LONG/4)-1UL)) +#define FB_PAT4(a) (FB_PATP((a)&1, 0)|FB_PATP(((a)&2)/2, 1)| \ + FB_PATP(((a)&4)/4, 2)|FB_PATP(((a)&8)/8, 3)) + +/* aligned 16/8 bpp blitting */ +static inline void fb_bitmap_4ppw(const struct fb_image *image, struct fb_address *dst, + unsigned long fgcolor, unsigned long bgcolor, + int words_per_line, struct fb_reverse reverse) +{ + static const unsigned long tab16_be[] = { + 0, FB_PAT4(1UL), FB_PAT4(2UL), FB_PAT4(3UL), + FB_PAT4(4UL), FB_PAT4(5UL), FB_PAT4(6UL), FB_PAT4(7UL), + FB_PAT4(8UL), FB_PAT4(9UL), FB_PAT4(10UL), FB_PAT4(11UL), + FB_PAT4(12UL), FB_PAT4(13UL), FB_PAT4(14UL), ~0UL + }; + static const unsigned long tab16_le[] = { + 0, FB_PAT4(8UL), FB_PAT4(4UL), FB_PAT4(12UL), + FB_PAT4(2UL), FB_PAT4(10UL), FB_PAT4(6UL), FB_PAT4(14UL), + FB_PAT4(1UL), FB_PAT4(9UL), FB_PAT4(5UL), FB_PAT4(13UL), + FB_PAT4(3UL), FB_PAT4(11UL), FB_PAT4(7UL), ~0UL + }; + const unsigned long *tab; + const u8 *src = (u8 *)image->data; + int width = image->width / 4; + int offset; + u32 height; + + fgcolor = fgcolor | fgcolor << BITS_PER_LONG/4; + bgcolor = bgcolor | bgcolor << BITS_PER_LONG/4; + fgcolor = fgcolor | fgcolor << BITS_PER_LONG/2; + bgcolor = bgcolor | bgcolor << BITS_PER_LONG/2; + fgcolor ^= bgcolor; + + if (BITS_PER_LONG/4 > BITS_PER_BYTE && reverse.byte) { + fgcolor = swab_long(fgcolor); + bgcolor = swab_long(bgcolor); + } + +#ifdef __LITTLE_ENDIAN + tab = reverse.byte ? tab16_be : tab16_le; +#else + tab = reverse.byte ? tab16_le : tab16_be; +#endif + + height = image->height; + while (height--) { + for (offset = 0; offset + 2 <= width; offset += 2, src++) { + fb_write_offset((fgcolor & tab[*src >> 4]) ^ bgcolor, offset + 0, dst); + fb_write_offset((fgcolor & tab[*src & 0xf]) ^ bgcolor, offset + 1, dst); + } + + if (offset < width) + fb_write_offset((fgcolor & tab[*src++ >> 4]) ^ bgcolor, offset, dst); + + fb_address_move_long(dst, words_per_line); + } +} + +static inline void fb_bitmap_imageblit(const struct fb_image *image, struct fb_address *dst, + unsigned int bits_per_line, const u32 *palette, int bpp, + struct fb_reverse reverse) +{ + unsigned long fgcolor, bgcolor; + + if (palette) { + fgcolor = palette[image->fg_color]; + bgcolor = palette[image->bg_color]; + } else { + fgcolor = image->fg_color; + bgcolor = image->bg_color; + } + + if (!dst->bits && !(bits_per_line & (BITS_PER_LONG-1))) { + if (bpp == BITS_PER_LONG && BITS_PER_LONG == 32) { + fb_bitmap_1ppw(image, dst, fgcolor, bgcolor, + bits_per_line / BITS_PER_LONG, reverse); + return; + } + if (bpp == BITS_PER_LONG/2 && !(image->width & 1)) { + fb_bitmap_2ppw(image, dst, fgcolor, bgcolor, + bits_per_line / BITS_PER_LONG, reverse); + return; + } + if (bpp == BITS_PER_LONG/4 && !(image->width & 3)) { + fb_bitmap_4ppw(image, dst, fgcolor, bgcolor, + bits_per_line / BITS_PER_LONG, reverse); + return; + } + } + + if (bpp > 0 && bpp <= BITS_PER_BYTE) + fb_bitmap4x_imageblit(image, dst, fgcolor, bgcolor, bpp, + bits_per_line, reverse); + else if (bpp > BITS_PER_BYTE && bpp <= BITS_PER_LONG) + fb_bitmap1x_imageblit(image, dst, fgcolor, bgcolor, bpp, + bits_per_line, reverse); +} + +static inline void fb_imageblit(struct fb_info *p, const struct fb_image *image) +{ + int bpp = p->var.bits_per_pixel; + unsigned int bits_per_line = BYTES_TO_BITS(p->fix.line_length); + struct fb_address dst = fb_address_init(p); + struct fb_reverse reverse = fb_reverse_init(p); + const u32 *palette = fb_palette(p); + + fb_address_forward(&dst, image->dy * bits_per_line + image->dx * bpp); + + if (image->depth == 1) + fb_bitmap_imageblit(image, &dst, bits_per_line, palette, bpp, reverse); + else + fb_color_imageblit(image, &dst, bits_per_line, palette, bpp, reverse); +} diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index fcabc668e9fb..2df48037688d 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -64,6 +64,8 @@ #include <linux/console.h> #include <linux/string.h> #include <linux/kd.h> +#include <linux/panic.h> +#include <linux/printk.h> #include <linux/slab.h> #include <linux/fb.h> #include <linux/fbcon.h> @@ -115,9 +117,14 @@ static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static struct fb_info *fbcon_info_from_console(int console) { + signed char fb; WARN_CONSOLE_UNLOCKED(); - return fbcon_registered_fb[con2fb_map[console]]; + fb = con2fb_map[console]; + if (fb < 0 || fb >= ARRAY_SIZE(fbcon_registered_fb)) + return NULL; + + return fbcon_registered_fb[fb]; } static int logo_lines; @@ -158,7 +165,6 @@ static int info_idx = -1; /* console rotation */ static int initial_rotation = -1; -static int fbcon_has_sysfs; static int margin_color; static const struct consw fb_con; @@ -270,12 +276,24 @@ static int fbcon_get_rotate(struct fb_info *info) return (ops) ? ops->rotate : 0; } +static bool fbcon_skip_panic(struct fb_info *info) +{ +/* panic_cpu is not exported, and can't be used if built as module. Use + * oops_in_progress instead, but non-fatal oops won't be printed. + */ +#if defined(MODULE) + return (info->skip_panic && unlikely(oops_in_progress)); +#else + return (info->skip_panic && unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID)); +#endif +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; return (info->state != FBINFO_STATE_RUNNING || - vc->vc_mode != KD_TEXT || ops->graphics); + vc->vc_mode != KD_TEXT || ops->graphics || fbcon_skip_panic(info)); } static int get_color(struct vc_data *vc, struct fb_info *info, @@ -498,8 +516,10 @@ static int search_fb_in_map(int idx) int i, retval = 0; for (i = first_fb_vc; i <= last_fb_vc; i++) { - if (con2fb_map[i] == idx) + if (con2fb_map[i] == idx) { retval = 1; + break; + } } return retval; } @@ -509,8 +529,10 @@ static int search_for_mapped_con(void) int i, retval = 0; for (i = first_fb_vc; i <= last_fb_vc; i++) { - if (con2fb_map[i] != -1) + if (con2fb_map[i] != -1) { retval = 1; + break; + } } return retval; } @@ -847,6 +869,8 @@ static int set_con2fb_map(int unit, int newidx, int user) return err; fbcon_add_cursor_work(info); + } else if (vc) { + set_blitting_type(vc, info); } con2fb_map[unit] = newidx; @@ -1238,7 +1262,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_ops *ops = info->fbcon_par; - + int fg, bg; struct fbcon_display *p = &fb_display[vc->vc_num]; u_int y_break; @@ -1259,16 +1283,18 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, fbcon_clear_margins(vc, 0); } + fg = get_color(vc, info, vc->vc_video_erase_char, 1); + bg = get_color(vc, info, vc->vc_video_erase_char, 0); /* Split blits that cross physical y_wrap boundary */ y_break = p->vrows - p->yscroll; if (sy < y_break && sy + height - 1 >= y_break) { u_int b = y_break - sy; - ops->clear(vc, info, real_y(p, sy), sx, b, width); + ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); ops->clear(vc, info, real_y(p, sy + b), sx, height - b, - width); + width, fg, bg); } else - ops->clear(vc, info, real_y(p, sy), sx, height, width); + ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); } static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, @@ -2907,7 +2933,7 @@ void fbcon_remap_all(struct fb_info *info) static void fbcon_select_primary(struct fb_info *info) { if (!map_override && primary_device == -1 && - fb_is_primary_device(info)) { + video_is_primary_device(info->device)) { int i; printk(KERN_INFO "fbcon: %s (fb%i) is primary device\n", @@ -3137,7 +3163,7 @@ static const struct consw fb_con = { .con_debug_leave = fbcon_debug_leave, }; -static ssize_t store_rotate(struct device *device, +static ssize_t rotate_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { @@ -3159,7 +3185,7 @@ err: return count; } -static ssize_t store_rotate_all(struct device *device, +static ssize_t rotate_all_store(struct device *device, struct device_attribute *attr,const char *buf, size_t count) { @@ -3181,7 +3207,7 @@ err: return count; } -static ssize_t show_rotate(struct device *device, +static ssize_t rotate_show(struct device *device, struct device_attribute *attr,char *buf) { struct fb_info *info; @@ -3200,7 +3226,7 @@ err: return sysfs_emit(buf, "%d\n", rotate); } -static ssize_t show_cursor_blink(struct device *device, +static ssize_t cursor_blink_show(struct device *device, struct device_attribute *attr, char *buf) { struct fb_info *info; @@ -3225,7 +3251,7 @@ err: return sysfs_emit(buf, "%d\n", blink); } -static ssize_t store_cursor_blink(struct device *device, +static ssize_t cursor_blink_store(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { @@ -3259,35 +3285,18 @@ err: return count; } -static struct device_attribute device_attrs[] = { - __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), - __ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all), - __ATTR(cursor_blink, S_IRUGO|S_IWUSR, show_cursor_blink, - store_cursor_blink), -}; - -static int fbcon_init_device(void) -{ - int i, error = 0; - - fbcon_has_sysfs = 1; +static DEVICE_ATTR_RW(cursor_blink); +static DEVICE_ATTR_RW(rotate); +static DEVICE_ATTR_WO(rotate_all); - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - error = device_create_file(fbcon_device, &device_attrs[i]); - - if (error) - break; - } - - if (error) { - while (--i >= 0) - device_remove_file(fbcon_device, &device_attrs[i]); - - fbcon_has_sysfs = 0; - } +static struct attribute *fbcon_device_attrs[] = { + &dev_attr_cursor_blink.attr, + &dev_attr_rotate.attr, + &dev_attr_rotate_all.attr, + NULL +}; - return 0; -} +ATTRIBUTE_GROUPS(fbcon_device); #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER static void fbcon_register_existing_fbs(struct work_struct *work) @@ -3345,16 +3354,16 @@ void __init fb_console_init(void) int i; console_lock(); - fbcon_device = device_create(fb_class, NULL, MKDEV(0, 0), NULL, - "fbcon"); + fbcon_device = device_create_with_groups(fb_class, NULL, + MKDEV(0, 0), NULL, + fbcon_device_groups, "fbcon"); if (IS_ERR(fbcon_device)) { printk(KERN_WARNING "Unable to create device " "for fbcon; errno = %ld\n", PTR_ERR(fbcon_device)); fbcon_device = NULL; - } else - fbcon_init_device(); + } for (i = 0; i < MAX_NR_CONSOLES; i++) con2fb_map[i] = -1; @@ -3365,18 +3374,6 @@ void __init fb_console_init(void) #ifdef MODULE -static void __exit fbcon_deinit_device(void) -{ - int i; - - if (fbcon_has_sysfs) { - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(fbcon_device, &device_attrs[i]); - - fbcon_has_sysfs = 0; - } -} - void __exit fb_console_exit(void) { #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER @@ -3389,7 +3386,6 @@ void __exit fb_console_exit(void) #endif console_lock(); - fbcon_deinit_device(); device_destroy(fb_class, MKDEV(0, 0)); do_unregister_con_driver(&fb_con); diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h index df70ea5ec5b3..4d97e6d8a16a 100644 --- a/drivers/video/fbdev/core/fbcon.h +++ b/drivers/video/fbdev/core/fbcon.h @@ -55,7 +55,7 @@ struct fbcon_ops { void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width); void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width); + int sx, int height, int width, int fb, int bg); void (*putcs)(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx, int fg, int bg); @@ -116,42 +116,6 @@ static inline int mono_col(const struct fb_info *info) return (~(0xfff << max_len)) & 0xff; } -static inline int attr_col_ec(int shift, struct vc_data *vc, - struct fb_info *info, int is_fg) -{ - int is_mono01; - int col; - int fg; - int bg; - - if (!vc) - return 0; - - if (vc->vc_can_do_color) - return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) - : attr_bgcol(shift,vc->vc_video_erase_char); - - if (!info) - return 0; - - col = mono_col(info); - is_mono01 = info->fix.visual == FB_VISUAL_MONO01; - - if (attr_reverse(vc->vc_video_erase_char)) { - fg = is_mono01 ? col : 0; - bg = is_mono01 ? 0 : col; - } - else { - fg = is_mono01 ? 0 : col; - bg = is_mono01 ? col : 0; - } - - return is_fg ? fg : bg; -} - -#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) -#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) - /* * Scroll Method */ diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index f9b794ff7d39..89ef4ba7e867 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -78,14 +78,13 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, } static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width) + int sx, int height, int width, int fg, int bg) { struct fbcon_ops *ops = info->fbcon_par; struct fb_fillrect region; - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; u32 vyres = GETVYRES(ops->p, info); - region.color = attr_bgcol_ec(bgshift,vc,info); + region.color = bg; region.dx = sy * vc->vc_font.height; region.dy = vyres - ((sx + width) * vc->vc_font.width); region.height = width * vc->vc_font.width; diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index 903f6fc174e1..b9dac7940fb7 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -63,14 +63,13 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, } static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width) + int sx, int height, int width, int fg, int bg) { struct fbcon_ops *ops = info->fbcon_par; struct fb_fillrect region; - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; u32 vxres = GETVXRES(ops->p, info); - region.color = attr_bgcol_ec(bgshift,vc,info); + region.color = bg; region.dx = vxres - ((sy + height) * vc->vc_font.height); region.dy = sx * vc->vc_font.width; region.height = width * vc->vc_font.width; diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 594331936fd3..0af7913a2abd 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -64,15 +64,14 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, } static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width) + int sx, int height, int width, int fg, int bg) { struct fbcon_ops *ops = info->fbcon_par; struct fb_fillrect region; - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; u32 vyres = GETVYRES(ops->p, info); u32 vxres = GETVXRES(ops->p, info); - region.color = attr_bgcol_ec(bgshift,vc,info); + region.color = bg; region.dy = vyres - ((sy + height) * vc->vc_font.height); region.dx = vxres - ((sx + width) * vc->vc_font.width); region.width = width * vc->vc_font.width; diff --git a/drivers/video/fbdev/core/fbcvt.c b/drivers/video/fbdev/core/fbcvt.c index 64843464c661..cd3821bd82e5 100644 --- a/drivers/video/fbdev/core/fbcvt.c +++ b/drivers/video/fbdev/core/fbcvt.c @@ -312,7 +312,7 @@ int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb) cvt.f_refresh = cvt.refresh; cvt.interlace = 1; - if (!cvt.xres || !cvt.yres || !cvt.refresh) { + if (!cvt.xres || !cvt.yres || !cvt.refresh || cvt.f_refresh > INT_MAX) { printk(KERN_INFO "fbcvt: Invalid input parameters\n"); return 1; } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 4c4ad0a86a50..eca2498f2436 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -328,8 +328,10 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) !list_empty(&info->modelist)) ret = fb_add_videomode(&mode, &info->modelist); - if (ret) + if (ret) { + info->var = old_var; return ret; + } event.info = info; event.data = &mode; @@ -388,7 +390,7 @@ static int fb_check_foreignness(struct fb_info *fi) static int do_register_framebuffer(struct fb_info *fb_info) { - int i; + int i, err = 0; struct fb_videomode mode; if (fb_check_foreignness(fb_info)) @@ -397,10 +399,18 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (num_registered_fb == FB_MAX) return -ENXIO; - num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) if (!registered_fb[i]) break; + + if (!fb_info->modelist.prev || !fb_info->modelist.next) + INIT_LIST_HEAD(&fb_info->modelist); + + fb_var_to_videomode(&mode, &fb_info->var); + err = fb_add_videomode(&mode, &fb_info->modelist); + if (err < 0) + return err; + fb_info->node = i; refcount_set(&fb_info->count, 1); mutex_init(&fb_info->lock); @@ -426,16 +436,12 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (bitmap_empty(fb_info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT)) bitmap_fill(fb_info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT); - if (!fb_info->modelist.prev || !fb_info->modelist.next) - INIT_LIST_HEAD(&fb_info->modelist); - if (fb_info->skip_vt_switch) pm_vt_switch_required(fb_info->device, false); else pm_vt_switch_required(fb_info->device, true); - fb_var_to_videomode(&mode, &fb_info->var); - fb_add_videomode(&mode, &fb_info->modelist); + num_registered_fb++; registered_fb[i] = fb_info; #ifdef CONFIG_GUMSTIX_AM200EPD @@ -544,6 +550,36 @@ unregister_framebuffer(struct fb_info *fb_info) } EXPORT_SYMBOL(unregister_framebuffer); +static void devm_unregister_framebuffer(void *data) +{ + struct fb_info *info = data; + + unregister_framebuffer(info); +} + +/** + * devm_register_framebuffer - resource-managed frame buffer device registration + * @dev: device the framebuffer belongs to + * @fb_info: frame buffer info structure + * + * Registers a frame buffer device @fb_info to device @dev. + * + * Returns negative errno on error, or zero for success. + * + */ +int +devm_register_framebuffer(struct device *dev, struct fb_info *fb_info) +{ + int ret; + + ret = register_framebuffer(fb_info); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, devm_unregister_framebuffer, fb_info); +} +EXPORT_SYMBOL(devm_register_framebuffer); + /** * fb_set_suspend - low level driver signals suspend * @info: framebuffer affected diff --git a/drivers/video/fbdev/core/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c index 1b3c9958ef5c..06d75c767579 100644 --- a/drivers/video/fbdev/core/fbsysfs.c +++ b/drivers/video/fbdev/core/fbsysfs.c @@ -416,55 +416,64 @@ static ssize_t show_bl_curve(struct device *device, /* When cmap is added back in it should be a binary attribute * not a text one. Consideration should also be given to converting * fbdev to use configfs instead of sysfs */ -static struct device_attribute device_attrs[] = { - __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), - __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), - __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console), - __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor), - __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode), - __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes), - __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan), - __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), - __ATTR(name, S_IRUGO, show_name, NULL), - __ATTR(stride, S_IRUGO, show_stride, NULL), - __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), - __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), +static DEVICE_ATTR(bits_per_pixel, 0644, show_bpp, store_bpp); +static DEVICE_ATTR(blank, 0644, show_blank, store_blank); +static DEVICE_ATTR(console, 0644, show_console, store_console); +static DEVICE_ATTR(cursor, 0644, show_cursor, store_cursor); +static DEVICE_ATTR(mode, 0644, show_mode, store_mode); +static DEVICE_ATTR(modes, 0644, show_modes, store_modes); +static DEVICE_ATTR(pan, 0644, show_pan, store_pan); +static DEVICE_ATTR(virtual_size, 0644, show_virtual, store_virtual); +static DEVICE_ATTR(name, 0444, show_name, NULL); +static DEVICE_ATTR(stride, 0444, show_stride, NULL); +static DEVICE_ATTR(rotate, 0644, show_rotate, store_rotate); +static DEVICE_ATTR(state, 0644, show_fbstate, store_fbstate); #if IS_ENABLED(CONFIG_FB_BACKLIGHT) - __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve), +static DEVICE_ATTR(bl_curve, 0644, show_bl_curve, store_bl_curve); #endif + +static struct attribute *fb_device_attrs[] = { + &dev_attr_bits_per_pixel.attr, + &dev_attr_blank.attr, + &dev_attr_console.attr, + &dev_attr_cursor.attr, + &dev_attr_mode.attr, + &dev_attr_modes.attr, + &dev_attr_pan.attr, + &dev_attr_virtual_size.attr, + &dev_attr_name.attr, + &dev_attr_stride.attr, + &dev_attr_rotate.attr, + &dev_attr_state.attr, +#if IS_ENABLED(CONFIG_FB_BACKLIGHT) + &dev_attr_bl_curve.attr, +#endif + NULL, +}; + +static const struct attribute_group fb_device_attr_group = { + .attrs = fb_device_attrs, }; static int fb_init_device(struct fb_info *fb_info) { - int i, error = 0; + int ret; dev_set_drvdata(fb_info->dev, fb_info); fb_info->class_flag |= FB_SYSFS_FLAG_ATTR; - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { - error = device_create_file(fb_info->dev, &device_attrs[i]); - - if (error) - break; - } - - if (error) { - while (--i >= 0) - device_remove_file(fb_info->dev, &device_attrs[i]); + ret = device_add_group(fb_info->dev, &fb_device_attr_group); + if (ret) fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; - } return 0; } static void fb_cleanup_device(struct fb_info *fb_info) { - unsigned int i; - if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) { - for (i = 0; i < ARRAY_SIZE(device_attrs); i++) - device_remove_file(fb_info->dev, &device_attrs[i]); + device_remove_group(fb_info->dev, &fb_device_attr_group); fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; } diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c index 75e7001e8450..b634e2d21208 100644 --- a/drivers/video/fbdev/core/syscopyarea.c +++ b/drivers/video/fbdev/core/syscopyarea.c @@ -1,373 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic Bit Block Transfer for frame buffers located in system RAM with - * packed pixels of any depth. - * - * Based almost entirely from cfbcopyarea.c (which is based almost entirely - * on Geert Uytterhoeven's copyarea routine) - * - * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ #include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#include <asm/io.h> -#include "fb_draw.h" - /* - * Generic bitwise copy algorithm - */ +#ifdef CONFIG_FB_SYS_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE +#endif -static void -bitcpy(struct fb_info *p, unsigned long *dst, unsigned dst_idx, - const unsigned long *src, unsigned src_idx, int bits, unsigned n) -{ - unsigned long first, last; - int const shift = dst_idx-src_idx; - int left, right; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (!shift) { - /* Same alignment for source and dest */ - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*src, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first != ~0UL) { - *dst = comp(*src, *dst, first); - dst++; - src++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - *dst++ = *src++; - n -= 8; - } - while (n--) - *dst++ = *src++; - - /* Trailing bits */ - if (last) - *dst = comp(*src, *dst, last); - } - } else { - unsigned long d0, d1; - int m; - - /* Different alignment for source and dest */ - right = shift & (bits - 1); - left = -shift & (bits - 1); - - if (dst_idx+n <= bits) { - /* Single destination word */ - if (last) - first &= last; - if (shift > 0) { - /* Single source word */ - *dst = comp(*src << left, *dst, first); - } else if (src_idx+n <= bits) { - /* Single source word */ - *dst = comp(*src >> right, *dst, first); - } else { - /* 2 source words */ - d0 = *src++; - d1 = *src; - *dst = comp(d0 >> right | d1 << left, *dst, - first); - } - } else { - /* Multiple destination words */ - /** We must always remember the last value read, - because in case SRC and DST overlap bitwise (e.g. - when moving just one pixel in 1bpp), we always - collect one full long for DST and that might - overlap with the current long from SRC. We store - this value in 'd0'. */ - d0 = *src++; - /* Leading bits */ - if (shift > 0) { - /* Single source word */ - *dst = comp(d0 << left, *dst, first); - dst++; - n -= bits - dst_idx; - } else { - /* 2 source words */ - d1 = *src++; - *dst = comp(d0 >> right | d1 << left, *dst, - first); - d0 = d1; - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - m = n % bits; - n /= bits; - while (n >= 4) { - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - n -= 4; - } - while (n--) { - d1 = *src++; - *dst++ = d0 >> right | d1 << left; - d0 = d1; - } - - /* Trailing bits */ - if (m) { - if (m <= bits - right) { - /* Single source word */ - d0 >>= right; - } else { - /* 2 source words */ - d1 = *src; - d0 = d0 >> right | d1 << left; - } - *dst = comp(d0, *dst, last); - } - } - } -} - - /* - * Generic bitwise copy algorithm, operating backward - */ - -static void -bitcpy_rev(struct fb_info *p, unsigned long *dst, unsigned dst_idx, - const unsigned long *src, unsigned src_idx, unsigned bits, - unsigned n) -{ - unsigned long first, last; - int shift; - - dst += (dst_idx + n - 1) / bits; - src += (src_idx + n - 1) / bits; - dst_idx = (dst_idx + n - 1) % bits; - src_idx = (src_idx + n - 1) % bits; - - shift = dst_idx-src_idx; - - first = ~FB_SHIFT_HIGH(p, ~0UL, (dst_idx + 1) % bits); - last = FB_SHIFT_HIGH(p, ~0UL, (bits + dst_idx + 1 - n) % bits); - - if (!shift) { - /* Same alignment for source and dest */ - if ((unsigned long)dst_idx+1 >= n) { - /* Single word */ - if (first) - last &= first; - *dst = comp(*src, *dst, last); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first) { - *dst = comp(*src, *dst, first); - dst--; - src--; - n -= dst_idx+1; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - *dst-- = *src--; - n -= 8; - } - while (n--) - *dst-- = *src--; - /* Trailing bits */ - if (last != -1UL) - *dst = comp(*src, *dst, last); - } - } else { - /* Different alignment for source and dest */ - - int const left = shift & (bits-1); - int const right = -shift & (bits-1); - - if ((unsigned long)dst_idx+1 >= n) { - /* Single destination word */ - if (first) - last &= first; - if (shift < 0) { - /* Single source word */ - *dst = comp(*src >> right, *dst, last); - } else if (1+(unsigned long)src_idx >= n) { - /* Single source word */ - *dst = comp(*src << left, *dst, last); - } else { - /* 2 source words */ - *dst = comp(*src << left | *(src-1) >> right, - *dst, last); - } - } else { - /* Multiple destination words */ - /** We must always remember the last value read, - because in case SRC and DST overlap bitwise (e.g. - when moving just one pixel in 1bpp), we always - collect one full long for DST and that might - overlap with the current long from SRC. We store - this value in 'd0'. */ - unsigned long d0, d1; - int m; - - d0 = *src--; - /* Leading bits */ - if (shift < 0) { - /* Single source word */ - d1 = d0; - d0 >>= right; - } else { - /* 2 source words */ - d1 = *src--; - d0 = d0 << left | d1 >> right; - } - if (!first) - *dst = d0; - else - *dst = comp(d0, *dst, first); - d0 = d1; - dst--; - n -= dst_idx+1; - - /* Main chunk */ - m = n % bits; - n /= bits; - while (n >= 4) { - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - n -= 4; - } - while (n--) { - d1 = *src--; - *dst-- = d0 << left | d1 >> right; - d0 = d1; - } - - /* Trailing bits */ - if (m) { - if (m <= bits - left) { - /* Single source word */ - d0 <<= left; - } else { - /* 2 source words */ - d1 = *src; - d0 = d0 << left | d1 >> right; - } - *dst = comp(d0, *dst, last); - } - } - } -} +#include "sysmem.h" +#include "fb_copyarea.h" void sys_copyarea(struct fb_info *p, const struct fb_copyarea *area) { - u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; - u32 height = area->height, width = area->width; - unsigned int const bits_per_line = p->fix.line_length * 8u; - unsigned long *base = NULL; - int bits = BITS_PER_LONG, bytes = bits >> 3; - unsigned dst_idx = 0, src_idx = 0, rev_copy = 0; - - if (p->state != FBINFO_STATE_RUNNING) - return; - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); - - /* if the beginning of the target area might overlap with the end of - the source area, be have to copy the area reverse. */ - if ((dy == sy && dx > sx) || (dy > sy)) { - dy += height; - sy += height; - rev_copy = 1; - } + fb_warn_once(p, "%s: framebuffer is not in virtual address space.\n", __func__); - /* split the base of the framebuffer into a long-aligned address and - the index of the first bit */ - base = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1)); - /* add offset of source and target area */ - dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel; - src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (rev_copy) { - while (height--) { - dst_idx -= bits_per_line; - src_idx -= bits_per_line; - bitcpy_rev(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel); - } - } else { - while (height--) { - bitcpy(p, base + (dst_idx / bits), dst_idx % bits, - base + (src_idx / bits), src_idx % bits, bits, - width*p->var.bits_per_pixel); - dst_idx += bits_per_line; - src_idx += bits_per_line; - } - } + fb_copyarea(p, area); } - EXPORT_SYMBOL(sys_copyarea); -MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); -MODULE_DESCRIPTION("Generic copyarea (sys-to-sys)"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("Virtual memory packed pixel framebuffer area copy"); MODULE_LICENSE("GPL"); - diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c index e49221a88ccc..372ca6a324c2 100644 --- a/drivers/video/fbdev/core/sysfillrect.c +++ b/drivers/video/fbdev/core/sysfillrect.c @@ -1,328 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic fillrect for frame buffers in system RAM with packed pixels of - * any depth. - * - * Based almost entirely from cfbfillrect.c (which is based almost entirely - * on Geert Uytterhoeven's fillrect routine) - * - * Copyright (C) 2007 Antonino Daplas <adaplas@pol.net> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ #include <linux/module.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#include "fb_draw.h" - /* - * Aligned pattern fill using 32/64-bit memory accesses - */ - -static void -bitfill_aligned(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(pat, *dst, first); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first!= ~0UL) { - *dst = comp(pat, *dst, first); - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - memset_l(dst, pat, n); - dst += n; - - /* Trailing bits */ - if (last) - *dst = comp(pat, *dst, last); - } -} - - - /* - * Unaligned generic pattern fill using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(pat, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first) { - *dst = comp(pat, *dst, first); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 4) { - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - *dst++ = pat; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - *dst++ = pat; - pat = pat << left | pat >> right; - } - - /* Trailing bits */ - if (last) - *dst = comp(pat, *dst, last); - } -} - - /* - * Aligned pattern invert using 32/64-bit memory accesses - */ -static void -bitfill_aligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, unsigned n, int bits) -{ - unsigned long val = pat; - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*dst ^ val, *dst, first); - } else { - /* Multiple destination words */ - /* Leading bits */ - if (first!=0UL) { - *dst = comp(*dst ^ val, *dst, first); - dst++; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 8) { - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - *dst++ ^= val; - n -= 8; - } - while (n--) - *dst++ ^= val; - /* Trailing bits */ - if (last) - *dst = comp(*dst ^ val, *dst, last); - } -} - - - /* - * Unaligned generic pattern invert using 32/64-bit memory accesses - * The pattern must have been expanded to a full 32/64-bit value - * Left/right are the appropriate shifts to convert to the pattern to be - * used for the next 32/64-bit word - */ - -static void -bitfill_unaligned_rev(struct fb_info *p, unsigned long *dst, int dst_idx, - unsigned long pat, int left, int right, unsigned n, - int bits) -{ - unsigned long first, last; - - if (!n) - return; - - first = FB_SHIFT_HIGH(p, ~0UL, dst_idx); - last = ~(FB_SHIFT_HIGH(p, ~0UL, (dst_idx+n) % bits)); - - if (dst_idx+n <= bits) { - /* Single word */ - if (last) - first &= last; - *dst = comp(*dst ^ pat, *dst, first); - } else { - /* Multiple destination words */ - - /* Leading bits */ - if (first != 0UL) { - *dst = comp(*dst ^ pat, *dst, first); - dst++; - pat = pat << left | pat >> right; - n -= bits - dst_idx; - } - - /* Main chunk */ - n /= bits; - while (n >= 4) { - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - *dst++ ^= pat; - pat = pat << left | pat >> right; - n -= 4; - } - while (n--) { - *dst ^= pat; - pat = pat << left | pat >> right; - } +#ifdef CONFIG_FB_SYS_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE +#endif - /* Trailing bits */ - if (last) - *dst = comp(*dst ^ pat, *dst, last); - } -} +#include "sysmem.h" +#include "fb_fillrect.h" void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { - unsigned long pat, pat2, fg; - unsigned long width = rect->width, height = rect->height; - int bits = BITS_PER_LONG, bytes = bits >> 3; - u32 bpp = p->var.bits_per_pixel; - unsigned long *dst; - int dst_idx, left; - - if (p->state != FBINFO_STATE_RUNNING) - return; - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); + fb_warn_once(p, "%s: framebuffer is not in virtual address space.\n", __func__); - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - fg = ((u32 *) (p->pseudo_palette))[rect->color]; - else - fg = rect->color; - - pat = pixel_to_pat( bpp, fg); - - dst = (unsigned long *)((unsigned long)p->screen_base & ~(bytes-1)); - dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8; - dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp; - /* FIXME For now we support 1-32 bpp only */ - left = bits % bpp; - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - if (!left) { - void (*fill_op32)(struct fb_info *p, unsigned long *dst, - int dst_idx, unsigned long pat, unsigned n, - int bits) = NULL; - - switch (rect->rop) { - case ROP_XOR: - fill_op32 = bitfill_aligned_rev; - break; - case ROP_COPY: - fill_op32 = bitfill_aligned; - break; - default: - printk( KERN_ERR "cfb_fillrect(): unknown rop, " - "defaulting to ROP_COPY\n"); - fill_op32 = bitfill_aligned; - break; - } - while (height--) { - dst += dst_idx >> (ffs(bits) - 1); - dst_idx &= (bits - 1); - fill_op32(p, dst, dst_idx, pat, width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } else { - int right, r; - void (*fill_op)(struct fb_info *p, unsigned long *dst, - int dst_idx, unsigned long pat, int left, - int right, unsigned n, int bits) = NULL; -#ifdef __LITTLE_ENDIAN - right = left; - left = bpp - right; -#else - right = bpp - left; -#endif - switch (rect->rop) { - case ROP_XOR: - fill_op = bitfill_unaligned_rev; - break; - case ROP_COPY: - fill_op = bitfill_unaligned; - break; - default: - printk(KERN_ERR "sys_fillrect(): unknown rop, " - "defaulting to ROP_COPY\n"); - fill_op = bitfill_unaligned; - break; - } - while (height--) { - dst += dst_idx / bits; - dst_idx &= (bits - 1); - r = dst_idx % bpp; - /* rotate pattern to the correct start position */ - pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp)); - fill_op(p, dst, dst_idx, pat2, left, right, - width*bpp, bits); - dst_idx += p->fix.line_length*8; - } - } + fb_fillrect(p, rect); } - EXPORT_SYMBOL(sys_fillrect); -MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); -MODULE_DESCRIPTION("Generic fill rectangle (sys-to-sys)"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("Virtual memory packed pixel framebuffer area fill"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index 6949bbd51d92..c756cc658b7d 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -1,339 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Generic 1-bit or 8-bit source to 1-32 bit destination expansion - * for frame buffer located in system RAM with packed pixels of any depth. - * - * Based almost entirely on cfbimgblt.c - * - * Copyright (C) April 2007 Antonino Daplas <adaplas@pol.net> - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ #include <linux/module.h> -#include <linux/string.h> #include <linux/fb.h> +#include <linux/bitrev.h> #include <asm/types.h> -#define DEBUG - -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt,__func__,## args) -#else -#define DPRINTK(fmt, args...) +#ifdef CONFIG_FB_SYS_REV_PIXELS_IN_BYTE +#define FB_REV_PIXELS_IN_BYTE #endif -static const u32 cfb_tab8_be[] = { - 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, - 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, - 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, - 0xffff0000,0xffff00ff,0xffffff00,0xffffffff -}; - -static const u32 cfb_tab8_le[] = { - 0x00000000,0xff000000,0x00ff0000,0xffff0000, - 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, - 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, - 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff -}; - -static const u32 cfb_tab16_be[] = { - 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff -}; - -static const u32 cfb_tab16_le[] = { - 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff -}; - -static const u32 cfb_tab32[] = { - 0x00000000, 0xffffffff -}; - -static void color_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 start_index, u32 pitch_index) -{ - /* Draw the penguin */ - u32 *dst, *dst2; - u32 color = 0, val, shift; - int i, n, bpp = p->var.bits_per_pixel; - u32 null_bits = 32 - bpp; - u32 *palette = (u32 *) p->pseudo_palette; - const u8 *src = image->data; - - dst2 = dst1; - for (i = image->height; i--; ) { - n = image->width; - dst = dst1; - shift = 0; - val = 0; - - if (start_index) { - u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, - start_index)); - val = *dst & start_mask; - shift = start_index; - } - while (n--) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR ) - color = palette[*src]; - else - color = *src; - color <<= FB_LEFT_POS(p, bpp); - val |= FB_SHIFT_HIGH(p, color, shift); - if (shift >= null_bits) { - *dst++ = val; - - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - src++; - } - if (shift) { - u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); - - *dst &= end_mask; - *dst |= val; - } - dst1 += p->fix.line_length; - if (pitch_index) { - dst2 += p->fix.line_length; - dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); - - start_index += pitch_index; - start_index &= 32 - 1; - } - } -} - -static void slow_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 fgcolor, u32 bgcolor, - u32 start_index, u32 pitch_index) -{ - u32 shift, color = 0, bpp = p->var.bits_per_pixel; - u32 *dst, *dst2; - u32 val, pitch = p->fix.line_length; - u32 null_bits = 32 - bpp; - u32 spitch = (image->width+7)/8; - const u8 *src = image->data, *s; - u32 i, j, l; - - dst2 = dst1; - fgcolor <<= FB_LEFT_POS(p, bpp); - bgcolor <<= FB_LEFT_POS(p, bpp); - - for (i = image->height; i--; ) { - shift = val = 0; - l = 8; - j = image->width; - dst = dst1; - s = src; - - /* write leading bits */ - if (start_index) { - u32 start_mask = ~(FB_SHIFT_HIGH(p, ~(u32)0, - start_index)); - val = *dst & start_mask; - shift = start_index; - } - - while (j--) { - l--; - color = (*s & (1 << l)) ? fgcolor : bgcolor; - val |= FB_SHIFT_HIGH(p, color, shift); - - /* Did the bitshift spill bits to the next long? */ - if (shift >= null_bits) { - *dst++ = val; - val = (shift == null_bits) ? 0 : - FB_SHIFT_LOW(p, color, 32 - shift); - } - shift += bpp; - shift &= (32 - 1); - if (!l) { l = 8; s++; } - } - - /* write trailing bits */ - if (shift) { - u32 end_mask = FB_SHIFT_HIGH(p, ~(u32)0, shift); - - *dst &= end_mask; - *dst |= val; - } - - dst1 += pitch; - src += spitch; - if (pitch_index) { - dst2 += pitch; - dst1 = (u8 *)((long)dst2 & ~(sizeof(u32) - 1)); - start_index += pitch_index; - start_index &= 32 - 1; - } - - } -} - -/* - * fast_imageblit - optimized monochrome color expansion - * - * Only if: bits_per_pixel == 8, 16, or 32 - * image->width is divisible by pixel/dword (ppw); - * fix->line_legth is divisible by 4; - * beginning and end of a scanline is dword aligned - */ -static void fast_imageblit(const struct fb_image *image, struct fb_info *p, - void *dst1, u32 fgcolor, u32 bgcolor) -{ - u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; - u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx, shift; - const u8 *s = image->data, *src; - u32 *dst; - const u32 *tab; - size_t tablen; - u32 colortab[16]; - int i, j, k; - - switch (bpp) { - case 8: - tab = fb_be_math(p) ? cfb_tab8_be : cfb_tab8_le; - tablen = 16; - break; - case 16: - tab = fb_be_math(p) ? cfb_tab16_be : cfb_tab16_le; - tablen = 4; - break; - case 32: - tab = cfb_tab32; - tablen = 2; - break; - default: - return; - } - - for (i = ppw-1; i--; ) { - fgx <<= bpp; - bgx <<= bpp; - fgx |= fgcolor; - bgx |= bgcolor; - } - - bit_mask = (1 << ppw) - 1; - eorx = fgx ^ bgx; - k = image->width/ppw; - - for (i = 0; i < tablen; ++i) - colortab[i] = (tab[i] & eorx) ^ bgx; - - for (i = image->height; i--; ) { - dst = dst1; - shift = 8; - src = s; - - /* - * Manually unroll the per-line copying loop for better - * performance. This works until we processed the last - * completely filled source byte (inclusive). - */ - switch (ppw) { - case 4: /* 8 bpp */ - for (j = k; j >= 2; j -= 2, ++src) { - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - case 2: /* 16 bpp */ - for (j = k; j >= 4; j -= 4, ++src) { - *dst++ = colortab[(*src >> 6) & bit_mask]; - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 2) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - case 1: /* 32 bpp */ - for (j = k; j >= 8; j -= 8, ++src) { - *dst++ = colortab[(*src >> 7) & bit_mask]; - *dst++ = colortab[(*src >> 6) & bit_mask]; - *dst++ = colortab[(*src >> 5) & bit_mask]; - *dst++ = colortab[(*src >> 4) & bit_mask]; - *dst++ = colortab[(*src >> 3) & bit_mask]; - *dst++ = colortab[(*src >> 2) & bit_mask]; - *dst++ = colortab[(*src >> 1) & bit_mask]; - *dst++ = colortab[(*src >> 0) & bit_mask]; - } - break; - } - - /* - * For image widths that are not a multiple of 8, there - * are trailing pixels left on the current line. Print - * them as well. - */ - for (; j--; ) { - shift -= ppw; - *dst++ = colortab[(*src >> shift) & bit_mask]; - if (!shift) { - shift = 8; - ++src; - } - } - - dst1 += p->fix.line_length; - s += spitch; - } -} +#include "sysmem.h" +#include "fb_imageblit.h" void sys_imageblit(struct fb_info *p, const struct fb_image *image) { - u32 fgcolor, bgcolor, start_index, bitstart, pitch_index = 0; - u32 bpl = sizeof(u32), bpp = p->var.bits_per_pixel; - u32 width = image->width; - u32 dx = image->dx, dy = image->dy; - void *dst1; - - if (p->state != FBINFO_STATE_RUNNING) - return; - if (!(p->flags & FBINFO_VIRTFB)) - fb_warn_once(p, "Framebuffer is not in virtual address space."); - - bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); - start_index = bitstart & (32 - 1); - pitch_index = (p->fix.line_length & (bpl - 1)) * 8; + fb_warn_once(p, "%s: framebuffer is not in virtual address space.\n", __func__); - bitstart /= 8; - bitstart &= ~(bpl - 1); - dst1 = (void __force *)p->screen_base + bitstart; - - if (p->fbops->fb_sync) - p->fbops->fb_sync(p); - - if (image->depth == 1) { - if (p->fix.visual == FB_VISUAL_TRUECOLOR || - p->fix.visual == FB_VISUAL_DIRECTCOLOR) { - fgcolor = ((u32*)(p->pseudo_palette))[image->fg_color]; - bgcolor = ((u32*)(p->pseudo_palette))[image->bg_color]; - } else { - fgcolor = image->fg_color; - bgcolor = image->bg_color; - } - - if (32 % bpp == 0 && !start_index && !pitch_index && - ((width & (32/bpp-1)) == 0) && - bpp >= 8 && bpp <= 32) - fast_imageblit(image, p, dst1, fgcolor, bgcolor); - else - slow_imageblit(image, p, dst1, fgcolor, bgcolor, - start_index, pitch_index); - } else - color_imageblit(image, p, dst1, start_index, pitch_index); + fb_imageblit(p, image); } - EXPORT_SYMBOL(sys_imageblit); -MODULE_AUTHOR("Antonino Daplas <adaplas@pol.net>"); -MODULE_DESCRIPTION("1-bit/8-bit to 1-32 bit color expansion (sys-to-sys)"); +MODULE_AUTHOR("Zsolt Kajtar <soci@c64.rulez.org>"); +MODULE_DESCRIPTION("Virtual memory packed pixel framebuffer image draw"); MODULE_LICENSE("GPL"); - diff --git a/drivers/video/fbdev/core/sysmem.h b/drivers/video/fbdev/core/sysmem.h new file mode 100644 index 000000000000..033c31a96e78 --- /dev/null +++ b/drivers/video/fbdev/core/sysmem.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * Virtual memory framebuffer access for drawing routines + * + * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) + */ + +/* keeps track of a bit address in framebuffer memory */ +struct fb_address { + void *address; + int bits; +}; + +/* initialize the bit address pointer to the beginning of the frame buffer */ +static inline struct fb_address fb_address_init(struct fb_info *p) +{ + void *base = p->screen_buffer; + struct fb_address ptr; + + ptr.address = PTR_ALIGN_DOWN(base, BITS_PER_LONG / BITS_PER_BYTE); + ptr.bits = (base - ptr.address) * BITS_PER_BYTE; + return ptr; +} + +/* framebuffer write access */ +static inline void fb_write_offset(unsigned long val, int offset, const struct fb_address *dst) +{ + unsigned long *mem = dst->address; + + mem[offset] = val; +} + +/* framebuffer read access */ +static inline unsigned long fb_read_offset(int offset, const struct fb_address *src) +{ + unsigned long *mem = src->address; + + return mem[offset]; +} diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c index eff7ec4da167..d342b90c42b7 100644 --- a/drivers/video/fbdev/core/tileblit.c +++ b/drivers/video/fbdev/core/tileblit.c @@ -32,16 +32,14 @@ static void tile_bmove(struct vc_data *vc, struct fb_info *info, int sy, } static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width) + int sx, int height, int width, int fg, int bg) { struct fb_tilerect rect; - int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; - int fgshift = (vc->vc_hi_font_mask) ? 9 : 8; rect.index = vc->vc_video_erase_char & ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); - rect.fg = attr_fgcol_ec(fgshift, vc, info); - rect.bg = attr_bgcol_ec(bgshift, vc, info); + rect.fg = fg; + rect.bg = bg; rect.sx = sx; rect.sy = sy; rect.width = width; @@ -76,7 +74,42 @@ static void tile_putcs(struct vc_data *vc, struct fb_info *info, static void tile_clear_margins(struct vc_data *vc, struct fb_info *info, int color, int bottom_only) { - return; + unsigned int cw = vc->vc_font.width; + unsigned int ch = vc->vc_font.height; + unsigned int rw = info->var.xres - (vc->vc_cols*cw); + unsigned int bh = info->var.yres - (vc->vc_rows*ch); + unsigned int rs = info->var.xres - rw; + unsigned int bs = info->var.yres - bh; + unsigned int vwt = info->var.xres_virtual / cw; + unsigned int vht = info->var.yres_virtual / ch; + struct fb_tilerect rect; + + rect.index = vc->vc_video_erase_char & + ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); + rect.fg = color; + rect.bg = color; + + if ((int) rw > 0 && !bottom_only) { + rect.sx = (info->var.xoffset + rs + cw - 1) / cw; + rect.sy = 0; + rect.width = (rw + cw - 1) / cw; + rect.height = vht; + if (rect.width + rect.sx > vwt) + rect.width = vwt - rect.sx; + if (rect.sx < vwt) + info->tileops->fb_tilefill(info, &rect); + } + + if ((int) bh > 0) { + rect.sx = info->var.xoffset / cw; + rect.sy = (info->var.yoffset + bs) / ch; + rect.width = rs / cw; + rect.height = (bh + ch - 1) / ch; + if (rect.height + rect.sy > vht) + rect.height = vht - rect.sy; + if (rect.sy < vht) + info->tileops->fb_tilefill(info, &rect); + } } static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable, diff --git a/drivers/video/fbdev/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c deleted file mode 100644 index 4ca70a1bdd3b..000000000000 --- a/drivers/video/fbdev/da8xx-fb.c +++ /dev/null @@ -1,1665 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2008-2009 MontaVista Software Inc. - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * Based on the LCD driver for TI Avalanche processors written by - * Ajay Singh and Shalom Hai. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/fb.h> -#include <linux/dma-mapping.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <linux/uaccess.h> -#include <linux/pm_runtime.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/console.h> -#include <linux/regulator/consumer.h> -#include <linux/spinlock.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/lcm.h> -#include <video/da8xx-fb.h> -#include <asm/div64.h> - -#define DRIVER_NAME "da8xx_lcdc" - -#define LCD_VERSION_1 1 -#define LCD_VERSION_2 2 - -/* LCD Status Register */ -#define LCD_END_OF_FRAME1 BIT(9) -#define LCD_END_OF_FRAME0 BIT(8) -#define LCD_PL_LOAD_DONE BIT(6) -#define LCD_FIFO_UNDERFLOW BIT(5) -#define LCD_SYNC_LOST BIT(2) -#define LCD_FRAME_DONE BIT(0) - -/* LCD DMA Control Register */ -#define LCD_DMA_BURST_SIZE(x) ((x) << 4) -#define LCD_DMA_BURST_1 0x0 -#define LCD_DMA_BURST_2 0x1 -#define LCD_DMA_BURST_4 0x2 -#define LCD_DMA_BURST_8 0x3 -#define LCD_DMA_BURST_16 0x4 -#define LCD_V1_END_OF_FRAME_INT_ENA BIT(2) -#define LCD_V2_END_OF_FRAME0_INT_ENA BIT(8) -#define LCD_V2_END_OF_FRAME1_INT_ENA BIT(9) -#define LCD_DUAL_FRAME_BUFFER_ENABLE BIT(0) - -/* LCD Control Register */ -#define LCD_CLK_DIVISOR(x) ((x) << 8) -#define LCD_RASTER_MODE 0x01 - -/* LCD Raster Control Register */ -#define LCD_PALETTE_LOAD_MODE(x) ((x) << 20) -#define PALETTE_AND_DATA 0x00 -#define PALETTE_ONLY 0x01 -#define DATA_ONLY 0x02 - -#define LCD_MONO_8BIT_MODE BIT(9) -#define LCD_RASTER_ORDER BIT(8) -#define LCD_TFT_MODE BIT(7) -#define LCD_V1_UNDERFLOW_INT_ENA BIT(6) -#define LCD_V2_UNDERFLOW_INT_ENA BIT(5) -#define LCD_V1_PL_INT_ENA BIT(4) -#define LCD_V2_PL_INT_ENA BIT(6) -#define LCD_MONOCHROME_MODE BIT(1) -#define LCD_RASTER_ENABLE BIT(0) -#define LCD_TFT_ALT_ENABLE BIT(23) -#define LCD_STN_565_ENABLE BIT(24) -#define LCD_V2_DMA_CLK_EN BIT(2) -#define LCD_V2_LIDD_CLK_EN BIT(1) -#define LCD_V2_CORE_CLK_EN BIT(0) -#define LCD_V2_LPP_B10 26 -#define LCD_V2_TFT_24BPP_MODE BIT(25) -#define LCD_V2_TFT_24BPP_UNPACK BIT(26) - -/* LCD Raster Timing 2 Register */ -#define LCD_AC_BIAS_TRANSITIONS_PER_INT(x) ((x) << 16) -#define LCD_AC_BIAS_FREQUENCY(x) ((x) << 8) -#define LCD_SYNC_CTRL BIT(25) -#define LCD_SYNC_EDGE BIT(24) -#define LCD_INVERT_PIXEL_CLOCK BIT(22) -#define LCD_INVERT_LINE_CLOCK BIT(21) -#define LCD_INVERT_FRAME_CLOCK BIT(20) - -/* LCD Block */ -#define LCD_PID_REG 0x0 -#define LCD_CTRL_REG 0x4 -#define LCD_STAT_REG 0x8 -#define LCD_RASTER_CTRL_REG 0x28 -#define LCD_RASTER_TIMING_0_REG 0x2C -#define LCD_RASTER_TIMING_1_REG 0x30 -#define LCD_RASTER_TIMING_2_REG 0x34 -#define LCD_DMA_CTRL_REG 0x40 -#define LCD_DMA_FRM_BUF_BASE_ADDR_0_REG 0x44 -#define LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG 0x48 -#define LCD_DMA_FRM_BUF_BASE_ADDR_1_REG 0x4C -#define LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG 0x50 - -/* Interrupt Registers available only in Version 2 */ -#define LCD_RAW_STAT_REG 0x58 -#define LCD_MASKED_STAT_REG 0x5c -#define LCD_INT_ENABLE_SET_REG 0x60 -#define LCD_INT_ENABLE_CLR_REG 0x64 -#define LCD_END_OF_INT_IND_REG 0x68 - -/* Clock registers available only on Version 2 */ -#define LCD_CLK_ENABLE_REG 0x6c -#define LCD_CLK_RESET_REG 0x70 -#define LCD_CLK_MAIN_RESET BIT(3) - -#define LCD_NUM_BUFFERS 2 - -#define PALETTE_SIZE 256 - -#define CLK_MIN_DIV 2 -#define CLK_MAX_DIV 255 - -static void __iomem *da8xx_fb_reg_base; -static unsigned int lcd_revision; -static irq_handler_t lcdc_irq_handler; -static wait_queue_head_t frame_done_wq; -static int frame_done_flag; - -static unsigned int lcdc_read(unsigned int addr) -{ - return (unsigned int)__raw_readl(da8xx_fb_reg_base + (addr)); -} - -static void lcdc_write(unsigned int val, unsigned int addr) -{ - __raw_writel(val, da8xx_fb_reg_base + (addr)); -} - -struct da8xx_fb_par { - struct device *dev; - dma_addr_t p_palette_base; - unsigned char *v_palette_base; - dma_addr_t vram_phys; - unsigned long vram_size; - void *vram_virt; - unsigned int dma_start; - unsigned int dma_end; - struct clk *lcdc_clk; - int irq; - unsigned int palette_sz; - int blank; - wait_queue_head_t vsync_wait; - int vsync_flag; - int vsync_timeout; - spinlock_t lock_for_chan_update; - - /* - * LCDC has 2 ping pong DMA channels, channel 0 - * and channel 1. - */ - unsigned int which_dma_channel_done; -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; -#endif - unsigned int lcdc_clk_rate; - struct regulator *lcd_supply; - u32 pseudo_palette[16]; - struct fb_videomode mode; - struct lcd_ctrl_config cfg; -}; - -static struct fb_var_screeninfo da8xx_fb_var; - -static struct fb_fix_screeninfo da8xx_fb_fix = { - .id = "DA8xx FB Drv", - .type = FB_TYPE_PACKED_PIXELS, - .type_aux = 0, - .visual = FB_VISUAL_PSEUDOCOLOR, - .xpanstep = 0, - .ypanstep = 1, - .ywrapstep = 0, - .accel = FB_ACCEL_NONE -}; - -static struct fb_videomode known_lcd_panels[] = { - /* Sharp LCD035Q3DG01 */ - [0] = { - .name = "Sharp_LCD035Q3DG01", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(4607), - .left_margin = 6, - .right_margin = 8, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 0, - .vsync_len = 0, - .sync = FB_SYNC_CLK_INVERT, - }, - /* Sharp LK043T1DG01 */ - [1] = { - .name = "Sharp_LK043T1DG01", - .xres = 480, - .yres = 272, - .pixclock = KHZ2PICOS(7833), - .left_margin = 2, - .right_margin = 2, - .upper_margin = 2, - .lower_margin = 2, - .hsync_len = 41, - .vsync_len = 10, - .sync = 0, - .flag = 0, - }, - [2] = { - /* Hitachi SP10Q010 */ - .name = "SP10Q010", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(7833), - .left_margin = 10, - .right_margin = 10, - .upper_margin = 10, - .lower_margin = 10, - .hsync_len = 10, - .vsync_len = 10, - .sync = 0, - .flag = 0, - }, - [3] = { - /* Densitron 84-0023-001T */ - .name = "Densitron_84-0023-001T", - .xres = 320, - .yres = 240, - .pixclock = KHZ2PICOS(6400), - .left_margin = 0, - .right_margin = 0, - .upper_margin = 0, - .lower_margin = 0, - .hsync_len = 30, - .vsync_len = 3, - .sync = 0, - }, -}; - -static bool da8xx_fb_is_raster_enabled(void) -{ - return !!(lcdc_read(LCD_RASTER_CTRL_REG) & LCD_RASTER_ENABLE); -} - -/* Enable the Raster Engine of the LCD Controller */ -static void lcd_enable_raster(void) -{ - u32 reg; - - /* Put LCDC in reset for several cycles */ - if (lcd_revision == LCD_VERSION_2) - /* Write 1 to reset LCDC */ - lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); - mdelay(1); - - /* Bring LCDC out of reset */ - if (lcd_revision == LCD_VERSION_2) - lcdc_write(0, LCD_CLK_RESET_REG); - mdelay(1); - - /* Above reset sequence doesnot reset register context */ - reg = lcdc_read(LCD_RASTER_CTRL_REG); - if (!(reg & LCD_RASTER_ENABLE)) - lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); -} - -/* Disable the Raster Engine of the LCD Controller */ -static void lcd_disable_raster(enum da8xx_frame_complete wait_for_frame_done) -{ - u32 reg; - int ret; - - reg = lcdc_read(LCD_RASTER_CTRL_REG); - if (reg & LCD_RASTER_ENABLE) - lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG); - else - /* return if already disabled */ - return; - - if ((wait_for_frame_done == DA8XX_FRAME_WAIT) && - (lcd_revision == LCD_VERSION_2)) { - frame_done_flag = 0; - ret = wait_event_interruptible_timeout(frame_done_wq, - frame_done_flag != 0, - msecs_to_jiffies(50)); - if (ret == 0) - pr_err("LCD Controller timed out\n"); - } -} - -static void lcd_blit(int load_mode, struct da8xx_fb_par *par) -{ - u32 start; - u32 end; - u32 reg_ras; - u32 reg_dma; - u32 reg_int; - - /* init reg to clear PLM (loading mode) fields */ - reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); - reg_ras &= ~(3 << 20); - - reg_dma = lcdc_read(LCD_DMA_CTRL_REG); - - if (load_mode == LOAD_DATA) { - start = par->dma_start; - end = par->dma_end; - - reg_ras |= LCD_PALETTE_LOAD_MODE(DATA_ONLY); - if (lcd_revision == LCD_VERSION_1) { - reg_dma |= LCD_V1_END_OF_FRAME_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_END_OF_FRAME0_INT_ENA | - LCD_V2_END_OF_FRAME1_INT_ENA | - LCD_FRAME_DONE | LCD_SYNC_LOST; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - reg_dma |= LCD_DUAL_FRAME_BUFFER_ENABLE; - - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - } else if (load_mode == LOAD_PALETTE) { - start = par->p_palette_base; - end = start + par->palette_sz - 1; - - reg_ras |= LCD_PALETTE_LOAD_MODE(PALETTE_ONLY); - - if (lcd_revision == LCD_VERSION_1) { - reg_ras |= LCD_V1_PL_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_PL_INT_ENA; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - } - - lcdc_write(reg_dma, LCD_DMA_CTRL_REG); - lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); - - /* - * The Raster enable bit must be set after all other control fields are - * set. - */ - lcd_enable_raster(); -} - -/* Configure the Burst Size and fifo threhold of DMA */ -static int lcd_cfg_dma(int burst_size, int fifo_th) -{ - u32 reg; - - reg = lcdc_read(LCD_DMA_CTRL_REG) & 0x00000001; - switch (burst_size) { - case 1: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_1); - break; - case 2: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_2); - break; - case 4: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_4); - break; - case 8: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_8); - break; - case 16: - default: - reg |= LCD_DMA_BURST_SIZE(LCD_DMA_BURST_16); - break; - } - - reg |= (fifo_th << 8); - - lcdc_write(reg, LCD_DMA_CTRL_REG); - - return 0; -} - -static void lcd_cfg_ac_bias(int period, int transitions_per_int) -{ - u32 reg; - - /* Set the AC Bias Period and Number of Transisitons per Interrupt */ - reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & 0xFFF00000; - reg |= LCD_AC_BIAS_FREQUENCY(period) | - LCD_AC_BIAS_TRANSITIONS_PER_INT(transitions_per_int); - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); -} - -static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0x3ff; - reg |= (((back_porch-1) & 0xff) << 24) - | (((front_porch-1) & 0xff) << 16) - | (((pulse_width-1) & 0x3f) << 10); - lcdc_write(reg, LCD_RASTER_TIMING_0_REG); - - /* - * LCDC Version 2 adds some extra bits that increase the allowable - * size of the horizontal timing registers. - * remember that the registers use 0 to represent 1 so all values - * that get set into register need to be decremented by 1 - */ - if (lcd_revision == LCD_VERSION_2) { - /* Mask off the bits we want to change */ - reg = lcdc_read(LCD_RASTER_TIMING_2_REG) & ~0x780000ff; - reg |= ((front_porch-1) & 0x300) >> 8; - reg |= ((back_porch-1) & 0x300) >> 4; - reg |= ((pulse_width-1) & 0x3c0) << 21; - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - } -} - -static void lcd_cfg_vertical_sync(int back_porch, int pulse_width, - int front_porch) -{ - u32 reg; - - reg = lcdc_read(LCD_RASTER_TIMING_1_REG) & 0x3ff; - reg |= ((back_porch & 0xff) << 24) - | ((front_porch & 0xff) << 16) - | (((pulse_width-1) & 0x3f) << 10); - lcdc_write(reg, LCD_RASTER_TIMING_1_REG); -} - -static int lcd_cfg_display(const struct lcd_ctrl_config *cfg, - struct fb_videomode *panel) -{ - u32 reg; - u32 reg_int; - - reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(LCD_TFT_MODE | - LCD_MONO_8BIT_MODE | - LCD_MONOCHROME_MODE); - - switch (cfg->panel_shade) { - case MONOCHROME: - reg |= LCD_MONOCHROME_MODE; - if (cfg->mono_8bit_mode) - reg |= LCD_MONO_8BIT_MODE; - break; - case COLOR_ACTIVE: - reg |= LCD_TFT_MODE; - if (cfg->tft_alt_mode) - reg |= LCD_TFT_ALT_ENABLE; - break; - - case COLOR_PASSIVE: - /* AC bias applicable only for Pasive panels */ - lcd_cfg_ac_bias(cfg->ac_bias, cfg->ac_bias_intrpt); - if (cfg->bpp == 12 && cfg->stn_565_mode) - reg |= LCD_STN_565_ENABLE; - break; - - default: - return -EINVAL; - } - - /* enable additional interrupts here */ - if (lcd_revision == LCD_VERSION_1) { - reg |= LCD_V1_UNDERFLOW_INT_ENA; - } else { - reg_int = lcdc_read(LCD_INT_ENABLE_SET_REG) | - LCD_V2_UNDERFLOW_INT_ENA; - lcdc_write(reg_int, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(reg, LCD_RASTER_CTRL_REG); - - reg = lcdc_read(LCD_RASTER_TIMING_2_REG); - - reg |= LCD_SYNC_CTRL; - - if (cfg->sync_edge) - reg |= LCD_SYNC_EDGE; - else - reg &= ~LCD_SYNC_EDGE; - - if ((panel->sync & FB_SYNC_HOR_HIGH_ACT) == 0) - reg |= LCD_INVERT_LINE_CLOCK; - else - reg &= ~LCD_INVERT_LINE_CLOCK; - - if ((panel->sync & FB_SYNC_VERT_HIGH_ACT) == 0) - reg |= LCD_INVERT_FRAME_CLOCK; - else - reg &= ~LCD_INVERT_FRAME_CLOCK; - - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - - return 0; -} - -static int lcd_cfg_frame_buffer(struct da8xx_fb_par *par, u32 width, u32 height, - u32 bpp, u32 raster_order) -{ - u32 reg; - - if (bpp > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - /* Set the Panel Width */ - /* Pixels per line = (PPL + 1)*16 */ - if (lcd_revision == LCD_VERSION_1) { - /* - * 0x3F in bits 4..9 gives max horizontal resolution = 1024 - * pixels. - */ - width &= 0x3f0; - } else { - /* - * 0x7F in bits 4..10 gives max horizontal resolution = 2048 - * pixels. - */ - width &= 0x7f0; - } - - reg = lcdc_read(LCD_RASTER_TIMING_0_REG); - reg &= 0xfffffc00; - if (lcd_revision == LCD_VERSION_1) { - reg |= ((width >> 4) - 1) << 4; - } else { - width = (width >> 4) - 1; - reg |= ((width & 0x3f) << 4) | ((width & 0x40) >> 3); - } - lcdc_write(reg, LCD_RASTER_TIMING_0_REG); - - /* Set the Panel Height */ - /* Set bits 9:0 of Lines Per Pixel */ - reg = lcdc_read(LCD_RASTER_TIMING_1_REG); - reg = ((height - 1) & 0x3ff) | (reg & 0xfffffc00); - lcdc_write(reg, LCD_RASTER_TIMING_1_REG); - - /* Set bit 10 of Lines Per Pixel */ - if (lcd_revision == LCD_VERSION_2) { - reg = lcdc_read(LCD_RASTER_TIMING_2_REG); - reg |= ((height - 1) & 0x400) << 16; - lcdc_write(reg, LCD_RASTER_TIMING_2_REG); - } - - /* Set the Raster Order of the Frame Buffer */ - reg = lcdc_read(LCD_RASTER_CTRL_REG) & ~(1 << 8); - if (raster_order) - reg |= LCD_RASTER_ORDER; - - par->palette_sz = 16 * 2; - - switch (bpp) { - case 1: - case 2: - case 4: - case 16: - break; - case 24: - reg |= LCD_V2_TFT_24BPP_MODE; - break; - case 32: - reg |= LCD_V2_TFT_24BPP_MODE; - reg |= LCD_V2_TFT_24BPP_UNPACK; - break; - case 8: - par->palette_sz = 256 * 2; - break; - - default: - return -EINVAL; - } - - lcdc_write(reg, LCD_RASTER_CTRL_REG); - - return 0; -} - -#define CNVT_TOHW(val, width) ((((val) << (width)) + 0x7FFF - (val)) >> 16) -static int fb_setcolreg(unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - unsigned short *palette = (unsigned short *) par->v_palette_base; - u_short pal; - int update_hw = 0; - - if (regno > 255) - return 1; - - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) - return 1; - - if (info->var.bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - red = CNVT_TOHW(red, info->var.red.length); - green = CNVT_TOHW(green, info->var.green.length); - blue = CNVT_TOHW(blue, info->var.blue.length); - break; - case FB_VISUAL_PSEUDOCOLOR: - switch (info->var.bits_per_pixel) { - case 4: - if (regno > 15) - return -EINVAL; - - if (info->var.grayscale) { - pal = regno; - } else { - red >>= 4; - green >>= 8; - blue >>= 12; - - pal = red & 0x0f00; - pal |= green & 0x00f0; - pal |= blue & 0x000f; - } - if (regno == 0) - pal |= 0x2000; - palette[regno] = pal; - break; - - case 8: - red >>= 4; - green >>= 8; - blue >>= 12; - - pal = (red & 0x0f00); - pal |= (green & 0x00f0); - pal |= (blue & 0x000f); - - if (palette[regno] != pal) { - update_hw = 1; - palette[regno] = pal; - } - break; - } - break; - } - - /* Truecolor has hardware independent palette */ - if (info->fix.visual == FB_VISUAL_TRUECOLOR) { - u32 v; - - if (regno > 15) - return -EINVAL; - - v = (red << info->var.red.offset) | - (green << info->var.green.offset) | - (blue << info->var.blue.offset); - - ((u32 *) (info->pseudo_palette))[regno] = v; - if (palette[0] != 0x4000) { - update_hw = 1; - palette[0] = 0x4000; - } - } - - /* Update the palette in the h/w as needed. */ - if (update_hw) - lcd_blit(LOAD_PALETTE, par); - - return 0; -} -#undef CNVT_TOHW - -static void da8xx_fb_lcd_reset(void) -{ - /* DMA has to be disabled */ - lcdc_write(0, LCD_DMA_CTRL_REG); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - if (lcd_revision == LCD_VERSION_2) { - lcdc_write(0, LCD_INT_ENABLE_SET_REG); - /* Write 1 to reset */ - lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG); - lcdc_write(0, LCD_CLK_RESET_REG); - } -} - -static int da8xx_fb_config_clk_divider(struct da8xx_fb_par *par, - unsigned lcdc_clk_div, - unsigned lcdc_clk_rate) -{ - int ret; - - if (par->lcdc_clk_rate != lcdc_clk_rate) { - ret = clk_set_rate(par->lcdc_clk, lcdc_clk_rate); - if (ret) { - dev_err(par->dev, - "unable to set clock rate at %u\n", - lcdc_clk_rate); - return ret; - } - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - } - - /* Configure the LCD clock divisor. */ - lcdc_write(LCD_CLK_DIVISOR(lcdc_clk_div) | - (LCD_RASTER_MODE & 0x1), LCD_CTRL_REG); - - if (lcd_revision == LCD_VERSION_2) - lcdc_write(LCD_V2_DMA_CLK_EN | LCD_V2_LIDD_CLK_EN | - LCD_V2_CORE_CLK_EN, LCD_CLK_ENABLE_REG); - - return 0; -} - -static unsigned int da8xx_fb_calc_clk_divider(struct da8xx_fb_par *par, - unsigned pixclock, - unsigned *lcdc_clk_rate) -{ - unsigned lcdc_clk_div; - - pixclock = PICOS2KHZ(pixclock) * 1000; - - *lcdc_clk_rate = par->lcdc_clk_rate; - - if (pixclock < (*lcdc_clk_rate / CLK_MAX_DIV)) { - *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, - pixclock * CLK_MAX_DIV); - lcdc_clk_div = CLK_MAX_DIV; - } else if (pixclock > (*lcdc_clk_rate / CLK_MIN_DIV)) { - *lcdc_clk_rate = clk_round_rate(par->lcdc_clk, - pixclock * CLK_MIN_DIV); - lcdc_clk_div = CLK_MIN_DIV; - } else { - lcdc_clk_div = *lcdc_clk_rate / pixclock; - } - - return lcdc_clk_div; -} - -static int da8xx_fb_calc_config_clk_divider(struct da8xx_fb_par *par, - struct fb_videomode *mode) -{ - unsigned lcdc_clk_rate; - unsigned lcdc_clk_div = da8xx_fb_calc_clk_divider(par, mode->pixclock, - &lcdc_clk_rate); - - return da8xx_fb_config_clk_divider(par, lcdc_clk_div, lcdc_clk_rate); -} - -static unsigned da8xx_fb_round_clk(struct da8xx_fb_par *par, - unsigned pixclock) -{ - unsigned lcdc_clk_div, lcdc_clk_rate; - - lcdc_clk_div = da8xx_fb_calc_clk_divider(par, pixclock, &lcdc_clk_rate); - return KHZ2PICOS(lcdc_clk_rate / (1000 * lcdc_clk_div)); -} - -static int lcd_init(struct da8xx_fb_par *par, const struct lcd_ctrl_config *cfg, - struct fb_videomode *panel) -{ - u32 bpp; - int ret = 0; - - ret = da8xx_fb_calc_config_clk_divider(par, panel); - if (ret) { - dev_err(par->dev, "unable to configure clock\n"); - return ret; - } - - if (panel->sync & FB_SYNC_CLK_INVERT) - lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) | - LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); - else - lcdc_write((lcdc_read(LCD_RASTER_TIMING_2_REG) & - ~LCD_INVERT_PIXEL_CLOCK), LCD_RASTER_TIMING_2_REG); - - /* Configure the DMA burst size and fifo threshold. */ - ret = lcd_cfg_dma(cfg->dma_burst_sz, cfg->fifo_th); - if (ret < 0) - return ret; - - /* Configure the vertical and horizontal sync properties. */ - lcd_cfg_vertical_sync(panel->upper_margin, panel->vsync_len, - panel->lower_margin); - lcd_cfg_horizontal_sync(panel->left_margin, panel->hsync_len, - panel->right_margin); - - /* Configure for disply */ - ret = lcd_cfg_display(cfg, panel); - if (ret < 0) - return ret; - - bpp = cfg->bpp; - - if (bpp == 12) - bpp = 16; - ret = lcd_cfg_frame_buffer(par, (unsigned int)panel->xres, - (unsigned int)panel->yres, bpp, - cfg->raster_order); - if (ret < 0) - return ret; - - /* Configure FDD */ - lcdc_write((lcdc_read(LCD_RASTER_CTRL_REG) & 0xfff00fff) | - (cfg->fdd << 12), LCD_RASTER_CTRL_REG); - - return 0; -} - -/* IRQ handler for version 2 of LCDC */ -static irqreturn_t lcdc_irq_handler_rev02(int irq, void *arg) -{ - struct da8xx_fb_par *par = arg; - u32 stat = lcdc_read(LCD_MASKED_STAT_REG); - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - lcdc_write(stat, LCD_MASKED_STAT_REG); - lcd_enable_raster(); - } else if (stat & LCD_PL_LOAD_DONE) { - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - - lcdc_write(stat, LCD_MASKED_STAT_REG); - - /* Disable PL completion interrupt */ - lcdc_write(LCD_V2_PL_INT_ENA, LCD_INT_ENABLE_CLR_REG); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - } else { - lcdc_write(stat, LCD_MASKED_STAT_REG); - - if (stat & LCD_END_OF_FRAME0) { - par->which_dma_channel_done = 0; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - if (stat & LCD_END_OF_FRAME1) { - par->which_dma_channel_done = 1; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - /* Set only when controller is disabled and at the end of - * active frame - */ - if (stat & BIT(0)) { - frame_done_flag = 1; - wake_up_interruptible(&frame_done_wq); - } - } - - lcdc_write(0, LCD_END_OF_INT_IND_REG); - return IRQ_HANDLED; -} - -/* IRQ handler for version 1 LCDC */ -static irqreturn_t lcdc_irq_handler_rev01(int irq, void *arg) -{ - struct da8xx_fb_par *par = arg; - u32 stat = lcdc_read(LCD_STAT_REG); - u32 reg_ras; - - if ((stat & LCD_SYNC_LOST) && (stat & LCD_FIFO_UNDERFLOW)) { - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - lcdc_write(stat, LCD_STAT_REG); - lcd_enable_raster(); - } else if (stat & LCD_PL_LOAD_DONE) { - /* - * Must disable raster before changing state of any control bit. - * And also must be disabled before clearing the PL loading - * interrupt via the following write to the status register. If - * this is done after then one gets multiple PL done interrupts. - */ - lcd_disable_raster(DA8XX_FRAME_NOWAIT); - - lcdc_write(stat, LCD_STAT_REG); - - /* Disable PL completion inerrupt */ - reg_ras = lcdc_read(LCD_RASTER_CTRL_REG); - reg_ras &= ~LCD_V1_PL_INT_ENA; - lcdc_write(reg_ras, LCD_RASTER_CTRL_REG); - - /* Setup and start data loading mode */ - lcd_blit(LOAD_DATA, par); - } else { - lcdc_write(stat, LCD_STAT_REG); - - if (stat & LCD_END_OF_FRAME0) { - par->which_dma_channel_done = 0; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - - if (stat & LCD_END_OF_FRAME1) { - par->which_dma_channel_done = 1; - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - par->vsync_flag = 1; - wake_up_interruptible(&par->vsync_wait); - } - } - - return IRQ_HANDLED; -} - -static int fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - int err = 0; - struct da8xx_fb_par *par = info->par; - int bpp = var->bits_per_pixel >> 3; - unsigned long line_size = var->xres_virtual * bpp; - - if (var->bits_per_pixel > 16 && lcd_revision == LCD_VERSION_1) - return -EINVAL; - - switch (var->bits_per_pixel) { - case 1: - case 8: - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = 0; - break; - case 4: - var->red.offset = 0; - var->red.length = 4; - var->green.offset = 0; - var->green.length = 4; - var->blue.offset = 0; - var->blue.length = 4; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = FB_NONSTD_REV_PIX_IN_B; - break; - case 16: /* RGB 565 */ - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - var->transp.offset = 0; - var->transp.length = 0; - var->nonstd = 0; - break; - case 24: - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->nonstd = 0; - break; - case 32: - var->transp.offset = 24; - var->transp.length = 8; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - var->nonstd = 0; - break; - default: - err = -EINVAL; - } - - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - var->transp.msb_right = 0; - - if (line_size * var->yres_virtual > par->vram_size) - var->yres_virtual = par->vram_size / line_size; - - if (var->yres > var->yres_virtual) - var->yres = var->yres_virtual; - - if (var->xres > var->xres_virtual) - var->xres = var->xres_virtual; - - if (var->xres + var->xoffset > var->xres_virtual) - var->xoffset = var->xres_virtual - var->xres; - if (var->yres + var->yoffset > var->yres_virtual) - var->yoffset = var->yres_virtual - var->yres; - - var->pixclock = da8xx_fb_round_clk(par, var->pixclock); - - return err; -} - -#ifdef CONFIG_CPU_FREQ -static int lcd_da8xx_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct da8xx_fb_par *par; - - par = container_of(nb, struct da8xx_fb_par, freq_transition); - if (val == CPUFREQ_POSTCHANGE) { - if (par->lcdc_clk_rate != clk_get_rate(par->lcdc_clk)) { - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - lcd_disable_raster(DA8XX_FRAME_WAIT); - da8xx_fb_calc_config_clk_divider(par, &par->mode); - if (par->blank == FB_BLANK_UNBLANK) - lcd_enable_raster(); - } - } - - return 0; -} - -static int lcd_da8xx_cpufreq_register(struct da8xx_fb_par *par) -{ - par->freq_transition.notifier_call = lcd_da8xx_cpufreq_transition; - - return cpufreq_register_notifier(&par->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static void lcd_da8xx_cpufreq_deregister(struct da8xx_fb_par *par) -{ - cpufreq_unregister_notifier(&par->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} -#endif - -static void fb_remove(struct platform_device *dev) -{ - struct fb_info *info = platform_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - -#ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); -#endif - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - dev_warn(&dev->dev, "Failed to disable regulator (%pe)\n", - ERR_PTR(ret)); - } - - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcdc_write(0, LCD_RASTER_CTRL_REG); - - /* disable DMA */ - lcdc_write(0, LCD_DMA_CTRL_REG); - - unregister_framebuffer(info); - fb_dealloc_cmap(&info->cmap); - pm_runtime_put_sync(&dev->dev); - pm_runtime_disable(&dev->dev); - framebuffer_release(info); -} - -/* - * Function to wait for vertical sync which for this LCD peripheral - * translates into waiting for the current raster frame to complete. - */ -static int fb_wait_for_vsync(struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret; - - /* - * Set flag to 0 and wait for isr to set to 1. It would seem there is a - * race condition here where the ISR could have occurred just before or - * just after this set. But since we are just coarsely waiting for - * a frame to complete then that's OK. i.e. if the frame completed - * just before this code executed then we have to wait another full - * frame time but there is no way to avoid such a situation. On the - * other hand if the frame completed just after then we don't need - * to wait long at all. Either way we are guaranteed to return to the - * user immediately after a frame completion which is all that is - * required. - */ - par->vsync_flag = 0; - ret = wait_event_interruptible_timeout(par->vsync_wait, - par->vsync_flag != 0, - par->vsync_timeout); - if (ret < 0) - return ret; - if (ret == 0) - return -ETIMEDOUT; - - return 0; -} - -static int fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - struct lcd_sync_arg sync_arg; - - switch (cmd) { - case FBIOGET_CONTRAST: - case FBIOPUT_CONTRAST: - case FBIGET_BRIGHTNESS: - case FBIPUT_BRIGHTNESS: - case FBIGET_COLOR: - case FBIPUT_COLOR: - return -ENOTTY; - case FBIPUT_HSYNC: - if (copy_from_user(&sync_arg, (char *)arg, - sizeof(struct lcd_sync_arg))) - return -EFAULT; - lcd_cfg_horizontal_sync(sync_arg.back_porch, - sync_arg.pulse_width, - sync_arg.front_porch); - break; - case FBIPUT_VSYNC: - if (copy_from_user(&sync_arg, (char *)arg, - sizeof(struct lcd_sync_arg))) - return -EFAULT; - lcd_cfg_vertical_sync(sync_arg.back_porch, - sync_arg.pulse_width, - sync_arg.front_porch); - break; - case FBIO_WAITFORVSYNC: - return fb_wait_for_vsync(info); - default: - return -EINVAL; - } - return 0; -} - -static int cfb_blank(int blank, struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret = 0; - - if (par->blank == blank) - return 0; - - par->blank = blank; - switch (blank) { - case FB_BLANK_UNBLANK: - lcd_enable_raster(); - - if (par->lcd_supply) { - ret = regulator_enable(par->lcd_supply); - if (ret) - return ret; - } - break; - case FB_BLANK_NORMAL: - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - return ret; - } - - lcd_disable_raster(DA8XX_FRAME_WAIT); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -/* - * Set new x,y offsets in the virtual display for the visible area and switch - * to the new mode. - */ -static int da8xx_pan_display(struct fb_var_screeninfo *var, - struct fb_info *fbi) -{ - int ret = 0; - struct fb_var_screeninfo new_var; - struct da8xx_fb_par *par = fbi->par; - struct fb_fix_screeninfo *fix = &fbi->fix; - unsigned int end; - unsigned int start; - unsigned long irq_flags; - - if (var->xoffset != fbi->var.xoffset || - var->yoffset != fbi->var.yoffset) { - memcpy(&new_var, &fbi->var, sizeof(new_var)); - new_var.xoffset = var->xoffset; - new_var.yoffset = var->yoffset; - if (fb_check_var(&new_var, fbi)) - ret = -EINVAL; - else { - memcpy(&fbi->var, &new_var, sizeof(new_var)); - - start = fix->smem_start + - new_var.yoffset * fix->line_length + - new_var.xoffset * fbi->var.bits_per_pixel / 8; - end = start + fbi->var.yres * fix->line_length - 1; - par->dma_start = start; - par->dma_end = end; - spin_lock_irqsave(&par->lock_for_chan_update, - irq_flags); - if (par->which_dma_channel_done == 0) { - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - } else if (par->which_dma_channel_done == 1) { - lcdc_write(par->dma_start, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - } - spin_unlock_irqrestore(&par->lock_for_chan_update, - irq_flags); - } - } - - return ret; -} - -static int da8xxfb_set_par(struct fb_info *info) -{ - struct da8xx_fb_par *par = info->par; - int ret; - bool raster = da8xx_fb_is_raster_enabled(); - - if (raster) - lcd_disable_raster(DA8XX_FRAME_WAIT); - - fb_var_to_videomode(&par->mode, &info->var); - - par->cfg.bpp = info->var.bits_per_pixel; - - info->fix.visual = (par->cfg.bpp <= 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - info->fix.line_length = (par->mode.xres * par->cfg.bpp) / 8; - - ret = lcd_init(par, &par->cfg, &par->mode); - if (ret < 0) { - dev_err(par->dev, "lcd init failed\n"); - return ret; - } - - par->dma_start = info->fix.smem_start + - info->var.yoffset * info->fix.line_length + - info->var.xoffset * info->var.bits_per_pixel / 8; - par->dma_end = par->dma_start + - info->var.yres * info->fix.line_length - 1; - - lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(par->dma_start, LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(par->dma_end, LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - - if (raster) - lcd_enable_raster(); - - return 0; -} - -static const struct fb_ops da8xx_fb_ops = { - .owner = THIS_MODULE, - FB_DEFAULT_IOMEM_OPS, - .fb_check_var = fb_check_var, - .fb_set_par = da8xxfb_set_par, - .fb_setcolreg = fb_setcolreg, - .fb_pan_display = da8xx_pan_display, - .fb_ioctl = fb_ioctl, - .fb_blank = cfb_blank, -}; - -static struct fb_videomode *da8xx_fb_get_videomode(struct platform_device *dev) -{ - struct da8xx_lcdc_platform_data *fb_pdata = dev_get_platdata(&dev->dev); - struct fb_videomode *lcdc_info; - int i; - - for (i = 0, lcdc_info = known_lcd_panels; - i < ARRAY_SIZE(known_lcd_panels); i++, lcdc_info++) { - if (strcmp(fb_pdata->type, lcdc_info->name) == 0) - break; - } - - if (i == ARRAY_SIZE(known_lcd_panels)) { - dev_err(&dev->dev, "no panel found\n"); - return NULL; - } - dev_info(&dev->dev, "found %s panel\n", lcdc_info->name); - - return lcdc_info; -} - -static int fb_probe(struct platform_device *device) -{ - struct da8xx_lcdc_platform_data *fb_pdata = - dev_get_platdata(&device->dev); - struct lcd_ctrl_config *lcd_cfg; - struct fb_videomode *lcdc_info; - struct fb_info *da8xx_fb_info; - struct da8xx_fb_par *par; - struct clk *tmp_lcdc_clk; - int ret; - unsigned long ulcm; - - if (fb_pdata == NULL) { - dev_err(&device->dev, "Can not get platform data\n"); - return -ENOENT; - } - - lcdc_info = da8xx_fb_get_videomode(device); - if (lcdc_info == NULL) - return -ENODEV; - - da8xx_fb_reg_base = devm_platform_ioremap_resource(device, 0); - if (IS_ERR(da8xx_fb_reg_base)) - return PTR_ERR(da8xx_fb_reg_base); - - tmp_lcdc_clk = devm_clk_get(&device->dev, "fck"); - if (IS_ERR(tmp_lcdc_clk)) - return dev_err_probe(&device->dev, PTR_ERR(tmp_lcdc_clk), - "Can not get device clock\n"); - - pm_runtime_enable(&device->dev); - pm_runtime_get_sync(&device->dev); - - /* Determine LCD IP Version */ - switch (lcdc_read(LCD_PID_REG)) { - case 0x4C100102: - lcd_revision = LCD_VERSION_1; - break; - case 0x4F200800: - case 0x4F201000: - lcd_revision = LCD_VERSION_2; - break; - default: - dev_warn(&device->dev, "Unknown PID Reg value 0x%x, " - "defaulting to LCD revision 1\n", - lcdc_read(LCD_PID_REG)); - lcd_revision = LCD_VERSION_1; - break; - } - - lcd_cfg = (struct lcd_ctrl_config *)fb_pdata->controller_data; - - if (!lcd_cfg) { - ret = -EINVAL; - goto err_pm_runtime_disable; - } - - da8xx_fb_info = framebuffer_alloc(sizeof(struct da8xx_fb_par), - &device->dev); - if (!da8xx_fb_info) { - ret = -ENOMEM; - goto err_pm_runtime_disable; - } - - par = da8xx_fb_info->par; - par->dev = &device->dev; - par->lcdc_clk = tmp_lcdc_clk; - par->lcdc_clk_rate = clk_get_rate(par->lcdc_clk); - - par->lcd_supply = devm_regulator_get_optional(&device->dev, "lcd"); - if (IS_ERR(par->lcd_supply)) { - if (PTR_ERR(par->lcd_supply) == -EPROBE_DEFER) { - ret = -EPROBE_DEFER; - goto err_release_fb; - } - - par->lcd_supply = NULL; - } else { - ret = regulator_enable(par->lcd_supply); - if (ret) - goto err_release_fb; - } - - fb_videomode_to_var(&da8xx_fb_var, lcdc_info); - par->cfg = *lcd_cfg; - - da8xx_fb_lcd_reset(); - - /* allocate frame buffer */ - par->vram_size = lcdc_info->xres * lcdc_info->yres * lcd_cfg->bpp; - ulcm = lcm((lcdc_info->xres * lcd_cfg->bpp)/8, PAGE_SIZE); - par->vram_size = roundup(par->vram_size/8, ulcm); - par->vram_size = par->vram_size * LCD_NUM_BUFFERS; - - par->vram_virt = dmam_alloc_coherent(par->dev, - par->vram_size, - &par->vram_phys, - GFP_KERNEL | GFP_DMA); - if (!par->vram_virt) { - dev_err(&device->dev, - "GLCD: kmalloc for frame buffer failed\n"); - ret = -EINVAL; - goto err_disable_reg; - } - - da8xx_fb_info->screen_base = (char __iomem *) par->vram_virt; - da8xx_fb_fix.smem_start = par->vram_phys; - da8xx_fb_fix.smem_len = par->vram_size; - da8xx_fb_fix.line_length = (lcdc_info->xres * lcd_cfg->bpp) / 8; - - par->dma_start = par->vram_phys; - par->dma_end = par->dma_start + lcdc_info->yres * - da8xx_fb_fix.line_length - 1; - - /* allocate palette buffer */ - par->v_palette_base = dmam_alloc_coherent(par->dev, PALETTE_SIZE, - &par->p_palette_base, - GFP_KERNEL | GFP_DMA); - if (!par->v_palette_base) { - dev_err(&device->dev, - "GLCD: kmalloc for palette buffer failed\n"); - ret = -EINVAL; - goto err_release_fb; - } - - par->irq = platform_get_irq(device, 0); - if (par->irq < 0) { - ret = -ENOENT; - goto err_release_fb; - } - - da8xx_fb_var.grayscale = - lcd_cfg->panel_shade == MONOCHROME ? 1 : 0; - da8xx_fb_var.bits_per_pixel = lcd_cfg->bpp; - - /* Initialize fbinfo */ - da8xx_fb_info->fix = da8xx_fb_fix; - da8xx_fb_info->var = da8xx_fb_var; - da8xx_fb_info->fbops = &da8xx_fb_ops; - da8xx_fb_info->pseudo_palette = par->pseudo_palette; - da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? - FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; - - ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0); - if (ret) - goto err_disable_reg; - da8xx_fb_info->cmap.len = par->palette_sz; - - /* initialize var_screeninfo */ - da8xx_fb_var.activate = FB_ACTIVATE_FORCE; - fb_set_var(da8xx_fb_info, &da8xx_fb_var); - - platform_set_drvdata(device, da8xx_fb_info); - - /* initialize the vsync wait queue */ - init_waitqueue_head(&par->vsync_wait); - par->vsync_timeout = HZ / 5; - par->which_dma_channel_done = -1; - spin_lock_init(&par->lock_for_chan_update); - - /* Register the Frame Buffer */ - if (register_framebuffer(da8xx_fb_info) < 0) { - dev_err(&device->dev, - "GLCD: Frame Buffer Registration Failed!\n"); - ret = -EINVAL; - goto err_dealloc_cmap; - } - -#ifdef CONFIG_CPU_FREQ - ret = lcd_da8xx_cpufreq_register(par); - if (ret) { - dev_err(&device->dev, "failed to register cpufreq\n"); - goto err_cpu_freq; - } -#endif - - if (lcd_revision == LCD_VERSION_1) - lcdc_irq_handler = lcdc_irq_handler_rev01; - else { - init_waitqueue_head(&frame_done_wq); - lcdc_irq_handler = lcdc_irq_handler_rev02; - } - - ret = devm_request_irq(&device->dev, par->irq, lcdc_irq_handler, 0, - DRIVER_NAME, par); - if (ret) - goto irq_freq; - return 0; - -irq_freq: -#ifdef CONFIG_CPU_FREQ - lcd_da8xx_cpufreq_deregister(par); -err_cpu_freq: -#endif - unregister_framebuffer(da8xx_fb_info); - -err_dealloc_cmap: - fb_dealloc_cmap(&da8xx_fb_info->cmap); - -err_disable_reg: - if (par->lcd_supply) - regulator_disable(par->lcd_supply); -err_release_fb: - framebuffer_release(da8xx_fb_info); - -err_pm_runtime_disable: - pm_runtime_put_sync(&device->dev); - pm_runtime_disable(&device->dev); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static struct lcdc_context { - u32 clk_enable; - u32 ctrl; - u32 dma_ctrl; - u32 raster_timing_0; - u32 raster_timing_1; - u32 raster_timing_2; - u32 int_enable_set; - u32 dma_frm_buf_base_addr_0; - u32 dma_frm_buf_ceiling_addr_0; - u32 dma_frm_buf_base_addr_1; - u32 dma_frm_buf_ceiling_addr_1; - u32 raster_ctrl; -} reg_context; - -static void lcd_context_save(void) -{ - if (lcd_revision == LCD_VERSION_2) { - reg_context.clk_enable = lcdc_read(LCD_CLK_ENABLE_REG); - reg_context.int_enable_set = lcdc_read(LCD_INT_ENABLE_SET_REG); - } - - reg_context.ctrl = lcdc_read(LCD_CTRL_REG); - reg_context.dma_ctrl = lcdc_read(LCD_DMA_CTRL_REG); - reg_context.raster_timing_0 = lcdc_read(LCD_RASTER_TIMING_0_REG); - reg_context.raster_timing_1 = lcdc_read(LCD_RASTER_TIMING_1_REG); - reg_context.raster_timing_2 = lcdc_read(LCD_RASTER_TIMING_2_REG); - reg_context.dma_frm_buf_base_addr_0 = - lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - reg_context.dma_frm_buf_ceiling_addr_0 = - lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - reg_context.dma_frm_buf_base_addr_1 = - lcdc_read(LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - reg_context.dma_frm_buf_ceiling_addr_1 = - lcdc_read(LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - reg_context.raster_ctrl = lcdc_read(LCD_RASTER_CTRL_REG); - return; -} - -static void lcd_context_restore(void) -{ - if (lcd_revision == LCD_VERSION_2) { - lcdc_write(reg_context.clk_enable, LCD_CLK_ENABLE_REG); - lcdc_write(reg_context.int_enable_set, LCD_INT_ENABLE_SET_REG); - } - - lcdc_write(reg_context.ctrl, LCD_CTRL_REG); - lcdc_write(reg_context.dma_ctrl, LCD_DMA_CTRL_REG); - lcdc_write(reg_context.raster_timing_0, LCD_RASTER_TIMING_0_REG); - lcdc_write(reg_context.raster_timing_1, LCD_RASTER_TIMING_1_REG); - lcdc_write(reg_context.raster_timing_2, LCD_RASTER_TIMING_2_REG); - lcdc_write(reg_context.dma_frm_buf_base_addr_0, - LCD_DMA_FRM_BUF_BASE_ADDR_0_REG); - lcdc_write(reg_context.dma_frm_buf_ceiling_addr_0, - LCD_DMA_FRM_BUF_CEILING_ADDR_0_REG); - lcdc_write(reg_context.dma_frm_buf_base_addr_1, - LCD_DMA_FRM_BUF_BASE_ADDR_1_REG); - lcdc_write(reg_context.dma_frm_buf_ceiling_addr_1, - LCD_DMA_FRM_BUF_CEILING_ADDR_1_REG); - lcdc_write(reg_context.raster_ctrl, LCD_RASTER_CTRL_REG); - return; -} - -static int fb_suspend(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - - console_lock(); - if (par->lcd_supply) { - ret = regulator_disable(par->lcd_supply); - if (ret) - return ret; - } - - fb_set_suspend(info, 1); - lcd_disable_raster(DA8XX_FRAME_WAIT); - lcd_context_save(); - pm_runtime_put_sync(dev); - console_unlock(); - - return 0; -} -static int fb_resume(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct da8xx_fb_par *par = info->par; - int ret; - - console_lock(); - pm_runtime_get_sync(dev); - lcd_context_restore(); - if (par->blank == FB_BLANK_UNBLANK) { - lcd_enable_raster(); - - if (par->lcd_supply) { - ret = regulator_enable(par->lcd_supply); - if (ret) - return ret; - } - } - - fb_set_suspend(info, 0); - console_unlock(); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(fb_pm_ops, fb_suspend, fb_resume); - -static struct platform_driver da8xx_fb_driver = { - .probe = fb_probe, - .remove_new = fb_remove, - .driver = { - .name = DRIVER_NAME, - .pm = &fb_pm_ops, - }, -}; -module_platform_driver(da8xx_fb_driver); - -MODULE_DESCRIPTION("Framebuffer driver for TI da8xx/omap-l1xx"); -MODULE_AUTHOR("Texas Instruments"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c index 8dd82afb3452..0e1bd3dba255 100644 --- a/drivers/video/fbdev/efifb.c +++ b/drivers/video/fbdev/efifb.c @@ -275,7 +275,7 @@ static const struct fb_ops efifb_ops = { .fb_setcolreg = efifb_setcolreg, }; -static int efifb_setup(struct screen_info *si, char *options) +static void efifb_setup(struct screen_info *si, char *options) { char *this_opt; @@ -299,8 +299,6 @@ static int efifb_setup(struct screen_info *si, char *options) use_bgrt = false; } } - - return 0; } static inline bool fb_base_is_valid(struct screen_info *si) @@ -322,7 +320,7 @@ static ssize_t name##_show(struct device *dev, \ struct device_attribute *attr, \ char *buf) \ { \ - struct screen_info *si = dev_get_platdata(dev); \ + struct screen_info *si = dev_get_drvdata(dev); \ if (!si) \ return -ENODEV; \ return sprintf(buf, fmt "\n", (si->lfb_##name)); \ @@ -369,6 +367,8 @@ static int efifb_probe(struct platform_device *dev) if (!si) return -ENOMEM; + dev_set_drvdata(&dev->dev, si); + if (si->orig_video_isVGA != VIDEO_TYPE_EFI) return -ENODEV; @@ -449,7 +449,6 @@ static int efifb_probe(struct platform_device *dev) err = -ENOMEM; goto err_release_mem; } - platform_set_drvdata(dev, info); par = info->par; info->pseudo_palette = par->pseudo_palette; @@ -561,15 +560,10 @@ static int efifb_probe(struct platform_device *dev) break; } - err = sysfs_create_groups(&dev->dev.kobj, efifb_groups); - if (err) { - pr_err("efifb: cannot add sysfs attrs\n"); - goto err_unmap; - } err = fb_alloc_cmap(&info->cmap, 256, 0); if (err < 0) { pr_err("efifb: cannot allocate colormap\n"); - goto err_groups; + goto err_unmap; } err = devm_aperture_acquire_for_platform_device(dev, par->base, par->size); @@ -577,7 +571,7 @@ static int efifb_probe(struct platform_device *dev) pr_err("efifb: cannot acquire aperture\n"); goto err_fb_dealloc_cmap; } - err = register_framebuffer(info); + err = devm_register_framebuffer(&dev->dev, info); if (err < 0) { pr_err("efifb: cannot register framebuffer\n"); goto err_fb_dealloc_cmap; @@ -587,8 +581,6 @@ static int efifb_probe(struct platform_device *dev) err_fb_dealloc_cmap: fb_dealloc_cmap(&info->cmap); -err_groups: - sysfs_remove_groups(&dev->dev.kobj, efifb_groups); err_unmap: if (mem_flags & (EFI_MEMORY_UC | EFI_MEMORY_WC)) iounmap(info->screen_base); @@ -602,21 +594,12 @@ err_release_mem: return err; } -static void efifb_remove(struct platform_device *pdev) -{ - struct fb_info *info = platform_get_drvdata(pdev); - - /* efifb_destroy takes care of info cleanup */ - unregister_framebuffer(info); - sysfs_remove_groups(&pdev->dev.kobj, efifb_groups); -} - static struct platform_driver efifb_driver = { .driver = { .name = "efi-framebuffer", + .dev_groups = efifb_groups, }, .probe = efifb_probe, - .remove_new = efifb_remove, }; builtin_platform_driver(efifb_driver); diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c index 3e378874ccc7..801ef427f1ba 100644 --- a/drivers/video/fbdev/ep93xx-fb.c +++ b/drivers/video/fbdev/ep93xx-fb.c @@ -592,7 +592,7 @@ static void ep93xxfb_remove(struct platform_device *pdev) static struct platform_driver ep93xxfb_driver = { .probe = ep93xxfb_probe, - .remove_new = ep93xxfb_remove, + .remove = ep93xxfb_remove, .driver = { .name = "ep93xx-fb", }, diff --git a/drivers/video/fbdev/ffb.c b/drivers/video/fbdev/ffb.c index 2a0f5337e091..34b6abff9493 100644 --- a/drivers/video/fbdev/ffb.c +++ b/drivers/video/fbdev/ffb.c @@ -710,7 +710,7 @@ static int ffb_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map ffb_mmap_map[] = { +static const struct sbus_mmap_map ffb_mmap_map[] = { { .voff = FFB_SFB8R_VOFF, .poff = FFB_SFB8R_POFF, @@ -1053,7 +1053,7 @@ static struct platform_driver ffb_driver = { .of_match_table = ffb_match, }, .probe = ffb_probe, - .remove_new = ffb_remove, + .remove = ffb_remove, }; static int __init ffb_init(void) diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c index 0191141657fd..b71d15794ce8 100644 --- a/drivers/video/fbdev/fsl-diu-fb.c +++ b/drivers/video/fbdev/fsl-diu-fb.c @@ -787,7 +787,7 @@ static void set_fix(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; struct mfb_info *mfbi = info->par; - strncpy(fix->id, mfbi->id, sizeof(fix->id)); + strscpy_pad(fix->id, mfbi->id); fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; fix->type = FB_TYPE_PACKED_PIXELS; fix->accel = FB_ACCEL_NONE; @@ -1827,6 +1827,7 @@ static void fsl_diu_remove(struct platform_device *pdev) int i; data = dev_get_drvdata(&pdev->dev); + device_remove_file(&pdev->dev, &data->dev_attr); disable_lcdc(&data->fsl_diu_info[0]); free_irq(data->irq, data->diu_reg); @@ -1876,12 +1877,12 @@ static const struct of_device_id fsl_diu_match[] = { MODULE_DEVICE_TABLE(of, fsl_diu_match); static struct platform_driver fsl_diu_driver = { - .driver = { + .driver = { .name = "fsl-diu-fb", .of_match_table = fsl_diu_match, }, - .probe = fsl_diu_probe, - .remove_new = fsl_diu_remove, + .probe = fsl_diu_probe, + .remove = fsl_diu_remove, .suspend = fsl_diu_suspend, .resume = fsl_diu_resume, }; diff --git a/drivers/video/fbdev/gbefb.c b/drivers/video/fbdev/gbefb.c index 8463de833d1e..4c36a3e409be 100644 --- a/drivers/video/fbdev/gbefb.c +++ b/drivers/video/fbdev/gbefb.c @@ -1247,10 +1247,10 @@ static void gbefb_remove(struct platform_device* p_dev) static struct platform_driver gbefb_driver = { .probe = gbefb_probe, - .remove_new = gbefb_remove, - .driver = { + .remove = gbefb_remove, + .driver = { .name = "gbefb", - .dev_groups = gbefb_groups, + .dev_groups = gbefb_groups, }, }; diff --git a/drivers/video/fbdev/geode/display_gx.c b/drivers/video/fbdev/geode/display_gx.c index b5f25dffd274..099322cefce0 100644 --- a/drivers/video/fbdev/geode/display_gx.c +++ b/drivers/video/fbdev/geode/display_gx.c @@ -13,6 +13,7 @@ #include <asm/io.h> #include <asm/div64.h> #include <asm/delay.h> +#include <asm/msr.h> #include <linux/cs5535.h> #include "gxfb.h" diff --git a/drivers/video/fbdev/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c index af996634c1a9..8d69be7c9d31 100644 --- a/drivers/video/fbdev/geode/gxfb_core.c +++ b/drivers/video/fbdev/geode/gxfb_core.c @@ -29,6 +29,7 @@ #include <linux/pci.h> #include <linux/cs5535.h> +#include <asm/msr.h> #include <asm/olpc.h> #include "gxfb.h" @@ -377,7 +378,7 @@ static int gxfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Figure out if this is a TFT or CRT part */ - rdmsrl(MSR_GX_GLD_MSR_CONFIG, val); + rdmsrq(MSR_GX_GLD_MSR_CONFIG, val); if ((val & MSR_GX_GLD_MSR_CONFIG_FP) == MSR_GX_GLD_MSR_CONFIG_FP) par->enable_crt = 0; diff --git a/drivers/video/fbdev/geode/lxfb_ops.c b/drivers/video/fbdev/geode/lxfb_ops.c index 32baaf59fcf7..2e33da9849b0 100644 --- a/drivers/video/fbdev/geode/lxfb_ops.c +++ b/drivers/video/fbdev/geode/lxfb_ops.c @@ -11,6 +11,7 @@ #include <linux/delay.h> #include <linux/cs5535.h> +#include <asm/msr.h> #include "lxfb.h" /* TODO @@ -358,7 +359,7 @@ void lx_set_mode(struct fb_info *info) /* Set output mode */ - rdmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); + rdmsrq(MSR_LX_GLD_MSR_CONFIG, msrval); msrval &= ~MSR_LX_GLD_MSR_CONFIG_FMT; if (par->output & OUTPUT_PANEL) { @@ -371,7 +372,7 @@ void lx_set_mode(struct fb_info *info) } else msrval |= MSR_LX_GLD_MSR_CONFIG_FMT_CRT; - wrmsrl(MSR_LX_GLD_MSR_CONFIG, msrval); + wrmsrq(MSR_LX_GLD_MSR_CONFIG, msrval); /* Clear the various buffers */ /* FIXME: Adjust for panning here */ @@ -419,7 +420,7 @@ void lx_set_mode(struct fb_info *info) /* Set default watermark values */ - rdmsrl(MSR_LX_SPARE_MSR, msrval); + rdmsrq(MSR_LX_SPARE_MSR, msrval); msrval &= ~(MSR_LX_SPARE_MSR_DIS_CFIFO_HGO | MSR_LX_SPARE_MSR_VFIFO_ARB_SEL @@ -427,7 +428,7 @@ void lx_set_mode(struct fb_info *info) | MSR_LX_SPARE_MSR_WM_LPEN_OVRD); msrval |= MSR_LX_SPARE_MSR_DIS_VIFO_WM | MSR_LX_SPARE_MSR_DIS_INIT_V_PRI; - wrmsrl(MSR_LX_SPARE_MSR, msrval); + wrmsrq(MSR_LX_SPARE_MSR, msrval); gcfg = DC_GENERAL_CFG_DFLE; /* Display fifo enable */ gcfg |= (0x6 << DC_GENERAL_CFG_DFHPSL_SHIFT) | /* default priority */ @@ -591,10 +592,10 @@ static void lx_save_regs(struct lxfb_par *par) } while ((i & GP_BLT_STATUS_PB) || !(i & GP_BLT_STATUS_CE)); /* save MSRs */ - rdmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); - rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll); - rdmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); - rdmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); + rdmsrq(MSR_LX_MSR_PADSEL, par->msr.padsel); + rdmsrq(MSR_GLCP_DOTPLL, par->msr.dotpll); + rdmsrq(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); + rdmsrq(MSR_LX_SPARE_MSR, par->msr.dcspare); write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); @@ -664,7 +665,7 @@ static void lx_restore_display_ctlr(struct lxfb_par *par) uint32_t filt; int i; - wrmsrl(MSR_LX_SPARE_MSR, par->msr.dcspare); + wrmsrq(MSR_LX_SPARE_MSR, par->msr.dcspare); for (i = 0; i < ARRAY_SIZE(par->dc); i++) { switch (i) { @@ -729,8 +730,8 @@ static void lx_restore_video_proc(struct lxfb_par *par) { int i; - wrmsrl(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); - wrmsrl(MSR_LX_MSR_PADSEL, par->msr.padsel); + wrmsrq(MSR_LX_GLD_MSR_CONFIG, par->msr.dfglcfg); + wrmsrq(MSR_LX_MSR_PADSEL, par->msr.padsel); for (i = 0; i < ARRAY_SIZE(par->vp); i++) { switch (i) { diff --git a/drivers/video/fbdev/geode/suspend_gx.c b/drivers/video/fbdev/geode/suspend_gx.c index 8c49d4e98772..73307f42e343 100644 --- a/drivers/video/fbdev/geode/suspend_gx.c +++ b/drivers/video/fbdev/geode/suspend_gx.c @@ -21,8 +21,8 @@ static void gx_save_regs(struct gxfb_par *par) } while (i & (GP_BLT_STATUS_BLT_PENDING | GP_BLT_STATUS_BLT_BUSY)); /* save MSRs */ - rdmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel); - rdmsrl(MSR_GLCP_DOTPLL, par->msr.dotpll); + rdmsrq(MSR_GX_MSR_PADSEL, par->msr.padsel); + rdmsrq(MSR_GLCP_DOTPLL, par->msr.dotpll); write_dc(par, DC_UNLOCK, DC_UNLOCK_UNLOCK); @@ -43,14 +43,14 @@ static void gx_set_dotpll(uint32_t dotpll_hi) uint32_t dotpll_lo; int i; - rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo); + rdmsrq(MSR_GLCP_DOTPLL, dotpll_lo); dotpll_lo |= MSR_GLCP_DOTPLL_DOTRESET; dotpll_lo &= ~MSR_GLCP_DOTPLL_BYPASS; wrmsr(MSR_GLCP_DOTPLL, dotpll_lo, dotpll_hi); /* wait for the PLL to lock */ for (i = 0; i < 200; i++) { - rdmsrl(MSR_GLCP_DOTPLL, dotpll_lo); + rdmsrq(MSR_GLCP_DOTPLL, dotpll_lo); if (dotpll_lo & MSR_GLCP_DOTPLL_LOCK) break; udelay(1); @@ -133,7 +133,7 @@ static void gx_restore_video_proc(struct gxfb_par *par) { int i; - wrmsrl(MSR_GX_MSR_PADSEL, par->msr.padsel); + wrmsrq(MSR_GX_MSR_PADSEL, par->msr.padsel); for (i = 0; i < ARRAY_SIZE(par->vp); i++) { switch (i) { diff --git a/drivers/video/fbdev/geode/video_gx.c b/drivers/video/fbdev/geode/video_gx.c index 91dac2aa247c..5717c3356949 100644 --- a/drivers/video/fbdev/geode/video_gx.c +++ b/drivers/video/fbdev/geode/video_gx.c @@ -142,8 +142,8 @@ void gx_set_dclk_frequency(struct fb_info *info) } } - rdmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); - rdmsrl(MSR_GLCP_DOTPLL, dotpll); + rdmsrq(MSR_GLCP_SYS_RSTPLL, sys_rstpll); + rdmsrq(MSR_GLCP_DOTPLL, dotpll); /* Program new M, N and P. */ dotpll &= 0x00000000ffffffffull; @@ -151,7 +151,7 @@ void gx_set_dclk_frequency(struct fb_info *info) dotpll |= MSR_GLCP_DOTPLL_DOTRESET; dotpll &= ~MSR_GLCP_DOTPLL_BYPASS; - wrmsrl(MSR_GLCP_DOTPLL, dotpll); + wrmsrq(MSR_GLCP_DOTPLL, dotpll); /* Program dividers. */ sys_rstpll &= ~( MSR_GLCP_SYS_RSTPLL_DOTPREDIV2 @@ -159,15 +159,15 @@ void gx_set_dclk_frequency(struct fb_info *info) | MSR_GLCP_SYS_RSTPLL_DOTPOSTDIV3 ); sys_rstpll |= pll_table[best_i].sys_rstpll_bits; - wrmsrl(MSR_GLCP_SYS_RSTPLL, sys_rstpll); + wrmsrq(MSR_GLCP_SYS_RSTPLL, sys_rstpll); /* Clear reset bit to start PLL. */ dotpll &= ~(MSR_GLCP_DOTPLL_DOTRESET); - wrmsrl(MSR_GLCP_DOTPLL, dotpll); + wrmsrq(MSR_GLCP_DOTPLL, dotpll); /* Wait for LOCK bit. */ do { - rdmsrl(MSR_GLCP_DOTPLL, dotpll); + rdmsrq(MSR_GLCP_DOTPLL, dotpll); } while (timeout-- && !(dotpll & MSR_GLCP_DOTPLL_LOCK)); } @@ -180,10 +180,10 @@ gx_configure_tft(struct fb_info *info) /* Set up the DF pad select MSR */ - rdmsrl(MSR_GX_MSR_PADSEL, val); + rdmsrq(MSR_GX_MSR_PADSEL, val); val &= ~MSR_GX_MSR_PADSEL_MASK; val |= MSR_GX_MSR_PADSEL_TFT; - wrmsrl(MSR_GX_MSR_PADSEL, val); + wrmsrq(MSR_GX_MSR_PADSEL, val); /* Turn off the panel */ diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c index ca9e8255947c..7704f2ab18c0 100644 --- a/drivers/video/fbdev/goldfishfb.c +++ b/drivers/video/fbdev/goldfishfb.c @@ -311,7 +311,7 @@ MODULE_DEVICE_TABLE(acpi, goldfish_fb_acpi_match); static struct platform_driver goldfish_fb_driver = { .probe = goldfish_fb_probe, - .remove_new = goldfish_fb_remove, + .remove = goldfish_fb_remove, .driver = { .name = "goldfish_fb", .of_match_table = goldfish_fb_of_match, @@ -321,4 +321,5 @@ static struct platform_driver goldfish_fb_driver = { module_platform_driver(goldfish_fb_driver); +MODULE_DESCRIPTION("Goldfish Virtual Platform Framebuffer driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/video/fbdev/grvga.c b/drivers/video/fbdev/grvga.c index 6d917e06e5f3..de8ab817d406 100644 --- a/drivers/video/fbdev/grvga.c +++ b/drivers/video/fbdev/grvga.c @@ -540,7 +540,7 @@ static struct platform_driver grvga_driver = { .of_match_table = svgactrl_of_match, }, .probe = grvga_probe, - .remove_new = grvga_remove, + .remove = grvga_remove, }; module_platform_driver(grvga_driver); diff --git a/drivers/video/fbdev/hecubafb.c b/drivers/video/fbdev/hecubafb.c index ef526ed4a2d9..3547d58a29cf 100644 --- a/drivers/video/fbdev/hecubafb.c +++ b/drivers/video/fbdev/hecubafb.c @@ -235,7 +235,7 @@ static void hecubafb_remove(struct platform_device *dev) static struct platform_driver hecubafb_driver = { .probe = hecubafb_probe, - .remove_new = hecubafb_remove, + .remove = hecubafb_remove, .driver = { .name = "hecubafb", }, diff --git a/drivers/video/fbdev/hgafb.c b/drivers/video/fbdev/hgafb.c index c3bc5b78b749..14418aa3791a 100644 --- a/drivers/video/fbdev/hgafb.c +++ b/drivers/video/fbdev/hgafb.c @@ -629,7 +629,7 @@ static void hgafb_remove(struct platform_device *pdev) static struct platform_driver hgafb_driver = { .probe = hgafb_probe, - .remove_new = hgafb_remove, + .remove = hgafb_remove, .driver = { .name = "hgafb", }, diff --git a/drivers/video/fbdev/hitfb.c b/drivers/video/fbdev/hitfb.c index b64b74b76c71..97db325df2b4 100644 --- a/drivers/video/fbdev/hitfb.c +++ b/drivers/video/fbdev/hitfb.c @@ -476,7 +476,7 @@ static const struct dev_pm_ops hitfb_dev_pm_ops = { static struct platform_driver hitfb_driver = { .probe = hitfb_probe, - .remove_new = hitfb_remove, + .remove = hitfb_remove, .driver = { .name = "hitfb", .pm = &hitfb_dev_pm_ops, diff --git a/drivers/video/fbdev/hpfb.c b/drivers/video/fbdev/hpfb.c index 66fac8e5393e..a1144b150982 100644 --- a/drivers/video/fbdev/hpfb.c +++ b/drivers/video/fbdev/hpfb.c @@ -345,6 +345,7 @@ static int hpfb_dio_probe(struct dio_dev *d, const struct dio_device_id *ent) if (hpfb_init_one(paddr, vaddr)) { if (d->scode >= DIOII_SCBASE) iounmap((void *)vaddr); + release_mem_region(d->resource.start, resource_size(&d->resource)); return -ENOMEM; } return 0; diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 8fdccf033b2d..75338ffc703f 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -282,6 +282,8 @@ static uint screen_depth; static uint screen_fb_size; static uint dio_fb_size; /* FB size for deferred IO */ +static void hvfb_putmem(struct fb_info *info); + /* Send message to Hyper-V host */ static inline int synthvid_send(struct hv_device *hdev, struct synthvid_msg *msg) @@ -863,6 +865,17 @@ static void hvfb_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, } /* + * fb_ops.fb_destroy is called by the last put_fb_info() call at the end + * of unregister_framebuffer() or fb_release(). Do any cleanup related to + * framebuffer here. + */ +static void hvfb_destroy(struct fb_info *info) +{ + hvfb_putmem(info); + framebuffer_release(info); +} + +/* * TODO: GEN1 codepaths allocate from system or DMA-able memory. Fix the * driver to use the _SYSMEM_ or _DMAMEM_ helpers in these cases. */ @@ -877,6 +890,7 @@ static const struct fb_ops hvfb_ops = { .fb_set_par = hvfb_set_par, .fb_setcolreg = hvfb_setcolreg, .fb_blank = hvfb_blank, + .fb_destroy = hvfb_destroy, }; /* Get options from kernel paramenter "video=" */ @@ -952,7 +966,7 @@ static phys_addr_t hvfb_get_phymem(struct hv_device *hdev, } /* Release contiguous physical memory */ -static void hvfb_release_phymem(struct hv_device *hdev, +static void hvfb_release_phymem(struct device *device, phys_addr_t paddr, unsigned int size) { unsigned int order = get_order(size); @@ -960,7 +974,7 @@ static void hvfb_release_phymem(struct hv_device *hdev, if (order <= MAX_PAGE_ORDER) __free_pages(pfn_to_page(paddr >> PAGE_SHIFT), order); else - dma_free_coherent(&hdev->device, + dma_free_coherent(device, round_up(size, PAGE_SIZE), phys_to_virt(paddr), paddr); @@ -989,6 +1003,7 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) base = pci_resource_start(pdev, 0); size = pci_resource_len(pdev, 0); + aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME); /* * For Gen 1 VM, we can directly use the contiguous memory @@ -1010,11 +1025,21 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) goto getmem_done; } pr_info("Unable to allocate enough contiguous physical memory on Gen 1 VM. Using MMIO instead.\n"); + } else { + aperture_remove_all_conflicting_devices(KBUILD_MODNAME); } /* - * Cannot use the contiguous physical memory. - * Allocate mmio space for framebuffer. + * Cannot use contiguous physical memory, so allocate MMIO space for + * the framebuffer. At this point in the function, conflicting devices + * that might have claimed the framebuffer MMIO space based on + * screen_info.lfb_base must have already been removed so that + * vmbus_allocate_mmio() does not allocate different MMIO space. If the + * kdump image were to be loaded using kexec_file_load(), the + * framebuffer location in the kdump image would be set from + * screen_info.lfb_base at the time that kdump is enabled. If the + * framebuffer has moved elsewhere, this could be the wrong location, + * causing kdump to hang when efifb (for example) loads. */ dio_fb_size = screen_width * screen_height * screen_depth / 8; @@ -1051,11 +1076,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) info->screen_size = dio_fb_size; getmem_done: - if (base && size) - aperture_remove_conflicting_devices(base, size, KBUILD_MODNAME); - else - aperture_remove_all_conflicting_devices(KBUILD_MODNAME); - if (!gen2vm) pci_dev_put(pdev); @@ -1074,16 +1094,16 @@ err1: } /* Release the framebuffer */ -static void hvfb_putmem(struct hv_device *hdev, struct fb_info *info) +static void hvfb_putmem(struct fb_info *info) { struct hvfb_par *par = info->par; if (par->need_docopy) { vfree(par->dio_vp); - iounmap(info->screen_base); + iounmap(par->mmio_vp); vmbus_free_mmio(par->mem->start, screen_fb_size); } else { - hvfb_release_phymem(hdev, info->fix.smem_start, + hvfb_release_phymem(info->device, info->fix.smem_start, screen_fb_size); } @@ -1172,7 +1192,7 @@ static int hvfb_probe(struct hv_device *hdev, if (ret) goto error; - ret = register_framebuffer(info); + ret = devm_register_framebuffer(&hdev->device, info); if (ret) { pr_err("Unable to register framebuffer\n"); goto error; @@ -1189,7 +1209,7 @@ static int hvfb_probe(struct hv_device *hdev, * which is almost at the end of list, with priority = INT_MIN + 1. */ par->hvfb_panic_nb.notifier_call = hvfb_on_panic; - par->hvfb_panic_nb.priority = INT_MIN + 10, + par->hvfb_panic_nb.priority = INT_MIN + 10; atomic_notifier_chain_register(&panic_notifier_list, &par->hvfb_panic_nb); @@ -1197,7 +1217,7 @@ static int hvfb_probe(struct hv_device *hdev, error: fb_deferred_io_cleanup(info); - hvfb_putmem(hdev, info); + hvfb_putmem(info); error2: vmbus_close(hdev->channel); error1: @@ -1220,14 +1240,10 @@ static void hvfb_remove(struct hv_device *hdev) fb_deferred_io_cleanup(info); - unregister_framebuffer(info); cancel_delayed_work_sync(&par->dwork); vmbus_close(hdev->channel); hv_set_drvdata(hdev, NULL); - - hvfb_putmem(hdev, info); - framebuffer_release(info); } static int hvfb_suspend(struct hv_device *hdev) diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 660499260f46..dc4e659e06af 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -995,7 +995,7 @@ imsttfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) bgc |= (bgc << 8); bgc |= (bgc << 16); - Bpp = info->var.bits_per_pixel >> 3, + Bpp = info->var.bits_per_pixel >> 3; line_pitch = info->fix.line_length; dy = rect->dy * line_pitch; @@ -1036,7 +1036,7 @@ imsttfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) __u32 Bpp, line_pitch, fb_offset_old, fb_offset_new, sp, dp_octl; __u32 cnt, bltctl, sx, sy, dx, dy, height, width; - Bpp = info->var.bits_per_pixel >> 3, + Bpp = info->var.bits_per_pixel >> 3; sx = area->sx * Bpp; sy = area->sy; diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index a4dbc72f93c3..f30da32cdaed 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -782,16 +782,6 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np, return 0; } -static int imxfb_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi) -{ - struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); - - if (!fi || fi->par == fbi) - return 1; - - return 0; -} - static int imxfb_lcd_get_contrast(struct lcd_device *lcddev) { struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); @@ -824,9 +814,9 @@ static int imxfb_lcd_get_power(struct lcd_device *lcddev) if (!IS_ERR(fbi->lcd_pwr) && !regulator_is_enabled(fbi->lcd_pwr)) - return FB_BLANK_POWERDOWN; + return LCD_POWER_OFF; - return FB_BLANK_UNBLANK; + return LCD_POWER_ON; } static int imxfb_regulator_set(struct imxfb_info *fbi, int enable) @@ -852,13 +842,12 @@ static int imxfb_lcd_set_power(struct lcd_device *lcddev, int power) struct imxfb_info *fbi = dev_get_drvdata(&lcddev->dev); if (!IS_ERR(fbi->lcd_pwr)) - return imxfb_regulator_set(fbi, power == FB_BLANK_UNBLANK); + return imxfb_regulator_set(fbi, power == LCD_POWER_ON); return 0; } -static struct lcd_ops imxfb_lcd_ops = { - .check_fb = imxfb_lcd_check_fb, +static const struct lcd_ops imxfb_lcd_ops = { .get_contrast = imxfb_lcd_get_contrast, .set_contrast = imxfb_lcd_set_contrast, .get_power = imxfb_lcd_get_power, @@ -1025,11 +1014,6 @@ static int imxfb_probe(struct platform_device *pdev) goto failed_cmap; imxfb_set_par(info); - ret = register_framebuffer(info); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register framebuffer\n"); - goto failed_register; - } fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd"); if (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER) { @@ -1046,13 +1030,19 @@ static int imxfb_probe(struct platform_device *pdev) lcd->props.max_contrast = 0xff; + info->lcd_dev = lcd; + + ret = register_framebuffer(info); + if (ret < 0) { + dev_err(&pdev->dev, "failed to register framebuffer\n"); + goto failed_lcd; + } + imxfb_enable_controller(fbi); return 0; failed_lcd: - unregister_framebuffer(info); -failed_register: fb_dealloc_cmap(&info->cmap); failed_cmap: dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer, @@ -1105,7 +1095,7 @@ static struct platform_driver imxfb_driver = { .pm = pm_sleep_ptr(&imxfb_pm_ops), }, .probe = imxfb_probe, - .remove_new = imxfb_remove, + .remove = imxfb_remove, .id_table = imxfb_devtype, }; module_platform_driver(imxfb_driver); diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c index af6c0581d3e2..08ee8baa79f8 100644 --- a/drivers/video/fbdev/kyro/fbdev.c +++ b/drivers/video/fbdev/kyro/fbdev.c @@ -811,4 +811,5 @@ module_exit(kyrofb_exit); #endif MODULE_AUTHOR("STMicroelectronics; Paul Mundt <lethal@linux-sh.org>"); +MODULE_DESCRIPTION("STG4000/Kyro/PowerVR 3 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/leo.c b/drivers/video/fbdev/leo.c index 7cf525c76079..b9fb059df2c7 100644 --- a/drivers/video/fbdev/leo.c +++ b/drivers/video/fbdev/leo.c @@ -338,7 +338,7 @@ static int leo_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map leo_mmap_map[] = { +static const struct sbus_mmap_map leo_mmap_map[] = { { .voff = LEO_SS0_MAP, .poff = LEO_OFF_SS0, @@ -657,7 +657,7 @@ static struct platform_driver leo_driver = { .of_match_table = leo_match, }, .probe = leo_probe, - .remove_new = leo_remove, + .remove = leo_remove, }; static int __init leo_init(void) diff --git a/drivers/video/fbdev/macmodes.c b/drivers/video/fbdev/macmodes.c index af86c081d2be..d6be3c67d3df 100644 --- a/drivers/video/fbdev/macmodes.c +++ b/drivers/video/fbdev/macmodes.c @@ -411,4 +411,5 @@ int mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, } EXPORT_SYMBOL(mac_find_mode); +MODULE_DESCRIPTION("MacOS video mode library"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c index 765e805d14e3..398b7035f5a9 100644 --- a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c +++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c @@ -1111,4 +1111,5 @@ EXPORT_SYMBOL(matrox_G100); EXPORT_SYMBOL(DAC1064_global_init); EXPORT_SYMBOL(DAC1064_global_restore); #endif +MODULE_DESCRIPTION("Matrox Mystique/G100 output driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c index 5617c014da87..f53b8066e8a5 100644 --- a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c +++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c @@ -746,4 +746,5 @@ struct matrox_switch matrox_millennium = { }; EXPORT_SYMBOL(matrox_millennium); #endif +MODULE_DESCRIPTION("Matrox Millennium output driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c index ce51227798a1..52e15dc6f45b 100644 --- a/drivers/video/fbdev/matrox/matroxfb_accel.c +++ b/drivers/video/fbdev/matrox/matroxfb_accel.c @@ -517,4 +517,5 @@ static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* imag } } +MODULE_DESCRIPTION("Accelerated fbops for Matrox Millennium/Mystique/G100/G200/G400/G450/G550"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h index c93c69bbcd57..a6437c40fc57 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.h +++ b/drivers/video/fbdev/matrox/matroxfb_base.h @@ -44,7 +44,7 @@ #include <linux/kd.h> #include <asm/io.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #if defined(CONFIG_PPC_PMAC) #include "../macmodes.h" diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c index b15a8ad92ba7..dcfae770b42d 100644 --- a/drivers/video/fbdev/matrox/matroxfb_maven.c +++ b/drivers/video/fbdev/matrox/matroxfb_maven.c @@ -1282,7 +1282,7 @@ static void maven_remove(struct i2c_client *client) } static const struct i2c_device_id maven_id[] = { - { "maven", 0 }, + { "maven" }, { } }; MODULE_DEVICE_TABLE(i2c, maven_id); diff --git a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c index baec312d7b33..ade88e7bc760 100644 --- a/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c +++ b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c @@ -834,7 +834,7 @@ static struct platform_driver of_platform_mb862xxfb_driver = { .of_match_table = of_platform_mb862xx_tbl, }, .probe = of_platform_mb862xx_probe, - .remove_new = of_platform_mb862xx_remove, + .remove = of_platform_mb862xx_remove, }; #endif diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c index 130394616a7c..6f0942c6e5f1 100644 --- a/drivers/video/fbdev/metronomefb.c +++ b/drivers/video/fbdev/metronomefb.c @@ -37,7 +37,7 @@ #include <video/metronomefb.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> /* Display specific information */ #define DPY_W 832 @@ -707,7 +707,7 @@ static void metronomefb_remove(struct platform_device *dev) static struct platform_driver metronomefb_driver = { .probe = metronomefb_probe, - .remove_new = metronomefb_remove, + .remove = metronomefb_remove, .driver = { .name = "metronomefb", }, diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c index 76b50b6c98ad..03e23173198c 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c +++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c @@ -313,7 +313,7 @@ static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode) mutex_unlock(&path->access_ok); } -static struct mmp_overlay_ops mmphw_overlay_ops = { +static const struct mmp_overlay_ops mmphw_overlay_ops = { .set_fetch = overlay_set_fetch, .set_onoff = overlay_set_onoff, .set_win = overlay_set_win, @@ -512,16 +512,13 @@ static int mmphw_probe(struct platform_device *pdev) } /* get clock */ - ctrl->clk = devm_clk_get(ctrl->dev, mi->clk_name); + ctrl->clk = devm_clk_get_enabled(ctrl->dev, mi->clk_name); if (IS_ERR(ctrl->clk)) { ret = PTR_ERR(ctrl->clk); dev_err_probe(ctrl->dev, ret, "unable to get clk %s\n", mi->clk_name); goto failed; } - ret = clk_prepare_enable(ctrl->clk); - if (ret) - goto failed; /* init global regs */ ctrl_set_default(ctrl); @@ -556,7 +553,6 @@ failed_path_init: path_deinit(path_plat); } - clk_disable_unprepare(ctrl->clk); failed: dev_err(&pdev->dev, "device init failed\n"); diff --git a/drivers/video/fbdev/mmp/hw/mmp_spi.c b/drivers/video/fbdev/mmp/hw/mmp_spi.c index cf23650d7f0b..3f253f4271ac 100644 --- a/drivers/video/fbdev/mmp/hw/mmp_spi.c +++ b/drivers/video/fbdev/mmp/hw/mmp_spi.c @@ -140,9 +140,9 @@ int lcd_spi_register(struct mmphw_ctrl *ctrl) void **p_regbase; int err; - ctlr = spi_alloc_master(ctrl->dev, sizeof(void *)); + ctlr = spi_alloc_host(ctrl->dev, sizeof(void *)); if (!ctlr) { - dev_err(ctrl->dev, "unable to allocate SPI master\n"); + dev_err(ctrl->dev, "unable to allocate SPI host\n"); return -ENOMEM; } p_regbase = spi_controller_get_devdata(ctlr); @@ -156,7 +156,7 @@ int lcd_spi_register(struct mmphw_ctrl *ctrl) err = spi_register_controller(ctlr); if (err < 0) { - dev_err(ctrl->dev, "unable to register SPI master\n"); + dev_err(ctrl->dev, "unable to register SPI host\n"); spi_controller_put(ctlr); return err; } diff --git a/drivers/video/fbdev/nvidia/nv_backlight.c b/drivers/video/fbdev/nvidia/nv_backlight.c index 160da9c50a52..7edd47ab16e9 100644 --- a/drivers/video/fbdev/nvidia/nv_backlight.c +++ b/drivers/video/fbdev/nvidia/nv_backlight.c @@ -112,7 +112,7 @@ void nvidia_bl_init(struct nvidia_par *par) 0x534 * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("nvidia: Backlight initialized (%s)\n", name); diff --git a/drivers/video/fbdev/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c index 9b0a324bb1b4..75afaa07e7eb 100644 --- a/drivers/video/fbdev/nvidia/nv_hw.c +++ b/drivers/video/fbdev/nvidia/nv_hw.c @@ -1509,10 +1509,10 @@ void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001); NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001); - if (!state) { - par->CurrentState = NULL; - return; - } + if (!state) { + par->CurrentState = NULL; + return; + } if (par->Architecture >= NV_ARCH_10) { if (par->twoHeads) { diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c index 8900f181f195..cfaf9454014d 100644 --- a/drivers/video/fbdev/nvidia/nvidia.c +++ b/drivers/video/fbdev/nvidia/nvidia.c @@ -1484,7 +1484,7 @@ static int nvidiafb_setup(char *options) flatpanel = 1; } else if (!strncmp(this_opt, "hwcur", 5)) { hwcur = 1; - } else if (!strncmp(this_opt, "noaccel", 6)) { + } else if (!strncmp(this_opt, "noaccel", 7)) { noaccel = 1; } else if (!strncmp(this_opt, "noscale", 7)) { noscale = 1; diff --git a/drivers/video/fbdev/ocfb.c b/drivers/video/fbdev/ocfb.c index 7dc305c67af8..893888260c21 100644 --- a/drivers/video/fbdev/ocfb.c +++ b/drivers/video/fbdev/ocfb.c @@ -391,7 +391,7 @@ MODULE_DEVICE_TABLE(of, ocfb_match); static struct platform_driver ocfb_driver = { .probe = ocfb_probe, - .remove_new = ocfb_remove, + .remove = ocfb_remove, .driver = { .name = "ocfb_fb", .of_match_table = ocfb_match, diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index b421b46d88ef..f85428e13996 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -357,7 +357,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp par->cmap_type = cmap_gxt2000; } else if (of_node_name_prefix(dp, "vga,Display-")) { /* Look for AVIVO initialized by SLOF */ - struct device_node *pciparent = of_get_parent(dp); + struct device_node *pciparent __free(device_node) = of_get_parent(dp); const u32 *vid, *did; vid = of_get_property(pciparent, "vendor-id", NULL); did = of_get_property(pciparent, "device-id", NULL); @@ -369,7 +369,6 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp if (par->cmap_adr) par->cmap_type = cmap_avivo; } - of_node_put(pciparent); } else if (dp && of_device_is_compatible(dp, "qemu,std-vga")) { #ifdef __BIG_ENDIAN const __be32 io_of_addr[3] = { 0x01000000, 0x0, 0x0 }; @@ -674,7 +673,7 @@ static struct platform_driver offb_driver_bootx_noscreen = { .name = "bootx-noscreen", }, .probe = offb_probe_bootx_noscreen, - .remove_new = offb_remove, + .remove = offb_remove, }; static int offb_probe_display(struct platform_device *pdev) @@ -696,7 +695,7 @@ static struct platform_driver offb_driver_display = { .of_match_table = offb_of_match_display, }, .probe = offb_probe_display, - .remove_new = offb_remove, + .remove = offb_remove, }; static int __init offb_init(void) @@ -718,4 +717,5 @@ static void __exit offb_exit(void) } module_exit(offb_exit); +MODULE_DESCRIPTION("Open Firmware frame buffer device driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c index 161fc65d6b57..64e76e1f5388 100644 --- a/drivers/video/fbdev/omap/hwa742.c +++ b/drivers/video/fbdev/omap/hwa742.c @@ -597,7 +597,7 @@ static int hwa742_set_update_mode(enum omapfb_update_mode mode) break; case OMAPFB_AUTO_UPDATE: hwa742.stop_auto_update = 1; - del_timer_sync(&hwa742.auto_update_timer); + timer_delete_sync(&hwa742.auto_update_timer); break; case OMAPFB_UPDATE_DISABLED: break; diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c index 6f860c814d2c..456e6e9e11a9 100644 --- a/drivers/video/fbdev/omap/lcd_ams_delta.c +++ b/drivers/video/fbdev/omap/lcd_ams_delta.c @@ -32,7 +32,7 @@ static struct gpio_desc *gpiod_ndisp; static int ams_delta_lcd_set_power(struct lcd_device *dev, int power) { - if (power == FB_BLANK_UNBLANK) { + if (power == LCD_POWER_ON) { if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) { omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST, OMAP_PWL_ENABLE); @@ -63,9 +63,9 @@ static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value) static int ams_delta_lcd_get_power(struct lcd_device *dev) { if (ams_delta_lcd & AMS_DELTA_LCD_POWER) - return FB_BLANK_UNBLANK; + return LCD_POWER_ON; else - return FB_BLANK_POWERDOWN; + return LCD_POWER_OFF; } static int ams_delta_lcd_get_contrast(struct lcd_device *dev) @@ -76,7 +76,7 @@ static int ams_delta_lcd_get_contrast(struct lcd_device *dev) return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST; } -static struct lcd_ops ams_delta_lcd_ops = { +static const struct lcd_ops ams_delta_lcd_ops = { .get_power = ams_delta_lcd_get_power, .set_power = ams_delta_lcd_set_power, .get_contrast = ams_delta_lcd_get_contrast, @@ -155,7 +155,7 @@ static int ams_delta_panel_probe(struct platform_device *pdev) #endif ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST); - ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK); + ams_delta_lcd_set_power(lcd_device, LCD_POWER_ON); omapfb_register_panel(&ams_delta_panel); return 0; diff --git a/drivers/video/fbdev/omap/lcd_dma.c b/drivers/video/fbdev/omap/lcd_dma.c index f85817635a8c..0da23c57e475 100644 --- a/drivers/video/fbdev/omap/lcd_dma.c +++ b/drivers/video/fbdev/omap/lcd_dma.c @@ -432,8 +432,8 @@ static int __init omap_init_lcd_dma(void) spin_lock_init(&lcd_dma.lock); - r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, - "LCD DMA", NULL); + r = request_threaded_irq(INT_DMA_LCD, NULL, lcd_dma_irq_handler, + IRQF_ONESHOT, "LCD DMA", NULL); if (r != 0) pr_err("unable to request IRQ for LCD DMA (error %d)\n", r); diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index aa31c0d26e92..2682b20d184a 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -1241,14 +1241,13 @@ static ssize_t omapfb_show_caps_num(struct device *dev, { struct omapfb_device *fbdev = dev_get_drvdata(dev); int plane; - size_t size; + size_t size = 0; struct omapfb_caps caps; plane = 0; - size = 0; - while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) { + while (plane < OMAPFB_PLANE_NUM) { omapfb_get_caps(fbdev, plane, &caps); - size += scnprintf(&buf[size], PAGE_SIZE - size, + size += sysfs_emit_at(buf, size, "plane#%d %#010x %#010x %#010x\n", plane, caps.ctrl, caps.plane_color, caps.wnd_color); plane++; @@ -1263,34 +1262,27 @@ static ssize_t omapfb_show_caps_text(struct device *dev, int i; struct omapfb_caps caps; int plane; - size_t size; + size_t size = 0; plane = 0; - size = 0; - while (size < PAGE_SIZE && plane < OMAPFB_PLANE_NUM) { + while (plane < OMAPFB_PLANE_NUM) { omapfb_get_caps(fbdev, plane, &caps); - size += scnprintf(&buf[size], PAGE_SIZE - size, - "plane#%d:\n", plane); - for (i = 0; i < ARRAY_SIZE(ctrl_caps) && - size < PAGE_SIZE; i++) { + size += sysfs_emit_at(buf, size, "plane#%d:\n", plane); + for (i = 0; i < ARRAY_SIZE(ctrl_caps); i++) { if (ctrl_caps[i].flag & caps.ctrl) - size += scnprintf(&buf[size], PAGE_SIZE - size, + size += sysfs_emit_at(buf, size, " %s\n", ctrl_caps[i].name); } - size += scnprintf(&buf[size], PAGE_SIZE - size, - " plane colors:\n"); - for (i = 0; i < ARRAY_SIZE(color_caps) && - size < PAGE_SIZE; i++) { + size += sysfs_emit_at(buf, size, " plane colors:\n"); + for (i = 0; i < ARRAY_SIZE(color_caps); i++) { if (color_caps[i].flag & caps.plane_color) - size += scnprintf(&buf[size], PAGE_SIZE - size, + size += sysfs_emit_at(buf, size, " %s\n", color_caps[i].name); } - size += scnprintf(&buf[size], PAGE_SIZE - size, - " window colors:\n"); - for (i = 0; i < ARRAY_SIZE(color_caps) && - size < PAGE_SIZE; i++) { + size += sysfs_emit_at(buf, size, " window colors:\n"); + for (i = 0; i < ARRAY_SIZE(color_caps); i++) { if (color_caps[i].flag & caps.wnd_color) - size += scnprintf(&buf[size], PAGE_SIZE - size, + size += sysfs_emit_at(buf, size, " %s\n", color_caps[i].name); } @@ -1833,7 +1825,7 @@ static int omapfb_resume(struct platform_device *pdev) static struct platform_driver omapfb_driver = { .probe = omapfb_probe, - .remove_new = omapfb_remove, + .remove = omapfb_remove, .suspend = omapfb_suspend, .resume = omapfb_resume, .driver = { diff --git a/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c index c6786726a1af..cef1603b7530 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-analog-tv.c @@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, tvc_of_match); static struct platform_driver tvc_connector_driver = { .probe = tvc_probe, - .remove_new = tvc_remove, + .remove = tvc_remove, .driver = { .name = "connector-analog-tv", .of_match_table = tvc_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c index 0cc9294f89b4..3f129ce9ff01 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-dvi.c @@ -328,7 +328,7 @@ MODULE_DEVICE_TABLE(of, dvic_of_match); static struct platform_driver dvi_connector_driver = { .probe = dvic_probe, - .remove_new = dvic_remove, + .remove = dvic_remove, .driver = { .name = "connector-dvi", .of_match_table = dvic_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c b/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c index b862a32670ae..e3df731172e8 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/connector-hdmi.c @@ -272,7 +272,7 @@ MODULE_DEVICE_TABLE(of, hdmic_of_match); static struct platform_driver hdmi_connector_driver = { .probe = hdmic_probe, - .remove_new = hdmic_remove, + .remove = hdmic_remove, .driver = { .name = "connector-hdmi", .of_match_table = hdmic_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c index f0d3eb581166..f4e7ed943b8a 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-opa362.c @@ -258,7 +258,7 @@ MODULE_DEVICE_TABLE(of, opa362_of_match); static struct platform_driver opa362_driver = { .probe = opa362_probe, - .remove_new = opa362_remove, + .remove = opa362_remove, .driver = { .name = "amplifier-opa362", .of_match_table = opa362_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c index c8aca4592949..458e65771cbb 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tfp410.c @@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, tfp410_of_match); static struct platform_driver tfp410_driver = { .probe = tfp410_probe, - .remove_new = tfp410_remove, + .remove = tfp410_remove, .driver = { .name = "tfp410", .of_match_table = tfp410_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c index eb3926d0361b..8cf0cb922f3c 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c @@ -311,7 +311,7 @@ MODULE_DEVICE_TABLE(of, tpd_of_match); static struct platform_driver tpd_driver = { .probe = tpd_probe, - .remove_new = tpd_remove, + .remove = tpd_remove, .driver = { .name = "tpd12s015", .of_match_table = tpd_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c index 937f9091274f..22f4262b2432 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dpi.c @@ -234,7 +234,7 @@ MODULE_DEVICE_TABLE(of, panel_dpi_of_match); static struct platform_driver panel_dpi_driver = { .probe = panel_dpi_probe, - .remove_new = panel_dpi_remove, + .remove = panel_dpi_remove, .driver = { .name = "panel-dpi", .of_match_table = panel_dpi_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c index adb8881bac28..1d75f27c6b80 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c @@ -356,11 +356,7 @@ static int dsicm_bl_update_status(struct backlight_device *dev) static int dsicm_bl_get_intensity(struct backlight_device *dev) { - if (dev->props.fb_blank == FB_BLANK_UNBLANK && - dev->props.power == FB_BLANK_UNBLANK) - return dev->props.brightness; - - return 0; + return backlight_get_brightness(dev); } static const struct backlight_ops dsicm_bl_ops = { @@ -1219,8 +1215,7 @@ static int dsicm_probe(struct platform_device *pdev) ddata->bldev = bldev; - bldev->props.fb_blank = FB_BLANK_UNBLANK; - bldev->props.power = FB_BLANK_UNBLANK; + bldev->props.power = BACKLIGHT_POWER_ON; bldev->props.brightness = 255; dsicm_bl_update_status(bldev); @@ -1258,7 +1253,7 @@ static void dsicm_remove(struct platform_device *pdev) bldev = ddata->bldev; if (bldev != NULL) { - bldev->props.power = FB_BLANK_POWERDOWN; + bldev->props.power = BACKLIGHT_POWER_OFF; dsicm_bl_update_status(bldev); backlight_device_unregister(bldev); } @@ -1280,7 +1275,7 @@ MODULE_DEVICE_TABLE(of, dsicm_of_match); static struct platform_driver dsicm_driver = { .probe = dsicm_probe, - .remove_new = dsicm_remove, + .remove = dsicm_remove, .driver = { .name = "panel-dsi-cm", .of_match_table = dsicm_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c index e37268cf8dca..888d94ea8e7d 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sharp-ls037v7dw01.c @@ -315,7 +315,7 @@ MODULE_DEVICE_TABLE(of, sharp_ls_of_match); static struct platform_driver sharp_ls_driver = { .probe = sharp_ls_probe, - .remove_new = sharp_ls_remove, + .remove = sharp_ls_remove, .driver = { .name = "panel-sharp-ls037v7dw01", .of_match_table = sharp_ls_of_match, diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c index 685c63aa4e03..8f430d9e8054 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-sony-acx565akm.c @@ -340,11 +340,7 @@ static int acx565akm_bl_update_status(struct backlight_device *dev) dev_dbg(&ddata->spi->dev, "%s\n", __func__); - if (dev->props.fb_blank == FB_BLANK_UNBLANK && - dev->props.power == FB_BLANK_UNBLANK) - level = dev->props.brightness; - else - level = 0; + level = backlight_get_brightness(dev); if (ddata->has_bc) acx565akm_set_brightness(ddata, level); @@ -363,8 +359,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev) if (!ddata->has_bc) return -ENODEV; - if (dev->props.fb_blank == FB_BLANK_UNBLANK && - dev->props.power == FB_BLANK_UNBLANK) { + if (!backlight_is_blank(dev)) { if (ddata->has_bc) return acx565akm_get_actual_brightness(ddata); else @@ -471,19 +466,20 @@ static ssize_t show_cabc_available_modes(struct device *dev, char *buf) { struct panel_drv_data *ddata = dev_get_drvdata(dev); - int len; + int len = 0; int i; if (!ddata->has_cabc) return sysfs_emit(buf, "%s\n", cabc_modes[0]); - for (i = 0, len = 0; - len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++) - len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s", - i ? " " : "", cabc_modes[i], - i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : ""); + for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) + len += sysfs_emit_at(buf, len, "%s ", cabc_modes[i]); + + /* Remove the trailing space */ + if (len) + buf[len - 1] = '\n'; - return len < PAGE_SIZE ? len : PAGE_SIZE - 1; + return len; } static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR, @@ -758,8 +754,7 @@ static int acx565akm_probe(struct spi_device *spi) } memset(&props, 0, sizeof(props)); - props.fb_blank = FB_BLANK_UNBLANK; - props.power = FB_BLANK_UNBLANK; + props.power = BACKLIGHT_POWER_ON; props.type = BACKLIGHT_RAW; bldev = backlight_device_register("acx565akm", &ddata->spi->dev, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/core.c b/drivers/video/fbdev/omap2/omapfb/dss/core.c index 5fbd8885bad8..55b640f2f245 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/core.c @@ -185,10 +185,10 @@ static void omap_dss_shutdown(struct platform_device *pdev) } static struct platform_driver omap_dss_driver = { - .remove_new = omap_dss_remove, + .remove = omap_dss_remove, .shutdown = omap_dss_shutdown, - .driver = { - .name = "omapdss", + .driver = { + .name = "omapdss", }, }; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c index 21fef9db90d2..1dc70c96d813 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c @@ -1230,17 +1230,6 @@ void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) dispc_write_reg(DISPC_OVL_PRELOAD(plane), min(high, 0xfffu)); } -void dispc_enable_fifomerge(bool enable) -{ - if (!dss_has_feature(FEAT_FIFO_MERGE)) { - WARN_ON(enable); - return; - } - - DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); - REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); -} - void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, bool manual_update) @@ -2670,13 +2659,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, row_inc = 0; pix_inc = 0; - if (plane == OMAP_DSS_WB) { - frame_width = out_width; - frame_height = out_height; - } else { - frame_width = in_width; - frame_height = height; - } + frame_width = in_width; + frame_height = height; if (rotation_type == OMAP_DSS_ROT_TILER) calc_tiler_rotation_offset(screen_width, frame_width, @@ -2749,9 +2733,13 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, bool mem_to_mem) { int r; - enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); + enum omap_overlay_caps caps; enum omap_channel channel; + if (plane == OMAP_DSS_WB) + return -EINVAL; + + caps = dss_feat_get_overlay_caps(plane); channel = dispc_ovl_get_channel_out(plane); DSSDBG("dispc_ovl_setup %d, pa %pad, pa_uv %pad, sw %d, %d,%d, %dx%d ->" @@ -3656,22 +3644,6 @@ void dispc_mgr_set_clock_div(enum omap_channel channel, dispc_mgr_set_lcd_divisor(channel, cinfo->lck_div, cinfo->pck_div); } -int dispc_mgr_get_clock_div(enum omap_channel channel, - struct dispc_clock_info *cinfo) -{ - unsigned long fck; - - fck = dispc_fclk_rate(); - - cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); - cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); - - cinfo->lck = fck / cinfo->lck_div; - cinfo->pck = cinfo->lck / cinfo->pck_div; - - return 0; -} - u32 dispc_read_irqstatus(void) { return dispc_read_reg(DISPC_IRQSTATUS); @@ -3960,18 +3932,13 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) return -ENODEV; } - if (np && of_property_read_bool(np, "syscon-pol")) { - dispc.syscon_pol = syscon_regmap_lookup_by_phandle(np, "syscon-pol"); + if (np && of_property_present(np, "syscon-pol")) { + dispc.syscon_pol = syscon_regmap_lookup_by_phandle_args(np, "syscon-pol", + 1, &dispc.syscon_pol_offset); if (IS_ERR(dispc.syscon_pol)) { dev_err(&pdev->dev, "failed to get syscon-pol regmap\n"); return PTR_ERR(dispc.syscon_pol); } - - if (of_property_read_u32_index(np, "syscon-pol", 1, - &dispc.syscon_pol_offset)) { - dev_err(&pdev->dev, "failed to get syscon-pol offset\n"); - return -EINVAL; - } } pm_runtime_enable(&pdev->dev); @@ -4072,7 +4039,7 @@ static const struct of_device_id dispc_of_match[] = { static struct platform_driver omap_dispchw_driver = { .probe = dispc_probe, - .remove_new = dispc_remove, + .remove = dispc_remove, .driver = { .name = "omapdss_dispc", .pm = &dispc_pm_ops, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dpi.c b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c index 7c1b7d89389a..86ed4c077c30 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dpi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c @@ -20,6 +20,7 @@ #include <linux/regulator/consumer.h> #include <linux/string.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/clk.h> #include <linux/component.h> @@ -817,8 +818,8 @@ static void dpi_remove(struct platform_device *pdev) static struct platform_driver omap_dpi_driver = { .probe = dpi_probe, - .remove_new = dpi_remove, - .driver = { + .remove = dpi_remove, + .driver = { .name = "omapdss_dpi", .suppress_bind_attrs = true, }, @@ -845,7 +846,7 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port) if (!dpi) return -ENOMEM; - ep = omapdss_of_get_next_endpoint(port, NULL); + ep = of_graph_get_next_port_endpoint(port, NULL); if (!ep) return 0; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c index b7eb17a16ec4..370e8623754e 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dsi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dsi.c @@ -28,6 +28,7 @@ #include <linux/debugfs.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/component.h> @@ -834,7 +835,7 @@ static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) #ifdef DSI_CATCH_MISSING_TE if (irqstatus & DSI_IRQ_TE_TRIGGER) - del_timer(&dsi->te_timer); + timer_delete(&dsi->te_timer); #endif /* make a copy and unlock, so that isrs can unregister @@ -5079,7 +5080,7 @@ static int dsi_probe_of(struct platform_device *pdev) struct device_node *ep; struct omap_dsi_pin_config pin_cfg; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return 0; @@ -5564,7 +5565,7 @@ static const struct of_device_id dsi_of_match[] = { static struct platform_driver omap_dsihw_driver = { .probe = dsi_probe, - .remove_new = dsi_remove, + .remove = dsi_remove, .driver = { .name = "omapdss_dsi", .pm = &dsi_pm_ops, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c index 0282d4eef139..7c636db79882 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c @@ -15,72 +15,6 @@ #include "dss.h" -struct device_node * -omapdss_of_get_next_port(const struct device_node *parent, - struct device_node *prev) -{ - struct device_node *port = NULL; - - if (!parent) - return NULL; - - if (!prev) { - struct device_node *ports; - /* - * It's the first call, we have to find a port subnode - * within this node or within an optional 'ports' node. - */ - ports = of_get_child_by_name(parent, "ports"); - if (ports) - parent = ports; - - port = of_get_child_by_name(parent, "port"); - - /* release the 'ports' node */ - of_node_put(ports); - } else { - struct device_node *ports; - - ports = of_get_parent(prev); - if (!ports) - return NULL; - - do { - port = of_get_next_child(ports, prev); - if (!port) { - of_node_put(ports); - return NULL; - } - prev = port; - } while (!of_node_name_eq(port, "port")); - - of_node_put(ports); - } - - return port; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); - -struct device_node * -omapdss_of_get_next_endpoint(const struct device_node *parent, - struct device_node *prev) -{ - struct device_node *ep = NULL; - - if (!parent) - return NULL; - - do { - ep = of_get_next_child(parent, prev); - if (!ep) - return NULL; - prev = ep; - } while (!of_node_name_eq(ep, "endpoint")); - - return ep; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); - struct device_node *dss_of_port_get_parent_device(struct device_node *port) { struct device_node *np; @@ -102,6 +36,7 @@ struct device_node *dss_of_port_get_parent_device(struct device_node *port) np = of_get_next_parent(np); } + of_node_put(np); return NULL; } @@ -117,37 +52,6 @@ u32 dss_of_port_get_port_number(struct device_node *port) return reg; } -static struct device_node *omapdss_of_get_remote_port(const struct device_node *node) -{ - struct device_node *np; - - np = of_graph_get_remote_endpoint(node); - if (!np) - return NULL; - - np = of_get_next_parent(np); - - return np; -} - -struct device_node * -omapdss_of_get_first_endpoint(const struct device_node *parent) -{ - struct device_node *port, *ep; - - port = omapdss_of_get_next_port(parent, NULL); - - if (!port) - return NULL; - - ep = omapdss_of_get_next_endpoint(port, NULL); - - of_node_put(port); - - return ep; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); - struct omap_dss_device * omapdss_of_find_source_for_first_ep(struct device_node *node) { @@ -155,17 +59,14 @@ omapdss_of_find_source_for_first_ep(struct device_node *node) struct device_node *src_port; struct omap_dss_device *src; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return ERR_PTR(-EINVAL); - src_port = omapdss_of_get_remote_port(ep); - if (!src_port) { - of_node_put(ep); - return ERR_PTR(-EINVAL); - } - + src_port = of_graph_get_remote_port(ep); of_node_put(ep); + if (!src_port) + return ERR_PTR(-EINVAL); src = omap_dss_find_output_by_port_node(src_port); diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c index d814e4baa4b3..3624a7fbdca8 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c @@ -26,6 +26,7 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/suspend.h> #include <linux/component.h> @@ -919,10 +920,7 @@ static int dss_init_ports(struct platform_device *pdev) struct device_node *port; int r, ret = 0; - if (parent == NULL) - return 0; - - port = omapdss_of_get_next_port(parent, NULL); + port = of_graph_get_next_port(parent, NULL); if (!port) return 0; @@ -952,8 +950,9 @@ static int dss_init_ports(struct platform_device *pdev) default: break; } - } while (!ret && - (port = omapdss_of_get_next_port(parent, port)) != NULL); + + port = of_graph_get_next_port(parent, port); + } while (!ret && port); if (ret) dss_uninit_ports(pdev); @@ -966,10 +965,7 @@ static void dss_uninit_ports(struct platform_device *pdev) struct device_node *parent = pdev->dev.of_node; struct device_node *port; - if (parent == NULL) - return; - - port = omapdss_of_get_next_port(parent, NULL); + port = of_graph_get_next_port(parent, NULL); if (!port) return; @@ -1000,7 +996,9 @@ static void dss_uninit_ports(struct platform_device *pdev) default: break; } - } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); + + port = of_graph_get_next_port(parent, port); + } while (port); } static int dss_video_pll_probe(struct platform_device *pdev) @@ -1278,7 +1276,7 @@ MODULE_DEVICE_TABLE(of, dss_of_match); static struct platform_driver omap_dsshw_driver = { .probe = dss_probe, - .remove_new = dss_remove, + .remove = dss_remove, .driver = { .name = "omapdss_dss", .pm = &dss_pm_ops, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.h b/drivers/video/fbdev/omap2/omapfb/dss/dss.h index 21cfcbf74a6d..a33a43f26829 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.h @@ -366,7 +366,6 @@ void dispc_disable_sidle(void); void dispc_lcd_enable_signal(bool enable); void dispc_pck_free_enable(bool enable); -void dispc_enable_fifomerge(bool enable); void dispc_enable_gamma_table(bool enable); typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, @@ -388,8 +387,6 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, void dispc_mgr_set_clock_div(enum omap_channel channel, const struct dispc_clock_info *cinfo); -int dispc_mgr_get_clock_div(enum omap_channel channel, - struct dispc_clock_info *cinfo); void dispc_set_tv_pclk(unsigned long pclk); u32 dispc_read_irqstatus(void); diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h b/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h index 9a7253355f6d..cdb1dedca492 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi.h @@ -351,7 +351,7 @@ struct omap_hdmi { bool audio_configured; struct omap_dss_audio audio_config; - /* This lock should be taken when booleans bellow are touched. */ + /* This lock should be taken when booleans below are touched. */ spinlock_t audio_playing_lock; bool audio_playing; bool display_enabled; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c index f05b4e35a842..428001fd4ac9 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi4.c @@ -20,6 +20,7 @@ #include <linux/pm_runtime.h> #include <linux/clk.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <video/omapfb_dss.h> @@ -529,7 +530,7 @@ static int hdmi_probe_of(struct platform_device *pdev) struct device_node *ep; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return 0; @@ -791,9 +792,9 @@ static const struct of_device_id hdmi_of_match[] = { static struct platform_driver omapdss_hdmihw_driver = { .probe = hdmi4_probe, - .remove_new = hdmi4_remove, - .driver = { - .name = "omapdss_hdmi", + .remove = hdmi4_remove, + .driver = { + .name = "omapdss_hdmi", .pm = &hdmi_pm_ops, .of_match_table = hdmi_of_match, .suppress_bind_attrs = true, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c index 03292945b1d4..aa052805050e 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5.c @@ -25,6 +25,7 @@ #include <linux/pm_runtime.h> #include <linux/clk.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/component.h> #include <video/omapfb_dss.h> @@ -561,7 +562,7 @@ static int hdmi_probe_of(struct platform_device *pdev) struct device_node *ep; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return 0; @@ -833,7 +834,7 @@ static const struct of_device_id hdmi_of_match[] = { static struct platform_driver omapdss_hdmihw_driver = { .probe = hdmi5_probe, - .remove_new = hdmi5_remove, + .remove = hdmi5_remove, .driver = { .name = "omapdss_hdmi5", .pm = &hdmi_pm_ops, diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c index b33f62c5cb22..bb7fe54dd019 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.c @@ -567,23 +567,6 @@ static void hdmi_core_enable_interrupts(struct hdmi_core_data *core) REG_FLD_MOD(core->base, HDMI_CORE_IH_MUTE, 0x0, 1, 0); } -int hdmi5_core_handle_irqs(struct hdmi_core_data *core) -{ - void __iomem *base = core->base; - - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT1, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_FC_STAT2, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_AS_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_PHY_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_I2CM_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_CEC_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_VP_STAT0, 0xff, 7, 0); - REG_FLD_MOD(base, HDMI_CORE_IH_I2CMPHY_STAT0, 0xff, 7, 0); - - return 0; -} - void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg) { diff --git a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h index 192c9b6e2f7b..493857374a15 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h +++ b/drivers/video/fbdev/omap2/omapfb/dss/hdmi5_core.h @@ -283,7 +283,6 @@ struct csc_table { int hdmi5_read_edid(struct hdmi_core_data *core, u8 *edid, int len); void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s); -int hdmi5_core_handle_irqs(struct hdmi_core_data *core); void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, struct hdmi_config *cfg); int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); diff --git a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c index 09f719af0d0c..d80720c84323 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/omapdss-boot-init.c @@ -149,8 +149,7 @@ static void __init omapdss_walk_device(struct device_node *node, bool root) of_node_put(n); - n = NULL; - while ((n = of_graph_get_next_endpoint(node, n)) != NULL) { + for_each_endpoint_of_node(node, n) { struct device_node *pn; pn = of_graph_get_remote_port_parent(n); diff --git a/drivers/video/fbdev/omap2/omapfb/dss/sdi.c b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c index d527931b2b16..2d3e5d4467c5 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/sdi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c @@ -16,6 +16,7 @@ #include <linux/platform_device.h> #include <linux/string.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/component.h> #include <video/omapfb_dss.h> @@ -382,9 +383,9 @@ static void sdi_remove(struct platform_device *pdev) static struct platform_driver omap_sdi_driver = { .probe = sdi_probe, - .remove_new = sdi_remove, - .driver = { - .name = "omapdss_sdi", + .remove = sdi_remove, + .driver = { + .name = "omapdss_sdi", .suppress_bind_attrs = true, }, }; @@ -405,7 +406,7 @@ int sdi_init_port(struct platform_device *pdev, struct device_node *port) u32 datapairs; int r; - ep = omapdss_of_get_next_endpoint(port, NULL); + ep = of_graph_get_next_port_endpoint(port, NULL); if (!ep) return 0; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/venc.c b/drivers/video/fbdev/omap2/omapfb/dss/venc.c index c9d40e28a06f..f99dda9e55a5 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/venc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/venc.c @@ -24,6 +24,7 @@ #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/component.h> #include <video/omapfb_dss.h> @@ -764,7 +765,7 @@ static int venc_probe_of(struct platform_device *pdev) u32 channels; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, -1); if (!ep) return 0; @@ -902,9 +903,7 @@ static int venc_runtime_resume(struct device *dev) if (r < 0) return r; - clk_prepare_enable(venc.tv_dac_clk); - - return 0; + return clk_prepare_enable(venc.tv_dac_clk); } static const struct dev_pm_ops venc_pm_ops = { @@ -921,9 +920,9 @@ static const struct of_device_id venc_of_match[] = { static struct platform_driver omap_venchw_driver = { .probe = venc_probe, - .remove_new = venc_remove, - .driver = { - .name = "omapdss_venc", + .remove = venc_remove, + .driver = { + .name = "omapdss_venc", .pm = &venc_pm_ops, .of_match_table = venc_of_match, .suppress_bind_attrs = true, diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c index 0db9c55fce5a..211f23648686 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c @@ -2614,7 +2614,7 @@ static void omapfb_remove(struct platform_device *pdev) static struct platform_driver omapfb_driver = { .probe = omapfb_probe, - .remove_new = omapfb_remove, + .remove = omapfb_remove, .driver = { .name = "omapfb", }, diff --git a/drivers/video/fbdev/p9100.c b/drivers/video/fbdev/p9100.c index e1356f8a866e..0bc0f78fe4b9 100644 --- a/drivers/video/fbdev/p9100.c +++ b/drivers/video/fbdev/p9100.c @@ -206,7 +206,7 @@ p9100_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map p9100_mmap_map[] = { +static const struct sbus_mmap_map p9100_mmap_map[] = { { CG3_MMAP_OFFSET, 0, SBUS_MMAP_FBSIZE(1) }, { 0, 0, 0 } }; @@ -347,7 +347,7 @@ static struct platform_driver p9100_driver = { .of_match_table = p9100_match, }, .probe = p9100_probe, - .remove_new = p9100_remove, + .remove = p9100_remove, }; static int __init p9100_init(void) diff --git a/drivers/video/fbdev/platinumfb.c b/drivers/video/fbdev/platinumfb.c index cb6fcc64c8e2..a08d955d9b43 100644 --- a/drivers/video/fbdev/platinumfb.c +++ b/drivers/video/fbdev/platinumfb.c @@ -668,7 +668,7 @@ static struct platform_driver platinum_driver = .of_match_table = platinumfb_match, }, .probe = platinumfb_probe, - .remove_new = platinumfb_remove, + .remove = platinumfb_remove, }; static int __init platinumfb_init(void) diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c index adee34386580..ec602f7776eb 100644 --- a/drivers/video/fbdev/pxa168fb.c +++ b/drivers/video/fbdev/pxa168fb.c @@ -799,7 +799,7 @@ static struct platform_driver pxa168fb_driver = { .name = "pxa168-fb", }, .probe = pxa168fb_probe, - .remove_new = pxa168fb_remove, + .remove = pxa168fb_remove, }; module_platform_driver(pxa168fb_driver); diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c index 43c80316d84b..4a78b387b343 100644 --- a/drivers/video/fbdev/pxa3xx-gcu.c +++ b/drivers/video/fbdev/pxa3xx-gcu.c @@ -594,8 +594,8 @@ static int pxa3xx_gcu_probe(struct platform_device *pdev) * container_of(). This isn't really necessary as we have a fixed minor * number anyway, but this is to avoid statics. */ - priv->misc_dev.minor = PXA3XX_GCU_MINOR, - priv->misc_dev.name = DRV_NAME, + priv->misc_dev.minor = PXA3XX_GCU_MINOR; + priv->misc_dev.name = DRV_NAME; priv->misc_dev.fops = &pxa3xx_gcu_miscdev_fops; /* handle IO resources */ @@ -696,10 +696,10 @@ MODULE_DEVICE_TABLE(of, pxa3xx_gcu_of_match); #endif static struct platform_driver pxa3xx_gcu_driver = { - .probe = pxa3xx_gcu_probe, - .remove_new = pxa3xx_gcu_remove, - .driver = { - .name = DRV_NAME, + .probe = pxa3xx_gcu_probe, + .remove = pxa3xx_gcu_remove, + .driver = { + .name = DRV_NAME, .of_match_table = of_match_ptr(pxa3xx_gcu_of_match), }, }; diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index fa943612c4e2..ee6da5084242 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -2171,7 +2171,7 @@ static int of_get_pxafb_mode_info(struct device *dev, u32 bus_width; int ret, i; - np = of_graph_get_next_endpoint(dev->of_node, NULL); + np = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); if (!np) { dev_err(dev, "could not find endpoint\n"); return -EINVAL; @@ -2233,32 +2233,27 @@ static int pxafb_probe(struct platform_device *dev) { struct pxafb_info *fbi; struct pxafb_mach_info *inf, *pdata; - int i, irq, ret; + int irq, ret; dev_dbg(&dev->dev, "pxafb_probe\n"); ret = -ENOMEM; pdata = dev_get_platdata(&dev->dev); - inf = devm_kmalloc(&dev->dev, sizeof(*inf), GFP_KERNEL); - if (!inf) - goto failed; - if (pdata) { - *inf = *pdata; - inf->modes = - devm_kmalloc_array(&dev->dev, pdata->num_modes, - sizeof(inf->modes[0]), GFP_KERNEL); + inf = devm_kmemdup(&dev->dev, pdata, sizeof(*pdata), GFP_KERNEL); + if (!inf) + goto failed; + + inf->modes = devm_kmemdup_array(&dev->dev, pdata->modes, pdata->num_modes, + sizeof(*pdata->modes), GFP_KERNEL); if (!inf->modes) goto failed; - for (i = 0; i < inf->num_modes; i++) - inf->modes[i] = pdata->modes[i]; } else { inf = of_pxafb_of_mach_info(&dev->dev); + if (IS_ERR_OR_NULL(inf)) + goto failed; } - if (IS_ERR_OR_NULL(inf)) - goto failed; - ret = pxafb_parse_options(&dev->dev, g_options, inf); if (ret < 0) goto failed; @@ -2403,6 +2398,7 @@ static void pxafb_remove(struct platform_device *dev) info = &fbi->fb; pxafb_overlay_exit(fbi); + cancel_work_sync(&fbi->task); unregister_framebuffer(info); pxafb_disable_controller(fbi); @@ -2426,7 +2422,7 @@ MODULE_DEVICE_TABLE(of, pxafb_of_dev_id); static struct platform_driver pxafb_driver = { .probe = pxafb_probe, - .remove_new = pxafb_remove, + .remove = pxafb_remove, .driver = { .name = "pxa2xx-fb", .of_match_table = pxafb_of_dev_id, diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 237db738af13..1e377b2ec089 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -347,7 +347,7 @@ static void riva_bl_init(struct riva_par *par) FB_BACKLIGHT_MAX); bd->props.brightness = bd->props.max_brightness; - bd->props.power = FB_BLANK_UNBLANK; + bd->props.power = BACKLIGHT_POWER_ON; backlight_update_status(bd); printk("riva: Backlight initialized (%s)\n", name); diff --git a/drivers/video/fbdev/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c index 0e871197c6de..e80c806ef520 100644 --- a/drivers/video/fbdev/s1d13xxxfb.c +++ b/drivers/video/fbdev/s1d13xxxfb.c @@ -1001,7 +1001,7 @@ static int s1d13xxxfb_resume(struct platform_device *dev) static struct platform_driver s1d13xxxfb_driver = { .probe = s1d13xxxfb_probe, - .remove_new = s1d13xxxfb_remove, + .remove = s1d13xxxfb_remove, #ifdef CONFIG_PM .suspend = s1d13xxxfb_suspend, .resume = s1d13xxxfb_resume, diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c index 2b85aad6a304..2f4d707e2e09 100644 --- a/drivers/video/fbdev/s3c-fb.c +++ b/drivers/video/fbdev/s3c-fb.c @@ -1789,7 +1789,7 @@ static const struct dev_pm_ops s3cfb_pm_ops = { static struct platform_driver s3c_fb_driver = { .probe = s3c_fb_probe, - .remove_new = s3c_fb_remove, + .remove = s3c_fb_remove, .id_table = s3c_fb_driver_ids, .driver = { .name = "s3c-fb", diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index ebc9aeffdde7..ac41f8f37589 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -2276,7 +2276,10 @@ static int savagefb_probe(struct pci_dev *dev, const struct pci_device_id *id) if (info->var.xres_virtual > 0x1000) info->var.xres_virtual = 0x1000; #endif - savagefb_check_var(&info->var, info); + err = savagefb_check_var(&info->var, info); + if (err) + goto failed; + savagefb_set_fix(info); /* diff --git a/drivers/video/fbdev/sbuslib.c b/drivers/video/fbdev/sbuslib.c index 634e3d159452..4c79654bda30 100644 --- a/drivers/video/fbdev/sbuslib.c +++ b/drivers/video/fbdev/sbuslib.c @@ -38,7 +38,7 @@ static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize) return fbsize * (-size); } -int sbusfb_mmap_helper(struct sbus_mmap_map *map, +int sbusfb_mmap_helper(const struct sbus_mmap_map *map, unsigned long physbase, unsigned long fbsize, unsigned long iospace, diff --git a/drivers/video/fbdev/sbuslib.h b/drivers/video/fbdev/sbuslib.h index 6466b4cbcd7b..e9af2dc93f94 100644 --- a/drivers/video/fbdev/sbuslib.h +++ b/drivers/video/fbdev/sbuslib.h @@ -19,7 +19,7 @@ struct sbus_mmap_map { extern void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp, int bpp); -extern int sbusfb_mmap_helper(struct sbus_mmap_map *map, +extern int sbusfb_mmap_helper(const struct sbus_mmap_map *map, unsigned long physbase, unsigned long fbsize, unsigned long iospace, struct vm_area_struct *vma); diff --git a/drivers/video/fbdev/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c index 08a4943dc541..130adef2e468 100644 --- a/drivers/video/fbdev/sh7760fb.c +++ b/drivers/video/fbdev/sh7760fb.c @@ -409,12 +409,11 @@ static int sh7760fb_alloc_mem(struct fb_info *info) vram = PAGE_SIZE; fbmem = dma_alloc_coherent(info->device, vram, &par->fbdma, GFP_KERNEL); - if (!fbmem) return -ENOMEM; if ((par->fbdma & SH7760FB_DMA_MASK) != SH7760FB_DMA_MASK) { - sh7760fb_free_mem(info); + dma_free_coherent(info->device, vram, fbmem, par->fbdma); dev_err(info->device, "kernel gave me memory at 0x%08lx, which is" "unusable for the LCDC\n", (unsigned long)par->fbdma); return -ENOMEM; @@ -575,7 +574,7 @@ static struct platform_driver sh7760_lcdc_driver = { .name = "sh7760-lcdc", }, .probe = sh7760fb_probe, - .remove_new = sh7760fb_remove, + .remove = sh7760fb_remove, }; module_platform_driver(sh7760_lcdc_driver); diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index eb2297b37504..dd950e4ab5ce 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -1049,7 +1049,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) sh_mobile_lcdc_display_on(ch); if (ch->bl) { - ch->bl->props.power = FB_BLANK_UNBLANK; + ch->bl->props.power = BACKLIGHT_POWER_ON; backlight_update_status(ch->bl); } } @@ -1082,7 +1082,7 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) } if (ch->bl) { - ch->bl->props.power = FB_BLANK_POWERDOWN; + ch->bl->props.power = BACKLIGHT_POWER_OFF; backlight_update_status(ch->bl); } @@ -1338,16 +1338,19 @@ overlay_rop3_store(struct device *dev, struct device_attribute *attr, return count; } -static const struct device_attribute overlay_sysfs_attrs[] = { - __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, - overlay_alpha_show, overlay_alpha_store), - __ATTR(ovl_mode, S_IRUGO|S_IWUSR, - overlay_mode_show, overlay_mode_store), - __ATTR(ovl_position, S_IRUGO|S_IWUSR, - overlay_position_show, overlay_position_store), - __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, - overlay_rop3_show, overlay_rop3_store), +static DEVICE_ATTR_RW(overlay_alpha); +static DEVICE_ATTR_RW(overlay_mode); +static DEVICE_ATTR_RW(overlay_position); +static DEVICE_ATTR_RW(overlay_rop3); + +static struct attribute *overlay_sysfs_attrs[] = { + &dev_attr_overlay_alpha.attr, + &dev_attr_overlay_mode.attr, + &dev_attr_overlay_position.attr, + &dev_attr_overlay_rop3.attr, + NULL, }; +ATTRIBUTE_GROUPS(overlay_sysfs); static const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { .id = "SH Mobile LCDC", @@ -1516,7 +1519,6 @@ sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) { struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; struct fb_info *info = ovl->info; - unsigned int i; int ret; if (info == NULL) @@ -1530,12 +1532,6 @@ sh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) dev_name(lcdc->dev), ovl->index, info->var.xres, info->var.yres, info->var.bits_per_pixel); - for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { - ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); - if (ret < 0) - return ret; - } - return 0; } @@ -1575,7 +1571,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) */ info->fix = sh_mobile_lcdc_overlay_fix; snprintf(info->fix.id, sizeof(info->fix.id), - "SH Mobile LCDC Overlay %u", ovl->index); + "SHMobile ovl %u", ovl->index); info->fix.smem_start = ovl->dma_handle; info->fix.smem_len = ovl->fb_size; info->fix.line_length = ovl->pitch; @@ -2123,11 +2119,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, static int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) { struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); - int brightness = bdev->props.brightness; - - if (bdev->props.power != FB_BLANK_UNBLANK || - bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) - brightness = 0; + int brightness = backlight_get_brightness(bdev); ch->bl_brightness = brightness; return ch->cfg->bl_info.set_brightness(brightness); @@ -2140,17 +2132,10 @@ static int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) return ch->bl_brightness; } -static int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, - struct fb_info *info) -{ - return (info->bl_dev == bdev); -} - static const struct backlight_ops sh_mobile_lcdc_bl_ops = { .options = BL_CORE_SUSPENDRESUME, .update_status = sh_mobile_lcdc_update_bl, .get_brightness = sh_mobile_lcdc_get_brightness, - .check_fb = sh_mobile_lcdc_check_fb, }; static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent, @@ -2652,10 +2637,11 @@ err1: static struct platform_driver sh_mobile_lcdc_driver = { .driver = { .name = "sh_mobile_lcdc_fb", + .dev_groups = overlay_sysfs_groups, .pm = &sh_mobile_lcdc_dev_pm_ops, }, .probe = sh_mobile_lcdc_probe, - .remove_new = sh_mobile_lcdc_remove, + .remove = sh_mobile_lcdc_remove, }; module_platform_driver(sh_mobile_lcdc_driver); diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c index 028a56525047..be95fcddce4c 100644 --- a/drivers/video/fbdev/simplefb.c +++ b/drivers/video/fbdev/simplefb.c @@ -677,7 +677,7 @@ static struct platform_driver simplefb_driver = { .of_match_table = simplefb_of_match, }, .probe = simplefb_probe, - .remove_new = simplefb_remove, + .remove = simplefb_remove, }; module_platform_driver(simplefb_driver); diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c index a8fb41f1a258..09329072004f 100644 --- a/drivers/video/fbdev/sis/init301.c +++ b/drivers/video/fbdev/sis/init301.c @@ -172,7 +172,7 @@ static const unsigned char SiS_HiTVGroup3_2[] = { }; /* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */ - +#ifdef CONFIG_FB_SIS_315 static const unsigned char SiS_Part2CLVX_1[] = { 0x00,0x00, 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E, @@ -245,7 +245,6 @@ static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */ 0xFF,0xFF, }; -#ifdef CONFIG_FB_SIS_315 /* 661 et al LCD data structure (2.03.00) */ static const unsigned char SiS_LCDStruct661[] = { /* 1024x768 */ diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index 009bf1d92644..75033e6be15a 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -183,7 +183,7 @@ static void sisfb_search_mode(char *name, bool quiet) { unsigned int j = 0, xres = 0, yres = 0, depth = 0, rate = 0; int i = 0; - char strbuf[16], strbuf1[20]; + char strbuf[24], strbuf1[20]; char *nameptr = name; /* We don't know the hardware specs yet and there is no ivideo */ diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index d6fdc1737cd2..ed6f4f43e2d5 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -27,6 +27,7 @@ #include <linux/clk.h> #include <linux/console.h> #include <linux/io.h> +#include <linux/string_choices.h> #include <linux/uaccess.h> #include <asm/div64.h> @@ -326,6 +327,13 @@ static int sm501fb_check_var(struct fb_var_screeninfo *var, if (var->xres_virtual > 4096 || var->yres_virtual > 2048) return -EINVAL; + /* geometry sanity checks */ + if (var->xres + var->xoffset > var->xres_virtual) + return -EINVAL; + + if (var->yres + var->yoffset > var->yres_virtual) + return -EINVAL; + /* can cope with 8,16 or 32bpp */ if (var->bits_per_pixel <= 8) @@ -1712,8 +1720,8 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, BUG(); } - dev_info(info->dev, "fb %s %sabled at start\n", - fbname, enable ? "en" : "dis"); + dev_info(info->dev, "fb %s %s at start\n", + fbname, str_enabled_disabled(enable)); /* check to see if our routing allows this */ @@ -2211,7 +2219,7 @@ static int sm501fb_resume(struct platform_device *pdev) static struct platform_driver sm501fb_driver = { .probe = sm501fb_probe, - .remove_new = sm501fb_remove, + .remove = sm501fb_remove, .suspend = sm501fb_suspend, .resume = sm501fb_resume, .driver = { diff --git a/drivers/video/fbdev/smscufx.c b/drivers/video/fbdev/smscufx.c index 35d682b110c4..5f0dd01fd834 100644 --- a/drivers/video/fbdev/smscufx.c +++ b/drivers/video/fbdev/smscufx.c @@ -1292,7 +1292,7 @@ static int ufx_realloc_framebuffer(struct ufx_data *dev, struct fb_info *info) return 0; } -/* sets up I2C Controller for 100 Kbps, std. speed, 7-bit addr, master, +/* sets up DDC channel for 100 Kbps, std. speed, 7-bit addr, controller mode, * restart enabled, but no start byte, enable controller */ static int ufx_i2c_init(struct ufx_data *dev) { @@ -1321,7 +1321,7 @@ static int ufx_i2c_init(struct ufx_data *dev) /* 7-bit (not 10-bit) addressing */ tmp &= ~(0x10); - /* enable restart conditions and master mode */ + /* enable restart conditions and controller mode */ tmp |= 0x21; status = ufx_reg_write(dev, 0x1000, tmp); diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 1a4f90ea7d5a..aa6cc0a8151a 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -530,17 +530,10 @@ static int ssd1307fb_get_brightness(struct backlight_device *bdev) return par->contrast; } -static int ssd1307fb_check_fb(struct backlight_device *bdev, - struct fb_info *info) -{ - return (info->bl_dev == bdev); -} - static const struct backlight_ops ssd1307fb_bl_ops = { .options = BL_CORE_SUSPENDRESUME, .update_status = ssd1307fb_update_bl, .get_brightness = ssd1307fb_get_brightness, - .check_fb = ssd1307fb_check_fb, }; static struct ssd1307fb_deviceinfo ssd1307fb_ssd1305_deviceinfo = { @@ -594,7 +587,6 @@ static int ssd1307fb_probe(struct i2c_client *client) { struct device *dev = &client->dev; struct backlight_device *bl; - char bl_name[12]; struct fb_info *info; struct fb_deferred_io *ssd1307fb_defio; u32 vmem_size; @@ -733,31 +725,30 @@ static int ssd1307fb_probe(struct i2c_client *client) if (ret) goto regulator_enable_error; - ret = register_framebuffer(info); - if (ret) { - dev_err(dev, "Couldn't register the framebuffer\n"); - goto panel_init_error; - } - - snprintf(bl_name, sizeof(bl_name), "ssd1307fb%d", info->node); - bl = backlight_device_register(bl_name, dev, par, &ssd1307fb_bl_ops, + bl = backlight_device_register("ssd1307fb-bl", dev, par, &ssd1307fb_bl_ops, NULL); if (IS_ERR(bl)) { ret = PTR_ERR(bl); dev_err(dev, "unable to register backlight device: %d\n", ret); - goto bl_init_error; + goto panel_init_error; + } + info->bl_dev = bl; + + ret = register_framebuffer(info); + if (ret) { + dev_err(dev, "Couldn't register the framebuffer\n"); + goto fb_init_error; } bl->props.brightness = par->contrast; bl->props.max_brightness = MAX_CONTRAST; - info->bl_dev = bl; dev_info(dev, "fb%d: %s framebuffer device registered, using %d bytes of video memory\n", info->node, info->fix.id, vmem_size); return 0; -bl_init_error: - unregister_framebuffer(info); +fb_init_error: + backlight_device_unregister(bl); panel_init_error: pwm_disable(par->pwm); pwm_put(par->pwm); @@ -791,10 +782,10 @@ static void ssd1307fb_remove(struct i2c_client *client) } static const struct i2c_device_id ssd1307fb_i2c_id[] = { - { "ssd1305fb", 0 }, - { "ssd1306fb", 0 }, - { "ssd1307fb", 0 }, - { "ssd1309fb", 0 }, + { "ssd1305fb" }, + { "ssd1306fb" }, + { "ssd1307fb" }, + { "ssd1309fb" }, { } }; MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); diff --git a/drivers/video/fbdev/sstfb.c b/drivers/video/fbdev/sstfb.c index f8ae54ca0cc3..2ea947f57efb 100644 --- a/drivers/video/fbdev/sstfb.c +++ b/drivers/video/fbdev/sstfb.c @@ -716,6 +716,7 @@ static void sstfb_setvgapass( struct fb_info *info, int enable ) pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); } +#ifdef CONFIG_FB_DEVICE static ssize_t store_vgapass(struct device *device, struct device_attribute *attr, const char *buf, size_t count) { @@ -739,7 +740,8 @@ static ssize_t show_vgapass(struct device *device, struct device_attribute *attr static struct device_attribute device_attrs[] = { __ATTR(vgapass, S_IRUGO|S_IWUSR, show_vgapass, store_vgapass) - }; +}; +#endif static int sstfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) @@ -1436,9 +1438,10 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) sstfb_clear_screen(info); +#ifdef CONFIG_FB_DEVICE if (device_create_file(info->dev, &device_attrs[0])) printk(KERN_WARNING "sstfb: can't create sysfs entry.\n"); - +#endif fb_info(info, "%s frame buffer device at 0x%p\n", fix->id, info->screen_base); @@ -1468,7 +1471,9 @@ static void sstfb_remove(struct pci_dev *pdev) info = pci_get_drvdata(pdev); par = info->par; +#ifdef CONFIG_FB_DEVICE device_remove_file(info->dev, &device_attrs[0]); +#endif sst_shutdown(info); iounmap(info->screen_base); iounmap(par->mmio_vbase); diff --git a/drivers/video/fbdev/tcx.c b/drivers/video/fbdev/tcx.c index fe7b7bc77eda..f9a0085ad72b 100644 --- a/drivers/video/fbdev/tcx.c +++ b/drivers/video/fbdev/tcx.c @@ -236,7 +236,7 @@ tcx_blank(int blank, struct fb_info *info) return 0; } -static struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { +static const struct sbus_mmap_map __tcx_mmap_map[TCX_MMAP_ENTRIES] = { { .voff = TCX_RAM8BIT, .size = SBUS_MMAP_FBSIZE(1) @@ -505,7 +505,7 @@ static struct platform_driver tcx_driver = { .of_match_table = tcx_match, }, .probe = tcx_probe, - .remove_new = tcx_remove, + .remove = tcx_remove, }; static int __init tcx_init(void) diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index 1514ddac4caf..acadf0eb450c 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -23,7 +23,7 @@ #include <linux/vmalloc.h> #include <linux/slab.h> #include <linux/delay.h> -#include <asm/unaligned.h> +#include <linux/unaligned.h> #include <video/udlfb.h> #include "edid.h" @@ -1416,7 +1416,7 @@ static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev, static ssize_t edid_show( struct file *filp, - struct kobject *kobj, struct bin_attribute *a, + struct kobject *kobj, const struct bin_attribute *a, char *buf, loff_t off, size_t count) { struct device *fbdev = kobj_to_dev(kobj); struct fb_info *fb_info = dev_get_drvdata(fbdev); @@ -1438,7 +1438,7 @@ static ssize_t edid_show( static ssize_t edid_store( struct file *filp, - struct kobject *kobj, struct bin_attribute *a, + struct kobject *kobj, const struct bin_attribute *a, char *src, loff_t src_off, size_t src_size) { struct device *fbdev = kobj_to_dev(kobj); struct fb_info *fb_info = dev_get_drvdata(fbdev); @@ -1482,8 +1482,8 @@ static const struct bin_attribute edid_attr = { .attr.name = "edid", .attr.mode = 0666, .size = EDID_LENGTH, - .read = edid_show, - .write = edid_store + .read_new = edid_show, + .write_new = edid_store }; static const struct device_attribute fb_device_attrs[] = { diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c index 73f00c079a94..5d52fd00806e 100644 --- a/drivers/video/fbdev/uvesafb.c +++ b/drivers/video/fbdev/uvesafb.c @@ -1794,7 +1794,7 @@ static void uvesafb_remove(struct platform_device *dev) static struct platform_driver uvesafb_driver = { .probe = uvesafb_probe, - .remove_new = uvesafb_remove, + .remove = uvesafb_remove, .driver = { .name = "uvesafb", }, @@ -1867,7 +1867,7 @@ static ssize_t v86d_show(struct device_driver *dev, char *buf) static ssize_t v86d_store(struct device_driver *dev, const char *buf, size_t count) { - strncpy(v86d_path, buf, PATH_MAX - 1); + strscpy_pad(v86d_path, buf); return count; } static DRIVER_ATTR_RW(v86d); diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c index 8ab64ae4cad3..a81df8865143 100644 --- a/drivers/video/fbdev/vesafb.c +++ b/drivers/video/fbdev/vesafb.c @@ -271,7 +271,7 @@ static int vesafb_probe(struct platform_device *dev) if (si->orig_video_isVGA != VIDEO_TYPE_VLFB) return -ENODEV; - vga_compat = (si->capabilities & 2) ? 0 : 1; + vga_compat = !__screen_info_vbe_mode_nonvga(si); vesafb_fix.smem_start = si->lfb_base; vesafb_defined.bits_per_pixel = si->lfb_depth; if (15 == vesafb_defined.bits_per_pixel) @@ -515,7 +515,7 @@ static struct platform_driver vesafb_driver = { .name = "vesa-framebuffer", }, .probe = vesafb_probe, - .remove_new = vesafb_remove, + .remove = vesafb_remove, }; module_platform_driver(vesafb_driver); diff --git a/drivers/video/fbdev/vfb.c b/drivers/video/fbdev/vfb.c index f86149ba3835..5b7965f36c5e 100644 --- a/drivers/video/fbdev/vfb.c +++ b/drivers/video/fbdev/vfb.c @@ -493,7 +493,7 @@ static void vfb_remove(struct platform_device *dev) static struct platform_driver vfb_driver = { .probe = vfb_probe, - .remove_new = vfb_remove, + .remove = vfb_remove, .driver = { .name = "vfb", }, @@ -546,5 +546,6 @@ static void __exit vfb_exit(void) module_exit(vfb_exit); +MODULE_DESCRIPTION("Virtual Frame Buffer driver"); MODULE_LICENSE("GPL"); #endif /* MODULE */ diff --git a/drivers/video/fbdev/vga16fb.c b/drivers/video/fbdev/vga16fb.c index a87bafbb119c..eedab14c7d51 100644 --- a/drivers/video/fbdev/vga16fb.c +++ b/drivers/video/fbdev/vga16fb.c @@ -185,9 +185,10 @@ static inline void setindex(int index) /* Check if the video mode is supported by the driver */ static inline int check_mode_supported(const struct screen_info *si) { + unsigned int type = screen_info_video_type(si); + /* only EGA and VGA in 16 color graphic mode are supported */ - if (si->orig_video_isVGA != VIDEO_TYPE_EGAC && - si->orig_video_isVGA != VIDEO_TYPE_VGAC) + if (type != VIDEO_TYPE_EGAC && type != VIDEO_TYPE_VGAC) return -ENODEV; if (si->orig_video_mode != 0x0D && /* 320x200/4 (EGA) */ @@ -1338,7 +1339,7 @@ static int vga16fb_probe(struct platform_device *dev) printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base); par = info->par; - par->isVGA = si->orig_video_isVGA == VIDEO_TYPE_VGAC; + par->isVGA = screen_info_video_type(si) == VIDEO_TYPE_VGAC; par->palette_blanked = 0; par->vesa_blanked = 0; @@ -1417,7 +1418,7 @@ MODULE_DEVICE_TABLE(platform, vga16fb_driver_id_table); static struct platform_driver vga16fb_driver = { .probe = vga16fb_probe, - .remove_new = vga16fb_remove, + .remove = vga16fb_remove, .driver = { .name = "vga16fb", }, diff --git a/drivers/video/fbdev/via/chip.h b/drivers/video/fbdev/via/chip.h index f0a19cbcb9e5..f81af13630e2 100644 --- a/drivers/video/fbdev/via/chip.h +++ b/drivers/video/fbdev/via/chip.h @@ -69,7 +69,7 @@ #define VT1632_TMDS 0x01 #define INTEGRATED_TMDS 0x42 -/* Definition TMDS Trasmitter I2C Slave Address */ +/* Definition TMDS Trasmitter I2C Target Address */ #define VT1632_TMDS_I2C_ADDR 0x10 /**************************************************/ @@ -88,21 +88,21 @@ #define TX_DATA_DDR_MODE 0x04 #define TX_DATA_SDR_MODE 0x08 -/* Definition LVDS Trasmitter I2C Slave Address */ +/* Definition LVDS Trasmitter I2C Target Address */ #define VT1631_LVDS_I2C_ADDR 0x70 #define VT3271_LVDS_I2C_ADDR 0x80 #define VT1636_LVDS_I2C_ADDR 0x80 struct tmds_chip_information { int tmds_chip_name; - int tmds_chip_slave_addr; + int tmds_chip_target_addr; int output_interface; int i2c_port; }; struct lvds_chip_information { int lvds_chip_name; - int lvds_chip_slave_addr; + int lvds_chip_target_addr; int output_interface; int i2c_port; }; diff --git a/drivers/video/fbdev/via/dvi.c b/drivers/video/fbdev/via/dvi.c index 13147e3066eb..27990a73bfa3 100644 --- a/drivers/video/fbdev/via/dvi.c +++ b/drivers/video/fbdev/via/dvi.c @@ -70,7 +70,7 @@ bool viafb_tmds_trasmitter_identify(void) /* Check for VT1632: */ viaparinfo->chip_info->tmds_chip_info.tmds_chip_name = VT1632_TMDS; viaparinfo->chip_info-> - tmds_chip_info.tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; + tmds_chip_info.tmds_chip_target_addr = VT1632_TMDS_I2C_ADDR; viaparinfo->chip_info->tmds_chip_info.i2c_port = VIA_PORT_31; if (check_tmds_chip(VT1632_DEVICE_ID_REG, VT1632_DEVICE_ID)) { /* @@ -128,14 +128,14 @@ bool viafb_tmds_trasmitter_identify(void) viaparinfo->chip_info-> tmds_chip_info.tmds_chip_name = NON_TMDS_TRANSMITTER; viaparinfo->chip_info->tmds_chip_info. - tmds_chip_slave_addr = VT1632_TMDS_I2C_ADDR; + tmds_chip_target_addr = VT1632_TMDS_I2C_ADDR; return false; } static void tmds_register_write(int index, u8 data) { viafb_i2c_writebyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr, index, data); } @@ -144,7 +144,7 @@ static int tmds_register_read(int index) u8 data; viafb_i2c_readbyte(viaparinfo->chip_info->tmds_chip_info.i2c_port, - (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr, (u8) index, &data); return data; } @@ -152,7 +152,7 @@ static int tmds_register_read(int index) static int tmds_register_read_bytes(int index, u8 *buff, int buff_len) { viafb_i2c_readbytes(viaparinfo->chip_info->tmds_chip_info.i2c_port, - (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr, + (u8) viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr, (u8) index, buff, buff_len); return 0; } @@ -256,14 +256,14 @@ static int viafb_dvi_query_EDID(void) DEBUG_MSG(KERN_INFO "viafb_dvi_query_EDID!!\n"); - restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr; - viaparinfo->chip_info->tmds_chip_info.tmds_chip_slave_addr = 0xA0; + restore = viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr; + viaparinfo->chip_info->tmds_chip_info.tmds_chip_target_addr = 0xA0; data0 = (u8) tmds_register_read(0x00); data1 = (u8) tmds_register_read(0x01); if ((data0 == 0) && (data1 == 0xFF)) { viaparinfo->chip_info-> - tmds_chip_info.tmds_chip_slave_addr = restore; + tmds_chip_info.tmds_chip_target_addr = restore; return EDID_VERSION_1; /* Found EDID1 Table */ } @@ -280,8 +280,8 @@ static void dvi_get_panel_size_from_DDCv1( DEBUG_MSG(KERN_INFO "\n dvi_get_panel_size_from_DDCv1 \n"); - restore = tmds_chip->tmds_chip_slave_addr; - tmds_chip->tmds_chip_slave_addr = 0xA0; + restore = tmds_chip->tmds_chip_target_addr; + tmds_chip->tmds_chip_target_addr = 0xA0; for (i = 0x25; i < 0x6D; i++) { switch (i) { case 0x36: @@ -306,7 +306,7 @@ static void dvi_get_panel_size_from_DDCv1( DEBUG_MSG(KERN_INFO "DVI max pixelclock = %d\n", tmds_setting->max_pixel_clock); - tmds_chip->tmds_chip_slave_addr = restore; + tmds_chip->tmds_chip_target_addr = restore; } /* If Disable DVI, turn off pad */ @@ -427,7 +427,7 @@ void viafb_dvi_enable(void) viafb_i2c_writebyte(viaparinfo->chip_info-> tmds_chip_info.i2c_port, viaparinfo->chip_info-> - tmds_chip_info.tmds_chip_slave_addr, + tmds_chip_info.tmds_chip_target_addr, 0x08, data); } } diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c index beec5c8d4d08..8673fced8749 100644 --- a/drivers/video/fbdev/via/lcd.c +++ b/drivers/video/fbdev/via/lcd.c @@ -147,7 +147,7 @@ bool viafb_lvds_trasmitter_identify(void) return true; /* Check for VT1631: */ viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = VT1631_LVDS; - viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = + viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr = VT1631_LVDS_I2C_ADDR; if (check_lvds_chip(VT1631_DEVICE_ID_REG, VT1631_DEVICE_ID)) { @@ -161,7 +161,7 @@ bool viafb_lvds_trasmitter_identify(void) viaparinfo->chip_info->lvds_chip_info.lvds_chip_name = NON_LVDS_TRANSMITTER; - viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = + viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr = VT1631_LVDS_I2C_ADDR; return false; } @@ -327,7 +327,7 @@ static int lvds_register_read(int index) u8 data; viafb_i2c_readbyte(VIA_PORT_2C, - (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr, + (u8) viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr, (u8) index, &data); return data; } diff --git a/drivers/video/fbdev/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c index 2719943c06f4..27226a8f3f42 100644 --- a/drivers/video/fbdev/via/via-gpio.c +++ b/drivers/video/fbdev/via/via-gpio.c @@ -81,8 +81,7 @@ struct viafb_gpio_cfg { /* * GPIO access functions */ -static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, - int value) +static int via_gpio_set(struct gpio_chip *chip, unsigned int nr, int value) { struct viafb_gpio_cfg *cfg = gpiochip_get_data(chip); u8 reg; @@ -99,13 +98,14 @@ static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, reg &= ~(0x10 << gpio->vg_mask_shift); via_write_reg(VIASR, gpio->vg_port_index, reg); spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); + + return 0; } static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr, int value) { - via_gpio_set(chip, nr, value); - return 0; + return via_gpio_set(chip, nr, value); } /* @@ -146,7 +146,7 @@ static struct viafb_gpio_cfg viafb_gpio_config = { .label = "VIAFB onboard GPIO", .owner = THIS_MODULE, .direction_output = via_gpio_dir_out, - .set = via_gpio_set, + .set_rv = via_gpio_set, .direction_input = via_gpio_dir_input, .get = via_gpio_get, .base = -1, @@ -292,7 +292,7 @@ static struct platform_driver via_gpio_driver = { .name = "viafb-gpio", }, .probe = viafb_gpio_probe, - .remove_new = viafb_gpio_remove, + .remove = viafb_gpio_remove, }; int viafb_gpio_init(void) diff --git a/drivers/video/fbdev/via/via_aux.h b/drivers/video/fbdev/via/via_aux.h index 0933bbf20e58..464723fd514c 100644 --- a/drivers/video/fbdev/via/via_aux.h +++ b/drivers/video/fbdev/via/via_aux.h @@ -24,7 +24,7 @@ struct via_aux_drv { struct list_head chain; /* chain to support multiple drivers */ struct via_aux_bus *bus; /* the I2C bus used */ - u8 addr; /* the I2C slave address */ + u8 addr; /* the I2C target address */ const char *name; /* human readable name of the driver */ void *data; /* private data of this driver */ diff --git a/drivers/video/fbdev/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c index 582502810575..cdbd7a9b8817 100644 --- a/drivers/video/fbdev/via/via_i2c.c +++ b/drivers/video/fbdev/via/via_i2c.c @@ -104,7 +104,7 @@ static void via_i2c_setsda(void *data, int state) spin_unlock_irqrestore(&i2c_vdev->reg_lock, flags); } -int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) +int viafb_i2c_readbyte(u8 adap, u8 target_addr, u8 index, u8 *pdata) { int ret; u8 mm1[] = {0x00}; @@ -115,7 +115,7 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) *pdata = 0; msgs[0].flags = 0; msgs[1].flags = I2C_M_RD; - msgs[0].addr = msgs[1].addr = slave_addr / 2; + msgs[0].addr = msgs[1].addr = target_addr / 2; mm1[0] = index; msgs[0].len = 1; msgs[1].len = 1; msgs[0].buf = mm1; msgs[1].buf = pdata; @@ -128,7 +128,7 @@ int viafb_i2c_readbyte(u8 adap, u8 slave_addr, u8 index, u8 *pdata) return ret; } -int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) +int viafb_i2c_writebyte(u8 adap, u8 target_addr, u8 index, u8 data) { int ret; u8 msg[2] = { index, data }; @@ -137,7 +137,7 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) if (!via_i2c_par[adap].is_active) return -ENODEV; msgs.flags = 0; - msgs.addr = slave_addr / 2; + msgs.addr = target_addr / 2; msgs.len = 2; msgs.buf = msg; ret = i2c_transfer(&via_i2c_par[adap].adapter, &msgs, 1); @@ -149,7 +149,7 @@ int viafb_i2c_writebyte(u8 adap, u8 slave_addr, u8 index, u8 data) return ret; } -int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len) +int viafb_i2c_readbytes(u8 adap, u8 target_addr, u8 index, u8 *buff, int buff_len) { int ret; u8 mm1[] = {0x00}; @@ -159,7 +159,7 @@ int viafb_i2c_readbytes(u8 adap, u8 slave_addr, u8 index, u8 *buff, int buff_len return -ENODEV; msgs[0].flags = 0; msgs[1].flags = I2C_M_RD; - msgs[0].addr = msgs[1].addr = slave_addr / 2; + msgs[0].addr = msgs[1].addr = target_addr / 2; mm1[0] = index; msgs[0].len = 1; msgs[1].len = buff_len; msgs[0].buf = mm1; msgs[1].buf = buff; @@ -265,7 +265,7 @@ static struct platform_driver via_i2c_driver = { .name = "viafb-i2c", }, .probe = viafb_i2c_probe, - .remove_new = viafb_i2c_remove, + .remove = viafb_i2c_remove, }; int viafb_i2c_init(void) diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c index a52b1ba43a48..6da5ae7d229a 100644 --- a/drivers/video/fbdev/via/viafbdev.c +++ b/drivers/video/fbdev/via/viafbdev.c @@ -2144,5 +2144,6 @@ MODULE_PARM_DESC(viafb_lcd_port, "Specify LCD output port."); module_param(viafb_dvi_port, charp, S_IRUSR); MODULE_PARM_DESC(viafb_dvi_port, "Specify DVI output port."); +MODULE_DESCRIPTION("VIA UniChrome (Pro) and Chrome9 display driver"); MODULE_LICENSE("GPL"); #endif diff --git a/drivers/video/fbdev/via/vt1636.c b/drivers/video/fbdev/via/vt1636.c index 8d8cfdb05618..0d58ca144e19 100644 --- a/drivers/video/fbdev/via/vt1636.c +++ b/drivers/video/fbdev/via/vt1636.c @@ -44,7 +44,7 @@ u8 viafb_gpio_i2c_read_lvds(struct lvds_setting_information u8 data; viafb_i2c_readbyte(plvds_chip_info->i2c_port, - plvds_chip_info->lvds_chip_slave_addr, index, &data); + plvds_chip_info->lvds_chip_target_addr, index, &data); return data; } @@ -60,7 +60,7 @@ void viafb_gpio_i2c_write_mask_lvds(struct lvds_setting_information data = (data & (~io_data.Mask)) | io_data.Data; viafb_i2c_writebyte(plvds_chip_info->i2c_port, - plvds_chip_info->lvds_chip_slave_addr, index, data); + plvds_chip_info->lvds_chip_target_addr, index, data); } void viafb_init_lvds_vt1636(struct lvds_setting_information @@ -113,7 +113,7 @@ bool viafb_lvds_identify_vt1636(u8 i2c_adapter) DEBUG_MSG(KERN_INFO "viafb_lvds_identify_vt1636.\n"); /* Sense VT1636 LVDS Transmiter */ - viaparinfo->chip_info->lvds_chip_info.lvds_chip_slave_addr = + viaparinfo->chip_info->lvds_chip_info.lvds_chip_target_addr = VT1636_LVDS_I2C_ADDR; /* Check vendor ID first: */ diff --git a/drivers/video/fbdev/vt8500lcdfb.c b/drivers/video/fbdev/vt8500lcdfb.c index ac73937073a7..b08a6fdc53fd 100644 --- a/drivers/video/fbdev/vt8500lcdfb.c +++ b/drivers/video/fbdev/vt8500lcdfb.c @@ -471,7 +471,7 @@ static const struct of_device_id via_dt_ids[] = { static struct platform_driver vt8500lcd_driver = { .probe = vt8500lcd_probe, - .remove_new = vt8500lcd_remove, + .remove = vt8500lcd_remove, .driver = { .name = "vt8500-lcd", .of_match_table = of_match_ptr(via_dt_ids), diff --git a/drivers/video/fbdev/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c index 00952e9c8802..5caf74ca92fb 100644 --- a/drivers/video/fbdev/wm8505fb.c +++ b/drivers/video/fbdev/wm8505fb.c @@ -392,7 +392,7 @@ static const struct of_device_id wmt_dt_ids[] = { static struct platform_driver wm8505fb_driver = { .probe = wm8505fb_probe, - .remove_new = wm8505fb_remove, + .remove = wm8505fb_remove, .driver = { .name = DRIVER_NAME, .of_match_table = wmt_dt_ids, diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c index b70961901683..92fbb3f3a0d3 100644 --- a/drivers/video/fbdev/wmt_ge_rops.c +++ b/drivers/video/fbdev/wmt_ge_rops.c @@ -12,7 +12,6 @@ #include <linux/io.h> #include <linux/platform_device.h> -#include "core/fb_draw.h" #include "wmt_ge_rops.h" #define GE_COMMAND_OFF 0x00 @@ -41,6 +40,33 @@ static void __iomem *regbase; +/* from the spec it seems more like depth than bits per pixel */ +static inline unsigned long pixel_to_pat(u32 depth, u32 pixel, struct fb_info *p) +{ + switch (depth) { + case 1: + return ~0ul*pixel; + case 2: + return ~0ul/3*pixel; + case 4: + return ~0ul/15*pixel; + case 8: + return ~0ul/255*pixel; + case 12: + case 15: + case 16: + return ~0ul/0xffff*pixel; + case 18: + case 24: + return 0x1000001ul*pixel; + case 32: + return pixel; + default: + fb_warn_once(p, "%s: unsupported pixelformat %d\n", __func__, depth); + return 0; + } +} + void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect) { unsigned long fg, pat; @@ -54,7 +80,7 @@ void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect) else fg = rect->color; - pat = pixel_to_pat(p->var.bits_per_pixel, fg); + pat = pixel_to_pat(p->var.bits_per_pixel, fg, p); if (p->fbops->fb_sync) p->fbops->fb_sync(p); @@ -159,7 +185,7 @@ static const struct of_device_id wmt_dt_ids[] = { static struct platform_driver wmt_ge_rops_driver = { .probe = wmt_ge_rops_probe, - .remove_new = wmt_ge_rops_remove, + .remove = wmt_ge_rops_remove, .driver = { .name = "wmt_ge_rops", .of_match_table = wmt_dt_ids, diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 66d4628a96ae..c90f48ebb15e 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -407,6 +407,7 @@ static int xenfb_probe(struct xenbus_device *dev, /* complete the abuse: */ fb_info->pseudo_palette = fb_info->par; fb_info->par = info; + fb_info->device = &dev->dev; fb_info->screen_buffer = info->fb; diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c index 33d20910cb41..0a6e05cd155a 100644 --- a/drivers/video/fbdev/xilinxfb.c +++ b/drivers/video/fbdev/xilinxfb.c @@ -488,7 +488,7 @@ MODULE_DEVICE_TABLE(of, xilinxfb_of_match); static struct platform_driver xilinxfb_of_driver = { .probe = xilinxfb_of_probe, - .remove_new = xilinxfb_of_remove, + .remove = xilinxfb_of_remove, .driver = { .name = DRIVER_NAME, .of_match_table = xilinxfb_of_match, diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index 03c7f27dde49..45b42f14a750 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c @@ -895,34 +895,6 @@ hdmi_vendor_any_infoframe_pack(union hdmi_vendor_any_infoframe *frame, } /** - * hdmi_infoframe_check() - check a HDMI infoframe - * @frame: HDMI infoframe - * - * Validates that the infoframe is consistent and updates derived fields - * (eg. length) based on other fields. - * - * Returns 0 on success or a negative error code on failure. - */ -int -hdmi_infoframe_check(union hdmi_infoframe *frame) -{ - switch (frame->any.type) { - case HDMI_INFOFRAME_TYPE_AVI: - return hdmi_avi_infoframe_check(&frame->avi); - case HDMI_INFOFRAME_TYPE_SPD: - return hdmi_spd_infoframe_check(&frame->spd); - case HDMI_INFOFRAME_TYPE_AUDIO: - return hdmi_audio_infoframe_check(&frame->audio); - case HDMI_INFOFRAME_TYPE_VENDOR: - return hdmi_vendor_any_infoframe_check(&frame->vendor); - default: - WARN(1, "Bad infoframe type %d\n", frame->any.type); - return -EINVAL; - } -} -EXPORT_SYMBOL(hdmi_infoframe_check); - -/** * hdmi_infoframe_pack_only() - write a HDMI infoframe to binary buffer * @frame: HDMI infoframe * @buffer: destination buffer @@ -1310,17 +1282,11 @@ static void hdmi_spd_infoframe_log(const char *level, struct device *dev, const struct hdmi_spd_infoframe *frame) { - u8 buf[17]; - hdmi_infoframe_log_header(level, dev, (const struct hdmi_any_infoframe *)frame); - memset(buf, 0, sizeof(buf)); - - strncpy(buf, frame->vendor, 8); - hdmi_log(" vendor: %s\n", buf); - strncpy(buf, frame->product, 16); - hdmi_log(" product: %s\n", buf); + hdmi_log(" vendor: %.8s\n", frame->vendor); + hdmi_log(" product: %.16s\n", frame->product); hdmi_log(" source device information: %s (0x%x)\n", hdmi_spd_sdi_get_name(frame->sdi), frame->sdi); } diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index b7d94d1dd158..ce6bb753522d 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -8,6 +8,8 @@ menuconfig LOGO depends on FB_CORE || SGI_NEWPORT_CONSOLE help Enable and select frame buffer bootup logos. + Monochrome logos will also be used by the DRM panic handler, if + enabled. if LOGO diff --git a/drivers/video/logo/pnmtologo.c b/drivers/video/logo/pnmtologo.c index 2434a25afb64..28d9f0b907a9 100644 --- a/drivers/video/logo/pnmtologo.c +++ b/drivers/video/logo/pnmtologo.c @@ -235,12 +235,10 @@ static void write_header(void) fputs("/*\n", out); fputs(" * DO NOT EDIT THIS FILE!\n", out); fputs(" *\n", out); - fprintf(out, " * It was automatically generated from %s\n", filename); - fputs(" *\n", out); fprintf(out, " * Linux logo %s\n", logoname); fputs(" */\n\n", out); fputs("#include <linux/linux_logo.h>\n\n", out); - fprintf(out, "static unsigned char %s_data[] __initdata = {\n", + fprintf(out, "static const unsigned char %s_data[] __initconst = {\n", logoname); } @@ -377,7 +375,7 @@ static void write_logo_clut224(void) fputs("\n};\n\n", out); /* write logo clut */ - fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", + fprintf(out, "static const unsigned char %s_clut[] __initconst = {\n", logoname); write_hex_cnt = 0; for (i = 0; i < logo_clutsize; i++) { diff --git a/drivers/video/screen_info_generic.c b/drivers/video/screen_info_generic.c index 64117c6367ab..900e9386eceb 100644 --- a/drivers/video/screen_info_generic.c +++ b/drivers/video/screen_info_generic.c @@ -144,3 +144,39 @@ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, return pos - r; } EXPORT_SYMBOL(screen_info_resources); + +/* + * The meaning of depth and bpp for direct-color formats is + * inconsistent: + * + * - DRM format info specifies depth as the number of color + * bits; including alpha, but not including filler bits. + * - Linux' EFI platform code computes lfb_depth from the + * individual color channels, including the reserved bits. + * - VBE 1.1 defines lfb_depth for XRGB1555 as 16, but later + * versions use 15. + * - On the kernel command line, 'bpp' of 32 is usually + * XRGB8888 including the filler bits, but 15 is XRGB1555 + * not including the filler bit. + * + * It is not easily possible to fix this in struct screen_info, + * as this could break UAPI. The best solution is to compute + * bits_per_pixel from the color bits, reserved bits and + * reported lfb_depth, whichever is highest. + */ + +u32 __screen_info_lfb_bits_per_pixel(const struct screen_info *si) +{ + u32 bits_per_pixel = si->lfb_depth; + + if (bits_per_pixel > 8) { + bits_per_pixel = max(max3(si->red_size + si->red_pos, + si->green_size + si->green_pos, + si->blue_size + si->blue_pos), + si->rsvd_size + si->rsvd_pos); + bits_per_pixel = max_t(u32, bits_per_pixel, si->lfb_depth); + } + + return bits_per_pixel; +} +EXPORT_SYMBOL(__screen_info_lfb_bits_per_pixel); |