Commit b239499f authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-misc-next-2018-11-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-next



drm-misc-next for v4.21, part 2:

UAPI Changes:
- Remove syncobj timeline support from drm.

Cross-subsystem Changes:
- Document canvas provider node in the DT bindings.
- Improve documentation for TPO TPG110 DT bindings.

Core Changes:
- Use explicit state in drm atomic functions.
- Add panel quirk for new GPD Win2 firmware.
- Add DRM_FORMAT_XYUV8888.
- Set the default import/export function in prime to drm_gem_prime_import/export.
- Add a separate drm_gem_object_funcs, to stop relying on dev->driver->*gem* functions.
- Make sure that tinydrm sets the virtual address also on imported buffers.

Driver Changes:
- Support active-low data enable signal in sun4i.
- Fix scaling in vc4.
- Use canvas provider node in meson.
- Remove unused variables in sti and qxl and cirrus.
- Add overlay plane support and primary plane scaling to meson.
- i2c fixes in drm/bridge/sii902x
- Fix mailbox read size in rockchip.
- Spelling fix in panel/s6d16d0.
- Remove unnecessary null check from qxl_bo_unref.
- Remove unused arguments from qxl_bo_pin.
- Fix qxl cursor pinning.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/9c0409e3-a85f-d2af-b4eb-baf1eb8bbae4@linux.intel.com
parents 9235dd44 0081cdfe
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -67,6 +67,8 @@ Required properties:
Optional properties:
- power-domains: Optional phandle to associated power domain as described in
	the file ../power/power_domain.txt
- amlogic,canvas: phandle to canvas provider node as described in the file
	../soc/amlogic/amlogic,canvas.txt

Required nodes:

+52 −29
Original line number Diff line number Diff line
TPO TPG110 Panel
================

This binding builds on the DPI bindings, adding a few properties
as a superset of a DPI. See panel-dpi.txt for the required DPI
bindings.
This panel driver is a component that acts as an intermediary
between an RGB output and a variety of panels. The panel
driver is strapped up in electronics to the desired resolution
and other properties, and has a control interface over 3WIRE
SPI. By talking to the TPG110 over SPI, the strapped properties
can be discovered and the hardware is therefore mostly
self-describing.

       +--------+
SPI -> |  TPO   | -> physical display
RGB -> | TPG110 |
       +--------+

If some electrical strap or alternate resolution is desired,
this can be set up by taking software control of the display
over the SPI interface. The interface can also adjust
for properties of the display such as gamma correction and
certain electrical driving levels.

The TPG110 does not know the physical dimensions of the panel
connected, so this needs to be specified in the device tree.

It requires a GPIO line for control of its reset line.

The serial protocol has line names that resemble I2C but the
protocol is not I2C but 3WIRE SPI.

Required properties:
- compatible : "tpo,tpg110"
- compatible : one of:
  "ste,nomadik-nhk15-display", "tpo,tpg110"
  "tpo,tpg110"
- grestb-gpios : panel reset GPIO
- scen-gpios : serial control enable GPIO
- scl-gpios : serial control clock line GPIO
- sda-gpios : serial control data line GPIO
- width-mm : see display/panel/panel-common.txt
- height-mm : see display/panel/panel-common.txt

The device needs to be a child of an SPI bus, see
spi/spi-bus.txt. The SPI child must set the following
properties:
- spi-3wire
- spi-max-frequency = <3000000>;
as these are characteristics of this device.

Required nodes:
- Video port for DPI input, see panel-dpi.txt
- Panel timing for DPI setup, see panel-dpi.txt
The device node can contain one 'port' child node with one child
'endpoint' node, according to the bindings defined in
media/video-interfaces.txt. This node should describe panel's video bus.

Example
-------

