Please make sure your patch is tagged with "i-g-t" so it is correctly identified by patchwork, as described in: http://lists.freedesktop.org/archives/intel-gfx/2015-November/079712.html It would also be helpful if the subject line briefly mentions what the patch does. On 20 November 2015 at 10:27, Dhanya Pillai <dhanya.p.r@xxxxxxxxx> wrote: > From: Dhanya <dhanya.p.r@xxxxxxxxx> > > This patch will verify color correction capability of a display driver. > Gamma/CSC/De-gamma verifications are supported. I have made a few specific comments below about this patch, but it would be good to include tests that verify the various features by comparing CRCs of a reference image and the output pipe. This would ensure that what is displayed on screen exactly corresponds to the expected state. > > Signed-off-by: Dhanya <dhanya.p.r@xxxxxxxxx> > --- > tests/Makefile.sources | 1 + > tests/kms_color.c | 1070 ++++++++++++++++++++++++++++++++++++++++++++++++ Please also add the binary name to .gitignore. > 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 This test produces a lot of compiler warnings and an error with the default CFLAGS. I have not mentioned them individually below, but please check and make sure the problems are addressed. > @@ -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"); It would be helpful if a more detailed description of the test could also be included here as a comment, specifying what specific featues are under test and how the results are verified. > +typedef unsigned char u8; > +typedef uint16_t u16; > +typedef uint32_t u32; These typedefs are not used anywhere, so can be removed. > + > +#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 The above defines are not used anywhere. > + > +#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 The PIPEC defines are not used. > + > +#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 The SECONDARY define is not used, and the PRIMARY define appears to be used in two different contexts. Could this be clarified? > + > +#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 */ These are usually prefixed with local_ so that the test will continue to compile when using a libdrm version that does include the new definitions. > +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; Since the test will always fail after this, it is probably better to fail directly in this function using igt_fail_on_f. > +} > + > +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) When function parameters wrap onto new lines, they should generally be aligned under the opening bracket. > +{ > + 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, As above, function parameters should be aligned under the opening bracket. > + 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); Wrong indent here. > +} Please make sure there is a blank line between functions. > +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; This pattern (igt_warn and return -1) is repeated a few times in this function and in set_color_property, but should probably always cause the test to fail. Using the appropriate igt_assert_f or igt_fail_on_f macros here may produce better failure messages and mean the test fails faster when there is a problem. > + } > + 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); Should the test skip rather than fail in this case? > + 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"); Should this be igt_fail_on_f? > + > + 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; Returning from the function here (and in similar places below) will mean igt_register_access_fini is not called. There is a similar issue in gamma_register_validation. > + } > + 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); Is this sleep necassary? > + 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) { Please use igt_subtest_init_parse_opts to add extra options to a test as this allows the standard command line options (such as --list-subtests) to continue working. > + 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); data.gen is only set inside the igt_fixture block, so may not be available outside it. Therefore, this check needs to be inside the igt_fixture block above. > + if (count == 1) { > + igt_info("Color Generic Tests\n"); Missing indentation here. > + display = 2; > + values = 1; > + igt_subtest_f("Enable_Gamma_8bit") Subtest names are generally lower case with words separated by hyphens. Also, since there is no format argument, igt_subtest would be sufficient. > + 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) { The followng subtests are repeated from above. Specifying a specific subtest should be possible using the --run-subtest option, so I don't think the other options to specify a test here are required. > + 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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx