Commit cccd559e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-v5.2' of git://github.com/bzolnier/linux

Pull fbdev updates from Bartlomiej Zolnierkiewicz:
 "Four small fixes for fb core, updates for udlfb, sm712fb, macfb and
  atafb drivers. Redundant code removals from amba-clcd and atmel_lcdfb
  drivers. Minor fixes/cleanups for other fb drivers

  Detailed summary:

   - fix regression in fbcon logo handling on 'quiet' boots (Andreas
     Schwab)

   - fix divide-by-zero error in fb_var_to_videomode() (Shile Zhang)

   - fix 'WARNING in __alloc_pages_nodemask' bug (Jiufei Xue)

   - list all PCI memory BARs as conflicting apertures (Gerd Hoffmann)

   - update udlfb driver: fix sleeping inside spinlock, add mutex around
     rendering calls and remove redundant code (Mikulas Patocka)

   - update sm712fb driver: fix SM720 support related issues (Yifeng Li)

   - update macfb driver: fix DAFB colour table pointer initialization
     and remove redundant code (Finn Thain)

   - update atafb driver: fix kexec support, use dev_*() calls instead
     of printk() and remove obsolete module support (Geert Uytterhoeven)

   - add support to mxsfb driver for skipping display initialization for
     flicker-free display takeover from bootloader (Melchior Franz)

   - remove Versatile and Nomadik board families support from amba-clcd
     driver as they are handled by DRM driver nowadays (Linus Walleij)

   - remove no longer needed AVR and platform_data support from
     atmel_lcdfb driver (Alexandre Belloni)

   - misc fixes (Colin Ian King, Julia Lawall, Gustavo A. R. Silva,
     Aditya Pakki, Kangjie Lu, YueHaibing)

   - misc cleanups (Enrico Weigelt, Kefeng Wang)"

* tag 'fbdev-v5.2' of git://github.com/bzolnier/linux: (38 commits)
  video: fbdev: Use dev_get_drvdata()
  fbcon: Don't reset logo_shown when logo is currently shown
  video: fbdev: atmel_lcdfb: remove set but not used variable 'pdata'
  video: fbdev: mxsfb: remove set but not used variable 'line_count'
  video: fbdev: pvr2fb: remove set but not used variable 'size'
  fbdev: fix WARNING in __alloc_pages_nodemask bug
  video: amba-clcd: Decomission Versatile and Nomadik
  fbdev: sm712fb: fix memory frequency by avoiding a switch/case fallthrough
  fbdev: fix divide error in fb_var_to_videomode
  fbdev: sm712fb: use 1024x768 by default on non-MIPS, fix garbled display
  fbdev: sm712fb: fix support for 1024x768-16 mode
  fbdev: sm712fb: fix crashes and garbled display during DPMS modesetting
  fbdev: sm712fb: fix crashes during framebuffer writes by correctly mapping VRAM
  fbdev: sm712fb: fix boot screen glitch when sm712fb replaces VGA
  fbdev: sm712fb: fix VRAM detection, don't set SR70/71/74/75
  fbdev: sm712fb: fix brightness control on reboot, don't set SR30
  fbdev: sm712fb: fix white screen of death on reboot, don't set CR3B-CR3F
  video: imsttfb: fix potential NULL pointer dereferences
  video: hgafb: fix potential NULL pointer dereference
  fbdev: list all pci memory bars as conflicting apertures
  ...
