tegra: dc: add support for adobeRGB color space
Arun Swain [Thu, 7 May 2015 21:32:02 +0000 (14:32 -0700)]
Support added for adobeRGB color space in kernel.

Bug 1644175

Change-Id: I5aa0fb4818b30eb84a07d8d6f4f5bc41a616e346
Reviewed-on: http://git-master/r/740307
(cherry picked from commit 2fa48d598b18813fd13ff95c6673451a89aacab4)
Signed-off-by: Arun Swain <arswain@nvidia.com>
Reviewed-on: http://git-master/r/748849
Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Tested-by: Jon Mayo <jmayo@nvidia.com>

arch/arm/mach-tegra/include/mach/dc.h
drivers/video/tegra/dc/dc.c
drivers/video/tegra/dc/ext/dev.c
drivers/video/tegra/dc/of_dc.c
include/video/tegra_dc_ext.h

index 05e29be..982fc0c 100644 (file)
@@ -992,6 +992,8 @@ struct tegra_dc_platform_data {
 #if defined(CONFIG_TEGRA_DC_CMU) || defined(CONFIG_TEGRA_DC_CMU_V2)
        bool                    cmu_enable;
        struct tegra_dc_cmu     *cmu;
+       struct tegra_dc_cmu     *cmu_adbRGB;
+       int                     default_clr_space;
 #endif
        unsigned long           ctrl_num;
        unsigned long           win_mask;
index 74d6520..fdb0b39 100644 (file)
@@ -2013,8 +2013,10 @@ static struct tegra_dc_cmu *tegra_dc_get_cmu(struct tegra_dc *dc)
                dc->out->type == TEGRA_DC_OUT_FAKE_DSI_GANGED ||
                dc->out->type == TEGRA_DC_OUT_NULL)
                return &default_cmu;
-       else if (dc->pdata->cmu)
+       if (dc->pdata->cmu && !dc->pdata->default_clr_space)
                return dc->pdata->cmu;
+       else if (dc->pdata->cmu_adbRGB && dc->pdata->default_clr_space)
+               return dc->pdata->cmu_adbRGB;
        else if (dc->out->type == TEGRA_DC_OUT_HDMI)
                return &default_limited_cmu;
        else
@@ -2150,7 +2152,6 @@ int tegra_dc_update_cmu_aligned(struct tegra_dc *dc, struct tegra_dc_cmu *cmu)
 }
 
 EXPORT_SYMBOL(tegra_dc_update_cmu_aligned);
-
 #else
 #define tegra_dc_cache_cmu(dc, src_cmu)
 #define tegra_dc_set_cmu(dc, cmu)
index 9226296..474c14e 100644 (file)
@@ -1546,6 +1546,38 @@ static int tegra_dc_ext_set_cmu_aligned(struct tegra_dc_ext_user *user,
        kfree(cmu);
        return 0;
 }
+static int tegra_dc_ext_get_cmu_adbRGB(struct tegra_dc_ext_user *user,
+                       struct tegra_dc_ext_cmu *args)
+{
+       int i;
+       struct tegra_dc *dc = user->ext->dc;
+       struct tegra_dc_cmu *cmu;
+
+       if (dc->pdata->cmu_adbRGB)
+               cmu = dc->pdata->cmu_adbRGB;
+       else
+               return -EACCES;
+
+       args->cmu_enable = dc->pdata->cmu_enable;
+       for (i = 0; i < 256; i++)
+               args->lut1[i] = cmu->lut1[i];
+
+       args->csc[0] = cmu->csc.krr;
+       args->csc[1] = cmu->csc.kgr;
+       args->csc[2] = cmu->csc.kbr;
+       args->csc[3] = cmu->csc.krg;
+       args->csc[4] = cmu->csc.kgg;
+       args->csc[5] = cmu->csc.kbg;
+       args->csc[6] = cmu->csc.krb;
+       args->csc[7] = cmu->csc.kgb;
+       args->csc[8] = cmu->csc.kbb;
+
+       for (i = 0; i < 960; i++)
+               args->lut2[i] = cmu->lut2[i];
+
+       return 0;
+}
+
 #endif
 
 #ifdef CONFIG_TEGRA_ISOMGR
@@ -2052,6 +2084,32 @@ static long tegra_dc_ioctl(struct file *filp, unsigned int cmd,
 #endif
        }
 
