[Intel-gfx] [PATCH] tests/kms_color:Color IGT
Daniel Vetter
daniel at ffwll.ch
Tue Nov 24 09:08:38 PST 2015
On Fri, Nov 20, 2015 at 03:57:24PM +0530, Dhanya Pillai wrote:
> 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>
Fundamental problem with this test is that pretty much all validation
you're doing is checking hw registers. That ties the test with the
platform, means we need to update it everywhere and is also not a real
functional testcase. Please remove that code.
This really needs to be build on top of the crc infrastructure like other
kms tests.
I didn't look how good the coverage for basic input validation (like color
matrix through a too small/big blob property) is. But from a quick look
there seem to be gaps in that area too.
-Daniel
> ---
> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the Intel-gfx
mailing list