aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorDiogo Ferreira <defer@cyngn.com>2016-04-07 15:11:28 +0100
committerMoyster <oysterized@gmail.com>2016-11-07 13:46:51 +0100
commit78ddc4b367f75fe6e3f00155ff43f4dc42a50a4b (patch)
treebc3e1b13c4306c78cb94f46c1a9f63680ca9408a /drivers/misc
parentc3618e9f5b718c99a843215e8a9b687480cad650 (diff)
mt6735: Add an RGB configuration sys attr driver for videox/corr10
Adds the RGB configuration node which leverages the gamma subsystem to perform color correction. The new node takes rgb triplets that range from 0-2000 each, computes the gamma registers and dispatches them to the gamma correction subsystem. Change-Id: Iac9d3cbd4f423ccfffb8d665c29cfd251767a398
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mediatek/Kconfig.drivers6
-rw-r--r--drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c12
-rw-r--r--drivers/misc/mediatek/video/Kconfig2
-rw-r--r--drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c95
4 files changed, 111 insertions, 4 deletions
diff --git a/drivers/misc/mediatek/Kconfig.drivers b/drivers/misc/mediatek/Kconfig.drivers
index df07465a9..9962ba0ba 100644
--- a/drivers/misc/mediatek/Kconfig.drivers
+++ b/drivers/misc/mediatek/Kconfig.drivers
@@ -337,6 +337,12 @@ config MTK_DITHERING_SUPPORT
avoid contour effect, but side effect is that dithering mechanism
will make some noises
+config MTK_VIDEOX_CYNGN_LIVEDISPLAY
+ bool CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+ default n
+ help
+ Enable the RGB interface for color calibration.
+
config MTK_LCM_PHYSICAL_ROTATION
string "MTK_LCM_PHYSICAL_ROTATION"
help
diff --git a/drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c b/drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c
index a9c47adda..e06b86070 100644
--- a/drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c
+++ b/drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c
@@ -110,11 +110,19 @@ static int disp_gamma_set_lut(const DISP_GAMMA_LUT_T __user *user_gamma_lut, voi
printk(KERN_ERR "[GAMMA] disp_gamma_set_lut: no memory\n");
return -EFAULT;
}
-
+
+#ifdef CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+ if (virt_addr_valid(user_gamma_lut)) {
+ memcpy(gamma_lut, user_gamma_lut, sizeof(DISP_GAMMA_LUT_T));
+ } else
+#endif
if (copy_from_user(gamma_lut, user_gamma_lut, sizeof(DISP_GAMMA_LUT_T)) != 0) {
+ GAMMA_ERR("disp_gamma_set_lut: cannot copy from user mem");
ret = -EFAULT;
kfree(gamma_lut);
- } else {
+ }
+
+ if (!ret) {
id = gamma_lut->hw_id;
if (0 <= id && id < DISP_GAMMA_TOTAL) {
mutex_lock(&g_gamma_global_lock);
diff --git a/drivers/misc/mediatek/video/Kconfig b/drivers/misc/mediatek/video/Kconfig
index 08960d42a..bc16b08db 100644
--- a/drivers/misc/mediatek/video/Kconfig
+++ b/drivers/misc/mediatek/video/Kconfig
@@ -2,4 +2,4 @@ config MTK_VIDEO
bool CONFIG_MTK_VIDEO
default n
help
- CONFIG_MTK_VIDEO
+ CONFIG_MTK_VIDEO \ No newline at end of file
diff --git a/drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c b/drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c
index 3632bd2f5..ca3c1170f 100644
--- a/drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c
+++ b/drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c
@@ -97,6 +97,13 @@ static dev_t mtk_disp_mgr_devno;
static struct cdev *mtk_disp_mgr_cdev;
static struct class *mtk_disp_mgr_class = NULL;
+#ifdef CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+static struct mtk_rgb_work_queue {
+ struct work_struct work;
+ struct mutex lock;
+} mtk_rgb_work_queue;
+#endif
+
static SWITCH_MODE_INFO_STRUCT path_info;
int ovl1_remove = 0;
@@ -2952,8 +2959,84 @@ static struct platform_device mtk_disp_mgr_device = {
.num_resources = 0,
};
+#ifdef CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+#define MAX_LUT_SCALE 2000
+#define PROGRESSION_SCALE 1000
+static u32 mtk_disp_ld_r = MAX_LUT_SCALE;
+static u32 mtk_disp_ld_g = MAX_LUT_SCALE;
+static u32 mtk_disp_ld_b = MAX_LUT_SCALE;
+
+static ssize_t mtk_disp_ld_get_rgb(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", mtk_disp_ld_r, mtk_disp_ld_g, mtk_disp_ld_b);
+}
+
+/**
+ * The default gamma array is an arithmetic progression with alpha=2 and n0=0 and
+ * n = 512.
+ *
+ * We scale it linearly with the color passed to this RGB interface. The display
+ * subsystem has a color precision of 10 bits which means that values from [0-1024[
+ * are acceptable.
+ *
+ * In order to avoid floating point computations in kernel space we scale the alpha
+ * value by 1000 and then scale back the result using integer division.
+ */
+static ssize_t mtk_disp_ld_set_rgb(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int r = MAX_LUT_SCALE, g = MAX_LUT_SCALE, b = MAX_LUT_SCALE;
+
+ if (count > 19)
+ return -EINVAL;
+
+ sscanf(buf, "%d %d %d", &r, &g, &b);
+
+ if (r < 0 || r > MAX_LUT_SCALE) return -EINVAL;
+ if (g < 0 || g > MAX_LUT_SCALE) return -EINVAL;
+ if (b < 0 || b > MAX_LUT_SCALE) return -EINVAL;
+
+ cancel_work_sync(&mtk_rgb_work_queue.work);
+ mtk_disp_ld_r = r;
+ mtk_disp_ld_g = g;
+ mtk_disp_ld_b = b;
+ schedule_work(&mtk_rgb_work_queue.work);
+
+ return count;
+}
+
+static DEVICE_ATTR(rgb, S_IRUGO | S_IWUSR | S_IWGRP, mtk_disp_ld_get_rgb, mtk_disp_ld_set_rgb);
+
+static void mtk_disp_rgb_work(struct work_struct *work) {
+ struct mtk_rgb_work_queue *rgb_wq = container_of(work, struct mtk_rgb_work_queue, work);
+ int r = mtk_disp_ld_r, g = mtk_disp_ld_g, b = mtk_disp_ld_b;
+ int i, gammutR, gammutG, gammutB, ret;
+ DISP_GAMMA_LUT_T *gamma;
+
+ mutex_lock(&rgb_wq->lock);
+
+ gamma = kzalloc(sizeof(DISP_GAMMA_LUT_T), GFP_KERNEL);
+ gamma->hw_id = 0;
+ for (i = 0; i < 512; i++) {
+ gammutR = i * r / PROGRESSION_SCALE;
+ gammutG = i * g / PROGRESSION_SCALE;
+ gammutB = i * b / PROGRESSION_SCALE;
+
+ gamma->lut[i] = GAMMA_ENTRY(gammutR, gammutG, gammutB);
+ }
+
+ ret = primary_display_user_cmd(DISP_IOCTL_SET_GAMMALUT, (unsigned long)gamma);
+
+ kfree(gamma);
+ mutex_unlock(&rgb_wq->lock);
+}
+#endif
+
static int __init mtk_disp_mgr_init(void)
{
+ int rc = 0;
+
if(platform_device_register(&mtk_disp_mgr_device))
{
return -ENODEV;
@@ -2965,12 +3048,22 @@ static int __init mtk_disp_mgr_init(void)
return -ENODEV;
}
+#ifdef CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+ rc = sysfs_create_file(&(mtk_disp_mgr_device.dev.kobj), &dev_attr_rgb.attr);
+ mutex_init(&mtk_rgb_work_queue.lock);
+ INIT_WORK(&mtk_rgb_work_queue.work, mtk_disp_rgb_work);
+#endif
- return 0;
+ return rc;
}
static void __exit mtk_disp_mgr_exit(void)
{
+#ifdef CONFIG_MTK_VIDEOX_CYNGN_LIVEDISPLAY
+ mutex_destroy(&mtk_rgb_work_queue.lock);
+ sysfs_remove_file(&(mtk_disp_mgr_device.dev.kobj), &dev_attr_rgb.attr);
+#endif
+
cdev_del(mtk_disp_mgr_cdev);
unregister_chrdev_region(mtk_disp_mgr_devno, 1);