static int mdss_mdp_kcal_update_queue(struct device *dev)
{
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	if (lut_data->queue_changes) {
		mdss_mdp_kcal_update_pcc(lut_data);
		mdss_mdp_kcal_update_pa(lut_data);
		mdss_mdp_kcal_update_igc(lut_data);
		lut_data->queue_changes = false;
	}

	return 0;
}
static int kcal_ctrl_probe(struct platform_device *pdev)
{
	int ret;
	struct kcal_lut_data *lut_data;

	lut_data = devm_kzalloc(&pdev->dev, sizeof(*lut_data), GFP_KERNEL);
	if (!lut_data) {
		pr_err("%s: failed to allocate memory for lut_data\n",
			__func__);
		return -ENOMEM;
	}

	ext_mdss_mdp_pcc_config = (void *)kallsyms_lookup_name("mdss_mdp_pcc_config");
	ext_mdss_mdp_igc_lut_config = (void *)kallsyms_lookup_name("mdss_mdp_igc_lut_config");
	ext_mdss_mdp_pa_v2_config = (void *)kallsyms_lookup_name("mdss_mdp_pa_v2_config");
	ext_mdss_mdp_pa_config = (void *)kallsyms_lookup_name("mdss_mdp_pa_config");

	platform_set_drvdata(pdev, lut_data);

	lut_data->enable = 0x1;
	lut_data->red = DEF_PCC;
	lut_data->green = DEF_PCC;
	lut_data->blue = DEF_PCC;
	lut_data->minimum = 0x23;
	lut_data->invert = 0x0;
	lut_data->hue = 0x0;
	lut_data->sat = DEF_PA;
	lut_data->val = DEF_PA;
	lut_data->cont = DEF_PA;

	mdss_mdp_kcal_update_pcc(lut_data);
	mdss_mdp_kcal_update_pa(lut_data);
	mdss_mdp_kcal_update_igc(lut_data);
	mdss_mdp_kcal_display_commit();

	ret = device_create_file(&pdev->dev, &dev_attr_kcal);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_min);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_enable);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_invert);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_sat);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_hue);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_val);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_cont);
	if (ret) {
		pr_err("%s: unable to create sysfs entries\n", __func__);
		return ret;
	}

	return 0;
}
static ssize_t kcal_min_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	int kcal_min, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = kstrtoint(buf, 10, &kcal_min);
	if ((r) || (kcal_min < 1 || kcal_min > 256))
		return -EINVAL;

	lut_data->minimum = kcal_min;

	mdss_mdp_kcal_update_pcc(lut_data);
	mdss_mdp_kcal_display_commit();

	return count;
}
static ssize_t kcal_invert_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	int kcal_invert, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = kstrtoint(buf, 10, &kcal_invert);
	if ((r) || (kcal_invert != 0 && kcal_invert != 1) ||
		(lut_data->invert == kcal_invert))
		return -EINVAL;

	lut_data->invert = kcal_invert;

	mdss_mdp_kcal_update_pcc(lut_data);
	mdss_mdp_kcal_display_commit();

	return count;
}
static ssize_t kcal_store(struct device *dev, struct device_attribute *attr,
						const char *buf, size_t count)
{
	int kcal_r, kcal_g, kcal_b, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = sscanf(buf, "%d %d %d", &kcal_r, &kcal_g, &kcal_b);
	if ((r != 3) || (kcal_r < 1 || kcal_r > 256) ||
		(kcal_g < 1 || kcal_g > 256) || (kcal_b < 1 || kcal_b > 256))
		return -EINVAL;

	lut_data->red = kcal_r;
	lut_data->green = kcal_g;
	lut_data->blue = kcal_b;

	mdss_mdp_kcal_update_pcc(lut_data);
	mdss_mdp_kcal_display_commit();

	return count;
}
static ssize_t kcal_min_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	int kcal_min, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = kstrtoint(buf, 10, &kcal_min);
	if ((r) || (kcal_min < 1 || kcal_min > 256))
		return -EINVAL;

	lut_data->minimum = kcal_min;

	mdss_mdp_kcal_check_pcc(lut_data);

	if (mdss_mdp_kcal_is_panel_on())
		mdss_mdp_kcal_update_pcc(lut_data);
	else
		lut_data->queue_changes = true;

	return count;
}
static ssize_t kcal_enable_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	int kcal_enable, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = kstrtoint(buf, 10, &kcal_enable);
	if ((r) || (kcal_enable != 0 && kcal_enable != 1) ||
		(lut_data->enable == kcal_enable))
		return -EINVAL;

	lut_data->enable = kcal_enable;

	if (mdss_mdp_kcal_is_panel_on()) {
		mdss_mdp_kcal_update_pcc(lut_data);
		mdss_mdp_kcal_update_pa(lut_data);
		mdss_mdp_kcal_update_igc(lut_data);
	} else
		lut_data->queue_changes = true;

	return count;
}
static ssize_t kcal_store(struct device *dev, struct device_attribute *attr,
						const char *buf, size_t count)
{
	int kcal_r, kcal_g, kcal_b, r;
	struct kcal_lut_data *lut_data = dev_get_drvdata(dev);

	r = sscanf(buf, "%d %d %d", &kcal_r, &kcal_g, &kcal_b);
	if ((r != 3) || (kcal_r < 1 || kcal_r > 256) ||
		(kcal_g < 1 || kcal_g > 256) || (kcal_b < 1 || kcal_b > 256))
		return -EINVAL;

	lut_data->red = kcal_r;
	lut_data->green = kcal_g;
	lut_data->blue = kcal_b;

	mdss_mdp_kcal_check_pcc(lut_data);

	if (mdss_mdp_kcal_is_panel_on())
		mdss_mdp_kcal_update_pcc(lut_data);
	else
		lut_data->queue_changes = true;

	return count;
}
static int kcal_ctrl_probe(struct platform_device *pdev)
{
	int ret;
	struct kcal_lut_data *lut_data;

	lut_data = devm_kzalloc(&pdev->dev, sizeof(*lut_data), GFP_KERNEL);
	if (!lut_data) {
		pr_err("%s: failed to allocate memory for lut_data\n",
			__func__);
		return -ENOMEM;
	}

	platform_set_drvdata(pdev, lut_data);

	lut_data->enable = 0x1;
	lut_data->red = DEF_PCC;
	lut_data->green = DEF_PCC;
	lut_data->blue = DEF_PCC;
	lut_data->minimum = 0x23;
	lut_data->invert = 0x0;
	lut_data->hue = 0x0;
	lut_data->sat = DEF_PA;
	lut_data->val = DEF_PA;
	lut_data->cont = DEF_PA;

	lut_data->queue_changes = false;

	mdss_mdp_kcal_update_pcc(lut_data);
	mdss_mdp_kcal_update_pa(lut_data);
	mdss_mdp_kcal_update_igc(lut_data);

#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS)
	lut_data->panel_nb.display_on = mdss_mdp_kcal_update_queue;
	lut_data->panel_nb.dev = &pdev->dev;
	ret = mmi_panel_register_notifier(&lut_data->panel_nb);
	if (ret) {
		pr_err("%s: unable to register MMI notifier\n", __func__);
		return ret;
	}
#elif defined(CONFIG_FB)
	lut_data->dev = pdev->dev;
	lut_data->panel_nb.notifier_call = fb_notifier_callback;
	ret = fb_register_client(&lut_data->panel_nb);
	if (ret) {
		pr_err("%s: unable to register fb notifier\n", __func__);
		return ret;
	}
#endif

	ret = device_create_file(&pdev->dev, &dev_attr_kcal);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_min);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_enable);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_invert);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_sat);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_hue);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_val);
	ret |= device_create_file(&pdev->dev, &dev_attr_kcal_cont);
	if (ret) {
		pr_err("%s: unable to create sysfs entries\n", __func__);
		goto out_notifier;
	}

	return 0;

out_notifier:
#if defined(CONFIG_MMI_PANEL_NOTIFICATIONS)
	mmi_panel_unregister_notifier(&lut_data->panel_nb);
#elif defined(CONFIG_FB)
	fb_unregister_client(&lut_data->panel_nb);
#endif
	return ret;
}