From: Dhanya <dhanya.p.r@xxxxxxxxx> 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@xxxxxxxxx> --- 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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx