it does not work "MXCFB_CSC_UPDATE" on fsl-yocto-Linux-4.9.11

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

it does not work "MXCFB_CSC_UPDATE" on fsl-yocto-Linux-4.9.11

1,025 Views
liangyan
Contributor II

below is imx_csc.c code, but it does not work on kernel 4.9.11, it is wrong?

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/fs.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include <math.h>

#include <linux/mxcfb.h>

static const int ycbcr2rgb_coeff_sd[5][3] = {
{0x095, 0x000, 0x0CC},
{0x095, 0x3CE, 0x398},
{0x095, 0x0FF, 0x000},
{0x3E42, 0x010A, 0x3DD6}, /*B0,B1,B2 */
{0x1, 0x1, 0x1}, /*S0,S1,S2 */
};

static const int ycbcr2rgb_coeff_hd[5][3] = {
{0x095, 0x000, 0x0E5},
{0x095, 0x3E5, 0x3BC},
{0x095, 0x10E, 0x000},
{0x3E10, 0x0099, 0x3DBE}, /*B0,B1,B2 */
{0x1, 0x1, 0x1}, /*S0,S1,S2 */
};

/* */
static double default_matrix_coeff_sd[3][3] = {
{ 1.1644, 0.0000, 1.5962 },
{ 1.1644, -0.3937, -0.8133 },
{ 1.1644, 2.0174, 0.0000 },
};

static double default_matrix_coeff_hd[3][3] = {
{ 1.1644, 0.0000, 1.7927 },
{ 1.1644, -0.2132, -0.5329 },
{ 1.1644, 2.1124, 0.0000 },
};

static double brightness_saturation_matrix[3][3] = {
{ 1.0000, 0.0000, 0.0000 },
{ 0.0000, 1.0000, 0.0000 },
{ 0.0000, 0.0000, 1.0000 },
};

static double hue_matrix[3][3] = {
{ 1.0000, 0.0000, 0.0000 },
{ 0.0000, 1.0000, 0.0000 },
{ 0.0000, 0.0000, 1.0000 },
};

static double SrSgSb_matrix[3][3] = {
{ 1.0000, 0.0000, 0.0000 },
{ 0.0000, 1.0000, 0.0000 },
{ 0.0000, 0.0000, 1.0000 },
};

static double ColorTemp_coeff_matrix[3][3] = {
{ 1.0000, 0.0000, 0.0000 },
{ 0.0000, 1.0000, 0.0000 },
{ 0.0000, 0.0000, 1.0000 },
};

static double ColorTemp_table[3][3];
static double White_P0[3] = { 1.0,1.0,1.0 };
static double White_P1[3] = { 1.0,1.0,1.0 };
static double White_XYZp0[3] = { 1.0,1.0,1.0 };
static double White_XYZp1[3] = { 1.0,1.0,1.0 };

static int enable_color_temp = 0;

static double xyz_inverse_matrix[3][3];
static double XYZ_matrix[3][3];
static double XYZ_inverse_matrix[3][3];

static double KRGB[3];
static double Kmax = 0;

static double color_correction_matrix[5][3];

static int file_matrix[5][3];

static int brightness = 50;
static int contrast = 50;
static int saturation = 50;
static int hue = 50;

static double brightness_coeff = 1.0;
static double contrast_coeff = 1.0;
static double saturation_coeff = 1.0;
static double hue_coeff = 0;

#if 0
static double gamma_value = 1.0;
#endif

static double r_gamma = 1.0;
static double g_gamma = 1.0;
static double b_gamma = 1.0;

#define PI 3.141592

void print_color_correction_matrix()
{
static int num = 1;


printf("\n");
printf("new matrix %d\n",num);

printf("-------------------------------\n");
printf("Hex. table\n");
printf("-------------------------------\n");
printf("{ %lf, %lf, %lf }\n",color_correction_matrix[0][0],color_correction_matrix[0][1],color_correction_matrix[0][2]);
printf("{ %lf, %lf, %lf }\n",color_correction_matrix[1][0],color_correction_matrix[1][1],color_correction_matrix[1][2]);
printf("{ %lf, %lf, %lf }\n",color_correction_matrix[2][0],color_correction_matrix[2][1],color_correction_matrix[2][2]);
printf("{ %lf, %lf, %lf }\n",color_correction_matrix[3][0],color_correction_matrix[3][1],color_correction_matrix[3][2]);
printf("{ %lf, %lf, %lf }\n",color_correction_matrix[4][0],color_correction_matrix[4][1],color_correction_matrix[4][2]);

num++;

}

int gauss_jordan(double a[3][3],double out[3][3])
{
int ipv, i, j;
double inv_pivot, temp;
double big;
int pivot_row = 0, row[3+10];
int n = 3;

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
out[i][j] = a[i][j];
}
}

for(ipv=0 ; ipv < n ; ipv++)
{
big=0.0;
for(i=ipv ; i < n ; i++)
{
if(fabs(out[i][ipv]) > big)
{
big = fabs(out[i][ipv]);
pivot_row = i;
}
}
if(big == 0.0)
{
return(0);
}
row[ipv] = pivot_row;

if(ipv != pivot_row)
{
for(i=0 ; i < n ; i++)
{
temp = out[ipv][i];
out[ipv][i] = out[pivot_row][i];
out[pivot_row][i] = temp;
}
}

inv_pivot = 1.0/out[ipv][ipv];
out[ipv][ipv]=1.0;
for(j=0 ; j < n ; j++)
{
out[ipv][j] *= inv_pivot;
}

for(i=0 ; i<n ; i++)
{
if(i != ipv)
{
temp = out[i][ipv];
out[i][ipv]=0.0;
for(j=0 ; j<n ; j++)
{
out[i][j] -= temp*out[ipv][j];
}
}
}
}

for(j=n-1 ; j>=0 ; j--)
{
if(j != row[j])
{
for(i=0 ; i<n ; i++)
{
temp = out[i][j];
out[i][j]=out[i][row[j]];
out[i][row[j]]=temp;
}
}
}
return(1);
}


void color_temp_func()
{
int i,j;

gauss_jordan(ColorTemp_table,xyz_inverse_matrix);

White_XYZp0[0] = White_P0[0] / White_P0[1];
White_XYZp0[1] = 1.0;
White_XYZp0[2] = White_P0[2] / White_P0[1];

for(i = 0;i < 3;i++)
{
SrSgSb_matrix[i][i] = xyz_inverse_matrix[i][0] * White_XYZp0[0] + xyz_inverse_matrix[i][1] * White_XYZp0[1] + xyz_inverse_matrix[i][2] * White_XYZp0[2];
}

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
XYZ_matrix[i][j] = SrSgSb_matrix[j][j] * ColorTemp_table[i][j];
}
}

gauss_jordan(XYZ_matrix,XYZ_inverse_matrix);

White_XYZp1[0] = White_P1[0] / White_P1[1];
White_XYZp1[1] = 1.0;
White_XYZp1[2] = White_P1[2] / White_P1[1];

for(i = 0;i < 3;i++)
{
KRGB[i] = XYZ_inverse_matrix[i][0] * White_XYZp1[0] + XYZ_inverse_matrix[i][1] * White_XYZp1[1] + XYZ_inverse_matrix[i][2] * White_XYZp1[2];
if(Kmax < KRGB[i])
{
Kmax = KRGB[i];
}
}

ColorTemp_coeff_matrix[0][0] = 1. / Kmax * KRGB[0];
ColorTemp_coeff_matrix[1][1] = 1. / Kmax * KRGB[1];
ColorTemp_coeff_matrix[2][2] = 1. / Kmax * KRGB[2];

ColorTemp_coeff_matrix[0][0] = pow(ColorTemp_coeff_matrix[0][0], 1./r_gamma);
ColorTemp_coeff_matrix[1][1] = pow(ColorTemp_coeff_matrix[1][1], 1./g_gamma);
ColorTemp_coeff_matrix[2][2] = pow(ColorTemp_coeff_matrix[2][2], 1./b_gamma);
}

void multi_color_temp_coeff()
{
int i,j;
double tmp[3][3];

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
tmp[i][j] = color_correction_matrix[i][j] / 128.;
}
}

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
color_correction_matrix[i][j] = ColorTemp_coeff_matrix[i][i] * tmp[i][j];
}
}


for(i = 0;i < 3;i++)
{
color_correction_matrix[3][i] = (color_correction_matrix[i][0] * -16.) + (color_correction_matrix[i][1] * -128.) + (color_correction_matrix[i][2] * -128.);
}

for(i = 0;i < 3;i++)
{
color_correction_matrix[3][i] = color_correction_matrix[3][i] * 2.0;
}


for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
color_correction_matrix[i][j] = color_correction_matrix[i][j] * 128.;
}
}

}

void create_color_correction_matrix()
{
int i,j;

double tmp;

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
color_correction_matrix[i][j] = color_correction_matrix[i][j] * contrast_coeff;
}
}

brightness_saturation_matrix[0][0] = brightness_coeff;
brightness_saturation_matrix[1][1] = saturation_coeff;
brightness_saturation_matrix[2][2] = saturation_coeff;

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
color_correction_matrix[i][j] = color_correction_matrix[i][j] * brightness_saturation_matrix[j][j];
}
}

hue_matrix[1][1] = cos(hue_coeff * PI / 180.);
hue_matrix[1][2] = sin(hue_coeff * PI / 180.);
hue_matrix[2][1] = sin(hue_coeff * PI / 180.) * -1.;
hue_matrix[2][2] = hue_matrix[1][1];

for(i = 0;i < 3;i++)
{
color_correction_matrix[i][0] = color_correction_matrix[i][0];

tmp = color_correction_matrix[i][1];

color_correction_matrix[i][1] = ( tmp * hue_matrix[1][1] ) + ( color_correction_matrix[i][2] * hue_matrix[2][1] );
color_correction_matrix[i][2] = ( tmp * hue_matrix[1][2] ) + ( color_correction_matrix[i][2] * hue_matrix[2][2] );
}


for(i = 0;i < 3;i++)
{
color_correction_matrix[3][i] = (color_correction_matrix[i][0] * -16.) + (color_correction_matrix[i][1] * -128.) + (color_correction_matrix[i][2] * -128.);
}

for(i = 0;i < 3;i++)
{
color_correction_matrix[3][i] = color_correction_matrix[3][i] * 2.0;
}

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
color_correction_matrix[i][j] = color_correction_matrix[i][j] * 128.;
}
}

color_correction_matrix[4][0] = 1.;
color_correction_matrix[4][1] = 1.;
color_correction_matrix[4][2] = 1.;
}

void fb_set_std_table(int fd_fb,int index)
{
struct mxcfb_csc_matrix csc_matrix;
int retval;

memset(&csc_matrix,0,sizeof(csc_matrix));

if(index == 0)
{
// BT709 standard
memcpy(csc_matrix.param,ycbcr2rgb_coeff_hd,sizeof(ycbcr2rgb_coeff_hd));

}
else if(index == 1)
{
// BT601 standard
memcpy(csc_matrix.param,ycbcr2rgb_coeff_sd,sizeof(ycbcr2rgb_coeff_sd));
}
else if(index == 2)
{
int i,j;

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
csc_matrix.param[i][j] = file_matrix[i][j] & 0x3FF;
}
}
for(i = 0;i < 3;i++)
{
csc_matrix.param[3][i] = file_matrix[3][i] & 0x3FFF;
csc_matrix.param[4][i] = file_matrix[4][i];
}
}
else
{
int i,j;

for(i = 0;i < 3;i++)
{
for(j = 0;j < 3;j++)
{
csc_matrix.param[i][j] = (int)color_correction_matrix[i][j] & 0x3FF;
}
}
for(i = 0;i < 3;i++)
{
csc_matrix.param[3][i] = (int)color_correction_matrix[3][i] & 0x3FFF;
csc_matrix.param[4][i] = (int)color_correction_matrix[4][i];
}
}

printf("\n");

printf("CSC parameters\n");

printf("\n");

printf("-------------------------------\n");
printf("Hex. table\n");
printf("-------------------------------\n");
printf("{ %03X, %03X, %03X }\n",csc_matrix.param[0][0],csc_matrix.param[0][1],csc_matrix.param[0][2]);
printf("{ %03X, %03X, %03X }\n",csc_matrix.param[1][0],csc_matrix.param[1][1],csc_matrix.param[1][2]);
printf("{ %03X, %03X, %03X }\n",csc_matrix.param[2][0],csc_matrix.param[2][1],csc_matrix.param[2][2]);
printf("{ %04X, %04X, %04X }\n",csc_matrix.param[3][0],csc_matrix.param[3][1],csc_matrix.param[3][2]);
printf("{ %03X, %03X, %03X }\n",csc_matrix.param[4][0],csc_matrix.param[4][1],csc_matrix.param[4][2]);

retval = ioctl(fd_fb, MXCFB_CSC_UPDATE, &csc_matrix);
if (retval < 0) {
printf("Ioctl MXCFB_CSC_UPDATE fail!\n");
}
}

