summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDongfang Shi <dshi@nvidia.com>2012-10-29 16:45:56 -0700
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 01:28:19 -0700
commit66b010fd6dd45f0abe9f8aafca7c2680fa0a9200 (patch)
tree7ff962522818f03c987bf14eedfd432a82957ec5
parent7ad191033deaef43515ffb7462424afbb4b7df4c (diff)
video: add ds90uh925q RGB to FPDLink Serializer i2c driver
This driver configures the RGB to FPDLink Serializer for proper output mode. It is used on different embedded platforms. Before it was part of dc enable code in board panel file. Make it separate driver to get it called at proper power stage to avoid failure when resume from sleep mode. bug 1158820 Change-Id: I6761c601b066339177f109656a227aa5214a9847 Signed-off-by: Dongfang Shi <dshi@nvidia.com> Reviewed-on: http://git-master/r/159659 (cherry picked from commit c862396ff0eb4c872644c96dbb03f32e9acd26c8) Reviewed-on: http://git-master/r/161470 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Bob Johnston <bjohnston@nvidia.com> Reviewed-by: Dan Willemsen <dwillemsen@nvidia.com>
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/ds90uh925q_ser.c219
-rw-r--r--include/linux/i2c/ds90uh925q_ser.h31
4 files changed, 257 insertions, 0 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 50ff2a917a08..127ae5140f27 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2513,4 +2513,10 @@ config FB_SSD1307
This driver implements support for the Solomon SSD1307
OLED controller over I2C.
+config DS90UH925Q_SER
+ bool "DS90UH925Q FPDLink Serializer"
+ depends on I2C
+ help
+ This is a driver for FPDLink Serializer DS90UH925Q.
+
endmenu
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 7341b0ba5d82..d15a83f800c5 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -150,6 +150,7 @@ obj-$(CONFIG_FB_NUC900) += nuc900fb.o
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
+obj-$(CONFIG_DS90UH925Q_SER) += ds90uh925q_ser.o
obj-y += tegra/
# Platform or fallback drivers go here
diff --git a/drivers/video/ds90uh925q_ser.c b/drivers/video/ds90uh925q_ser.c
new file mode 100644
index 000000000000..e84967bf8363
--- /dev/null
+++ b/drivers/video/ds90uh925q_ser.c
@@ -0,0 +1,219 @@
+/*
+ * drivers/video/ds90uh925q_ser.c
+ * FPDLink Serializer driver
+ *
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <linux/nvhost.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c/ds90uh925q_ser.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+
+#define LVDS_SER_REG_CONFIG_1 0x4
+#define LVDS_SER_REG_CONFIG_1_BKWD_OVERRIDE 3
+#define LVDS_SER_REG_CONFIG_1_BKWD 2
+
+#define LVDS_SER_REG_DATA_PATH_CTRL 0x12
+#define LVDS_SER_REG_DATA_PATH_CTRL_PASS_RGB 6
+
+#define LVDS_SER_REG_CONFIG_0 0x3
+#define LVDS_SER_REG_CONFIG_0_TRFB 0
+
+struct ds90uh925q_rec {
+ struct ds90uh925q_platform_data *pdata;
+};
+
+static int ser_i2c_read(struct i2c_client *client, int reg, uint8_t *val)
+{
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
+ return ret;
+ }
+
+ *val = ret;
+ return 0;
+}
+
+static int ser_i2c_write(struct i2c_client *client, u8 reg, u8 val)
+{
+ int ret = i2c_smbus_write_byte_data(client, reg, val);
+ if (ret)
+ dev_err(&client->dev, "failed to write\n");
+
+ return ret;
+}
+
+static int lvds_ser_config(struct i2c_client *client,
+ bool is_fpdlinkII,
+ bool support_hdcp,
+ bool clk_rise_edge)
+{
+ u8 val;
+ int err = 0;
+
+ if (is_fpdlinkII) {
+ err = ser_i2c_read(client, LVDS_SER_REG_CONFIG_1, &val);
+ if (err < 0)
+ return err;
+
+ val |= (1 << LVDS_SER_REG_CONFIG_1_BKWD_OVERRIDE);
+ val |= (1 << LVDS_SER_REG_CONFIG_1_BKWD);
+
+ err = ser_i2c_write(client, LVDS_SER_REG_CONFIG_1, val);
+ if (err < 0)
+ return err;
+ } else if (!support_hdcp) {
+ err = ser_i2c_read(client, LVDS_SER_REG_DATA_PATH_CTRL, &val);
+ if (err < 0)
+ return err;
+
+ val |= (1 << LVDS_SER_REG_DATA_PATH_CTRL_PASS_RGB);
+
+ err = ser_i2c_write(client, LVDS_SER_REG_DATA_PATH_CTRL, val);
+ if (err < 0)
+ return err;
+ }
+
+ if (clk_rise_edge) {
+ err = ser_i2c_read(client, LVDS_SER_REG_CONFIG_0, &val);
+ if (err < 0)
+ return err;
+
+ val |= (1 << LVDS_SER_REG_CONFIG_0_TRFB);
+
+ err = ser_i2c_write(client, LVDS_SER_REG_CONFIG_0, val);
+ }
+
+ return (err < 0 ? err : 0);
+}
+
+static int ds90uh925q_enable(struct i2c_client *client)
+{
+ struct ds90uh925q_rec *data = i2c_get_clientdata(client);
+ int err;
+
+ /* Turn on serializer chip */
+ if (data->pdata->has_lvds_en_gpio)
+ gpio_set_value(data->pdata->lvds_en_gpio, 1);
+
+ err = lvds_ser_config(client,
+ data->pdata->is_fpdlinkII,
+ data->pdata->support_hdcp,
+ data->pdata->clk_rise_edge);
+ if (err)
+ pr_err("%s: lvds failed\n", __func__);
+
+ return err;
+}
+
+static void ds90uh925q_disable(struct i2c_client *client)
+{
+ struct ds90uh925q_rec *data = i2c_get_clientdata(client);
+
+ /* Turn off serializer chip */
+ if (data->pdata->has_lvds_en_gpio)
+ gpio_set_value(data->pdata->lvds_en_gpio, 0);
+}
+
+static int ds90uh925q_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct ds90uh925q_rec *data;
+ struct ds90uh925q_platform_data *pdata =
+ client->dev.platform_data;
+ int err;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+ return -EIO;
+ }
+
+ if (!pdata) {
+ dev_err(&client->dev, "no platform data?\n");
+ return -EINVAL;
+ }
+
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ data->pdata = pdata;
+ i2c_set_clientdata(client, data);
+
+ err = ds90uh925q_enable(client);
+ if (err)
+ goto err_out;
+
+ return 0;
+
+err_out:
+ i2c_set_clientdata(client, NULL);
+ return err;
+}
+
+static int ds90uh925q_remove(struct i2c_client *client)
+{
+ struct ds90uh925q_rec *data = i2c_get_clientdata(client);
+
+ ds90uh925q_disable(client);
+
+ i2c_set_clientdata(client, NULL);
+
+ return 0;
+}
+
+static int ds90uh925q_suspend(struct i2c_client *client, pm_message_t message)
+{
+ ds90uh925q_disable(client);
+
+ return 0;
+}
+
+static int ds90uh925q_resume(struct i2c_client *client)
+{
+ return ds90uh925q_enable(client);
+}
+
+
+static const struct i2c_device_id ds90uh925q_id[] = {
+ { "ds90uh925q", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ds90uh925q_id);
+
+static struct i2c_driver ds90uh925q_driver = {
+ .driver = {
+ .name = "ds90uh925q",
+ .owner = THIS_MODULE,
+ },
+ .probe = ds90uh925q_probe,
+ .remove = ds90uh925q_remove,
+ .suspend = ds90uh925q_suspend,
+ .resume = ds90uh925q_resume,
+ .id_table = ds90uh925q_id,
+};
+
+module_i2c_driver(ds90uh925q_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DS90UH925Q FPDLink Serializer driver");
+MODULE_ALIAS("i2c:ds90uh925q_ser");
diff --git a/include/linux/i2c/ds90uh925q_ser.h b/include/linux/i2c/ds90uh925q_ser.h
new file mode 100644
index 000000000000..7c18edcebb01
--- /dev/null
+++ b/include/linux/i2c/ds90uh925q_ser.h
@@ -0,0 +1,31 @@
+/*
+ * FPDLink Serializer driver
+ *
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_DS90UH925Q_SER_H
+#define __LINUX_DS90UH925Q_SER_H
+
+#include <linux/types.h>
+
+/* The platform data for the FPDLink Serializer driver */
+struct ds90uh925q_platform_data {
+ bool has_lvds_en_gpio; /* has GPIO to enable */
+ int lvds_en_gpio; /* GPIO */
+
+ bool is_fpdlinkII;
+ bool support_hdcp;
+ bool clk_rise_edge;
+};
+
+#endif /* __LINUX_DS90UH925Q_SER_H */