提交 084165a3 编写于 作者: L Linus Torvalds

Merge tag 'fbdev-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux

Pull fbdev updates from Tomi Valkeinen:
 "Main changes:

   - amba-cldc: DT backlight support, Nomadik support, Versatile
     improvements, fixes

   - efifb: fix fbcon RGB565 palette

   - exynos: remove unused DSI driver"

* tag 'fbdev-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (42 commits)
  video: smscufx: remove unused variable
  matroxfb: fix size of memcpy
  fbdev: ssd1307fb: fix a possible NULL dereference
  fbdev: ssd1307fb: constify the device_info pointer
  simplefb: Disable and release clocks and regulators in destroy callback
  video: fbdev: constify fb_fix_screeninfo and fb_var_screeninfo structures
  matroxfb: constify local structures
  video: fbdev: i810: add in missing white space in error message text
  video: fbdev: add missing \n at end of printk error message
  ARM: exynos_defconfig: Remove old non-working MIPI driver
  video: fbdev: exynos: Remove old non-working MIPI driver
  omapfb: fix return value check in dsi_bind()
  MAINTAINERS: update fbdev entries
  video: fbdev: offb: Call pci_enable_device() before using the PCI VGA device
  fbdev: vfb: simplify memory management
  fbdev: vfb: add option for video mode
  fbdev: vfb: add description to module parameters
  video: fbdev: intelfb: remove impossible condition
  fb: adv7393: off by one in probe function
  video: fbdev: pxafb: add missing of_node_put() in of_get_pxafb_mode_info()
  ...
...@@ -4775,15 +4775,6 @@ L: iommu@lists.linux-foundation.org ...@@ -4775,15 +4775,6 @@ L: iommu@lists.linux-foundation.org
S: Maintained S: Maintained
F: drivers/iommu/exynos-iommu.c F: drivers/iommu/exynos-iommu.c
EXYNOS MIPI DISPLAY DRIVERS
M: Inki Dae <inki.dae@samsung.com>
M: Donghwa Lee <dh09.lee@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/exynos/exynos_mipi*
F: include/video/exynos_mipi*
EZchip NPS platform support EZchip NPS platform support
M: Noam Camus <noamc@ezchip.com> M: Noam Camus <noamc@ezchip.com>
S: Supported S: Supported
...@@ -4962,12 +4953,9 @@ F: drivers/net/wan/dlci.c ...@@ -4962,12 +4953,9 @@ F: drivers/net/wan/dlci.c
F: drivers/net/wan/sdla.c F: drivers/net/wan/sdla.c
FRAMEBUFFER LAYER FRAMEBUFFER LAYER
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
M: Tomi Valkeinen <tomi.valkeinen@ti.com> M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org L: linux-fbdev@vger.kernel.org
W: http://linux-fbdev.sourceforge.net/
Q: http://patchwork.kernel.org/project/linux-fbdev/list/ Q: http://patchwork.kernel.org/project/linux-fbdev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/plagnioj/linux-fbdev.git
S: Maintained S: Maintained
F: Documentation/fb/ F: Documentation/fb/
F: drivers/video/ F: drivers/video/
......
...@@ -168,8 +168,6 @@ CONFIG_DRM_PANEL_SAMSUNG_LD9040=y ...@@ -168,8 +168,6 @@ CONFIG_DRM_PANEL_SAMSUNG_LD9040=y
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=y CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=y
CONFIG_DRM_NXP_PTN3460=y CONFIG_DRM_NXP_PTN3460=y
CONFIG_DRM_PARADE_PS8622=y CONFIG_DRM_PARADE_PS8622=y
CONFIG_EXYNOS_VIDEO=y
CONFIG_EXYNOS_MIPI_DSI=y
CONFIG_LCD_CLASS_DEVICE=y CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=y CONFIG_LCD_PLATFORM=y
CONFIG_BACKLIGHT_PWM=y CONFIG_BACKLIGHT_PWM=y
......
...@@ -284,12 +284,14 @@ config FB_PM2_FIFO_DISCONNECT ...@@ -284,12 +284,14 @@ config FB_PM2_FIFO_DISCONNECT
config FB_ARMCLCD config FB_ARMCLCD
tristate "ARM PrimeCell PL110 support" tristate "ARM PrimeCell PL110 support"
depends on ARM || ARM64 || COMPILE_TEST depends on ARM || ARM64 || COMPILE_TEST
depends on FB && ARM_AMBA depends on FB && ARM_AMBA && HAS_IOMEM
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
select FB_CFB_COPYAREA select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT select FB_CFB_IMAGEBLIT
select FB_MODE_HELPERS if OF select FB_MODE_HELPERS if OF
select VIDEOMODE_HELPERS if OF select VIDEOMODE_HELPERS if OF
select BACKLIGHT_LCD_SUPPORT if OF
select BACKLIGHT_CLASS_DEVICE if OF
help help
This framebuffer device driver is for the ARM PrimeCell PL110 This framebuffer device driver is for the ARM PrimeCell PL110
Colour LCD controller. ARM PrimeCells provide the building Colour LCD controller. ARM PrimeCells provide the building
...@@ -305,6 +307,8 @@ config PLAT_VERSATILE_CLCD ...@@ -305,6 +307,8 @@ config PLAT_VERSATILE_CLCD
def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR
depends on ARM depends on ARM
depends on FB_ARMCLCD && FB=y depends on FB_ARMCLCD && FB=y
select REGMAP
select MFD_SYSCON
config FB_ACORN config FB_ACORN
bool "Acorn VIDC support" bool "Acorn VIDC support"
...@@ -2443,7 +2447,6 @@ config FB_SIMPLE ...@@ -2443,7 +2447,6 @@ config FB_SIMPLE
source "drivers/video/fbdev/omap/Kconfig" source "drivers/video/fbdev/omap/Kconfig"
source "drivers/video/fbdev/omap2/Kconfig" source "drivers/video/fbdev/omap2/Kconfig"
source "drivers/video/fbdev/exynos/Kconfig"
source "drivers/video/fbdev/mmp/Kconfig" source "drivers/video/fbdev/mmp/Kconfig"
config FB_SH_MOBILE_MERAM config FB_SH_MOBILE_MERAM
......
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
obj-y += core/ obj-y += core/
obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
obj-$(CONFIG_FB_MACMODES) += macmodes.o obj-$(CONFIG_FB_MACMODES) += macmodes.o
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
...@@ -79,6 +77,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o ...@@ -79,6 +77,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.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_PLAT_VERSATILE_CLCD) += amba-clcd-versatile.o
obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_68328) += 68328fb.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");
grestb = devm_get_gpiod_from_child(dev, "grestb", &np->fwnode);
if (IS_ERR(grestb)) {
dev_err(dev, "no GRESTB GPIO\n");
return;
}
/* This asserts the GRESTB signal, putting the display into reset */
gpiod_direction_output(grestb, 1);
scen = devm_get_gpiod_from_child(dev, "scen", &np->fwnode);
if (IS_ERR(scen)) {
dev_err(dev, "no SCEN GPIO\n");
return;
}
gpiod_direction_output(scen, 0);
scl = devm_get_gpiod_from_child(dev, "scl", &np->fwnode);
if (IS_ERR(scl)) {
dev_err(dev, "no SCL GPIO\n");
return;
}
gpiod_direction_output(scl, 0);
sda = devm_get_gpiod_from_child(dev, "sda", &np->fwnode);
if (IS_ERR(sda)) {
dev_err(dev, "no SDA GPIO\n");
return;
}
gpiod_direction_output(sda, 0);
board->enable = tpg110_enable;
board->disable = tpg110_disable;
}
int nomadik_clcd_init_panel(struct clcd_fb *fb,
struct device_node *endpoint)
{
struct device_node *panel;
panel = of_graph_get_remote_port_parent(endpoint);
if (!panel)
return -ENODEV;
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);
#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 *endpoint);
#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 *endpoint)
{
return 0;
}
#endif
#endif /* inclusion guard */
...@@ -3,6 +3,12 @@ ...@@ -3,6 +3,12 @@
#include <linux/amba/bus.h> #include <linux/amba/bus.h>
#include <linux/amba/clcd.h> #include <linux/amba/clcd.h>
#include <linux/platform_data/video-clcd-versatile.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 = { static struct clcd_panel vga = {
.mode = { .mode = {
...@@ -178,3 +184,392 @@ void versatile_clcd_remove_dma(struct clcd_fb *fb) ...@@ -178,3 +184,392 @@ void versatile_clcd_remove_dma(struct clcd_fb *fb)
dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base, dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base,
fb->fb.fix.smem_start); 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 *endpoint)
{
struct versatile_panel const *vpanel = NULL;
struct device_node *panel = 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;
}
panel = of_graph_get_remote_port_parent(endpoint);
if (!panel) {
dev_err(dev, "could not locate panel in DT\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 *endpoint)
{
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) {
dev_err(dev, "no Versatile syscon node\n");
return -ENODEV;
}
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, endpoint);
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
/*
* 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 *endpoint);
#else
static inline int versatile_clcd_init_panel(struct clcd_fb *fb,
struct device_node *endpoint)
{
return 0;
}
#endif
...@@ -30,10 +30,14 @@ ...@@ -30,10 +30,14 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/backlight.h>
#include <video/display_timing.h> #include <video/display_timing.h>
#include <video/of_display_timing.h> #include <video/of_display_timing.h>
#include <video/videomode.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) #define to_clcd(info) container_of(info, struct clcd_fb, fb)
/* This is limited to 16 characters when displayed by X startup */ /* This is limited to 16 characters when displayed by X startup */
...@@ -71,6 +75,11 @@ static void clcdfb_disable(struct clcd_fb *fb) ...@@ -71,6 +75,11 @@ static void clcdfb_disable(struct clcd_fb *fb)
if (fb->board->disable) if (fb->board->disable)
fb->board->disable(fb); fb->board->disable(fb);
if (fb->panel->backlight) {
fb->panel->backlight->props.power = FB_BLANK_POWERDOWN;
backlight_update_status(fb->panel->backlight);
}
val = readl(fb->regs + fb->off_cntl); val = readl(fb->regs + fb->off_cntl);
if (val & CNTL_LCDPWR) { if (val & CNTL_LCDPWR) {
val &= ~CNTL_LCDPWR; val &= ~CNTL_LCDPWR;
...@@ -116,6 +125,14 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl) ...@@ -116,6 +125,14 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
cntl |= CNTL_LCDPWR; cntl |= CNTL_LCDPWR;
writel(cntl, fb->regs + fb->off_cntl); writel(cntl, fb->regs + fb->off_cntl);
/*
* Turn on backlight
*/
if (fb->panel->backlight) {
fb->panel->backlight->props.power = FB_BLANK_UNBLANK;
backlight_update_status(fb->panel->backlight);
}
/* /*
* finally, enable the interface. * finally, enable the interface.
*/ */
...@@ -211,6 +228,15 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var) ...@@ -211,6 +228,15 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
var->blue.length = 4; var->blue.length = 4;
} }
break; 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: case 32:
/* If we can't do 888, reject */ /* If we can't do 888, reject */
caps &= CLCD_CAP_888; caps &= CLCD_CAP_888;
...@@ -297,6 +323,12 @@ static int clcdfb_set_par(struct fb_info *info) ...@@ -297,6 +323,12 @@ static int clcdfb_set_par(struct fb_info *info)
clcdfb_disable(fb); 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.tim0, fb->regs + CLCD_TIM0);
writel(regs.tim1, fb->regs + CLCD_TIM1); writel(regs.tim1, fb->regs + CLCD_TIM1);
writel(regs.tim2, fb->regs + CLCD_TIM2); writel(regs.tim2, fb->regs + CLCD_TIM2);
...@@ -551,7 +583,7 @@ static int clcdfb_register(struct clcd_fb *fb) ...@@ -551,7 +583,7 @@ static int clcdfb_register(struct clcd_fb *fb)
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int clcdfb_of_get_dpi_panel_mode(struct device_node *node, static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
struct fb_videomode *mode) struct clcd_panel *clcd_panel)
{ {
int err; int err;
struct display_timing timing; struct display_timing timing;
...@@ -563,10 +595,31 @@ static int clcdfb_of_get_dpi_panel_mode(struct device_node *node, ...@@ -563,10 +595,31 @@ static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
videomode_from_timing(&timing, &video); videomode_from_timing(&timing, &video);
err = fb_videomode_from_videomode(&video, mode); err = fb_videomode_from_videomode(&video, &clcd_panel->mode);
if (err) if (err)
return err; return err;
/* Set up some inversion flags */
if (timing.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
clcd_panel->tim2 |= TIM2_IPC;
else if (!(timing.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE))
/*
* To preserve backwards compatibility, the IPC (inverted
* pixel clock) flag needs to be set on any display that
* doesn't explicitly specify that the pixel clock is
* active on the negative or positive edge.
*/
clcd_panel->tim2 |= TIM2_IPC;
if (timing.flags & DISPLAY_FLAGS_HSYNC_LOW)
clcd_panel->tim2 |= TIM2_IHS;
if (timing.flags & DISPLAY_FLAGS_VSYNC_LOW)
clcd_panel->tim2 |= TIM2_IVS;
if (timing.flags & DISPLAY_FLAGS_DE_LOW)
clcd_panel->tim2 |= TIM2_IOE;
return 0; return 0;
} }
...@@ -576,11 +629,34 @@ static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode) ...@@ -576,11 +629,34 @@ static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
mode->refresh); mode->refresh);
} }
static int clcdfb_of_get_backlight(struct device_node *endpoint,
struct clcd_panel *clcd_panel)
{
struct device_node *panel;
struct device_node *backlight;
panel = of_graph_get_remote_port_parent(endpoint);
if (!panel)
return -ENODEV;
/* Look up the optional backlight phandle */
backlight = of_parse_phandle(panel, "backlight", 0);
if (backlight) {
clcd_panel->backlight = of_find_backlight_by_node(backlight);
of_node_put(backlight);
if (!clcd_panel->backlight)
return -EPROBE_DEFER;
}
return 0;
}
static int clcdfb_of_get_mode(struct device *dev, struct device_node *endpoint, static int clcdfb_of_get_mode(struct device *dev, struct device_node *endpoint,
struct fb_videomode *mode) struct clcd_panel *clcd_panel)
{ {
int err; int err;
struct device_node *panel; struct device_node *panel;
struct fb_videomode *mode;
char *name; char *name;
int len; int len;
...@@ -590,11 +666,12 @@ static int clcdfb_of_get_mode(struct device *dev, struct device_node *endpoint, ...@@ -590,11 +666,12 @@ static int clcdfb_of_get_mode(struct device *dev, struct device_node *endpoint,
/* Only directly connected DPI panels supported for now */ /* Only directly connected DPI panels supported for now */
if (of_device_is_compatible(panel, "panel-dpi")) if (of_device_is_compatible(panel, "panel-dpi"))
err = clcdfb_of_get_dpi_panel_mode(panel, mode); err = clcdfb_of_get_dpi_panel_mode(panel, clcd_panel);
else else
err = -ENOENT; err = -ENOENT;
if (err) if (err)
return err; return err;
mode = &clcd_panel->mode;
len = clcdfb_snprintf_mode(NULL, 0, mode); len = clcdfb_snprintf_mode(NULL, 0, mode);
name = devm_kzalloc(dev, len + 1, GFP_KERNEL); name = devm_kzalloc(dev, len + 1, GFP_KERNEL);
...@@ -616,6 +693,7 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0) ...@@ -616,6 +693,7 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
} panels[] = { } panels[] = {
{ 0x110, 1, 7, 13, CLCD_CAP_5551 }, { 0x110, 1, 7, 13, CLCD_CAP_5551 },
{ 0x110, 0, 8, 16, CLCD_CAP_888 }, { 0x110, 0, 8, 16, CLCD_CAP_888 },
{ 0x110, 16, 8, 0, CLCD_CAP_888 },
{ 0x111, 4, 14, 20, CLCD_CAP_444 }, { 0x111, 4, 14, 20, CLCD_CAP_444 },
{ 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 }, { 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
{ 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 | { 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
...@@ -625,8 +703,8 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0) ...@@ -625,8 +703,8 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
}; };
int i; int i;
/* Bypass pixel clock divider, data output on the falling edge */ /* Bypass pixel clock divider */
fb->panel->tim2 = TIM2_BCD | TIM2_IPC; fb->panel->tim2 |= TIM2_BCD;
/* TFT display, vert. comp. interrupt at the start of the back porch */ /* TFT display, vert. comp. interrupt at the start of the back porch */
fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1); fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
...@@ -643,6 +721,49 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0) ...@@ -643,6 +721,49 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
fb->panel->caps = panels[i].caps; fb->panel->caps = panels[i].caps;
} }
/*
* If we actually physically connected the R lines to B and
* vice versa
*/
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; return fb->panel->caps ? 0 : -EINVAL;
} }
...@@ -658,11 +779,24 @@ static int clcdfb_of_init_display(struct clcd_fb *fb) ...@@ -658,11 +779,24 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
if (!fb->panel) if (!fb->panel)
return -ENOMEM; return -ENOMEM;
/*
* Fetch the panel endpoint.
*/
endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL); endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL);
if (!endpoint) if (!endpoint)
return -ENODEV; return -ENODEV;
err = clcdfb_of_get_mode(&fb->dev->dev, endpoint, &fb->panel->mode); if (fb->vendor->init_panel) {
err = fb->vendor->init_panel(fb, endpoint);
if (err)
return err;
}
err = clcdfb_of_get_backlight(endpoint, fb->panel);
if (err)
return err;
err = clcdfb_of_get_mode(&fb->dev->dev, endpoint, fb->panel);
if (err) if (err)
return err; return err;
...@@ -693,11 +827,11 @@ static int clcdfb_of_init_display(struct clcd_fb *fb) ...@@ -693,11 +827,11 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
if (of_property_read_u32_array(endpoint, if (of_property_read_u32_array(endpoint,
"arm,pl11x,tft-r0g0b0-pads", "arm,pl11x,tft-r0g0b0-pads",
tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) == 0) tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0)
return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0], return -ENOENT;
tft_r0b0g0[1], tft_r0b0g0[2]);
return -ENOENT; return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
tft_r0b0g0[1], tft_r0b0g0[2]);
} }
static int clcdfb_of_vram_setup(struct clcd_fb *fb) static int clcdfb_of_vram_setup(struct clcd_fb *fb)
...@@ -818,6 +952,7 @@ static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev) ...@@ -818,6 +952,7 @@ 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) static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
{ {
struct clcd_board *board = dev_get_platdata(&dev->dev); struct clcd_board *board = dev_get_platdata(&dev->dev);
struct clcd_vendor_data *vendor = id->data;
struct clcd_fb *fb; struct clcd_fb *fb;
int ret; int ret;
...@@ -827,6 +962,12 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -827,6 +962,12 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
if (!board) if (!board)
return -EINVAL; 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)); ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
if (ret) if (ret)
goto out; goto out;
...@@ -845,17 +986,18 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -845,17 +986,18 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
} }
fb->dev = dev; fb->dev = dev;
fb->vendor = vendor;
fb->board = board; fb->board = board;
dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n", dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n",
amba_part(dev), amba_rev(dev), amba_part(dev), amba_manf(dev), amba_rev(dev),
(unsigned long long)dev->res.start); (unsigned long long)dev->res.start);
ret = fb->board->setup(fb); ret = fb->board->setup(fb);
if (ret) if (ret)
goto free_fb; goto free_fb;
ret = clcdfb_register(fb); ret = clcdfb_register(fb);
if (ret == 0) { if (ret == 0) {
amba_set_drvdata(dev, fb); amba_set_drvdata(dev, fb);
goto out; goto out;
...@@ -891,10 +1033,30 @@ static int clcdfb_remove(struct amba_device *dev) ...@@ -891,10 +1033,30 @@ static int clcdfb_remove(struct amba_device *dev)
return 0; 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 struct amba_id clcdfb_id_table[] = { static struct amba_id clcdfb_id_table[] = {
{ {
.id = 0x00041110, .id = 0x00041110,
.mask = 0x000ffffe, .mask = 0x000ffffe,
.data = &vendor_arm,
},
/* ST Electronics Nomadik variant */
{
.id = 0x00180110,
.mask = 0x00fffffe,
.data = &vendor_nomadik,
}, },
{ 0, 0 }, { 0, 0 },
}; };
......
...@@ -79,7 +79,7 @@ struct arcfb_par { ...@@ -79,7 +79,7 @@ struct arcfb_par {
spinlock_t lock; spinlock_t lock;
}; };
static struct fb_fix_screeninfo arcfb_fix = { static const struct fb_fix_screeninfo arcfb_fix = {
.id = "arcfb", .id = "arcfb",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_MONO01, .visual = FB_VISUAL_MONO01,
...@@ -89,7 +89,7 @@ static struct fb_fix_screeninfo arcfb_fix = { ...@@ -89,7 +89,7 @@ static struct fb_fix_screeninfo arcfb_fix = {
.accel = FB_ACCEL_NONE, .accel = FB_ACCEL_NONE,
}; };
static struct fb_var_screeninfo arcfb_var = { static const struct fb_var_screeninfo arcfb_var = {
.xres = 128, .xres = 128,
.yres = 64, .yres = 64,
.xres_virtual = 128, .xres_virtual = 128,
......
...@@ -474,7 +474,7 @@ static void chips_hw_init(struct fb_info *p) ...@@ -474,7 +474,7 @@ static void chips_hw_init(struct fb_info *p)
write_fr(chips_init_fr[i].addr, chips_init_fr[i].data); write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
} }
static struct fb_fix_screeninfo asiliantfb_fix = { static const struct fb_fix_screeninfo asiliantfb_fix = {
.id = "Asiliant 69000", .id = "Asiliant 69000",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR, .visual = FB_VISUAL_PSEUDOCOLOR,
...@@ -483,7 +483,7 @@ static struct fb_fix_screeninfo asiliantfb_fix = { ...@@ -483,7 +483,7 @@ static struct fb_fix_screeninfo asiliantfb_fix = {
.smem_len = 0x200000, /* 2MB */ .smem_len = 0x200000, /* 2MB */
}; };
static struct fb_var_screeninfo asiliantfb_var = { static const struct fb_var_screeninfo asiliantfb_var = {
.xres = 640, .xres = 640,
.yres = 480, .yres = 480,
.xres_virtual = 640, .xres_virtual = 640,
......
...@@ -93,7 +93,7 @@ ...@@ -93,7 +93,7 @@
#ifndef CONFIG_PPC_PMAC #ifndef CONFIG_PPC_PMAC
/* default mode */ /* default mode */
static struct fb_var_screeninfo default_var = { static const struct fb_var_screeninfo default_var = {
/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
640, 480, 640, 480, 0, 0, 8, 0, 640, 480, 640, 480, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
...@@ -104,7 +104,7 @@ static struct fb_var_screeninfo default_var = { ...@@ -104,7 +104,7 @@ static struct fb_var_screeninfo default_var = {
#else /* CONFIG_PPC_PMAC */ #else /* CONFIG_PPC_PMAC */
/* default to 1024x768 at 75Hz on PPC - this will work /* default to 1024x768 at 75Hz on PPC - this will work
* on the iMac, the usual 640x480 @ 60Hz doesn't. */ * on the iMac, the usual 640x480 @ 60Hz doesn't. */
static struct fb_var_screeninfo default_var = { static const struct fb_var_screeninfo default_var = {
/* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */ /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
1024, 768, 1024, 768, 0, 0, 8, 0, 1024, 768, 1024, 768, 0, 0, 8, 0,
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
...@@ -375,7 +375,7 @@ static const struct aty128_meminfo ddr_sgram = { ...@@ -375,7 +375,7 @@ static const struct aty128_meminfo ddr_sgram = {
.name = "64-bit DDR SGRAM", .name = "64-bit DDR SGRAM",
}; };
static struct fb_fix_screeninfo aty128fb_fix = { static const struct fb_fix_screeninfo aty128fb_fix = {
.id = "ATY Rage128", .id = "ATY Rage128",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR, .visual = FB_VISUAL_PSEUDOCOLOR,
......
...@@ -212,7 +212,7 @@ struct pci_mmap_map { ...@@ -212,7 +212,7 @@ struct pci_mmap_map {
unsigned long prot_mask; unsigned long prot_mask;
}; };
static struct fb_fix_screeninfo atyfb_fix = { static const struct fb_fix_screeninfo atyfb_fix = {
.id = "ATY Mach64", .id = "ATY Mach64",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR, .visual = FB_VISUAL_PSEUDOCOLOR,
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "../edid.h" #include "../edid.h"
static struct fb_var_screeninfo radeonfb_default_var = { static const struct fb_var_screeninfo radeonfb_default_var = {
.xres = 640, .xres = 640,
.yres = 480, .yres = 480,
.xres_virtual = 640, .xres_virtual = 640,
......
...@@ -375,7 +375,6 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client, ...@@ -375,7 +375,6 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
{ {
int ret = 0; int ret = 0;
struct proc_dir_entry *entry; struct proc_dir_entry *entry;
int num_modes = ARRAY_SIZE(known_modes);
struct adv7393fb_device *fbdev = NULL; struct adv7393fb_device *fbdev = NULL;
...@@ -384,7 +383,7 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client, ...@@ -384,7 +383,7 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
if (mode > num_modes) { if (mode >= ARRAY_SIZE(known_modes)) {
dev_err(&client->dev, "mode %d: not supported", mode); dev_err(&client->dev, "mode %d: not supported", mode);
return -EFAULT; return -EFAULT;
} }
...@@ -797,7 +796,7 @@ static struct i2c_driver bfin_adv7393_fb_driver = { ...@@ -797,7 +796,7 @@ static struct i2c_driver bfin_adv7393_fb_driver = {
static int __init bfin_adv7393_fb_driver_init(void) static int __init bfin_adv7393_fb_driver_init(void)
{ {
#if defined(CONFIG_I2C_BLACKFIN_TWI) || defined(CONFIG_I2C_BLACKFIN_TWI_MODULE) #if IS_ENABLED(CONFIG_I2C_BLACKFIN_TWI)
request_module("i2c-bfin-twi"); request_module("i2c-bfin-twi");
#else #else
request_module("i2c-gpio"); request_module("i2c-gpio");
......
...@@ -50,9 +50,9 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -50,9 +50,9 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 1; return 1;
if (regno < 16) { if (regno < 16) {
red >>= 8; red >>= 16 - info->var.red.length;
green >>= 8; green >>= 16 - info->var.green.length;
blue >>= 8; blue >>= 16 - info->var.blue.length;
((u32 *)(info->pseudo_palette))[regno] = ((u32 *)(info->pseudo_palette))[regno] =
(red << info->var.red.offset) | (red << info->var.red.offset) |
(green << info->var.green.offset) | (green << info->var.green.offset) |
......
#
# Exynos Video configuration
#
menuconfig EXYNOS_VIDEO
tristate "Exynos Video driver support"
depends on ARCH_S5PV210 || ARCH_EXYNOS
help
This enables support for EXYNOS Video device.
if EXYNOS_VIDEO
#
# MIPI DSI driver
#
config EXYNOS_MIPI_DSI
tristate "EXYNOS MIPI DSI driver support."
select GENERIC_PHY
help
This enables support for MIPI-DSI device.
config EXYNOS_LCD_S6E8AX0
tristate "S6E8AX0 MIPI AMOLED LCD Driver"
depends on EXYNOS_MIPI_DSI && BACKLIGHT_CLASS_DEVICE
depends on (LCD_CLASS_DEVICE = y)
default n
help
If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
LCD control driver.
endif # EXYNOS_VIDEO
#
# Makefile for the exynos video drivers.
#
obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos-mipi-dsi-mod.o
exynos-mipi-dsi-mod-objs += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
exynos_mipi_dsi_lowlevel.o
obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
/* linux/drivers/video/exynos/exynos_mipi_dsi.c
*
* Samsung SoC MIPI-DSIM driver.
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd
*
* InKi Dae, <inki.dae@samsung.com>
* Donghwa Lee, <dh09.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/fb.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/memory.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
#include <video/exynos_mipi_dsim.h>
#include "exynos_mipi_dsi_common.h"
#include "exynos_mipi_dsi_lowlevel.h"
struct mipi_dsim_ddi {
int bus_id;
struct list_head list;
struct mipi_dsim_lcd_device *dsim_lcd_dev;
struct mipi_dsim_lcd_driver *dsim_lcd_drv;
};
static LIST_HEAD(dsim_ddi_list);
static DEFINE_MUTEX(mipi_dsim_lock);
static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
*pdev)
{
return pdev->dev.platform_data;
}
static struct regulator_bulk_data supplies[] = {
{ .supply = "vdd11", },
{ .supply = "vdd18", },
};
static int exynos_mipi_regulator_enable(struct mipi_dsim_device *dsim)
{
int ret;
mutex_lock(&dsim->lock);
ret = regulator_bulk_enable(ARRAY_SIZE(supplies), supplies);
mutex_unlock(&dsim->lock);
return ret;
}
static int exynos_mipi_regulator_disable(struct mipi_dsim_device *dsim)
{
int ret;
mutex_lock(&dsim->lock);
ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies);
mutex_unlock(&dsim->lock);
return ret;
}
/* update all register settings to MIPI DSI controller. */
static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
{
/*
* data from Display controller(FIMD) is not transferred in video mode
* but in case of command mode, all settings is not updated to
* registers.
*/
exynos_mipi_dsi_stand_by(dsim, 0);
exynos_mipi_dsi_init_dsim(dsim);
exynos_mipi_dsi_init_link(dsim);
exynos_mipi_dsi_set_hs_enable(dsim);
/* set display timing. */
exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
exynos_mipi_dsi_init_interrupt(dsim);
/*
* data from Display controller(FIMD) is transferred in video mode
* but in case of command mode, all settings are updated to registers.
*/
exynos_mipi_dsi_stand_by(dsim, 1);
}
static int exynos_mipi_dsi_early_blank_mode(struct mipi_dsim_device *dsim,
int power)
{
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
switch (power) {
case FB_BLANK_POWERDOWN:
if (dsim->suspended)
return 0;
if (client_drv && client_drv->suspend)
client_drv->suspend(client_dev);
clk_disable(dsim->clock);
exynos_mipi_regulator_disable(dsim);
dsim->suspended = true;
break;
default:
break;
}
return 0;
}
static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
{
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
switch (power) {
case FB_BLANK_UNBLANK:
if (!dsim->suspended)
return 0;
/* lcd panel power on. */
if (client_drv && client_drv->power_on)
client_drv->power_on(client_dev, 1);
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
phy_power_on(dsim->phy);
clk_enable(dsim->clock);
exynos_mipi_update_cfg(dsim);
/* set lcd panel sequence commands. */
if (client_drv && client_drv->set_sequence)
client_drv->set_sequence(client_dev);
dsim->suspended = false;
break;
case FB_BLANK_NORMAL:
/* TODO. */
break;
default:
break;
}
return 0;
}
int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
{
struct mipi_dsim_ddi *dsim_ddi;
if (!lcd_dev->name) {
pr_err("dsim_lcd_device name is NULL.\n");
return -EFAULT;
}
dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
if (!dsim_ddi) {
pr_err("failed to allocate dsim_ddi object.\n");
return -ENOMEM;
}
dsim_ddi->dsim_lcd_dev = lcd_dev;
mutex_lock(&mipi_dsim_lock);
list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
mutex_unlock(&mipi_dsim_lock);
return 0;
}
static struct mipi_dsim_ddi *exynos_mipi_dsi_find_lcd_device(
struct mipi_dsim_lcd_driver *lcd_drv)
{
struct mipi_dsim_ddi *dsim_ddi, *next;
struct mipi_dsim_lcd_device *lcd_dev;
mutex_lock(&mipi_dsim_lock);
list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
if (!dsim_ddi)
goto out;
lcd_dev = dsim_ddi->dsim_lcd_dev;
if (!lcd_dev)
continue;
if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
/**
* bus_id would be used to identify
* connected bus.
*/
dsim_ddi->bus_id = lcd_dev->bus_id;
mutex_unlock(&mipi_dsim_lock);
return dsim_ddi;
}
list_del(&dsim_ddi->list);
kfree(dsim_ddi);
}
out:
mutex_unlock(&mipi_dsim_lock);
return NULL;
}
int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
{
struct mipi_dsim_ddi *dsim_ddi;
if (!lcd_drv->name) {
pr_err("dsim_lcd_driver name is NULL.\n");
return -EFAULT;
}
dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
if (!dsim_ddi) {
pr_err("mipi_dsim_ddi object not found.\n");
return -EFAULT;
}
dsim_ddi->dsim_lcd_drv = lcd_drv;
pr_info("registered panel driver(%s) to mipi-dsi driver.\n",
lcd_drv->name);
return 0;
}
EXPORT_SYMBOL_GPL(exynos_mipi_dsi_register_lcd_driver);
static struct mipi_dsim_ddi *exynos_mipi_dsi_bind_lcd_ddi(
struct mipi_dsim_device *dsim,
const char *name)
{
struct mipi_dsim_ddi *dsim_ddi, *next;
struct mipi_dsim_lcd_driver *lcd_drv;
struct mipi_dsim_lcd_device *lcd_dev;
int ret;
mutex_lock(&dsim->lock);
list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
lcd_drv = dsim_ddi->dsim_lcd_drv;
lcd_dev = dsim_ddi->dsim_lcd_dev;
if (!lcd_drv || !lcd_dev ||
(dsim->id != dsim_ddi->bus_id))
continue;
dev_dbg(dsim->dev, "lcd_drv->id = %d, lcd_dev->id = %d\n",
lcd_drv->id, lcd_dev->id);
dev_dbg(dsim->dev, "lcd_dev->bus_id = %d, dsim->id = %d\n",
lcd_dev->bus_id, dsim->id);
if ((strcmp(lcd_drv->name, name) == 0)) {
lcd_dev->master = dsim;
lcd_dev->dev.parent = dsim->dev;
dev_set_name(&lcd_dev->dev, "%s", lcd_drv->name);
ret = device_register(&lcd_dev->dev);
if (ret < 0) {
dev_err(dsim->dev,
"can't register %s, status %d\n",
dev_name(&lcd_dev->dev), ret);
mutex_unlock(&dsim->lock);
return NULL;
}
dsim->dsim_lcd_dev = lcd_dev;
dsim->dsim_lcd_drv = lcd_drv;
mutex_unlock(&dsim->lock);
return dsim_ddi;
}
}
mutex_unlock(&dsim->lock);
return NULL;
}
/* define MIPI-DSI Master operations. */
static struct mipi_dsim_master_ops master_ops = {
.cmd_read = exynos_mipi_dsi_rd_data,
.cmd_write = exynos_mipi_dsi_wr_data,
.get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
.clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
.set_early_blank_mode = exynos_mipi_dsi_early_blank_mode,
.set_blank_mode = exynos_mipi_dsi_blank_mode,
};
static int exynos_mipi_dsi_probe(struct platform_device *pdev)
{
struct resource *res;
struct mipi_dsim_device *dsim;
struct mipi_dsim_config *dsim_config;
struct mipi_dsim_platform_data *dsim_pd;
struct mipi_dsim_ddi *dsim_ddi;
int ret = -EINVAL;
dsim = devm_kzalloc(&pdev->dev, sizeof(struct mipi_dsim_device),
GFP_KERNEL);
if (!dsim) {
dev_err(&pdev->dev, "failed to allocate dsim object.\n");
return -ENOMEM;
}
dsim->pd = to_dsim_plat(pdev);
dsim->dev = &pdev->dev;
dsim->id = pdev->id;
/* get mipi_dsim_platform_data. */
dsim_pd = (struct mipi_dsim_platform_data *)dsim->pd;
if (dsim_pd == NULL) {
dev_err(&pdev->dev, "failed to get platform data for dsim.\n");
return -EINVAL;
}
/* get mipi_dsim_config. */
dsim_config = dsim_pd->dsim_config;
if (dsim_config == NULL) {
dev_err(&pdev->dev, "failed to get dsim config data.\n");
return -EINVAL;
}
dsim->dsim_config = dsim_config;
dsim->master_ops = &master_ops;
mutex_init(&dsim->lock);
ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(supplies),
supplies);
if (ret) {
dev_err(&pdev->dev, "Failed to get regulators: %d\n", ret);
return ret;
}
dsim->phy = devm_phy_get(&pdev->dev, "dsim");
if (IS_ERR(dsim->phy))
return PTR_ERR(dsim->phy);
dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
if (IS_ERR(dsim->clock)) {
dev_err(&pdev->dev, "failed to get dsim clock source\n");
return -ENODEV;
}
clk_enable(dsim->clock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dsim->reg_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dsim->reg_base)) {
ret = PTR_ERR(dsim->reg_base);
goto error;
}
mutex_init(&dsim->lock);
/* bind lcd ddi matched with panel name. */
dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
if (!dsim_ddi) {
dev_err(&pdev->dev, "mipi_dsim_ddi object not found.\n");
ret = -EINVAL;
goto error;
}
ret = platform_get_irq(pdev, 0);
if (ret < 0) {
dev_err(&pdev->dev, "failed to request dsim irq resource\n");
goto error;
}
dsim->irq = ret;
init_completion(&dsim_wr_comp);
init_completion(&dsim_rd_comp);
platform_set_drvdata(pdev, dsim);
ret = devm_request_irq(&pdev->dev, dsim->irq,
exynos_mipi_dsi_interrupt_handler,
IRQF_SHARED, dev_name(&pdev->dev), dsim);
if (ret != 0) {
dev_err(&pdev->dev, "failed to request dsim irq\n");
ret = -EINVAL;
goto error;
}
/* enable interrupts */
exynos_mipi_dsi_init_interrupt(dsim);
/* initialize mipi-dsi client(lcd panel). */
if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
/* in case mipi-dsi has been enabled by bootloader */
if (dsim_pd->enabled) {
exynos_mipi_regulator_enable(dsim);
goto done;
}
/* lcd panel power on. */
if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
dsim_ddi->dsim_lcd_drv->power_on(dsim_ddi->dsim_lcd_dev, 1);
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
phy_power_on(dsim->phy);
exynos_mipi_update_cfg(dsim);
/* set lcd panel sequence commands. */
if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->set_sequence)
dsim_ddi->dsim_lcd_drv->set_sequence(dsim_ddi->dsim_lcd_dev);
dsim->suspended = false;
done:
platform_set_drvdata(pdev, dsim);
dev_dbg(&pdev->dev, "%s() completed successfully (%s mode)\n", __func__,
dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
return 0;
error:
clk_disable(dsim->clock);
return ret;
}
static int exynos_mipi_dsi_remove(struct platform_device *pdev)
{
struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
struct mipi_dsim_ddi *dsim_ddi, *next;
struct mipi_dsim_lcd_driver *dsim_lcd_drv;
clk_disable(dsim->clock);
list_for_each_entry_safe(dsim_ddi, next, &dsim_ddi_list, list) {
if (dsim_ddi) {
if (dsim->id != dsim_ddi->bus_id)
continue;
dsim_lcd_drv = dsim_ddi->dsim_lcd_drv;
if (dsim_lcd_drv->remove)
dsim_lcd_drv->remove(dsim_ddi->dsim_lcd_dev);
kfree(dsim_ddi);
}
}
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int exynos_mipi_dsi_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
disable_irq(dsim->irq);
if (dsim->suspended)
return 0;
if (client_drv && client_drv->suspend)
client_drv->suspend(client_dev);
/* disable MIPI-DSI PHY. */
phy_power_off(dsim->phy);
clk_disable(dsim->clock);
exynos_mipi_regulator_disable(dsim);
dsim->suspended = true;
return 0;
}
static int exynos_mipi_dsi_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
enable_irq(dsim->irq);
if (!dsim->suspended)
return 0;
/* lcd panel power on. */
if (client_drv && client_drv->power_on)
client_drv->power_on(client_dev, 1);
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
phy_power_on(dsim->phy);
clk_enable(dsim->clock);
exynos_mipi_update_cfg(dsim);
/* set lcd panel sequence commands. */
if (client_drv && client_drv->set_sequence)
client_drv->set_sequence(client_dev);
dsim->suspended = false;
return 0;
}
#endif
static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
};
static struct platform_driver exynos_mipi_dsi_driver = {
.probe = exynos_mipi_dsi_probe,
.remove = exynos_mipi_dsi_remove,
.driver = {
.name = "exynos-mipi-dsim",
.pm = &exynos_mipi_dsi_pm_ops,
},
};
module_platform_driver(exynos_mipi_dsi_driver);
MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>");
MODULE_DESCRIPTION("Samsung SoC MIPI-DSI driver");
MODULE_LICENSE("GPL");
/* linux/drivers/video/exynos_mipi_dsi_common.h
*
* Header file for Samsung SoC MIPI-DSI common driver.
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd
*
* InKi Dae <inki.dae@samsung.com>
* Donghwa Lee <dh09.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _EXYNOS_MIPI_DSI_COMMON_H
#define _EXYNOS_MIPI_DSI_COMMON_H
static DECLARE_COMPLETION(dsim_rd_comp);
static DECLARE_COMPLETION(dsim_wr_comp);
int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id,
const unsigned char *data0, unsigned int data_size);
int exynos_mipi_dsi_rd_data(struct mipi_dsim_device *dsim, unsigned int data_id,
unsigned int data0, unsigned int req_size, u8 *rx_buf);
irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id);
void exynos_mipi_dsi_init_interrupt(struct mipi_dsim_device *dsim);
int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_stand_by(struct mipi_dsim_device *dsim,
unsigned int enable);
int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
struct mipi_dsim_config *dsim_info);
int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim);
int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim);
int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim,
unsigned int mode);
int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim,
unsigned int enable);
int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
extern struct fb_info *registered_fb[FB_MAX] __read_mostly;
int exynos_mipi_dsi_fifo_clear(struct mipi_dsim_device *dsim,
unsigned int val);
#endif /* _EXYNOS_MIPI_DSI_COMMON_H */
/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c
*
* Samsung SoC MIPI-DSI lowlevel driver.
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd
*
* InKi Dae, <inki.dae@samsung.com>
* Donghwa Lee, <dh09.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/ctype.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <video/exynos_mipi_dsim.h>
#include "exynos_mipi_dsi_regs.h"
#include "exynos_mipi_dsi_lowlevel.h"
void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
reg |= DSIM_FUNCRST;
writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
}
void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_SWRST);
reg |= DSIM_SWRST;
writel(reg, dsim->reg_base + EXYNOS_DSIM_SWRST);
}
void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
reg |= INTSRC_SW_RST_RELEASE;
writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
}
int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim)
{
return (readl(dsim->reg_base + EXYNOS_DSIM_INTSRC)) &
INTSRC_SW_RST_RELEASE;
}
unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_INTMSK);
return reg;
}
void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
unsigned int mode, unsigned int mask)
{
unsigned int reg = 0;
if (mask)
reg |= mode;
else
reg &= ~mode;
writel(reg, dsim->reg_base + EXYNOS_DSIM_INTMSK);
}
void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
unsigned int cfg)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
writel(reg & ~(cfg), dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
mdelay(10);
reg |= cfg;
writel(reg, dsim->reg_base + EXYNOS_DSIM_FIFOCTRL);
}
/*
* this function set PLL P, M and S value in D-PHY
*/
void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
unsigned int value)
{
writel(DSIM_AFC_CTL(value), dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
}
void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
unsigned int enable)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL);
reg &= ~DSIM_MAIN_STAND_BY;
if (enable)
reg |= DSIM_MAIN_STAND_BY;
writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
}
void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
unsigned int width_resol, unsigned int height_resol)
{
unsigned int reg;
/* standby should be set after configuration so set to not ready*/
reg = (readl(dsim->reg_base + EXYNOS_DSIM_MDRESOL)) &
~(DSIM_MAIN_STAND_BY);
writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
reg &= ~((0x7ff << 16) | (0x7ff << 0));
reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol);
reg |= DSIM_MAIN_STAND_BY;
writel(reg, dsim->reg_base + EXYNOS_DSIM_MDRESOL);
}
void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
unsigned int cmd_allow, unsigned int vfront, unsigned int vback)
{
unsigned int reg;
reg = (readl(dsim->reg_base + EXYNOS_DSIM_MVPORCH)) &
~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) |
(DSIM_MAIN_VBP_MASK));
reg |= (DSIM_CMD_ALLOW_SHIFT(cmd_allow & 0xf) |
DSIM_STABLE_VFP_SHIFT(vfront & 0x7ff) |
DSIM_MAIN_VBP_SHIFT(vback & 0x7ff));
writel(reg, dsim->reg_base + EXYNOS_DSIM_MVPORCH);
}
void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
unsigned int front, unsigned int back)
{
unsigned int reg;
reg = (readl(dsim->reg_base + EXYNOS_DSIM_MHPORCH)) &
~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK));
reg |= DSIM_MAIN_HFP_SHIFT(front) | DSIM_MAIN_HBP_SHIFT(back);
writel(reg, dsim->reg_base + EXYNOS_DSIM_MHPORCH);
}
void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
unsigned int vert, unsigned int hori)
{
unsigned int reg;
reg = (readl(dsim->reg_base + EXYNOS_DSIM_MSYNC)) &
~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK));
reg |= (DSIM_MAIN_VSA_SHIFT(vert & 0x3ff) |
DSIM_MAIN_HSA_SHIFT(hori));
writel(reg, dsim->reg_base + EXYNOS_DSIM_MSYNC);
}
void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
unsigned int vert, unsigned int hori)
{
unsigned int reg;
reg = (readl(dsim->reg_base + EXYNOS_DSIM_SDRESOL)) &
~(DSIM_SUB_STANDY_MASK);
writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK);
reg |= (DSIM_SUB_VRESOL_SHIFT(vert & 0x7ff) |
DSIM_SUB_HRESOL_SHIFT(hori & 0x7ff));
writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
reg |= DSIM_SUB_STANDY_SHIFT(1);
writel(reg, dsim->reg_base + EXYNOS_DSIM_SDRESOL);
}
void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim)
{
struct mipi_dsim_config *dsim_config = dsim->dsim_config;
unsigned int cfg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
~((1 << 28) | (0x1f << 20) | (0x3 << 5));
cfg = ((DSIM_AUTO_FLUSH(dsim_config->auto_flush)) |
(DSIM_EOT_DISABLE(dsim_config->eot_disable)) |
(DSIM_AUTO_MODE_SHIFT(dsim_config->auto_vertical_cnt)) |
(DSIM_HSE_MODE_SHIFT(dsim_config->hse)) |
(DSIM_HFP_MODE_SHIFT(dsim_config->hfp)) |
(DSIM_HBP_MODE_SHIFT(dsim_config->hbp)) |
(DSIM_HSA_MODE_SHIFT(dsim_config->hsa)) |
(DSIM_NUM_OF_DATALANE_SHIFT(dsim_config->e_no_data_lane)));
writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
}
void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
struct mipi_dsim_config *dsim_config)
{
u32 reg = (readl(dsim->reg_base + EXYNOS_DSIM_CONFIG)) &
~((0x3 << 26) | (1 << 25) | (0x3 << 18) | (0x7 << 12) |
(0x3 << 16) | (0x7 << 8));
if (dsim_config->e_interface == DSIM_VIDEO)
reg |= (1 << 25);
else if (dsim_config->e_interface == DSIM_COMMAND)
reg &= ~(1 << 25);
else {
dev_err(dsim->dev, "unknown lcd type.\n");
return;
}
/* main lcd */
reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << 26 |
((u8) (dsim_config->e_virtual_ch) & 0x3) << 18 |
((u8) (dsim_config->e_pixel_format) & 0x7) << 12;
writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
}
void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
unsigned int enable)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_CONFIG);
if (enable)
reg |= DSIM_LANE_ENx(lane);
else
reg &= ~DSIM_LANE_ENx(lane);
writel(reg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
}
void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
unsigned int count)
{
unsigned int cfg;
/* get the data lane number. */
cfg = DSIM_NUM_OF_DATALANE_SHIFT(count);
writel(cfg, dsim->reg_base + EXYNOS_DSIM_CONFIG);
}
void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
unsigned int afc_code)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
if (enable) {
reg |= (1 << 14);
reg &= ~(0x7 << 5);
reg |= (afc_code & 0x7) << 5;
} else
reg &= ~(1 << 14);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR);
}
void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
unsigned int enable)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
~(DSIM_PLL_BYPASS_SHIFT(0x1));
reg |= DSIM_PLL_BYPASS_SHIFT(enable);
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
unsigned int m, unsigned int s)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
reg |= ((p & 0x3f) << 13) | ((m & 0x1ff) << 4) | ((s & 0x7) << 1);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
unsigned int freq_band)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
~(DSIM_FREQ_BAND_SHIFT(0x1f));
reg |= DSIM_FREQ_BAND_SHIFT(freq_band & 0x1f);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
unsigned int pre_divider, unsigned int main_divider,
unsigned int scaler)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
~(0x7ffff << 1);
reg |= (pre_divider & 0x3f) << 13 | (main_divider & 0x1ff) << 4 |
(scaler & 0x7) << 1;
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
unsigned int lock_time)
{
writel(lock_time, dsim->reg_base + EXYNOS_DSIM_PLLTMR);
}
void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, unsigned int enable)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
~(DSIM_PLL_EN_SHIFT(0x1));
reg |= DSIM_PLL_EN_SHIFT(enable & 0x1);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
unsigned int src)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
~(DSIM_BYTE_CLK_SRC_SHIFT(0x3));
reg |= (DSIM_BYTE_CLK_SRC_SHIFT(src));
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
unsigned int enable)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
~(DSIM_BYTE_CLKEN_SHIFT(0x1));
reg |= DSIM_BYTE_CLKEN_SHIFT(enable);
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
unsigned int enable, unsigned int prs_val)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
~(DSIM_ESC_CLKEN_SHIFT(0x1) | 0xffff);
reg |= DSIM_ESC_CLKEN_SHIFT(enable);
if (enable)
reg |= prs_val;
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
unsigned int lane_sel, unsigned int enable)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
if (enable)
reg |= DSIM_LANE_ESC_CLKEN(lane_sel);
else
reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel);
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
unsigned int enable)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
~(DSIM_FORCE_STOP_STATE_SHIFT(0x1));
reg |= (DSIM_FORCE_STOP_STATE_SHIFT(enable & 0x1));
writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
}
unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
/**
* check clock and data lane states.
* if MIPI-DSI controller was enabled at bootloader then
* TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK.
* so it should be checked for two case.
*/
if ((reg & DSIM_STOP_STATE_DAT(0xf)) &&
((reg & DSIM_STOP_STATE_CLK) ||
(reg & DSIM_TX_READY_HS_CLK)))
return 1;
return 0;
}
void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
unsigned int cnt_val)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE)) &
~(DSIM_STOP_STATE_CNT_SHIFT(0x7ff));
reg |= (DSIM_STOP_STATE_CNT_SHIFT(cnt_val & 0x7ff));
writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
}
void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
unsigned int timeout)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
~(DSIM_BTA_TOUT_SHIFT(0xff));
reg |= (DSIM_BTA_TOUT_SHIFT(timeout));
writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
}
void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
unsigned int timeout)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_TIMEOUT)) &
~(DSIM_LPDR_TOUT_SHIFT(0xffff));
reg |= (DSIM_LPDR_TOUT_SHIFT(timeout));
writel(reg, dsim->reg_base + EXYNOS_DSIM_TIMEOUT);
}
void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
unsigned int lp)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
reg &= ~DSIM_CMD_LPDT_LP;
if (lp)
reg |= DSIM_CMD_LPDT_LP;
writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
}
void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
unsigned int lp)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_ESCMODE);
reg &= ~DSIM_TX_LPDT_LP;
if (lp)
reg |= DSIM_TX_LPDT_LP;
writel(reg, dsim->reg_base + EXYNOS_DSIM_ESCMODE);
}
void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
unsigned int enable)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_CLKCTRL)) &
~(DSIM_TX_REQUEST_HSCLK_SHIFT(0x1));
reg |= DSIM_TX_REQUEST_HSCLK_SHIFT(enable);
writel(reg, dsim->reg_base + EXYNOS_DSIM_CLKCTRL);
}
void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
unsigned int swap_en)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
reg &= ~(0x3 << 0);
reg |= (swap_en & 0x3) << 0;
writel(reg, dsim->reg_base + EXYNOS_DSIM_PHYACCHR1);
}
void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
unsigned int hs_zero)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
~(0xf << 28);
reg |= ((hs_zero & 0xf) << 28);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep)
{
unsigned int reg = (readl(dsim->reg_base + EXYNOS_DSIM_PLLCTRL)) &
~(0x7 << 20);
reg |= ((prep & 0x7) << 20);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PLLCTRL);
}
unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim)
{
return readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
}
void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
unsigned int src)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
reg |= src;
writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
}
void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
unsigned int src, unsigned int enable)
{
unsigned int reg = 0;
if (enable)
reg |= src;
else
reg &= ~src;
writel(reg, dsim->reg_base + EXYNOS_DSIM_INTSRC);
}
unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim)
{
unsigned int reg;
reg = readl(dsim->reg_base + EXYNOS_DSIM_STATUS);
return reg & (1 << 31) ? 1 : 0;
}
unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim)
{
return readl(dsim->reg_base + EXYNOS_DSIM_FIFOCTRL) & ~(0x1f);
}
void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim,
unsigned int di, unsigned int data0, unsigned int data1)
{
unsigned int reg = (data1 << 16) | (data0 << 8) | ((di & 0x3f) << 0);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
}
void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
unsigned int di, unsigned int data0)
{
unsigned int reg = (data0 << 8) | (di << 0);
writel(reg, dsim->reg_base + EXYNOS_DSIM_PKTHDR);
}
unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim)
{
return readl(dsim->reg_base + EXYNOS_DSIM_RXFIFO);
}
unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
return (reg & INTSRC_FRAME_DONE) ? 1 : 0;
}
void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim)
{
unsigned int reg = readl(dsim->reg_base + EXYNOS_DSIM_INTSRC);
writel(reg | INTSRC_FRAME_DONE, dsim->reg_base +
EXYNOS_DSIM_INTSRC);
}
void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
unsigned int tx_data)
{
writel(tx_data, dsim->reg_base + EXYNOS_DSIM_PAYLOAD);
}
/* linux/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h
*
* Header file for Samsung SoC MIPI-DSI lowlevel driver.
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd
*
* InKi Dae <inki.dae@samsung.com>
* Donghwa Lee <dh09.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H
#define _EXYNOS_MIPI_DSI_LOWLEVEL_H
void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_sw_reset_release(struct mipi_dsim_device *dsim);
int exynos_mipi_dsi_get_sw_reset_release(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim,
unsigned int mode, unsigned int mask);
void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
unsigned int count);
void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim,
unsigned int cfg);
void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
unsigned int value);
void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim,
unsigned int value);
void exynos_mipi_dsi_set_main_stand_by(struct mipi_dsim_device *dsim,
unsigned int enable);
void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim,
unsigned int width_resol, unsigned int height_resol);
void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim,
unsigned int cmd_allow, unsigned int vfront, unsigned int vback);
void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim,
unsigned int front, unsigned int back);
void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim,
unsigned int vert, unsigned int hori);
void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim,
unsigned int vert, unsigned int hori);
void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim,
struct mipi_dsim_config *dsim_config);
void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim,
unsigned int count);
void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, unsigned int lane,
unsigned int enable);
void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, unsigned int enable,
unsigned int afc_code);
void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim,
unsigned int enable);
void exynos_mipi_dsi_set_pll_pms(struct mipi_dsim_device *dsim, unsigned int p,
unsigned int m, unsigned int s);
void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim,
unsigned int freq_band);
void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim,
unsigned int pre_divider, unsigned int main_divider,
unsigned int scaler);
void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim,
unsigned int lock_time);
void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim,
unsigned int enable);
void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim,
unsigned int src);
void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim,
unsigned int enable);
void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim,
unsigned int enable, unsigned int prs_val);
void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim,
unsigned int lane_sel, unsigned int enable);
void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim,
unsigned int enable);
unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim,
unsigned int cnt_val);
void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim,
unsigned int timeout);
void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim,
unsigned int timeout);
void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim,
unsigned int lp);
void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim,
unsigned int lp);
void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim,
unsigned int enable);
void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim,
unsigned int swap_en);
void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim,
unsigned int hs_zero);
void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep);
unsigned int exynos_mipi_dsi_read_interrupt(struct mipi_dsim_device *dsim);
unsigned int exynos_mipi_dsi_read_interrupt_mask(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim,
unsigned int src);
void exynos_mipi_dsi_set_interrupt(struct mipi_dsim_device *dsim,
unsigned int src, unsigned int enable);
unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim);
unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim);
unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim);
void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim);
void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, unsigned int di,
unsigned int data0, unsigned int data1);
void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim,
unsigned int tx_data);
void exynos_mipi_dsi_rd_tx_header(struct mipi_dsim_device *dsim,
unsigned int data0, unsigned int data1);
unsigned int exynos_mipi_dsi_rd_rx_fifo(struct mipi_dsim_device *dsim);
#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */
/* linux/driver/video/exynos/exynos_mipi_dsi_regs.h
*
* Register definition file for Samsung MIPI-DSIM driver
*
* Copyright (c) 2012 Samsung Electronics Co., Ltd
*
* InKi Dae <inki.dae@samsung.com>
* Donghwa Lee <dh09.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _EXYNOS_MIPI_DSI_REGS_H
#define _EXYNOS_MIPI_DSI_REGS_H
#define EXYNOS_DSIM_STATUS 0x0 /* Status register */
#define EXYNOS_DSIM_SWRST 0x4 /* Software reset register */
#define EXYNOS_DSIM_CLKCTRL 0x8 /* Clock control register */
#define EXYNOS_DSIM_TIMEOUT 0xc /* Time out register */
#define EXYNOS_DSIM_CONFIG 0x10 /* Configuration register */
#define EXYNOS_DSIM_ESCMODE 0x14 /* Escape mode register */
/* Main display image resolution register */
#define EXYNOS_DSIM_MDRESOL 0x18
#define EXYNOS_DSIM_MVPORCH 0x1c /* Main display Vporch register */
#define EXYNOS_DSIM_MHPORCH 0x20 /* Main display Hporch register */
#define EXYNOS_DSIM_MSYNC 0x24 /* Main display sync area register */
/* Sub display image resolution register */
#define EXYNOS_DSIM_SDRESOL 0x28
#define EXYNOS_DSIM_INTSRC 0x2c /* Interrupt source register */
#define EXYNOS_DSIM_INTMSK 0x30 /* Interrupt mask register */
#define EXYNOS_DSIM_PKTHDR 0x34 /* Packet Header FIFO register */
#define EXYNOS_DSIM_PAYLOAD 0x38 /* Payload FIFO register */
#define EXYNOS_DSIM_RXFIFO 0x3c /* Read FIFO register */
#define EXYNOS_DSIM_FIFOTHLD 0x40 /* FIFO threshold level register */
#define EXYNOS_DSIM_FIFOCTRL 0x44 /* FIFO status and control register */
/* FIFO memory AC characteristic register */
#define EXYNOS_DSIM_PLLCTRL 0x4c /* PLL control register */
#define EXYNOS_DSIM_PLLTMR 0x50 /* PLL timer register */
#define EXYNOS_DSIM_PHYACCHR 0x54 /* D-PHY AC characteristic register */
#define EXYNOS_DSIM_PHYACCHR1 0x58 /* D-PHY AC characteristic register1 */
/* DSIM_STATUS */
#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
#define DSIM_STOP_STATE_CLK (1 << 8)
#define DSIM_TX_READY_HS_CLK (1 << 10)
/* DSIM_SWRST */
#define DSIM_FUNCRST (1 << 16)
#define DSIM_SWRST (1 << 0)
/* EXYNOS_DSIM_TIMEOUT */
#define DSIM_LPDR_TOUT_SHIFT(x) ((x) << 0)
#define DSIM_BTA_TOUT_SHIFT(x) ((x) << 16)
/* EXYNOS_DSIM_CLKCTRL */
#define DSIM_LANE_ESC_CLKEN(x) (((x) & 0x1f) << 19)
#define DSIM_BYTE_CLKEN_SHIFT(x) ((x) << 24)
#define DSIM_BYTE_CLK_SRC_SHIFT(x) ((x) << 25)
#define DSIM_PLL_BYPASS_SHIFT(x) ((x) << 27)
#define DSIM_ESC_CLKEN_SHIFT(x) ((x) << 28)
#define DSIM_TX_REQUEST_HSCLK_SHIFT(x) ((x) << 31)
/* EXYNOS_DSIM_CONFIG */
#define DSIM_LANE_ENx(x) (((x) & 0x1f) << 0)
#define DSIM_NUM_OF_DATALANE_SHIFT(x) ((x) << 5)
#define DSIM_HSA_MODE_SHIFT(x) ((x) << 20)
#define DSIM_HBP_MODE_SHIFT(x) ((x) << 21)
#define DSIM_HFP_MODE_SHIFT(x) ((x) << 22)
#define DSIM_HSE_MODE_SHIFT(x) ((x) << 23)
#define DSIM_AUTO_MODE_SHIFT(x) ((x) << 24)
#define DSIM_EOT_DISABLE(x) ((x) << 28)
#define DSIM_AUTO_FLUSH(x) ((x) << 29)
#define DSIM_NUM_OF_DATA_LANE(x) ((x) << DSIM_NUM_OF_DATALANE_SHIFT)
/* EXYNOS_DSIM_ESCMODE */
#define DSIM_TX_LPDT_LP (1 << 6)
#define DSIM_CMD_LPDT_LP (1 << 7)
#define DSIM_FORCE_STOP_STATE_SHIFT(x) ((x) << 20)
#define DSIM_STOP_STATE_CNT_SHIFT(x) ((x) << 21)
/* EXYNOS_DSIM_MDRESOL */
#define DSIM_MAIN_STAND_BY (1 << 31)
#define DSIM_MAIN_VRESOL(x) (((x) & 0x7ff) << 16)
#define DSIM_MAIN_HRESOL(x) (((x) & 0X7ff) << 0)
/* EXYNOS_DSIM_MVPORCH */
#define DSIM_CMD_ALLOW_SHIFT(x) ((x) << 28)
#define DSIM_STABLE_VFP_SHIFT(x) ((x) << 16)
#define DSIM_MAIN_VBP_SHIFT(x) ((x) << 0)
#define DSIM_CMD_ALLOW_MASK (0xf << 28)
#define DSIM_STABLE_VFP_MASK (0x7ff << 16)
#define DSIM_MAIN_VBP_MASK (0x7ff << 0)
/* EXYNOS_DSIM_MHPORCH */
#define DSIM_MAIN_HFP_SHIFT(x) ((x) << 16)
#define DSIM_MAIN_HBP_SHIFT(x) ((x) << 0)
#define DSIM_MAIN_HFP_MASK ((0xffff) << 16)
#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
/* EXYNOS_DSIM_MSYNC */
#define DSIM_MAIN_VSA_SHIFT(x) ((x) << 22)
#define DSIM_MAIN_HSA_SHIFT(x) ((x) << 0)
#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
/* EXYNOS_DSIM_SDRESOL */
#define DSIM_SUB_STANDY_SHIFT(x) ((x) << 31)
#define DSIM_SUB_VRESOL_SHIFT(x) ((x) << 16)
#define DSIM_SUB_HRESOL_SHIFT(x) ((x) << 0)
#define DSIM_SUB_STANDY_MASK ((0x1) << 31)
#define DSIM_SUB_VRESOL_MASK ((0x7ff) << 16)
#define DSIM_SUB_HRESOL_MASK ((0x7ff) << 0)
/* EXYNOS_DSIM_INTSRC */
#define INTSRC_PLL_STABLE (1 << 31)
#define INTSRC_SW_RST_RELEASE (1 << 30)
#define INTSRC_SFR_FIFO_EMPTY (1 << 29)
#define INTSRC_FRAME_DONE (1 << 24)
#define INTSRC_RX_DATA_DONE (1 << 18)
/* EXYNOS_DSIM_INTMSK */
#define INTMSK_FIFO_EMPTY (1 << 29)
#define INTMSK_BTA (1 << 25)
#define INTMSK_FRAME_DONE (1 << 24)
#define INTMSK_RX_TIMEOUT (1 << 21)
#define INTMSK_BTA_TIMEOUT (1 << 20)
#define INTMSK_RX_DONE (1 << 18)
#define INTMSK_RX_TE (1 << 17)
#define INTMSK_RX_ACK (1 << 16)
#define INTMSK_RX_ECC_ERR (1 << 15)
#define INTMSK_RX_CRC_ERR (1 << 14)
/* EXYNOS_DSIM_FIFOCTRL */
#define SFR_HEADER_EMPTY (1 << 22)
/* EXYNOS_DSIM_PHYACCHR */
#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
/* EXYNOS_DSIM_PLLCTRL */
#define DSIM_PLL_EN_SHIFT(x) ((x) << 23)
#define DSIM_FREQ_BAND_SHIFT(x) ((x) << 24)
#endif /* _EXYNOS_MIPI_DSI_REGS_H */
此差异已折叠。
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
#define DPY_W 600 #define DPY_W 600
#define DPY_H 800 #define DPY_H 800
static struct fb_fix_screeninfo hecubafb_fix = { static const struct fb_fix_screeninfo hecubafb_fix = {
.id = "hecubafb", .id = "hecubafb",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_MONO01, .visual = FB_VISUAL_MONO01,
...@@ -58,7 +58,7 @@ static struct fb_fix_screeninfo hecubafb_fix = { ...@@ -58,7 +58,7 @@ static struct fb_fix_screeninfo hecubafb_fix = {
.accel = FB_ACCEL_NONE, .accel = FB_ACCEL_NONE,
}; };
static struct fb_var_screeninfo hecubafb_var = { static const struct fb_var_screeninfo hecubafb_var = {
.xres = DPY_W, .xres = DPY_W,
.yres = DPY_H, .yres = DPY_H,
.xres_virtual = DPY_W, .xres_virtual = DPY_W,
......
...@@ -106,7 +106,7 @@ static DEFINE_SPINLOCK(hga_reg_lock); ...@@ -106,7 +106,7 @@ static DEFINE_SPINLOCK(hga_reg_lock);
/* Framebuffer driver structures */ /* Framebuffer driver structures */
static struct fb_var_screeninfo hga_default_var = { static const struct fb_var_screeninfo hga_default_var = {
.xres = 720, .xres = 720,
.yres = 348, .yres = 348,
.xres_virtual = 720, .xres_virtual = 720,
......
...@@ -82,7 +82,7 @@ struct i740fb_par { ...@@ -82,7 +82,7 @@ struct i740fb_par {
#define DACSPEED24_SD 128 #define DACSPEED24_SD 128
#define DACSPEED32 86 #define DACSPEED32 86
static struct fb_fix_screeninfo i740fb_fix = { static const struct fb_fix_screeninfo i740fb_fix = {
.id = "i740fb", .id = "i740fb",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR, .visual = FB_VISUAL_TRUECOLOR,
......
...@@ -1691,7 +1691,7 @@ static int i810_alloc_agp_mem(struct fb_info *info) ...@@ -1691,7 +1691,7 @@ static int i810_alloc_agp_mem(struct fb_info *info)
if (!(par->i810_gtt.i810_cursor_memory = if (!(par->i810_gtt.i810_cursor_memory =
agp_allocate_memory(bridge, par->cursor_heap.size >> 12, agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
AGP_PHYSICAL_MEMORY))) { AGP_PHYSICAL_MEMORY))) {
printk("i810fb_alloc_cursormem: can't allocate" printk("i810fb_alloc_cursormem: can't allocate "
"cursor memory\n"); "cursor memory\n");
agp_backend_release(bridge); agp_backend_release(bridge);
return -ENOMEM; return -ENOMEM;
......
...@@ -1301,11 +1301,6 @@ static int intelfb_check_var(struct fb_var_screeninfo *var, ...@@ -1301,11 +1301,6 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
break; break;
} }
if (v.xoffset < 0)
v.xoffset = 0;
if (v.yoffset < 0)
v.yoffset = 0;
if (v.xoffset > v.xres_virtual - v.xres) if (v.xoffset > v.xres_virtual - v.xres)
v.xoffset = v.xres_virtual - v.xres; v.xoffset = v.xres_virtual - v.xres;
if (v.yoffset > v.yres_virtual - v.yres) if (v.yoffset > v.yres_virtual - v.yres)
......
...@@ -44,7 +44,7 @@ static struct fb_fix_screeninfo kyro_fix = { ...@@ -44,7 +44,7 @@ static struct fb_fix_screeninfo kyro_fix = {
.accel = FB_ACCEL_NONE, .accel = FB_ACCEL_NONE,
}; };
static struct fb_var_screeninfo kyro_var = { static const struct fb_var_screeninfo kyro_var = {
/* 640x480, 16bpp @ 60 Hz */ /* 640x480, 16bpp @ 60 Hz */
.xres = 640, .xres = 640,
.yres = 480, .yres = 480,
......
...@@ -372,7 +372,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m) ...@@ -372,7 +372,7 @@ static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
DBG(__func__) DBG(__func__)
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg)); memcpy(hw->DACreg, MGADACbpp32, sizeof(MGADACbpp32));
switch (minfo->fbcon.var.bits_per_pixel) { switch (minfo->fbcon.var.bits_per_pixel) {
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */ case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR; hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
......
...@@ -433,7 +433,7 @@ static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct outp ...@@ -433,7 +433,7 @@ static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct outp
0x00, /* 3E written multiple times */ 0x00, /* 3E written multiple times */
0x00, /* 3F not written */ 0x00, /* 3F not written */
} }; } };
static struct mavenregs ntscregs = { { static const struct mavenregs ntscregs = { {
0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */ 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
0x00, 0x00,
0x00, /* test */ 0x00, /* test */
......
...@@ -157,17 +157,10 @@ static struct i2c_adapter mb862xx_i2c_adapter = { ...@@ -157,17 +157,10 @@ static struct i2c_adapter mb862xx_i2c_adapter = {
int mb862xx_i2c_init(struct mb862xxfb_par *par) int mb862xx_i2c_init(struct mb862xxfb_par *par)
{ {
int ret;
mb862xx_i2c_adapter.algo_data = par; mb862xx_i2c_adapter.algo_data = par;
par->adap = &mb862xx_i2c_adapter; par->adap = &mb862xx_i2c_adapter;
ret = i2c_add_adapter(par->adap); return i2c_add_adapter(par->adap);
if (ret < 0) {
dev_err(par->dev, "failed to add %s\n",
mb862xx_i2c_adapter.name);
}
return ret;
} }
void mb862xx_i2c_exit(struct mb862xxfb_par *par) void mb862xx_i2c_exit(struct mb862xxfb_par *par)
......
...@@ -845,7 +845,7 @@ static int __set_par(struct fb_info *fbi, bool lock) ...@@ -845,7 +845,7 @@ static int __set_par(struct fb_info *fbi, bool lock)
if (fbi->var.sync & FB_SYNC_SHARP_MODE) if (fbi->var.sync & FB_SYNC_SHARP_MODE)
mode = IPU_PANEL_SHARP_TFT; mode = IPU_PANEL_SHARP_TFT;
dev_dbg(fbi->device, "pixclock = %ul Hz\n", dev_dbg(fbi->device, "pixclock = %u Hz\n",
(u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL));
if (sdc_init_panel(mx3fb, mode, if (sdc_init_panel(mx3fb, mode,
......
...@@ -800,6 +800,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host, ...@@ -800,6 +800,7 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host,
struct fb_videomode *vmode) struct fb_videomode *vmode)
{ {
int ret; int ret;
struct device *dev = &host->pdev->dev;
struct fb_info *fb_info = &host->fb_info; struct fb_info *fb_info = &host->fb_info;
struct fb_var_screeninfo *var = &fb_info->var; struct fb_var_screeninfo *var = &fb_info->var;
dma_addr_t fb_phys; dma_addr_t fb_phys;
...@@ -825,12 +826,10 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host, ...@@ -825,12 +826,10 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host,
/* Memory allocation for framebuffer */ /* Memory allocation for framebuffer */
fb_size = SZ_2M; fb_size = SZ_2M;
fb_virt = alloc_pages_exact(fb_size, GFP_DMA); fb_virt = dma_alloc_wc(dev, PAGE_ALIGN(fb_size), &fb_phys, GFP_KERNEL);
if (!fb_virt) if (!fb_virt)
return -ENOMEM; return -ENOMEM;
fb_phys = virt_to_phys(fb_virt);
fb_info->fix.smem_start = fb_phys; fb_info->fix.smem_start = fb_phys;
fb_info->screen_base = fb_virt; fb_info->screen_base = fb_virt;
fb_info->screen_size = fb_info->fix.smem_len = fb_size; fb_info->screen_size = fb_info->fix.smem_len = fb_size;
...@@ -843,9 +842,11 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host, ...@@ -843,9 +842,11 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host,
static void mxsfb_free_videomem(struct mxsfb_info *host) static void mxsfb_free_videomem(struct mxsfb_info *host)
{ {
struct device *dev = &host->pdev->dev;
struct fb_info *fb_info = &host->fb_info; struct fb_info *fb_info = &host->fb_info;
free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len); dma_free_wc(dev, fb_info->screen_size, fb_info->screen_base,
fb_info->fix.smem_start);
} }
static const struct platform_device_id mxsfb_devtype[] = { static const struct platform_device_id mxsfb_devtype[] = {
......
...@@ -625,6 +625,21 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) ...@@ -625,6 +625,21 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node)
if (address == OF_BAD_ADDR && addr_prop) if (address == OF_BAD_ADDR && addr_prop)
address = (u64)addr_prop; address = (u64)addr_prop;
if (address != OF_BAD_ADDR) { if (address != OF_BAD_ADDR) {
#ifdef CONFIG_PCI
const __be32 *vidp, *didp;
u32 vid, did;
struct pci_dev *pdev;
vidp = of_get_property(dp, "vendor-id", NULL);
didp = of_get_property(dp, "device-id", NULL);
if (vidp && didp) {
vid = be32_to_cpup(vidp);
did = be32_to_cpup(didp);
pdev = pci_get_device(vid, did, NULL);
if (!pdev || pci_enable_device(pdev))
return;
}
#endif
/* kludge for valkyrie */ /* kludge for valkyrie */
if (strcmp(dp->name, "valkyrie") == 0) if (strcmp(dp->name, "valkyrie") == 0)
address += 0x1000; address += 0x1000;
......
...@@ -60,7 +60,6 @@ struct mipid_device { ...@@ -60,7 +60,6 @@ struct mipid_device {
struct mutex mutex; struct mutex mutex;
struct lcd_panel panel; struct lcd_panel panel;
struct workqueue_struct *esd_wq;
struct delayed_work esd_work; struct delayed_work esd_work;
void (*esd_check)(struct mipid_device *m); void (*esd_check)(struct mipid_device *m);
}; };
...@@ -390,7 +389,7 @@ static void ls041y3_esd_check(struct mipid_device *md) ...@@ -390,7 +389,7 @@ static void ls041y3_esd_check(struct mipid_device *md)
static void mipid_esd_start_check(struct mipid_device *md) static void mipid_esd_start_check(struct mipid_device *md)
{ {
if (md->esd_check != NULL) if (md->esd_check != NULL)
queue_delayed_work(md->esd_wq, &md->esd_work, schedule_delayed_work(&md->esd_work,
MIPID_ESD_CHECK_PERIOD); MIPID_ESD_CHECK_PERIOD);
} }
...@@ -476,11 +475,6 @@ static int mipid_init(struct lcd_panel *panel, ...@@ -476,11 +475,6 @@ static int mipid_init(struct lcd_panel *panel,
struct mipid_device *md = to_mipid_device(panel); struct mipid_device *md = to_mipid_device(panel);
md->fbdev = fbdev; md->fbdev = fbdev;
md->esd_wq = create_singlethread_workqueue("mipid_esd");
if (md->esd_wq == NULL) {
dev_err(&md->spi->dev, "can't create ESD workqueue\n");
return -ENOMEM;
}
INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work); INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
mutex_init(&md->mutex); mutex_init(&md->mutex);
...@@ -500,7 +494,6 @@ static void mipid_cleanup(struct lcd_panel *panel) ...@@ -500,7 +494,6 @@ static void mipid_cleanup(struct lcd_panel *panel)
if (md->enabled) if (md->enabled)
mipid_esd_stop_check(md); mipid_esd_stop_check(md);
destroy_workqueue(md->esd_wq);
} }
static struct lcd_panel mipid_panel = { static struct lcd_panel mipid_panel = {
......
...@@ -75,8 +75,6 @@ struct panel_drv_data { ...@@ -75,8 +75,6 @@ struct panel_drv_data {
bool intro_printed; bool intro_printed;
struct workqueue_struct *workqueue;
bool ulps_enabled; bool ulps_enabled;
unsigned ulps_timeout; unsigned ulps_timeout;
struct delayed_work ulps_work; struct delayed_work ulps_work;
...@@ -232,7 +230,7 @@ static int dsicm_set_update_window(struct panel_drv_data *ddata, ...@@ -232,7 +230,7 @@ static int dsicm_set_update_window(struct panel_drv_data *ddata,
static void dsicm_queue_ulps_work(struct panel_drv_data *ddata) static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
{ {
if (ddata->ulps_timeout > 0) if (ddata->ulps_timeout > 0)
queue_delayed_work(ddata->workqueue, &ddata->ulps_work, schedule_delayed_work(&ddata->ulps_work,
msecs_to_jiffies(ddata->ulps_timeout)); msecs_to_jiffies(ddata->ulps_timeout));
} }
...@@ -1244,11 +1242,6 @@ static int dsicm_probe(struct platform_device *pdev) ...@@ -1244,11 +1242,6 @@ static int dsicm_probe(struct platform_device *pdev)
dev_dbg(dev, "Using GPIO TE\n"); dev_dbg(dev, "Using GPIO TE\n");
} }
ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
if (ddata->workqueue == NULL) {
dev_err(dev, "can't create workqueue\n");
return -ENOMEM;
}
INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work); INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
dsicm_hw_reset(ddata); dsicm_hw_reset(ddata);
...@@ -1262,7 +1255,7 @@ static int dsicm_probe(struct platform_device *pdev) ...@@ -1262,7 +1255,7 @@ static int dsicm_probe(struct platform_device *pdev)
dev, ddata, &dsicm_bl_ops, &props); dev, ddata, &dsicm_bl_ops, &props);
if (IS_ERR(bldev)) { if (IS_ERR(bldev)) {
r = PTR_ERR(bldev); r = PTR_ERR(bldev);
goto err_bl; goto err_reg;
} }
ddata->bldev = bldev; ddata->bldev = bldev;
...@@ -1285,8 +1278,6 @@ static int dsicm_probe(struct platform_device *pdev) ...@@ -1285,8 +1278,6 @@ static int dsicm_probe(struct platform_device *pdev)
err_sysfs_create: err_sysfs_create:
if (bldev != NULL) if (bldev != NULL)
backlight_device_unregister(bldev); backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(ddata->workqueue);
err_reg: err_reg:
return r; return r;
} }
...@@ -1316,7 +1307,6 @@ static int __exit dsicm_remove(struct platform_device *pdev) ...@@ -1316,7 +1307,6 @@ static int __exit dsicm_remove(struct platform_device *pdev)
omap_dss_put_device(ddata->in); omap_dss_put_device(ddata->in);
dsicm_cancel_ulps_work(ddata); dsicm_cancel_ulps_work(ddata);
destroy_workqueue(ddata->workqueue);
/* reset, to be sure that the panel is in a valid state */ /* reset, to be sure that the panel is in a valid state */
dsicm_hw_reset(ddata); dsicm_hw_reset(ddata);
......
...@@ -644,6 +644,7 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ...@@ -644,6 +644,7 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
{ {
int r; int r;
long time_left;
DECLARE_COMPLETION_ONSTACK(completion); DECLARE_COMPLETION_ONSTACK(completion);
r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion,
...@@ -652,15 +653,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, ...@@ -652,15 +653,15 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
if (r) if (r)
return r; return r;
timeout = wait_for_completion_interruptible_timeout(&completion, time_left = wait_for_completion_interruptible_timeout(&completion,
timeout); timeout);
omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask);
if (timeout == 0) if (time_left == 0)
return -ETIMEDOUT; return -ETIMEDOUT;
if (timeout == -ERESTARTSYS) if (time_left == -ERESTARTSYS)
return -ERESTARTSYS; return -ERESTARTSYS;
return 0; return 0;
......
...@@ -1167,7 +1167,6 @@ static int dsi_regulator_init(struct platform_device *dsidev) ...@@ -1167,7 +1167,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
{ {
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
struct regulator *vdds_dsi; struct regulator *vdds_dsi;
int r;
if (dsi->vdds_dsi_reg != NULL) if (dsi->vdds_dsi_reg != NULL)
return 0; return 0;
...@@ -1180,13 +1179,6 @@ static int dsi_regulator_init(struct platform_device *dsidev) ...@@ -1180,13 +1179,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
return PTR_ERR(vdds_dsi); return PTR_ERR(vdds_dsi);
} }
r = regulator_set_voltage(vdds_dsi, 1800000, 1800000);
if (r) {
devm_regulator_put(vdds_dsi);
DSSERR("can't set the DSI regulator voltage\n");
return r;
}
dsi->vdds_dsi_reg = vdds_dsi; dsi->vdds_dsi_reg = vdds_dsi;
return 0; return 0;
...@@ -5348,7 +5340,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -5348,7 +5340,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
dsi->phy_base = devm_ioremap(&dsidev->dev, res->start, dsi->phy_base = devm_ioremap(&dsidev->dev, res->start,
resource_size(res)); resource_size(res));
if (!dsi->proto_base) { if (!dsi->phy_base) {
DSSERR("can't ioremap DSI PHY\n"); DSSERR("can't ioremap DSI PHY\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -5368,7 +5360,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data) ...@@ -5368,7 +5360,7 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
dsi->pll_base = devm_ioremap(&dsidev->dev, res->start, dsi->pll_base = devm_ioremap(&dsidev->dev, res->start,
resource_size(res)); resource_size(res));
if (!dsi->proto_base) { if (!dsi->pll_base) {
DSSERR("can't ioremap DSI PLL\n"); DSSERR("can't ioremap DSI PLL\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -100,7 +100,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data) ...@@ -100,7 +100,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
static int hdmi_init_regulator(void) static int hdmi_init_regulator(void)
{ {
int r;
struct regulator *reg; struct regulator *reg;
if (hdmi.vdda_reg != NULL) if (hdmi.vdda_reg != NULL)
...@@ -114,13 +113,6 @@ static int hdmi_init_regulator(void) ...@@ -114,13 +113,6 @@ static int hdmi_init_regulator(void)
return PTR_ERR(reg); return PTR_ERR(reg);
} }
r = regulator_set_voltage(reg, 1800000, 1800000);
if (r) {
devm_regulator_put(reg);
DSSWARN("can't set the regulator voltage\n");
return r;
}
hdmi.vdda_reg = reg; hdmi.vdda_reg = reg;
return 0; return 0;
......
...@@ -119,7 +119,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data) ...@@ -119,7 +119,6 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data)
static int hdmi_init_regulator(void) static int hdmi_init_regulator(void)
{ {
int r;
struct regulator *reg; struct regulator *reg;
if (hdmi.vdda_reg != NULL) if (hdmi.vdda_reg != NULL)
...@@ -131,13 +130,6 @@ static int hdmi_init_regulator(void) ...@@ -131,13 +130,6 @@ static int hdmi_init_regulator(void)
return PTR_ERR(reg); return PTR_ERR(reg);
} }
r = regulator_set_voltage(reg, 1800000, 1800000);
if (r) {
devm_regulator_put(reg);
DSSWARN("can't set the regulator voltage\n");
return r;
}
hdmi.vdda_reg = reg; hdmi.vdda_reg = reg;
return 0; return 0;
......
...@@ -113,7 +113,7 @@ static struct fb_fix_screeninfo pm2fb_fix = { ...@@ -113,7 +113,7 @@ static struct fb_fix_screeninfo pm2fb_fix = {
/* /*
* Default video mode. In case the modedb doesn't work. * Default video mode. In case the modedb doesn't work.
*/ */
static struct fb_var_screeninfo pm2fb_var = { static const struct fb_var_screeninfo pm2fb_var = {
/* "640x480, 8 bpp @ 60 Hz */ /* "640x480, 8 bpp @ 60 Hz */
.xres = 640, .xres = 640,
.yres = 480, .yres = 480,
......
...@@ -2125,7 +2125,7 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp, ...@@ -2125,7 +2125,7 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
timings = of_get_display_timings(disp); timings = of_get_display_timings(disp);
if (!timings) if (!timings)
goto out; return -EINVAL;
ret = -ENOMEM; ret = -ENOMEM;
info->modes = kmalloc_array(timings->num_timings, info->modes = kmalloc_array(timings->num_timings,
...@@ -2186,6 +2186,7 @@ static int of_get_pxafb_mode_info(struct device *dev, ...@@ -2186,6 +2186,7 @@ static int of_get_pxafb_mode_info(struct device *dev,
ret = of_property_read_u32(np, "bus-width", &bus_width); ret = of_property_read_u32(np, "bus-width", &bus_width);
if (ret) { if (ret) {
dev_err(dev, "no bus-width specified: %d\n", ret); dev_err(dev, "no bus-width specified: %d\n", ret);
of_node_put(np);
return ret; return ret;
} }
......
...@@ -83,7 +83,7 @@ static const char *s1d13xxxfb_prod_names[] = { ...@@ -83,7 +83,7 @@ static const char *s1d13xxxfb_prod_names[] = {
/* /*
* here we define the default struct fb_fix_screeninfo * here we define the default struct fb_fix_screeninfo
*/ */
static struct fb_fix_screeninfo s1d13xxxfb_fix = { static const struct fb_fix_screeninfo s1d13xxxfb_fix = {
.id = S1D_FBID, .id = S1D_FBID,
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_PSEUDOCOLOR, .visual = FB_VISUAL_PSEUDOCOLOR,
...@@ -929,7 +929,7 @@ static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state) ...@@ -929,7 +929,7 @@ static int s1d13xxxfb_suspend(struct platform_device *dev, pm_message_t state)
s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL); s1dfb->disp_save = kmalloc(info->fix.smem_len, GFP_KERNEL);
if (!s1dfb->disp_save) { if (!s1dfb->disp_save) {
printk(KERN_ERR PFX "no memory to save screen"); printk(KERN_ERR PFX "no memory to save screen\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -767,7 +767,7 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) ...@@ -767,7 +767,7 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
static int s3c2410fb_cpufreq_transition(struct notifier_block *nb, static int s3c2410fb_cpufreq_transition(struct notifier_block *nb,
unsigned long val, void *data) unsigned long val, void *data)
......
...@@ -32,7 +32,7 @@ struct s3c2410fb_info { ...@@ -32,7 +32,7 @@ struct s3c2410fb_info {
unsigned long clk_rate; unsigned long clk_rate;
unsigned int palette_ready; unsigned int palette_ready;
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_ARM_S3C24XX_CPUFREQ
struct notifier_block freq_transition; struct notifier_block freq_transition;
#endif #endif
......
...@@ -1660,7 +1660,7 @@ static struct fb_ops savagefb_ops = { ...@@ -1660,7 +1660,7 @@ static struct fb_ops savagefb_ops = {
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
static struct fb_var_screeninfo savagefb_var800x600x8 = { static const struct fb_var_screeninfo savagefb_var800x600x8 = {
.accel_flags = FB_ACCELF_TEXT, .accel_flags = FB_ACCELF_TEXT,
.xres = 800, .xres = 800,
.yres = 600, .yres = 600,
......
...@@ -33,14 +33,14 @@ ...@@ -33,14 +33,14 @@
#include <linux/parser.h> #include <linux/parser.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
static struct fb_fix_screeninfo simplefb_fix = { static const struct fb_fix_screeninfo simplefb_fix = {
.id = "simple", .id = "simple",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_TRUECOLOR, .visual = FB_VISUAL_TRUECOLOR,
.accel = FB_ACCEL_NONE, .accel = FB_ACCEL_NONE,
}; };
static struct fb_var_screeninfo simplefb_var = { static const struct fb_var_screeninfo simplefb_var = {
.height = -1, .height = -1,
.width = -1, .width = -1,
.activate = FB_ACTIVATE_NOW, .activate = FB_ACTIVATE_NOW,
...@@ -74,8 +74,14 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -74,8 +74,14 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
return 0; return 0;
} }
struct simplefb_par;
static void simplefb_clocks_destroy(struct simplefb_par *par);
static void simplefb_regulators_destroy(struct simplefb_par *par);
static void simplefb_destroy(struct fb_info *info) static void simplefb_destroy(struct fb_info *info)
{ {
simplefb_regulators_destroy(info->par);
simplefb_clocks_destroy(info->par);
if (info->screen_base) if (info->screen_base)
iounmap(info->screen_base); iounmap(info->screen_base);
} }
...@@ -487,11 +493,8 @@ static int simplefb_probe(struct platform_device *pdev) ...@@ -487,11 +493,8 @@ static int simplefb_probe(struct platform_device *pdev)
static int simplefb_remove(struct platform_device *pdev) static int simplefb_remove(struct platform_device *pdev)
{ {
struct fb_info *info = platform_get_drvdata(pdev); struct fb_info *info = platform_get_drvdata(pdev);
struct simplefb_par *par = info->par;
unregister_framebuffer(info); unregister_framebuffer(info);
simplefb_regulators_destroy(par);
simplefb_clocks_destroy(par);
framebuffer_release(info); framebuffer_release(info);
return 0; return 0;
......
...@@ -56,7 +56,7 @@ struct smtcfb_info { ...@@ -56,7 +56,7 @@ struct smtcfb_info {
void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */ void __iomem *smtc_regbaseaddress; /* Memory Map IO starting address */
static struct fb_var_screeninfo smtcfb_var = { static const struct fb_var_screeninfo smtcfb_var = {
.xres = 1024, .xres = 1024,
.yres = 600, .yres = 600,
.xres_virtual = 1024, .xres_virtual = 1024,
......
...@@ -1761,10 +1761,8 @@ static int ufx_usb_probe(struct usb_interface *interface, ...@@ -1761,10 +1761,8 @@ static int ufx_usb_probe(struct usb_interface *interface,
static void ufx_usb_disconnect(struct usb_interface *interface) static void ufx_usb_disconnect(struct usb_interface *interface)
{ {
struct ufx_data *dev; struct ufx_data *dev;
struct fb_info *info;
dev = usb_get_intfdata(interface); dev = usb_get_intfdata(interface);
info = dev->info;
pr_debug("USB disconnect starting\n"); pr_debug("USB disconnect starting\n");
......
此差异已折叠。
此差异已折叠。
...@@ -33,7 +33,7 @@ static struct cb_id uvesafb_cn_id = { ...@@ -33,7 +33,7 @@ static struct cb_id uvesafb_cn_id = {
static char v86d_path[PATH_MAX] = "/sbin/v86d"; static char v86d_path[PATH_MAX] = "/sbin/v86d";
static char v86d_started; /* has v86d been started by uvesafb? */ static char v86d_started; /* has v86d been started by uvesafb? */
static struct fb_fix_screeninfo uvesafb_fix = { static const struct fb_fix_screeninfo uvesafb_fix = {
.id = "VESA VGA", .id = "VESA VGA",
.type = FB_TYPE_PACKED_PIXELS, .type = FB_TYPE_PACKED_PIXELS,
.accel = FB_ACCEL_NONE, .accel = FB_ACCEL_NONE,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册