diff options
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r-- | drivers/video/fbdev/msm/Makefile | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/lcd_effect.c | 761 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/lcd_effect.h | 90 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdp3.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_ams520.h | 286 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_cmd.h | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_panel.c | 225 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_dsi_status.c | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/msm/mdss_fb.c | 16 |
9 files changed, 1388 insertions, 2 deletions
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index dfbc604dafa5..7e910eb58334 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -8,6 +8,9 @@ mdss-mdp3-objs += mdp3_ppp.o mdp3_ppp_hwio.o mdp3_ppp_data.o obj-$(CONFIG_FB_MSM_MDSS_MDP3) += mdss-mdp3.o mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o dsi_status_6g.o +ifeq ($(CONFIG_MACH_ZUK_Z2_ROW), y) +mdss-mdp-objs += lcd_effect.o +endif mdss-mdp-objs += mdss_mdp_pp.o mdss_mdp_pp_debug.o mdss_mdp_pp_cache_config.o mdss-mdp-objs += mdss_mdp_intf_video.o mdss-mdp-objs += mdss_mdp_intf_cmd.o diff --git a/drivers/video/fbdev/msm/lcd_effect.c b/drivers/video/fbdev/msm/lcd_effect.c new file mode 100644 index 000000000000..567e33ac750e --- /dev/null +++ b/drivers/video/fbdev/msm/lcd_effect.c @@ -0,0 +1,761 @@ +#include "lcd_effect.h" + +extern int is_show_lcd_param; +extern void show_lcd_param(struct dsi_cmd_desc *cmds, int cmd_cnt); +#ifdef CONFIG_BACKLIGHT_LM36923 +int lm36923_sunlight_settings (int level); +#endif + +#define TAG "[LCD_EFFECT: ]" +//#define LCDDEBUG +#ifdef LCDDEBUG +#define lcd_effect_info(fmt, ...) printk(TAG fmt, ##__VA_ARGS__); +#else +#define lcd_effect_info(fmt, ...) do {} while (0) +#endif + +#ifdef READ_LCD_PARAM +static int read_lcd_file = 0; +struct lcd_cmds lcd_txt_cmds; + +#define BUFSIZE 3 +#define LENGHT 256 +#define LENGHT_POS 0 +#define TYPE_POS 1 +#define DELAY_POS 2 +#define DATA_POS 3 +#define FILEPATH "/data/lcd.txt" +static char data_buf[LENGHT] = {0}; +static char *data_pos[LENGHT]; + +static int get_data(char *buf) +{ + char a, b; + + if (buf[0] >= 'A' && buf[0] <= 'F') { + a = buf[0] - 55; + } else if (buf[0] >= 'a' && buf[0] <= 'f') { + a = buf[0] - 87; + } else { + a = buf[0] - 48; + } + if (buf[1] >= 'A' && buf[1] <= 'F') { + b = buf[1] - 55; + } else if (buf[1] >= 'a' && buf[1] <= 'f') { + b = buf[1] - 87; + } else { + b = buf[1] - 48; + } + return a * 16 + b; +} +static void clear_data_and_mem(void) +{ + int i; + + if (lcd_txt_cmds.cnt) { + pr_info("Free mem for lcd txt file's cmds buf.\n"); + for (i = 0; i < lcd_txt_cmds.cnt; i++) { + if (data_pos[i]) + kfree(data_pos[i]); + } + if (lcd_txt_cmds.cmd) + kfree(lcd_txt_cmds.cmd); + lcd_txt_cmds.cnt = 0; + } +} +static int open_lcd_and_get_data(void) +{ + struct file *fp; + int ret, lenght = 0; + int i = 0, j = 0; + char buf[BUFSIZE] = {0}; + char *filepath = FILEPATH; + mm_segment_t old_fs; + + lcd_txt_cmds.cnt = 0; + //清空BUF + for (i = 0; i < LENGHT; i++) { + data_buf[i] = 0; + } + fp = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(fp)) { + pr_info("open file failure\n"); + return -1; + } else { + pr_info("open file success, begin to read\n"); + old_fs = get_fs(); + set_fs(KERNEL_DS); + do { + ret = vfs_read(fp, buf, BUFSIZE, &fp->f_pos); + if (ret == -1) { + pr_info("read file failure\n"); + goto read_err; + } + if (ret == BUFSIZE) { + lenght++; + //buf里留一个位置给lenght + data_buf[lenght] = get_data(buf); //数据格式为:长度+格式 + 延时+数据,现在长度data_buf[0]为空 + + if (buf[2] == '\n') { //标记一行结束 + if (lenght > LENGHT) { //如果一行的数据超过buf的大小 + pr_info("data too long !!!!!!!!!!!!!!!\n"); + goto large_err; + } + + //把data_buf[0]赋值为长度 + data_buf[LENGHT_POS] = lenght + 1; + data_pos[lcd_txt_cmds.cnt] = kmalloc(sizeof(char) * data_buf[LENGHT_POS], GFP_KERNEL); + if (!data_pos[lcd_txt_cmds.cnt]) { + pr_info("kmalloc failure !!!!\n"); + goto mem_err; + } + + memcpy(data_pos[lcd_txt_cmds.cnt], data_buf, data_buf[0]); //把数据拷贝到新分配的空间 + + //pr_info("buf[%d] lenght = %d\n", lcd_txt_cmds.cnt, lenght); + lcd_txt_cmds.cnt++; //数据的行号+1 + lenght = 0; + } + } + } while (ret != 0); + j = 0; + + lcd_txt_cmds.cmd = kmalloc(sizeof(struct dsi_cmd_desc) * lcd_txt_cmds.cnt, GFP_KERNEL); + if (!lcd_txt_cmds.cmd) { + pr_info("kmalloc failure !!!!\n"); + goto cmds_err; + } + + for (i = 0; i < lcd_txt_cmds.cnt; i++) { + lcd_txt_cmds.cmd[i].dchdr.dtype = data_pos[i][TYPE_POS]; + lcd_txt_cmds.cmd[i].dchdr.last = 1; + lcd_txt_cmds.cmd[i].dchdr.vc = 0; + lcd_txt_cmds.cmd[i].dchdr.ack = 0; + lcd_txt_cmds.cmd[i].dchdr.wait = data_pos[i][DELAY_POS]; + lcd_txt_cmds.cmd[i].dchdr.dlen = data_pos[i][LENGHT_POS] - DATA_POS; + lcd_txt_cmds.cmd[i].payload = &data_pos[i][DATA_POS]; + } + + filp_close(fp, NULL); + } + return 0; +cmds_err: +large_err: +read_err: +mem_err: + for (i = 0; i < lcd_txt_cmds.cnt; i++) { + kfree(data_pos[i]); + } + lcd_txt_cmds.cnt = 0; + return -1; +} + + +#endif +static int is_custom_mode(struct lcd_mode_data *mode_data) +{ + return !mode_data->current_mode; +} + +int get_effect_index_by_name(char *name, struct panel_effect_data *lcd_data) +{ + int i; + struct lcd_effect *effect = lcd_data->effect_data->effect; + + for (i = 0; i < lcd_data->effect_data->supported_effect; i++) { + if (!strcmp(name, effect[i].name)) + return i; + } + return -EINVAL; +} +int get_mode_index_by_name(char *name, struct panel_effect_data *lcd_data) +{ + int i; + struct lcd_mode *mode= lcd_data->mode_data->mode; + + for (i = 0; i < lcd_data->mode_data->supported_mode; i++) { + if (!strcmp(name, mode[i].name)) + return i; + } + return -EINVAL; +} +static void update_effect_cmds(struct lcd_effect *effect, int level) +{ + struct lcd_effect_cmd_data *effect_cmd_data = &effect->effect_cmd_data; + struct lcd_effect_cmds *effect_cmd = effect_cmd_data->effect_cmd; + int cmd_cnt = effect_cmd_data->cnt; + int code_cnt ; + int i; + + for (i = 0; i < cmd_cnt; i++) { + code_cnt = effect_cmd[i].effect_code.cnt; + effect_cmd[i].lcd_cmd.cmd->payload = effect_cmd[i].effect_code.code[level >= code_cnt ? code_cnt -1 : level]; + } +} + +static void inline update_level(struct lcd_effect *effect, int level) +{ + effect->level = level; +} + +static inline void update_mode(struct lcd_mode_data *mode_data, int index) +{ + mode_data->current_mode = index; +} + +static inline int get_level(struct lcd_effect *effect) +{ + return effect->level; +} + +static inline int get_effect_cmd_cnt(struct lcd_effect *effect) +{ + return effect->effect_cmd_data.cnt; +} + +static inline int get_head_cmd_cnt(struct lcd_cmds *head_cmd) +{ + return head_cmd->cnt; +} + +static inline struct dsi_cmd_desc *get_head_cmd(struct lcd_cmds *head_cmd) +{ + return head_cmd->cmd; +} +static inline struct lcd_cmds *get_lcd_cmd(struct lcd_effect_cmds *effect_cmd) +{ + return &effect_cmd->lcd_cmd; +} +static inline struct lcd_effect_cmds * get_effect_cmd(struct lcd_effect *effect) +{ + return effect->effect_cmd_data.effect_cmd; +} + +static inline struct dsi_cmd_desc *get_effect_cmd_desc(struct lcd_effect_cmds *effect_cmd) +{ + return effect_cmd->lcd_cmd.cmd; +} +static inline struct dsi_cmd_desc * get_mode_cmd(struct lcd_mode *mode) +{ + return mode->mode_cmd.cmd; +} +static inline int get_mode_cmd_cnt(struct lcd_mode *mode) +{ + return mode->mode_cmd.cnt; +} + +static int get_mode_max_cnt(struct lcd_mode_data *mode_data) +{ + int i; + int temp; + int cnt = 0; + + for (i = 0; i < mode_data->supported_mode; i++) { + temp = mode_data->mode[i].mode_cmd.cnt; + cnt = (cnt > temp) ? cnt : temp; + lcd_effect_info("%s cnt = %d temp = %d\n", __func__, cnt, temp); + } + + return cnt; +} + +static int get_effect_max_cnt(struct lcd_effect_data *effect_data) +{ + int cnt = 0; + int temp; + int i; + + for (i = 0; i < effect_data->supported_effect; i++) { + temp = effect_data->effect[i].effect_cmd_data.cnt; + cnt = cnt + temp; + lcd_effect_info("%s cnt = %d temp = %d\n", __func__, cnt, temp); + } + + return cnt; +} + +static int get_init_code_max_cnt(struct panel_effect_data *panel_data, struct lcd_cmds *save_cmd) +{ + int cnt = save_cmd->cnt; + + cnt += get_mode_max_cnt(panel_data->mode_data); + cnt += get_effect_max_cnt(panel_data->effect_data); + lcd_effect_info("%s cnt: %d\n", __func__, cnt); + return cnt; +} + +static int send_lcd_cmds(struct msm_fb_data_type *mfd, struct lcd_cmds *cmds) +{ + struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL; + struct dcs_cmd_req cmdreq; + struct mdss_panel_data *pdata; + struct mdss_panel_info *pinfo; + + int ret; + + pdata = dev_get_platdata(&mfd->pdev->dev); + ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata, panel_data); + if (mfd->panel_power_state == false) { + pr_err("%s: LCD panel have powered off\n", __func__); + return -EPERM; + } + + pinfo = &(ctrl_pdata->panel_data.panel_info); + if (pinfo->dcs_cmd_by_left) { + if (ctrl_pdata->ndx != DSI_CTRL_LEFT) + return 1; + } + + memset(&cmdreq, 0, sizeof(cmdreq)); + cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL | CMD_REQ_LP_MODE; + cmdreq.rlen = 0; + cmdreq.cb = NULL; + cmdreq.cmds = cmds->cmd; + cmdreq.cmds_cnt = cmds->cnt; + + ret = mdss_dsi_cmdlist_put(ctrl_pdata, &cmdreq); + + return ret; +} + +static struct dsi_cmd_desc *copy_init_code(struct panel_effect_data *panel_data, int *cnt) +{ + int init_cnt = panel_data->save_cmd.cnt; + + memcpy(panel_data->buf, panel_data->save_cmd.cmd, (init_cnt - CMDS_LAST_CNT) * sizeof (struct dsi_cmd_desc)); + *cnt += (init_cnt - CMDS_LAST_CNT); + lcd_effect_info("%s: line=%d\n", __func__,__LINE__); + return (panel_data->buf + (init_cnt - CMDS_LAST_CNT)); +} + +static struct dsi_cmd_desc *copy_sleep_out_code( + struct panel_effect_data *panel_data, + struct dsi_cmd_desc *buf, + int *cnt) +{ + memcpy(buf, panel_data->save_cmd.cmd + panel_data->save_cmd.cnt - CMDS_LAST_CNT, CMDS_LAST_CNT * sizeof (struct dsi_cmd_desc)); + *cnt += CMDS_LAST_CNT; + lcd_effect_info("%s: line=%d\n", __func__,__LINE__); + return (buf + CMDS_LAST_CNT); +} +static struct dsi_cmd_desc *copy_head_code(struct panel_effect_data *panel_data, struct dsi_cmd_desc *buf, int *cnt) +{ + struct lcd_cmds *head_cmds = panel_data->effect_data->head_cmd; + int head_cnt = get_head_cmd_cnt(head_cmds); + + memcpy(buf, head_cmds->cmd, head_cnt * sizeof (struct dsi_cmd_desc)); + *cnt += head_cnt; + + lcd_effect_info("%s: line=%d\n", __func__,__LINE__); + return (buf + head_cnt); +} + +static struct dsi_cmd_desc * copy_single_effect_code( + struct panel_effect_data *panel_data, + struct dsi_cmd_desc *buf, + int index, + int level, + int *cnt) +{ + struct lcd_effect_data *effect_data = panel_data->effect_data; + struct lcd_effect *effect = &effect_data->effect[index]; + struct dsi_cmd_desc *temp = buf; + struct lcd_effect_cmds *effect_cmd; + int cmd_cnt; + int i; + + update_effect_cmds(effect, level); + cmd_cnt = get_effect_cmd_cnt(effect); + effect_cmd = get_effect_cmd(effect); + *cnt += cmd_cnt; + for (i = 0; i < cmd_cnt; i++) + memcpy(temp++, get_effect_cmd_desc(&effect_cmd[i]), sizeof (struct dsi_cmd_desc)); + + return (buf + cmd_cnt); +} + +static struct dsi_cmd_desc *copy_used_effect_code(struct panel_effect_data *panel_data, struct dsi_cmd_desc *buf, int *cnt) +{ + struct dsi_cmd_desc *temp; + struct lcd_effect_data *effect_data = panel_data->effect_data; + struct lcd_effect *effect = effect_data->effect; + + temp = buf; + //protect eys mode(ct level 3) is highest priority + if((effect[EFFECT_CE].level) && (effect[EFFECT_CT].level!=3)) + temp = copy_single_effect_code(panel_data, temp, EFFECT_CE, effect[EFFECT_CE].level, cnt); + else + temp = copy_single_effect_code(panel_data, temp, EFFECT_CT, effect[EFFECT_CT].level, cnt); + + temp = copy_single_effect_code(panel_data, temp, EFFECT_CABC, effect[EFFECT_CABC].level, cnt); + temp = copy_single_effect_code(panel_data, temp, EFFECT_HBM, effect[EFFECT_HBM].level, cnt); + + lcd_effect_info("%s,EFFECT_CE level:%d,EFFECT_CT level:%d,EFFECT_CABC level:%d,EFFECT_HBM level:%d\n",__func__, + effect[EFFECT_CE].level,effect[EFFECT_CT].level,effect[EFFECT_CABC].level,effect[EFFECT_HBM].level); + + return temp; +} + +static struct dsi_cmd_desc *copy_all_effect_code(struct panel_effect_data *panel_data, struct dsi_cmd_desc *buf, int *cnt) +{ + struct dsi_cmd_desc *temp; + struct lcd_effect_data *effect_data = panel_data->effect_data; + struct lcd_effect *effect = effect_data->effect; + struct lcd_effect_cmds *effect_cmd; + int i, j; + int cmd_cnt; + + temp = buf; + for (i = 0; i < effect_data->supported_effect; i++) { + update_effect_cmds(&effect[i], effect[i].level); + cmd_cnt = get_effect_cmd_cnt(&effect[i]); + effect_cmd = get_effect_cmd(&effect[i]); + lcd_effect_info("%s name: [%s] level: [%d],cmd_cnt:[%d]\n", __func__, + effect[i].name, effect[i].level,cmd_cnt); + *cnt += cmd_cnt; + for (j = 0; j < cmd_cnt; j++) + memcpy(temp++, get_effect_cmd_desc(&effect_cmd[j]), sizeof (struct dsi_cmd_desc)); + } + + return temp; +} + +static struct dsi_cmd_desc * copy_mode_code( + struct panel_effect_data *panel_data, + struct dsi_cmd_desc *buf, + int mode_index, + int *cnt) +{ + struct lcd_mode *mode = &panel_data->mode_data->mode[mode_index]; + struct lcd_cmds *mode_cmds = &mode->mode_cmd; + struct dsi_cmd_desc *temp; + int count = 0; + int mode_cnt = get_mode_cmd_cnt(mode); + lcd_effect_info("%s: line=%d mode_cnt=%d\n", __func__,__LINE__,mode_cnt); + if (mode_index == 0) { + lcd_effect_info("%s: current is custom mode\n", __func__); + temp = copy_all_effect_code(panel_data, buf, &count); + *cnt += count; + } else { + lcd_effect_info("%s: current is %s\n", __func__, mode->name); + memcpy(buf, mode_cmds->cmd, mode_cnt * sizeof (struct dsi_cmd_desc)); + temp = buf + mode_cnt; + *cnt += mode_cnt; + } + + return temp; +} + +static int set_mode(struct msm_fb_data_type *mfd, struct panel_effect_data *panel_data, int index) +{ + struct lcd_cmds lcd_cmd; + struct dsi_cmd_desc *temp; + int cnt = 0; + int ret; + + lcd_cmd.cmd = panel_data->buf; + + temp = copy_head_code(panel_data, panel_data->buf, &cnt); + copy_mode_code(panel_data, temp, index, &cnt); + + lcd_cmd.cnt = cnt; + + ret = send_lcd_cmds(mfd, &lcd_cmd); + if (ret >= 0 || ret == -EPERM) { + panel_data->mode_data->current_mode = index; + lcd_effect_info("%s %s success\n", __func__, panel_data->mode_data->mode[index].name); + ret = 0; + } + if (is_show_lcd_param) + show_lcd_param(lcd_cmd.cmd, lcd_cmd.cnt); + + return ret; +} + +static int set_effect(struct msm_fb_data_type *mfd, struct panel_effect_data *panel_data, int index, int level) +{ + struct lcd_cmds lcd_cmd; + struct dsi_cmd_desc *temp; + int cnt = 0; + int ret; + + lcd_cmd.cmd = panel_data->buf; + + temp = copy_head_code(panel_data, panel_data->buf, &cnt); + copy_single_effect_code(panel_data, temp, index, level, &cnt); + + lcd_cmd.cnt = cnt; + + ret = send_lcd_cmds(mfd, &lcd_cmd); + + if (ret >= 0 || ret == -EPERM) { + panel_data->effect_data->effect[index].level = level; + lcd_effect_info("%s name: [%s] level: [%d] success\n", __func__, panel_data->effect_data->effect[index].name, level); + ret = 0; + } + if (is_show_lcd_param) + show_lcd_param(lcd_cmd.cmd, lcd_cmd.cnt); + + return ret; +} + +static int lcd_get_mode(struct lcd_mode_data *mode_data) +{ + if (mode_data == NULL) + return -EINVAL; + + lcd_effect_info("%s name: [%s] index: [%d]\n", __func__, mode_data->mode[mode_data->current_mode].name, mode_data->current_mode); + return mode_data->current_mode; +} + +static int lcd_get_supported_effect_level(struct lcd_effect_data *effect_data, int index) +{ + if (effect_data == NULL || index < 0) { + lcd_effect_info("%s index: %d invalid, max index is: 0 - %d\n", __func__, index, effect_data->supported_effect - 1); + return -EINVAL; + } + + lcd_effect_info("%s name: [%s] index: [%d] max_level: [%d]\n", __func__, effect_data->effect[index].name, index, effect_data->effect[index].max_level); + return effect_data->effect[index].max_level; +} +static int lcd_get_effect_level(struct lcd_effect_data *effect_data, int index) +{ + if (effect_data == NULL || index < 0) { + lcd_effect_info("%s index: %d invalid, max index is: 0 - %d\n", __func__, index, effect_data->supported_effect - 1); + return -EINVAL; + } + + lcd_effect_info("%s name: [%s] index: [%d] level: [%d]\n", __func__, effect_data->effect[index].name, index, effect_data->effect[index].level); + return effect_data->effect[index].level; +} + +static int lcd_get_supported_effect(struct lcd_effect_data *effect_data, struct hal_panel_data *data) +{ + int i; + + if (effect_data == NULL || data == NULL) + return -EINVAL; + + if (EFFECT_COUNT < effect_data->supported_effect) + return -ENOMEM; + + for (i = 0; i < effect_data->supported_effect; i++) { + memcpy(data->effect[i].name, effect_data->effect[i].name, strlen(effect_data->effect[i].name)); + } + data->effect_cnt = effect_data->supported_effect; + + return data->effect_cnt; +} + +static int lcd_get_supported_mode(struct lcd_mode_data *mode_data, struct hal_panel_data *data) +{ + int i; + + if (mode_data == NULL || data == NULL) + return -EINVAL; + + if (MODE_COUNT < mode_data->supported_mode) + return -ENOMEM; + + for (i = 0; i < mode_data->supported_mode; i++) { + memcpy(data->mode[i].name, mode_data->mode[i].name, strlen(mode_data->mode[i].name)); + } + data->mode_cnt = mode_data->supported_mode; + + return data->mode_cnt; +} + +static int lcd_set_mode(struct msm_fb_data_type *mfd, struct panel_effect_data *panel_data, int mode) +{ + int ret; + struct lcd_mode_data *mode_data = panel_data->mode_data; + + if (mode >= mode_data->supported_mode || mode < 0) { + lcd_effect_info("%s mode invalid, max mode is: 0 - %d\n", __func__, mode_data->supported_mode - 1); + return -EINVAL; + } + + ret = set_mode(mfd, panel_data, mode); + + return ret; +} + +static int lcd_set_effect(struct msm_fb_data_type *mfd, struct panel_effect_data *panel_data, int index, int level) +{ + int ret = 0; + struct lcd_effect_data *effect_data = panel_data->effect_data; + +#ifdef CONFIG_BACKLIGHT_LM36923 + if(index == 3){ + ret = lm36923_sunlight_settings(level); + } +#endif + + if (index >= effect_data->supported_effect || index < 0) { + lcd_effect_info("%s index invalid, max index is: 0 - %d\n", __func__, effect_data->supported_effect - 1); + return -EINVAL; + } + + if (level >= effect_data->effect[index].max_level || level < 0) { + lcd_effect_info("%s level invalid, max level is: 0 - %d\n", __func__, effect_data->effect[index].max_level - 1); + return -EINVAL; + } + + ret = set_effect(mfd, panel_data, index, level); + + return ret; +} + +int update_init_code( + struct mdss_dsi_ctrl_pdata *ctrl_pdata, + struct panel_effect_data *panel_data, + void (*mdss_dsi_panel_cmds_send)(struct mdss_dsi_ctrl_pdata *ctrl,struct dsi_panel_cmds *pcmds,u32 flags)) +{ + struct lcd_cmds lcd_cmd; + struct dsi_cmd_desc *temp; + struct lcd_cmds *save_cmd = &panel_data->save_cmd; + int cnt = 0; + int ret = 0; + lcd_cmd.cmd = panel_data->buf; + + temp = copy_init_code(panel_data, &cnt); + + temp = copy_used_effect_code(panel_data, temp, &cnt); + temp = copy_sleep_out_code(panel_data, temp, &cnt); + + lcd_cmd.cnt = cnt; + +#ifdef READ_LCD_PARAM + if (read_lcd_file) + { + if (!open_lcd_and_get_data()) { + ctrl_pdata->on_cmds.cmds = lcd_txt_cmds.cmd; + ctrl_pdata->on_cmds.cmd_cnt = lcd_txt_cmds.cnt; + lcd_effect_info("%s Use Txt file param\n", __func__); + } + } else +#endif + { + ctrl_pdata->on_cmds.cmds = lcd_cmd.cmd; + ctrl_pdata->on_cmds.cmd_cnt = lcd_cmd.cnt; + lcd_effect_info("%s Use system param\n", __func__); + } + + mdss_dsi_panel_cmds_send(ctrl_pdata, &ctrl_pdata->on_cmds,CMD_REQ_COMMIT); + + if (is_show_lcd_param) + show_lcd_param(ctrl_pdata->on_cmds.cmds, ctrl_pdata->on_cmds.cmd_cnt); + + ctrl_pdata->on_cmds.cmds = save_cmd->cmd; + ctrl_pdata->on_cmds.cmd_cnt = save_cmd->cnt; +#ifdef READ_LCD_PARAM + clear_data_and_mem(); +#endif + return ret; +} + + +int handle_lcd_effect_data( + struct msm_fb_data_type *mfd, + struct panel_effect_data *panel_data, + struct hal_panel_ctrl_data *ctrl_data) +{ + struct lcd_effect_data *effect_data = panel_data->effect_data; + struct lcd_mode_data *mode_data = panel_data->mode_data; + int mode_index = mode_data->current_mode; + int ret = 0; + + switch(ctrl_data->id) { + case GET_EFFECT_NUM: + ret = lcd_get_supported_effect(effect_data, &ctrl_data->panel_data); + break; + case GET_EFFECT_LEVEL: + ret = lcd_get_supported_effect_level(effect_data, ctrl_data->index); + break; + case GET_EFFECT: + ret = lcd_get_effect_level(effect_data, ctrl_data->index); + break; + case GET_MODE_NUM: + ret = lcd_get_supported_mode(mode_data, &ctrl_data->panel_data); + break; + case GET_MODE: + ret = lcd_get_mode(mode_data); + break; + case SET_EFFECT: + if (is_custom_mode(mode_data)) { + pr_info("%s:SET_EFFECT,index=%d,level=%d\n",__func__,ctrl_data->index,ctrl_data->level); + ret = lcd_set_effect(mfd, panel_data, ctrl_data->index, ctrl_data->level); + } else { + lcd_effect_info("(%s) can't support change effect\n", mode_data->mode[mode_index].name); + ret = -EINVAL; + } + break; + case SET_MODE: + ret = lcd_set_mode(mfd, panel_data, ctrl_data->mode); + break; + default: + break; + } + + return ret; +} + + +int malloc_lcd_effect_code_buf(struct panel_effect_data *panel_data) +{ + struct lcd_cmds *save_cmd = &panel_data->save_cmd; + if (panel_data->buf == NULL) { + panel_data->buf_size = get_init_code_max_cnt(panel_data, save_cmd); + panel_data->buf = kmalloc(sizeof(struct dsi_cmd_desc) * panel_data->buf_size, GFP_KERNEL); + if ( !panel_data->buf) + return -ENOMEM; + return 0; + } + return 0; +} +#ifdef READ_LCD_PARAM +static int get_lcd_param_func(const char *val, struct kernel_param *kp) +{ + int value; + int ret = param_set_int(val, kp); + + if(ret < 0) + { + pr_info(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + value = *((int*)kp->arg); + if (value) { + read_lcd_file = 1; + pr_info("prepare to read lcd param...\n"); + } else { + read_lcd_file = 0; + pr_info("show lcd param off...\n"); + } + return 0; +} + +module_param_call(read_txt_file, get_lcd_param_func, param_get_int, &read_lcd_file, S_IRUSR | S_IWUSR); +#endif +static int show_lcd_param_func(const char *val, struct kernel_param *kp) +{ + int value; + int ret = param_set_int(val, kp); + + if(ret < 0) + { + pr_info(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + value = *((int*)kp->arg); + if (value) { + is_show_lcd_param = 1; + pr_info("show lcd param on...\n"); + } else { + is_show_lcd_param = 0; + pr_info("show lcd param off...\n"); + } + return 0; +} + +module_param_call(show_lcd_cmd, show_lcd_param_func, param_get_int, &is_show_lcd_param, S_IRUSR | S_IWUSR); diff --git a/drivers/video/fbdev/msm/lcd_effect.h b/drivers/video/fbdev/msm/lcd_effect.h new file mode 100644 index 000000000000..b7f4848b9c3a --- /dev/null +++ b/drivers/video/fbdev/msm/lcd_effect.h @@ -0,0 +1,90 @@ +#ifndef __LCD_EFFECT_H__ +#define __LCD_EFFECT_H__ + +#include <linux/msm_mdp.h> +#include <linux/moduleparam.h> +#include <linux/gpio.h> +#include <asm/uaccess.h> +#include "mdss_panel.h" +#include "mdss_dsi.h" +#include "mdss_fb.h" +#include "mdss_dsi_cmd.h" + +#define CMDS_LAST_CNT 1 +enum { + EFFECT_CE = 0, + EFFECT_CT, + EFFECT_CABC, + EFFECT_HBM, +}; + +struct lcd_cmds { + struct dsi_cmd_desc *cmd; + int cnt; +}; + +struct lcd_effect_code { + char **code; + const int cnt; +}; + +struct lcd_effect_cmds { + struct lcd_effect_code effect_code; + struct lcd_cmds lcd_cmd; +}; + +struct lcd_effect_cmd_data { + struct lcd_effect_cmds *effect_cmd; + const int cnt; +}; + +struct lcd_effect { + //char *aliases; + const char *name; + const int max_level; + int level; + struct lcd_effect_cmd_data effect_cmd_data; +}; + +struct lcd_mode { + //char *aliases; + const char *name; + const int bl_ctrl; + struct lcd_cmds mode_cmd; +}; + +typedef enum { + EFFECT = 0, + MODE = 1, +}control_mode; + +struct lcd_effect_data { + struct lcd_effect *effect; + struct lcd_cmds *head_cmd; + const int supported_effect; +}; + +struct lcd_mode_data { + struct lcd_mode *mode; + struct lcd_cmds *head_cmd; + const int supported_mode; + int current_mode; +}; +struct panel_effect_data { + struct lcd_effect_data *effect_data; + struct lcd_mode_data *mode_data; + struct lcd_cmds save_cmd; + struct dsi_cmd_desc *buf; + int buf_size; +}; + + +int malloc_lcd_effect_code_buf(struct panel_effect_data *panel_data); +int update_init_code( + struct mdss_dsi_ctrl_pdata*, + struct panel_effect_data *, + void (*)(struct mdss_dsi_ctrl_pdata *ctrl,struct dsi_panel_cmds *pcmds,u32 flags)); +int handle_lcd_effect_data(struct msm_fb_data_type *, struct panel_effect_data *, struct hal_panel_ctrl_data *); +int get_effect_index_by_name(char *, struct panel_effect_data *); +int get_mode_index_by_name(char *, struct panel_effect_data *); +#endif diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c index 7454bba68117..f5fbada08c0e 100644 --- a/drivers/video/fbdev/msm/mdp3.c +++ b/drivers/video/fbdev/msm/mdp3.c @@ -2914,7 +2914,7 @@ static int mdp3_resume(struct platform_device *pdev) #endif -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM static int mdp3_runtime_resume(struct device *dev) { bool device_on = true; diff --git a/drivers/video/fbdev/msm/mdss_ams520.h b/drivers/video/fbdev/msm/mdss_ams520.h new file mode 100644 index 000000000000..dc7bf55a4fef --- /dev/null +++ b/drivers/video/fbdev/msm/mdss_ams520.h @@ -0,0 +1,286 @@ +#ifndef MDSS_AMS520_H +#define MDSS_AMS520_H +#include "lcd_effect.h" +#include "mdss_panel.h" + +/*********************************** head cmd *************************************/ +//static char ams520_addr_mode[] = {0x36,0x00}; + +static struct dsi_cmd_desc ams520_packet_head_cmds[] = { +// {{DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ams520_addr_mode)}, ams520_addr_mode}, +}; +/*********************************** ce head cmd *************************************/ +//struct dsi_ctrl_hdr cmd_head={0x29,1,0,0,0,2}; +static char ams520_normal_mode_cmd[] = {0x00,0x00}; + +static struct dsi_cmd_desc ams520_ct_cold_cmd[] = { + {{0x29,1,0,0,0,2},ams520_normal_mode_cmd}, +}; + +static struct dsi_cmd_desc ams520_ct_default_cmd[] = { + {{0x29,1,0,0,0,2},ams520_normal_mode_cmd}, +}; + +static struct dsi_cmd_desc ams520_ct_warm_cmd[] = { + {{0x29,1,0,0,0,2},ams520_normal_mode_cmd}, +}; + +static char ams520_ce_soft_cmd1[] = {0x00,0x00}; +static char ams520_ce_default_cmd1[] = {0x00,0x00}; +static char ams520_ce_bright_cmd1[] = {0x00,0x00}; + +static struct dsi_cmd_desc ams520_ce_soft_cmd[] = { + {{0x29,0,0,0,0,2},ams520_normal_mode_cmd}, + {{0x29,1,0,0,0,2},ams520_ce_soft_cmd1}, +}; +static struct dsi_cmd_desc ams520_ce_default_cmd[] = { + {{0x29,0,0,0,0,2},ams520_normal_mode_cmd}, + {{0x29,1,0,0,0,2},ams520_ce_default_cmd1}, +}; +static struct dsi_cmd_desc ams520_ce_bright_cmd[] = { + {{0x29,0,0,0,0,2},ams520_normal_mode_cmd}, + {{0x29,1,0,0,0,2},ams520_ce_bright_cmd1}, +}; + +/*********************************** ce *************************************/ +static char ams520_ce_enable0[] = {0xF0,0x5A,0x5A}; +static char ams520_seed_edbe[] = {0xED,0xBE}; +static char ams520_seed_b008[] = {0xB0,0x08}; +static char ams520_ce_seed_setv1[] = {0xED,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00, + 0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00, + 0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF};//original 7300K +static char ams520_seed_b01d[] = {0xB0,0x1D}; +static char ams520_ce_seed_setv2[] = {0xED,0xA3,0x01,0x04,0x44,0xE0,0x12,0x03, + 0x08,0xB7,0x4B,0xF4,0xD9,0xAB,0x09, + 0xBB,0xEB,0xE7,0x17,0xFF,0xFF,0xFF};//sRGB 7300K +static char ams520_seed_b032[] = {0xB0,0x32}; +static char ams520_ce_seed_setv3[] = {0xED,0xEA,0x01,0x06,0x00,0xD2,0x06,0x04, + 0x09,0xCC,0x00,0xEB,0xD0,0xFC,0x0B, + 0xD8,0xE9,0xE6,0x0D,0xFF,0xFF,0xE7};//adobe 7300K + +static char ams520_ce0[] = {0x57,0x4C};//Set1 +static char ams520_ce1[] = {0x57,0x44};//Set2 +static char ams520_ce2[] = {0x57,0xA4};//Set3 +//static char ams520_ce3[] = {0x57,0xA4};//CRC off +static char ams520_ce_lock0[] = {0xF0,0xA5,0xA5}; + +char *ams520_ce[] = { + ams520_ce0, + ams520_ce1, + ams520_ce2, + ams520_ce0, +}; +static char *ams520_ce_enable[] = { + ams520_ce_enable0, +}; +static char *ams520_seed_ed[] = { + ams520_seed_edbe, +}; +static char *ams520_seed_b01[] = { + ams520_seed_b008, +}; +static char *ams520_ce_seed_set1[] = { + ams520_ce_seed_setv1, +}; +static char *ams520_seed_b02[] = { + ams520_seed_b01d, +}; +static char *ams520_ce_seed_set2[] = { + ams520_ce_seed_setv2, +}; +static char *ams520_seed_b03[] = { + ams520_seed_b032, +}; +static char *ams520_ce_seed_set3[] = { + ams520_ce_seed_setv3, +}; + +static char *ams520_ce_lock[] = { + ams520_ce_lock0, +}; + +static struct dsi_cmd_desc ams520_effect_ce[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ce0)}, ams520_ce0}, +}; +static struct dsi_cmd_desc ams520_effect_ce_enable[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ce_enable0)}, ams520_ce_enable0}, +}; +static struct dsi_cmd_desc ams520_effect_ed[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_seed_edbe)}, ams520_seed_edbe}, +}; +static struct dsi_cmd_desc ams520_effect_b01[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_seed_b008)}, ams520_seed_b008}, +}; +static struct dsi_cmd_desc ams520_effect_ce_seed_set1[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ce_seed_setv1)}, ams520_ce_seed_setv1}, +}; +static struct dsi_cmd_desc ams520_effect_b02[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_seed_b01d)}, ams520_seed_b01d}, +}; +static struct dsi_cmd_desc ams520_effect_ce_seed_set2[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ce_seed_setv2)}, ams520_ce_seed_setv2}, +}; +static struct dsi_cmd_desc ams520_effect_b03[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_seed_b032)}, ams520_seed_b032}, +}; +static struct dsi_cmd_desc ams520_effect_ce_seed_set3[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ce_seed_setv3)}, ams520_ce_seed_setv3}, +}; +static struct dsi_cmd_desc ams520_effect_ce_lock[] = { + {{DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ams520_ce_lock0)}, ams520_ce_lock0}, +}; + +struct lcd_effect_cmds ams520_effect_ce_cmd[] = { + {{ams520_ce_enable, ARRAY_SIZE(ams520_ce_enable)}, {ams520_effect_ce_enable, ARRAY_SIZE(ams520_effect_ce_enable)}}, + {{ams520_seed_ed, ARRAY_SIZE(ams520_seed_ed)}, {ams520_effect_ed, ARRAY_SIZE(ams520_effect_ed)}}, + {{ams520_seed_b01, ARRAY_SIZE(ams520_seed_b01)}, {ams520_effect_b01, ARRAY_SIZE(ams520_effect_b01)}}, + {{ams520_ce_seed_set1, ARRAY_SIZE(ams520_ce_seed_set1)}, {ams520_effect_ce_seed_set1, ARRAY_SIZE(ams520_effect_ce_seed_set1)}}, + {{ams520_seed_b02, ARRAY_SIZE(ams520_seed_b02)}, {ams520_effect_b02, ARRAY_SIZE(ams520_effect_b02)}}, + {{ams520_ce_seed_set2, ARRAY_SIZE(ams520_ce_seed_set2)}, {ams520_effect_ce_seed_set2, ARRAY_SIZE(ams520_effect_ce_seed_set2)}}, + {{ams520_seed_b03, ARRAY_SIZE(ams520_seed_b03)}, {ams520_effect_b03, ARRAY_SIZE(ams520_effect_b03)}}, + {{ams520_ce_seed_set3, ARRAY_SIZE(ams520_ce_seed_set3)}, {ams520_effect_ce_seed_set3, ARRAY_SIZE(ams520_effect_ce_seed_set3)}}, + {{ams520_ce_lock, ARRAY_SIZE(ams520_ce_lock)}, {ams520_effect_ce_lock, ARRAY_SIZE(ams520_effect_ce_lock)}}, + {{ams520_ce_enable, ARRAY_SIZE(ams520_ce_enable)}, {ams520_effect_ce_enable, ARRAY_SIZE(ams520_effect_ce_enable)}}, + {{ams520_seed_ed, ARRAY_SIZE(ams520_seed_ed)}, {ams520_effect_ed, ARRAY_SIZE(ams520_effect_ed)}}, + {{ams520_ce, ARRAY_SIZE(ams520_ce)}, {ams520_effect_ce, ARRAY_SIZE(ams520_effect_ce)}}, + {{ams520_ce_lock, ARRAY_SIZE(ams520_ce_lock)}, {ams520_effect_ce_lock, ARRAY_SIZE(ams520_effect_ce_lock)}}, +}; + +/*********************************** ct *************************************/ +static char ams520_ct_seed_setv1[] = {0xED,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00, + 0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00, + 0xFF,0xFF,0xFF,0x00,0xFF,0xF6,0xD1,};//original 6000 +static char ams520_ct_seed_setv2[] = {0xED,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00, + 0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00, + 0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF};//original 7300K +static char ams520_ct_seed_setv3[] = {0xED,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00, + 0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00, + 0xFF,0xFF,0xFF,0x00,0xD0,0xE8,0xFF, +}; +static char ams520_ct_seed_setv4[] = {0xED,0xFF,0x00,0x00,0x00,0xFF,0x00,0x00, + 0x00,0xFF,0x00,0xFF,0xFF,0xFF,0x00, + 0xFF,0xFF,0xFF,0x00,0xD0,0xc6,0x73, +}; + +static char *ams520_ct_seed_set1[] = { + ams520_ct_seed_setv1, + ams520_ct_seed_setv1, + ams520_ct_seed_setv1, + ams520_ct_seed_setv4, +}; +static char *ams520_ct_seed_set2[] = { + ams520_ct_seed_setv2, +}; +static char *ams520_ct_seed_set3[] = { + ams520_ct_seed_setv3, +}; + +static struct dsi_cmd_desc ams520_effect_ct_seed_set1[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ct_seed_setv1)}, ams520_ct_seed_setv1}, +}; +static struct dsi_cmd_desc ams520_effect_ct_seed_set2[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ct_seed_setv2)}, ams520_ct_seed_setv2}, +}; +static struct dsi_cmd_desc ams520_effect_ct_seed_set3[] = { + {{DTYPE_GEN_LWRITE, 0, 0, 0, 0, sizeof(ams520_ct_seed_setv3)}, ams520_ct_seed_setv3}, +}; + +struct lcd_effect_cmds ams520_effect_ct_cmd[] = { + {{ams520_ce_enable, ARRAY_SIZE(ams520_ce_enable)}, {ams520_effect_ce_enable, ARRAY_SIZE(ams520_effect_ce_enable)}}, + {{ams520_seed_ed, ARRAY_SIZE(ams520_seed_ed)}, {ams520_effect_ed, ARRAY_SIZE(ams520_effect_ed)}}, + {{ams520_seed_b01, ARRAY_SIZE(ams520_seed_b01)}, {ams520_effect_b01, ARRAY_SIZE(ams520_effect_b01)}}, + {{ams520_ct_seed_set1, ARRAY_SIZE(ams520_ct_seed_set1)}, {ams520_effect_ct_seed_set1, ARRAY_SIZE(ams520_effect_ct_seed_set1)}}, + {{ams520_seed_b02, ARRAY_SIZE(ams520_seed_b02)}, {ams520_effect_b02, ARRAY_SIZE(ams520_effect_b02)}}, + {{ams520_ct_seed_set2, ARRAY_SIZE(ams520_ct_seed_set2)}, {ams520_effect_ct_seed_set2, ARRAY_SIZE(ams520_effect_ct_seed_set2)}}, + {{ams520_seed_b03, ARRAY_SIZE(ams520_seed_b03)}, {ams520_effect_b03, ARRAY_SIZE(ams520_effect_b03)}}, + {{ams520_ct_seed_set3, ARRAY_SIZE(ams520_ct_seed_set3)}, {ams520_effect_ct_seed_set3, ARRAY_SIZE(ams520_effect_ct_seed_set3)}}, + {{ams520_ce_lock, ARRAY_SIZE(ams520_ce_lock)}, {ams520_effect_ce_lock, ARRAY_SIZE(ams520_effect_ce_lock)}}, + {{ams520_ce_enable, ARRAY_SIZE(ams520_ce_enable)}, {ams520_effect_ce_enable, ARRAY_SIZE(ams520_effect_ce_enable)}}, + {{ams520_seed_ed, ARRAY_SIZE(ams520_seed_ed)}, {ams520_effect_ed, ARRAY_SIZE(ams520_effect_ed)}}, + {{ams520_ce, ARRAY_SIZE(ams520_ce)}, {ams520_effect_ce, ARRAY_SIZE(ams520_effect_ce)}}, + {{ams520_ce_lock, ARRAY_SIZE(ams520_ce_lock)}, {ams520_effect_ce_lock, ARRAY_SIZE(ams520_effect_ce_lock)}}, +}; + +/************************************ cabc ***********************************/ +static char ams520_cabc0[] = {0x55, 0x00}; +static char ams520_cabc1[] = {0x55, 0x01}; +static char ams520_cabc2[] = {0x55, 0x02}; +static char ams520_cabc3[] = {0x55, 0x03}; + +char *ams520_cabc[] = { + ams520_cabc0, + ams520_cabc1, + ams520_cabc2, + ams520_cabc3, +}; + +static struct dsi_cmd_desc ams520_effect_cabc[] = { + {{DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ams520_cabc0)}, ams520_cabc0}, +}; +struct lcd_effect_cmds ams520_effect_cabc_cmd[] = { + {{ams520_cabc, ARRAY_SIZE(ams520_cabc)}, {ams520_effect_cabc, ARRAY_SIZE(ams520_effect_cabc)}}, +}; +/************************************* hbm ***********************************/ +static char ams520_hbm0[] = {0x53,0x20};//dimming speed 1frames +static char ams520_hbm1[] = {0x53,0xe0}; +static char ams520_hbm2[] = {0x53,0x28};//dimming speed 32frames +static char ams520_hbm3[] = {0x53,0xe8}; + + +static char *ams520_hbm[] = { + ams520_hbm0,//32frames + ams520_hbm1, + ams520_hbm2, + ams520_hbm3, +}; + +static struct dsi_cmd_desc ams520_effect_hbm[] = { + {{DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ams520_hbm0)}, ams520_hbm0}, +}; + +struct lcd_effect_cmds ams520_effect_hbm_cmd[] = { + {{ams520_hbm, ARRAY_SIZE(ams520_hbm)}, {ams520_effect_hbm, ARRAY_SIZE(ams520_effect_hbm)}}, +}; + + +/************************************** normal mode **************************************/ +static struct dsi_cmd_desc ams520_normal_mode[] = { + {{DTYPE_GEN_LWRITE, 1, 0, 0, 0, sizeof(ams520_normal_mode_cmd)}, ams520_normal_mode_cmd}, +}; + +/*********************************** all effect ************************************/ +struct lcd_effect ams520_effect[] = { + {"ce", ARRAY_SIZE(ams520_ce), 0, {ams520_effect_ce_cmd, ARRAY_SIZE(ams520_effect_ce_cmd)}}, + {"ct", ARRAY_SIZE(ams520_ce), 0, {ams520_effect_ct_cmd, ARRAY_SIZE(ams520_effect_ct_cmd)}}, + {"cabc", ARRAY_SIZE(ams520_cabc), 0, {ams520_effect_cabc_cmd, ARRAY_SIZE(ams520_effect_cabc_cmd)}}, + {"hbm", ARRAY_SIZE(ams520_hbm), 0, {ams520_effect_hbm_cmd, ARRAY_SIZE(ams520_effect_hbm_cmd)}}, +}; +/**************************************************************************************/ + +/************************************** all mode **************************************/ +struct lcd_mode ams520_mode[] = { + {"custom_mode", 0, {ams520_normal_mode, ARRAY_SIZE(ams520_normal_mode)}}, + {"ct_warm_mode", 0, {ams520_ct_warm_cmd, ARRAY_SIZE(ams520_ct_warm_cmd)}}, + {"ct_default_mode", 0, {ams520_ct_default_cmd, ARRAY_SIZE(ams520_ct_default_cmd)}}, + {"ct_cold_mode", 0, {ams520_ct_cold_cmd, ARRAY_SIZE(ams520_ct_cold_cmd)}}, + {"ce_soft_mode", 0, {ams520_ce_soft_cmd, ARRAY_SIZE(ams520_ce_soft_cmd)}}, + {"ce_default_mode", 0, {ams520_ce_default_cmd, ARRAY_SIZE(ams520_ce_default_cmd)}}, + {"ce_bright_mode", 0, {ams520_ce_bright_cmd, ARRAY_SIZE(ams520_ce_bright_cmd)}}, +}; +/**************************************************************************************/ +static struct lcd_cmds ams520_head_cmds = + {ams520_packet_head_cmds, ARRAY_SIZE(ams520_packet_head_cmds)}; + +static struct lcd_effect_data ams520_effect_data = + {ams520_effect, &ams520_head_cmds, ARRAY_SIZE(ams520_effect)}; + +static struct lcd_mode_data ams520_mode_data = + {ams520_mode, &ams520_head_cmds, ARRAY_SIZE(ams520_mode), 0}; + +/**************************************************************************************/ +struct panel_effect_data lcd_ams520_data = { + &ams520_effect_data, + &ams520_mode_data, +}; + +#endif diff --git a/drivers/video/fbdev/msm/mdss_dsi_cmd.h b/drivers/video/fbdev/msm/mdss_dsi_cmd.h index f323a2b665b6..24fe6795d071 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_cmd.h +++ b/drivers/video/fbdev/msm/mdss_dsi_cmd.h @@ -98,6 +98,9 @@ struct dsi_cmd_desc { #define CMD_REQ_MAX 4 #define CMD_REQ_RX 0x0001 #define CMD_REQ_COMMIT 0x0002 +#ifdef CONFIG_MACH_ZUK_Z2_ROW +#define CMD_CLK_CTRL 0x0004 +#endif #define CMD_CLK_CTRL 0x0004 #define CMD_REQ_UNICAST 0x0008 #define CMD_REQ_DMA_TPG 0x0040 diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c index 1ab256cd08af..dd5b5c4b5d10 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_panel.c +++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c @@ -22,6 +22,24 @@ #include <linux/qpnp/pwm.h> #include <linux/err.h> #include <linux/string.h> +#ifdef CONFIG_MACH_ZUK_Z2_ROW +#include <linux/irq.h> +#include <linux/gpio.h> +#include <linux/workqueue.h> +#include <linux/time.h> + #include <linux/fs.h> +#include <linux/string.h> +#include <asm/uaccess.h> +#include "mdss_fb.h" +#include "mdss_ams520.h" + #include <linux/init.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/gpio.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/regulator/consumer.h> +#endif #include "mdss_dsi.h" #include "mdss_dba_utils.h" @@ -33,6 +51,31 @@ #define VSYNC_DELAY msecs_to_jiffies(17) +#ifdef CONFIG_MACH_ZUK_Z2_ROW +struct panel_effect_data lcd_data; + int is_show_lcd_param = 0; +extern struct msm_fb_data_type *mfd_priv; + int show_lcd_param(struct dsi_cmd_desc *cmds, int cmd_cnt) +{ + int i, j; + printk("======================================= cmds_cnt %d =========================================\n", cmd_cnt); + for (i = 0; i < cmd_cnt; i++) { + printk("%2x %2x %2x %2x %2x %2x ", cmds[i].dchdr.dtype, + cmds[i].dchdr.last, + cmds[i].dchdr.vc, + cmds[i].dchdr.ack, + cmds[i].dchdr.wait, + cmds[i].dchdr.dlen); + for (j = 0; j < cmds[i].dchdr.dlen; j++) { + printk("%2x ", cmds[i].payload[j]); + } + printk("\n"); + } + pr_debug("===========================================================================================\n"); + return 0; +} +#endif + DEFINE_LED_TRIGGER(bl_led_trigger); void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl) @@ -247,6 +290,167 @@ static void mdss_dsi_panel_bklt_dcs(struct mdss_dsi_ctrl_pdata *ctrl, int level) mdss_dsi_cmdlist_put(ctrl, &cmdreq); } +#ifdef CONFIG_MACH_ZUK_Z2_ROW +static int lcd_register_rwlen=2; +static int lcd_register_id=0; +static int lcd_register_value=0; +static char lcd_register[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; /* DTYPE_DCS_WRITE1 */ +static struct mdss_dsi_ctrl_pdata *registerctrl; +static struct dsi_cmd_desc write_register_cmd = { + {DTYPE_GEN_LWRITE, 1, 0, 0, 1, 2}, + lcd_register +}; +static struct dsi_cmd_desc read_register_cmd = { + {DTYPE_GEN_READ, 1, 0, 1, 5, 2}, + lcd_register +}; + static int mdss_dsi_read_register(struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct dcs_cmd_req cmdreq; + int i = 0; + memset(&cmdreq, 0, sizeof(cmdreq)); + cmdreq.cmds = &read_register_cmd; + cmdreq.cmds_cnt = 1; + cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL | CMD_REQ_RX; + cmdreq.rlen = 2;//ctrl->status_cmds_rlen; + cmdreq.cb = NULL; + if(ctrl && ctrl->panel_data.panel_info.panel_power_state) { + cmdreq.rbuf = ctrl->status_buf.data; + mdss_dsi_cmdlist_put(ctrl, &cmdreq); + printk("%s: LCD register 0x%02x value:\n", __func__,lcd_register_id); + for(i=0; i<lcd_register_rwlen; i++){ + printk("0x%02x ", ctrl->status_buf.data[i]); + } + printk("\n"); + return ctrl->status_buf.data[0]; + } else { + pr_err("%s: LCD panel have powered off\n", __func__); + return -1; + } +} +void mdss_dsi_write_register(struct mdss_dsi_ctrl_pdata *ctrl) +{ + struct dcs_cmd_req cmdreq; + //pr_err(KERN_ERR"%s,ndx=%d \n", __func__,ctrl->ndx); + memset(&cmdreq, 0, sizeof(cmdreq)); + cmdreq.cmds = &write_register_cmd; + cmdreq.cmds_cnt = 1; + cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; + cmdreq.rlen = 0; + cmdreq.cb = NULL; + if(ctrl && ctrl->panel_data.panel_info.panel_power_state) + mdss_dsi_cmdlist_put(ctrl, &cmdreq); + else + pr_err("%s: LCD panel have powered off\n", __func__); + } + static int set_lcd_register_rwlen_func(const char *val, struct kernel_param *kp) +{ + int ret = param_set_int(val, kp); + if(ret < 0) + { + pr_err(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + lcd_register_rwlen = *((int*)kp->arg); + if(lcd_register_rwlen > sizeof(lcd_register)){ + printk("%s register read write max length is %d\n", __func__,(int)sizeof(lcd_register)); + lcd_register_rwlen = 2; + return 0; + } + write_register_cmd.dchdr.dlen = (short)lcd_register_rwlen; + read_register_cmd.dchdr.dlen = (short)lcd_register_rwlen; + printk("%s register read write length is:%d\n", __func__,lcd_register_rwlen); + return 0; +} + static int get_lcd_register_rwlen_func(char *val, struct kernel_param *kp) +{ + int ret=sprintf(val, "0x%02x\n", lcd_register_rwlen); + printk("%s register read write leagth is:0x%02x\n", __func__,lcd_register_rwlen); + return ret; +} + static int set_lcd_register_id_func(const char *val, struct kernel_param *kp) +{ + int ret = param_set_int(val, kp); + if(ret < 0) + { + pr_err(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + lcd_register_id = *((int*)kp->arg); + lcd_register[0]=lcd_register_id; + printk("%s register id is:%d\n", __func__,lcd_register_id); + return 0; +} + static int get_lcd_register_id_func(char *val, struct kernel_param *kp) +{ + int ret=sprintf(val, "0x%02x\n", lcd_register_id); + printk("%s register id is:0x%02x\n", __func__,lcd_register_id); + return ret; +} + static int set_lcd_register_value_func(const char *val, struct kernel_param *kp) +{ + int ret = param_set_ulong(val, kp); + int i = 0; + if(ret < 0) + { + pr_err(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + lcd_register_value = *((int*)kp->arg); + printk("%s register value is:0x%08x ", __func__,lcd_register_value); + for(i=0; i<lcd_register_rwlen; i++){ + lcd_register[i] = (lcd_register_value >> (lcd_register_rwlen - 1 - i)*8); + printk("0x%02x ", lcd_register[i]); + } + printk("\n"); + mdss_dsi_write_register(registerctrl); + for(i=0; i<sizeof(lcd_register); i++)//8 need change with length + lcd_register[i] = 0x00; + lcd_register_rwlen = 2; + write_register_cmd.dchdr.dlen = (short)lcd_register_rwlen; + read_register_cmd.dchdr.dlen = (short)lcd_register_rwlen; + return 0; +} + static int get_lcd_register_value_func(char *val, struct kernel_param *kp) +{ + int ret=0; + lcd_register_value = mdss_dsi_read_register(registerctrl); + ret=sprintf(val, "0x%02x\n", lcd_register_value); + pr_err(KERN_ERR"%s register value is:0x%02x\n", __func__,lcd_register_value); + //pr_err(KERN_ERR"%s register value 2 is:0x%02x\n", __func__,registerctrl->status_buf.data[1]); + return ret; +} +module_param_call(lcdrwlen, set_lcd_register_rwlen_func,get_lcd_register_rwlen_func, &lcd_register_rwlen, S_IRUSR | S_IWUSR); +module_param_call(lcdid, set_lcd_register_id_func,get_lcd_register_id_func, &lcd_register_id, S_IRUSR | S_IWUSR); +module_param_call(lcdvalue, set_lcd_register_value_func,get_lcd_register_value_func, &lcd_register_value, S_IRUSR | S_IWUSR); +static int lcd_overturn = 0; +static int get_lcd_overturn_func(char *val, struct kernel_param *kp) +{ + int ret=sprintf(val, "0x%02x\n", lcd_overturn); + pr_err(KERN_ERR"%s lcd_overturn is:0x%02x\n", __func__,lcd_overturn); + return ret; +} +static int set_lcd_overturn_func(const char *val, struct kernel_param *kp) +{ + int ret = param_set_int(val, kp); + if(ret < 0) + { + pr_err(KERN_ERR"%s Invalid argument\n", __func__); + return -EINVAL; + } + lcd_overturn = *((int*)kp->arg); + lcd_register[0]=0x36; + if(lcd_overturn) + lcd_register[1]=0xc0; + else + lcd_register[1]=0x0; + mdss_dsi_write_register(registerctrl); + pr_err(KERN_ERR"%s lcdoverturn is:%d\n", __func__,lcd_overturn); + return 0; +} +module_param_call(lcdoverturn, set_lcd_overturn_func,get_lcd_overturn_func, &lcd_overturn, S_IRUSR | S_IWUSR); +#endif + static int mdss_dsi_request_gpios(struct mdss_dsi_ctrl_pdata *ctrl_pdata) { int rc = 0; @@ -948,8 +1152,12 @@ static int mdss_dsi_panel_on(struct mdss_panel_data *pdata) pr_debug("%s: ndx=%d cmd_cnt=%d\n", __func__, ctrl->ndx, on_cmds->cmd_cnt); +#ifdef CONFIG_MACH_ZUK_Z2_ROW + update_init_code(ctrl, &lcd_data, (void *)mdss_dsi_panel_cmds_send); +#else if (on_cmds->cmd_cnt) mdss_dsi_panel_cmds_send(ctrl, on_cmds, CMD_REQ_COMMIT); +#endif if (pinfo->compression_mode == COMPRESSION_DSC) mdss_dsi_panel_dsc_pps_send(ctrl, pinfo); @@ -2627,12 +2835,29 @@ static int mdss_dsi_panel_config_res_properties(struct device_node *np, bool default_timing) { int rc = 0; +#ifdef CONFIG_MACH_ZUK_Z2_ROW + lcd_data = lcd_ams520_data; +#endif mdss_dsi_parse_roi_alignment(np, pt); +#ifdef CONFIG_MACH_ZUK_Z2_ROW + rc = mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, +#else mdss_dsi_parse_dcs_cmds(np, &pt->on_cmds, +#endif "qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state"); +#ifdef CONFIG_MACH_ZUK_Z2_ROW + if (!rc) { + lcd_data.save_cmd.cmd = pt->on_cmds.cmds; + lcd_data.save_cmd.cnt = pt->on_cmds.cmd_cnt; + rc = malloc_lcd_effect_code_buf(&lcd_data); + if (rc) { + printk("malloc_lcd_effect_code_buf failure\n"); + } + } +#endif mdss_dsi_parse_dcs_cmds(np, &pt->post_panel_on_cmds, "qcom,mdss-dsi-post-panel-on-command", NULL); diff --git a/drivers/video/fbdev/msm/mdss_dsi_status.c b/drivers/video/fbdev/msm/mdss_dsi_status.c index 64e9739a46f5..ef07291d4d9a 100644 --- a/drivers/video/fbdev/msm/mdss_dsi_status.c +++ b/drivers/video/fbdev/msm/mdss_dsi_status.c @@ -30,7 +30,11 @@ #include "mdss_panel.h" #include "mdss_mdp.h" +#ifdef CONFIG_MACH_ZUK_Z2_ROW +#define STATUS_CHECK_INTERVAL_MS 2000 +#else #define STATUS_CHECK_INTERVAL_MS 5000 +#endif #define STATUS_CHECK_INTERVAL_MIN_MS 50 #define DSI_STATUS_CHECK_INIT -1 #define DSI_STATUS_CHECK_DISABLE 1 diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c index 64f86084b01d..ee5f15664fd3 100644 --- a/drivers/video/fbdev/msm/mdss_fb.c +++ b/drivers/video/fbdev/msm/mdss_fb.c @@ -55,6 +55,9 @@ #include "mdss_debug.h" #include "mdss_smmu.h" #include "mdss_mdp.h" +#ifdef CONFIG_MACH_ZUK_Z2_ROW +#include "lcd_effect.h" +#endif #include "mdss_livedisplay.h" @@ -83,6 +86,10 @@ * Default value is set to 1 sec. */ #define MDP_TIME_PERIOD_CALC_FPS_US 1000000 +#ifdef CONFIG_MACH_ZUK_Z2_ROW +extern struct panel_effect_data lcd_data; +struct msm_fb_data_type *mfd_priv; +#endif static struct fb_info *fbi_list[MAX_FBI_LIST]; static int fbi_list_index; @@ -5356,7 +5363,14 @@ void mdss_fb_calc_fps(struct msm_fb_data_type *mfd) void mdss_fb_idle_pc(struct msm_fb_data_type *mfd) { - struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd); + struct mdss_overlay_private *mdp5_data = NULL; + + if (mfd) + mdp5_data = mfd_to_mdp5_data(mfd); + else { + pr_warn("%s: mfd is NULL\n", __func__); + return; + } if (mdss_fb_is_power_off(mfd)) return; |