Commit a9ac6cc4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-v4.20' of https://github.com/bzolnier/linux

Pull fbdev updates from Bartlomiej Zolnierkiewicz:
 "No major changes to the subsystem itself, mainly fb drivers fixes &
  cleanups (atyfb & udlfb updates stand out from the rest) + removal of
  no longer needed old clps711xfb driver.

  Details:

   - update atyfb driver - improvements for ATI Mach64 chips: detect the
     dot clock divider correctly on Sparc, fix display corruptions (due
     to endianness issues and improper reading of accelerator
     registers), optimize scrolling performance and also fix debugging
     printks (Mikulas Patocka)

   - rewrite USB unplug handling in udlfb driver using framebuffer
     subsystem reference counting (Mikulas Patocka)

   - fix support for native-mode display-timings in atmel_lcdfb driver
     (Sam Ravnborg)

   - fix information leak & add missing access_ok() checks in sbuslib
     (Dan Carpenter)

   - allow using GPIO expanders that can sleep in ssd1307fb driver
     (Michal Vokáč)

   - convert omapfb driver to use GPIO descriptors instead of GPIO
     numbers for Amstrad Delta board (Janusz Krzysztofik)

   - fix broken Kconfig menu dependencies (Randy Dunlap)

   - convert fbdev subsystem to use %pOFn instead of device_node.name
     (Rob Herring)

   - remove the dead old CLPS711x LCD support driver (the new CLPS711x
     LCD support driver is still available)

   - misc fixes (Jia-Ju Bai, Gustavo A. R. Silva)

   - misc cleanups (Mehdi Bounya, Nathan Chancellor, YueHaibing)"

* tag 'fbdev-v4.20' of https://github.com/bzolnier/linux: (22 commits)
  video: fbdev: remove redundant 'default n' from Kconfig-s
  video: fbdev: remove dead old CLPS711x LCD support driver
  Revert "video: ssd1307fb: Do not hard code active-low reset sequence"
  video: fbdev: arcfb: mark expected switch fall-through
  pxa168fb: remove set but not used variables 'mi'
  video: ssd1307fb: Do not hard code active-low reset sequence
  video: ssd1307fb: Use gpiod_set_value_cansleep() for reset
  fbdev: fix broken menu dependencies
  video: fbdev: sis: Remove unnecessary parentheses and commented code
  video: fbdev: omapfb: lcd_ams_delta: use GPIO lookup table
  fbdev: sbuslib: integer overflow in sbusfb_ioctl_helper()
  fbdev: sbuslib: use checked version of put_user()
  fbdev: Convert to using %pOFn instead of device_node.name
  atmel_lcdfb: support native-mode display-timings
  Video: vgastate: fixed a spacing coding style
  atyfb: fix debugging printks
  mach64: optimize wait_for_fifo
  mach64: fix image corruption due to reading accelerator registers
  mach64: fix display corruption on big endian machines
  mach64: detect the dot clock divider correctly on sparc
  ...
