All of lore.kernel.org
 help / color / mirror / Atom feed
From: s.hauer@pengutronix.de (Sascha Hauer)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 4/5] DRM: Add support for the sii902x HDMI/DVI encoder
Date: Tue,  7 Jun 2011 12:45:49 +0200	[thread overview]
Message-ID: <1307443550-25549-5-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1307443550-25549-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/Kconfig       |    6 +
 drivers/gpu/drm/i2c/Makefile  |    3 +
 drivers/gpu/drm/i2c/sii902x.c |  334 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/i2c/sii902x.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index bcd9a27..01d5444 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -166,6 +166,12 @@ config DRM_SAVAGE
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  chipset. If M is selected the module will be called savage.
 
+config DRM_I2C_SII902X
+	tristate "sii902x"
+	depends on DRM && I2C
+	help
+	  Support for sii902x DVI/HDMI encoder chips
+
 config DRM_IMX_IPUV3
 	tristate "i.MX IPUv3"
 	depends on DRM && ARCH_MXC
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 9286256..a7a8d40 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 
 sil164-y := sil164_drv.o
 obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
+
+sii902x := sii902x_drv.o
+obj-$(CONFIG_DRM_I2C_SII902X) += sii902x.o
diff --git a/drivers/gpu/drm/i2c/sii902x.c b/drivers/gpu/drm/i2c/sii902x.c
new file mode 100644
index 0000000..7928533
--- /dev/null
+++ b/drivers/gpu/drm/i2c/sii902x.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2010 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_encon.h>
+
+struct sii902x_encoder_params {
+};
+
+struct sii902x_priv {
+	struct sii902x_encoder_params config;
+	struct i2c_client *client;
+	struct drm_encoder_connector encon;
+};
+
+#define to_sii902x(x) container_of(x, struct sii902x_priv, encon)
+
+static int sii902x_write(struct i2c_client *client, uint8_t addr, uint8_t val)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, addr, val);
+	if (ret) {
+		dev_dbg(&client->dev, "%s failed with %d\n", __func__, ret);
+	}
+	return ret;
+}
+
+static uint8_t sii902x_read(struct i2c_client *client, uint8_t addr)
+{
+	int dat;
+
+	dat = i2c_smbus_read_byte_data(client, addr);
+
+	return dat;	
+}
+
+static int hdmi_cap = 0; /* FIXME */
+
+static void sii902x_poweron(struct sii902x_priv *priv)
+{
+	struct i2c_client *client = priv->client;
+
+	/* Turn on DVI or HDMI */
+	if (hdmi_cap)
+		sii902x_write(client, 0x1A, 0x01 | 4);
+	else
+		sii902x_write(client, 0x1A, 0x00);
+
+	return;
+}
+
+static void sii902x_poweroff(struct sii902x_priv *priv)
+{
+	struct i2c_client *client = priv->client;
+	
+	/* disable tmds before changing resolution */
+	if (hdmi_cap)
+		sii902x_write(client, 0x1A, 0x11);
+	else
+		sii902x_write(client, 0x1A, 0x10);
+
+	return;
+}
+
+static int sii902x_get_modes(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+	struct i2c_client *client = priv->client;
+	struct i2c_adapter *adap = client->adapter;
+	struct drm_connector *connector = &encon->connector;
+	struct edid *edid;
+	int ret;
+	int old, dat, cnt = 100;
+
+	old = sii902x_read(client, 0x1A);
+
+	sii902x_write(client, 0x1A, old | 0x4);
+	do {
+		cnt--;
+		msleep(10);
+		dat = sii902x_read(client, 0x1A);
+	} while ((!(dat & 0x2)) && cnt);
+
+	if (!cnt)
+		return -ETIMEDOUT;
+
+	sii902x_write(client, 0x1A, old | 0x06);
+
+	edid = drm_get_edid(connector, adap);
+	if (edid) {
+		drm_mode_connector_update_edid_property(connector, edid);
+		ret = drm_add_edid_modes(connector, edid);
+		connector->display_info.raw_edid = NULL;
+		kfree(edid);
+	}
+
+	cnt = 100;
+	do {
+		cnt--;
+		sii902x_write(client, 0x1A, old & ~0x6);
+		msleep(10);
+		dat = sii902x_read(client, 0x1A);
+	} while ((dat & 0x6) && cnt);
+
+	if (!cnt)
+		ret = -1;
+
+	sii902x_write(client, 0x1A, old);
+
+	return 0;
+}
+
+static irqreturn_t sii902x_detect_handler(int irq, void *data)
+{
+	struct sii902x_priv *priv = data;
+	struct i2c_client *client = priv->client;
+	int dat;
+
+	dat = sii902x_read(client, 0x3D);
+	if (dat & 0x1) {
+		/* cable connection changes */
+		if (dat & 0x4) {
+			printk("plugin\n");
+		} else {
+			printk("plugout\n");
+		}
+	}
+	sii902x_write(client, 0x3D, dat);
+
+	return IRQ_HANDLED;
+}
+
+
+static int sii902x_mode_valid(struct drm_encoder_connector *encon,
+			  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static void sii902x_mode_set(struct drm_encoder_connector *encon,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+	struct i2c_client *client = priv->client;
+	u16 data[4];
+	u32 refresh;
+	u8 *tmp;
+	int i;
+
+	/* Power up */
+	sii902x_write(client, 0x1E, 0x00);
+
+	dev_dbg(&client->dev, "%s: %dx%d, pixclk %d\n", __func__,
+			mode->hdisplay, mode->vdisplay,
+			mode->clock * 1000);
+
+	/* set TPI video mode */
+	data[0] = mode->clock / 10;
+	data[2] = mode->htotal;
+	data[3] = mode->vtotal;
+	refresh = data[2] * data[3];
+	refresh = (mode->clock * 1000) / refresh;
+	data[1] = refresh * 100;
+	tmp = (u8 *)data;
+	for (i = 0; i < 8; i++)
+		sii902x_write(client, i, tmp[i]);
+
+	/* input bus/pixel: full pixel wide (24bit), rising edge */
+	sii902x_write(client, 0x08, 0x70);
+	/* Set input format to RGB */
+	sii902x_write(client, 0x09, 0x00);
+	/* set output format to RGB */
+	sii902x_write(client, 0x0A, 0x00);
+	/* audio setup */
+	sii902x_write(client, 0x25, 0x00);
+	sii902x_write(client, 0x26, 0x40);
+	sii902x_write(client, 0x27, 0x00);
+}
+
+static void sii902x_dpms(struct drm_encoder_connector *encon, int mode)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	if (mode)
+		sii902x_poweroff(priv);
+	else
+		sii902x_poweron(priv);
+}
+
+static void sii902x_prepare(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	sii902x_poweroff(priv);
+}
+
+static void sii902x_commit(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	sii902x_poweron(priv);
+}
+
+struct drm_encoder_connector_funcs sii902x_funcs = {
+	.dpms = sii902x_dpms,
+	.prepare = sii902x_prepare,
+	.commit = sii902x_commit,
+	.get_modes = sii902x_get_modes,
+	.mode_valid = sii902x_mode_valid,
+	.mode_set = sii902x_mode_set,
+};
+
+/* I2C driver functions */
+
+static int
+sii902x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int dat, ret;
+	struct sii902x_priv *priv;
+	const char *drm_name = "imx-drm.0"; /* FIXME: pass from pdata */
+	int encon_id = 0; /* FIXME: pass from pdata */
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+
+	/* Set 902x in hardware TPI mode on and jump out of D3 state */
+	if (sii902x_write(client, 0xc7, 0x00) < 0) {
+		dev_err(&client->dev, "SII902x: cound not find device\n");
+		return -ENODEV;
+	}
+
+	/* read device ID */
+	dat = sii902x_read(client, 0x1b);
+	if (dat != 0xb0) {
+		dev_err(&client->dev, "not found. id is 0x%02x instead of 0xb0\n",
+				dat);
+		return -ENODEV;
+	}
+
+	if (client->irq) {
+		ret = request_threaded_irq(client->irq, NULL, sii902x_detect_handler,
+				IRQF_TRIGGER_FALLING,
+				"SII902x_det", priv);
+		sii902x_write(client, 0x3c, 0x01);
+	}
+
+	priv->encon.funcs = &sii902x_funcs;
+
+	i2c_set_clientdata(client, priv);
+
+	drm_encon_register(drm_name, encon_id, &priv->encon);
+
+	dev_info(&client->dev, "initialized\n");
+
+	return 0;
+}
+
+static int sii902x_remove(struct i2c_client *client)
+{
+	struct sii902x_priv *priv;
+	int ret;
+
+	priv = i2c_get_clientdata(client);
+
+	ret = drm_encon_unregister(&priv->encon);
+	if (ret)
+		return ret;
+
+	kfree(priv);
+
+	return 0;
+}
+
+static struct i2c_device_id sii902x_ids[] = {
+	{ "sii9022", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sii902x_ids);
+
+static struct i2c_driver sii902x_i2c_driver = {
+	.probe = sii902x_probe,
+	.remove = sii902x_remove,
+	.driver = {
+		.name = "sii902x",
+	},
+	.id_table = sii902x_ids,
+};
+
+static int __init sii902x_init(void)
+{
+	return i2c_add_driver(&sii902x_i2c_driver);
+}
+
+static void __exit sii902x_exit(void)
+{
+	i2c_del_driver(&sii902x_i2c_driver);
+}
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("Silicon Image sii902x HDMI transmitter driver");
+MODULE_LICENSE("GPL");
+
+module_init(sii902x_init);
+module_exit(sii902x_exit);
-- 
1.7.5.3

WARNING: multiple messages have this Message-ID (diff)
From: Sascha Hauer <s.hauer@pengutronix.de>
To: linux-arm-kernel@lists.infradead.org
Cc: Konstantinos Margaritis <markos@genesi-usa.com>,
	Eric Miao <eric.miao@linaro.org>, Jason Chen <weitway@gmail.com>,
	DRI mailing list <dri-devel@lists.freedesktop.org>,
	Sascha Hauer <s.hauer@pengutronix.de>
Subject: [PATCH 4/5] DRM: Add support for the sii902x HDMI/DVI encoder
Date: Tue,  7 Jun 2011 12:45:49 +0200	[thread overview]
Message-ID: <1307443550-25549-5-git-send-email-s.hauer@pengutronix.de> (raw)
In-Reply-To: <1307443550-25549-1-git-send-email-s.hauer@pengutronix.de>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/gpu/drm/Kconfig       |    6 +
 drivers/gpu/drm/i2c/Makefile  |    3 +
 drivers/gpu/drm/i2c/sii902x.c |  334 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 343 insertions(+), 0 deletions(-)
 create mode 100644 drivers/gpu/drm/i2c/sii902x.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index bcd9a27..01d5444 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -166,6 +166,12 @@ config DRM_SAVAGE
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  chipset. If M is selected the module will be called savage.
 
+config DRM_I2C_SII902X
+	tristate "sii902x"
+	depends on DRM && I2C
+	help
+	  Support for sii902x DVI/HDMI encoder chips
+
 config DRM_IMX_IPUV3
 	tristate "i.MX IPUv3"
 	depends on DRM && ARCH_MXC
diff --git a/drivers/gpu/drm/i2c/Makefile b/drivers/gpu/drm/i2c/Makefile
index 9286256..a7a8d40 100644
--- a/drivers/gpu/drm/i2c/Makefile
+++ b/drivers/gpu/drm/i2c/Makefile
@@ -5,3 +5,6 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 
 sil164-y := sil164_drv.o
 obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o
+
+sii902x := sii902x_drv.o
+obj-$(CONFIG_DRM_I2C_SII902X) += sii902x.o
diff --git a/drivers/gpu/drm/i2c/sii902x.c b/drivers/gpu/drm/i2c/sii902x.c
new file mode 100644
index 0000000..7928533
--- /dev/null
+++ b/drivers/gpu/drm/i2c/sii902x.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2010 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder_slave.h>
+#include <drm/drm_encon.h>
+
+struct sii902x_encoder_params {
+};
+
+struct sii902x_priv {
+	struct sii902x_encoder_params config;
+	struct i2c_client *client;
+	struct drm_encoder_connector encon;
+};
+
+#define to_sii902x(x) container_of(x, struct sii902x_priv, encon)
+
+static int sii902x_write(struct i2c_client *client, uint8_t addr, uint8_t val)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, addr, val);
+	if (ret) {
+		dev_dbg(&client->dev, "%s failed with %d\n", __func__, ret);
+	}
+	return ret;
+}
+
+static uint8_t sii902x_read(struct i2c_client *client, uint8_t addr)
+{
+	int dat;
+
+	dat = i2c_smbus_read_byte_data(client, addr);
+
+	return dat;	
+}
+
+static int hdmi_cap = 0; /* FIXME */
+
+static void sii902x_poweron(struct sii902x_priv *priv)
+{
+	struct i2c_client *client = priv->client;
+
+	/* Turn on DVI or HDMI */
+	if (hdmi_cap)
+		sii902x_write(client, 0x1A, 0x01 | 4);
+	else
+		sii902x_write(client, 0x1A, 0x00);
+
+	return;
+}
+
+static void sii902x_poweroff(struct sii902x_priv *priv)
+{
+	struct i2c_client *client = priv->client;
+	
+	/* disable tmds before changing resolution */
+	if (hdmi_cap)
+		sii902x_write(client, 0x1A, 0x11);
+	else
+		sii902x_write(client, 0x1A, 0x10);
+
+	return;
+}
+
+static int sii902x_get_modes(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+	struct i2c_client *client = priv->client;
+	struct i2c_adapter *adap = client->adapter;
+	struct drm_connector *connector = &encon->connector;
+	struct edid *edid;
+	int ret;
+	int old, dat, cnt = 100;
+
+	old = sii902x_read(client, 0x1A);
+
+	sii902x_write(client, 0x1A, old | 0x4);
+	do {
+		cnt--;
+		msleep(10);
+		dat = sii902x_read(client, 0x1A);
+	} while ((!(dat & 0x2)) && cnt);
+
+	if (!cnt)
+		return -ETIMEDOUT;
+
+	sii902x_write(client, 0x1A, old | 0x06);
+
+	edid = drm_get_edid(connector, adap);
+	if (edid) {
+		drm_mode_connector_update_edid_property(connector, edid);
+		ret = drm_add_edid_modes(connector, edid);
+		connector->display_info.raw_edid = NULL;
+		kfree(edid);
+	}
+
+	cnt = 100;
+	do {
+		cnt--;
+		sii902x_write(client, 0x1A, old & ~0x6);
+		msleep(10);
+		dat = sii902x_read(client, 0x1A);
+	} while ((dat & 0x6) && cnt);
+
+	if (!cnt)
+		ret = -1;
+
+	sii902x_write(client, 0x1A, old);
+
+	return 0;
+}
+
+static irqreturn_t sii902x_detect_handler(int irq, void *data)
+{
+	struct sii902x_priv *priv = data;
+	struct i2c_client *client = priv->client;
+	int dat;
+
+	dat = sii902x_read(client, 0x3D);
+	if (dat & 0x1) {
+		/* cable connection changes */
+		if (dat & 0x4) {
+			printk("plugin\n");
+		} else {
+			printk("plugout\n");
+		}
+	}
+	sii902x_write(client, 0x3D, dat);
+
+	return IRQ_HANDLED;
+}
+
+
+static int sii902x_mode_valid(struct drm_encoder_connector *encon,
+			  struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static void sii902x_mode_set(struct drm_encoder_connector *encon,
+			 struct drm_display_mode *mode,
+			 struct drm_display_mode *adjusted_mode)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+	struct i2c_client *client = priv->client;
+	u16 data[4];
+	u32 refresh;
+	u8 *tmp;
+	int i;
+
+	/* Power up */
+	sii902x_write(client, 0x1E, 0x00);
+
+	dev_dbg(&client->dev, "%s: %dx%d, pixclk %d\n", __func__,
+			mode->hdisplay, mode->vdisplay,
+			mode->clock * 1000);
+
+	/* set TPI video mode */
+	data[0] = mode->clock / 10;
+	data[2] = mode->htotal;
+	data[3] = mode->vtotal;
+	refresh = data[2] * data[3];
+	refresh = (mode->clock * 1000) / refresh;
+	data[1] = refresh * 100;
+	tmp = (u8 *)data;
+	for (i = 0; i < 8; i++)
+		sii902x_write(client, i, tmp[i]);
+
+	/* input bus/pixel: full pixel wide (24bit), rising edge */
+	sii902x_write(client, 0x08, 0x70);
+	/* Set input format to RGB */
+	sii902x_write(client, 0x09, 0x00);
+	/* set output format to RGB */
+	sii902x_write(client, 0x0A, 0x00);
+	/* audio setup */
+	sii902x_write(client, 0x25, 0x00);
+	sii902x_write(client, 0x26, 0x40);
+	sii902x_write(client, 0x27, 0x00);
+}
+
+static void sii902x_dpms(struct drm_encoder_connector *encon, int mode)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	if (mode)
+		sii902x_poweroff(priv);
+	else
+		sii902x_poweron(priv);
+}
+
+static void sii902x_prepare(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	sii902x_poweroff(priv);
+}
+
+static void sii902x_commit(struct drm_encoder_connector *encon)
+{
+	struct sii902x_priv *priv = to_sii902x(encon);
+
+	sii902x_poweron(priv);
+}
+
+struct drm_encoder_connector_funcs sii902x_funcs = {
+	.dpms = sii902x_dpms,
+	.prepare = sii902x_prepare,
+	.commit = sii902x_commit,
+	.get_modes = sii902x_get_modes,
+	.mode_valid = sii902x_mode_valid,
+	.mode_set = sii902x_mode_set,
+};
+
+/* I2C driver functions */
+
+static int
+sii902x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int dat, ret;
+	struct sii902x_priv *priv;
+	const char *drm_name = "imx-drm.0"; /* FIXME: pass from pdata */
+	int encon_id = 0; /* FIXME: pass from pdata */
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+
+	/* Set 902x in hardware TPI mode on and jump out of D3 state */
+	if (sii902x_write(client, 0xc7, 0x00) < 0) {
+		dev_err(&client->dev, "SII902x: cound not find device\n");
+		return -ENODEV;
+	}
+
+	/* read device ID */
+	dat = sii902x_read(client, 0x1b);
+	if (dat != 0xb0) {
+		dev_err(&client->dev, "not found. id is 0x%02x instead of 0xb0\n",
+				dat);
+		return -ENODEV;
+	}
+
+	if (client->irq) {
+		ret = request_threaded_irq(client->irq, NULL, sii902x_detect_handler,
+				IRQF_TRIGGER_FALLING,
+				"SII902x_det", priv);
+		sii902x_write(client, 0x3c, 0x01);
+	}
+
+	priv->encon.funcs = &sii902x_funcs;
+
+	i2c_set_clientdata(client, priv);
+
+	drm_encon_register(drm_name, encon_id, &priv->encon);
+
+	dev_info(&client->dev, "initialized\n");
+
+	return 0;
+}
+
+static int sii902x_remove(struct i2c_client *client)
+{
+	struct sii902x_priv *priv;
+	int ret;
+
+	priv = i2c_get_clientdata(client);
+
+	ret = drm_encon_unregister(&priv->encon);
+	if (ret)
+		return ret;
+
+	kfree(priv);
+
+	return 0;
+}
+
+static struct i2c_device_id sii902x_ids[] = {
+	{ "sii9022", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sii902x_ids);
+
+static struct i2c_driver sii902x_i2c_driver = {
+	.probe = sii902x_probe,
+	.remove = sii902x_remove,
+	.driver = {
+		.name = "sii902x",
+	},
+	.id_table = sii902x_ids,
+};
+
+static int __init sii902x_init(void)
+{
+	return i2c_add_driver(&sii902x_i2c_driver);
+}
+
+static void __exit sii902x_exit(void)
+{
+	i2c_del_driver(&sii902x_i2c_driver);
+}
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("Silicon Image sii902x HDMI transmitter driver");
+MODULE_LICENSE("GPL");
+
+module_init(sii902x_init);
+module_exit(sii902x_exit);
-- 
1.7.5.3

  parent reply	other threads:[~2011-06-07 10:45 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-07 10:45 [RFC PATCH] KMS support for i.MX51/53 Sascha Hauer
2011-06-07 10:45 ` Sascha Hauer
2011-06-07 10:45 ` [PATCH 1/5] DRM: add i.MX IPUv3 base driver Sascha Hauer
2011-06-07 10:45   ` Sascha Hauer
2011-06-07 15:45   ` Fabio Estevam
2011-06-07 15:45     ` Fabio Estevam
2011-06-07 10:45 ` [PATCH 2/5] DRM i.MX IPU: Add support for IPU submodules Sascha Hauer
2011-06-07 10:45   ` Sascha Hauer
2011-06-07 10:45 ` [PATCH 3/5] DRM: Add drm encoder/connector helper Sascha Hauer
2011-06-07 10:45   ` Sascha Hauer
2011-06-07 10:45 ` Sascha Hauer [this message]
2011-06-07 10:45   ` [PATCH 4/5] DRM: Add support for the sii902x HDMI/DVI encoder Sascha Hauer
2011-07-08 20:42   ` Alex Deucher
2011-07-08 20:42     ` Alex Deucher
2011-07-08 21:01   ` Michał Mirosław
2011-07-08 21:01     ` Michał Mirosław
2011-07-12 13:21     ` Sascha Hauer
2011-07-12 13:21       ` Sascha Hauer
2011-06-07 10:45 ` [PATCH 5/5] DRM: Add i.MX IPUv3 support Sascha Hauer
2011-06-07 10:45   ` Sascha Hauer
2011-06-07 11:17 ` [RFC PATCH] KMS support for i.MX51/53 Alan Cox
2011-06-07 11:17   ` Alan Cox
2011-06-07 19:12   ` Sascha Hauer
2011-06-07 19:12     ` Sascha Hauer
2011-06-07 19:59     ` Alan Cox
2011-06-07 19:59       ` Alan Cox
2011-06-08  8:54       ` Sascha Hauer
2011-06-08  8:54         ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1307443550-25549-5-git-send-email-s.hauer@pengutronix.de \
    --to=s.hauer@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.