[Intel-gfx] [PATCH] tests/kms_color:Color IGT
Dhanya Pillai
dhanya.p.r at intel.com
Fri Nov 20 02:27:24 PST 2015
From: Dhanya <dhanya.p.r at intel.com>
This patch will verify color correction capability of a display driver.
Gamma/CSC/De-gamma verifications are supported.
Signed-off-by: Dhanya <dhanya.p.r at intel.com>
---
tests/Makefile.sources | 1 +
tests/kms_color.c | 1070 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1071 insertions(+)
create mode 100644 tests/kms_color.c
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index 8fb2de8..906c14f 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -64,6 +64,7 @@ TESTS_progs_M = \
gem_write_read_ring_switch \
kms_addfb_basic \
kms_atomic \
+ kms_color \
kms_cursor_crc \
kms_draw_crc \
kms_fbc_crc \
diff --git a/tests/kms_color.c b/tests/kms_color.c
new file mode 100644
index 0000000..c261c3f
--- /dev/null
+++ b/tests/kms_color.c
@@ -0,0 +1,1070 @@
+/*
+ * Copyright © 2015 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.
+ *
+ */
+
+#include <math.h>
+#include "drmtest.h"
+#include "drm.h"
+#include "igt_debugfs.h"
+#include "igt_kms.h"
+#include "igt_core.h"
+#include "intel_io.h"
+#include "intel_chipset.h"
+#include "igt_aux.h"
+#include<unistd.h>
+#include<stdlib.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+
+
+IGT_TEST_DESCRIPTION("Test Color Features at Pipe level");
+typedef unsigned char u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+#define CSC_MAX_VALS 9
+
+#define GEN9_SPLITGAMMA_MAX_VALS 512
+#define GEN9_8BIT_GAMMA_MAX_VALS 256
+#define GEN9_10BIT_GAMMA_MAX_VALS 1024
+#define GEN9_12BIT_GAMMA_MAX_VALS 513
+#define BDW_MAX_GAMMA ((1 << 24) - 1)
+
+
+#define CSC_COEFF_MAX 0x3FE000000
+#define CSC_COEFF_MIN 0xFFFFFFFC00000000
+
+#define VAR_LEN 100
+/*OFFSETS*/
+
+#define _PIPE_A_CSC_COEFF 0x49010
+#define _PIPE_B_CSC_COEFF 0x49110
+#define GAMMA_8BIT_PIPEA 0x4A000
+#define GAMMA_8BIT_PIPEB 0x4A800
+#define GAMMA_8BIT_PIPEC 0x4B000
+
+#define GAMMA_10BIT_PIPEA 0x4A404
+#define GAMMA_10BIT_PIPEB 0x4AC04
+#define GAMMA_10BIT_PIPEC 0x4B404
+
+#define CSC_TEST 0
+#define GAMMA_TEST 1
+#define DEGAMMA_TEST 2
+#define ENABLE 0
+#define DISABLE 1
+#define RED 0
+#define GREEN 1
+#define BLUE 2
+#define UNITY 3
+#define GAMMA_1 0
+#define GAMMA_2 1
+#define GAMMA_2_2 2
+#define PRIMARY 0
+#define SECONDARY 1
+
+#define CSC_COEFF_UNITY 0x100000000
+
+#define GET_BIT_MASK(n) ((1 << n) - 1)
+#define GET_BITS(x, start, nbits) ((x >> start) & GET_BIT_MASK(nbits))
+#define GET_BITS_ROUNDOFF(x, start, nbits) \
+ ((GET_BITS(x, start, (nbits + 1)) + 1) >> 1)
+
+/*Structure defination will be removed once intergrated in libdrm */
+struct drm_r32g32b32 {
+ __u32 r32;
+ __u32 g32;
+ __u32 b32;
+ __u32 reserved;
+};
+
+struct drm_palette {
+ struct drm_r32g32b32 lut[0];
+};
+
+struct drm_ctm {
+ __s64 ctm_coeff[9];
+};
+
+float ctm_red[9] = {1, 1, 1, 0, 0, 0, 0, 0, 0};
+float ctm_green[9] = {0, 0, 0, 1, 1, 1, 0, 0, 0};
+float ctm_blue[9] = {0, 0, 0, 0, 0, 0, 1, 1, 1};
+float ctm_unity[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
+
+struct data_t {
+ int fb_initial;
+ int drm_fd;
+ int gen;
+ int w, h;
+ igt_display_t display;
+ struct igt_fb fb_prep;
+ struct igt_fb fb, fb1;
+};
+
+
+static int create_blob(int fd, uint64_t *data, int length)
+{
+ struct drm_mode_create_blob blob;
+ int ret = -1;
+
+ blob.data = (uint64_t)data;
+ blob.length = length;
+ blob.blob_id = -1;
+ ret = ioctl(fd, DRM_IOCTL_MODE_CREATEPROPBLOB, &blob);
+ if (!ret)
+ return blob.blob_id;
+ igt_info("Blob creation ioctl failed");
+ return ret;
+}
+
+static void prepare_crtc(struct data_t *data, igt_output_t *output,
+ enum pipe pipe, igt_plane_t *plane, drmModeModeInfo *mode,
+ enum igt_commit_style s)
+{
+ igt_display_t *display = &data->display;
+
+ igt_output_set_pipe(output, pipe);
+
+
+ /* before allocating, free if any older fb */
+ if (data->fb_initial) {
+ igt_remove_fb(data->drm_fd, &data->fb_prep);
+ data->fb_initial = 0;
+ }
+
+ /* allocate fb for plane 1 */
+ data->fb_initial = igt_create_color_fb(data->drm_fd,
+ mode->hdisplay, mode->vdisplay,
+ DRM_FORMAT_XRGB8888,
+ LOCAL_I915_FORMAT_MOD_X_TILED, /* tiled */
+ 0, 0, 1.0,
+ &data->fb_prep);
+ igt_assert(data->fb_initial);
+
+ igt_plane_set_fb(plane, &data->fb_prep);
+
+ igt_display_commit2(display, s);
+}
+static void cleanup_fb(struct data_t *data)
+{
+ igt_display_t *display = &data->display;
+
+ if (data->fb_initial) {
+ igt_remove_fb(data->drm_fd, &data->fb_prep);
+ data->fb_initial = 0;
+ }
+ if (data->fb.fb_id)
+ igt_remove_fb(data->drm_fd, &data->fb);
+
+}
+static void cleanup_crtc(struct data_t *data, igt_output_t *output,
+ igt_plane_t *plane)
+{
+ igt_display_t *display = &data->display;
+
+ if (!plane->is_primary) {
+ igt_plane_t *primary;
+
+ primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+ igt_plane_set_fb(primary, NULL);
+ }
+
+ igt_plane_set_fb(plane, NULL);
+ igt_output_set_pipe(output, PIPE_ANY);
+ igt_display_commit2(display, COMMIT_UNIVERSAL);
+
+}
+
+
+
+static int get_color_property(int drm_fd, int id, int object,
+ char *prop_name, int blob_id)
+{
+ int i = 0, ret = 0;
+ uint64_t value = 0;
+ struct drm_palette *gamma_data = NULL;
+ drmModeObjectPropertiesPtr props = NULL;
+
+ if (id < 0 || ((object != DRM_MODE_OBJECT_CRTC) &&
+ (object != DRM_MODE_OBJECT_PLANE))) {
+ igt_warn("Invalid input to get color property %d", id);
+ return -1;
+ }
+ value = blob_id;
+
+ props = drmModeObjectGetProperties(drm_fd, id, object);
+ if (!props) {
+ igt_warn("\nNo property for object id=%d\n", id);
+ return -1;
+ }
+ for (i = 0; i < props->count_props; i++) {
+ drmModePropertyPtr prop = drmModeGetProperty(drm_fd,
+ props->props[i]);
+ if (strcmp(prop->name, prop_name) == 0) {
+ blob_id = props->prop_values[i];
+ break;
+ }
+ drmModeFreeProperty(prop);
+ }
+
+ ret = blob_id;
+ drmModeFreeObjectProperties(props);
+ if (i == props->count_props) {
+ igt_warn("%s No such property\n", prop_name);
+ return -1;
+ }
+ return ret;
+}
+
+
+static int set_color_property(int drm_fd, int id, int object, char *prop_name,
+ int blob_id)
+{
+ int i = 0, res;
+
+ drmModeObjectPropertiesPtr props = NULL;
+
+ if (id < 0 || ((object != DRM_MODE_OBJECT_CRTC) &&
+ (object != DRM_MODE_OBJECT_PLANE))) {
+ igt_warn("Invalid input to set color property %d", id);
+ return -1;
+ }
+
+ props = drmModeObjectGetProperties(drm_fd, id, object);
+ if (!props) {
+ igt_warn("\nNo property for object id=%d\n", id);
+ return -1;
+ }
+ for (i = 0; i < props->count_props; i++) {
+ drmModePropertyPtr prop = drmModeGetProperty(drm_fd,
+ props->props[i]);
+ if (strcmp(prop->name, prop_name) == 0) {
+ res = drmModeObjectSetProperty(drm_fd, id, object,
+ (uint32_t)prop->prop_id, blob_id);
+
+ if (res) {
+ drmModeFreeProperty(prop);
+ drmModeFreeObjectProperties(props);
+ } else {
+ drmModeFreeProperty(prop);
+ break;
+ }
+ }
+
+ drmModeFreeProperty(prop);
+ }
+ drmModeFreeObjectProperties(props);
+ if (i == props->count_props) {
+ igt_warn("%s No such property\n", prop_name);
+ return -1;
+ }
+ return 0;
+}
+static int64_t convertFloatToBinary(double input)
+{
+
+ int integer_part, count = 0;
+ uint32_t temp_ip, frac_val = 0x00000000;
+ uint64_t integer_val = 0x00000000;
+ int64_t value = 0x0000000000000000;
+ float fractional_part, ip;
+ integer_part = (int)input;
+ fractional_part = input - integer_part;
+ while (fractional_part != 0.000000) {
+ ip = fractional_part * 16;
+ temp_ip = (int)(fractional_part * 16);
+ frac_val = frac_val | (temp_ip << (28 - count * 4));
+ count++;
+ fractional_part = ip - temp_ip;
+ }
+ integer_val = integer_part;
+ value = value | (integer_val << 32);
+ value = value | frac_val;
+ return value;
+
+
+}
+static void write_gamma_lut(int brightness, int contrast, int gamma, uint32_t num_samples,
+ struct drm_r32g32b32 *gamma_ptr)
+{
+ unsigned short Red, Green, Blue;
+ uint32_t r32, b32, g32;
+ uint64_t i, index, val;
+ uint32_t data[num_samples];
+
+ for (i = 0; i < num_samples; i++) {
+ data[i] = (brightness + contrast * pow((double)i, (double)gamma)) * num_samples;
+ Blue = data[i];
+ Green = data[i] >> 8;
+ Red = data[i] >> 16;
+ r32 = Red << 16;
+ b32 = Blue ;
+ g32 = Green << 8;
+ gamma_ptr[i].r32 = r32;
+ gamma_ptr[i].g32 = g32;
+ gamma_ptr[i].b32 = b32;
+ val = 0;
+ val = r32;
+ val <<= 8;
+ val = val | g32;
+ val <<= 8;
+ val = val | b32;
+ }
+}
+static uint64_t get_blob(int fd, int blob_id, int length)
+{
+ struct drm_mode_get_blob blob;
+ int ret = 0;
+ int count = 0;
+
+ blob.blob_id = blob_id;
+ blob.length = length;
+ blob.data = (uint64_t) malloc(blob.length);
+ ret = ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob);
+
+ if (ret)
+ igt_info("GET BLOB Failed\n");
+
+ return blob.data;
+}
+
+static uint32_t csc_coeff(int64_t coeff)
+{
+ uint32_t reg_val, ls_bit_pos, exponent_bits, sign_bit = 0;
+ int32_t mantissa;
+ uint64_t abs_coeff;
+
+ abs_coeff = coeff;
+ if (abs_coeff < (CSC_COEFF_UNITY >> 3)) {
+ exponent_bits = 3;
+ ls_bit_pos = 19;
+ } else if (abs_coeff >= (CSC_COEFF_UNITY >> 3) &&
+ abs_coeff < (CSC_COEFF_UNITY >> 2)) {
+ exponent_bits = 2;
+ ls_bit_pos = 20;
+ } else if (abs_coeff >= (CSC_COEFF_UNITY >> 2)
+ && abs_coeff < (CSC_COEFF_UNITY >> 1)) {
+ exponent_bits = 1;
+ ls_bit_pos = 21;
+ } else if (abs_coeff >= (CSC_COEFF_UNITY >> 1)
+ && abs_coeff < CSC_COEFF_UNITY) {
+ exponent_bits = 0;
+ ls_bit_pos = 22;
+ } else if (abs_coeff >= CSC_COEFF_UNITY &&
+ abs_coeff < (CSC_COEFF_UNITY << 1)) {
+ exponent_bits = 7;
+ ls_bit_pos = 23;
+ } else {
+ exponent_bits = 6;
+ ls_bit_pos = 24;
+ }
+ mantissa = GET_BITS_ROUNDOFF(abs_coeff, ls_bit_pos, CSC_MAX_VALS);
+ if (coeff < 0)
+ sign_bit = 1;
+
+ reg_val = 0;
+ reg_val |= (exponent_bits << 12);
+ reg_val |= mantissa << 3;
+ reg_val |= sign_bit << 15;
+ return reg_val;
+}
+
+static bool validate_ctm_registers(int display, int64_t value[CSC_MAX_VALS])
+{
+ uint32_t temp_reg_val = 0, RValue = 0, OFFSET;
+ uint32_t tmp_val, tmp2_val;
+ bool result = false;
+ uint32_t RY_Val = 0, GY_Val = 0, BY_Val = 0;
+ uint32_t RU_Val = 0, GU_Val = 0, BU_Val = 0;
+ uint32_t RV_Val = 0, GV_Val = 0, BV_Val = 0;
+ char register_to_validate[VAR_LEN];
+ intel_register_access_init(intel_get_pci_device(), 0);
+
+ if (display == PRIMARY)
+ OFFSET = _PIPE_A_CSC_COEFF;
+ else
+ OFFSET = _PIPE_B_CSC_COEFF;
+
+ temp_reg_val = INREG(OFFSET);
+ GY_Val = temp_reg_val & 0xFFFF;
+ tmp_val = csc_coeff(value[1]);
+ if (GY_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", GY_Val, tmp_val, value[1]);
+ return result;
+ }
+ RY_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[0]);
+ if (RY_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[0]);
+ return result;
+ }
+ OFFSET += 4;
+ temp_reg_val = INREG(OFFSET);
+ BY_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[2]);
+ if (BY_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[2]);
+ return result;
+ }
+ OFFSET += 4;
+ temp_reg_val = INREG(OFFSET);
+ RU_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[3]);
+ if (RU_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[3]);
+ return result;
+ }
+ GU_Val = temp_reg_val & 0xFFFF;
+ tmp_val = csc_coeff(value[4]);
+ if (GU_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[4]);
+ return result;
+ }
+ OFFSET += 4;
+ temp_reg_val = INREG(OFFSET);
+ BU_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[5]);
+ if (BU_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[5]);
+ return result;
+ }
+ OFFSET += 4;
+ temp_reg_val = INREG(OFFSET);
+ RV_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[6]);
+ if (RV_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[6]);
+ return result;
+ }
+ GV_Val = temp_reg_val & 0xFFFF;
+ tmp_val = csc_coeff(value[7]);
+ if (GV_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[7]);
+ return result;
+ }
+ OFFSET += 4;
+ temp_reg_val = INREG(OFFSET);
+ BV_Val = (temp_reg_val >> 16) & 0xFFFF;
+ tmp_val = csc_coeff(value[8]);
+ if (BV_Val != tmp_val) {
+ igt_warn("reading register is failed - Reg:%x Val:%x Expected:%x\n", temp_reg_val, tmp_val, value[8]);
+ return result;
+ }
+
+ igt_info("CTM Register test for Coefficient is PASS \n");
+ intel_register_access_fini();
+
+ return true;
+}
+static void enable_plane(struct data_t *data, igt_display_t *display, igt_output_t *output, int pipe1)
+{
+ enum igt_commit_style commit;
+ int res, i;
+ int fb_id, fb_id1;
+ int width, height;
+ uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+ commit = COMMIT_UNIVERSAL;
+ enum pipe pipe;
+ for_each_connected_output(display, output) {
+ drmModeModeInfo *mode;
+ pipe = output->config.pipe;
+
+ if (pipe != pipe1)
+ break;
+ igt_plane_t *plane;
+ igt_output_set_pipe(output, pipe);
+ mode = igt_output_get_mode(output);
+ /*Draw the initial primary plane*/
+ plane = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+
+ prepare_crtc(data, output, pipe, plane, mode, commit);
+ /*Random Size Buffer Creation */
+ width = 600;
+ height = 600;
+
+ plane = igt_output_get_plane(output, IGT_PLANE_2);
+ fb_id = igt_create_color_fb(data->drm_fd,
+ width, height,
+ pixelformat,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0,
+ 1.0,
+ 0.0,
+ &data->fb);
+ igt_plane_set_position(plane, 100, 100);
+
+ igt_plane_set_fb(plane, &data->fb);
+ igt_display_commit2(display, commit);
+ }
+
+}
+static void test_pipe_csc(struct data_t *data, igt_display_t *display, igt_output_t *output,
+ igt_plane_t *plane, int enable, int value, int pipe1)
+{
+ struct drm_ctm *ctm_data = NULL;
+ bool ret = false;
+ ctm_data = (struct drm_ctm *)
+ malloc(sizeof(struct drm_ctm));
+ enum igt_commit_style commit;
+ int res, i;
+ int fb_id, fb_id1;
+ int width, height;
+ uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+ commit = COMMIT_UNIVERSAL;
+ float *ctm;
+ enum pipe pipe;
+ if (!enable)
+ ctm = ctm_unity;
+ else {
+ if (value == RED) {
+ ctm = ctm_red;
+ } else if (value == GREEN) {
+ ctm = ctm_green;
+ } else if (value == BLUE) {
+ ctm = ctm_blue;
+ } else{
+ ctm = ctm_unity;
+ } }
+ for (i = 0; i < CSC_MAX_VALS; i++) {
+ ctm_data->ctm_coeff[i] = convertFloatToBinary(*(ctm + i));
+ }
+
+ int blob_id = create_blob(display->drm_fd,
+ (int *)(ctm_data), sizeof(struct drm_ctm));
+ if (blob_id < 0) {
+ igt_warn("CTM:BLOB IOCTL Fail\n");
+ }
+ igt_assert_lte(0, blob_id);
+ res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC, "CTM", blob_id);
+ if (res < 0)
+ igt_warn("CTM:Set Property Failed\n");
+ igt_assert_lte(0, res);
+ res = get_color_property(display->drm_fd, output->config.crtc->crtc_id, DRM_MODE_OBJECT_CRTC, "CTM", blob_id);
+ if (res < 0)
+ igt_warn("CTM:Get Property Failed\n");
+ igt_assert_lte(0, res);
+ uint64_t blob_address = get_blob(display->drm_fd, res, sizeof(struct drm_ctm));
+ ctm_data = (struct drm_ctm *) (intptr_t) blob_address;
+ i = 0;
+ enable_plane(data, display, output, pipe1);
+ /*Register Verification*/
+ ret = validate_ctm_registers(pipe1, ctm_data->ctm_coeff);
+ if (!ret)
+ igt_warn("Register Verification Failed for CTM");
+ free(ctm_data);
+ igt_assert(ret);
+
+
+}
+
+static bool gamma_register_validation(int pipe, int mode, struct drm_r32g32b32 gamma_lut[mode])
+{
+ uint16_t blue_fract, green_fract, red_fract, blue_fract1, green_fract1, red_fract1, blue_fract2, green_fract2, red_fract2;
+ int ret, count, num_samples, length;
+ uint32_t blue, green, red, word, index, odd_word, even_word;
+ uint32_t offset, gamma;
+ intel_register_access_init(intel_get_pci_device(), 0);
+
+ if (pipe == PRIMARY) {
+ if (mode == GEN9_8BIT_GAMMA_MAX_VALS)
+ offset = GAMMA_8BIT_PIPEA;
+ else
+ offset = GAMMA_10BIT_PIPEA;
+ } else {
+ if (mode == GEN9_8BIT_GAMMA_MAX_VALS)
+ offset = GAMMA_8BIT_PIPEB;
+ else
+ offset = GAMMA_10BIT_PIPEB;
+ }
+
+ switch (mode) {
+ case 0:
+ return true;
+ case GEN9_8BIT_GAMMA_MAX_VALS:
+ count = 0;
+ while (count < GEN9_8BIT_GAMMA_MAX_VALS) {
+ blue = gamma_lut[count].b32;
+ green = gamma_lut[count].g32;
+ red = gamma_lut[count].r32;
+ if (blue >= BDW_MAX_GAMMA)
+ blue = BDW_MAX_GAMMA;
+ if (green >= BDW_MAX_GAMMA)
+ green = BDW_MAX_GAMMA;
+ if (red >= BDW_MAX_GAMMA)
+ red = BDW_MAX_GAMMA;
+
+ blue_fract = (blue >> 16) & 0xFF;
+ green_fract = (green >> 16) & 0xFF;
+ red_fract = (red >> 16) & 0xFF;
+ /* Red (23:16) Green (15:8) and Blue (7:0) */
+ word = red_fract << 16 ;
+ word = word | (green_fract << 8);
+ word = word | blue_fract;
+ gamma = INREG(offset);
+ if (gamma != word) {
+ igt_warn("Register Values not proper read value =%x \t written = %x \t ", gamma, word);
+ return false;
+ }
+ offset += 4;
+ count++;
+ }
+ break;
+ case GEN9_10BIT_GAMMA_MAX_VALS:
+ count = 0;
+ while (count < GEN9_10BIT_GAMMA_MAX_VALS) {
+ blue = gamma_lut[count].b32;
+ green = gamma_lut[count].g32;
+ red = gamma_lut[count].r32;
+ if (blue >= BDW_MAX_GAMMA)
+ blue = BDW_MAX_GAMMA;
+ if (green >= BDW_MAX_GAMMA)
+ green = BDW_MAX_GAMMA;
+ if (red >= BDW_MAX_GAMMA)
+ red = BDW_MAX_GAMMA;
+
+ blue_fract = (blue >> 14) & 0x3FF ;
+ green_fract = (green >> 14) & 0x3FF;
+ red_fract = (red >> 14) & 0x3FF;
+ word = red_fract << 20;
+ word = word | (green_fract << 10);
+ word = word | blue_fract;
+ gamma = INREG(offset);
+ if (gamma != word) {
+ igt_warn("Register Values not proper read value =%x \t written = %x \t ", gamma, word);
+ return false;
+ }
+ count++;
+ }
+ break;
+ case GEN9_SPLITGAMMA_MAX_VALS:
+ count = 0;
+ while (count < GEN9_10BIT_GAMMA_MAX_VALS) {
+ blue = gamma_lut[count].b32;
+ green = gamma_lut[count].g32;
+ red = gamma_lut[count].r32;
+ if (blue >= BDW_MAX_GAMMA)
+ blue = BDW_MAX_GAMMA;
+ if (green >= BDW_MAX_GAMMA)
+ green = BDW_MAX_GAMMA;
+ if (red >= BDW_MAX_GAMMA)
+ red = BDW_MAX_GAMMA;
+ blue_fract = (blue >> 14) & 0x3FF ;
+ green_fract = (green >> 14) & 0x3FF;
+ red_fract = (red >> 14) & 0x3FF;
+ word = red_fract << 20;
+ word = word | (green_fract << 10);
+ word = word | blue_fract;
+ gamma = INREG(offset);
+ if (gamma != word) {
+ igt_warn("Register Values not proper read value =%x \t written = %x \t ", gamma, word);
+ return false;
+ }
+ count++;
+ }
+ break;
+
+ case GEN9_12BIT_GAMMA_MAX_VALS:
+ count = 0;
+ even_word = 0x0;
+ odd_word = 0x0;
+ while (count < GEN9_12BIT_GAMMA_MAX_VALS - 1) {
+ blue = gamma_lut[count].b32;
+ green = gamma_lut[count].g32;
+ red = gamma_lut[count].r32;
+ if (blue >= BDW_MAX_GAMMA)
+ blue = BDW_MAX_GAMMA;
+ if (green >= BDW_MAX_GAMMA)
+ green = BDW_MAX_GAMMA;
+ if (red >= BDW_MAX_GAMMA)
+ red = BDW_MAX_GAMMA;
+
+ red_fract = (red >> 8) & 0xFFFF ;
+ green_fract = (green >> 8) & 0xFFFF;
+ blue_fract = (blue >> 8) & 0xFFFF;
+
+ red_fract1 = red_fract & 0x3F ;
+ green_fract1 = green_fract & 0x3F ;
+ blue_fract1 = blue_fract & 0x3F ;
+ even_word = red_fract1 << 24;
+ even_word = even_word | (green_fract1 << 14) ;
+ even_word = even_word | (blue_fract1 << 4);
+ even_word = even_word & 0xFF0FC3F0 ;
+
+ gamma = INREG(offset);
+ if (gamma != even_word) {
+ igt_warn("EVEN:Register Values not proper read value =%x \t written = %x \t count = %d ", gamma, even_word, count);
+ return false;
+ }
+ gamma = 0x0;
+ red_fract2 = ((red_fract >> 6) & 0x3FF);
+ green_fract2 = ((green_fract >> 6) & 0x3FF);
+ blue_fract2 = ((blue_fract >> 6) & 0x3FF);
+
+ odd_word = (red_fract2 << 20);
+ odd_word = odd_word | (green_fract2 << 10) ;
+ odd_word = odd_word | blue_fract2 ;
+
+ gamma = INREG(offset);
+
+ if (gamma != odd_word) {
+ igt_warn("ODD:Register Values not proper read value =%x \t written = %x \t ", gamma, odd_word);
+ return false;
+ }
+ count++;
+ }
+ break;
+ }
+
+ intel_register_access_fini();
+
+ igt_info("Gamma Values Are Programmed Correctly\n");
+ return true;
+}
+static void test_pipe_degamma(struct data_t *data, igt_display_t *display, igt_output_t *output,
+ igt_plane_t *plane, uint32_t num_samples, int values, int pipe1)
+{
+ struct drm_palette *degamma_data = NULL;
+ int res, ret;
+ float degamma;
+ enum pipe pipe;
+ enum igt_commit_style commit;
+ int i;
+ int fb_id, fb_id1;
+ int width, height;
+ uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+ bool status = false;
+ commit = COMMIT_UNIVERSAL;
+
+ int brightness = 50, contrast = 50, blob_length;
+ if (values == GAMMA_1)
+ degamma = 1.0;
+ else if (values == GAMMA_2)
+ degamma = 2.0;
+ else
+ degamma = 2.2;
+ if (num_samples == 0)
+ blob_length = 1;
+ else
+ blob_length = (sizeof(struct drm_palette) + (num_samples * sizeof(struct drm_r32g32b32)));
+
+ degamma_data = malloc(blob_length);
+ struct drm_r32g32b32 degamma_ptr[num_samples];
+ write_gamma_lut(brightness, contrast, degamma, num_samples, degamma_ptr);
+ for (int i = 0; i < num_samples; i++)
+ degamma_data->lut[i] = degamma_ptr[i];
+ int blob_id = create_blob(display->drm_fd, (uint64_t *)(degamma_data), blob_length);
+ if (blob_id < 0) {
+ igt_warn("Set blob IOCTL failed\n");
+ }
+ igt_assert_lte(0, blob_id);
+ res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC, "PALETTE_BEFORE_CTM", blob_id);
+ ret = get_color_property(display->drm_fd, output->config.crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC, "PALETTE_BEFORE_CTM", blob_id);
+ igt_assert_lte(0, res);
+ igt_assert_lte(0, ret);
+ enable_plane(data, display, output, pipe1);
+ if (num_samples != 0) {
+ status = gamma_register_validation(pipe1, num_samples, degamma_data->lut);
+ free(degamma_data);
+ }
+ igt_assert(status);
+
+
+}
+
+static void test_pipe_gamma(struct data_t *data, igt_display_t *display, igt_output_t *output,
+ uint32_t num_samples, int values, int pipe1)
+{
+ enum igt_commit_style commit;
+ int res, i;
+ int fb_id, fb_id1;
+ int width, height;
+ igt_plane_t *plane;
+ uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+ commit = COMMIT_UNIVERSAL;
+ enum pipe pipe;
+ struct drm_palette *gamma_data = NULL;
+ int ret;
+ bool status = false;
+ float gamma;
+ int brightness = 50, contrast = 50, blob_length;
+ if (values == GAMMA_1)
+ gamma = 1.0;
+ else if (values == GAMMA_2)
+ gamma = 2.0;
+ else if (values == GAMMA_2_2)
+ gamma = 2.2;
+ else
+ gamma = values;
+ if (num_samples == 0)
+ blob_length = 1;
+ else
+ blob_length = (sizeof(struct drm_palette) + (num_samples * sizeof(struct drm_r32g32b32)));
+
+ gamma_data = malloc(blob_length);
+ struct drm_r32g32b32 gamma_ptr[num_samples];
+ write_gamma_lut(brightness, contrast, gamma, num_samples, gamma_ptr);
+
+ for (int i = 0; i < num_samples; i++)
+ gamma_data->lut[i] = gamma_ptr[i];
+
+
+ int blob_id = create_blob(display->drm_fd, (uint64_t *)(gamma_data), blob_length);
+ if (blob_id < 0) {
+ igt_warn("Set blob IOCTL failed\n");
+ }
+ igt_assert_lte(0, blob_id);
+
+
+ res = set_color_property(display->drm_fd, output->config.crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC, "PALETTE_AFTER_CTM", blob_id);
+ if (res < 0) {
+ igt_info("Setting Gamma failed!");
+
+ free(gamma_data);
+ }
+ igt_assert_lte(0, res);
+
+ ret = get_color_property(display->drm_fd, output->config.crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC, "PALETTE_AFTER_CTM", blob_id);
+ if (ret < 0) {
+ igt_info("Getting Gamma failed!");
+ free(gamma_data);
+ }
+ igt_assert_lte(0, ret);
+ enable_plane(data, display, output, pipe1);
+ if (num_samples != 0) {
+
+ status = gamma_register_validation(pipe1, num_samples, gamma_data->lut);
+
+ igt_assert(status);
+ }
+
+ free(gamma_data);
+}
+static void test_pipe_color(struct data_t *data, char *prop_name, int enable, int display_in, int value)
+{
+ igt_display_t *display = &data->display;
+ igt_output_t *output;
+ igt_plane_t *plane;
+ enum pipe pipe;
+ enum igt_commit_style commit;
+ int res, i;
+ int fb_id, fb_id1;
+ int width, height;
+ uint32_t pixelformat = DRM_FORMAT_XRGB8888;
+ commit = COMMIT_UNIVERSAL;
+ for_each_connected_output(display, output) {
+ drmModeModeInfo *mode;
+ pipe = output->config.pipe;
+ if (display_in != 2 && pipe != display_in)
+ break;
+ igt_plane_t *plane;
+ igt_output_set_pipe(output, pipe);
+ mode = igt_output_get_mode(output);
+ /*Draw the initial primary plane*/
+ plane = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
+
+ prepare_crtc(data, output, pipe, plane, mode, commit);
+ /*Random sized Frame buffer creation */
+ width = 600;
+ height = 600;
+
+ plane = igt_output_get_plane(output, IGT_PLANE_2);
+ fb_id = igt_create_color_fb(data->drm_fd,
+ width, height,
+ pixelformat,
+ LOCAL_DRM_FORMAT_MOD_NONE,
+ 0.0,
+ 1.0,
+ 0.0,
+ &data->fb);
+ plane->crtc_x = 100;
+ plane->crtc_y = 100;
+ plane->fb_changed = true;
+ igt_plane_set_fb(plane, &data->fb);
+ igt_display_commit2(display, commit);
+
+ if ((strcmp(prop_name, "gamma_property_8bit") == 0) &&
+ enable == ENABLE){
+ test_pipe_gamma(data, display, output,
+ GEN9_8BIT_GAMMA_MAX_VALS, value, pipe);
+ } else if ((strcmp(prop_name, "gamma_property_8bit") == 0) &&
+ enable == DISABLE) {
+ test_pipe_gamma(data, display, output, 0, value, pipe);
+ } else if ((strcmp(prop_name, "gamma_property_10bit") == 0) &&
+ enable == ENABLE) {
+ test_pipe_gamma(data, display, output, GEN9_10BIT_GAMMA_MAX_VALS, value, pipe);
+ } else if ((strcmp(prop_name, "csc_property") == 0)) {
+ test_pipe_csc(data, display, output, plane, enable, value, pipe);
+ } else if ((strcmp(prop_name, "degamma_property") == 0) &&
+ enable == ENABLE) {
+ test_pipe_degamma(data, display, output, plane, GEN9_SPLITGAMMA_MAX_VALS, value, pipe);
+ } else if ((strcmp(prop_name, "degamma_property") == 0) &&
+ enable == DISABLE) {
+ test_pipe_degamma(data, display, output, plane, 0, value, pipe);
+ } else if ((strcmp(prop_name, "gamma_property_split") == 0) &&
+ enable == ENABLE) {
+ test_pipe_gamma(data, display, output,
+ GEN9_SPLITGAMMA_MAX_VALS, value, pipe);
+ } else if ((strcmp(prop_name, "gamma_property_12bit") == 0) && enable == ENABLE) {
+ test_pipe_gamma(data, display, output,
+ GEN9_12BIT_GAMMA_MAX_VALS, value, pipe);
+
+ } else {
+ igt_info("Invalid Test\n");
+ }
+
+ cleanup_fb(data);
+ plane = igt_output_get_plane(output, IGT_PLANE_2);
+ usleep(2000000);
+ cleanup_crtc(data, output, plane);
+
+ }
+}
+
+static void print_usage(void)
+{
+ igt_info("Usage: ./kms_color \n");
+ igt_info("\t-d\t<display> \t0->primary\t1->Secondary \n");
+ igt_info("\t-t\t<test> \t0->csc \t1->gamma\t2->degamma\n");
+ igt_info("\t-e\t<enable/disable> \t0->enable \t1->disable\n");
+ igt_info("\t-v\t<Values> \tFor csc values: \t0->Red \t1->Green\t2->Blue \t3->Unity \n");
+ igt_info(" \tFor Gamma values:\t0->1.0 \t1->2.0 \t2->2.2 \tx-> Any Gamma Custom Values\n");
+ igt_info("\t-m\t<Mode> \tOnly For Gamma \t0->8bit\t1->10bit\t2->12bit\t3->SplitLevel\n");
+}
+
+main(int argc, char *argv[])
+{
+ struct data_t data = {};
+ int gen = 0;
+ int display_id = 0;
+ int option = 0, count = -1;
+ int display = -1, test = -1, values = -1, enable_in = -1, mode = 0;
+ while ((option = getopt(argc, argv, "d:t:e:v:m:")) != -1) {
+ switch (option) {
+ case 'd':
+ display = atoi(optarg);
+ break;
+ case 't':
+ test = atoi(optarg);
+ break;
+ case 'v':
+ values = atoi(optarg);
+ break;
+ case 'e':
+ enable_in = atoi(optarg);
+ break;
+ case 'm':
+ mode = atoi(optarg);
+ break;
+ default:
+ print_usage();
+ return -1;
+ }
+ }
+ count = argc;
+ igt_skip_on_simulation();
+ igt_subtest_init(argc, argv);
+ igt_fixture{
+ data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
+ kmstest_set_vt_graphics_mode();
+ igt_display_init(&data.display, data.drm_fd);
+ data.gen = intel_gen(intel_get_drm_devid(data.drm_fd));
+ }
+ igt_require(data.gen >= 9);
+ if (count == 1) {
+ igt_info("Color Generic Tests\n");
+ display = 2;
+ values = 1;
+ igt_subtest_f("Enable_Gamma_8bit")
+ test_pipe_color(&data, "gamma_property_8bit", ENABLE, display, values);
+ igt_subtest_f("Enable_Gamma_10bit")
+ test_pipe_color(&data, "gamma_property_10bit", ENABLE, display, values);
+ igt_subtest_f("Enable_Gamma_12bit")
+ test_pipe_color(&data, "gamma_property_12bit", ENABLE, display, values);
+ igt_subtest_f("Enable_SPLIT_GAMMA")
+ test_pipe_color(&data, "gamma_property_split", ENABLE, display, values);
+ igt_subtest_f("Disable_Gamma_8bit")
+ test_pipe_color(&data, "gamma_property_8bit", DISABLE, display, values);
+ igt_subtest_f("CSC_ENABLE")
+ test_pipe_color(&data, "csc_property", ENABLE, display, values);
+ igt_subtest_f("CSC_DISABLE")
+ test_pipe_color(&data, "csc_property", ENABLE, display, values);
+ igt_subtest_f("Enable_De-gamma")
+ test_pipe_color(&data, "degamma_property", ENABLE, display, values);
+ igt_subtest_f("Disable_De-gamma")
+ test_pipe_color(&data, "degamma_property", DISABLE, display, values);
+ } else {
+ if (((count < 7) || (display == -1) || (test == -1) || (values == -1) || (enable_in == -1))) {
+ print_usage();
+ return -1;
+ } else {
+ igt_info("Color Customised Tests\n");
+
+ if (test == CSC_TEST) {
+ igt_subtest_f("CSC")
+ test_pipe_color(&data, "csc_property", enable_in, display, values);
+ } else if (test == GAMMA_TEST) {
+ if (enable_in == ENABLE) {
+ if (mode == 0) {
+ igt_subtest_f("Enable_Gamma_8bit")
+ test_pipe_color(&data, "gamma_property_8bit", ENABLE, display, values);
+ } else if (mode == 1) {
+ igt_subtest_f("Enable_Gamma_10bit")
+ test_pipe_color(&data, "gamma_property_10bit", ENABLE, display, values);
+
+ } else if (mode == 2) {
+ igt_subtest_f("Enable_Gamma_12bit")
+ test_pipe_color(&data, "gamma_property_12bit", ENABLE, display, values);
+
+ } else if (mode == 3) {
+ igt_subtest_f("Enable_SPLIT_GAMMA")
+ test_pipe_color(&data, "gamma_property_split", ENABLE, display, values);
+ }
+ } else {
+ igt_subtest_f("Disable_Gamma_8bit")
+ test_pipe_color(&data, "gamma_property_8bit", DISABLE, display, values);
+
+ }
+ } else if (test == DEGAMMA_TEST) {
+ if (enable_in == ENABLE) {
+ igt_subtest_f("Enable_De-gamma")
+ test_pipe_color(&data, "degamma_property", ENABLE, display, values);
+ } else {
+ igt_subtest_f("Disable_De-gamma")
+ test_pipe_color(&data, "degamma_property", DISABLE, display, values);
+
+ } } else {
+ print_usage();
+ }
+ }
+
+ }
+ igt_fixture{
+ igt_display_fini(&data.display);
+ }
+ igt_exit();
+}
+
--
1.9.1
More information about the Intel-gfx
mailing list