-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'fbdev-4.9' of git://git.kernel.org/pub/scm/linux/kernel/gi…
…t/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() ...
- Loading branch information
Showing
59 changed files
with
1,042 additions
and
3,916 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 */ |
Oops, something went wrong.