+       case TEGRA_DC_EXT_GET_CMU_ADBRGB:
+       {
+#ifdef CONFIG_TEGRA_DC_CMU
+               struct tegra_dc_ext_cmu *args;
+
+               args = kzalloc(sizeof(*args), GFP_KERNEL);
+               if (!args)
+                       return -ENOMEM;
+
+               if (tegra_dc_ext_get_cmu_adbRGB(user, args)) {
+                       kfree(args);
+                       return -EACCES;
+               }
+
+               if (copy_to_user(user_arg, args, sizeof(*args))) {
+                       kfree(args);
+                       return -EFAULT;
+               }
+
+               kfree(args);
+               return 0;
+#else
+               return -EACCES;
+#endif
+       }
+
        case TEGRA_DC_EXT_SET_CMU:
        {
 #ifdef CONFIG_TEGRA_DC_CMU
index 40acd1f..8377d2d 100644 (file)
@@ -889,16 +889,19 @@ static int parse_cmu_data(struct device_node *np,
        struct tegra_dc_cmu *cmu)
 {
        u16 *csc_parse;
+       u16 *addr_cmu_lut1;
        u8 *addr_cmu_lut2;
        struct property *prop;
        const __be32 *p;
        u32 u;
        int csc_count = 0;
+       int lut1_count = 0;
        int lut2_count = 0;
 
        memcpy(cmu, &default_cmu, sizeof(struct tegra_dc_cmu));
 
        csc_parse = &(cmu->csc.krr);
+       addr_cmu_lut1 = &(cmu->lut1[0]);
        addr_cmu_lut2 = &(cmu->lut2[0]);
 
        of_property_for_each_u32(np, "nvidia,cmu-csc", prop, p, u)
@@ -915,9 +918,22 @@ static int parse_cmu_data(struct device_node *np,
                }
        }
 
+       of_property_for_each_u32(np, "nvidia,cmu-lut1", prop, p, u)
+               lut1_count++;
+       if (lut1_count >
+               (sizeof(cmu->lut1) / sizeof(cmu->lut1[0]))) {
+               pr_err("cmu lut1 overflow\n");
+               return -EINVAL;
+       } else {
+               of_property_for_each_u32(np, "nvidia,cmu-lut1",
+                       prop, p, u) {
+                       /* OF_DC_LOG("cmu lut1 0x%x\n", u); */
+                       *(addr_cmu_lut1++) = (u8)u;
+               }
+       }
+
        of_property_for_each_u32(np, "nvidia,cmu-lut2", prop, p, u)
                lut2_count++;
-
        if (lut2_count >
                (sizeof(cmu->lut2) / sizeof(cmu->lut2[0]))) {
                pr_err("cmu lut2 overflow\n");
@@ -2111,6 +2127,7 @@ struct tegra_dc_platform_data
        struct device_node *entry = NULL;
 #if defined(CONFIG_TEGRA_DC_CMU) || defined(CONFIG_TEGRA_DC_CMU_V2)
        struct device_node *cmu_np = NULL;
+       struct device_node *cmu_adbRGB_np = NULL;
 #endif
        struct property *prop;
        const __be32 *p;
@@ -2436,6 +2453,22 @@ struct tegra_dc_platform_data
                        goto fail_parse;
                }
        }
+
+       cmu_adbRGB_np = of_get_child_by_name(np_target_disp,
+               "cmu_adobe_rgb");
+
+       if (!cmu_adbRGB_np) {
+               pr_info("%s: could not find cmu node for adobeRGB\n",
+                       __func__);
+       } else {
+               pdata->cmu_adbRGB = devm_kzalloc(&ndev->dev,
+                       sizeof(struct tegra_dc_cmu), GFP_KERNEL);
+               if (!pdata->cmu_adbRGB) {
+                       dev_err(&ndev->dev, "not enough memory\n");
+                       goto fail_parse;
+               }
+       }
+
 #endif
 
        /*
@@ -2464,6 +2497,16 @@ struct tegra_dc_platform_data
                if (err)
                        goto fail_parse;
        }
+
+       if (pdata->cmu_adbRGB != NULL) {
+               err = parse_cmu_data(cmu_adbRGB_np, pdata->cmu_adbRGB);
+               if (err)
+                       goto fail_parse;
+       }
+
+       if (!of_property_read_u32(np_dsi_panel, "nvidia,default_color_space"
+                                               , &pdata->default_clr_space))
+               pdata->default_clr_space = 0;
 #endif
 
        of_property_for_each_u32(np, "nvidia,dc-flags", prop, p, temp) {
@@ -2513,6 +2556,7 @@ struct tegra_dc_platform_data
        of_node_put(sd_np);
 #if defined(CONFIG_TEGRA_DC_CMU) || defined(CONFIG_TEGRA_DC_CMU_V2)
        of_node_put(cmu_np);
+       of_node_put(cmu_adbRGB_np);
 #endif
        of_node_put(np_target_disp);
        of_node_put(np_dsi);
@@ -2524,6 +2568,7 @@ fail_parse:
        of_node_put(sd_np);
 #if defined(CONFIG_TEGRA_DC_CMU) || defined(CONFIG_TEGRA_DC_CMU_V2)
        of_node_put(cmu_np);
+       of_node_put(cmu_adbRGB_np);
 #endif
        of_node_put(np_dsi);
        of_node_put(np_sor);
index 71879d9..5b608b1 100644 (file)
@@ -536,6 +536,9 @@ struct tegra_dc_ext_feature {
 #define TEGRA_DC_EXT_SET_PROPOSED_BW_3 \
        _IOR('D', 0x1B, struct tegra_dc_ext_flip_3)
 
+#define TEGRA_DC_EXT_GET_CMU_ADBRGB\
+       _IOR('D', 0x1C, struct tegra_dc_ext_cmu)
+
 enum tegra_dc_ext_control_output_type {
        TEGRA_DC_EXT_DSI,
        TEGRA_DC_EXT_LVDS,