void usage()
{
printf(" Usage :\n");
printf(" imx_csc <0 or 1 or f <csc file>> [-b <value>] [-c <value>] [-s <value>] [-h <value>] [-a <xy file>] [-x <x value>] [-y <y value>] [-g <value>]\n");
printf("\n Mandatory Options :\n");
printf(" 0 : Use BT.709 standard(HDTV)\n");
printf(" 1 : Use BT.601 standard(SDTV)\n");
printf(" f <csc file> : Read matrix from file (Other options are ignored)\n");

printf("\n Options : All <value>s set to a percentage(0%% to 100%%) number\n");
printf(" -b <value> : set Brightness value (default 50%%)\n");
printf(" -c <value> : set Contrast value (default 50%%)\n");
printf(" -s <value> : set Saturation value (default 50%%)\n");
printf(" -h <value> : set Hue value (default 50%%)\n");

printf("\n Options : All <value>s set to a fraction (0.0 to 1.0) number\n");
printf(" You must specify all three options. If not, it will be ignored.\n");
printf(" -a <xy file> : Read default xy axis from file (default is ignored)\n");
printf(" -x <value> : set target x axis (default value from xy file)\n");
printf(" -y <value> : set target y axis (default value from xy file)\n");
printf(" gamma value set to a fraction (0.1 to 3.0) number.\n");
printf(" -g <r,g,b> : set target gamma value(default 1.0)\n");
}

void parse_command_line_args (int argc, char **argv)
{
extern int optind; /* getopt sys globals */
extern char *optarg; /* getopt sys globals */
signed char command;

int flag = 0;
struct stat st;

while ((command = getopt(argc, argv, "b:c:s:h:a:x:y:g:")) != -1)
{
switch (command)
{
case 'b':
brightness = atoi(optarg);
if(brightness < 0)
{
printf("Clip to 0%% for braightness\n");
brightness = 0;
}
else if(brightness > 100)
{
printf("Clip to 100%% for braightness\n");
brightness = 100;
}
brightness_coeff = 2.0 * ((float)brightness/100.);
break;

case 'c':
contrast = atoi(optarg);
if(contrast < 0)
{
printf("Clip to 0%% for contrast\n");
contrast = 0;
}
else if(contrast > 100)
{
printf("Clip to 100%% for contrast\n");
contrast = 100;
}
contrast_coeff = 2.0 * ((float)contrast/100.);
break;

case 's':
saturation = atoi(optarg);
if(saturation < 0)
{
printf("Clip to 0%% for saturation\n");
saturation = 0;
}
else if(saturation > 100)
{
printf("Clip to 100%% for saturation\n");
saturation = 100;
}
saturation_coeff = 2.0 * ((float)saturation/100.);
break;

case 'h':
hue = atoi(optarg);
if(hue < 0)
{
printf("Clip to 0%% for hue\n");
hue = 0;
}
else if(hue > 100)
{
printf("Clip to 100%% for hue\n");
hue = 100;
}
if(hue < 50)
{
hue = hue * 2;
hue_coeff = 180 + (180 * ((float)hue/100.));
}
else
{
hue = (hue - 50) * 2;
hue_coeff = 180 * ((float)hue/100.);
}
break;

case 'a':
if(stat(optarg,&st) != 0)
{
printf("xy axis file not found. color temp function is ignored.\n");
flag = 0;
}
else
{
if( (st.st_mode & S_IFMT) == S_IFREG)
{
FILE *fp;
fp = fopen(optarg,"r");
if(fp == NULL)
{
printf("can not open xy axis file. color temp function is ignored.\n");
flag = 0;
}
else
{
// R G B W
fscanf(fp,"%lf,%lf,%lf,%lf",&ColorTemp_table[0][0],&ColorTemp_table[0][1],&ColorTemp_table[0][2],&White_P0[0]); // x
fscanf(fp,"%lf,%lf,%lf,%lf",&ColorTemp_table[1][0],&ColorTemp_table[1][1],&ColorTemp_table[1][2],&White_P0[1]); // y
fclose(fp);

// z
ColorTemp_table[2][0] = 1. - ColorTemp_table[0][0] - ColorTemp_table[1][0];
ColorTemp_table[2][1] = 1. - ColorTemp_table[0][1] - ColorTemp_table[1][1];
ColorTemp_table[2][2] = 1. - ColorTemp_table[0][2] - ColorTemp_table[1][2];
White_P0[2] = 1. - White_P0[0] - White_P0[1];

flag |= 1;
}
}
else
{
printf("xy axis file not found. color temp function is ignored.\n");
flag = 0;
}
}
break;

case 'x':
White_P1[0] = atof(optarg);
flag |= 2;
break;

case 'y':
White_P1[1] = atof(optarg);
flag |= 4;
break;

case 'g':

if(sscanf(optarg,"%lf,%lf,%lf",&r_gamma,&g_gamma,&b_gamma) == EOF)
{
r_gamma = 1.0;
g_gamma = 1.0;
b_gamma = 1.0;
printf("all gamma value set to 1.0\n");
}
#if 0
gamma_value = atof(optarg);
if(gamma_value < 0.1)
{
printf("Clip to 0.1 for gamma\n");
gamma_value = 0.1;
}
else if(gamma_value > 3.0)
{
printf("Clip to 3.0 for gamma\n");
gamma_value = 3.0;
}
#endif
flag |= 8;
break;

default:
usage();
exit(1);
break;
}
}
if(flag == 15)
{
if(White_P0[0] == White_P1[0] && White_P0[1] == White_P1[1])
{
printf("target xy and file xy as same. color temp function is ignored.\n");
}
else
{
White_P1[2] = 1. - White_P1[0] - White_P1[1];
enable_color_temp = 1;
}
}
}