parents cece6460 d4a56117
......@@ -293,14 +293,6 @@ config FB_ARMCLCD
here and read <file:Documentation/kbuild/modules.txt>. The module
will be called amba-clcd.
# Helper logic selected only by the ARM Versatile platform family.
config PLAT_VERSATILE_CLCD
def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR
depends on ARM
depends on FB_ARMCLCD && FB=y
select REGMAP
select MFD_SYSCON
config FB_ACORN
bool "Acorn VIDC support"
depends on (FB = y) && ARM && ARCH_ACORN
......@@ -866,8 +858,8 @@ config FB_S1D13XXX
<http://vdc.epson.com/>
config FB_ATMEL
tristate "AT91/AT32 LCD Controller support"
depends on FB && HAVE_FB_ATMEL
tristate "AT91 LCD Controller support"
depends on FB && OF && HAVE_FB_ATMEL
select FB_BACKLIGHT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
......@@ -875,7 +867,7 @@ config FB_ATMEL
select FB_MODE_HELPERS
select VIDEOMODE_HELPERS
help
This enables support for the AT91/AT32 LCD Controller.
This enables support for the AT91 LCD Controller.
config FB_NVIDIA
tristate "nVidia Framebuffer Support"
......@@ -2183,7 +2175,7 @@ config FB_EP93XX
config FB_PRE_INIT_FB
bool "Don't reinitialize, use bootloader's GDC/Display configuration"
depends on FB && FB_MB862XX_LIME
depends on FB && (FB_MB862XX_LIME || FB_MXS)
---help---
Select this option if display contents should be inherited as set by
the bootloader.
......
......@@ -76,8 +76,6 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
obj-$(CONFIG_ARCH_NOMADIK) += amba-clcd-nomadik.o
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += amba-clcd-versatile.o
obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
obj-$(CONFIG_FB_68328) += 68328fb.o
obj-$(CONFIG_FB_GBE) += gbefb.o
......
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "amba-clcd-nomadik.h"
static struct gpio_desc *grestb;
static struct gpio_desc *scen;
static struct gpio_desc *scl;
static struct gpio_desc *sda;
static u8 tpg110_readwrite_reg(bool write, u8 address, u8 outval)
{
int i;
u8 inval = 0;
/* Assert SCEN */
gpiod_set_value_cansleep(scen, 1);
ndelay(150);
/* Hammer out the address */
for (i = 5; i >= 0; i--) {
if (address & BIT(i))
gpiod_set_value_cansleep(sda, 1);
else
gpiod_set_value_cansleep(sda, 0);
ndelay(150);
/* Send an SCL pulse */
gpiod_set_value_cansleep(scl, 1);
ndelay(160);
gpiod_set_value_cansleep(scl, 0);
ndelay(160);
}
if (write) {
/* WRITE */
gpiod_set_value_cansleep(sda, 0);
} else {
/* READ */
gpiod_set_value_cansleep(sda, 1);
}
ndelay(150);
/* Send an SCL pulse */
gpiod_set_value_cansleep(scl, 1);
ndelay(160);
gpiod_set_value_cansleep(scl, 0);
ndelay(160);
if (!write)
/* HiZ turn-around cycle */
gpiod_direction_input(sda);
ndelay(150);
/* Send an SCL pulse */
gpiod_set_value_cansleep(scl, 1);
ndelay(160);
gpiod_set_value_cansleep(scl, 0);
ndelay(160);
/* Hammer in/out the data */
for (i = 7; i >= 0; i--) {
int value;
if (write) {
value = !!(outval & BIT(i));
gpiod_set_value_cansleep(sda, value);
} else {
value = gpiod_get_value(sda);
if (value)
inval |= BIT(i);
}
ndelay(150);
/* Send an SCL pulse */
gpiod_set_value_cansleep(scl, 1);
ndelay(160);
gpiod_set_value_cansleep(scl, 0);
ndelay(160);
}
gpiod_direction_output(sda, 0);
/* Deassert SCEN */
gpiod_set_value_cansleep(scen, 0);
/* Satisfies SCEN pulse width */
udelay(1);
return inval;
}
static u8 tpg110_read_reg(u8 address)
{
return tpg110_readwrite_reg(false, address, 0);
}
static void tpg110_write_reg(u8 address, u8 outval)
{
tpg110_readwrite_reg(true, address, outval);
}
static void tpg110_startup(struct device *dev)
{
u8 val;
dev_info(dev, "TPG110 display enable\n");
/* De-assert the reset signal */
gpiod_set_value_cansleep(grestb, 0);
mdelay(1);
dev_info(dev, "de-asserted GRESTB\n");
/* Test display communication */
tpg110_write_reg(0x00, 0x55);
val = tpg110_read_reg(0x00);
if (val == 0x55)
dev_info(dev, "passed communication test\n");
val = tpg110_read_reg(0x01);
dev_info(dev, "TPG110 chip ID: %d version: %d\n",
val>>4, val&0x0f);
/* Show display resolution */
val = tpg110_read_reg(0x02);
val &= 7;
switch (val) {
case 0x0:
dev_info(dev, "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)");
break;
case 0x1:
dev_info(dev, "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)");
break;
case 0x4:
dev_info(dev, "480x640 RGB");
break;
case 0x5:
dev_info(dev, "480x272 RGB");
break;
case 0x6:
dev_info(dev, "640x480 RGB");
break;
case 0x7:
dev_info(dev, "800x480 RGB");
break;
default:
dev_info(dev, "ILLEGAL RESOLUTION");
break;
}
val = tpg110_read_reg(0x03);
dev_info(dev, "resolution is controlled by %s\n",
(val & BIT(7)) ? "software" : "hardware");
}
static void tpg110_enable(struct clcd_fb *fb)
{
struct device *dev = &fb->dev->dev;
static bool startup;
u8 val;
if (!startup) {
tpg110_startup(dev);
startup = true;
}
/* Take chip out of standby */
val = tpg110_read_reg(0x03);
val |= BIT(0);
tpg110_write_reg(0x03, val);
}
static void tpg110_disable(struct clcd_fb *fb)
{
u8 val;
dev_info(&fb->dev->dev, "TPG110 display disable\n");
val = tpg110_read_reg(0x03);
/* Put into standby */
val &= ~BIT(0);
tpg110_write_reg(0x03, val);
}
static void tpg110_init(struct device *dev, struct device_node *np,
struct clcd_board *board)
{
dev_info(dev, "TPG110 display init\n");
/* This asserts the GRESTB signal, putting the display into reset */
grestb = devm_fwnode_get_gpiod_from_child(dev, "grestb", &np->fwnode,
GPIOD_OUT_HIGH, "grestb");
if (IS_ERR(grestb)) {
dev_err(dev, "no GRESTB GPIO\n");
return;
}
scen = devm_fwnode_get_gpiod_from_child(dev, "scen", &np->fwnode,
GPIOD_OUT_LOW, "scen");
if (IS_ERR(scen)) {
dev_err(dev, "no SCEN GPIO\n");
return;
}
scl = devm_fwnode_get_gpiod_from_child(dev, "scl", &np->fwnode,
GPIOD_OUT_LOW, "scl");
if (IS_ERR(scl)) {
dev_err(dev, "no SCL GPIO\n");
return;
}
sda = devm_fwnode_get_gpiod_from_child(dev, "sda", &np->fwnode,
GPIOD_OUT_LOW, "sda");
if (IS_ERR(sda)) {
dev_err(dev, "no SDA GPIO\n");
return;
}
board->enable = tpg110_enable;
board->disable = tpg110_disable;
}
int nomadik_clcd_init_panel(struct clcd_fb *fb, struct device_node *panel)
{
if (of_device_is_compatible(panel, "tpo,tpg110"))
tpg110_init(&fb->dev->dev, panel, fb->board);
else
dev_info(&fb->dev->dev, "unknown panel\n");
/* Unknown panel, fall through */
return 0;
}
EXPORT_SYMBOL_GPL(nomadik_clcd_init_panel);
#define PMU_CTRL_OFFSET 0x0000
#define PMU_CTRL_LCDNDIF BIT(26)
int nomadik_clcd_init_board(struct amba_device *adev,
struct clcd_board *board)
{
struct regmap *pmu_regmap;
dev_info(&adev->dev, "Nomadik CLCD board init\n");
pmu_regmap =
syscon_regmap_lookup_by_compatible("stericsson,nomadik-pmu");
if (IS_ERR(pmu_regmap)) {
dev_err(&adev->dev, "could not find PMU syscon regmap\n");
return PTR_ERR(pmu_regmap);
}
regmap_update_bits(pmu_regmap,
PMU_CTRL_OFFSET,
PMU_CTRL_LCDNDIF,
0);
dev_info(&adev->dev, "set PMU mux to CLCD mode\n");
return 0;
}
EXPORT_SYMBOL_GPL(nomadik_clcd_init_board);
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _AMBA_CLCD_NOMADIK_H
#define _AMBA_CLCD_NOMADIK_H
#include <linux/amba/bus.h>
#ifdef CONFIG_ARCH_NOMADIK
int nomadik_clcd_init_board(struct amba_device *adev,
struct clcd_board *board);
int nomadik_clcd_init_panel(struct clcd_fb *fb, struct device_node *panel);
#else
static inline int nomadik_clcd_init_board(struct amba_device *adev,
struct clcd_board *board)
{
return 0;
}
static inline int nomadik_clcd_init_panel(struct clcd_fb *fb,
struct device_node *panel)
{
return 0;
}
#endif
#endif /* inclusion guard */
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/amba/bus.h>
#include <linux/amba/clcd.h>
#include <linux/platform_data/video-clcd-versatile.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/bitops.h>
#include "amba-clcd-versatile.h"
static struct clcd_panel vga = {
.mode = {
.name = "VGA",
.refresh = 60,
.xres = 640,
.yres = 480,
.pixclock = 39721,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
.bpp = 16,
};
static struct clcd_panel xvga = {
.mode = {
.name = "XVGA",
.refresh = 60,
.xres = 1024,
.yres = 768,
.pixclock = 15748,
.left_margin = 152,
.right_margin = 48,
.upper_margin = 23,
.lower_margin = 3,
.hsync_len = 104,
.vsync_len = 4,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
.bpp = 16,
};
/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */
static struct clcd_panel sanyo_tm38qv67a02a = {
.mode = {
.name = "Sanyo TM38QV67A02A",
.refresh = 116,
.xres = 320,
.yres = 240,
.pixclock = 100000,
.left_margin = 6,
.right_margin = 6,
.upper_margin = 5,
.lower_margin = 5,
.hsync_len = 6,
.vsync_len = 6,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
static struct clcd_panel sanyo_2_5_in = {
.mode = {
.name = "Sanyo QVGA Portrait",
.refresh = 116,
.xres = 240,
.yres = 320,
.pixclock = 100000,
.left_margin = 20,
.right_margin = 10,
.upper_margin = 2,
.lower_margin = 2,
.hsync_len = 10,
.vsync_len = 2,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_IVS | TIM2_IHS | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */
static struct clcd_panel epson_l2f50113t00 = {
.mode = {
.name = "Epson L2F50113T00",
.refresh = 390,
.xres = 176,
.yres = 220,
.pixclock = 62500,
.left_margin = 3,
.right_margin = 2,
.upper_margin = 1,
.lower_margin = 0,
.hsync_len = 3,
.vsync_len = 2,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
},
.width = -1,
.height = -1,
.tim2 = TIM2_BCD | TIM2_IPC,
.cntl = CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
.caps = CLCD_CAP_5551,
.bpp = 16,
};
static struct clcd_panel *panels[] = {
&vga,
&xvga,
&sanyo_tm38qv67a02a,
&sanyo_2_5_in,
&epson_l2f50113t00,
};
struct clcd_panel *versatile_clcd_get_panel(const char *name)
{
int i;
for (i = 0; i < ARRAY_SIZE(panels); i++)
if (strcmp(panels[i]->mode.name, name) == 0)
break;
if (i < ARRAY_SIZE(panels))
return panels[i];
pr_err("CLCD: couldn't get parameters for panel %s\n", name);
return NULL;
}
int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
{
dma_addr_t dma;
fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, framesize, &dma,
GFP_KERNEL);
if (!fb->fb.screen_base) {
pr_err("CLCD: unable to map framebuffer\n");
return -ENOMEM;
}
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base,
fb->fb.fix.smem_start, fb->fb.fix.smem_len);
}
void versatile_clcd_remove_dma(struct clcd_fb *fb)
{
dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
fb->fb.fix.smem_start);
}
#ifdef CONFIG_OF
static struct regmap *versatile_syscon_map;
static struct regmap *versatile_ib2_map;
/*
* We detect the different syscon types from the compatible strings.
*/
enum versatile_clcd {
INTEGRATOR_CLCD_CM,
VERSATILE_CLCD,
REALVIEW_CLCD_EB,
REALVIEW_CLCD_PB1176,
REALVIEW_CLCD_PB11MP,
REALVIEW_CLCD_PBA8,
REALVIEW_CLCD_PBX,
};
static const struct of_device_id versatile_clcd_of_match[] = {
{
.compatible = "arm,core-module-integrator",
.data = (void *)INTEGRATOR_CLCD_CM,
},
{
.compatible = "arm,versatile-sysreg",
.data = (void *)VERSATILE_CLCD,
},
{
.compatible = "arm,realview-eb-syscon",
.data = (void *)REALVIEW_CLCD_EB,
},
{
.compatible = "arm,realview-pb1176-syscon",
.data = (void *)REALVIEW_CLCD_PB1176,
},
{
.compatible = "arm,realview-pb11mp-syscon",
.data = (void *)REALVIEW_CLCD_PB11MP,
},
{
.compatible = "arm,realview-pba8-syscon",
.data = (void *)REALVIEW_CLCD_PBA8,
},
{
.compatible = "arm,realview-pbx-syscon",
.data = (void *)REALVIEW_CLCD_PBX,
},
{},
};
/*
* Core module CLCD control on the Integrator/CP, bits
* 8 thru 19 of the CM_CONTROL register controls a bunch
* of CLCD settings.
*/
#define INTEGRATOR_HDR_CTRL_OFFSET 0x0C
#define INTEGRATOR_CLCD_LCDBIASEN BIT(8)
#define INTEGRATOR_CLCD_LCDBIASUP BIT(9)
#define INTEGRATOR_CLCD_LCDBIASDN BIT(10)
/* Bits 11,12,13 controls the LCD type */
#define INTEGRATOR_CLCD_LCDMUX_MASK (BIT(11)|BIT(12)|BIT(13))
#define INTEGRATOR_CLCD_LCDMUX_LCD24 BIT(11)
#define INTEGRATOR_CLCD_LCDMUX_VGA565 BIT(12)
#define INTEGRATOR_CLCD_LCDMUX_SHARP (BIT(11)|BIT(12))
#define INTEGRATOR_CLCD_LCDMUX_VGA555 BIT(13)
#define INTEGRATOR_CLCD_LCDMUX_VGA24 (BIT(11)|BIT(12)|BIT(13))
#define INTEGRATOR_CLCD_LCD0_EN BIT(14)
#define INTEGRATOR_CLCD_LCD1_EN BIT(15)
/* R/L flip on Sharp */
#define INTEGRATOR_CLCD_LCD_STATIC1 BIT(16)
/* U/D flip on Sharp */
#define INTEGRATOR_CLCD_LCD_STATIC2 BIT(17)
/* No connection on Sharp */
#define INTEGRATOR_CLCD_LCD_STATIC BIT(18)
/* 0 = 24bit VGA, 1 = 18bit VGA */
#define INTEGRATOR_CLCD_LCD_N24BITEN BIT(19)
#define INTEGRATOR_CLCD_MASK (INTEGRATOR_CLCD_LCDBIASEN | \
INTEGRATOR_CLCD_LCDBIASUP | \
INTEGRATOR_CLCD_LCDBIASDN | \
INTEGRATOR_CLCD_LCDMUX_MASK | \
INTEGRATOR_CLCD_LCD0_EN | \
INTEGRATOR_CLCD_LCD1_EN | \
INTEGRATOR_CLCD_LCD_STATIC1 | \
INTEGRATOR_CLCD_LCD_STATIC2 | \
INTEGRATOR_CLCD_LCD_STATIC | \
INTEGRATOR_CLCD_LCD_N24BITEN)
static void integrator_clcd_enable(struct clcd_fb *fb)
{
struct fb_var_screeninfo *var = &fb->fb.var;
u32 val;
dev_info(&fb->dev->dev, "enable Integrator CLCD connectors\n");
/* FIXME: really needed? */
val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 |
INTEGRATOR_CLCD_LCD0_EN | INTEGRATOR_CLCD_LCD1_EN;
if (var->bits_per_pixel <= 8 ||
(var->bits_per_pixel == 16 && var->green.length == 5))
/* Pseudocolor, RGB555, BGR555 */
val |= INTEGRATOR_CLCD_LCDMUX_VGA555;
else if (fb->fb.var.bits_per_pixel <= 16)
/* truecolor RGB565 */
val |= INTEGRATOR_CLCD_LCDMUX_VGA565;
else
val = 0; /* no idea for this, don't trust the docs */
regmap_update_bits(versatile_syscon_map,
INTEGRATOR_HDR_CTRL_OFFSET,
INTEGRATOR_CLCD_MASK,
val);
}
/*
* This configuration register in the Versatile and RealView
* family is uniformly present but appears more and more
* unutilized starting with the RealView series.
*/
#define SYS_CLCD 0x50
#define SYS_CLCD_MODE_MASK (BIT(0)|BIT(1))
#define SYS_CLCD_MODE_888 0
#define SYS_CLCD_MODE_5551 BIT(0)
#define SYS_CLCD_MODE_565_R_LSB BIT(1)
#define SYS_CLCD_MODE_565_B_LSB (BIT(0)|BIT(1))
#define SYS_CLCD_CONNECTOR_MASK (BIT(2)|BIT(3)|BIT(4)|BIT(5))
#define SYS_CLCD_NLCDIOON BIT(2)
#define SYS_CLCD_VDDPOSSWITCH BIT(3)
#define SYS_CLCD_PWR3V5SWITCH BIT(4)
#define SYS_CLCD_VDDNEGSWITCH BIT(5)
#define SYS_CLCD_TSNSS BIT(6) /* touchscreen enable */
#define SYS_CLCD_SSPEXP BIT(7) /* SSP expansion enable */
/* The Versatile can detect the connected panel type */
#define SYS_CLCD_CLCDID_MASK (BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12))
#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)
#define SYS_CLCD_ID_SHARP_8_4 (0x01 << 8)
#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)
#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
#define SYS_CLCD_ID_VGA (0x1f << 8)
#define SYS_CLCD_TSNDAV BIT(13) /* data ready from TS */
/* IB2 control register for the Versatile daughterboard */
#define IB2_CTRL 0x00
#define IB2_CTRL_LCD_SD BIT(1) /* 1 = shut down LCD */
#define IB2_CTRL_LCD_BL_ON BIT(0)
#define IB2_CTRL_LCD_MASK (BIT(0)|BIT(1))
static void versatile_clcd_disable(struct clcd_fb *fb)
{
dev_info(&fb->dev->dev, "disable Versatile CLCD connectors\n");
regmap_update_bits(versatile_syscon_map,
SYS_CLCD,
SYS_CLCD_CONNECTOR_MASK,
0);
/* If we're on an IB2 daughterboard, turn off display */
if (versatile_ib2_map) {
dev_info(&fb->dev->dev, "disable IB2 display\n");
regmap_update_bits(versatile_ib2_map,
IB2_CTRL,
IB2_CTRL_LCD_MASK,
IB2_CTRL_LCD_SD);
}
}
static void versatile_clcd_enable(struct clcd_fb *fb)
{
struct fb_var_screeninfo *var = &fb->fb.var;
u32 val = 0;
dev_info(&fb->dev->dev, "enable Versatile CLCD connectors\n");
switch (var->green.length) {
case 5:
val |= SYS_CLCD_MODE_5551;
break;
case 6:
if (var->red.offset == 0)
val |= SYS_CLCD_MODE_565_R_LSB;
else
val |= SYS_CLCD_MODE_565_B_LSB;
break;
case 8:
val |= SYS_CLCD_MODE_888;
break;
}
/* Set up the MUX */
regmap_update_bits(versatile_syscon_map,
SYS_CLCD,
SYS_CLCD_MODE_MASK,
val);
/* Then enable the display */
regmap_update_bits(versatile_syscon_map,
SYS_CLCD,
SYS_CLCD_CONNECTOR_MASK,
SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH);
/* If we're on an IB2 daughterboard, turn on display */
if (versatile_ib2_map) {
dev_info(&fb->dev->dev, "enable IB2 display\n");
regmap_update_bits(versatile_ib2_map,
IB2_CTRL,
IB2_CTRL_LCD_MASK,
IB2_CTRL_LCD_BL_ON);
}
}
static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs)
{
clcdfb_decode(fb, regs);
/* Always clear BGR for RGB565: we do the routing externally */
if (fb->fb.var.green.length == 6)
regs->cntl &= ~CNTL_BGR;
}
static void realview_clcd_disable(struct clcd_fb *fb)
{
dev_info(&fb->dev->dev, "disable RealView CLCD connectors\n");
regmap_update_bits(versatile_syscon_map,
SYS_CLCD,
SYS_CLCD_CONNECTOR_MASK,
0);
}
static void realview_clcd_enable(struct clcd_fb *fb)
{
dev_info(&fb->dev->dev, "enable RealView CLCD connectors\n");
regmap_update_bits(versatile_syscon_map,
SYS_CLCD,
SYS_CLCD_CONNECTOR_MASK,
SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH);
}
struct versatile_panel {
u32 id;
char *compatible;
bool ib2;
};
static const struct versatile_panel versatile_panels[] = {
{
.id = SYS_CLCD_ID_VGA,
.compatible = "VGA",
},
{
.id = SYS_CLCD_ID_SANYO_3_8,
.compatible = "sanyo,tm38qv67a02a",
},
{
.id = SYS_CLCD_ID_SHARP_8_4,
.compatible = "sharp,lq084v1dg21",
},
{
.id = SYS_CLCD_ID_EPSON_2_2,
.compatible = "epson,l2f50113t00",
},
{
.id = SYS_CLCD_ID_SANYO_2_5,
.compatible = "sanyo,alr252rgt",
.ib2 = true,
},
};
static void versatile_panel_probe(struct device *dev, struct device_node *panel)
{
struct versatile_panel const *vpanel = NULL;
u32 val;
int ret;
int i;
/*
* The Versatile CLCD has a panel auto-detection mechanism.
* We use this and look for the compatible panel in the
* device tree.
*/
ret = regmap_read(versatile_syscon_map, SYS_CLCD, &val);
if (ret) {
dev_err(dev, "cannot read CLCD syscon register\n");
return;
}
val &= SYS_CLCD_CLCDID_MASK;
/* First find corresponding panel information */
for (i = 0; i < ARRAY_SIZE(versatile_panels); i++) {
vpanel = &versatile_panels[i];
if (val == vpanel->id) {
dev_err(dev, "autodetected panel \"%s\"\n",
vpanel->compatible);
break;
}
}
if (i == ARRAY_SIZE(versatile_panels)) {
dev_err(dev, "could not auto-detect panel\n");
return;
}
if (!of_device_is_compatible(panel, vpanel->compatible))
dev_err(dev, "panel in DT is not compatible with the "
"auto-detected panel, continuing anyway\n");
/*
* If we have a Sanyo 2.5" port
* that we're running on an IB2 and proceed to look for the
* IB2 syscon regmap.
*/
if (!vpanel->ib2)
return;
versatile_ib2_map = syscon_regmap_lookup_by_compatible(
"arm,versatile-ib2-syscon");
if (IS_ERR(versatile_ib2_map)) {
dev_err(dev, "could not locate IB2 control register\n");
versatile_ib2_map = NULL;
return;
}
}
int versatile_clcd_init_panel(struct clcd_fb *fb, struct device_node *panel)
{
const struct of_device_id *clcd_id;
enum versatile_clcd versatile_clcd_type;
struct device_node *np;
struct regmap *map;
struct device *dev = &fb->dev->dev;
np = of_find_matching_node_and_match(NULL, versatile_clcd_of_match,
&clcd_id);
if (!np) {
/* Vexpress does not have this */
return 0;
}
versatile_clcd_type = (enum versatile_clcd)clcd_id->data;
map = syscon_node_to_regmap(np);
if (IS_ERR(map)) {
dev_err(dev, "no Versatile syscon regmap\n");
return PTR_ERR(map);
}
switch (versatile_clcd_type) {
case INTEGRATOR_CLCD_CM:
versatile_syscon_map = map;
fb->board->enable = integrator_clcd_enable;
/* Override the caps, we have only these */
fb->board->caps = CLCD_CAP_5551 | CLCD_CAP_RGB565 |
CLCD_CAP_888;
dev_info(dev, "set up callbacks for Integrator PL110\n");
break;
case VERSATILE_CLCD:
versatile_syscon_map = map;
fb->board->enable = versatile_clcd_enable;
fb->board->disable = versatile_clcd_disable;
fb->board->decode = versatile_clcd_decode;
versatile_panel_probe(dev, panel);
dev_info(dev, "set up callbacks for Versatile\n");
break;
case REALVIEW_CLCD_EB:
case REALVIEW_CLCD_PB1176:
case REALVIEW_CLCD_PB11MP:
case REALVIEW_CLCD_PBA8:
case REALVIEW_CLCD_PBX:
versatile_syscon_map = map;
fb->board->enable = realview_clcd_enable;
fb->board->disable = realview_clcd_disable;
dev_info(dev, "set up callbacks for RealView PL111\n");
break;
default:
dev_info(dev, "unknown Versatile system controller\n");
break;
}
return 0;
}
EXPORT_SYMBOL_GPL(versatile_clcd_init_panel);
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Special local versatile callbacks
*/
#include <linux/of.h>
#include <linux/amba/bus.h>
#include <linux/platform_data/video-clcd-versatile.h>
#if defined(CONFIG_PLAT_VERSATILE_CLCD) && defined(CONFIG_OF)
int versatile_clcd_init_panel(struct clcd_fb *fb, struct device_node *panel);
#else
static inline int versatile_clcd_init_panel(struct clcd_fb *fb,
struct device_node *panel)
{
return 0;
}
#endif
......@@ -30,9 +30,6 @@
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include "amba-clcd-nomadik.h"
#include "amba-clcd-versatile.h"
#define to_clcd(info) container_of(info, struct clcd_fb, fb)
/* This is limited to 16 characters when displayed by X startup */
......@@ -223,15 +220,6 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
var->blue.length = 4;
}
break;
case 24:
if (fb->vendor->packed_24_bit_pixels) {
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
} else {
ret = -EINVAL;
}
break;
case 32:
/* If we can't do 888, reject */
caps &= CLCD_CAP_888;
......@@ -318,12 +306,6 @@ static int clcdfb_set_par(struct fb_info *info)
clcdfb_disable(fb);
/* Some variants must be clocked here */
if (fb->vendor->clock_timregs && !fb->clk_enabled) {
fb->clk_enabled = true;
clk_enable(fb->clk);
}
writel(regs.tim0, fb->regs + CLCD_TIM0);
writel(regs.tim1, fb->regs + CLCD_TIM1);
writel(regs.tim2, fb->regs + CLCD_TIM2);
......@@ -464,16 +446,10 @@ static int clcdfb_register(struct clcd_fb *fb)
if (amba_manf(fb->dev) == 0x41 && amba_part(fb->dev) == 0x111) {
fb->off_ienb = CLCD_PL111_IENB;
fb->off_cntl = CLCD_PL111_CNTL;
} else {
if (of_machine_is_compatible("arm,versatile-ab") ||
of_machine_is_compatible("arm,versatile-pb")) {
fb->off_ienb = CLCD_PL111_IENB;
fb->off_cntl = CLCD_PL111_CNTL;
} else {
fb->off_ienb = CLCD_PL110_IENB;
fb->off_cntl = CLCD_PL110_CNTL;
}
}
fb->clk = clk_get(&fb->dev->dev, NULL);
if (IS_ERR(fb->clk)) {
......@@ -713,42 +689,6 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
if (r0 != 0 && b0 == 0)
fb->panel->bgr_connection = true;
if (fb->panel->caps && fb->vendor->st_bitmux_control) {
/*
* Set up the special bits for the Nomadik control register
* (other platforms tend to do this through an external
* register).
*/
/* Offset of the highest used color */
int maxoff = max3(r0, g0, b0);
/* Most significant bit out, highest used bit */
int msb = 0;
if (fb->panel->caps & CLCD_CAP_888) {
msb = maxoff + 8 - 1;
} else if (fb->panel->caps & CLCD_CAP_565) {
msb = maxoff + 5 - 1;
fb->panel->cntl |= CNTL_ST_1XBPP_565;
} else if (fb->panel->caps & CLCD_CAP_5551) {
msb = maxoff + 5 - 1;
fb->panel->cntl |= CNTL_ST_1XBPP_5551;
} else if (fb->panel->caps & CLCD_CAP_444) {
msb = maxoff + 4 - 1;
fb->panel->cntl |= CNTL_ST_1XBPP_444;
}
/* Send out as many bits as we need */
if (msb > 17)
fb->panel->cntl |= CNTL_ST_CDWID_24;
else if (msb > 15)
fb->panel->cntl |= CNTL_ST_CDWID_18;
else if (msb > 11)
fb->panel->cntl |= CNTL_ST_CDWID_16;
else
fb->panel->cntl |= CNTL_ST_CDWID_12;
}
return fb->panel->caps ? 0 : -EINVAL;
}
......@@ -775,12 +715,6 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
if (!panel)
return -ENODEV;
if (fb->vendor->init_panel) {
err = fb->vendor->init_panel(fb, panel);
if (err)
return err;
}
err = clcdfb_of_get_backlight(panel, fb->panel);
if (err)
return err;
......@@ -941,7 +875,6 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
{
struct clcd_board *board = dev_get_platdata(&dev->dev);
struct clcd_vendor_data *vendor = id->data;
struct clcd_fb *fb;
int ret;
......@@ -951,12 +884,6 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
if (!board)
return -EINVAL;
if (vendor->init_board) {
ret = vendor->init_board(dev, board);
if (ret)
return ret;
}
ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
if (ret)
goto out;
......@@ -974,7 +901,6 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
}
fb->dev = dev;
fb->vendor = vendor;
fb->board = board;
dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n",
......@@ -1021,30 +947,10 @@ static int clcdfb_remove(struct amba_device *dev)
return 0;
}
static struct clcd_vendor_data vendor_arm = {
/* Sets up the versatile board displays */
.init_panel = versatile_clcd_init_panel,
};
static struct clcd_vendor_data vendor_nomadik = {
.clock_timregs = true,
.packed_24_bit_pixels = true,
.st_bitmux_control = true,
.init_board = nomadik_clcd_init_board,
.init_panel = nomadik_clcd_init_panel,
};
static const struct amba_id clcdfb_id_table[] = {
{
.id = 0x00041110,
.mask = 0x000ffffe,
.data = &vendor_arm,
},
/* ST Electronics Nomadik variant */
{
.id = 0x00180110,
.mask = 0x00fffffe,
.data = &vendor_nomadik,
},
{ 0, 0 },
};
......
......@@ -47,7 +47,6 @@
#define ATAFB_EXT
#define ATAFB_FALCON
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
......@@ -55,6 +54,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/setup.h>
#include <linux/uaccess.h>
......@@ -3073,28 +3073,22 @@ int __init atafb_setup(char *options)
return 0;
}
int __init atafb_init(void)
static int __init atafb_probe(struct platform_device *pdev)
{
int pad, detected_mode, error;
unsigned int defmode = 0;
unsigned long mem_req;
#ifndef MODULE
char *option = NULL;
if (fb_get_options("atafb", &option))
return -ENODEV;
atafb_setup(option);
#endif
printk("atafb_init: start\n");
if (!MACH_IS_ATARI)
return -ENODEV;
dev_dbg(&pdev->dev, "%s: start\n", __func__);
do {
#ifdef ATAFB_EXT
if (external_addr) {
printk("atafb_init: initializing external hw\n");
dev_dbg(&pdev->dev, "initializing external hw\n");
fbhw = &ext_switch;
atafb_ops.fb_setcolreg = &ext_setcolreg;
defmode = DEFMODE_EXT;
......@@ -3103,7 +3097,7 @@ int __init atafb_init(void)
#endif
#ifdef ATAFB_TT
if (ATARIHW_PRESENT(TT_SHIFTER)) {
printk("atafb_init: initializing TT hw\n");
dev_dbg(&pdev->dev, "initializing TT hw\n");
fbhw = &tt_switch;
atafb_ops.fb_setcolreg = &tt_setcolreg;
defmode = DEFMODE_TT;
......@@ -3112,7 +3106,7 @@ int __init atafb_init(void)
#endif
#ifdef ATAFB_FALCON
if (ATARIHW_PRESENT(VIDEL_SHIFTER)) {
printk("atafb_init: initializing Falcon hw\n");
dev_dbg(&pdev->dev, "initializing Falcon hw\n");
fbhw = &falcon_switch;
atafb_ops.fb_setcolreg = &falcon_setcolreg;
error = request_irq(IRQ_AUTO_4, falcon_vbl_switcher, 0,
......@@ -3127,7 +3121,7 @@ int __init atafb_init(void)
#ifdef ATAFB_STE
if (ATARIHW_PRESENT(STND_SHIFTER) ||
ATARIHW_PRESENT(EXTD_SHIFTER)) {
printk("atafb_init: initializing ST/E hw\n");
dev_dbg(&pdev->dev, "initializing ST/E hw\n");
fbhw = &st_switch;
atafb_ops.fb_setcolreg = &stste_setcolreg;
defmode = DEFMODE_STE;
......@@ -3135,7 +3129,8 @@ int __init atafb_init(void)
}
fbhw = &st_switch;
atafb_ops.fb_setcolreg = &stste_setcolreg;
printk("Cannot determine video hardware; defaulting to ST(e)\n");
dev_warn(&pdev->dev,
"Cannot determine video hardware; defaulting to ST(e)\n");
#else /* ATAFB_STE */
/* no default driver included */
/* Nobody will ever see this message :-) */
......@@ -3175,8 +3170,8 @@ int __init atafb_init(void)
kernel_set_cachemode(screen_base, screen_len,
IOMAP_WRITETHROUGH);
}
printk("atafb: screen_base %p phys_screen_base %lx screen_len %d\n",
screen_base, phys_screen_base, screen_len);
dev_info(&pdev->dev, "phys_screen_base %lx screen_len %d\n",
phys_screen_base, screen_len);
#ifdef ATAFB_EXT
} else {
/* Map the video memory (physical address given) to somewhere
......@@ -3223,12 +3218,12 @@ int __init atafb_init(void)
fb_alloc_cmap(&(fb_info.cmap), 1 << fb_info.var.bits_per_pixel, 0);
printk("Determined %dx%d, depth %d\n",
fb_info.var.xres, fb_info.var.yres, fb_info.var.bits_per_pixel);
dev_info(&pdev->dev, "Determined %dx%d, depth %d\n", fb_info.var.xres,
fb_info.var.yres, fb_info.var.bits_per_pixel);
if ((fb_info.var.xres != fb_info.var.xres_virtual) ||
(fb_info.var.yres != fb_info.var.yres_virtual))
printk(" virtual %dx%d\n", fb_info.var.xres_virtual,
fb_info.var.yres_virtual);
dev_info(&pdev->dev, " virtual %dx%d\n",
fb_info.var.xres_virtual, fb_info.var.yres_virtual);
if (register_framebuffer(&fb_info) < 0) {
#ifdef ATAFB_EXT
......@@ -3251,14 +3246,32 @@ int __init atafb_init(void)
return 0;
}
module_init(atafb_init);
static void atafb_shutdown(struct platform_device *pdev)
{
/* Unblank before kexec */
if (fbhw->blank)
fbhw->blank(0);
}
#ifdef MODULE
MODULE_LICENSE("GPL");
static struct platform_driver atafb_driver = {
.shutdown = atafb_shutdown,
.driver = {
.name = "atafb",
},
};
int cleanup_module(void)
static int __init atafb_init(void)
{
unregister_framebuffer(&fb_info);
return atafb_deinit();
struct platform_device *pdev;
if (!MACH_IS_ATARI)
return -ENODEV;
pdev = platform_device_register_simple("atafb", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
return platform_driver_probe(&atafb_driver, atafb_probe);
}
#endif /* MODULE */
device_initcall(atafb_init);
......@@ -10,7 +10,6 @@
* more details.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fb.h>
......@@ -269,25 +268,3 @@ void atafb_iplan2p2_linefill(struct fb_info *info, u_long next_line,
if (width)
fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{
}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(atafb_iplan2p2_copyarea);
EXPORT_SYMBOL(atafb_iplan2p2_fillrect);
EXPORT_SYMBOL(atafb_iplan2p2_linefill);
......@@ -10,7 +10,6 @@
* more details.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fb.h>
......@@ -284,25 +283,3 @@ void atafb_iplan2p4_linefill(struct fb_info *info, u_long next_line,
if (width)
fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{
}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(atafb_iplan2p4_copyarea);
EXPORT_SYMBOL(atafb_iplan2p4_fillrect);
EXPORT_SYMBOL(atafb_iplan2p4_linefill);
......@@ -10,7 +10,6 @@
* more details.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fb.h>
......@@ -321,25 +320,3 @@ void atafb_iplan2p8_linefill(struct fb_info *info, u_long next_line,
if (width)
fill8_2col((u8 *)dest, fgcolor, bgcolor, *data);
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{
}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(atafb_iplan2p8_copyarea);
EXPORT_SYMBOL(atafb_iplan2p8_fillrect);
EXPORT_SYMBOL(atafb_iplan2p8_linefill);
......@@ -9,7 +9,6 @@
* more details.
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/fb.h>
......@@ -88,25 +87,3 @@ void atafb_mfb_linefill(struct fb_info *info, u_long next_line,
*dest++ = *data++;
}
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{
}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(atafb_mfb_copyarea);
EXPORT_SYMBOL(atafb_mfb_fillrect);
EXPORT_SYMBOL(atafb_mfb_linefill);
/*
* Driver for AT91/AT32 LCD Controller
* Driver for AT91 LCD Controller
*
* Copyright (C) 2007 Atmel Corporation
*
......@@ -99,86 +99,6 @@ static struct atmel_lcdfb_config at91sam9rl_config = {
.have_intensity_bit = true,
};
static struct atmel_lcdfb_config at32ap_config = {
.have_hozval = true,
};
static const struct platform_device_id atmel_lcdfb_devtypes[] = {
{
.name = "at91sam9261-lcdfb",
.driver_data = (unsigned long)&at91sam9261_config,
}, {
.name = "at91sam9263-lcdfb",
.driver_data = (unsigned long)&at91sam9263_config,
}, {
.name = "at91sam9g10-lcdfb",
.driver_data = (unsigned long)&at91sam9g10_config,
}, {
.name = "at91sam9g45-lcdfb",
.driver_data = (unsigned long)&at91sam9g45_config,
}, {
.name = "at91sam9g45es-lcdfb",
.driver_data = (unsigned long)&at91sam9g45es_config,
}, {
.name = "at91sam9rl-lcdfb",
.driver_data = (unsigned long)&at91sam9rl_config,
}, {
.name = "at32ap-lcdfb",
.driver_data = (unsigned long)&at32ap_config,
}, {
/* terminator */
}
};
MODULE_DEVICE_TABLE(platform, atmel_lcdfb_devtypes);
static struct atmel_lcdfb_config *
atmel_lcdfb_get_config(struct platform_device *pdev)
{
unsigned long data;
data = platform_get_device_id(pdev)->driver_data;
return (struct atmel_lcdfb_config *)data;
}
#if defined(CONFIG_ARCH_AT91)
#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
| FBINFO_PARTIAL_PAN_OK \
| FBINFO_HWACCEL_YPAN)
static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
struct fb_var_screeninfo *var,
struct fb_info *info)
{
}
#elif defined(CONFIG_AVR32)
#define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \
| FBINFO_PARTIAL_PAN_OK \
| FBINFO_HWACCEL_XPAN \
| FBINFO_HWACCEL_YPAN)
static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
struct fb_var_screeninfo *var,
struct fb_info *info)
{
u32 dma2dcfg;
u32 pixeloff;
pixeloff = (var->xoffset * info->var.bits_per_pixel) & 0x1f;
dma2dcfg = (info->var.xres_virtual - info->var.xres)
* info->var.bits_per_pixel / 8;
dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
/* Update configuration */
lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
| ATMEL_LCDC_DMAUPDT);
}
#endif
static u32 contrast_ctr = ATMEL_LCDC_PS_DIV8
| ATMEL_LCDC_POL_POSITIVE
| ATMEL_LCDC_ENA_PWMENABLE;
......@@ -404,8 +324,6 @@ static void atmel_lcdfb_update_dma(struct fb_info *info,
/* Set framebuffer DMA base address and pixel offset */
lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
atmel_lcdfb_update_dma2d(sinfo, var, info);
}
static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
......@@ -978,7 +896,6 @@ static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
clk_disable_unprepare(sinfo->lcdc_clk);
}
#ifdef CONFIG_OF
static const struct of_device_id atmel_lcdfb_dt_ids[] = {
{ .compatible = "atmel,at91sam9261-lcdc" , .data = &at91sam9261_config, },
{ .compatible = "atmel,at91sam9263-lcdc" , .data = &at91sam9263_config, },
......@@ -986,7 +903,6 @@ static const struct of_device_id atmel_lcdfb_dt_ids[] = {
{ .compatible = "atmel,at91sam9g45-lcdc" , .data = &at91sam9g45_config, },
{ .compatible = "atmel,at91sam9g45es-lcdc" , .data = &at91sam9g45es_config, },
{ .compatible = "atmel,at91sam9rl-lcdc" , .data = &at91sam9rl_config, },
{ .compatible = "atmel,at32ap-lcdc" , .data = &at32ap_config, },
{ /* sentinel */ }
};
......@@ -1122,19 +1038,12 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
of_node_put(display_np);
return ret;
}
#else
static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
{
return 0;
}
#endif
static int __init atmel_lcdfb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct fb_info *info;
struct atmel_lcdfb_info *sinfo;
struct atmel_lcdfb_pdata *pdata = NULL;
struct resource *regs = NULL;
struct resource *map = NULL;
struct fb_modelist *modelist;
......@@ -1159,21 +1068,6 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
ret = atmel_lcdfb_of_init(sinfo);
if (ret)
goto free_info;
} else if (dev_get_platdata(dev)) {
struct fb_monspecs *monspecs;
int i;
pdata = dev_get_platdata(dev);
monspecs = pdata->default_monspecs;
sinfo->pdata = *pdata;
for (i = 0; i < monspecs->modedb_len; i++)
fb_add_videomode(&monspecs->modedb[i], &info->modelist);
sinfo->config = atmel_lcdfb_get_config(pdev);
info->var.bits_per_pixel = pdata->default_bpp ? pdata->default_bpp : 16;
memcpy(&info->monspecs, pdata->default_monspecs, sizeof(info->monspecs));
} else {
dev_err(dev, "cannot get default configuration\n");
goto free_info;
......@@ -1186,7 +1080,8 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
if (IS_ERR(sinfo->reg_lcd))
sinfo->reg_lcd = NULL;
info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
FBINFO_HWACCEL_YPAN;
info->pseudo_palette = sinfo->pseudo_palette;
info->fbops = &atmel_lcdfb_ops;
......@@ -1357,12 +1252,10 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct fb_info *info = dev_get_drvdata(dev);
struct atmel_lcdfb_info *sinfo;
struct atmel_lcdfb_pdata *pdata;
if (!info || !info->par)
return 0;
sinfo = info->par;
pdata = &sinfo->pdata;
cancel_work_sync(&sinfo->task);
exit_backlight(sinfo);
......@@ -1435,7 +1328,6 @@ static struct platform_driver atmel_lcdfb_driver = {
.remove = __exit_p(atmel_lcdfb_remove),
.suspend = atmel_lcdfb_suspend,
.resume = atmel_lcdfb_resume,
.id_table = atmel_lcdfb_devtypes,
.driver = {
.name = "atmel_lcdfb",
.of_match_table = of_match_ptr(atmel_lcdfb_dt_ids),
......@@ -1444,6 +1336,6 @@ static struct platform_driver atmel_lcdfb_driver = {
module_platform_driver_probe(atmel_lcdfb_driver, atmel_lcdfb_probe);
MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
MODULE_DESCRIPTION("AT91 LCD Controller framebuffer driver");
MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@atmel.com>");
MODULE_LICENSE("GPL");
......@@ -94,6 +94,8 @@ int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
int size = len * sizeof(u16);
int ret = -ENOMEM;
flags |= __GFP_NOWARN;
if (cmap->len != len) {
fb_dealloc_cmap(cmap);
if (!len)
......
......@@ -1069,7 +1069,7 @@ static void fbcon_init(struct vc_data *vc, int init)
cap = info->flags;
if (console_loglevel <= CONSOLE_LOGLEVEL_QUIET)
if (logo_shown < 0 && console_loglevel <= CONSOLE_LOGLEVEL_QUIET)
logo_shown = FBCON_LOGO_DONTSHOW;
if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
......
......@@ -1882,14 +1882,35 @@ int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, int res_id, const
{
struct apertures_struct *ap;
bool primary = false;
int err;
int err, idx, bar;
bool res_id_found = false;
for (idx = 0, bar = 0; bar < PCI_ROM_RESOURCE; bar++) {
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
continue;
idx++;
}
ap = alloc_apertures(1);
ap = alloc_apertures(idx);
if (!ap)
return -ENOMEM;
ap->ranges[0].base = pci_resource_start(pdev, res_id);
ap->ranges[0].size = pci_resource_len(pdev, res_id);
for (idx = 0, bar = 0; bar < PCI_ROM_RESOURCE; bar++) {
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
continue;
ap->ranges[idx].base = pci_resource_start(pdev, bar);
ap->ranges[idx].size = pci_resource_len(pdev, bar);
pci_info(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
(unsigned long)pci_resource_start(pdev, bar),
(unsigned long)pci_resource_end(pdev, bar));
idx++;
if (res_id == bar)
res_id_found = true;
}
if (!res_id_found)
pci_warn(pdev, "%s: passed res_id (%d) is not a memory bar\n",
__func__, res_id);
#ifdef CONFIG_X86
primary = pdev->resource[PCI_ROM_RESOURCE].flags &
IORESOURCE_ROM_SHADOW;
......
......@@ -935,6 +935,9 @@ void fb_var_to_videomode(struct fb_videomode *mode,
if (var->vmode & FB_VMODE_DOUBLE)
vtotal *= 2;
if (!htotal || !vtotal)
return;
hfreq = pixclock/htotal;
mode->refresh = hfreq/vtotal;
}
......
......@@ -285,6 +285,8 @@ static int hga_card_detect(void)
hga_vram_len = 0x08000;
hga_vram = ioremap(0xb0000, hga_vram_len);
if (!hga_vram)
goto error;
if (request_region(0x3b0, 12, "hgafb"))
release_io_ports = 1;
......
......@@ -1515,6 +1515,11 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
info->fix.smem_start = addr;
info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
0x400000 : 0x800000);
if (!info->screen_base) {
release_mem_region(addr, size);
framebuffer_release(info);
return -ENOMEM;
}
info->fix.mmio_start = addr + 0x800000;
par->dc_regs = ioremap(addr + 0x800000, 0x1000);
par->cmap_regs_phys = addr + 0x840000;
......
......@@ -120,10 +120,7 @@ struct jet_cmap_regs {
#define PIXEL_TO_MM(a) (((a)*10)/28) /* width in mm at 72 dpi */
static struct fb_var_screeninfo macfb_defined = {
.bits_per_pixel = 8,
.activate = FB_ACTIVATE_NOW,
.width = -1,
.height = -1,
.right_margin = 32,
.upper_margin = 16,
.lower_margin = 4,
......@@ -139,7 +136,6 @@ static struct fb_fix_screeninfo macfb_fix = {
static void *slot_addr;
static struct fb_info fb_info;
static u32 pseudo_palette[16];
static int inverse;
static int vidtest;
/*
......@@ -152,7 +148,7 @@ static int dafb_setpalette(unsigned int regno, unsigned int red,
unsigned int green, unsigned int blue,
struct fb_info *info)
{
static int lastreg = -1;
static int lastreg = -2;
unsigned long flags;
local_irq_save(flags);
......@@ -201,9 +197,6 @@ static int v8_brazil_setpalette(unsigned int regno, unsigned int red,
unsigned int bpp = info->var.bits_per_pixel;
unsigned long flags;
if (bpp > 8)
return 1; /* failsafe */
local_irq_save(flags);
/* On these chips, the CLUT register numbers are spread out
......@@ -234,9 +227,6 @@ static int rbv_setpalette(unsigned int regno, unsigned int red,
{
unsigned long flags;
if (info->var.bits_per_pixel > 8)
return 1; /* failsafe */
local_irq_save(flags);
/* From the VideoToolbox driver. Seems to be saying that
......@@ -353,9 +343,6 @@ static int civic_setpalette(unsigned int regno, unsigned int red,
unsigned long flags;
int clut_status;
if (info->var.bits_per_pixel > 8)
return 1; /* failsafe */
local_irq_save(flags);
/* Set the register address */
......@@ -532,7 +519,7 @@ static void __init macfb_setup(char *options)
continue;
if (!strcmp(this_opt, "inverse"))
inverse = 1;
fb_invert_cmaps();
else
if (!strcmp(this_opt, "vidtest"))
vidtest = 1; /* enable experimental CLUT code */
......@@ -688,17 +675,14 @@ static int __init macfb_init(void)
case NUBUS_DRHW_APPLE_MDC:
strcpy(macfb_fix.id, "Mac Disp. Card");
macfb_setpalette = mdc_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
case NUBUS_DRHW_APPLE_TFB:
strcpy(macfb_fix.id, "Toby");
macfb_setpalette = toby_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
case NUBUS_DRHW_APPLE_JET:
strcpy(macfb_fix.id, "Jet");
macfb_setpalette = jet_setpalette;
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
strcpy(macfb_fix.id, "Generic NuBus");
......@@ -731,7 +715,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
......@@ -741,7 +724,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
......@@ -755,7 +737,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
......@@ -772,7 +753,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "Sonora");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
......@@ -785,7 +765,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "RBV");
macfb_setpalette = rbv_setpalette;
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
/*
......@@ -796,7 +775,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "Civic");
macfb_setpalette = civic_setpalette;
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
......@@ -810,7 +788,6 @@ static int __init macfb_init(void)
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
}
break;
......@@ -823,7 +800,6 @@ static int __init macfb_init(void)
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs =
ioremap(DAC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
}
break;
......@@ -892,7 +868,6 @@ static int __init macfb_init(void)
strcpy(macfb_fix.id, "CSC");
macfb_setpalette = csc_setpalette;
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
macfb_defined.activate = FB_ACTIVATE_NOW;
break;
default:
......
......@@ -181,6 +181,7 @@ struct mxsfb_info {
const struct mxsfb_devdata *devdata;
u32 sync;
struct regulator *reg_lcd;
int pre_init;
};
#define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
......@@ -419,6 +420,12 @@ static int mxsfb_set_par(struct fb_info *fb_info)
fb_info->fix.line_length = line_size;
if (host->pre_init) {
mxsfb_enable_controller(fb_info);
host->pre_init = 0;
return 0;
}
/*
* It seems, you can't re-program the controller if it is still running.
* This may lead into shifted pictures (FIFO issue?).
......@@ -623,7 +630,6 @@ static int mxsfb_restore_mode(struct fb_info *fb_info,
struct fb_videomode *vmode)
{
struct mxsfb_info *host = fb_info->par;
unsigned line_count;
unsigned period;
unsigned long pa, fbsize;
int bits_per_pixel, ofs, ret = 0;
......@@ -710,7 +716,6 @@ static int mxsfb_restore_mode(struct fb_info *fb_info,
writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf);
}
line_count = fb_info->fix.smem_len / fb_info->fix.line_length;
fb_info->fix.ypanstep = 1;
clk_prepare_enable(host->clk);
......@@ -931,6 +936,10 @@ static int mxsfb_probe(struct platform_device *pdev)
if (IS_ERR(host->reg_lcd))
host->reg_lcd = NULL;
#if defined(CONFIG_FB_PRE_INIT_FB)
host->pre_init = 1;
#endif
fb_info->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32),
GFP_KERNEL);
if (!fb_info->pseudo_palette) {
......@@ -963,6 +972,7 @@ static int mxsfb_probe(struct platform_device *pdev)
mxsfb_enable_controller(fb_info);
}
host->pre_init = 0;
dev_info(&pdev->dev, "initialized\n");
return 0;
......
......@@ -455,7 +455,7 @@ static int nuc900fb_cpufreq_transition(struct notifier_block *nb,
struct fb_info *fbinfo;
long delta_f;
info = container_of(nb, struct nuc900fb_info, freq_transition);
fbinfo = platform_get_drvdata(to_platform_device(info->dev));
fbinfo = dev_get_drvdata(info->dev);
delta_f = info->clk_rate - clk_get_rate(info->clk);
......
......@@ -57,5 +57,3 @@ config FB_OMAP_DMA_TUNE
If you have such a system and want to use rotation
answer yes. Answer no if you have a dedicated video
memory, or don't use any of the accelerated features.
......@@ -111,6 +111,8 @@ static void __init omapdss_omapify_node(struct device_node *node)
new_len = prop->length + strlen(prefix) * num_strs;
new_compat = kmalloc(new_len, GFP_KERNEL);
if (!new_compat)
return;
omapdss_prefix_strcpy(new_compat, new_len, prop->value, prop->length);
......@@ -193,8 +195,10 @@ static int __init omapdss_boot_init(void)
dss = of_find_matching_node(NULL, omapdss_of_match);
if (dss == NULL || !of_device_is_available(dss))
if (dss == NULL || !of_device_is_available(dss)) {
of_node_put(dss);
return 0;
}
omapdss_walk_device(dss, true);
......
......@@ -1071,7 +1071,6 @@ static struct pvr2_board {
static int __init pvr2fb_init(void)
{
int i, ret = -ENODEV;
int size;
#ifndef MODULE
char *option = NULL;
......@@ -1080,7 +1079,6 @@ static int __init pvr2fb_init(void)
return -ENODEV;
pvr2fb_setup(option);
#endif
size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
fb_info = framebuffer_alloc(sizeof(struct pvr2fb_par), NULL);
......
......@@ -777,7 +777,7 @@ static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
long delta_f;
info = container_of(nb, struct s3c2410fb_info, freq_transition);
fbinfo = platform_get_drvdata(to_platform_device(info->dev));
fbinfo = dev_get_drvdata(info->dev);
/* work out change, <0 for speed-up */
delta_f = info->clk_rate - clk_get_rate(info->clk);
......
......@@ -16,14 +16,10 @@
#define FB_ACCEL_SMI_LYNX 88
#define SCREEN_X_RES 1024
#define SCREEN_Y_RES 600
#define SCREEN_Y_RES_PC 768
#define SCREEN_Y_RES_NETBOOK 600
#define SCREEN_BPP 16
/*Assume SM712 graphics chip has 4MB VRAM */
#define SM712_VIDEOMEMORYSIZE 0x00400000
/*Assume SM722 graphics chip has 8MB VRAM */
#define SM722_VIDEOMEMORYSIZE 0x00800000
#define dac_reg (0x3c8)
#define dac_val (0x3c9)
......
......@@ -530,6 +530,65 @@ static const struct modeinit vgamode[] = {
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
},
},
{ /* 1024 x 768 16Bpp 60Hz */
1024, 768, 16, 60,
/* Init_MISC */
0xEB,
{ /* Init_SR0_SR4 */
0x03, 0x01, 0x0F, 0x03, 0x0E,
},
{ /* Init_SR10_SR24 */
0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C,
0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC4, 0x30, 0x02, 0x01, 0x01,
},
{ /* Init_SR30_SR75 */
0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A,
0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF,
0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC,
0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A,
0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03,
0x0F, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A,
0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00,
0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02,
0x04, 0x45, 0x30, 0x30, 0x40, 0x20,
},
{ /* Init_SR80_SR93 */
0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A,
0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A,
0x00, 0x00, 0x00, 0x00,
},
{ /* Init_SRA0_SRAF */
0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED,
0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF,
},
{ /* Init_GR00_GR08 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
0xFF,
},
{ /* Init_AR00_AR14 */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x41, 0x00, 0x0F, 0x00, 0x00,
},
{ /* Init_CR00_CR18 */
0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5,
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3,
0xFF,
},
{ /* Init_CR30_CR4D */
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20,
0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF,
0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00,
0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF,
},
{ /* Init_CR90_CRA7 */
0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26,
0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03,
},
},
{ /* mode#5: 1024 x 768 24Bpp 60Hz */
1024, 768, 24, 60,
/* Init_MISC */
......@@ -827,67 +886,80 @@ static inline unsigned int chan_to_field(unsigned int chan,
static int smtc_blank(int blank_mode, struct fb_info *info)
{
struct smtcfb_info *sfb = info->par;
/* clear DPMS setting */
switch (blank_mode) {
case FB_BLANK_UNBLANK:
/* Screen On: HSync: On, VSync : On */
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
switch (sfb->chip_id) {
case 0x710:
case 0x712:
smtc_seqw(0x6a, 0x16);
smtc_seqw(0x6b, 0x02);
break;
case 0x720:
smtc_seqw(0x6a, 0x0d);
smtc_seqw(0x6b, 0x02);
break;
}
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77));
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03));
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
break;
case FB_BLANK_NORMAL:
/* Screen Off: HSync: On, VSync : On Soft blank */
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20)));
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
smtc_seqw(0x6a, 0x16);
smtc_seqw(0x6b, 0x02);
smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30)));
smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0)));
smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
break;
case FB_BLANK_VSYNC_SUSPEND:
/* Screen On: HSync: On, VSync : Off */
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20));
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
break;
case FB_BLANK_HSYNC_SUSPEND:
/* Screen On: HSync: Off, VSync : On */
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
break;
case FB_BLANK_POWERDOWN:
/* Screen On: HSync: Off, VSync : Off */
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88));
smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0)));
smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30));
smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8));
smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01)));
smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00));
smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80));
smtc_seqw(0x6a, 0x0c);
smtc_seqw(0x6b, 0x02);
break;
default:
return -EINVAL;
......@@ -1145,8 +1217,10 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb)
/* init SEQ register SR30 - SR75 */
for (i = 0; i < SIZE_SR30_SR75; i++)
if ((i + 0x30) != 0x62 && (i + 0x30) != 0x6a &&
(i + 0x30) != 0x6b)
if ((i + 0x30) != 0x30 && (i + 0x30) != 0x62 &&
(i + 0x30) != 0x6a && (i + 0x30) != 0x6b &&
(i + 0x30) != 0x70 && (i + 0x30) != 0x71 &&
(i + 0x30) != 0x74 && (i + 0x30) != 0x75)
smtc_seqw(i + 0x30,
vgamode[j].init_sr30_sr75[i]);
......@@ -1171,8 +1245,12 @@ static void sm7xx_set_timing(struct smtcfb_info *sfb)
smtc_crtcw(i, vgamode[j].init_cr00_cr18[i]);
/* init CRTC register CR30 - CR4D */
for (i = 0; i < SIZE_CR30_CR4D; i++)
for (i = 0; i < SIZE_CR30_CR4D; i++) {
if ((i + 0x30) >= 0x3B && (i + 0x30) <= 0x3F)
/* side-effect, don't write to CR3B-CR3F */
continue;
smtc_crtcw(i + 0x30, vgamode[j].init_cr30_cr4d[i]);
}
/* init CRTC register CR90 - CRA7 */
for (i = 0; i < SIZE_CR90_CRA7; i++)
......@@ -1323,6 +1401,11 @@ static int smtc_map_smem(struct smtcfb_info *sfb,
{
sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
if (sfb->chip_id == 0x720)
/* on SM720, the framebuffer starts at the 1 MB offset */
sfb->fb->fix.smem_start += 0x00200000;
/* XXX: is it safe for SM720 on Big-Endian? */
if (sfb->fb->var.bits_per_pixel == 32)
sfb->fb->fix.smem_start += big_addr;
......@@ -1360,12 +1443,82 @@ static inline void sm7xx_init_hw(void)
outb_p(0x11, 0x3c5);
}
static u_long sm7xx_vram_probe(struct smtcfb_info *sfb)
{
u8 vram;
switch (sfb->chip_id) {
case 0x710:
case 0x712:
/*
* Assume SM712 graphics chip has 4MB VRAM.
*
* FIXME: SM712 can have 2MB VRAM, which is used on earlier
* laptops, such as IBM Thinkpad 240X. This driver would
* probably crash on those machines. If anyone gets one of
* those and is willing to help, run "git blame" and send me
* an E-mail.
*/
return 0x00400000;
case 0x720:
outb_p(0x76, 0x3c4);
vram = inb_p(0x3c5) >> 6;
if (vram == 0x00)
return 0x00800000; /* 8 MB */
else if (vram == 0x01)
return 0x01000000; /* 16 MB */
else if (vram == 0x02)
return 0x00400000; /* illegal, fallback to 4 MB */
else if (vram == 0x03)
return 0x00400000; /* 4 MB */
}
return 0; /* unknown hardware */
}
static void sm7xx_resolution_probe(struct smtcfb_info *sfb)
{
/* get mode parameter from smtc_scr_info */
if (smtc_scr_info.lfb_width != 0) {
sfb->fb->var.xres = smtc_scr_info.lfb_width;
sfb->fb->var.yres = smtc_scr_info.lfb_height;
sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
goto final;
}
/*
* No parameter, default resolution is 1024x768-16.
*
* FIXME: earlier laptops, such as IBM Thinkpad 240X, has a 800x600
* panel, also see the comments about Thinkpad 240X above.
*/
sfb->fb->var.xres = SCREEN_X_RES;
sfb->fb->var.yres = SCREEN_Y_RES_PC;
sfb->fb->var.bits_per_pixel = SCREEN_BPP;
#ifdef CONFIG_MIPS
/*
* Loongson MIPS netbooks use 1024x600 LCD panels, which is the original
* target platform of this driver, but nearly all old x86 laptops have
* 1024x768. Lighting 768 panels using 600's timings would partially
* garble the display, so we don't want that. But it's not possible to
* distinguish them reliably.
*
* So we change the default to 768, but keep 600 as-is on MIPS.
*/
sfb->fb->var.yres = SCREEN_Y_RES_NETBOOK;
#endif
final:
big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
}
static int smtcfb_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct smtcfb_info *sfb;
struct fb_info *info;
u_long smem_size = 0x00800000; /* default 8MB */
u_long smem_size;
int err;
unsigned long mmio_base;
......@@ -1405,29 +1558,19 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
sm7xx_init_hw();
/* get mode parameter from smtc_scr_info */
if (smtc_scr_info.lfb_width != 0) {
sfb->fb->var.xres = smtc_scr_info.lfb_width;
sfb->fb->var.yres = smtc_scr_info.lfb_height;
sfb->fb->var.bits_per_pixel = smtc_scr_info.lfb_depth;
} else {
/* default resolution 1024x600 16bit mode */
sfb->fb->var.xres = SCREEN_X_RES;
sfb->fb->var.yres = SCREEN_Y_RES;
sfb->fb->var.bits_per_pixel = SCREEN_BPP;
}
big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
/* Map address and memory detection */
mmio_base = pci_resource_start(pdev, 0);
pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
smem_size = sm7xx_vram_probe(sfb);
dev_info(&pdev->dev, "%lu MiB of VRAM detected.\n",
smem_size / 1048576);
switch (sfb->chip_id) {
case 0x710:
case 0x712:
sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
sfb->fb->fix.mmio_len = 0x00400000;
smem_size = SM712_VIDEOMEMORYSIZE;
sfb->lfb = ioremap(mmio_base, mmio_addr);
if (!sfb->lfb) {
dev_err(&pdev->dev,
......@@ -1459,8 +1602,7 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
case 0x720:
sfb->fb->fix.mmio_start = mmio_base;
sfb->fb->fix.mmio_len = 0x00200000;
smem_size = SM722_VIDEOMEMORYSIZE;
sfb->dp_regs = ioremap(mmio_base, 0x00a00000);
sfb->dp_regs = ioremap(mmio_base, 0x00200000 + smem_size);
sfb->lfb = sfb->dp_regs + 0x00200000;
sfb->mmio = (smtc_regbaseaddress =
sfb->dp_regs + 0x000c0000);
......@@ -1477,6 +1619,9 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
goto failed_fb;
}
/* probe and decide resolution */
sm7xx_resolution_probe(sfb);
/* can support 32 bpp */
if (sfb->fb->var.bits_per_pixel == 15)
sfb->fb->var.bits_per_pixel = 16;
......@@ -1487,7 +1632,11 @@ static int smtcfb_pci_probe(struct pci_dev *pdev,
if (err)
goto failed;
smtcfb_setmode(sfb);
/*
* The screen would be temporarily garbled when sm712fb takes over
* vesafb or VGA text mode. Zero the framebuffer.
*/
memset_io(sfb->lfb, 0, sfb->fb->fix.smem_len);
err = register_framebuffer(info);
if (err < 0)
......
......@@ -594,8 +594,7 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
return 0;
}
static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
int width, int height, char *data)
static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y, int width, int height)
{
int i, ret;
char *cmd;
......@@ -607,21 +606,29 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
start_cycles = get_cycles();
mutex_lock(&dlfb->render_mutex);
aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
x = aligned_x;
if ((width <= 0) ||
(x + width > dlfb->info->var.xres) ||
(y + height > dlfb->info->var.yres))
return -EINVAL;
(y + height > dlfb->info->var.yres)) {
ret = -EINVAL;
goto unlock_ret;
}
if (!atomic_read(&dlfb->usb_active))
return 0;
if (!atomic_read(&dlfb->usb_active)) {
ret = 0;
goto unlock_ret;
}
urb = dlfb_get_urb(dlfb);
if (!urb)
return 0;
if (!urb) {
ret = 0;
goto unlock_ret;
}
cmd = urb->transfer_buffer;
for (i = y; i < y + height ; i++) {
......@@ -641,7 +648,7 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
*cmd++ = 0xAF;
/* Send partial buffer remaining before exiting */
len = cmd - (char *) urb->transfer_buffer;
ret = dlfb_submit_urb(dlfb, urb, len);
dlfb_submit_urb(dlfb, urb, len);
bytes_sent += len;
} else
dlfb_urb_completion(urb);
......@@ -655,7 +662,55 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
>> 10)), /* Kcycles */
&dlfb->cpu_kcycles_used);
return 0;
ret = 0;
unlock_ret:
mutex_unlock(&dlfb->render_mutex);
return ret;
}
static void dlfb_init_damage(struct dlfb_data *dlfb)
{
dlfb->damage_x = INT_MAX;
dlfb->damage_x2 = 0;
dlfb->damage_y = INT_MAX;
dlfb->damage_y2 = 0;
}
static void dlfb_damage_work(struct work_struct *w)
{
struct dlfb_data *dlfb = container_of(w, struct dlfb_data, damage_work);
int x, x2, y, y2;
spin_lock_irq(&dlfb->damage_lock);
x = dlfb->damage_x;
x2 = dlfb->damage_x2;
y = dlfb->damage_y;
y2 = dlfb->damage_y2;
dlfb_init_damage(dlfb);
spin_unlock_irq(&dlfb->damage_lock);
if (x < x2 && y < y2)
dlfb_handle_damage(dlfb, x, y, x2 - x, y2 - y);
}
static void dlfb_offload_damage(struct dlfb_data *dlfb, int x, int y, int width, int height)
{
unsigned long flags;
int x2 = x + width;
int y2 = y + height;
if (x >= x2 || y >= y2)
return;
spin_lock_irqsave(&dlfb->damage_lock, flags);
dlfb->damage_x = min(x, dlfb->damage_x);
dlfb->damage_x2 = max(x2, dlfb->damage_x2);
dlfb->damage_y = min(y, dlfb->damage_y);
dlfb->damage_y2 = max(y2, dlfb->damage_y2);
spin_unlock_irqrestore(&dlfb->damage_lock, flags);
schedule_work(&dlfb->damage_work);
}
/*
......@@ -679,7 +734,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf,
(u32)info->var.yres);
dlfb_handle_damage(dlfb, 0, start, info->var.xres,
lines, info->screen_base);
lines);
}
return result;
......@@ -694,8 +749,8 @@ static void dlfb_ops_copyarea(struct fb_info *info,
sys_copyarea(info, area);
dlfb_handle_damage(dlfb, area->dx, area->dy,
area->width, area->height, info->screen_base);
dlfb_offload_damage(dlfb, area->dx, area->dy,
area->width, area->height);
}
static void dlfb_ops_imageblit(struct fb_info *info,
......@@ -705,8 +760,8 @@ static void dlfb_ops_imageblit(struct fb_info *info,
sys_imageblit(info, image);
dlfb_handle_damage(dlfb, image->dx, image->dy,
image->width, image->height, info->screen_base);
dlfb_offload_damage(dlfb, image->dx, image->dy,
image->width, image->height);
}
static void dlfb_ops_fillrect(struct fb_info *info,
......@@ -716,8 +771,8 @@ static void dlfb_ops_fillrect(struct fb_info *info,
sys_fillrect(info, rect);
dlfb_handle_damage(dlfb, rect->dx, rect->dy, rect->width,
rect->height, info->screen_base);
dlfb_offload_damage(dlfb, rect->dx, rect->dy, rect->width,
rect->height);
}
/*
......@@ -739,17 +794,19 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
int bytes_identical = 0;
int bytes_rendered = 0;
mutex_lock(&dlfb->render_mutex);
if (!fb_defio)
return;
goto unlock_ret;
if (!atomic_read(&dlfb->usb_active))
return;
goto unlock_ret;
start_cycles = get_cycles();
urb = dlfb_get_urb(dlfb);
if (!urb)
return;
goto unlock_ret;
cmd = urb->transfer_buffer;
......@@ -782,6 +839,8 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
atomic_add(((unsigned int) ((end_cycles - start_cycles)
>> 10)), /* Kcycles */
&dlfb->cpu_kcycles_used);
unlock_ret:
mutex_unlock(&dlfb->render_mutex);
}
static int dlfb_get_edid(struct dlfb_data *dlfb, char *edid, int len)
......@@ -859,8 +918,7 @@ static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
if (area.y > info->var.yres)
area.y = info->var.yres;
dlfb_handle_damage(dlfb, area.x, area.y, area.w, area.h,
info->screen_base);
dlfb_handle_damage(dlfb, area.x, area.y, area.w, area.h);
}
return 0;
......@@ -942,6 +1000,10 @@ static void dlfb_ops_destroy(struct fb_info *info)
{
struct dlfb_data *dlfb = info->par;
cancel_work_sync(&dlfb->damage_work);
mutex_destroy(&dlfb->render_mutex);
if (info->cmap.len != 0)
fb_dealloc_cmap(&info->cmap);
if (info->monspecs.modedb)
......@@ -1065,8 +1127,7 @@ static int dlfb_ops_set_par(struct fb_info *info)
pix_framebuffer[i] = 0x37e6;
}
dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres,
info->screen_base);
dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres);
return 0;
}
......@@ -1639,6 +1700,11 @@ static int dlfb_usb_probe(struct usb_interface *intf,
dlfb->ops = dlfb_ops;
info->fbops = &dlfb->ops;
mutex_init(&dlfb->render_mutex);
dlfb_init_damage(dlfb);
spin_lock_init(&dlfb->damage_lock);
INIT_WORK(&dlfb->damage_work, dlfb_damage_work);
INIT_LIST_HEAD(&info->modelist);
if (!dlfb_alloc_urb_list(dlfb, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
......
......@@ -1543,7 +1543,7 @@ static void uvesafb_ioremap(struct fb_info *info)
static ssize_t uvesafb_show_vbe_ver(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
return snprintf(buf, PAGE_SIZE, "%.4x\n", par->vbe_ib.vbe_version);
......@@ -1554,7 +1554,7 @@ static DEVICE_ATTR(vbe_version, S_IRUGO, uvesafb_show_vbe_ver, NULL);
static ssize_t uvesafb_show_vbe_modes(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
int ret = 0, i;
......@@ -1573,7 +1573,7 @@ static DEVICE_ATTR(vbe_modes, S_IRUGO, uvesafb_show_vbe_modes, NULL);
static ssize_t uvesafb_show_vendor(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
if (par->vbe_ib.oem_vendor_name_ptr)
......@@ -1588,7 +1588,7 @@ static DEVICE_ATTR(oem_vendor, S_IRUGO, uvesafb_show_vendor, NULL);
static ssize_t uvesafb_show_product_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
if (par->vbe_ib.oem_product_name_ptr)
......@@ -1603,7 +1603,7 @@ static DEVICE_ATTR(oem_product_name, S_IRUGO, uvesafb_show_product_name, NULL);
static ssize_t uvesafb_show_product_rev(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
if (par->vbe_ib.oem_product_rev_ptr)
......@@ -1618,7 +1618,7 @@ static DEVICE_ATTR(oem_product_rev, S_IRUGO, uvesafb_show_product_rev, NULL);
static ssize_t uvesafb_show_oem_string(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
if (par->vbe_ib.oem_string_ptr)
......@@ -1633,7 +1633,7 @@ static DEVICE_ATTR(oem_string, S_IRUGO, uvesafb_show_oem_string, NULL);
static ssize_t uvesafb_show_nocrtc(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
return snprintf(buf, PAGE_SIZE, "%d\n", par->nocrtc);
......@@ -1642,7 +1642,7 @@ static ssize_t uvesafb_show_nocrtc(struct device *dev,
static ssize_t uvesafb_store_nocrtc(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct fb_info *info = platform_get_drvdata(to_platform_device(dev));
struct fb_info *info = dev_get_drvdata(dev);
struct uvesafb_par *par = info->par;
if (count > 0) {
......
......@@ -337,7 +337,7 @@ static int vesafb_probe(struct platform_device *dev)
if (pmi_base[3]) {
printk(KERN_INFO "vesafb: pmi: ports = ");
for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
printk("%x ",pmi_base[i]);
printk("%x ", pmi_base[i]);
printk("\n");
if (pmi_base[i] != 0xffff) {
/*
......
......@@ -677,7 +677,7 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
case XenbusStateClosed:
if (dev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
/* fall through - Missed the backend's CLOSING state. */
case XenbusStateClosing:
xenbus_frontend_closed(dev);
break;
......
......@@ -124,38 +124,11 @@ struct clcd_board {
struct amba_device;
struct clk;
/**
* struct clcd_vendor_data - holds hardware (IP-block) vendor-specific
* variant information
*
* @clock_timregs: the CLCD needs to be clocked when accessing the
* timer registers, or the hardware will hang.
* @packed_24_bit_pixels: this variant supports 24bit packed pixel data,
* so that RGB accesses 3 bytes at a time, not just on even 32bit
* boundaries, packing the pixel data in memory. ST Microelectronics
* have this.
* @st_bitmux_control: ST Microelectronics have implemented output
* bit line multiplexing into the CLCD control register. This indicates
* that we need to use this.
* @init_board: custom board init function for this variant
* @init_panel: custom panel init function for this variant
*/
struct clcd_vendor_data {
bool clock_timregs;
bool packed_24_bit_pixels;
bool st_bitmux_control;
int (*init_board)(struct amba_device *adev,
struct clcd_board *board);
int (*init_panel)(struct clcd_fb *fb,
struct device_node *panel);
};
/* this data structure describes each frame buffer device we find */
struct clcd_fb {
struct fb_info fb;
struct amba_device *dev;
struct clk *clk;
struct clcd_vendor_data *vendor;
struct clcd_panel *panel;
struct clcd_board *board;
void *board_data;
......@@ -257,10 +230,6 @@ static inline void clcdfb_decode(struct clcd_fb *fb, struct clcd_regs *regs)
else
val |= CNTL_LCDBPP16_444;
break;
case 24:
/* Modified variant supporting 24 bit packed pixels */
val |= CNTL_ST_LCDBPP24_PACKED;
break;
case 32:
val |= CNTL_LCDBPP24;
break;
......
......@@ -48,6 +48,13 @@ struct dlfb_data {
int base8;
u32 pseudo_palette[256];
int blank_mode; /*one of FB_BLANK_ */
struct mutex render_mutex;
int damage_x;
int damage_y;
int damage_x2;
int damage_y2;
spinlock_t damage_lock;
struct work_struct damage_work;
struct fb_ops ops;
/* blit-only rendering path metrics, exposed through sysfs */
atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
......
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