blob: 850643534233f0a35a3ff33023ba0c4c511a618b [file] [log] [blame] [edit]
/*
* drivers/display/lcd/aml_lcd_unifykey.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the named License,
* or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <common.h>
#include <malloc.h>
#include <asm/arch/gpio.h>
#ifdef CONFIG_OF_LIBFDT
#include <libfdt.h>
#endif
#include <amlogic/keyunify.h>
#include <amlogic/aml_lcd.h>
#include "aml_lcd_reg.h"
#include "aml_lcd_common.h"
#define LCD_UNIFYKEY_TEST
#define LCDUKEY(fmt, args...) printf("lcd ukey: "fmt"", ## args)
#define LCDUKEYERR(fmt, args...) printf("lcd ukey err: "fmt"", ## args)
#ifdef CONFIG_UNIFY_KEY_MANAGE
int aml_lcd_unifykey_len_check(int key_len, int len)
{
if (key_len < len) {
LCDUKEYERR("invalid unifykey length %d, need %d\n", key_len, len);
return -1;
}
return 0;
}
int aml_lcd_unifykey_header_check(unsigned char *buf, struct aml_lcd_unifykey_header_s *header)
{
header->crc32 = (buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
header->data_len = (buf[4] | (buf[5] << 8));
header->version = (buf[6] | (buf[7] << 8));
header->reserved = (buf[8] | (buf[9] << 8));
return 0;
}
int aml_lcd_unifykey_check(const char *key_name)
{
ssize_t key_size;
int key_exist, isSecure, key_len;
unsigned char buf[550];
struct aml_lcd_unifykey_header_s key_header;
int retry_cnt = 0;
uint32_t key_crc;
unsigned int key_crc32;
int ret;
key_size = 0;
key_exist = 0;
ret = key_unify_query_exist(key_name, &key_exist);
if (ret) {
if (lcd_debug_print_flag)
LCDUKEYERR("%s query exist error\n", key_name);
return -1;
}
if (key_exist == 0) {
if (lcd_debug_print_flag)
LCDUKEYERR("%s is not exist\n", key_name);
return -1;
}
ret = key_unify_query_secure(key_name, &isSecure);
if (ret) {
LCDUKEYERR("%s query secure error\n", key_name);
return -1;
}
if (isSecure) {
LCDUKEYERR("%s is secure key\n", key_name);
return -1;
}
ret = key_unify_query_size(key_name, &key_size);
if (ret) {
LCDUKEYERR("%s query size error\n", key_name);
return -1;
}
key_len = (int)key_size;
if (key_len == 0) {
if (lcd_debug_print_flag)
LCDUKEY("%s size is zero\n", key_name);
return -1;
}
if (lcd_debug_print_flag)
LCDUKEY("%s size: %d\n", key_name, key_len);
lcd_unifykey_read:
ret = key_unify_read(key_name, buf, key_len);
if (ret) {
LCDUKEYERR("%s unify read error\n", key_name);
return -1;
}
/* check header */
if (key_len <= LCD_UKEY_HEAD_SIZE) {
LCDUKEYERR("%s unify key_len %d error\n", key_name, key_len);
return -1;
}
aml_lcd_unifykey_header_check(buf, &key_header);
if (key_len != key_header.data_len) { //length check
if (lcd_debug_print_flag) {
LCDUKEYERR("data_len %d is not match key_len %d\n",
key_header.data_len, key_len);
}
if (retry_cnt < LCD_UKEY_RETRY_CNT_MAX) {
retry_cnt++;
goto lcd_unifykey_read;
} else {
LCDUKEYERR("%s: load unifykey failed\n", key_name);
return -1;
}
}
key_crc = crc32(0, &buf[4], (key_len - 4)); //except crc32
key_crc32 = (unsigned int)key_crc;
if (key_crc32 != key_header.crc32) { //crc32 check
if (lcd_debug_print_flag) {
LCDUKEYERR("crc32 0x%08x is not match 0x%08x\n",
key_header.crc32, key_crc32);
}
if (retry_cnt < LCD_UKEY_RETRY_CNT_MAX) {
retry_cnt++;
goto lcd_unifykey_read;
} else {
LCDUKEYERR("%s: load unifykey failed\n", key_name);
return -1;
}
}
return 0;
}
int aml_lcd_unifykey_get(const char *key_name, unsigned char *buf, int *len)
{
ssize_t key_size;
int key_len;
int ret;
key_size = 0;
ret = aml_lcd_unifykey_check(key_name);
if (ret)
return -1;
ret = key_unify_query_size(key_name, &key_size);
key_len = (int)key_size;
if (key_len > *len) {
LCDUKEYERR("%s size(%d) is bigger than buf_size(%d)\n",
key_name, key_len, *len);
return -1;
}
*len = key_len;
ret = key_unify_read(key_name, buf, key_len);
if (ret) {
LCDUKEYERR("%s unify read error\n", key_name);
return -1;
}
return 0;
}
#ifdef LCD_UNIFYKEY_TEST
static void aml_lcd_test_unifykey(void)
{
int len;
unsigned char buf[150];
const char *str;
int i, n;
uint32_t key_crc;
unsigned int key_crc32;
len = 10 + 105 + 20 + 15;
/* basic */
str = "lcd_unifykey_test";
n = strlen(str);
strcpy((char *)(&buf[10]), str);
buf[10+n] = '\0';
buf[39] = '\0';
buf[40] = 1; /* interface */
buf[41] = 8; /* lcd bits */
buf[42] = 16; /* screen width bit[7:0] */
buf[43] = 0; /* screen width bit[15:8] */
buf[44] = 9; /* screen height bit[7:0] */
buf[45] = 0; /* screen height bit[15:8] */
/* timing */
buf[46] = 0x80; /* h active bit[7:0] */ /* 1920 */
buf[47] = 0x07; /* h active bit[15:8] */
buf[48] = 0x38; /* v active bit[7:0] */ /* 1080 */
buf[49] = 0x04; /* v active bit[15:8] */
buf[50] = 0x98; /* h period bit[7:0] */ /* 2200 */
buf[51] = 0x08; /* h period bit[15:8] */
buf[52] = 0x65; /* v period bit[7:0] */ /* 1125 */
buf[53] = 0x04; /* v period bit[15:8] */
buf[54] = 42; /* hs width bit[7:0] */
buf[55] = 0; /* hs width bit[15:8] */
buf[56] = 145; /* hs bp bit[7:0] */
buf[57] = 0; /* hs bp bit[15:8] */
buf[58] = 0; /* hs pol */
buf[59] = 6; /* vs width bit[7:0] */
buf[60] = 0; /* vs width bit[15:8] */
buf[61] = 31; /* vs bp bit[7:0] */
buf[62] = 0; /* vs bp bit[15:8] */
buf[63] = 0; /* hs pol */
/* customer */
buf[64] = 1; /* fr_adj_type */
buf[65] = 0; /* ss_level */
buf[66] = 1; /* clk_auto_gen */
buf[67] = 0; /* pclk bit[7:0] */
buf[68] = 0; /* pclk bit[15:8] */
buf[69] = 0; /* pclk bit[23:16] */
buf[70] = 0; /* pclk bit[31:24] */
for (i = 71; i < 95; i++)
buf[i] = 0;
/* interface */
buf[95] = 1; /* lvds_repack bit[7:0] */
buf[96] = 0; /* lvds_repack bit[15:8] */
buf[97] = 1; /* lvds_dual_port bit[7:0] */
buf[98] = 0; /* lvds_dual_port bit[15:8] */
buf[99] = 0; /* lvds_pn_swap bit[7:0] */
buf[100] = 0; /* lvds_pn_swap bit[15:8] */
buf[101] = 0; /* lvds_port_swap bit[7:0] */
buf[102] = 0; /* lvds_port_swap bit[15:8] */
buf[103] = 3; /* phy_vswing_level bit[7:0] */
buf[104] = 0; /* phy_vswing_level bit[15:8] */
buf[105] = 0; /* phy_preem_level bit[7:0] */
buf[106] = 0; /* phy_preem_level bit[15:8] */
buf[107] = 1; /* phy_clk_vswing_level bit[7:0] */
buf[108] = 0; /* phy_clk_vswing_level bit[15:8] */
buf[109] = 0; /* phy_clk_preem_level bit[7:0] */
buf[110] = 0; /* phy_clk_preem_level bit[15:8] */
for (i = 111; i < 115; i++)
buf[i] = 0;
/* power */
buf[115] = 0; /* power_on: type */
buf[116] = 0; /* power_on: index */
buf[117] = 1; /* power_on: val */
buf[118] = 20; /* power_on: delay bit[7:0] */
buf[119] = 0; /* power_on: delay bit[15:8] */
buf[120] = 2; /* power_on: type */
buf[121] = 0; /* power_on: index */
buf[122] = 0; /* power_on: val */
buf[123] = 10; /* power_on: delay bit[7:0] */
buf[124] = 0; /* power_on: delay bit[15:8] */
buf[125] = 3; /* power_on: type */
buf[126] = 0; /* power_on: index */
buf[127] = 0; /* power_on: val */
buf[128] = 10; /* power_on: delay bit[7:0] */
buf[129] = 0; /* power_on: delay bit[15:8] */
buf[130] = 0xff; /* power_on: type */
buf[131] = 0; /* power_on: index */
buf[132] = 0; /* power_on: val */
buf[133] = 0; /* power_on: delay bit[7:0] */
buf[134] = 0; /* power_on: delay bit[15:8] */
buf[135] = 2; /* power_off: type */
buf[136] = 0; /* power_off: index */
buf[137] = 0; /* power_off: val */
buf[138] = 20; /* power_off: delay bit[7:0] */
buf[139] = 0; /* power_off: delay bit[15:8] */
buf[140] = 0; /* power_off: type */
buf[141] = 0; /* power_off: index */
buf[142] = 0; /* power_off: val */
buf[143] = 100; /* power_off: delay bit[7:0] */
buf[144] = 0; /* power_off: delay bit[15:8] */
buf[145] = 0xff; /* power_off: type */
buf[146] = 0; /* power_off: index */
buf[147] = 0; /* power_off: val */
buf[148] = 0; /* power_off: delay bit[7:0] */
buf[149] = 0; /* power_off: delay bit[15:8] */
/* header */
buf[4] = 150;
buf[5] = 0; /* data_len */
buf[6] = 1;
buf[7] = 0; /* version */
buf[8] = 0;
buf[9] = 0; /* reserved */
key_crc = crc32(0, &buf[4], 146); //except crc32
key_crc32 = (unsigned int)key_crc;
for (i = 0; i < 4; i++)
buf[i] = (unsigned char)((key_crc32 >> (i * 8)) & 0xff);
key_unify_write("lcd", buf, len);
}
static void aml_lcd_extern_test_unifykey(void)
{
int len;
unsigned char buf[90];
const char *str;
int i, n;
uint32_t key_crc;
unsigned int key_crc32;
len = 10 + 33 + 10 + 4*9;
/* basic */
str = "lcd_extern_unifykey_test";
n = strlen(str);
strcpy((char *)(&buf[10]), str);
buf[10+n] = '\0';
buf[39] = '\0';
buf[40] = 0; /* index */
buf[41] = 0; /* type */
buf[42] = 1; /* status */
/* type */
buf[43] = 0x1c; /* i2c_addr */
buf[44] = 0xff; /* i2c_second_addr */
buf[45] = 0x1; /* i2c_bus */
buf[46] = 0x9; /* cmd_size */
for (i = 47; i < 53; i++)
buf[i] = 0;
/* init */
buf[53] = 0x10;
buf[54] = 0x20;
buf[55] = 0x01;
buf[56] = 0x02;
buf[57] = 0x00;
buf[58] = 0x40;
buf[59] = 0xff;
buf[60] = 0x00;
buf[61] = 0x00; //init step 1
buf[62] = 0x10;
buf[63] = 0x80;
buf[64] = 0x02;
buf[65] = 0x00;
buf[66] = 0x40;
buf[67] = 0x62;
buf[68] = 0x51;
buf[69] = 0x73;
buf[70] = 0x0a; //init step 2
buf[71] = 0xff;
buf[72] = 0x00;
buf[73] = 0x00;
buf[74] = 0x00;
buf[75] = 0x00;
buf[76] = 0x00;
buf[77] = 0x00;
buf[78] = 0x00;
buf[79] = 0x00; //init_on ending
buf[80] = 0xff;
buf[81] = 0x00;
buf[82] = 0x00;
buf[83] = 0x00;
buf[84] = 0x00;
buf[85] = 0x00;
buf[86] = 0x00;
buf[87] = 0x00;
buf[88] = 0x00; //init_off ending
/* header */
buf[4] = 89;
buf[5] = 0; /* data_len */
buf[6] = 1;
buf[7] = 0; /* version */
buf[8] = 0;
buf[9] = 0; /* reserved */
key_crc = crc32(0, &buf[4], 85); //except crc32
key_crc32 = (unsigned int)key_crc;
for (i = 0; i < 4; i++)
buf[i] = (unsigned char)((key_crc32 >> (i * 8)) & 0xff);
key_unify_write("lcd_extern", buf, len);
}
static void aml_bl_test_unifykey(void)
{
int len;
unsigned char buf[102];
const char *str;
int i, n;
uint32_t key_crc;
unsigned int key_crc32;
len = 102;
/* basic */
str = "backlight_unifykey_test";
n = strlen(str);
strcpy((char *)(&buf[10]), str);
buf[10+n] = '\0';
buf[39] = '\0';
/* level */
buf[40] = 128; /* level uboot */
buf[41] = 0;
buf[42] = 128; /* level kernel */
buf[43] = 0;
buf[44] = 255; /* level max */
buf[45] = 0;
buf[46] = 10; /* level min */
buf[47] = 0;
buf[48] = 128; /* level mid */
buf[49] = 0;
buf[50] = 128; /* level mid mapping */
buf[51] = 0;
/* method */
buf[52] = 1; /* bl method */
buf[53] = 0; /* bl enable gpio */
buf[54] = 1; /* bl enable gpio on */
buf[55] = 0; /* bl enable gpio off */
buf[56] = 200; /* power on delay bit[7:0] */
buf[57] = 0; /* power on delay bit[15:8] */
buf[58] = 30; /* power off delay bit[7:0] */
buf[59] = 0; /* power off delay bit[15:8] */
/* pwm */
buf[60] = 10; /* pwm on delay bit[15:8] */
buf[61] = 0; /* pwm on delay bit[15:8] */
buf[62] = 10; /* pwm off delay bit[15:8] */
buf[63] = 0; /* pwm off delay bit[15:8] */
buf[64] = 1; /* pwm method */
buf[65] = 3; /* pwm port */
buf[66] = 180; /* pwm freq bit[7:0] */
buf[67] = 0; /* pwm freq bit[15:8] */
buf[68] = 0; /* pwm freq bit[23:16] */
buf[69] = 0; /* pwm freq bit[31:24] */
buf[70] = 100; /* pwm duty max */
buf[71] = 25; /* pwm duty min */
buf[72] = 1; /* pwm gpio */
buf[73] = 0; /* pwm gpio off */
for (i = 74; i < 84; i++) /* pwm2 for pwm_combo */
buf[i] = 0;
for (i = 84; i < 92; i++) /* pwm/pwm2_level_range for pwm_combo */
buf[i] = 0;
/* customer */
for (i = 92; i < 102; i++)
buf[i] = 0;
/* header */
buf[4] = 102;
buf[5] = 0; /* data_len */
buf[6] = 2;
buf[7] = 0; /* version */
buf[8] = 0;
buf[9] = 0; /* reserved */
key_crc = crc32(0, &buf[4], 98); //except crc32
key_crc32 = (unsigned int)key_crc;
for (i = 0; i < 4; i++)
buf[i] = (unsigned char)((key_crc32 >> (i * 8)) & 0xff);
key_unify_write("backlight", buf, len);
}
#endif
void aml_lcd_unifykey_test(void)
{
#ifdef LCD_UNIFYKEY_TEST
LCDUKEY("Be Careful!! This test will overwrite lcd unifykeys!!\n");
aml_lcd_test_unifykey();
aml_lcd_extern_test_unifykey();
aml_bl_test_unifykey();
#else
LCDUKEY("default bypass for lcd unifykey test\n");
LCDUKEY("should enable macro definition: LCD_UNIFYKEY_TEST\n");
LCDUKEY("Be Careful!! This test will overwrite lcd unifykeys!!\n");
#endif
}
void aml_lcd_unifykey_dump(void)
{
unsigned char *para;
int key_len;
int ret, i;
/* dump unifykey: lcd */
para = (unsigned char *)malloc(sizeof(unsigned char) * LCD_UKEY_LCD_SIZE);
if (!para) {
LCDUKEYERR("%s: Not enough memory\n", __func__);
return;
}
key_len = LCD_UKEY_LCD_SIZE;
memset(para, 0, (sizeof(unsigned char) * key_len));
ret = aml_lcd_unifykey_get("lcd", para, &key_len);
if (ret == 0) {
printf("unifykey: lcd:");
for (i = 0; i < key_len; i++) {
if ((i % 16) == 0)
printf("\n%02x:", (i / 16));
printf(" %02x", para[i]);
}
}
printf("\n");
free(para);
/* dump unifykey: lcd_extern */
para = (unsigned char *)malloc(sizeof(unsigned char) * LCD_UKEY_LCD_EXT_SIZE);
if (!para) {
LCDUKEYERR("%s: Not enough memory\n", __func__);
return;
}
key_len = LCD_UKEY_LCD_EXT_SIZE;
memset(para, 0, (sizeof(unsigned char) * key_len));
ret = aml_lcd_unifykey_get("lcd_extern", para, &key_len);
if (ret == 0) {
printf("unifykey: lcd_extern:");
for (i = 0; i < key_len; i++) {
if ((i % 16) == 0)
printf("\n%02x:", (i / 16));
printf(" %02x", para[i]);
}
}
printf("\n");
free(para);
/* dump unifykey: backlight */
para = (unsigned char *)malloc(sizeof(unsigned char) * LCD_UKEY_BL_SIZE);
if (!para) {
LCDUKEYERR("%s: Not enough memory\n", __func__);
return;
}
key_len = LCD_UKEY_BL_SIZE;
memset(para, 0, (sizeof(unsigned char) * key_len));
ret = aml_lcd_unifykey_get("backlight", para, &key_len);
if (ret == 0) {
printf("unifykey: backlight:");
for (i = 0; i < key_len; i++) {
if ((i % 16) == 0)
printf("\n%02x:", (i / 16));
printf(" %02x", para[i]);
}
}
printf("\n");
free(para);
}
#else
/* dummy driver */
int aml_lcd_unifykey_len_check(int key_len, int len)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int aml_lcd_unifykey_header_check(unsigned char *buf, struct aml_lcd_unifykey_header_s *header)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int aml_lcd_unifykey_check(const char *key_name)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
int aml_lcd_unifykey_get(const char *key_name, unsigned char *buf, int *len)
{
LCDUKEYERR("Don't support unifykey\n");
return -1;
}
void aml_lcd_unifykey_test(void)
{
LCDUKEYERR("Don't support unifykey\n");
}
void aml_lcd_unifykey_dump(void)
{
LCDUKEYERR("Don't support unifykey\n");
}
#endif