int main(int argc, char *argv[])
{
int fd;
int index = 1;

int i;

FILE *fp;

if(argc < 2)
{
printf("invald arguments!\n");
usage();
return -1;
}

if(strcmp(argv[1],"0") == 0)
{
index = 0;
}
else if(strcmp(argv[1],"1") == 0)
{
index = 1;
}
else if(strcmp(argv[1],"f") == 0)
{
index = 2;
}
else
{
printf("invald arguments!\n");
usage();
return -1;
}

parse_command_line_args(argc, argv);

fd = open("/dev/fb0",O_RDWR);

if(fd < 0)
{
printf("Can not open device\n");
return -1;
}
if(argc == 2)
{
if(index == 0)
{
printf("Set to BT.709 standard(HDTV) and all parameters set to default\n");
}
else
{
printf("Set to BT.601 standard(SDTV) and all parameters set to default\n");
}
fb_set_std_table(fd, index);
}
else
{
if(index == 2)
{
fp = fopen(argv[2],"r");
if(fp == NULL)
{
printf("CSC file open Error!");
close(fd);
return -1;
}
for(i = 0;i < 5;i++)
{
fscanf(fp,"%d,%d,%d",&file_matrix[i][0],&file_matrix[i][1],&file_matrix[i][2]);
}
fb_set_std_table(fd, 2);
fclose(fp);
close(fd);
printf("Done.\n");
return 0;
}
else if(index == 0)
{
memcpy(color_correction_matrix,default_matrix_coeff_hd,sizeof(default_matrix_coeff_hd));
}
else
{
memcpy(color_correction_matrix,default_matrix_coeff_sd,sizeof(default_matrix_coeff_sd));
}

printf("Brightness set to : %d%%(%lf)\n",brightness,brightness_coeff);
printf(" Contrast set to : %d%%(%lf)\n",contrast,contrast_coeff);
printf("Saturation set to : %d%%(%lf)\n",saturation,saturation_coeff);
printf(" Hue set to : %lf degree\n",hue_coeff);

create_color_correction_matrix();
if(enable_color_temp == 1)
{
color_temp_func();
multi_color_temp_coeff();

printf("Default xy value(W): (%lf,%lf)\n",White_P0[0],White_P0[1]);
printf(" Target xy value(W): (%lf,%lf)\n",White_P1[0],White_P1[1]);
printf(" Target gamma value: %lf,%lf,%lf\n",r_gamma,g_gamma,b_gamma);
}
fb_set_std_table(fd, 255);
}
close(fd);
printf("Done.\n");
return 0;
}

Labels (2)
0 Kudos
Reply
4 Replies

955 Views
igorpadykov
NXP Employee
NXP Employee

Hi liang

one can try with unit tests:

mxc_fb_test.c\mxc_fb_test\test - imx-test - i.MX Driver Test Application Software 

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
Reply

955 Views
liangyan
Contributor II

hi igorpadykov

in file mxc_fb_test.c, i can't find   about "MXCFB_CSC_UPDATE" ioctl text?, could you share me this file ? 

0 Kudos
Reply

955 Views
igorpadykov
NXP Employee
NXP Employee
0 Kudos
Reply

955 Views
liangyan
Contributor II

hi igorpadykov 

i read the kernel code ,and find about "MXCFB_CSC_UPDATE" mxc_ipuv3_fb.c\mxc\fbdev\video\drivers.

but i have one questio:

1. int ipu_set_csc_coefficients() funciton , it just setup Color conversion coefficient, and do not setup IPU_DP_COM_CONF_ASYNC0 reg to enable the CSC funciton , is it disabled when IPU finished initialization?, so when I use imx_csc.c to setup CSC is useless?

0 Kudos
Reply