panel {
	compatible = "tpo,tpg110", "panel-dpi";
	grestb-gpios = <&stmpe_gpio44 5 GPIO_ACTIVE_LOW>;
	scen-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
	scl-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
	sda-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
panel: display@0 {
	compatible = "tpo,tpg110";
	reg = <0>;
	spi-3wire;
	/* 320 ns min period ~= 3 MHz */
	spi-max-frequency = <3000000>;
	/* Width and height from data sheet */
	width-mm = <116>;
	height-mm = <87>;
	grestb-gpios = <&foo_gpio 5 GPIO_ACTIVE_LOW>;
	backlight = <&bl>;

	port {
		nomadik_clcd_panel: endpoint {
			remote-endpoint = <&nomadik_clcd_pads>;
			remote-endpoint = <&foo>;
		};
	};

	panel-timing {
		clock-frequency = <33200000>;
		hactive = <800>;
		hback-porch = <216>;
		hfront-porch = <40>;
		hsync-len = <1>;
		vactive = <480>;
		vback-porch = <35>;
		vfront-porch = <10>;
		vsync-len = <1>;
	};
};
+13 −0
Original line number Diff line number Diff line
@@ -234,6 +234,19 @@ efficient.

Contact: Daniel Vetter

Defaults for .gem_prime_import and export
-----------------------------------------

Most drivers don't need to set drm_driver->gem_prime_import and
->gem_prime_export now that drm_gem_prime_import() and drm_gem_prime_export()
are the default.

struct drm_gem_object_funcs
---------------------------

GEM objects can now have a function table instead of having the callbacks on the
DRM driver struct. This is now the preferred way and drivers can be moved over.

Core refactorings
=================

+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ config DRM_SII902X
	depends on OF
	select DRM_KMS_HELPER
	select REGMAP_I2C
	select I2C_MUX
	---help---
	  Silicon Image sii902x bridge chip driver.

+178 −69
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 Renesas Electronics
 *
 * Copyright (C) 2016 Atmel
 *		      Bo Shen <voice.shen@atmel.com>
 *
@@ -21,6 +23,7 @@
 */

#include <linux/gpio/consumer.h>
#include <linux/i2c-mux.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/regmap.h>
@@ -86,8 +89,49 @@ struct sii902x {
	struct drm_bridge bridge;
	struct drm_connector connector;
	struct gpio_desc *reset_gpio;
	struct i2c_mux_core *i2cmux;
};

static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val)
{
	union i2c_smbus_data data;
	int ret;

	ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
			       I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data);

	if (ret < 0)
		return ret;

	*val = data.byte;
	return 0;
}

static int sii902x_write_unlocked(struct i2c_client *i2c, u8 reg, u8 val)
{
	union i2c_smbus_data data;

	data.byte = val;

	return __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
				I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA,
				&data);
}

static int sii902x_update_bits_unlocked(struct i2c_client *i2c, u8 reg, u8 mask,
					u8 val)
{
	int ret;
	u8 status;

	ret = sii902x_read_unlocked(i2c, reg, &status);
	if (ret)
		return ret;
	status &= ~mask;
	status |= val & mask;
	return sii902x_write_unlocked(i2c, reg, status);
}

static inline struct sii902x *bridge_to_sii902x(struct drm_bridge *bridge)
{
	return container_of(bridge, struct sii902x, bridge);
@@ -135,41 +179,11 @@ static const struct drm_connector_funcs sii902x_connector_funcs = {
static int sii902x_get_modes(struct drm_connector *connector)
{
	struct sii902x *sii902x = connector_to_sii902x(connector);
	struct regmap *regmap = sii902x->regmap;
	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
	struct device *dev = &sii902x->i2c->dev;
	unsigned long timeout;
	unsigned int retries;
	unsigned int status;
	struct edid *edid;
	int num = 0;
	int ret;
	int num = 0, ret;

	ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
				 SII902X_SYS_CTRL_DDC_BUS_REQ,
				 SII902X_SYS_CTRL_DDC_BUS_REQ);
	if (ret)
		return ret;

	timeout = jiffies +
		  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
	do {
		ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
		if (ret)
			return ret;
	} while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
		 time_before(jiffies, timeout));

	if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
		dev_err(dev, "failed to acquire the i2c bus\n");
		return -ETIMEDOUT;
	}

	ret = regmap_write(regmap, SII902X_SYS_CTRL_DATA, status);
	if (ret)
		return ret;

	edid = drm_get_edid(connector, sii902x->i2c->adapter);
	edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
	drm_connector_update_edid_property(connector, edid);
	if (edid) {
		num = drm_add_edid_modes(connector, edid);
@@ -181,42 +195,6 @@ static int sii902x_get_modes(struct drm_connector *connector)
	if (ret)
		return ret;

	/*
	 * Sometimes the I2C bus can stall after failure to use the
	 * EDID channel. Retry a few times to see if things clear
	 * up, else continue anyway.
	 */
	retries = 5;
	do {
		ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA,
				  &status);
		retries--;
	} while (ret && retries);
	if (ret)
		dev_err(dev, "failed to read status (%d)\n", ret);

	ret = regmap_update_bits(regmap, SII902X_SYS_CTRL_DATA,
				 SII902X_SYS_CTRL_DDC_BUS_REQ |
				 SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
	if (ret)
		return ret;

	timeout = jiffies +
		  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
	do {
		ret = regmap_read(regmap, SII902X_SYS_CTRL_DATA, &status);
		if (ret)
			return ret;
	} while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
			   SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
		 time_before(jiffies, timeout));

	if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
		      SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
		dev_err(dev, "failed to release the i2c bus\n");
		return -ETIMEDOUT;
	}

	return num;
}

