Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 084165a3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
  ...
parents ef6000b4 c456a2f3
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -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/
+0 −2
Original line number Diff line number Diff line
@@ -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
+5 −2
Original line number Diff line number Diff line
@@ -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
+1 −2
Original line number Diff line number Diff line
@@ -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
+259 −0
Original line number Diff line number Diff line
#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);
Loading