You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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()
...
This commit is contained in:
-12
@@ -4775,15 +4775,6 @@ L: iommu@lists.linux-foundation.org
|
||||
S: Maintained
|
||||
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
|
||||
M: Noam Camus <noamc@ezchip.com>
|
||||
S: Supported
|
||||
@@ -4962,12 +4953,9 @@ F: drivers/net/wan/dlci.c
|
||||
F: drivers/net/wan/sdla.c
|
||||
|
||||
FRAMEBUFFER LAYER
|
||||
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
|
||||
M: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
W: http://linux-fbdev.sourceforge.net/
|
||||
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
|
||||
F: Documentation/fb/
|
||||
F: drivers/video/
|
||||
|
||||
@@ -168,8 +168,6 @@ CONFIG_DRM_PANEL_SAMSUNG_LD9040=y
|
||||
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=y
|
||||
CONFIG_DRM_NXP_PTN3460=y
|
||||
CONFIG_DRM_PARADE_PS8622=y
|
||||
CONFIG_EXYNOS_VIDEO=y
|
||||
CONFIG_EXYNOS_MIPI_DSI=y
|
||||
CONFIG_LCD_CLASS_DEVICE=y
|
||||
CONFIG_LCD_PLATFORM=y
|
||||
CONFIG_BACKLIGHT_PWM=y
|
||||
|
||||
@@ -284,12 +284,14 @@ config FB_PM2_FIFO_DISCONNECT
|
||||
config FB_ARMCLCD
|
||||
tristate "ARM PrimeCell PL110 support"
|
||||
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_COPYAREA
|
||||
select FB_CFB_IMAGEBLIT
|
||||
select FB_MODE_HELPERS if OF
|
||||
select VIDEOMODE_HELPERS if OF
|
||||
select BACKLIGHT_LCD_SUPPORT if OF
|
||||
select BACKLIGHT_CLASS_DEVICE if OF
|
||||
help
|
||||
This framebuffer device driver is for the ARM PrimeCell PL110
|
||||
Colour LCD controller. ARM PrimeCells provide the building
|
||||
@@ -305,6 +307,8 @@ config PLAT_VERSATILE_CLCD
|
||||
def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR
|
||||
depends on ARM
|
||||
depends on FB_ARMCLCD && FB=y
|
||||
select REGMAP
|
||||
select MFD_SYSCON
|
||||
|
||||
config FB_ACORN
|
||||
bool "Acorn VIDC support"
|
||||
@@ -2443,7 +2447,6 @@ config FB_SIMPLE
|
||||
|
||||
source "drivers/video/fbdev/omap/Kconfig"
|
||||
source "drivers/video/fbdev/omap2/Kconfig"
|
||||
source "drivers/video/fbdev/exynos/Kconfig"
|
||||
source "drivers/video/fbdev/mmp/Kconfig"
|
||||
|
||||
config FB_SH_MOBILE_MERAM
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
|
||||
obj-y += core/
|
||||
|
||||
obj-$(CONFIG_EXYNOS_VIDEO) += exynos/
|
||||
|
||||
obj-$(CONFIG_FB_MACMODES) += macmodes.o
|
||||
obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
|
||||
|
||||
@@ -79,6 +77,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o
|
||||
obj-$(CONFIG_FB_PVR2) += pvr2fb.o
|
||||
obj-$(CONFIG_FB_VOODOO1) += sstfb.o
|
||||
obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o
|
||||
obj-$(CONFIG_ARCH_NOMADIK) += amba-clcd-nomadik.o
|
||||
obj-$(CONFIG_PLAT_VERSATILE_CLCD) += amba-clcd-versatile.o
|
||||
obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o
|
||||
obj-$(CONFIG_FB_68328) += 68328fb.o
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
#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);
|
||||
@@ -0,0 +1,24 @@
|
||||
#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 @@
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/clcd.h>
|
||||
#include <linux/platform_data/video-clcd-versatile.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/bitops.h>
|
||||
#include "amba-clcd-versatile.h"
|
||||
|
||||
static struct clcd_panel vga = {
|
||||
.mode = {
|
||||
@@ -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,
|
||||
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
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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
|
||||
+176
-14
@@ -30,10 +30,14 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <video/display_timing.h>
|
||||
#include <video/of_display_timing.h>
|
||||
#include <video/videomode.h>
|
||||
|
||||
#include "amba-clcd-nomadik.h"
|
||||
#include "amba-clcd-versatile.h"
|
||||
|
||||
#define to_clcd(info) container_of(info, struct clcd_fb, fb)
|
||||
|
||||
/* This is limited to 16 characters when displayed by X startup */
|
||||
@@ -71,6 +75,11 @@ static void clcdfb_disable(struct clcd_fb *fb)
|
||||
if (fb->board->disable)
|
||||
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);
|
||||
if (val & CNTL_LCDPWR) {
|
||||
val &= ~CNTL_LCDPWR;
|
||||
@@ -116,6 +125,14 @@ static void clcdfb_enable(struct clcd_fb *fb, u32 cntl)
|
||||
cntl |= CNTL_LCDPWR;
|
||||
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.
|
||||
*/
|
||||
@@ -211,6 +228,15 @@ clcdfb_set_bitfields(struct clcd_fb *fb, struct fb_var_screeninfo *var)
|
||||
var->blue.length = 4;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if (fb->vendor->packed_24_bit_pixels) {
|
||||
var->red.length = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
/* If we can't do 888, reject */
|
||||
caps &= CLCD_CAP_888;
|
||||
@@ -297,6 +323,12 @@ static int clcdfb_set_par(struct fb_info *info)
|
||||
|
||||
clcdfb_disable(fb);
|
||||
|
||||
/* Some variants must be clocked here */
|
||||
if (fb->vendor->clock_timregs && !fb->clk_enabled) {
|
||||
fb->clk_enabled = true;
|
||||
clk_enable(fb->clk);
|
||||
}
|
||||
|
||||
writel(regs.tim0, fb->regs + CLCD_TIM0);
|
||||
writel(regs.tim1, fb->regs + CLCD_TIM1);
|
||||
writel(regs.tim2, fb->regs + CLCD_TIM2);
|
||||
@@ -551,7 +583,7 @@ static int clcdfb_register(struct clcd_fb *fb)
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
|
||||
struct fb_videomode *mode)
|
||||
struct clcd_panel *clcd_panel)
|
||||
{
|
||||
int err;
|
||||
struct display_timing timing;
|
||||
@@ -563,10 +595,31 @@ static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
|
||||
|
||||
videomode_from_timing(&timing, &video);
|
||||
|
||||
err = fb_videomode_from_videomode(&video, mode);
|
||||
err = fb_videomode_from_videomode(&video, &clcd_panel->mode);
|
||||
if (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;
|
||||
}
|
||||
|
||||
@@ -576,11 +629,34 @@ static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
|
||||
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,
|
||||
struct fb_videomode *mode)
|
||||
struct clcd_panel *clcd_panel)
|
||||
{
|
||||
int err;
|
||||
struct device_node *panel;
|
||||
struct fb_videomode *mode;
|
||||
char *name;
|
||||
int len;
|
||||
|
||||
@@ -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 */
|
||||
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
|
||||
err = -ENOENT;
|
||||
if (err)
|
||||
return err;
|
||||
mode = &clcd_panel->mode;
|
||||
|
||||
len = clcdfb_snprintf_mode(NULL, 0, mode);
|
||||
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)
|
||||
} panels[] = {
|
||||
{ 0x110, 1, 7, 13, CLCD_CAP_5551 },
|
||||
{ 0x110, 0, 8, 16, CLCD_CAP_888 },
|
||||
{ 0x110, 16, 8, 0, CLCD_CAP_888 },
|
||||
{ 0x111, 4, 14, 20, CLCD_CAP_444 },
|
||||
{ 0x111, 3, 11, 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)
|
||||
};
|
||||
int i;
|
||||
|
||||
/* Bypass pixel clock divider, data output on the falling edge */
|
||||
fb->panel->tim2 = TIM2_BCD | TIM2_IPC;
|
||||
/* Bypass pixel clock divider */
|
||||
fb->panel->tim2 |= TIM2_BCD;
|
||||
|
||||
/* TFT display, vert. comp. interrupt at the start of the back porch */
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -658,11 +779,24 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
|
||||
if (!fb->panel)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* Fetch the panel endpoint.
|
||||
*/
|
||||
endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL);
|
||||
if (!endpoint)
|
||||
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)
|
||||
return err;
|
||||
|
||||
@@ -693,11 +827,11 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
|
||||
|
||||
if (of_property_read_u32_array(endpoint,
|
||||
"arm,pl11x,tft-r0g0b0-pads",
|
||||
tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) == 0)
|
||||
return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
|
||||
tft_r0b0g0[1], tft_r0b0g0[2]);
|
||||
tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) != 0)
|
||||
return -ENOENT;
|
||||
|
||||
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)
|
||||
@@ -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)
|
||||
{
|
||||
struct clcd_board *board = dev_get_platdata(&dev->dev);
|
||||
struct clcd_vendor_data *vendor = id->data;
|
||||
struct clcd_fb *fb;
|
||||
int ret;
|
||||
|
||||
@@ -827,6 +962,12 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
if (!board)
|
||||
return -EINVAL;
|
||||
|
||||
if (vendor->init_board) {
|
||||
ret = vendor->init_board(dev, board);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dma_set_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
goto out;
|
||||
@@ -845,17 +986,18 @@ static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
}
|
||||
|
||||
fb->dev = dev;
|
||||
fb->vendor = vendor;
|
||||
fb->board = board;
|
||||
|
||||
dev_info(&fb->dev->dev, "PL%03x rev%u at 0x%08llx\n",
|
||||
amba_part(dev), amba_rev(dev),
|
||||
dev_info(&fb->dev->dev, "PL%03x designer %02x rev%u at 0x%08llx\n",
|
||||
amba_part(dev), amba_manf(dev), amba_rev(dev),
|
||||
(unsigned long long)dev->res.start);
|
||||
|
||||
ret = fb->board->setup(fb);
|
||||
if (ret)
|
||||
goto free_fb;
|
||||
|
||||
ret = clcdfb_register(fb);
|
||||
ret = clcdfb_register(fb);
|
||||
if (ret == 0) {
|
||||
amba_set_drvdata(dev, fb);
|
||||
goto out;
|
||||
@@ -891,10 +1033,30 @@ static int clcdfb_remove(struct amba_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clcd_vendor_data vendor_arm = {
|
||||
/* Sets up the versatile board displays */
|
||||
.init_panel = versatile_clcd_init_panel,
|
||||
};
|
||||
|
||||
static struct clcd_vendor_data vendor_nomadik = {
|
||||
.clock_timregs = true,
|
||||
.packed_24_bit_pixels = true,
|
||||
.st_bitmux_control = true,
|
||||
.init_board = nomadik_clcd_init_board,
|
||||
.init_panel = nomadik_clcd_init_panel,
|
||||
};
|
||||
|
||||
static struct amba_id clcdfb_id_table[] = {
|
||||
{
|
||||
.id = 0x00041110,
|
||||
.mask = 0x000ffffe,
|
||||
.data = &vendor_arm,
|
||||
},
|
||||
/* ST Electronics Nomadik variant */
|
||||
{
|
||||
.id = 0x00180110,
|
||||
.mask = 0x00fffffe,
|
||||
.data = &vendor_nomadik,
|
||||
},
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ struct arcfb_par {
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo arcfb_fix = {
|
||||
static const struct fb_fix_screeninfo arcfb_fix = {
|
||||
.id = "arcfb",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_MONO01,
|
||||
@@ -89,7 +89,7 @@ static struct fb_fix_screeninfo arcfb_fix = {
|
||||
.accel = FB_ACCEL_NONE,
|
||||
};
|
||||
|
||||
static struct fb_var_screeninfo arcfb_var = {
|
||||
static const struct fb_var_screeninfo arcfb_var = {
|
||||
.xres = 128,
|
||||
.yres = 64,
|
||||
.xres_virtual = 128,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
static struct fb_fix_screeninfo asiliantfb_fix = {
|
||||
static const struct fb_fix_screeninfo asiliantfb_fix = {
|
||||
.id = "Asiliant 69000",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
@@ -483,7 +483,7 @@ static struct fb_fix_screeninfo asiliantfb_fix = {
|
||||
.smem_len = 0x200000, /* 2MB */
|
||||
};
|
||||
|
||||
static struct fb_var_screeninfo asiliantfb_var = {
|
||||
static const struct fb_var_screeninfo asiliantfb_var = {
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.xres_virtual = 640,
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
#ifndef CONFIG_PPC_PMAC
|
||||
/* 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) */
|
||||
640, 480, 640, 480, 0, 0, 8, 0,
|
||||
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
|
||||
@@ -104,7 +104,7 @@ static struct fb_var_screeninfo default_var = {
|
||||
#else /* CONFIG_PPC_PMAC */
|
||||
/* default to 1024x768 at 75Hz on PPC - this will work
|
||||
* 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) */
|
||||
1024, 768, 1024, 768, 0, 0, 8, 0,
|
||||
{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
|
||||
@@ -375,7 +375,7 @@ static const struct aty128_meminfo 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",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
|
||||
@@ -212,7 +212,7 @@ struct pci_mmap_map {
|
||||
unsigned long prot_mask;
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo atyfb_fix = {
|
||||
static const struct fb_fix_screeninfo atyfb_fix = {
|
||||
.id = "ATY Mach64",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include "../edid.h"
|
||||
|
||||
static struct fb_var_screeninfo radeonfb_default_var = {
|
||||
static const struct fb_var_screeninfo radeonfb_default_var = {
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.xres_virtual = 640,
|
||||
|
||||
@@ -375,7 +375,6 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
{
|
||||
int ret = 0;
|
||||
struct proc_dir_entry *entry;
|
||||
int num_modes = ARRAY_SIZE(known_modes);
|
||||
|
||||
struct adv7393fb_device *fbdev = NULL;
|
||||
|
||||
@@ -384,7 +383,7 @@ static int bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode > num_modes) {
|
||||
if (mode >= ARRAY_SIZE(known_modes)) {
|
||||
dev_err(&client->dev, "mode %d: not supported", mode);
|
||||
return -EFAULT;
|
||||
}
|
||||
@@ -797,7 +796,7 @@ static struct i2c_driver bfin_adv7393_fb_driver = {
|
||||
|
||||
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");
|
||||
#else
|
||||
request_module("i2c-gpio");
|
||||
|
||||
@@ -50,9 +50,9 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
|
||||
return 1;
|
||||
|
||||
if (regno < 16) {
|
||||
red >>= 8;
|
||||
green >>= 8;
|
||||
blue >>= 8;
|
||||
red >>= 16 - info->var.red.length;
|
||||
green >>= 16 - info->var.green.length;
|
||||
blue >>= 16 - info->var.blue.length;
|
||||
((u32 *)(info->pseudo_palette))[regno] =
|
||||
(red << info->var.red.offset) |
|
||||
(green << info->var.green.offset) |
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
@@ -1,9 +0,0 @@
|
||||
#
|
||||
# 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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user