@@ -366,6 +344,121 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
	return IRQ_HANDLED;
}

/*
 * The purpose of sii902x_i2c_bypass_select is to enable the pass through
 * mode of the HDMI transmitter. Do not use regmap from within this function,
 * only use sii902x_*_unlocked functions to read/modify/write registers.
 * We are holding the parent adapter lock here, keep this in mind before
 * adding more i2c transactions.
 *
 * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
 * in this driver, we need to make sure that we only touch 0x1A[2:1] from
 * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
 * we leave the remaining bits as we have found them.
 */
static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
{
	struct sii902x *sii902x = i2c_mux_priv(mux);
	struct device *dev = &sii902x->i2c->dev;
	unsigned long timeout;
	u8 status;
	int ret;

	ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
					   SII902X_SYS_CTRL_DDC_BUS_REQ,
					   SII902X_SYS_CTRL_DDC_BUS_REQ);
	if (ret)
		return ret;

	timeout = jiffies +
		  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
	do {
		ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
					    &status);
		if (ret)
			return ret;
	} while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
		 time_before(jiffies, timeout));

	if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
		dev_err(dev, "Failed to acquire the i2c bus\n");
		return -ETIMEDOUT;
	}

	return sii902x_write_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
				      status);
}

/*
 * The purpose of sii902x_i2c_bypass_deselect is to disable the pass through
 * mode of the HDMI transmitter. Do not use regmap from within this function,
 * only use sii902x_*_unlocked functions to read/modify/write registers.
 * We are holding the parent adapter lock here, keep this in mind before
 * adding more i2c transactions.
 *
 * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
 * in this driver, we need to make sure that we only touch 0x1A[2:1] from
 * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
 * we leave the remaining bits as we have found them.
 */
static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
{
	struct sii902x *sii902x = i2c_mux_priv(mux);
	struct device *dev = &sii902x->i2c->dev;
	unsigned long timeout;
	unsigned int retries;
	u8 status;
	int ret;

	/*
	 * When the HDMI transmitter is in pass through mode, we need an
	 * (undocumented) additional delay between STOP and START conditions
	 * to guarantee the bus won't get stuck.
	 */
	udelay(30);

	/*
	 * Sometimes the I2C bus can stall after failure to use the
	 * EDID channel. Retry a few times to see if things clear
	 * up, else continue anyway.
	 */
	retries = 5;
	do {
		ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
					    &status);
		retries--;
	} while (ret && retries);
	if (ret) {
		dev_err(dev, "failed to read status (%d)\n", ret);
		return ret;
	}

	ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
					   SII902X_SYS_CTRL_DDC_BUS_REQ |
					   SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
	if (ret)
		return ret;

	timeout = jiffies +
		  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
	do {
		ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
					    &status);
		if (ret)
			return ret;
	} while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
			   SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
		 time_before(jiffies, timeout));

	if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
		      SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
		dev_err(dev, "failed to release the i2c bus\n");
		return -ETIMEDOUT;
	}

	return 0;
}

static int sii902x_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
@@ -375,6 +468,13 @@ static int sii902x_probe(struct i2c_client *client,
	u8 chipid[4];
	int ret;

	ret = i2c_check_functionality(client->adapter,
				      I2C_FUNC_SMBUS_BYTE_DATA);
	if (!ret) {
		dev_err(dev, "I2C adapter not suitable\n");
		return -EIO;
	}

	sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL);
	if (!sii902x)
		return -ENOMEM;
@@ -433,7 +533,15 @@ static int sii902x_probe(struct i2c_client *client,

	i2c_set_clientdata(client, sii902x);

	return 0;
	sii902x->i2cmux = i2c_mux_alloc(client->adapter, dev,
					1, 0, I2C_MUX_GATE,
					sii902x_i2c_bypass_select,
					sii902x_i2c_bypass_deselect);
	if (!sii902x->i2cmux)
		return -ENOMEM;

	sii902x->i2cmux->priv = sii902x;
	return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
}

static int sii902x_remove(struct i2c_client *client)
@@ -441,6 +549,7 @@ static int sii902x_remove(struct i2c_client *client)
{
	struct sii902x *sii902x = i2c_get_clientdata(client);

	i2c_mux_del_adapters(sii902x->i2cmux);
	drm_bridge_remove(&sii902x->bridge);

	return 0;
Loading