parents d547d44e 217188d9
......@@ -2,6 +2,12 @@
# fbdev configuration
#
config FB_CMDLINE
bool
config FB_NOTIFY
bool
menuconfig FB
tristate "Support for frame buffer devices"
select FB_CMDLINE
......@@ -41,7 +47,6 @@ menuconfig FB
config FIRMWARE_EDID
bool "Enable firmware EDID"
depends on FB
default n
---help---
This enables access to the EDID transferred from the firmware.
On the i386, this is from the Video BIOS. Enable this if DDC/I2C
......@@ -54,23 +59,15 @@ config FIRMWARE_EDID
combination with certain motherboards and monitors are known to
suffer from this problem.
config FB_CMDLINE
bool
config FB_NOTIFY
bool
config FB_DDC
tristate
depends on FB
select I2C_ALGOBIT
select I2C
default n
config FB_BOOT_VESA_SUPPORT
bool
depends on FB
default n
---help---
If true, at least one selected framebuffer driver can take advantage
of VESA video modes set at an early boot stage via the vga= parameter.
......@@ -78,7 +75,6 @@ config FB_BOOT_VESA_SUPPORT
config FB_CFB_FILLRECT
tristate
depends on FB
default n
---help---
Include the cfb_fillrect function for generic software rectangle
filling. This is used by drivers that don't provide their own
......@@ -87,7 +83,6 @@ config FB_CFB_FILLRECT
config FB_CFB_COPYAREA
tristate
depends on FB
default n
---help---
Include the cfb_copyarea function for generic software area copying.
This is used by drivers that don't provide their own (accelerated)
......@@ -96,7 +91,6 @@ config FB_CFB_COPYAREA
config FB_CFB_IMAGEBLIT
tristate
depends on FB
default n
---help---
Include the cfb_imageblit function for generic software image
blitting. This is used by drivers that don't provide their own
......@@ -105,7 +99,6 @@ config FB_CFB_IMAGEBLIT
config FB_CFB_REV_PIXELS_IN_BYTE
bool
depends on FB
default n
---help---
Allow generic frame-buffer functions to work on displays with 1, 2
and 4 bits per pixel depths which has opposite order of pixels in
......@@ -114,7 +107,6 @@ config FB_CFB_REV_PIXELS_IN_BYTE
config FB_SYS_FILLRECT
tristate
depends on FB
default n
---help---
Include the sys_fillrect function for generic software rectangle
filling. This is used by drivers that don't provide their own
......@@ -123,7 +115,6 @@ config FB_SYS_FILLRECT
config FB_SYS_COPYAREA
tristate
depends on FB
default n
---help---
Include the sys_copyarea function for generic software area copying.
This is used by drivers that don't provide their own (accelerated)
......@@ -132,7 +123,6 @@ config FB_SYS_COPYAREA
config FB_SYS_IMAGEBLIT
tristate
depends on FB
default n
---help---
Include the sys_imageblit function for generic software image
blitting. This is used by drivers that don't provide their own
......@@ -141,7 +131,6 @@ config FB_SYS_IMAGEBLIT
config FB_PROVIDE_GET_FB_UNMAPPED_AREA
bool
depends on FB
default n
---help---
Allow generic frame-buffer to provide get_fb_unmapped_area
function.
......@@ -173,7 +162,6 @@ endchoice
config FB_SYS_FOPS
tristate
depends on FB
default n
config FB_DEFERRED_IO
bool
......@@ -187,7 +175,6 @@ config FB_HECUBA
config FB_SVGALIB
tristate
depends on FB
default n
---help---
Common utility functions useful to fbdev drivers of VGA-based
cards.
......@@ -195,19 +182,16 @@ config FB_SVGALIB
config FB_MACMODES
tristate
depends on FB
default n
config FB_BACKLIGHT
bool
depends on FB
select BACKLIGHT_LCD_SUPPORT
select BACKLIGHT_CLASS_DEVICE
default n
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
depends on FB
default n
---help---
This enables functions for handling video modes using the
Generalized Timing Formula and the EDID parser. A few drivers rely
......@@ -218,7 +202,6 @@ config FB_MODE_HELPERS
config FB_TILEBLITTING
bool "Enable Tile Blitting Support"
depends on FB
default n
---help---
This enables tile blitting. Tile blitting is a drawing technique
where the screen is divided into rectangular sections (tiles), whereas
......@@ -329,16 +312,9 @@ config FB_ACORN
hardware found in Acorn RISC PCs and other ARM-based machines. If
unsure, say N.
config FB_CLPS711X_OLD
tristate
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
config FB_CLPS711X
tristate "CLPS711X LCD support"
depends on FB && (ARCH_CLPS711X || COMPILE_TEST)
select FB_CLPS711X_OLD if ARCH_CLPS711X && !ARCH_MULTIPLATFORM
select BACKLIGHT_LCD_SUPPORT
select FB_MODE_HELPERS
select FB_SYS_FILLRECT
......@@ -936,7 +912,6 @@ config FB_NVIDIA_I2C
config FB_NVIDIA_DEBUG
bool "Lots of debug output"
depends on FB_NVIDIA
default n
help
Say Y here if you want the nVidia driver to output all sorts
of debugging information to provide to the maintainer when
......@@ -983,7 +958,6 @@ config FB_RIVA_I2C
config FB_RIVA_DEBUG
bool "Lots of debug output"
depends on FB_RIVA
default n
help
Say Y here if you want the Riva driver to output all sorts
of debugging information to provide to the maintainer when
......@@ -1266,7 +1240,6 @@ config FB_RADEON_BACKLIGHT
config FB_RADEON_DEBUG
bool "Lots of debug output from Radeon driver"
depends on FB_RADEON
default n
help
Say Y here if you want the Radeon driver to output all sorts
of debugging information to provide to the maintainer when
......@@ -1399,7 +1372,6 @@ config FB_SAVAGE_I2C
config FB_SAVAGE_ACCEL
bool "Enable Console Acceleration"
depends on FB_SAVAGE
default n
help
This option will compile in console acceleration support. If
the resulting framebuffer console has bothersome glitches, then
......@@ -1456,8 +1428,6 @@ if FB_VIA
config FB_VIA_DIRECT_PROCFS
bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)"
depends on FB_VIA
default n
help
Allow direct hardware access to some output registers via procfs.
This is dangerous but may provide the only chance to get the
......@@ -1466,8 +1436,6 @@ config FB_VIA_DIRECT_PROCFS
config FB_VIA_X_COMPATIBILITY
bool "X server compatibility"
depends on FB_VIA
default n
help
This option reduces the functionality (power saving, ...) of the
framebuffer to avoid negative impact on the OpenChrome X server.
......@@ -1692,7 +1660,6 @@ config FB_WM8505
config FB_WMT_GE_ROPS
bool "VT8500/WM8xxx accelerated raster ops support"
depends on (FB = y) && (FB_VT8500 || FB_WM8505)
default n
help
This adds support for accelerated raster operations on the
VIA VT8500 and Wondermedia 85xx series SoCs.
......@@ -1802,17 +1769,14 @@ config FB_PXA
config FB_PXA_OVERLAY
bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer"
default n
depends on FB_PXA && (PXA27x || PXA3xx)
config FB_PXA_SMARTPANEL
bool "PXA Smartpanel LCD support"
default n
depends on FB_PXA
config FB_PXA_PARAMETERS
bool "PXA LCD command line parameters"
default n
depends on FB_PXA
---help---
Enable the use of kernel command line or module parameters
......@@ -1850,7 +1814,6 @@ config FB_MBX
config FB_MBX_DEBUG
bool "Enable debugging info via debugfs"
depends on FB_MBX && DEBUG_FS
default n
---help---
Enable this if you want debugging information using the debug
filesystem (debugfs)
......@@ -2240,7 +2203,7 @@ config FB_MX3
config FB_BROADSHEET
tristate "E-Ink Broadsheet/Epson S1D13521 controller support"
depends on FB
depends on FB && (ARCH_PXA || COMPILE_TEST)
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
......@@ -2308,10 +2271,6 @@ config FB_SIMPLE
Configuration re: surface address, size, and format must be provided
through device tree, or plain old platform data.
source "drivers/video/fbdev/omap/Kconfig"
source "drivers/video/fbdev/omap2/Kconfig"
source "drivers/video/fbdev/mmp/Kconfig"
config FB_SSD1307
tristate "Solomon SSD1307 framebuffer support"
depends on FB && I2C
......@@ -2341,3 +2300,7 @@ config FB_SM712
This driver is also available as a module. The module will be
called sm712fb. If you want to compile it as a module, say M
here and read <file:Documentation/kbuild/modules.txt>.
source "drivers/video/fbdev/omap/Kconfig"
source "drivers/video/fbdev/omap2/Kconfig"
source "drivers/video/fbdev/mmp/Kconfig"
......@@ -14,7 +14,6 @@ obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o
obj-$(CONFIG_FB_CLPS711X_OLD) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_GRVGA) += grvga.o
obj-$(CONFIG_FB_PM2) += pm2fb.o
......
......@@ -419,6 +419,8 @@ static int arcfb_ioctl(struct fb_info *info,
schedule();
finish_wait(&arcfb_waitq, &wait);
}
/* fall through */
case FBIO_GETCONTROL2:
{
unsigned char ctl2;
......
......@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <video/of_videomode.h>
#include <video/of_display_timing.h>
#include <linux/regulator/consumer.h>
#include <video/videomode.h>
......@@ -1028,11 +1029,11 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
struct device *dev = &sinfo->pdev->dev;
struct device_node *np =dev->of_node;
struct device_node *display_np;
struct device_node *timings_np;
struct display_timings *timings;
struct atmel_lcdfb_power_ctrl_gpio *og;
bool is_gpio_power = false;
struct fb_videomode fb_vm;
struct gpio_desc *gpiod;
struct videomode vm;
int ret = -ENOENT;
int i;
......@@ -1105,44 +1106,18 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
pdata->lcdcon_pol_negative = of_property_read_bool(display_np, "atmel,lcdcon-backlight-inverted");
timings = of_get_display_timings(display_np);
if (!timings) {
dev_err(dev, "failed to get display timings\n");
ret = -EINVAL;
goto put_display_node;
}
timings_np = of_get_child_by_name(display_np, "display-timings");
if (!timings_np) {
dev_err(dev, "failed to find display-timings node\n");
ret = -ENODEV;
ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE);
if (ret) {
dev_err(dev, "failed to get videomode from DT\n");
goto put_display_node;
}
for (i = 0; i < of_get_child_count(timings_np); i++) {
struct videomode vm;
struct fb_videomode fb_vm;
ret = videomode_from_timings(timings, &vm, i);
if (ret < 0)
goto put_timings_node;
ret = fb_videomode_from_videomode(&vm, &fb_vm);
if (ret < 0)
goto put_timings_node;
goto put_display_node;
fb_add_videomode(&fb_vm, &info->modelist);
}
/*
* FIXME: Make sure we are not referencing any fields in display_np
* and timings_np and drop our references to them before returning to
* avoid leaking the nodes on probe deferral and driver unbind.
*/
return 0;
put_timings_node:
of_node_put(timings_np);
put_display_node:
of_node_put(display_np);
return ret;
......
......@@ -147,6 +147,7 @@ struct atyfb_par {
u16 pci_id;
u32 accel_flags;
int blitter_may_be_busy;
unsigned fifo_space;
int asleep;
int lock_blank;
unsigned long res_start;
......@@ -346,10 +347,13 @@ extern int aty_init_cursor(struct fb_info *info);
* Hardware acceleration
*/
static inline void wait_for_fifo(u16 entries, const struct atyfb_par *par)
static inline void wait_for_fifo(u16 entries, struct atyfb_par *par)
{
while ((aty_ld_le32(FIFO_STAT, par) & 0xffff) >
((u32) (0x8000 >> entries)));
unsigned fifo_space = par->fifo_space;
while (entries > fifo_space) {
fifo_space = 16 - fls(aty_ld_le32(FIFO_STAT, par) & 0xffff);
}
par->fifo_space = fifo_space - entries;
}
static inline void wait_for_idle(struct atyfb_par *par)
......@@ -359,7 +363,7 @@ static inline void wait_for_idle(struct atyfb_par *par)
par->blitter_may_be_busy = 0;
}
extern void aty_reset_engine(const struct atyfb_par *par);
extern void aty_reset_engine(struct atyfb_par *par);
extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info);
void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
......
......@@ -1480,24 +1480,28 @@ static int atyfb_set_par(struct fb_info *info)
base = 0x2000;
printk("debug atyfb: Mach64 non-shadow register values:");
for (i = 0; i < 256; i = i+4) {
if (i % 16 == 0)
printk("\ndebug atyfb: 0x%04X: ", base + i);
printk(" %08X", aty_ld_le32(i, par));
if (i % 16 == 0) {
pr_cont("\n");
printk("debug atyfb: 0x%04X: ", base + i);
}
printk("\n\n");
pr_cont(" %08X", aty_ld_le32(i, par));
}
pr_cont("\n\n");
#ifdef CONFIG_FB_ATY_CT
/* PLL registers */
base = 0x00;
printk("debug atyfb: Mach64 PLL register values:");
for (i = 0; i < 64; i++) {
if (i % 16 == 0)
printk("\ndebug atyfb: 0x%02X: ", base + i);
if (i % 16 == 0) {
pr_cont("\n");
printk("debug atyfb: 0x%02X: ", base + i);
}
if (i % 4 == 0)
printk(" ");
printk("%02X", aty_ld_pll_ct(i, par));
pr_cont(" ");
pr_cont("%02X", aty_ld_pll_ct(i, par));
}
printk("\n\n");
pr_cont("\n\n");
#endif /* CONFIG_FB_ATY_CT */
#ifdef CONFIG_FB_ATY_GENERIC_LCD
......@@ -1509,19 +1513,19 @@ static int atyfb_set_par(struct fb_info *info)
for (i = 0; i <= POWER_MANAGEMENT; i++) {
if (i == EXT_VERT_STRETCH)
continue;
printk("\ndebug atyfb: 0x%04X: ",
pr_cont("\ndebug atyfb: 0x%04X: ",
lt_lcd_regs[i]);
printk(" %08X", aty_ld_lcd(i, par));
pr_cont(" %08X", aty_ld_lcd(i, par));
}
} else {
for (i = 0; i < 64; i++) {
if (i % 4 == 0)
printk("\ndebug atyfb: 0x%02X: ",
pr_cont("\ndebug atyfb: 0x%02X: ",
base + i);
printk(" %08X", aty_ld_lcd(i, par));
pr_cont(" %08X", aty_ld_lcd(i, par));
}
}
printk("\n\n");
pr_cont("\n\n");
}
#endif /* CONFIG_FB_ATY_GENERIC_LCD */
}
......@@ -2597,8 +2601,8 @@ static int aty_init(struct fb_info *info)
aty_ld_le32(DSP_ON_OFF, par),
aty_ld_le32(CLOCK_CNTL, par));
for (i = 0; i < 40; i++)
printk(" %02x", aty_ld_pll_ct(i, par));
printk("\n");
pr_cont(" %02x", aty_ld_pll_ct(i, par));
pr_cont("\n");
}
#endif
if (par->pll_ops->init_pll)
......
......@@ -37,7 +37,7 @@ static u32 rotation24bpp(u32 dx, u32 direction)
return ((rotation << 8) | DST_24_ROTATION_ENABLE);
}
void aty_reset_engine(const struct atyfb_par *par)
void aty_reset_engine(struct atyfb_par *par)
{
/* reset engine */
aty_st_le32(GEN_TEST_CNTL,
......@@ -50,6 +50,8 @@ void aty_reset_engine(const struct atyfb_par *par)
/* HOST errors */
aty_st_le32(BUS_CNTL,
aty_ld_le32(BUS_CNTL, par) | BUS_HOST_ERR_ACK | BUS_FIFO_ERR_ACK, par);
par->fifo_space = 0;
}
static void reset_GTC_3D_engine(const struct atyfb_par *par)
......@@ -127,7 +129,7 @@ void aty_init_engine(struct atyfb_par *par, struct fb_info *info)
/* set host attributes */
wait_for_fifo(13, par);
aty_st_le32(HOST_CNTL, 0, par);
aty_st_le32(HOST_CNTL, HOST_BYTE_ALIGN, par);
/* set pattern attributes */
aty_st_le32(PAT_REG0, 0, par);
......@@ -233,7 +235,8 @@ void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
rotation = rotation24bpp(dx, direction);
}
wait_for_fifo(4, par);
wait_for_fifo(5, par);
aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, par);
aty_st_le32(DP_SRC, FRGD_SRC_BLIT, par);
aty_st_le32(SRC_Y_X, (sx << 16) | sy, par);
aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | area->height, par);
......@@ -269,7 +272,8 @@ void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
rotation = rotation24bpp(dx, DST_X_LEFT_TO_RIGHT);
}
wait_for_fifo(3, par);
wait_for_fifo(4, par);
aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, par);
aty_st_le32(DP_FRGD_CLR, color, par);
aty_st_le32(DP_SRC,
BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE,
......@@ -284,7 +288,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct atyfb_par *par = (struct atyfb_par *) info->par;
u32 src_bytes, dx = image->dx, dy = image->dy, width = image->width;
u32 pix_width_save, pix_width, host_cntl, rotation = 0, src, mix;
u32 pix_width, rotation = 0, src, mix;
if (par->asleep)
return;
......@@ -296,8 +300,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
return;
}
pix_width = pix_width_save = aty_ld_le32(DP_PIX_WIDTH, par);
host_cntl = aty_ld_le32(HOST_CNTL, par) | HOST_BYTE_ALIGN;
pix_width = par->crtc.dp_pix_width;
switch (image->depth) {
case 1:
......@@ -345,7 +348,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
* since Rage 3D IIc we have DP_HOST_TRIPLE_EN bit
* this hwaccelerated triple has an issue with not aligned data
*/
if (M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
if (image->depth == 1 && M64_HAS(HW_TRIPLE) && image->width % 8 == 0)
pix_width |= DP_HOST_TRIPLE_EN;
}
......@@ -370,19 +373,18 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
mix = FRGD_MIX_D_XOR_S | BKGD_MIX_D;
}
wait_for_fifo(6, par);
aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF, par);
wait_for_fifo(5, par);
aty_st_le32(DP_PIX_WIDTH, pix_width, par);
aty_st_le32(DP_MIX, mix, par);
aty_st_le32(DP_SRC, src, par);
aty_st_le32(HOST_CNTL, host_cntl, par);
aty_st_le32(HOST_CNTL, HOST_BYTE_ALIGN, par);
aty_st_le32(DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT | rotation, par);
draw_rect(dx, dy, width, image->height, par);
src_bytes = (((image->width * image->depth) + 7) / 8) * image->height;
/* manual triple each pixel */
if (info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
if (image->depth == 1 && info->var.bits_per_pixel == 24 && !(pix_width & DP_HOST_TRIPLE_EN)) {
int inbit, outbit, mult24, byte_id_in_dword, width;
u8 *pbitmapin = (u8*)image->data, *pbitmapout;
u32 hostdword;
......@@ -415,7 +417,7 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
}
}
wait_for_fifo(1, par);
aty_st_le32(HOST_DATA0, hostdword, par);
aty_st_le32(HOST_DATA0, le32_to_cpu(hostdword), par);
}
} else {
u32 *pbitmap, dwords = (src_bytes + 3) / 4;
......@@ -424,8 +426,4 @@ void atyfb_imageblit(struct fb_info *info, const struct fb_image *image)
aty_st_le32(HOST_DATA0, get_unaligned_le32(pbitmap), par);
}
}
/* restore pix_width */
wait_for_fifo(1, par);
aty_st_le32(DP_PIX_WIDTH, pix_width_save, par);
}
......@@ -355,9 +355,7 @@ static int cg14_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
static void cg14_init_fix(struct fb_info *info, int linebytes,
struct device_node *dp)
{
const char *name = dp->name;
strlcpy(info->fix.id, name, sizeof(info->fix.id));
snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
......
......@@ -246,7 +246,7 @@ static int cg3_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
static void cg3_init_fix(struct fb_info *info, int linebytes,
struct device_node *dp)
{
strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
......
/*
* linux/drivers/video/clps711xfb.c
*
* Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Framebuffer driver for the CLPS7111 and EP7212 processors.
*/
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <linux/uaccess.h>
struct fb_info *cfb;
#define CMAP_MAX_SIZE 16
/*
* LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
* This determines how many clocks + 1 of CL1 before the M signal toggles.
* The number of lines on the display must not be divisible by this number.
*/
static unsigned int lcd_ac_prescale = 13;
/*
* Set a single color register. Return != 0 for invalid regno.
*/
static int
clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
unsigned int level, mask, shift, pal;
if (regno >= (1 << info->var.bits_per_pixel))
return 1;
/* gray = 0.30*R + 0.58*G + 0.11*B */
level = (red * 77 + green * 151 + blue * 28) >> 20;
/*
* On an LCD, a high value is dark, while a low value is light.
* So we invert the level.
*
* This isn't true on all machines, so we only do it on EDB7211.
* --rmk
*/
if (machine_is_edb7211()) {
level = 15 - level;
}
shift = 4 * (regno & 7);
level <<= shift;
mask = 15 << shift;
level &= mask;
regno = regno < 8 ? PALLSW : PALMSW;
pal = clps_readl(regno);
pal = (pal & ~mask) | level;
clps_writel(pal, regno);
return 0;
}
/*
* Validate the purposed mode.
*/
static int
clps7111fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
var->transp.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->red.msb_right = 0;
var->red.offset = 0;
var->red.length = var->bits_per_pixel;
var->green = var->red;
var->blue = var->red;
if (var->bits_per_pixel > 4)
return -EINVAL;
return 0;
}
/*
* Set the hardware state.
*/
static int
clps7111fb_set_par(struct fb_info *info)
{
unsigned int lcdcon, syscon, pixclock;
switch (info->var.bits_per_pixel) {
case 1:
info->fix.visual = FB_VISUAL_MONO01;
break;
case 2:
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 4:
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
}
info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
lcdcon = (info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel) / 128 - 1;
lcdcon |= ((info->var.xres_virtual / 16) - 1) << 13;
lcdcon |= lcd_ac_prescale << 25;
/*
* Calculate pixel prescale value from the pixclock. This is:
* 36.864MHz / pixclock_mhz - 1.
* However, pixclock is in picoseconds, so this ends up being:
* 36864000 * pixclock_ps / 10^12 - 1
* and this will overflow the 32-bit math. We perform this as
* (9 * 4096000 == 36864000):
* pixclock_ps * 9 * (4096000 / 10^12) - 1
*/
pixclock = 9 * info->var.pixclock / 244140 - 1;
lcdcon |= pixclock << 19;
if (info->var.bits_per_pixel == 4)
lcdcon |= LCDCON_GSMD;
if (info->var.bits_per_pixel >= 2)
lcdcon |= LCDCON_GSEN;
/*
* LCDCON must only be changed while the LCD is disabled
*/
syscon = clps_readl(SYSCON1);
clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
clps_writel(lcdcon, LCDCON);
clps_writel(syscon | SYSCON1_LCDEN, SYSCON1);
return 0;
}
static int clps7111fb_blank(int blank, struct fb_info *info)
{
/* Enable/Disable LCD controller. */
if (blank)
clps_writel(clps_readl(SYSCON1) & ~SYSCON1_LCDEN, SYSCON1);
else
clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN, SYSCON1);
return 0;
}
static struct fb_ops clps7111fb_ops = {
.owner = THIS_MODULE,
.fb_check_var = clps7111fb_check_var,
.fb_set_par = clps7111fb_set_par,
.fb_setcolreg = clps7111fb_setcolreg,
.fb_blank = clps7111fb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
static void clps711x_guess_lcd_params(struct fb_info *info)
{
unsigned int lcdcon, syscon, size;
unsigned long phys_base = PAGE_OFFSET;
void *virt_base = (void *)PAGE_OFFSET;
info->var.xres_virtual = 640;
info->var.yres_virtual = 240;
info->var.bits_per_pixel = 4;
info->var.activate = FB_ACTIVATE_NOW;
info->var.height = -1;
info->var.width = -1;
info->var.pixclock = 93006; /* 10.752MHz pixel clock */
/*
* If the LCD controller is already running, decode the values
* in LCDCON to xres/yres/bpp/pixclock/acprescale
*/
syscon = clps_readl(SYSCON1);
if (syscon & SYSCON1_LCDEN) {
lcdcon = clps_readl(LCDCON);
/*
* Decode GSMD and GSEN bits to bits per pixel
*/
switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
case LCDCON_GSMD | LCDCON_GSEN:
info->var.bits_per_pixel = 4;
break;
case LCDCON_GSEN:
info->var.bits_per_pixel = 2;
break;
default:
info->var.bits_per_pixel = 1;
break;
}
/*
* Decode xres/yres
*/
info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
(info->var.xres_virtual *
info->var.bits_per_pixel);
/*
* Calculate pixclock
*/
info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
/*
* Grab AC prescale
*/
lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
}
info->var.xres = info->var.xres_virtual;
info->var.yres = info->var.yres_virtual;
info->var.grayscale = info->var.bits_per_pixel > 1;
size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
/*
* Might be worth checking to see if we can use the on-board
* RAM if size here...
* CLPS7110 - no on-board SRAM
* EP7212 - 38400 bytes
*/
if (size <= 38400) {
printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
}
if ((syscon & SYSCON1_LCDEN) == 0) {
/*
* The display isn't running. Ensure that
* the display memory is empty.
*/
memset(virt_base, 0, size);
}
info->screen_base = virt_base;
info->fix.smem_start = phys_base;
info->fix.smem_len = PAGE_ALIGN(size);
info->fix.type = FB_TYPE_PACKED_PIXELS;
}
static int clps711x_fb_probe(struct platform_device *pdev)
{
int err = -ENOMEM;
if (fb_get_options("clps711xfb", NULL))
return -ENODEV;
cfb = kzalloc(sizeof(*cfb), GFP_KERNEL);
if (!cfb)
goto out;
strcpy(cfb->fix.id, "clps711x");
cfb->fbops = &clps7111fb_ops;
cfb->flags = FBINFO_DEFAULT;
clps711x_guess_lcd_params(cfb);
fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
err = register_framebuffer(cfb);
out: return err;
}
static int clps711x_fb_remove(struct platform_device *pdev)
{
unregister_framebuffer(cfb);
kfree(cfb);
return 0;
}
static struct platform_driver clps711x_fb_driver = {
.driver = {
.name = "video-clps711x",
},
.probe = clps711x_fb_probe,
.remove = clps711x_fb_remove,
};
module_platform_driver(clps711x_fb_driver);
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
MODULE_DESCRIPTION("CLPS711X framebuffer driver");
MODULE_LICENSE("GPL");
......@@ -1480,8 +1480,8 @@ int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
if (ret)
return ret;
pr_debug("%pOF: got %dx%d display mode from %s\n",
np, vm.hactive, vm.vactive, np->name);
pr_debug("%pOF: got %dx%d display mode\n",
np, vm.hactive, vm.vactive);
dump_fb_videomode(fb);
return 0;
......
......@@ -1473,7 +1473,7 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dp = pci_device_to_OF_node(pdev);
if(dp)
printk(KERN_INFO "%s: OF name %s\n",__func__, dp->name);
printk(KERN_INFO "%s: OF name %pOFn\n",__func__, dp);
else if (IS_ENABLED(CONFIG_OF))
printk(KERN_ERR "imsttfb: no OF node for pci device\n");
......
......@@ -434,7 +434,7 @@ static int leo_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
static void
leo_init_fix(struct fb_info *info, struct device_node *dp)
{
strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_TRUECOLOR;
......
......@@ -3,7 +3,6 @@ if MMP_DISP
config MMP_DISP_CONTROLLER
bool "mmp display controller hw support"
depends on CPU_PXA910 || CPU_MMP2
default n
help
Marvell MMP display hw controller support
this controller is used on Marvell PXA910 and
......
......@@ -2,6 +2,5 @@
config MMP_PANEL_TPOHVGA
bool "tpohvga panel TJ032MD01BW support"
depends on SPI_MASTER
default n
help
tpohvga panel support
......@@ -419,9 +419,13 @@ static void __init offb_init_fb(const char *name,
var = &info->var;
info->par = par;
if (name) {
strcpy(fix->id, "OFfb ");
strncat(fix->id, name, sizeof(fix->id) - sizeof("OFfb "));
fix->id[sizeof(fix->id) - 1] = '\0';
} else
snprintf(fix->id, sizeof(fix->id), "OFfb %pOFn", dp);
var->xres = var->xres_virtual = width;
var->yres = var->yres_virtual = height;
......@@ -644,7 +648,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
/* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0)
address += 0x1000;
offb_init_fb(no_real_node ? "bootx" : dp->name,
offb_init_fb(no_real_node ? "bootx" : NULL,
width, height, depth, pitch, address,
foreign_endian, no_real_node ? NULL : dp);
}
......
......@@ -24,11 +24,10 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/lcd.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
#include <mach/board-ams-delta.h>
#include "omapfb.h"
......@@ -41,6 +40,8 @@
/* LCD class device section */
static int ams_delta_lcd;
static struct gpio_desc *gpiod_vblen;
static struct gpio_desc *gpiod_ndisp;
static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
{
......@@ -99,41 +100,17 @@ static struct lcd_ops ams_delta_lcd_ops = {
/* omapfb panel section */
static const struct gpio _gpios[] = {
{
.gpio = AMS_DELTA_GPIO_PIN_LCD_VBLEN,
.flags = GPIOF_OUT_INIT_LOW,
.label = "lcd_vblen",
},
{
.gpio = AMS_DELTA_GPIO_PIN_LCD_NDISP,
.flags = GPIOF_OUT_INIT_LOW,
.label = "lcd_ndisp",
},
};
static int ams_delta_panel_init(struct lcd_panel *panel,
struct omapfb_device *fbdev)
{
return gpio_request_array(_gpios, ARRAY_SIZE(_gpios));
}
static void ams_delta_panel_cleanup(struct lcd_panel *panel)
{
gpio_free_array(_gpios, ARRAY_SIZE(_gpios));
}
static int ams_delta_panel_enable(struct lcd_panel *panel)
{
gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1);
gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1);
gpiod_set_value(gpiod_ndisp, 1);
gpiod_set_value(gpiod_vblen, 1);
return 0;
}
static void ams_delta_panel_disable(struct lcd_panel *panel)
{
gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0);
gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0);
gpiod_set_value(gpiod_vblen, 0);
gpiod_set_value(gpiod_ndisp, 0);
}
static struct lcd_panel ams_delta_panel = {
......@@ -154,8 +131,6 @@ static struct lcd_panel ams_delta_panel = {
.pcd = 0,
.acb = 37,
.init = ams_delta_panel_init,
.cleanup = ams_delta_panel_cleanup,
.enable = ams_delta_panel_enable,
.disable = ams_delta_panel_disable,
};
......@@ -166,9 +141,23 @@ static struct lcd_panel ams_delta_panel = {
static int ams_delta_panel_probe(struct platform_device *pdev)
{
struct lcd_device *lcd_device = NULL;
#ifdef CONFIG_LCD_CLASS_DEVICE
int ret;
gpiod_vblen = devm_gpiod_get(&pdev->dev, "vblen", GPIOD_OUT_LOW);
if (IS_ERR(gpiod_vblen)) {
ret = PTR_ERR(gpiod_vblen);
dev_err(&pdev->dev, "VBLEN GPIO request failed (%d)\n", ret);
return ret;
}
gpiod_ndisp = devm_gpiod_get(&pdev->dev, "ndisp", GPIOD_OUT_LOW);
if (IS_ERR(gpiod_ndisp)) {
ret = PTR_ERR(gpiod_ndisp);
dev_err(&pdev->dev, "NDISP GPIO request failed (%d)\n", ret);
return ret;
}
#ifdef CONFIG_LCD_CLASS_DEVICE
lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
&ams_delta_lcd_ops);
......
......@@ -10,7 +10,6 @@ config FB_OMAP2_DSS
config FB_OMAP2_DSS_DEBUG
bool "Debug support"
default n
help
This enables printing of debug messages. Alternatively, debug messages
can also be enabled by setting CONFIG_DYNAMIC_DEBUG and then setting
......@@ -19,7 +18,6 @@ config FB_OMAP2_DSS_DEBUG
config FB_OMAP2_DSS_DEBUGFS
bool "Debugfs filesystem support"
depends on DEBUG_FS
default n
help
This enables debugfs for OMAPDSS at <debugfs>/omapdss. This enables
querying about clock configuration and register configuration of dss,
......@@ -28,7 +26,6 @@ config FB_OMAP2_DSS_DEBUGFS
config FB_OMAP2_DSS_COLLECT_IRQ_STATS
bool "Collect DSS IRQ statistics"
depends on FB_OMAP2_DSS_DEBUGFS
default n
help
Collect DSS IRQ statistics, printable via debugfs.
......@@ -45,7 +42,6 @@ config FB_OMAP2_DSS_DPI
config FB_OMAP2_DSS_RFBI
bool "RFBI support"
depends on BROKEN
default n
help
MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
Instrument's terminology).
......@@ -73,7 +69,6 @@ config FB_OMAP4_DSS_HDMI
config FB_OMAP5_DSS_HDMI
bool "HDMI support for OMAP5"
default n
select FB_OMAP2_DSS_HDMI_COMMON
help
HDMI Interface for OMAP5 and similar cores. This adds the High
......@@ -82,7 +77,6 @@ config FB_OMAP5_DSS_HDMI
config FB_OMAP2_DSS_SDI
bool "SDI support"
default n
help
SDI (Serial Display Interface) support.
......@@ -91,7 +85,6 @@ config FB_OMAP2_DSS_SDI
config FB_OMAP2_DSS_DSI
bool "DSI support"
default n
help
MIPI DSI (Display Serial Interface) support.
......
......@@ -239,7 +239,7 @@ static int p9100_ioctl(struct fb_info *info, unsigned int cmd,
static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_node *dp)
{
strlcpy(info->fix.id, dp->name, sizeof(info->fix.id));
snprintf(info->fix.id, sizeof(info->fix.id), "%pOFn", dp);
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
......
......@@ -405,9 +405,6 @@ static int pxa168fb_set_par(struct fb_info *info)
struct fb_var_screeninfo *var = &info->var;
struct fb_videomode mode;
u32 x;
struct pxa168fb_mach_info *mi;
mi = dev_get_platdata(fbi->dev);
/*
* Set additional mode info.
......
......@@ -106,11 +106,11 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
struct fbtype __user *f = (struct fbtype __user *) arg;
if (put_user(type, &f->fb_type) ||
__put_user(info->var.yres, &f->fb_height) ||
__put_user(info->var.xres, &f->fb_width) ||
__put_user(fb_depth, &f->fb_depth) ||
__put_user(0, &f->fb_cmsize) ||
__put_user(fb_size, &f->fb_cmsize))
put_user(info->var.yres, &f->fb_height) ||
put_user(info->var.xres, &f->fb_width) ||
put_user(fb_depth, &f->fb_depth) ||
put_user(0, &f->fb_cmsize) ||
put_user(fb_size, &f->fb_cmsize))
return -EFAULT;
return 0;
}
......@@ -125,10 +125,10 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
unsigned int index, count, i;
if (get_user(index, &c->index) ||
__get_user(count, &c->count) ||
__get_user(ured, &c->red) ||
__get_user(ugreen, &c->green) ||
__get_user(ublue, &c->blue))
get_user(count, &c->count) ||
get_user(ured, &c->red) ||
get_user(ugreen, &c->green) ||
get_user(ublue, &c->blue))
return -EFAULT;
cmap.len = 1;
......@@ -165,13 +165,13 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
u8 red, green, blue;
if (get_user(index, &c->index) ||
__get_user(count, &c->count) ||
__get_user(ured, &c->red) ||
__get_user(ugreen, &c->green) ||
__get_user(ublue, &c->blue))
get_user(count, &c->count) ||
get_user(ured, &c->red) ||
get_user(ugreen, &c->green) ||
get_user(ublue, &c->blue))
return -EFAULT;
if (index + count > cmap->len)
if (index > cmap->len || count > cmap->len - index)
return -EINVAL;
for (i = 0; i < count; i++) {
......
......@@ -848,9 +848,7 @@ SiS_PanelDelay(struct SiS_Private *SiS_Pr, unsigned short DelayTime)
SiS_DDC2Delay(SiS_Pr, 0x4000);
}
} else if((SiS_Pr->SiS_IF_DEF_LVDS == 1) /* ||
(SiS_Pr->SiS_CustomT == CUT_COMPAQ1280) ||
(SiS_Pr->SiS_CustomT == CUT_CLEVO1400) */ ) { /* 315 series, LVDS; Special */
} else if (SiS_Pr->SiS_IF_DEF_LVDS == 1) { /* 315 series, LVDS; Special */
if(SiS_Pr->SiS_IF_DEF_CH70xx == 0) {
PanelID = SiS_GetReg(SiS_Pr->SiS_P3d4,0x36);
......
......@@ -667,9 +667,9 @@ static int ssd1307fb_probe(struct i2c_client *client,
if (par->reset) {
/* Reset the screen */
gpiod_set_value(par->reset, 0);
gpiod_set_value_cansleep(par->reset, 0);
udelay(4);
gpiod_set_value(par->reset, 1);
gpiod_set_value_cansleep(par->reset, 1);
udelay(4);
}
......
......@@ -916,8 +916,6 @@ static int dlfb_ops_open(struct fb_info *info, int user)
dlfb->fb_count++;
kref_get(&dlfb->kref);
if (fb_defio && (info->fbdefio == NULL)) {
/* enable defio at last moment if not disabled by client */
......@@ -940,14 +938,17 @@ static int dlfb_ops_open(struct fb_info *info, int user)
return 0;
}
/*
* Called when all client interfaces to start transactions have been disabled,
* and all references to our device instance (dlfb_data) are released.
* Every transaction must have a reference, so we know are fully spun down
*/
static void dlfb_free(struct kref *kref)
static void dlfb_ops_destroy(struct fb_info *info)
{
struct dlfb_data *dlfb = container_of(kref, struct dlfb_data, kref);
struct dlfb_data *dlfb = info->par;
if (info->cmap.len != 0)
fb_dealloc_cmap(&info->cmap);
if (info->monspecs.modedb)
fb_destroy_modedb(info->monspecs.modedb);
vfree(info->screen_base);
fb_destroy_modelist(&info->modelist);
while (!list_empty(&dlfb->deferred_free)) {
struct dlfb_deferred_free *d = list_entry(dlfb->deferred_free.next, struct dlfb_deferred_free, list);
......@@ -957,40 +958,13 @@ static void dlfb_free(struct kref *kref)
}
vfree(dlfb->backing_buffer);
kfree(dlfb->edid);
usb_put_dev(dlfb->udev);
kfree(dlfb);
}
static void dlfb_free_framebuffer(struct dlfb_data *dlfb)
{
struct fb_info *info = dlfb->info;
if (info) {
unregister_framebuffer(info);
if (info->cmap.len != 0)
fb_dealloc_cmap(&info->cmap);
if (info->monspecs.modedb)
fb_destroy_modedb(info->monspecs.modedb);
vfree(info->screen_base);
fb_destroy_modelist(&info->modelist);
dlfb->info = NULL;
/* Assume info structure is freed after this point */
framebuffer_release(info);
}
/* ref taken in probe() as part of registering framebfufer */
kref_put(&dlfb->kref, dlfb_free);
}
static void dlfb_free_framebuffer_work(struct work_struct *work)
{
struct dlfb_data *dlfb = container_of(work, struct dlfb_data,
free_framebuffer_work.work);
dlfb_free_framebuffer(dlfb);
}
/*
* Assumes caller is holding info->lock mutex (for open and release at least)
*/
......@@ -1000,10 +974,6 @@ static int dlfb_ops_release(struct fb_info *info, int user)
dlfb->fb_count--;
/* We can't free fb_info here - fbmem will touch it when we return */
if (dlfb->virtualized && (dlfb->fb_count == 0))
schedule_delayed_work(&dlfb->free_framebuffer_work, HZ);
if ((dlfb->fb_count == 0) && (info->fbdefio)) {
fb_deferred_io_cleanup(info);
kfree(info->fbdefio);
......@@ -1013,8 +983,6 @@ static int dlfb_ops_release(struct fb_info *info, int user)
dev_dbg(info->dev, "release, user=%d count=%d\n", user, dlfb->fb_count);
kref_put(&dlfb->kref, dlfb_free);
return 0;
}
......@@ -1172,6 +1140,7 @@ static struct fb_ops dlfb_ops = {
.fb_blank = dlfb_ops_blank,
.fb_check_var = dlfb_ops_check_var,
.fb_set_par = dlfb_ops_set_par,
.fb_destroy = dlfb_ops_destroy,
};
......@@ -1615,12 +1584,13 @@ static int dlfb_parse_vendor_descriptor(struct dlfb_data *dlfb,
return true;
}
static void dlfb_init_framebuffer_work(struct work_struct *work);
static int dlfb_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
int i;
const struct device_attribute *attr;
struct dlfb_data *dlfb;
struct fb_info *info;
int retval = -ENOMEM;
struct usb_device *usbdev = interface_to_usbdev(intf);
......@@ -1631,10 +1601,9 @@ static int dlfb_usb_probe(struct usb_interface *intf,
goto error;
}
kref_init(&dlfb->kref); /* matching kref_put in usb .disconnect fn */
INIT_LIST_HEAD(&dlfb->deferred_free);
dlfb->udev = usbdev;
dlfb->udev = usb_get_dev(usbdev);
usb_set_intfdata(intf, dlfb);
dev_dbg(&intf->dev, "console enable=%d\n", console);
......@@ -1657,42 +1626,6 @@ static int dlfb_usb_probe(struct usb_interface *intf,
}
if (!dlfb_alloc_urb_list(dlfb, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
retval = -ENOMEM;
dev_err(&intf->dev, "unable to allocate urb list\n");
goto error;
}
kref_get(&dlfb->kref); /* matching kref_put in free_framebuffer_work */
/* We don't register a new USB class. Our client interface is dlfbev */
/* Workitem keep things fast & simple during USB enumeration */
INIT_DELAYED_WORK(&dlfb->init_framebuffer_work,
dlfb_init_framebuffer_work);
schedule_delayed_work(&dlfb->init_framebuffer_work, 0);
return 0;
error:
if (dlfb) {
kref_put(&dlfb->kref, dlfb_free); /* last ref from kref_init */
/* dev has been deallocated. Do not dereference */
}
return retval;
}
static void dlfb_init_framebuffer_work(struct work_struct *work)
{
int i, retval;
struct fb_info *info;
const struct device_attribute *attr;
struct dlfb_data *dlfb = container_of(work, struct dlfb_data,
init_framebuffer_work.work);
/* allocates framebuffer driver structure, not framebuffer memory */
info = framebuffer_alloc(0, &dlfb->udev->dev);
if (!info) {
......@@ -1706,17 +1639,22 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
dlfb->ops = dlfb_ops;
info->fbops = &dlfb->ops;
INIT_LIST_HEAD(&info->modelist);
if (!dlfb_alloc_urb_list(dlfb, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
retval = -ENOMEM;
dev_err(&intf->dev, "unable to allocate urb list\n");
goto error;
}
/* We don't register a new USB class. Our client interface is dlfbev */
retval = fb_alloc_cmap(&info->cmap, 256, 0);
if (retval < 0) {
dev_err(info->device, "cmap allocation failed: %d\n", retval);
goto error;
}
INIT_DELAYED_WORK(&dlfb->free_framebuffer_work,
dlfb_free_framebuffer_work);
INIT_LIST_HEAD(&info->modelist);
retval = dlfb_setup_modes(dlfb, info, NULL, 0);
if (retval != 0) {
dev_err(info->device,
......@@ -1760,10 +1698,16 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
dev_name(info->dev), info->var.xres, info->var.yres,
((dlfb->backing_buffer) ?
info->fix.smem_len * 2 : info->fix.smem_len) >> 10);
return;
return 0;
error:
dlfb_free_framebuffer(dlfb);
if (dlfb->info) {
dlfb_ops_destroy(dlfb->info);
} else if (dlfb) {
usb_put_dev(dlfb->udev);
kfree(dlfb);
}
return retval;
}
static void dlfb_usb_disconnect(struct usb_interface *intf)
......@@ -1791,20 +1735,9 @@ static void dlfb_usb_disconnect(struct usb_interface *intf)
for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
device_remove_file(info->dev, &fb_device_attrs[i]);
device_remove_bin_file(info->dev, &edid_attr);
unlink_framebuffer(info);
}
usb_set_intfdata(intf, NULL);
dlfb->udev = NULL;
/* if clients still have us open, will be freed on last close */
if (dlfb->fb_count == 0)
schedule_delayed_work(&dlfb->free_framebuffer_work, 0);
/* release reference taken by kref_init in probe() */
kref_put(&dlfb->kref, dlfb_free);
/* consider dlfb_data freed */
unregister_framebuffer(info);
}
static struct usb_driver dlfb_driver = {
......
......@@ -170,7 +170,7 @@ struct display_timings *of_get_display_timings(const struct device_node *np)
goto entryfail;
}
pr_debug("%pOF: using %s as default timing\n", np, entry->name);
pr_debug("%pOF: using %pOFn as default timing\n", np, entry);
native_mode = entry;
......
......@@ -455,7 +455,7 @@ int save_vga(struct vgastate *state)
return 0;
}
int restore_vga (struct vgastate *state)
int restore_vga(struct vgastate *state)
{
if (state->vidstate == NULL)
return 1;
......
......@@ -36,12 +36,9 @@ struct dlfb_data {
struct usb_device *udev;
struct fb_info *info;
struct urb_list urbs;
struct kref kref;
char *backing_buffer;
int fb_count;
bool virtualized; /* true when physical usb device not present */
struct delayed_work init_framebuffer_work;
struct delayed_work free_framebuffer_work;
atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
char *edid; /* null until we read edid from hw or get from sysfs */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment