All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shashank Sharma <shashank.sharma@intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: uma.shankar@intel.com
Subject: [PATCH 1/6] drm/i915: Add Color manager framework
Date: Thu, 20 Feb 2014 18:07:22 +0530	[thread overview]
Message-ID: <1392899847-2641-2-git-send-email-shashank.sharma@intel.com> (raw)
In-Reply-To: <1392899847-2641-1-git-send-email-shashank.sharma@intel.com>

Intel color manager is a new framework to provide control over
few of the color properties (supported by intel Gen 7 and+
hardware) via sysfs interface. Currently supported properties
are:
1. CSC correction (wide gamute)
2. Gamma correction
3. Hue and Saturation correction
4. Brightness and contrast correction

This patch contains basic implementation of color manager
framework consisting:
1. A register function, which gets called from a dispaly
   while initializing its DRM connector(for example eDP
   and Mipi).
2. Read and write functions for /sysfs interface
3. A command and a data parser.
4. Dummy prototypes for color correction functions.

The sysfs entry will be created at:
/sys/class/drm/<connector-name>/color-manager
Signed-off-by: Shashank Sharma <shashank.sharma@intel.com>
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
---
 drivers/gpu/drm/i915/Makefile       |    1 +
 drivers/gpu/drm/i915/i915_drv.h     |   29 ++
 drivers/gpu/drm/i915/intel_clrmgr.c |  643 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_clrmgr.h |  238 +++++++++++++
 drivers/gpu/drm/i915/intel_dp.c     |    4 +
 drivers/gpu/drm/i915/intel_dsi.c    |    4 +
 6 files changed, 919 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/intel_clrmgr.c
 create mode 100644 drivers/gpu/drm/i915/intel_clrmgr.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4850494..0d8d877 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -40,6 +40,7 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o \
 	  intel_sprite.o \
 	  intel_opregion.o \
 	  intel_sideband.o \
+	  intel_clrmgr.o \
 	  intel_uncore.o \
 	  dvo_ch7xxx.o \
 	  dvo_ch7017.o \
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b4587ac..6c8cbc3 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -79,6 +79,13 @@ enum plane {
 };
 #define plane_name(p) ((p) + 'A')
 
