aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArve Hjønnevåg <arve@android.com>2011-07-21 17:03:44 -0700
committerArve Hjønnevåg <arve@android.com>2011-08-03 17:31:08 -0700
commit5045c1cb7ae32fce559bf5bc40f831b5c5d95986 (patch)
tree8108ebcd53e839413769610e763a5a84ee872631
parentcf9ac51014915c7913464cfd52d937c69eedcdb2 (diff)
downloadkernel_samsung_tuna-5045c1cb7ae32fce559bf5bc40f831b5c5d95986.zip
kernel_samsung_tuna-5045c1cb7ae32fce559bf5bc40f831b5c5d95986.tar.gz
kernel_samsung_tuna-5045c1cb7ae32fce559bf5bc40f831b5c5d95986.tar.bz2
OMAP: DSS: panel-s6e8aa0: Add debugfs file to adjust gamma table
Adds a new debugfs file, gamma_correction, which reads and writes the first stage gamma table. This table was initialized by the factory calibration data at boot and is used to modify the brightness value before looking up the voltage in gamma table provided in the platform data. Change-Id: I537ece3e3a8a5da474b76f88beec2ea589b5b3d4 Signed-off-by: Arve Hjønnevåg <arve@android.com>
-rw-r--r--drivers/video/omap2/displays/panel-s6e8aa0.c153
1 files changed, 151 insertions, 2 deletions
diff --git a/drivers/video/omap2/displays/panel-s6e8aa0.c b/drivers/video/omap2/displays/panel-s6e8aa0.c
index 3b9d107..2e09805 100644
--- a/drivers/video/omap2/displays/panel-s6e8aa0.c
+++ b/drivers/video/omap2/displays/panel-s6e8aa0.c
@@ -35,6 +35,7 @@
#include <linux/regulator/consumer.h>
#include <linux/mutex.h>
#include <linux/i2c.h>
+#include <linux/uaccess.h>
#include <video/omapdss.h>
@@ -1178,12 +1179,157 @@ static int s6e8aa0_current_gamma_open(struct inode *inode, struct file *file)
return single_open(file, s6e8aa0_current_gamma_show, inode->i_private);
}
+static int s6e8aa0_gamma_correction_show(struct seq_file *m, void *unused)
+{
+ struct s6e8aa0_data *s6 = m->private;
+ const struct s6e8aa0_gamma_entry *bte;
+ int n, c;
+
+ mutex_lock(&s6->lock);
+ n = s6->brightness_table_size;
+ bte = s6->brightness_table;
+ while (n--) {
+ seq_printf(m, "0x%08x", bte->brightness);
+ for (c = 0; c < 3; c++)
+ seq_printf(m, " 0x%08x", bte->v[c]);
+ seq_printf(m, "\n");
+ bte++;
+ }
+ seq_printf(m, "\n");
+ seq_printf(m, "0x%08x", BV_255);
+ for (c = 0; c < 3; c++)
+ seq_printf(m, " 0x%08x", s6->brightness_limit[c]);
+ seq_printf(m, "\n");
+ mutex_unlock(&s6->lock);
+ return 0;
+}
+
+static int s6e8aa0_gamma_correction_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s6e8aa0_gamma_correction_show,
+ inode->i_private);
+}
+
+static ssize_t s6e8aa0_gamma_correction_write(struct file *file,
+ const char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ struct seq_file *m = file->private_data;
+ struct s6e8aa0_data *s6 = m->private;
+ struct omap_dss_device *dssdev = s6->dssdev;
+ char sbuf[80];
+ u32 val[4] = {
+ };
+ u32 last_val[4];
+ struct s6e8aa0_gamma_entry *bt = NULL;
+ struct s6e8aa0_gamma_entry *new_bt;
+ int bt_size = 0;
+
+ int ret;
+ size_t used;
+ size_t sbuf_len = sizeof(sbuf) - 1;
+ size_t rem = size;
+ int c;
+ int i;
+
+ while (rem && val[0] != BV_255) {
+ if (sbuf_len > rem)
+ sbuf_len = rem;
+ if (copy_from_user(sbuf, buf, sbuf_len)) {
+ ret = -EFAULT;
+ goto err;
+ }
+ sbuf[sbuf_len] = '\0';
+
+ for (i = 0; i < ARRAY_SIZE(val); i++)
+ last_val[i] = val[i];
+ ret = sscanf(sbuf, "%i %i %i %i\n%n",
+ &val[0], &val[1], &val[2], &val[3], &used);
+ if (ret < 4 || !used)
+ break;
+
+ buf += used;
+ rem -= used;
+
+ if (!bt_size) {
+ for (i = 0; i < ARRAY_SIZE(val); i++) {
+ if (val[i] != 0) {
+ pr_info("%s: invalid start value %d: "
+ "0x%08x != 0\n",
+ __func__, i, val[i]);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(val); i++) {
+ if (val[i] <= last_val[i]) {
+ pr_info("%s: invalid value %d: "
+ "0x%08x <= 0x%08x\n", __func__,
+ i, val[i], last_val[i]);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+ for (c = 0; c < 3; c++) {
+ if (val[c + 1] > s6->brightness_limit[c]) {
+ pr_info("%s: invalid value %d: "
+ "0x%08x > 0x%08x\n", __func__,
+ c, val[c + 1],
+ s6->brightness_limit[c]);
+ ret = -EOVERFLOW;
+ goto err;
+ }
+ }
+ }
+
+ new_bt = krealloc(bt, (bt_size + 1) * sizeof(*bt), GFP_KERNEL);
+ if (!new_bt) {
+ ret = -ENOMEM;
+ goto err;
+ }
+ bt = new_bt;
+ bt[bt_size].brightness = val[0];
+ for (c = 0; c < 3; c++)
+ bt[bt_size].v[c] = val[c + 1];
+ bt_size++;
+ }
+ if (val[0] != BV_255) {
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = size - rem;
+ mutex_lock(&s6->lock);
+ pr_debug("%s: got new brightness_table size %d\n", __func__, bt_size);
+ swap(bt, s6->brightness_table);
+ s6->brightness_table_size = bt_size;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
+ dsi_bus_lock(dssdev);
+ s6e8aa0_update_brightness(dssdev);
+ dsi_bus_unlock(dssdev);
+ }
+ mutex_unlock(&s6->lock);
+
+err:
+ kfree(bt);
+ return ret;
+}
+
static const struct file_operations s6e8aa0_current_gamma_fops = {
.open = s6e8aa0_current_gamma_open,
.read = seq_read,
.release = single_release,
};
+static const struct file_operations s6e8aa0_gamma_correction_fops = {
+ .open = s6e8aa0_gamma_correction_open,
+ .read = seq_read,
+ .write = s6e8aa0_gamma_correction_write,
+ .release = single_release,
+};
+
static int s6e8aa0_probe(struct omap_dss_device *dssdev)
{
int ret = 0;
@@ -1249,11 +1395,14 @@ static int s6e8aa0_probe(struct omap_dss_device *dssdev)
}
s6->debug_dir = debugfs_create_dir("s6e8aa0", NULL);
- if (!s6->debug_dir)
+ if (!s6->debug_dir) {
dev_err(&dssdev->dev, "failed to create debug dir\n");
- else
+ } else {
debugfs_create_file("current_gamma", S_IRUGO,
s6->debug_dir, s6, &s6e8aa0_current_gamma_fops);
+ debugfs_create_file("gamma_correction", S_IRUGO | S_IWUSR,
+ s6->debug_dir, s6, &s6e8aa0_gamma_correction_fops);
+ }
if (cpu_is_omap44xx())
s6->force_update = true;