diff options
| author | Diogo Ferreira <defer@cyngn.com> | 2016-04-07 15:11:28 +0100 |
|---|---|---|
| committer | Moyster <oysterized@gmail.com> | 2016-11-07 13:46:51 +0100 |
| commit | 78ddc4b367f75fe6e3f00155ff43f4dc42a50a4b (patch) | |
| tree | bc3e1b13c4306c78cb94f46c1a9f63680ca9408a /drivers/misc | |
| parent | c3618e9f5b718c99a843215e8a9b687480cad650 (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.drivers | 6 | ||||
| -rw-r--r-- | drivers/misc/mediatek/dispsys/mt6735/ddp_gamma.c | 12 | ||||
| -rw-r--r-- | drivers/misc/mediatek/video/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/misc/mediatek/videox/mt6735/mtk_disp_mgr.c | 95 |
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); |