+enum sprite_plane {
+	SPRITE_PLANE_A = 0,
+	SPRITE_PLANE_B = 1,
+	SPRITE_PLANE_C = 0,
+	SPRITE_PLANE_D = 1,
+};
+
 #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites + (s) + 'A')
 
 enum port {
@@ -1391,6 +1398,25 @@ struct intel_pipe_crc {
 	wait_queue_head_t wq;
 };
 
+/*
+  * Intel color manager structures.
+  * Used to represent the current status of
+  * color manager parameters
+  */
+struct clrmgr_pipe_status {
+	bool csc_enabled;
+	bool gamma_enabled;
+	bool hs_enabled;
+	bool cb_enabled;
+	bool gamma_s_enabled;
+	int planeid;
+};
+
+struct clrmgr_map {
+	struct drm_connector *connector;
+	struct clrmgr_pipe_status *pstatus;
+};
+
 typedef struct drm_i915_private {
 	struct drm_device *dev;
 	struct kmem_cache *slab;
@@ -1594,6 +1620,8 @@ typedef struct drm_i915_private {
 	struct i915_dri1_state dri1;
 	/* Old ums support infrastructure, same warning applies. */
 	struct i915_ums_state ums;
+	/* Color manager current status */
+	struct clrmgr_map clrmgr_status;
 } drm_i915_private_t;
 
 static inline struct drm_i915_private *to_i915(const struct drm_device *dev)
@@ -2008,6 +2036,7 @@ extern void intel_uncore_early_sanitize(struct drm_device *dev);
 extern void intel_uncore_init(struct drm_device *dev);
 extern void intel_uncore_check_errors(struct drm_device *dev);
 extern void intel_uncore_fini(struct drm_device *dev);
+extern bool intel_clrmgr_register(struct drm_connector *connector);
 
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe,
diff --git a/drivers/gpu/drm/i915/intel_clrmgr.c b/drivers/gpu/drm/i915/intel_clrmgr.c
new file mode 100644
index 0000000..2c826f3
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_clrmgr.c
@@ -0,0 +1,643 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Shashank Sharma <shashank.sharma@intel.com>
+ * Uma Shankar <uma.shankar@intel.com>
+ * Shobhit Kumar <shobhit.kumar@intel.com>
+ */
+
+#include <linux/device.h>
+#include "drmP.h"
+#include "intel_drv.h"
+#include "i915_drm.h"
+#include "i915_drv.h"
+#include "intel_clrmgr.h"
+
+/* Sprite register default gamma values */
+u32 default_sprite_gamma_vals[] = {
+	0, 0, 0, 0, 0, 0
+};
+
+/* Gamma lookup table for Sprite planes */
+u32 gamma_sprite_softlut[GAMMA_SP_MAX_COUNT] = {
+	0, 0, 0, 0, 0, 1023
+};
+
+/* Gamma soft lookup table for default gamma =1.0 */
+u32 gamma_softlut[GAMMA_CORRECT_MAX_COUNT] =  {
+	0x000000, 0x0, 0x020202, 0x0, 0x040404, 0x0, 0x060606, 0x0,
+	0x080808, 0x0, 0x0A0A0A, 0x0, 0x0C0C0C, 0x0, 0x0E0E0E, 0x0,
+	0x101010, 0x0, 0x121212, 0x0, 0x141414, 0x0, 0x161616, 0x0,
+	0x181818, 0x0, 0x1A1A1A, 0x0, 0x1C1C1C, 0x0, 0x1E1E1E, 0x0,
+	0x202020, 0x0, 0x222222, 0x0, 0x242424, 0x0, 0x262626, 0x0,
+	0x282828, 0x0, 0x2A2A2A, 0x0, 0x2C2C2C, 0x0, 0x2E2E2E, 0x0,
+	0x303030, 0x0, 0x323232, 0x0, 0x343434, 0x0, 0x363636, 0x0,
+	0x383838, 0x0, 0x3A3A3A, 0x0, 0x3C3C3C, 0x0, 0x3E3E3E, 0x0,
+	0x404040, 0x0, 0x424242, 0x0, 0x444444, 0x0, 0x464646, 0x0,
+	0x484848, 0x0, 0x4A4A4A, 0x0, 0x4C4C4C, 0x0, 0x4E4E4E, 0x0,
+	0x505050, 0x0, 0x525252, 0x0, 0x545454, 0x0, 0x565656, 0x0,
+	0x585858, 0x0, 0x5A5A5A, 0x0, 0x5C5C5C, 0x0, 0x5E5E5E, 0x0,
+	0x606060, 0x0, 0x626262, 0x0, 0x646464, 0x0, 0x666666, 0x0,
+	0x686868, 0x0, 0x6A6A6A, 0x0, 0x6C6C6C, 0x0, 0x6E6E6E, 0x0,
+	0x707070, 0x0, 0x727272, 0x0, 0x747474, 0x0, 0x767676, 0x0,
+	0x787878, 0x0, 0x7A7A7A, 0x0, 0x7C7C7C, 0x0, 0x7E7E7E, 0x0,
+	0x808080, 0x0, 0x828282, 0x0, 0x848484, 0x0, 0x868686, 0x0,
+	0x888888, 0x0, 0x8A8A8A, 0x0, 0x8C8C8C, 0x0, 0x8E8E8E, 0x0,
+	0x909090, 0x0, 0x929292, 0x0, 0x949494, 0x0, 0x969696, 0x0,
+	0x989898, 0x0, 0x9A9A9A, 0x0, 0x9C9C9C, 0x0, 0x9E9E9E, 0x0,
+	0xA0A0A0, 0x0, 0xA2A2A2, 0x0, 0xA4A4A4, 0x0, 0xA6A6A6, 0x0,
+	0xA8A8A8, 0x0, 0xAAAAAA, 0x0, 0xACACAC, 0x0, 0xAEAEAE, 0x0,
+	0xB0B0B0, 0x0, 0xB2B2B2, 0x0, 0xB4B4B4, 0x0, 0xB6B6B6, 0x0,
+	0xB8B8B8, 0x0, 0xBABABA, 0x0, 0xBCBCBC, 0x0, 0xBEBEBE, 0x0,
+	0xC0C0C0, 0x0, 0xC2C2C2, 0x0, 0xC4C4C4, 0x0, 0xC6C6C6, 0x0,
+	0xC8C8C8, 0x0, 0xCACACA, 0x0, 0xCCCCCC, 0x0, 0xCECECE, 0x0,
+	0xD0D0D0, 0x0, 0xD2D2D2, 0x0, 0xD4D4D4, 0x0, 0xD6D6D6, 0x0,
+	0xD8D8D8, 0x0, 0xDADADA, 0x0, 0xDCDCDC, 0x0, 0xDEDEDE, 0x0,
+	0xE0E0E0, 0x0, 0xE2E2E2, 0x0, 0xE4E4E4, 0x0, 0xE6E6E6, 0x0,
+	0xE8E8E8, 0x0, 0xEAEAEA, 0x0, 0xECECEC, 0x0, 0xEEEEEE, 0x0,
+	0xF0F0F0, 0x0, 0xF2F2F2, 0x0, 0xF4F4F4, 0x0, 0xF6F6F6, 0x0,
+	0xF8F8F8, 0x0, 0xFAFAFA, 0x0, 0xFCFCFC, 0x0, 0xFEFEFE, 0x0
+};
+
+/* Color space conversion coff's */
+u32 csc_softlut[CSC_MAX_COEFF_COUNT] = {
+	1024,	 0, 67108864, 0, 0, 1024
+};
+
+u32 cb_softlut[CB_MAX_COEFF_COUNT] = {
+	0x80
+};
+
+u32 hs_softlut[HS_MAX_COEFF_COUNT] = {
+	0x1000000
+};
+
+u32 *clrmgr_luts[] = {
+	csc_softlut,
+	gamma_softlut,
+	cb_softlut,
+	hs_softlut,
+	gamma_sprite_softlut
+};
+
+/* Hue Saturation defaults */
+struct hue_saturationlut saved_hsvals[VLV_NO_SPRITE_REG] = {
+	{sprite_a, 0x1000000},
+	{sprite_b, 0x1000000},
+	{sprite_c, 0x1000000},
+	{sprite_d, 0x1000000}
+};
+
+/* Contrast brightness defaults */
+struct cont_brightlut saved_cbvals[VLV_NO_SPRITE_REG] = {
+	{sprite_a, 0x80},
+	{sprite_b, 0x80},
+	{sprite_c, 0x80},
+	{sprite_d, 0x80}
+};
+
+/* Get no of pipes in SOC */
+static int get_no_of_pipes(struct drm_device *dev)
+{
+	if (!dev) {
+		DRM_ERROR("NULL input to get no of pipes");
+		return 0;
+	}
+
+	if (IS_VALLEYVIEW(dev))
+		return VLV_NO_OF_PIPES;
+	if (IS_HASWELL(dev))
+		return HSW_NO_OF_PIPES;
+
+	return 0;
+}
+
+static bool intel_clrmgr_disable_hs(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+static bool intel_clrmgr_disable_cb(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+static bool intel_clrmgr_disable_gamma(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+static void intel_clrmgr_disable_csc(struct drm_device *dev, int identifier)
+{
+}
+
+static bool intel_clrmgr_enable_hs(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+static bool intel_clrmgr_enable_cb(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+static bool intel_clrmgr_enable_gamma(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+static bool intel_clrmgr_enable_csc(struct drm_device *dev, int identifier)
+{
+	return true;
+}
+
+/*
+* Enable a color manager property
+* This function assumes all the validation is done
+* by the caller
+*/
+static bool intel_clrmgr_enable_property(struct drm_device *dev,
+		int property, int identifier)
+{
+	switch (property) {
+	case clrmgr_csc:
+		intel_clrmgr_enable_csc(dev, identifier);
+		break;
+	case clrmgr_gamma:
+	case clrmgr_gammaspr:
+		intel_clrmgr_enable_gamma(dev, identifier);
+		break;
+	case clrmgr_cb:
+		intel_clrmgr_enable_cb(dev, identifier);
+		break;
+	case clrmgr_hs:
+		intel_clrmgr_enable_hs(dev, identifier);
+		break;
+	default:
+		DRM_ERROR("Clrmgr: Enable, invalid property %d", property);
+		return false;
+	}
+
+	return true;
+}
+
+/*
+* Disable a color manager property
+* This function assumes all the validation is done
+* by the caller
+*/
+static bool intel_clrmgr_disable_property(struct drm_device *dev,
+		int property, int identifier)
+{
+	switch (property) {
+	case clrmgr_csc:
+		intel_clrmgr_disable_csc(dev, identifier);
+		break;
+	case clrmgr_gamma:
+		intel_clrmgr_disable_gamma(dev, identifier);
+		break;
+	case clrmgr_cb:
+		intel_clrmgr_disable_cb(dev, identifier);
+		break;
+	case clrmgr_hs:
+		intel_clrmgr_disable_hs(dev, identifier);
+		break;
+	}
+	DRM_DEBUG_DRIVER("Clrmgr: %s disabled",
+		clrmgr_properties[property]);
+	return true;
+}
+
+/*
+* _parse_clrmgr_data: Extract the data from color manager buffer
+* The data parser follows a strict grammar.
+===============================
+* -The values must start with 0x and
+* -The values must be seperated by a comma
+* -There mustn't be a space after/before comma
+* -No non alphanumeric at start
+* -Sample: 0x5678,0xABCD
+*/
+int _parse_clrmgr_data(uint *dest, char *src, int max)
+{
+	int size = 0;
+	int bytes = 0;
+	char *populate = NULL;
+
+	/* Check grammar */
+	if (!dest || !src || *src != '0') {
+		DRM_ERROR("Clrmgr: Invalid input to parser");
+		return -EINVAL;
+	}
+
+	/* Extract values from buffer */
+	while ((size < max) && (*src != '\n')) {
+		populate = strsep(&src, ",");
+		if (!populate) {
+			if (size < max)
+				DRM_ERROR("Clrmgr: Parser: %d values missing",
+					max-size);
+			break;
+		}
+
+		/* Consider ',' also for length */
+		bytes += (strlen(populate)+1);
+		if (kstrtouint((const char *)populate, CLRMGR_PARSE_BASE,
+			&dest[size++])) {
+			DRM_ERROR("ClrMgr Parse: Invalid limit\n");
+			return -EINVAL;
+		}
+
+		if (CLRMGR_DEBUG_ENABLE)
+			DRM_DEBUG_DRIVER("Parse data: dest[%d] = 0x%x",
+			size-1, dest[size-1]);
+
+		/* End of data */
+		if (src == NULL || *src == '\0') {
+			if (size < max)
+				DRM_ERROR("Clrmgr: Parser: %d values missing",
+				max-size);
+			break;
+		}
+	}
+
+	DRM_DEBUG_DRIVER("Clrmgr: Parser: Loaded %d bytes from source", bytes);
+	return bytes;
+}
+
+/*
+* _extract_cmd
+* Actual extraction and interpratation of a
+* color manager command
+*/
+int _extract_cmd(const char *buf)
+{
+	u8 count = 2;
+	u8 update = 0;
+	int cmd = 0;
+
+	if (!buf) {
+		DRM_ERROR("Clrmgr: Apply: invalid input to extract_cmd\n");
+		return -1;
+	}
+
+	/* Check for alphanumeric chars */
+	while (count--) {
+		if (*buf >= 'A' && *buf <= 'F')
+			update = (*buf - 'A' + CLRMGR_HEX_ADDITION);
+		else if (*buf >= 'a' && *buf <= 'f')
+			update = (*buf - 'a' + CLRMGR_HEX_ADDITION);
+		else if (*buf >= '0' && *buf <= '9')
+			update = (*buf - '0');
+		else {
+			DRM_ERROR("Clrmgr: extract_cmd: Stupid input");
+			return -1;
+		}
+		cmd = cmd * CLRMGR_PARSE_BASE + update;
+		buf++;
+	}
+	DRM_DEBUG_DRIVER("Clrmgr: Extarcted: %d", cmd);
+	return cmd;
+}
+
+
+/*
+* _parse_clrmgr_cmd:
+* Extract command from color EDID
+*Color EDID (4 bytes) :
+*================
+*Byte 0	: Property to modify
+*Byte 1	: Enable /Disable property
+*Byte 2	: Identifier (Plane/Pipe)
+*Byte 3	: How many data bytes are following this byte
+*
+*	<1Byte>	  <1Byte>	               <1Byte>		<1Byte>
+*<<=property=>,<=enable/disable=>,<=identifier=>,<=No of data blocks=>,
+*<0xdata>,<0xdata>,<0xdata> ..... <0xdata>
+* Sample command+ data : 0x01010001,0x1234
+* This is to enable Gamma on Pipe A, with val=0x1234
+*/
+bool _parse_clrmgr_cmd(const char *ubuf, struct clrmgr_cmd *cmd)
+{
+	int ret = 0;
+
+	/* Validate input, command must start with 0x */
+	if (!ubuf || !cmd || *ubuf != '0') {
+		DRM_ERROR("Clrmgr: Apply: invalid input to parse_command\n");
+		return false;
+	}
+
+	/* Extract property to be changed */
+	ret = _extract_cmd(ubuf + CLR_EDID_PROPERTY);
+	if (ret < 0) {
+		DRM_ERROR("Clrmgr: Parse: extract property failed\n");
+		return false;
+	}
+	cmd->property = ret;
+
+	/* Extract enabled/disable choice */
+	ret = _extract_cmd(ubuf + CLR_EDID_ENABLE);
+	if (ret  < 0) {
+		DRM_ERROR("Clrmgr: Parse: extract enable failed\n");
+		return false;
+	}
+	cmd->enable = (ret ? true : false);
+
+	/* Extract Identifier of pipe/plane */
+	ret = _extract_cmd(ubuf + CLR_EDID_IDENTIFIER);
+	if (ret < 0) {
+		DRM_ERROR("Clrmgr: Parse: extract identifier failed\n");
+		return false;
+	}
+	cmd->identifier = ret;
+
+	/* Extract no of data bytes following */
+	ret = _extract_cmd(ubuf + CLR_EDID_SIZE);
+	if (ret < 0) {
+		DRM_ERROR("Clrmgr: Parse: extract size failed\n");
+		return false;
+	}
+	cmd->size = ret;
+	return true;
+}
+
+/*
+* intel_clrmgr_apply:
+* Parse, decode and Apply a change.
+*/
+bool intel_clrmgr_apply(struct drm_device *dev,
+	const char *ubuf, size_t count)
+{
+	bool ret = false;
+	struct clrmgr_cmd cmd = {0, 0, 0, 0};
+	char *raw_data = NULL;
+
+	if (!ubuf || !count) {
+		DRM_ERROR("Clrmgr: Apply: insufficient data\n");
+		return -EINVAL;
+	}
+
+	/* Parse command */
+	if (!_parse_clrmgr_cmd(ubuf, &cmd)) {
+		DRM_ERROR("Clrmgr: Command parsing failed");
+		return false;
+	}
+
+	/* Validate property */
+	if (cmd.property < clrmgr_csc || cmd.property > clrmgr_gammaspr) {
+		DRM_ERROR("Clrmgr: Invalid input, propery Max=%d, Min=%d",
+			clrmgr_csc, clrmgr_gammaspr);
+		return false;
+	}
+
+	/* Validate Identifier */
+	if (cmd.identifier < pipe_a || cmd.identifier > sprite_d) {
+		DRM_ERROR("Clrmgr: Invalid input, identifier Max=%d, Min=%d",
+			pipe_a, sprite_d);
+		return false;
+	}
+
+	if (cmd.enable) {
+		/* Validite size, min 1 block of data is required */
+		if (cmd.size > clrmgr_maxsize[cmd.property]  ||
+			cmd.size < CLR_MGR_PARSE_MIN) {
+			DRM_ERROR("Clrmgr: Invalid size=%d, range %d to %d",
+				(int)count, CLR_MGR_PARSE_MIN,
+				clrmgr_maxsize[cmd.property]);
+			return false;
+		}
+
+		raw_data = kzalloc(count, GFP_KERNEL);
+		if (!raw_data) {
+			DRM_ERROR("Clrmgr: Out of memory");
+			return false;
+		}
+
+		/* Get the data */
+		memcpy((void *)raw_data,
+			(const void *)&ubuf[CLR_EDID_DATA], count);
+
+		/* Parse data and load corresponsing soft LUT */
+		if (_parse_clrmgr_data(clrmgr_luts[cmd.property], raw_data,
+				cmd.size) < 0) {
+			DRM_ERROR("Clrmgr: Parse failed");
+			ret = false;
+			goto FREE_AND_RETURN;
+		}
+
+		/* Data loaded, now do changes in property */
+		if (!intel_clrmgr_enable_property(dev, cmd.property,
+			cmd.identifier)) {
+			DRM_ERROR("Clrmgr: Enable property %s failed",
+				clrmgr_properties[cmd.property]);
+			ret = false;
+			goto FREE_AND_RETURN;
+		}
+	} else {
+		/* Validite size, for disable just command is enough */
+		if (cmd.size) {
+			DRM_ERROR("Clrmgr: Invalid input, No data required");
+			return false;
+		}
+
+		/* Disable specified property */
+		if (!intel_clrmgr_disable_property(dev, cmd.property,
+			cmd.identifier)) {
+			DRM_ERROR("Clrmgr: Disable property %s failed",
+				clrmgr_properties[cmd.property]);
+			return false;
+		}
+	}
+
+	ret = true;
+	DRM_DEBUG_DRIVER("Clrmgr: apply success");
+
+FREE_AND_RETURN:
+	kfree(raw_data);
+	return ret;
+}
+
+/*
+  * Color manager write function.
+  * Current interface is /sys/class/drm/<connector-name>/color-manager
+  * Shows the current status of color manager features
+*/
+ssize_t intel_clrmgr_write(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *ba, char *ubuf,
+		loff_t offset, size_t count)
+{
+	struct device *connector_dev = container_of(kobj, struct device, kobj);
+	struct drm_connector *connector = dev_get_drvdata(connector_dev);
+	struct drm_device *dev = connector->dev;
+
+	DRM_DEBUG_DRIVER("Clrmgr write");
+
+	/* Validate input */
+	if (!count || !ubuf) {
+		DRM_ERROR("Clrmgr: insufficient data\n");
+		return -EINVAL;
+	}
+
+	/* Parse the color EDID, apply the change */
+	if (!intel_clrmgr_apply(dev, ubuf, count)) {
+		DRM_ERROR("Clrmgr: Parse and apply failed\n");
+		return -1;
+	}
+
+	DRM_DEBUG_DRIVER("Clrmgr: Write success\n");
+	return count;
+}
+
+/*
+  * Color manager read function.
+  * Current interface is /sys/class/drm/<connector-name>/color-manager
+  * Shows the current status of color manager features
+*/
+ssize_t intel_clrmgr_read(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *ba, char *buf, loff_t off, size_t count)
+{
+	u16 size = 0;
+	u8 pipe_count = 0;
+	const char *p = NULL;
+	struct device *connector_dev = container_of(kobj, struct device, kobj);
+	struct drm_connector *connector = dev_get_drvdata(connector_dev);
+	struct drm_device *dev = connector->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	struct clrmgr_pipe_status *pstatus = dev_priv->clrmgr_status.pstatus;
+
+	if (!pstatus) {
+		DRM_DEBUG_DRIVER("Clrmgr not initialized yet");
+		return 0;
+	}
+
+	/* One page read is enough */
+	if (off)
+		return 0;
+
+	/* Get no of pipes in this arch */
+	pipe_count = get_no_of_pipes(dev);
+	if (!pipe_count) {
+		DRM_ERROR("This Gen device is not supported, cant get pipes\n");
+		return false;
+	}
+
+	/* Load per pipe color status */
+	do {
+		size += sprintf(buf + size, "PIPE %c\n", ('A' + pipe_count-1));
+		size += sprintf(buf + size, "=====\n");
+		p = clrmgr_properties[clrmgr_csc];
+		size += sprintf(buf + size, "1.%s %s\n", p,
+		pstatus[pipe_count-1].csc_enabled ? "Enabled" : "Disabled");
+		p = clrmgr_properties[clrmgr_gamma];
+		size += sprintf(buf + size, "2.%s %s\n", p,
+		pstatus[pipe_count-1].gamma_enabled ? "Enabled" : "Disabled");
+		p = clrmgr_properties[clrmgr_cb];
+		size += sprintf(buf + size, "3.%s %s\n", p,
+		pstatus[pipe_count-1].cb_enabled ? "Enabled" : "Disabled");
+		p = clrmgr_properties[clrmgr_hs];
+		size += sprintf(buf + size, "4.%s %s\n", p,
+		pstatus[pipe_count-1].hs_enabled ? "Enabled" : "Disabled");
+		p = clrmgr_properties[clrmgr_gammaspr];
+		size += sprintf(buf + size, "5.%s %s\n", p,
+		pstatus[pipe_count-1].gamma_s_enabled ? "Enabled" : "Disabled");
+	} while (--pipe_count);
+
+	DRM_DEBUG_DRIVER("Clrmgr Read done, %d bytes", size);
+	return size;
+}
+
+static struct bin_attribute clrmgr_attr = {
+	.attr.name = "color-manager",
+	.attr.mode = 0644,
+	.size = 0,
+	.read = intel_clrmgr_read,
+	.write = intel_clrmgr_write
+};
+
+/* Register color manager with a connector
+  * The connecter init function should call this function
+  * The current implementation is for Primary/Fix panels Like Mipi/EDP
+*/
+bool intel_clrmgr_register(struct drm_connector *connector)
+{
+	int pipe_count = 0;
+	struct clrmgr_pipe_status *pstatus = NULL;
+	struct drm_device *dev = connector->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	/* Clr mgr is available for Gen 7 and + for now */
+	if (INTEL_INFO(dev)->gen < CLRMGR_GEN_THRESHOLD) {
+		DRM_ERROR("Clrmgr: This Gen device is not supported\n");
+		return false;
+	}
+
+	/* Todo: Current implementation supports only VLV.
+	Extend this for HSW and other gen 7+ devices */
+	if (!IS_VALLEYVIEW(dev)) {
+		DRM_ERROR("Clrmgr: Current implementation supports only VLV\n");
+		return false;
+	}
+
+	/* Create sysfs entry for color manager */
+	if (sysfs_create_bin_file(&connector->kdev->kobj, &clrmgr_attr)) {
+		DRM_ERROR("Clrmgr:  %s Register Color interface failed\n",
+			drm_get_connector_name(connector));
+		return false;
+	}
+
+	/* Get no of pipes of the arch */
+	pipe_count = get_no_of_pipes(dev);
+	if (!pipe_count) {
+		DRM_ERROR("Clrmgr: Cant get pipe info\n");
+		return false;
+	}
+
+	/* Load color status of the pipes */
+	pstatus = kzalloc(pipe_count * sizeof(struct clrmgr_pipe_status),
+				GFP_KERNEL);
+	if (!pstatus) {
+		DRM_ERROR("Clrmgr: %s Out of memory\n",
+			drm_get_connector_name(connector));
+		return false;
+	}
+
+	/* Initialize color status of the pipe,
+	  * planeid will be filled with specific enable call
+	  */
+	do {
+		pstatus[pipe_count-1].planeid = -1;
+		pstatus[pipe_count-1].csc_enabled = false;
+		pstatus[pipe_count-1].gamma_enabled = false;
+		pstatus[pipe_count-1].hs_enabled = false;
+		pstatus[pipe_count-1].cb_enabled = false;
+		pstatus[pipe_count-1].gamma_s_enabled = false;
+	} while (--pipe_count);
+
+	/* Load color manager status */
+	dev_priv->clrmgr_status.pstatus = pstatus;
+	dev_priv->clrmgr_status.connector = connector;
+
+	DRM_DEBUG_DRIVER("Clrmgr: Successfully registered for %s",
+			drm_get_connector_name(connector));
+	return true;
+}
+EXPORT_SYMBOL(intel_clrmgr_register);
diff --git a/drivers/gpu/drm/i915/intel_clrmgr.h b/drivers/gpu/drm/i915/intel_clrmgr.h
new file mode 100644
index 0000000..25d3491
--- /dev/null
+++ b/drivers/gpu/drm/i915/intel_clrmgr.h
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2008 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Shashank Sharma <shashank.sharma@intel.com>
+ * Uma Shankar <uma.shankar@intel.com>
+ */
+
+#ifndef _I915_CLR_MNGR_H_
+#define _I915_CLR_MNGR_H_
+
+
+struct cont_brightlut {
+	short sprite_no;
+	u32 val;
+};
+
+struct hue_saturationlut {
+	short sprite_no;
+	u32 val;
+};
+
+/* Debugging support */
+#define CLRMGR_DEBUG_ENABLE		0
+
+/* General defines */
+#define CLR_MGR_PARSE_MAX		256
+#define CLR_MGR_PARSE_MIN		1
+#define VLV_NO_SPRITE_REG				4
+#define SIZE_STATUS				10
+#define CLR_EDID_PROPERTY			2
+#define CLR_EDID_ENABLE			(CLR_EDID_PROPERTY + 2)
+#define CLR_EDID_IDENTIFIER		(CLR_EDID_ENABLE + 2)
+#define CLR_EDID_SIZE				(CLR_EDID_IDENTIFIER + 2)
+#define CLR_EDID_DATA				(CLR_EDID_SIZE + 3)
+#define CLRMGR_GEN_THRESHOLD	7
+#define VLV_NO_OF_PIPES			2
+#define HSW_NO_OF_PIPES			3
+#define CLRMGR_PARSE_BASE		16
+#define CLRMGR_HEX_ADDITION		10
+
+/* Pipe level gamma correction defines */
+#define PIPECONF_GAMMA			(1<<24)
+#define GAMMA_SP_MAX_COUNT		6
+#define GAMMA_MAX_VAL			1024
+#define SHIFTBY6(val)				(val<<6)
+#define GAMMA_CORRECT_MAX_COUNT 256
+
+#define PIPEA_MAX_RED		(dev_priv->info.display_mmio_offset + 0x70010)
+#define PIPEA_MAX_GREEN	(dev_priv->info.display_mmio_offset + 0x70014)
+#define PIPEA_MAX_BLUE	(dev_priv->info.display_mmio_offset + 0x70018)
+
+/* Sprite gamma correction regs */
+#define GAMMA_SPA_GAMC0		(dev_priv->info.display_mmio_offset + 0x721F4)
+#define GAMMA_SPB_GAMC0		(dev_priv->info.display_mmio_offset + 0x722F4)
+#define GAMMA_SPC_GAMC0		(dev_priv->info.display_mmio_offset + 0x723F4)
+#define GAMMA_SPD_GAMC0		(dev_priv->info.display_mmio_offset + 0x724F4)
+#define GAMMA_SP_REG_OFFSET	0x100
+
+/* Sprite control regs */
+#define GAMMA_SPA_CNTRL		(dev_priv->info.display_mmio_offset + 0x72180)
+#define GAMMA_SPB_CNTRL		(dev_priv->info.display_mmio_offset + 0x72280)
+#define GAMMA_SPC_CNTRL		(dev_priv->info.display_mmio_offset + 0x72380)
+#define GAMMA_SPD_CNTRL		(dev_priv->info.display_mmio_offset + 0x72480)
+#define GAMMA_SP_CTL_OFFSET	0x100
+#define GAMMA_ENABLE_SPR		(1<<30)
+#define GET_SPRITE_CTL(plid)	(GAMMA_SPA_CNTRL +		\
+				((plid - sprite_a) * GAMMA_SP_CTL_OFFSET))
+#define GET_SPRITE_REG(plid)	(GAMMA_SPA_GAMC0 +		\
+				((plid - sprite_a) * GAMMA_SP_REG_OFFSET))
+
+/* CSC defines and Control Register */
+#define	_PIPEACSC		(dev_priv->info.display_mmio_offset + 0x600b0)
+#define	_PIPEBCSC		(dev_priv->info.display_mmio_offset + 0x610b0)
+#define	PIPECSC(p)		(p ? _PIPEACSC : _PIPEBCSC)
+#define	PIPECONF_CSC_ENABLE		(1<<15)
+#define	CSC_MAX_COEFF_COUNT	6
+
+
+/* Sprite Contrast and Brightness Registers */
+#define CB_MAX_COEFF_COUNT	1
+#define SPRITEA_CB_REG		(dev_priv->info.display_mmio_offset + 0x721d0)
+#define SPRITEB_CB_REG		(dev_priv->info.display_mmio_offset + 0x722d0)
+#define SPRITEC_CB_REG		(dev_priv->info.display_mmio_offset + 0x723d0)
+#define SPRITED_CB_REG		(dev_priv->info.display_mmio_offset + 0x724d0)
+#define SPRITE_CB_OFFSET		0x100
+#define GET_SPRITE_CB(plid)		(SPRITEA_CB_REG +		\
+					(plid * SPRITE_CB_OFFSET))
+#define CB_DEFAULT_VAL		0x80
+
+/* Sprite Hue and Saturation Registers */
+#define HS_MAX_COEFF_COUNT	1
+#define SPRITEA_HS_REG		0x721d4
+#define SPRITEB_HS_REG		0x722d4
+#define SPRITEC_HS_REG		0x723d4
+#define SPRITED_HS_REG		0x724d4
+#define HS_DEFAULT_VAL		0x1000000
+#define SPRITE_HS_OFFSET		0x100
+#define GET_SPRITE_HS(plid)		(SPRITEA_HS_REG +		\
+						(plid * SPRITE_HS_OFFSET))
+
+
+/* Color manager properties */
+const char	*clrmgr_properties[] = {
+	"CSC_CORRECTION",
+	"GAMMA CORRECTION",
+	"BRIGHTNESS/CONTRAST",
+	"HUE/SATURATION",
+	"GAMMA CORRECTTION SPRITE"
+};
+
+/* Color manager max values */
+int clrmgr_maxsize[] = {
+	CSC_MAX_COEFF_COUNT,
+	GAMMA_CORRECT_MAX_COUNT,
+	CB_MAX_COEFF_COUNT,
+	HS_MAX_COEFF_COUNT,
+	GAMMA_SP_MAX_COUNT
+};
+
+/* Color manager features */
+enum clrmgr_features {
+	clrmgr_csc = 0,
+	clrmgr_gamma,
+	clrmgr_cb,
+	clrmgr_hs,
+	clrmgr_gammaspr
+};
+
+struct clrmgr_cmd {
+	bool enable;
+	int size;
+	int identifier;
+	enum clrmgr_features property;
+};
+
+/* Color manager features */
+enum clrmgr_identifiers {
+	pipe_a = 0,
+	pipe_b,
+	pipe_c,
+	plane_a,
+	plane_b,
+	plane_c,
+	sprite_a,
+	sprite_b,
+	sprite_c,
+	sprite_d
+};
+
+/* Required for sysfs calls */
+extern u32 csc_softlut[CSC_MAX_COEFF_COUNT];
+extern u32 gamma_softlut[GAMMA_CORRECT_MAX_COUNT];
+extern u32 gamma_sprite_softlut[GAMMA_SP_MAX_COUNT];
+extern u32 cb_softlut[CB_MAX_COEFF_COUNT];
+extern u32 hs_softlut[HS_MAX_COEFF_COUNT];
+extern void intel_crtc_load_lut(struct drm_crtc *crtc);
+
+/* Data dump */
+#define CLR_LIMIT_INTERNAL		1
+
+#if CLR_LIMIT_INTERNAL
+static inline int _validate_pipe(int identifier)
+{
+	if (identifier != pipe_a) {
+		DRM_ERROR("This functionality is only for PIPE A\n");
+		return -ENOSYS;
+	}
+	return 0;
+}
+static inline int _validate_plane(int identifier)
+{
+	if (identifier != plane_a) {
+		DRM_ERROR("This functionality is only for Plane A\n");
+		return -ENOSYS;
+	}
+	return 0;
+}
+static inline int _validate_sprite(int identifier)
+{
+	if (identifier != sprite_a && identifier != sprite_b) {
+		DRM_ERROR("This functionality is only for Sprite A/B\n");
+		return -ENOSYS;
+	}
+	return 0;
+}
+#else
+static inline int _validate_pipe(int identifier)
+{
+	return 0;
+}
+static inline int _validate_plane(int identifier)
+{
+	return 0;
+}
+static inline int _validate_sprite(int identifier)
+{
+	return 0;
+}
+#endif
+#define clrmgr_get_drvdata(d) dev_get_drvdata(d)
+#define _get_pipe_from_plane(pid) (pid - plane_a)
+
+
+/* Prototypes */
+int parse_clrmgr_input(uint *dest, char *src, int max, int read);
+int do_intel_enable_csc(struct drm_device *dev, void *data,
+				struct drm_crtc *crtc);
+bool intel_pipe_has_type(const struct drm_crtc *crtc, int type);
+void do_intel_disable_csc(struct drm_device *dev, struct drm_crtc *crtc);
+int intel_crtc_enable_gamma(struct drm_device *dev, u32 identifier);
+int intel_crtc_disable_gamma(struct drm_device *dev, u32 identifier);
+int intel_sprite_cb_adjust(struct drm_device *dev,
+		struct cont_brightlut *cb_ptr);
+int intel_sprite_hs_adjust(struct drm_device *dev,
+		struct hue_saturationlut *hs_ptr);
+void intel_save_clr_mgr_status(struct drm_device *dev);
+bool intel_restore_clr_mgr_status(struct drm_device *dev);
+#endif
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1ac4b11..10ef04e 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3898,6 +3898,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
 	}
 
+	/* Register color manager interface */
+	if (!intel_clrmgr_register(connector))
+		DRM_ERROR("DP: Failed to register color manager features");
+
 	return true;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 3ee1db1..ff9bbd8 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -627,6 +627,10 @@ bool intel_dsi_init(struct drm_device *dev)
 	fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
 	intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
 
+	/* Register to color manager interface */
+	if (!intel_clrmgr_register(connector))
+		DRM_ERROR("Mipi: Failed to register color manager features");
+
 	return true;
 
 err:
-- 
1.7.10.4

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2014-02-20 12:34 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-20 12:37 [PATCH 0/6] Intel Color Manager Framework Shashank Sharma
2014-02-20 12:37 ` Shashank Sharma [this message]
2014-02-20 12:37 ` [PATCH 2/6] drm/i915: Color Manager: Add CSC color correction Shashank Sharma
2014-02-20 12:37 ` [PATCH 3/6] drm/i915: Color manager: Add Gamma correction Shashank Sharma
2014-02-20 12:37 ` [PATCH 4/6] drm/i915: Color manager: brightness/contrast Shashank Sharma
2014-02-20 12:37 ` [PATCH 5/6] drm/i915: Color manager: hue/saturation correction Shashank Sharma
2014-02-20 12:37 ` [PATCH 6/6] drm/i915: Save color manager status Shashank Sharma
2014-02-20 13:11 ` [Intel-gfx] [PATCH 0/6] Intel Color Manager Framework Ville Syrjälä
2014-02-21  3:34   ` Sharma, Shashank
2014-02-21  9:17     ` Ville Syrjälä
2014-02-21 14:20       ` Sharma, Shashank
2014-02-21 14:46         ` [Intel-gfx] " Ville Syrjälä
2014-02-21 15:41           ` Alex Deucher
2014-02-25 11:41             ` [Intel-gfx] " Thierry Reding
2014-02-22  4:11           ` Sharma, Shashank
2014-02-21 14:49         ` Rob Clark
2014-02-21 18:24           ` Sean Paul
2014-02-21 18:57   ` [Intel-gfx] " Stéphane Marchesin
2014-02-22  3:49     ` Sharma, Shashank
2014-02-24  4:04       ` Stéphane Marchesin
2014-02-25  3:56         ` Sharma, Shashank

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1392899847-2641-2-git-send-email-shashank.sharma@intel.com \
    --to=shashank.sharma@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=uma.shankar@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.