| // SPDX-License-Identifier: (GPL-2.0+ OR MIT) |
| /* |
| * |
| * Copyright (C) 2019 Amlogic, Inc. All rights reserved. |
| * |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/version.h> |
| #include <linux/types.h> |
| #include <linux/slab.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/platform_device.h> |
| #include <linux/delay.h> |
| #include <linux/io.h> |
| #include <linux/fs.h> |
| #include <linux/uaccess.h> |
| #include <linux/amlogic/media/vout/lcd/aml_bl.h> |
| #include <linux/amlogic/media/vout/lcd/lcd_vout.h> |
| #include <linux/amlogic/media/vout/lcd/lcd_tcon_data.h> |
| #include <linux/amlogic/media/vout/lcd/lcd_notify.h> |
| #include <linux/amlogic/media/vout/lcd/lcd_unifykey.h> |
| #include "lcd_reg.h" |
| #include "lcd_common.h" |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| #include <linux/amlogic/media/vout/lcd/lcd_mipi.h> |
| #include "lcd_tablet/mipi_dsi_util.h" |
| #endif |
| #include "lcd_debug.h" |
| #include "lcd_tcon.h" |
| |
| /* 1: unlocked, 0: locked, negative: locked, possible waiters */ |
| struct mutex lcd_tcon_adb_mutex; |
| |
| static struct lcd_debug_info_reg_s *lcd_debug_info_reg; |
| static struct lcd_debug_info_if_s *lcd_debug_info_if; |
| |
| #define PR_BUF_MAX (8 * 1024) |
| |
| /*for tconless reg adb use*/ |
| static struct lcd_tcon_adb_reg_s adb_reg = { |
| .rw_mode = LCD_ADB_TCON_REG_RW_MODE_NULL, |
| .bit_width = ADB_TCON_REG_8_bit, |
| .addr = 0, |
| .len = 0, |
| }; |
| |
| static void lcd_debug_parse_param(char *buf_orig, char **parm) |
| { |
| char *ps, *token; |
| char str[3] = {' ', '\n', '\0'}; |
| unsigned int n = 0; |
| |
| ps = buf_orig; |
| while (1) { |
| token = strsep(&ps, str); |
| if (!token) |
| break; |
| if (*token == '\0') |
| continue; |
| parm[n++] = token; |
| } |
| } |
| |
| static void lcd_debug_info_print(char *print_buf) |
| { |
| char *ps, *token; |
| char str[3] = {'\n', '\0'}; |
| |
| ps = print_buf; |
| while (1) { |
| token = strsep(&ps, str); |
| if (!token) |
| break; |
| if (*token == '\0') { |
| pr_info("\n"); |
| continue; |
| } |
| pr_info("%s\n", token); |
| } |
| } |
| |
| int lcd_debug_info_len(int num) |
| { |
| int ret = 0; |
| |
| if (num >= (PR_BUF_MAX - 1)) { |
| pr_info("%s: string length %d is out of support\n", |
| __func__, num); |
| return 0; |
| } |
| |
| ret = PR_BUF_MAX - 1 - num; |
| return ret; |
| } |
| |
| static const char *lcd_common_usage_str = { |
| "Usage:\n" |
| " echo <0|1> > enable ; 0=disable lcd; 1=enable lcd\n" |
| "\n" |
| " echo type <adj_type> > frame_rate ; set lcd frame rate adjust type\n" |
| " echo set <frame_rate> > frame_rate ; set lcd frame rate(unit in 1/100Hz)\n" |
| " cat frame_rate ; read current lcd frame rate\n" |
| "\n" |
| " echo <num> > test ; show lcd bist pattern(1~7), 0=disable bist\n" |
| "\n" |
| " echo level <val> > ss ; set lcd clk spread spectrum level\n" |
| " echo freq <val> > ss ; set lcd clk spread spectrum freq\n" |
| " echo mode <val> > ss ; set lcd clk spread spectrum mode\n" |
| " cat ss ; show lcd clk spread spectrum information\n" |
| "\n" |
| " echo w<v|h|c|p|mh|mp|t> <reg> <data> > reg ; write data to vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" |
| " echo r<v|h|c|p|mh|mp|t> <reg> > reg ; read vcbus|hiu|cbus|periphs|mipi host|mipi phy reg\n" |
| " echo d<v|h|c|p|mh|mp|t> <reg> <num> > reg ; dump vcbus|hiu|cbus|periphs|mipi host|mipi phy regs\n" |
| "\n" |
| " echo <0|1> > print ; 0=disable debug print; 1=enable debug print\n" |
| " cat print ; read current debug print flag\n" |
| "\n" |
| " echo <cmd> > dump ; change dump info\n" |
| " cat dump ; read specified info\n" |
| "data format:\n" |
| " <cmd> : info, interface, reg, reg2, power, hdr\n" |
| "\n" |
| " echo <cmd> ... > debug ; lcd common debug, use 'cat debug' for help\n" |
| " cat debug ; print help information for debug command\n" |
| "\n" |
| " echo <0|1> > power; lcd power control: 0=lcd power off, 1=lcd power on\n" |
| " echo <on|off> <step_num> <delay> > power_step ; set power on/off step delay(unit: ms)\n" |
| " cat power ; print lcd power on/off step\n" |
| "\n" |
| " cat key_valid ; print lcd_key_valid setting\n" |
| " cat config_load ; print lcd_config load_id(0=dts, 1=unifykey)\n" |
| }; |
| |
| static const char *lcd_debug_usage_str = { |
| "Usage:\n" |
| " echo clk <freq> > debug ; set lcd pixel clock, unit in Hz\n" |
| " echo bit <lcd_bits> > debug ; set lcd bits\n" |
| " echo basic <h_active> <v_active> <h_period> <v_period> <lcd_bits> > debug ; set lcd basic config\n" |
| " echo sync <hs_width> <hs_bp> <hs_pol> <vs_width> <vs_bp> <vs_pol> > debug ; set lcd sync timing\n" |
| "data format:\n" |
| " <xx_pol> : 0=negative, 1=positive\n" |
| "\n" |
| " echo info > debug ; show lcd information\n" |
| " echo reg > debug ; show lcd registers\n" |
| " echo dump > debug ; show lcd information & registers\n" |
| " echo dith <dither_en> <rounding_en> <dither_md> > debug ; set vpu_vencl_dith_ctrl\n" |
| " echo key > debug ; show lcd_key_valid config, and lcd unifykey raw data\n" |
| "\n" |
| " echo reset > debug; reset lcd driver\n" |
| " echo power <0|1> > debug ; lcd power control: 0=power off, 1=power on\n" |
| }; |
| |
| static const char *lcd_debug_change_usage_str = { |
| "Usage:\n" |
| " echo clk <freq> > change ; change lcd pixel clock, unit in Hz\n" |
| " echo bit <lcd_bits> > change ; change lcd bits\n" |
| " echo basic <h_active> <v_active> <h_period> <v_period> <lcd_bits> > change ; change lcd basic config\n" |
| " echo sync <hs_width> <hs_bp> <hs_pol> <vs_width> <vs_bp> <vs_pol> > change ; change lcd sync timing\n" |
| "data format:\n" |
| " <xx_pol> : 0=negative, 1=positive\n" |
| "\n" |
| " echo set > change; apply lcd config changing\n" |
| }; |
| |
| static ssize_t lcd_debug_common_help(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%s\n", lcd_common_usage_str); |
| } |
| |
| static ssize_t lcd_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%s\n", lcd_debug_usage_str); |
| } |
| |
| static int lcd_cpu_gpio_register_print(struct lcd_config_s *pconf, char *buf, int offset) |
| { |
| int i, n, len = 0; |
| struct lcd_cpu_gpio_s *cpu_gpio; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "cpu_gpio register:\n"); |
| |
| i = 0; |
| while (i < LCD_CPU_GPIO_NUM_MAX) { |
| cpu_gpio = &pconf->power.cpu_gpio[i]; |
| if (cpu_gpio->probe_flag == 0) { |
| i++; |
| continue; |
| } |
| |
| if (cpu_gpio->register_flag) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%d: name=%s, gpio=%p\n", |
| i, cpu_gpio->name, cpu_gpio->gpio); |
| } else { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%d: name=%s, no registered\n", |
| i, cpu_gpio->name); |
| } |
| i++; |
| } |
| |
| return len; |
| } |
| |
| static int lcd_power_step_print(struct lcd_config_s *pconf, int status, char *buf, int offset) |
| { |
| int i, n, len = 0; |
| struct lcd_power_step_s *power_step; |
| |
| n = lcd_debug_info_len(len + offset); |
| if (status) |
| len += snprintf((buf + len), n, "power on step:\n"); |
| else |
| len += snprintf((buf + len), n, "power off step:\n"); |
| |
| i = 0; |
| while (i < LCD_PWR_STEP_MAX) { |
| if (status) |
| power_step = &pconf->power.power_on_step[i]; |
| else |
| power_step = &pconf->power.power_off_step[i]; |
| |
| if (power_step->type >= LCD_POWER_TYPE_MAX) |
| break; |
| switch (power_step->type) { |
| case LCD_POWER_TYPE_CPU: |
| case LCD_POWER_TYPE_PMU: |
| case LCD_POWER_TYPE_WAIT_GPIO: |
| case LCD_POWER_TYPE_CLK_SS: |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%d: type=%d, index=%d, value=%d, delay=%d\n", |
| i, power_step->type, power_step->index, |
| power_step->value, power_step->delay); |
| break; |
| case LCD_POWER_TYPE_EXTERN: |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%d: type=%d, index=%d, delay=%d\n", |
| i, power_step->type, power_step->index, |
| power_step->delay); |
| break; |
| case LCD_POWER_TYPE_SIGNAL: |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%d: type=%d, delay=%d\n", |
| i, power_step->type, power_step->delay); |
| break; |
| default: |
| break; |
| } |
| i++; |
| } |
| |
| return len; |
| } |
| |
| static int lcd_power_step_info_print(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int len = 0; |
| |
| len += lcd_power_step_print(&pdrv->config, 1, |
| (buf + len), (len + offset)); |
| len += lcd_power_step_print(&pdrv->config, 0, |
| (buf + len), (len + offset)); |
| len += lcd_cpu_gpio_register_print(&pdrv->config, |
| (buf + len), (len + offset)); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_ttl(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "clk_pol %u\n" |
| "de_valid %u\n" |
| "hvsync_valid %u\n" |
| "rb_swap %u\n" |
| "bit_swap %u\n\n", |
| pdrv->config.control.ttl_cfg.clk_pol, |
| ((pdrv->config.control.ttl_cfg.sync_valid >> 1) & 1), |
| ((pdrv->config.control.ttl_cfg.sync_valid >> 0) & 1), |
| ((pdrv->config.control.ttl_cfg.swap_ctrl >> 1) & 1), |
| ((pdrv->config.control.ttl_cfg.swap_ctrl >> 0) & 1)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pinmux_flag %d\n" |
| "pinmux_pointer 0x%p\n\n", |
| pdrv->config.pinmux_flag, |
| pdrv->config.pin); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_lvds(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "lvds_repack %u\n" |
| "dual_port %u\n" |
| "pn_swap %u\n" |
| "port_swap %u\n" |
| "lane_reverse %u\n" |
| "phy_vswing 0x%x\n" |
| "phy_preem 0x%x\n\n", |
| pdrv->config.control.lvds_cfg.lvds_repack, |
| pdrv->config.control.lvds_cfg.dual_port, |
| pdrv->config.control.lvds_cfg.pn_swap, |
| pdrv->config.control.lvds_cfg.port_swap, |
| pdrv->config.control.lvds_cfg.lane_reverse, |
| pdrv->config.control.lvds_cfg.phy_vswing, |
| pdrv->config.control.lvds_cfg.phy_preem); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_vbyone(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| struct vbyone_config_s *vx1_conf; |
| int n, len = 0; |
| |
| vx1_conf = &pdrv->config.control.vbyone_cfg; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "lane_count %u\n" |
| "region_num %u\n" |
| "byte_mode %u\n" |
| "color_fmt %u\n" |
| "bit_rate %uHz\n" |
| "phy_vswing 0x%x\n" |
| "phy_preem 0x%x\n" |
| "intr_en %u\n" |
| "vsync_intr_en %u\n" |
| "hw_filter_time 0x%x\n" |
| "hw_filter_cnt 0x%x\n" |
| "ctrl_flag 0x%x\n\n", |
| vx1_conf->lane_count, |
| vx1_conf->region_num, |
| vx1_conf->byte_mode, |
| vx1_conf->color_fmt, |
| pdrv->config.timing.bit_rate, |
| vx1_conf->phy_vswing, |
| vx1_conf->phy_preem, |
| vx1_conf->intr_en, |
| vx1_conf->vsync_intr_en, |
| vx1_conf->hw_filter_time, |
| vx1_conf->hw_filter_cnt, |
| vx1_conf->ctrl_flag); |
| if (vx1_conf->ctrl_flag & 0x1) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "power_on_reset_en %u\n" |
| "power_on_reset_delay %ums\n\n", |
| (vx1_conf->ctrl_flag & 0x1), |
| vx1_conf->power_on_reset_delay); |
| } |
| if (vx1_conf->ctrl_flag & 0x2) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "hpd_data_delay_en %u\n" |
| "hpd_data_delay %ums\n\n", |
| ((vx1_conf->ctrl_flag >> 1) & 0x1), |
| vx1_conf->hpd_data_delay); |
| } |
| if (vx1_conf->ctrl_flag & 0x4) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "cdr_training_hold_en %u\n" |
| "cdr_training_hold %ums\n\n", |
| ((vx1_conf->ctrl_flag >> 2) & 0x1), |
| vx1_conf->cdr_training_hold); |
| } |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pinmux_flag %d\n" |
| "pinmux_pointer 0x%p\n\n", |
| pdrv->config.pinmux_flag, |
| pdrv->config.pin); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_mipi(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int len = 0; |
| |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| mipi_dsi_print_info(&pdrv->config); |
| #endif |
| |
| return len; |
| } |
| |
| static int lcd_info_print_edp(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "max_lane_count %d\n" |
| "max_link_rate %d\n" |
| "training_mode %d\n" |
| "dpcd_caps_en %d\n" |
| "sync_clk_mode %d\n\n" |
| "lane_count %d\n" |
| "link_rate %d\n" |
| "bit_rate %uHz\n" |
| "training_settings 0x%x\n" |
| "main_stream_enable %d\n" |
| "phy_vswing 0x%x\n" |
| "phy_preem 0x%x\n\n", |
| pdrv->config.control.edp_cfg.max_lane_count, |
| pdrv->config.control.edp_cfg.max_link_rate, |
| pdrv->config.control.edp_cfg.training_mode, |
| pdrv->config.control.edp_cfg.dpcd_caps_en, |
| pdrv->config.control.edp_cfg.sync_clk_mode, |
| pdrv->config.control.edp_cfg.lane_count, |
| pdrv->config.control.edp_cfg.link_rate, |
| pdrv->config.timing.bit_rate, |
| pdrv->config.control.edp_cfg.training_settings, |
| pdrv->config.control.edp_cfg.main_stream_enable, |
| pdrv->config.control.edp_cfg.phy_vswing, |
| pdrv->config.control.edp_cfg.phy_preem); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pinmux_flag %d\n" |
| "pinmux_pointer 0x%p\n\n", |
| pdrv->config.pinmux_flag, |
| pdrv->config.pin); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_mlvds(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "channel_num %d\n" |
| "channel_sel0 0x%08x\n" |
| "channel_sel1 0x%08x\n" |
| "clk_phase 0x%04x\n" |
| "pn_swap %u\n" |
| "bit_swap %u\n" |
| "phy_vswing 0x%x\n" |
| "phy_preem 0x%x\n" |
| "bit_rate %uHz\n" |
| "pi_clk_sel 0x%03x\n\n", |
| pdrv->config.control.mlvds_cfg.channel_num, |
| pdrv->config.control.mlvds_cfg.channel_sel0, |
| pdrv->config.control.mlvds_cfg.channel_sel1, |
| pdrv->config.control.mlvds_cfg.clk_phase, |
| pdrv->config.control.mlvds_cfg.pn_swap, |
| pdrv->config.control.mlvds_cfg.bit_swap, |
| pdrv->config.control.mlvds_cfg.phy_vswing, |
| pdrv->config.control.mlvds_cfg.phy_preem, |
| pdrv->config.timing.bit_rate, |
| pdrv->config.control.mlvds_cfg.pi_clk_sel); |
| |
| len += lcd_tcon_info_print((buf + len), (len + offset)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pinmux_flag %d\n" |
| "pinmux_pointer 0x%p\n\n", |
| pdrv->config.pinmux_flag, |
| pdrv->config.pin); |
| |
| return len; |
| } |
| |
| static int lcd_info_print_p2p(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "p2p_type 0x%x\n" |
| "lane_num %d\n" |
| "channel_sel0 0x%08x\n" |
| "channel_sel1 0x%08x\n" |
| "pn_swap %u\n" |
| "bit_swap %u\n" |
| "bit_rate %uHz\n" |
| "phy_vswing 0x%x\n" |
| "phy_preem 0x%x\n\n", |
| pdrv->config.control.p2p_cfg.p2p_type, |
| pdrv->config.control.p2p_cfg.lane_num, |
| pdrv->config.control.p2p_cfg.channel_sel0, |
| pdrv->config.control.p2p_cfg.channel_sel1, |
| pdrv->config.control.p2p_cfg.pn_swap, |
| pdrv->config.control.p2p_cfg.bit_swap, |
| pdrv->config.timing.bit_rate, |
| pdrv->config.control.p2p_cfg.phy_vswing, |
| pdrv->config.control.p2p_cfg.phy_preem); |
| |
| len += lcd_tcon_info_print((buf + len), (len + offset)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pinmux_flag %d\n" |
| "pinmux_pointer 0x%p\n\n", |
| pdrv->config.pinmux_flag, |
| pdrv->config.pin); |
| |
| return len; |
| } |
| |
| static int lcd_info_print(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int lcd_clk, sync_duration; |
| struct lcd_config_s *pconf; |
| int n, len = 0; |
| |
| pconf = &pdrv->config; |
| lcd_clk = (pconf->timing.lcd_clk / 1000); |
| sync_duration = pconf->timing.sync_duration_num * 100; |
| sync_duration = sync_duration / pconf->timing.sync_duration_den; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "driver version: %s\n" |
| "panel_type: %s, chip: %d, mode: %s, status: %d\n" |
| "viu_sel: %d, isr_cnt: %d, resume_type: %d, resume_flag: 0x%x\n" |
| "fr_auto_policy: %d, fr_mode: %d, fr_duration: %d\n" |
| "mute_flag: 0x%x, test_flag: 0x%x\n" |
| "key_valid: %d, config_load: %d\n", |
| LCD_DRV_VERSION, |
| pconf->propname, pdrv->data->chip_type, |
| lcd_mode_mode_to_str(pdrv->mode), pdrv->status, |
| pdrv->viu_sel, pdrv->vsync_cnt, |
| pdrv->resume_type, pdrv->resume_flag, |
| pdrv->fr_auto_policy, pdrv->fr_mode, pdrv->fr_duration, |
| pdrv->mute_flag, pdrv->test_flag, |
| pdrv->key_valid, pdrv->config_load); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "%s, %s %ubit, %ux%u@%u.%02uHz\n", |
| pconf->basic.model_name, |
| lcd_type_type_to_str(pconf->basic.lcd_type), |
| pconf->basic.lcd_bits, |
| pconf->basic.h_active, pconf->basic.v_active, |
| (sync_duration / 100), (sync_duration % 100)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "lcd_clk %u.%03uMHz\n" |
| "ss_level 0x%x\n" |
| "clk_auto %d\n" |
| "fr_adj_type %d\n\n", |
| (lcd_clk / 1000), (lcd_clk % 1000), |
| pconf->timing.ss_level, pconf->timing.clk_auto, |
| pconf->timing.fr_adjust_type); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "h_period %d\n" |
| "v_period %d\n" |
| "hs_width %d\n" |
| "hs_backporch %d\n" |
| "hs_pol %d\n" |
| "vs_width %d\n" |
| "vs_backporch %d\n" |
| "vs_pol %d\n\n", |
| pconf->basic.h_period, pconf->basic.v_period, |
| pconf->timing.hsync_width, pconf->timing.hsync_bp, |
| pconf->timing.hsync_pol, |
| pconf->timing.vsync_width, pconf->timing.vsync_bp, |
| pconf->timing.vsync_pol); |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "h_period_min %d\n" |
| "h_period_max %d\n" |
| "v_period_min %d\n" |
| "v_period_max %d\n" |
| "frame_rate_min %d\n" |
| "frame_rate_max %d\n" |
| "pclk_min %d\n" |
| "pclk_max %d\n\n", |
| pconf->basic.h_period_min, pconf->basic.h_period_max, |
| pconf->basic.v_period_min, pconf->basic.v_period_max, |
| pconf->basic.frame_rate_min, pconf->basic.frame_rate_max, |
| pconf->basic.lcd_clk_min, pconf->basic.lcd_clk_max); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "pll_ctrl 0x%08x\n" |
| "div_ctrl 0x%08x\n" |
| "clk_ctrl 0x%08x\n" |
| "video_on_pixel %d\n" |
| "video_on_line %d\n\n", |
| pconf->timing.pll_ctrl, pconf->timing.div_ctrl, |
| pconf->timing.clk_ctrl, |
| pconf->timing.video_on_pixel, |
| pconf->timing.video_on_line); |
| |
| if (lcd_debug_info_if && lcd_debug_info_if->interface_print) |
| len += lcd_debug_info_if->interface_print(pdrv, (buf + len), (len + offset)); |
| else |
| LCDERR("%s: lcd_debug_info_if is null\n", __func__); |
| |
| len += lcd_clk_clkmsr_print(pdrv, (buf + len), (len + offset)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_ttl(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nttl regs:\n"); |
| reg = L_DUAL_PORT_CNTL_ADDR; |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "PORT_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STH1_HS_ADDR; |
| len += snprintf((buf + len), n, |
| "STH1_HS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STH1_HE_ADDR; |
| len += snprintf((buf + len), n, |
| "STH1_HE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STH1_VS_ADDR; |
| len += snprintf((buf + len), n, |
| "STH1_VS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STH1_VE_ADDR; |
| len += snprintf((buf + len), n, |
| "STH1_VE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STV1_HS_ADDR; |
| len += snprintf((buf + len), n, |
| "STV1_HS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STV1_HE_ADDR; |
| len += snprintf((buf + len), n, |
| "STV1_HE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STV1_VS_ADDR; |
| len += snprintf((buf + len), n, |
| "STV1_VS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_STV1_VE_ADDR; |
| len += snprintf((buf + len), n, |
| "STV1_VE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_OEH_HS_ADDR; |
| len += snprintf((buf + len), n, |
| "OEH_HS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_OEH_HE_ADDR; |
| len += snprintf((buf + len), n, |
| "OEH_HE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_OEH_VS_ADDR; |
| len += snprintf((buf + len), n, |
| "OEH_VS_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = L_OEH_VE_ADDR; |
| len += snprintf((buf + len), n, |
| "OEH_VE_ADDR [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_lvds(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nlvds regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = LVDS_PACK_CNTL_ADDR; |
| len += snprintf((buf + len), n, |
| "LVDS_PACK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = LVDS_GEN_CNTL; |
| len += snprintf((buf + len), n, |
| "LVDS_GEN_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP0; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP0 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP1; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP1 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_lvds_t7(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg, reg_offset; |
| int n, len = 0; |
| |
| reg_offset = pdrv->data->offset_venc_if[pdrv->index]; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nlvds regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = LVDS_SER_EN_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "LVDS_SER_EN [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = LVDS_PACK_CNTL_ADDR_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "LVDS_PACK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = LVDS_GEN_CNTL_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "LVDS_GEN_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP0_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP0 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP1_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP1 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_BIT_REV_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "P2P_BIT_REV [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_vbyone(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg, reg_offset; |
| int n, len = 0; |
| |
| reg_offset = pdrv->data->offset_venc_if[pdrv->index]; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nvbyone regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_STATUS_L + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_STATUS [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INFILTER_TICK_PERIOD_H + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INFILTER_TICK_PERIOD_H [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INFILTER_TICK_PERIOD_L + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INFILTER_TICK_PERIOD_L [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INSGN_CTRL + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INSGN_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_FSM_HOLDER_L + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_FSM_HOLDER_L [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_FSM_HOLDER_H + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_FSM_HOLDER_H [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_STATE_CTRL + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_STATE_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_UNMASK + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_UNMASK [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_STATE + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_STATE [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_vbyone_t7(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg, reg_offset; |
| int n, len = 0; |
| |
| reg_offset = pdrv->data->offset_venc_if[pdrv->index]; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nvbyone regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_STATUS_L_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_STATUS [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INFILTER_CTRL_H_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INFILTER_CTRL_H [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INFILTER_CTRL_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INFILTER_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INSGN_CTRL_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VBO_INSGN_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_FSM_HOLDER_L_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_FSM_HOLDER_L [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_FSM_HOLDER_H_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_FSM_HOLDER_H [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_STATE_CTRL_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_STATE_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_UNMASK_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_UNMASK [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = VBO_INTR_STATE_T7 + reg_offset; |
| len += snprintf((buf + len), n, |
| "VX1_INTR_STATE [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_mipi(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nmipi_dsi regs:\n"); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_TOP_CNTL; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_TOP_CNTL [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_TOP_CLK_CNTL; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_TOP_CLK_CNTL [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_PWR_UP_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_PWR_UP_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_PCKHDL_CFG_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_PCKHDL_CFG_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_LPCLK_CTRL_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_LPCLK_CTRL_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_CMD_MODE_CFG_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_CMD_MODE_CFG_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_VID_MODE_CFG_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_VID_MODE_CFG_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_MODE_CFG_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_MODE_CFG_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_PHY_STATUS_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_PHY_STATUS_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_INT_ST0_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_INT_ST0_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_DWC_INT_ST1_OS; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_DWC_INT_ST1_OS [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_TOP_STAT; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_TOP_STAT [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_TOP_INTR_CNTL_STAT; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_TOP_INTR_CNTL_STAT [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = MIPI_DSI_TOP_MEM_PD; |
| len += snprintf((buf + len), n, |
| "MIPI_DSI_TOP_MEM_PD [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_edp(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nedp regs:\n"); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_LINK_BW_SET; |
| len += snprintf((buf + len), n, |
| "EDP_TX_LINK_BW_SET [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_LINK_COUNT_SET; |
| len += snprintf((buf + len), n, |
| "EDP_TX_LINK_COUNT_SET [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_TRAINING_PATTERN_SET; |
| len += snprintf((buf + len), n, |
| "EDP_TX_TRAINING_PATTERN_SET [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_SCRAMBLING_DISABLE; |
| len += snprintf((buf + len), n, |
| "EDP_TX_SCRAMBLING_DISABLE [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_TRANSMITTER_OUTPUT_ENABLE; |
| len += snprintf((buf + len), n, |
| "EDP_TX_TRANSMITTER_OUTPUT_ENABLE [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_MAIN_STREAM_ENABLE; |
| len += snprintf((buf + len), n, |
| "EDP_TX_MAIN_STREAM_ENABLE [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_PHY_RESET; |
| len += snprintf((buf + len), n, |
| "EDP_TX_PHY_RESET [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_PHY_STATUS; |
| len += snprintf((buf + len), n, |
| "EDP_TX_PHY_STATUS [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_COMMAND; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_COMMAND [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_ADDRESS; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_ADDRESS [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_STATE; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_STATE [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_REPLY_CODE; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_REPLY_CODE [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_REPLY_COUNT; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_REPLY_COUNT [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_REPLY_DATA_COUNT; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_REPLY_DATA_COUNT [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = EDP_TX_AUX_TRANSFER_STATUS; |
| len += snprintf((buf + len), n, |
| "EDP_TX_AUX_TRANSFER_STATUS [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_tcon(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\ntcon regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_TCON_CLK_CNTL; |
| len += snprintf((buf + len), n, |
| "HHI_TCON_CLK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_clk_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_TOP_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_TOP_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_RGB_IN_MUX; |
| len += snprintf((buf + len), n, |
| "TCON_RGB_IN_MUX [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_OUT_CH_SEL0; |
| len += snprintf((buf + len), n, |
| "TCON_OUT_CH_SEL0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_OUT_CH_SEL1; |
| len += snprintf((buf + len), n, |
| "TCON_OUT_CH_SEL1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_STATUS0; |
| len += snprintf((buf + len), n, |
| "TCON_STATUS0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_PLLLOCK_CNTL; |
| len += snprintf((buf + len), n, |
| "TCON_PLLLOCK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_RST_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_RST_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST0; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST1; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST2; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST2 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_CLK_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_CLK_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_STATUS1; |
| len += snprintf((buf + len), n, |
| "TCON_STATUS1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_DDRIF_CTRL1; |
| len += snprintf((buf + len), n, |
| "TCON_DDRIF_CTRL1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| reg = TCON_DDRIF_CTRL2; |
| len += snprintf((buf + len), n, |
| "TCON_DDRIF_CTRL2 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_INTR_MASKN; |
| len += snprintf((buf + len), n, |
| "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| reg = TCON_INTR_RO; |
| len += snprintf((buf + len), n, |
| "TCON_INTR_RO [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP0; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP0 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP1; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP1 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_tcon_t3(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\ntcon regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = CLKCTRL_TCON_CLK_CNTL; |
| len += snprintf((buf + len), n, |
| "CLKCTRL_TCON_CLK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_clk_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_TOP_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_TOP_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_RGB_IN_MUX; |
| len += snprintf((buf + len), n, |
| "TCON_RGB_IN_MUX [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_OUT_CH_SEL0; |
| len += snprintf((buf + len), n, |
| "TCON_OUT_CH_SEL0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_OUT_CH_SEL1; |
| len += snprintf((buf + len), n, |
| "TCON_OUT_CH_SEL1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_STATUS0; |
| len += snprintf((buf + len), n, |
| "TCON_STATUS0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_PLLLOCK_CNTL; |
| len += snprintf((buf + len), n, |
| "TCON_PLLLOCK_CNTL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_RST_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_RST_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST0; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST0 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST1; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_AXI_OFST2; |
| len += snprintf((buf + len), n, |
| "TCON_AXI_OFST2 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_CLK_CTRL; |
| len += snprintf((buf + len), n, |
| "TCON_CLK_CTRL [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_STATUS1; |
| len += snprintf((buf + len), n, |
| "TCON_STATUS1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_DDRIF_CTRL1; |
| len += snprintf((buf + len), n, |
| "TCON_DDRIF_CTRL1 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| reg = TCON_DDRIF_CTRL2; |
| len += snprintf((buf + len), n, |
| "TCON_DDRIF_CTRL2 [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = TCON_INTR_MASKN; |
| len += snprintf((buf + len), n, |
| "TCON_INTR_MASKN [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| reg = TCON_INTR_RO; |
| len += snprintf((buf + len), n, |
| "TCON_INTR_RO [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_read(pdrv, reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP0_T7; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP0 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = P2P_CH_SWAP1_T7; |
| len += snprintf((buf + len), n, |
| "P2P_CH_SWAP1 [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_dphy(char *buf, int offset) |
| { |
| unsigned int reg0, reg1; |
| int n, len = 0; |
| |
| reg0 = HHI_LVDS_TX_PHY_CNTL0; |
| reg1 = HHI_LVDS_TX_PHY_CNTL1; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "HHI_LVDS_TX_PHY_CNTL0 [0x%04x] = 0x%08x\n", |
| reg0, lcd_ana_read(reg0)); |
| len += snprintf((buf + len), n, |
| "HHI_LVDS_TX_PHY_CNTL1 [0x%04x] = 0x%08x\n", |
| reg1, lcd_ana_read(reg1)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_phy_analog(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| len += lcd_reg_print_dphy((buf + len), (len + offset)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nphy analog regs:\n"); |
| |
| reg = HHI_LVDS_TX_PHY_CNTL0; |
| len += snprintf((buf + len), n, |
| "HHI_LVDS_TX_PHY_CNTL0 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_LVDS_TX_PHY_CNTL1; |
| len += snprintf((buf + len), n, |
| "HHI_LVDS_TX_PHY_CNTL1 [0x%02x] = 0x%08x\n\n", |
| reg, lcd_ana_read(reg)); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL1; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL1 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL2; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL2 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL3; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL3 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL4; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL4 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL6; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL6 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL7; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL7 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL8; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL8 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL9; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL9 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL10; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL10 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL11; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL11 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL12; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL12 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL13; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL13 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL14; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL14 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL15; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL15 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_DIF_CSI_PHY_CNTL16; |
| len += snprintf((buf + len), n, |
| "HHI_DIF_CSI_PHY_CNTL16 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_dphy_t7(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg0, reg1; |
| int n, len = 0; |
| |
| switch (pdrv->index) { |
| case 1: |
| reg0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0; |
| reg1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1; |
| break; |
| case 2: |
| reg0 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL0; |
| reg1 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL1; |
| break; |
| case 0: |
| default: |
| reg0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0; |
| reg1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1; |
| break; |
| } |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "\nCOMBO_DPHY_CNTL0 [0x%04x] = 0x%08x\n", |
| COMBO_DPHY_CNTL0, lcd_combo_dphy_read(pdrv, COMBO_DPHY_CNTL0)); |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "COMBO_DPHY_CNTL1 [0x%04x] = 0x%08x\n", |
| COMBO_DPHY_CNTL1, lcd_combo_dphy_read(pdrv, COMBO_DPHY_CNTL1)); |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "COMBO_DPHY_EDP_LVDS_TX_PHY_CNTL0 [0x%04x] = 0x%08x\n", |
| reg0, lcd_combo_dphy_read(pdrv, reg0)); |
| len += snprintf((buf + len), n, |
| "COMBO_DPHY_EDP_LVDS_TX_PHY_CNTL1 [0x%04x] = 0x%08x\n", |
| reg1, lcd_combo_dphy_read(pdrv, reg1)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_phy_analog_t7(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| len += lcd_reg_print_dphy_t7(pdrv, (buf + len), (len + offset)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nphy analog regs:\n"); |
| |
| reg = ANACTRL_DIF_PHY_CNTL1; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL1 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL2; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL2 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL3; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL3 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL4; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL4 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL5; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL5 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL6; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL6 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL7; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL7 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL8; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL8 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL9; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL9 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL10; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL10 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL11; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL11 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL12; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL12 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL13; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL13 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL14; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL14 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL15; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL15 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL16; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL16 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL17; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL17 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL18; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL18 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL19; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL19 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL20; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL20 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL21; |
| len += snprintf((buf + len), n, |
| "PHY_CNTL21 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_dphy_t3(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg0, reg1; |
| int n, len = 0; |
| |
| switch (pdrv->index) { |
| case 1: |
| reg0 = ANACTRL_LVDS_TX_PHY_CNTL2; |
| reg1 = ANACTRL_LVDS_TX_PHY_CNTL3; |
| break; |
| case 0: |
| default: |
| reg0 = ANACTRL_LVDS_TX_PHY_CNTL0; |
| reg1 = ANACTRL_LVDS_TX_PHY_CNTL1; |
| break; |
| } |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "ANACTRL_LVDS_TX_PHY_CNTL0 [0x%04x] = 0x%08x\n", |
| reg0, lcd_ana_read(reg0)); |
| len += snprintf((buf + len), n, |
| "ANACTRL_LVDS_TX_PHY_CNTL1 [0x%04x] = 0x%08x\n", |
| reg1, lcd_ana_read(reg1)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_phy_analog_t3(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| len += lcd_reg_print_dphy_t3(pdrv, (buf + len), (len + offset)); |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nphy analog regs:\n"); |
| |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL1; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL1 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL2; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL2 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL3; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL3 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL4; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL4 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL6; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL6 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL7; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL7 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL8; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL8 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL9; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL9 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL10; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL10 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL11; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL11 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL12; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL12 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL13; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL13 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL14; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL14 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL15; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL15 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = ANACTRL_DIF_PHY_CNTL16; |
| len += snprintf((buf + len), n, |
| "ANACTRL_DIF_PHY_CNTL16 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print_mipi_phy_analog(struct aml_lcd_drv_s *pdrv, |
| char *buf, int offset) |
| { |
| unsigned int reg; |
| int n, len = 0; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nmipi_dsi_phy analog regs:\n"); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_MIPI_CNTL0; |
| len += snprintf((buf + len), n, |
| "HHI_MIPI_CNTL0 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_MIPI_CNTL1; |
| len += snprintf((buf + len), n, |
| "HHI_MIPI_CNTL1 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| n = lcd_debug_info_len(len + offset); |
| reg = HHI_MIPI_CNTL2; |
| len += snprintf((buf + len), n, |
| "HHI_MIPI_CNTL2 [0x%02x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| |
| return len; |
| } |
| |
| static int lcd_reg_print(struct aml_lcd_drv_s *pdrv, char *buf, int offset) |
| { |
| int i, n, len = 0; |
| struct lcd_config_s *pconf; |
| unsigned int *table; |
| |
| pconf = &pdrv->config; |
| |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nclk regs:\n"); |
| if (lcd_debug_info_reg) { |
| if (lcd_debug_info_reg->reg_pll_table) { |
| table = lcd_debug_info_reg->reg_pll_table; |
| i = 0; |
| while (i < LCD_DEBUG_REG_CNT_MAX) { |
| if (table[i] == LCD_DEBUG_REG_END) |
| break; |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "ana [0x%02x] = 0x%08x\n", |
| table[i], lcd_ana_read(table[i])); |
| i++; |
| } |
| } |
| |
| if (lcd_debug_info_reg->reg_clk_table) { |
| table = lcd_debug_info_reg->reg_clk_table; |
| i = 0; |
| while (i < LCD_DEBUG_REG_CNT_MAX) { |
| if (table[i] == LCD_DEBUG_REG_END) |
| break; |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "clk [0x%02x] = 0x%08x\n", |
| table[i], lcd_clk_read(table[i])); |
| i++; |
| } |
| } |
| |
| if (lcd_debug_info_reg->reg_encl_table) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\nencl regs:\n"); |
| table = lcd_debug_info_reg->reg_encl_table; |
| i = 0; |
| while (i < LCD_DEBUG_REG_CNT_MAX) { |
| if (table[i] == LCD_DEBUG_REG_END) |
| break; |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "vcbus [0x%04x] = 0x%08x\n", |
| table[i], lcd_vcbus_read(table[i])); |
| i++; |
| } |
| } |
| |
| if (lcd_debug_info_reg->reg_pinmux_table) { |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, "\npinmux regs:\n"); |
| table = lcd_debug_info_reg->reg_pinmux_table; |
| i = 0; |
| while (i < LCD_DEBUG_REG_CNT_MAX) { |
| if (table[i] == LCD_DEBUG_REG_END) |
| break; |
| len += snprintf((buf + len), n, |
| "PERIPHS_PIN_MUX [0x%02x] = 0x%08x\n", |
| table[i], lcd_periphs_read(pdrv, table[i])); |
| i++; |
| } |
| } |
| } else { |
| LCDERR("%s: lcd_debug_info_reg is null\n", __func__); |
| } |
| |
| if (lcd_debug_info_if) { |
| if (lcd_debug_info_if->reg_dump_interface) { |
| len += lcd_debug_info_if->reg_dump_interface(pdrv, (buf + len), |
| (len + offset)); |
| } |
| |
| if (lcd_debug_info_if->reg_dump_phy) { |
| len += lcd_debug_info_if->reg_dump_phy(pdrv, (buf + len), |
| (len + offset)); |
| } |
| } else { |
| LCDERR("%s: lcd_debug_info_if is null\n", __func__); |
| } |
| |
| return len; |
| } |
| |
| static int lcd_optical_info_print(struct aml_lcd_drv_s *pdrv, |
| char *buf, int offset) |
| { |
| struct lcd_config_s *pconf; |
| int n, len = 0; |
| |
| pconf = &pdrv->config; |
| n = lcd_debug_info_len(len + offset); |
| len += snprintf((buf + len), n, |
| "\nlcd optical info:\n" |
| "hdr_support %d\n" |
| "features %d\n" |
| "primaries_r_x %d\n" |
| "primaries_r_y %d\n" |
| "primaries_g_x %d\n" |
| "primaries_g_y %d\n" |
| "primaries_b_x %d\n" |
| "primaries_b_y %d\n" |
| "white_point_x %d\n" |
| "white_point_y %d\n" |
| "luma_max %d\n" |
| "luma_min %d\n" |
| "luma_avg %d\n\n", |
| pconf->optical.hdr_support, |
| pconf->optical.features, |
| pconf->optical.primaries_r_x, |
| pconf->optical.primaries_r_y, |
| pconf->optical.primaries_g_x, |
| pconf->optical.primaries_g_y, |
| pconf->optical.primaries_b_x, |
| pconf->optical.primaries_b_y, |
| pconf->optical.white_point_x, |
| pconf->optical.white_point_y, |
| pconf->optical.luma_max, |
| pconf->optical.luma_min, |
| pconf->optical.luma_avg); |
| |
| return len; |
| } |
| |
| static void lcd_test_pattern_check(struct work_struct *work) |
| { |
| struct aml_lcd_drv_s *pdrv; |
| |
| pdrv = container_of(work, struct aml_lcd_drv_s, test_check_work); |
| aml_lcd_notifier_call_chain(LCD_EVENT_TEST_PATTERN, (void *)pdrv); |
| } |
| |
| #define LCD_ENC_TST_NUM_MAX 9 |
| static char *lcd_enc_tst_str[] = { |
| "0-None", /* 0 */ |
| "1-Color Bar", /* 1 */ |
| "2-Thin Line", /* 2 */ |
| "3-Dot Grid", /* 3 */ |
| "4-Gray", /* 4 */ |
| "5-Red", /* 5 */ |
| "6-Green", /* 6 */ |
| "7-Blue", /* 7 */ |
| "8-Black", /* 8 */ |
| }; |
| |
| static unsigned int lcd_enc_tst[][7] = { |
| /*tst_mode, Y, Cb, Cr, tst_en, vfifo_en rgbin*/ |
| {0, 0x200, 0x200, 0x200, 0, 1, 3}, /* 0 */ |
| {1, 0x200, 0x200, 0x200, 1, 0, 1}, /* 1 */ |
| {2, 0x200, 0x200, 0x200, 1, 0, 1}, /* 2 */ |
| {3, 0x200, 0x200, 0x200, 1, 0, 1}, /* 3 */ |
| {0, 0x1ff, 0x1ff, 0x1ff, 1, 0, 3}, /* 4 */ |
| {0, 0x3ff, 0x0, 0x0, 1, 0, 3}, /* 5 */ |
| {0, 0x0, 0x3ff, 0x0, 1, 0, 3}, /* 6 */ |
| {0, 0x0, 0x0, 0x3ff, 1, 0, 3}, /* 7 */ |
| {0, 0x0, 0x0, 0x0, 1, 0, 3}, /* 8 */ |
| }; |
| |
| void lcd_debug_test(struct aml_lcd_drv_s *pdrv, unsigned int num) |
| { |
| unsigned int h_active, video_on_pixel, offset; |
| |
| num = (num >= LCD_ENC_TST_NUM_MAX) ? 0 : num; |
| offset = pdrv->data->offset_venc[pdrv->index]; |
| |
| lcd_queue_work(&pdrv->test_check_work); |
| |
| h_active = pdrv->config.basic.h_active; |
| video_on_pixel = pdrv->config.timing.video_on_pixel; |
| if (num > 0) |
| lcd_gamma_debug_test_en(pdrv, 0); |
| else |
| lcd_gamma_debug_test_en(pdrv, 1); |
| |
| lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL + offset, lcd_enc_tst[num][6]); |
| lcd_vcbus_write(ENCL_TST_MDSEL + offset, lcd_enc_tst[num][0]); |
| lcd_vcbus_write(ENCL_TST_Y + offset, lcd_enc_tst[num][1]); |
| lcd_vcbus_write(ENCL_TST_CB + offset, lcd_enc_tst[num][2]); |
| lcd_vcbus_write(ENCL_TST_CR + offset, lcd_enc_tst[num][3]); |
| lcd_vcbus_write(ENCL_TST_CLRBAR_STRT + offset, video_on_pixel); |
| lcd_vcbus_write(ENCL_TST_CLRBAR_WIDTH + offset, (h_active / 9)); |
| lcd_vcbus_write(ENCL_TST_EN + offset, lcd_enc_tst[num][4]); |
| lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV + offset, lcd_enc_tst[num][5], 3, 1); |
| if (num > 0) |
| LCDPR("[%d]: show test pattern: %s\n", pdrv->index, lcd_enc_tst_str[num]); |
| else |
| LCDPR("[%d]: disable test pattern\n", pdrv->index); |
| } |
| |
| static void lcd_mute_setting(struct aml_lcd_drv_s *pdrv, unsigned char flag) |
| { |
| unsigned int offset; |
| |
| offset = pdrv->data->offset_venc[pdrv->index]; |
| |
| if (flag) { |
| lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL + offset, 3); |
| lcd_vcbus_write(ENCL_TST_MDSEL + offset, 0); |
| lcd_vcbus_write(ENCL_TST_Y + offset, 0); |
| lcd_vcbus_write(ENCL_TST_CB + offset, 0); |
| lcd_vcbus_write(ENCL_TST_CR + offset, 0); |
| lcd_vcbus_write(ENCL_TST_EN + offset, 1); |
| lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV + offset, 0, 3, 1); |
| } else { |
| lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV + offset, 1, 3, 1); |
| lcd_vcbus_write(ENCL_TST_EN + offset, 0); |
| } |
| LCDPR("[%d]: mute: %d\n", pdrv->index, flag); |
| } |
| |
| static void lcd_screen_restore(struct aml_lcd_drv_s *pdrv) |
| { |
| unsigned int h_active, video_on_pixel, offset; |
| unsigned int num; |
| |
| num = pdrv->test_state; |
| num = (num >= LCD_ENC_TST_NUM_MAX) ? 0 : num; |
| offset = pdrv->data->offset_venc[pdrv->index]; |
| |
| lcd_queue_work(&pdrv->test_check_work); |
| |
| h_active = pdrv->config.basic.h_active; |
| video_on_pixel = pdrv->config.timing.video_on_pixel; |
| |
| lcd_vcbus_write(ENCL_VIDEO_RGBIN_CTRL + offset, lcd_enc_tst[num][6]); |
| lcd_vcbus_write(ENCL_TST_MDSEL + offset, lcd_enc_tst[num][0]); |
| lcd_vcbus_write(ENCL_TST_Y + offset, lcd_enc_tst[num][1]); |
| lcd_vcbus_write(ENCL_TST_CB + offset, lcd_enc_tst[num][2]); |
| lcd_vcbus_write(ENCL_TST_CR + offset, lcd_enc_tst[num][3]); |
| lcd_vcbus_write(ENCL_TST_CLRBAR_STRT + offset, video_on_pixel); |
| lcd_vcbus_write(ENCL_TST_CLRBAR_WIDTH + offset, (h_active / 9)); |
| lcd_vcbus_write(ENCL_TST_EN + offset, lcd_enc_tst[num][4]); |
| lcd_vcbus_setb(ENCL_VIDEO_MODE_ADV + offset, lcd_enc_tst[num][5], 3, 1); |
| if (num > 0) |
| LCDPR("[%d]: show test pattern: %s\n", pdrv->index, lcd_enc_tst_str[num]); |
| } |
| |
| static void lcd_screen_black(struct aml_lcd_drv_s *pdrv) |
| { |
| lcd_mute_setting(pdrv, 1); |
| } |
| |
| #define CLK_CHK_MAX 2000000 /*Hz*/ |
| static unsigned int lcd_prbs_performed, lcd_prbs_err; |
| static unsigned int lcd_prbs_flag; |
| static unsigned long lcd_encl_clk_check_std = 121000000; |
| static unsigned long lcd_fifo_clk_check_std = 42000000; |
| |
| static unsigned long lcd_abs(unsigned long a, unsigned long b) |
| { |
| unsigned long val; |
| |
| if (a >= b) |
| val = a - b; |
| else |
| val = b - a; |
| |
| return val; |
| } |
| |
| static int lcd_prbs_clk_check(unsigned long encl_clk, unsigned int encl_msr_id, |
| unsigned long fifo_clk, unsigned int fifo_msr_id, |
| unsigned int cnt) |
| { |
| unsigned long clk_check, temp; |
| |
| if (encl_msr_id == LCD_CLK_MSR_INVALID) |
| goto lcd_prbs_clk_check_next; |
| clk_check = meson_clk_measure(encl_msr_id); |
| if (clk_check != encl_clk) { |
| temp = lcd_abs(clk_check, encl_clk); |
| if (temp >= CLK_CHK_MAX) { |
| if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { |
| LCDERR("encl clkmsr error %ld, cnt:%d\n", |
| clk_check, cnt); |
| } |
| return -1; |
| } |
| } |
| |
| lcd_prbs_clk_check_next: |
| if (encl_msr_id == LCD_CLK_MSR_INVALID) |
| return 0; |
| clk_check = meson_clk_measure(fifo_msr_id); |
| if (clk_check != fifo_clk) { |
| temp = lcd_abs(clk_check, fifo_clk); |
| if (temp >= CLK_CHK_MAX) { |
| if (lcd_debug_print_flag & LCD_DBG_PR_TEST) { |
| LCDERR("fifo clkmsr error %ld, cnt:%d\n", |
| clk_check, cnt); |
| } |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| static void aml_lcd_prbs_test(struct aml_lcd_drv_s *pdrv, |
| unsigned int s, unsigned int mode_flag) |
| { |
| struct lcd_clk_config_s *cconf = get_lcd_clk_config(pdrv); |
| unsigned int lcd_prbs_mode, lcd_prbs_cnt; |
| unsigned int reg0, reg1; |
| unsigned int val1, val2, timeout; |
| unsigned int clk_err_cnt = 0; |
| int i, j, ret; |
| |
| if (!cconf) |
| return; |
| |
| reg0 = HHI_LVDS_TX_PHY_CNTL0; |
| reg1 = HHI_LVDS_TX_PHY_CNTL1; |
| |
| s = (s > 1800) ? 1800 : s; |
| timeout = s * 200; |
| |
| for (i = 0; i < LCD_PRBS_MODE_MAX; i++) { |
| if ((mode_flag & (1 << i)) == 0) |
| continue; |
| |
| lcd_ana_write(reg0, 0); |
| lcd_ana_write(reg1, 0); |
| |
| lcd_prbs_cnt = 0; |
| clk_err_cnt = 0; |
| lcd_prbs_mode = (1 << i); |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_encl_clk_check_std = 136000000; |
| lcd_fifo_clk_check_std = 48000000; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_encl_clk_check_std = 594000000; |
| lcd_fifo_clk_check_std = 297000000; |
| } |
| if (cconf->data->prbs_clk_config) { |
| cconf->data->prbs_clk_config(pdrv, lcd_prbs_mode); |
| } else { |
| LCDERR("%s: prbs_clk_config is null\n", __func__); |
| goto lcd_prbs_test_end; |
| } |
| msleep(20); |
| |
| lcd_ana_write(reg0, 0x000000c0); |
| lcd_ana_setb(reg0, 0xfff, 16, 12); |
| lcd_ana_setb(reg0, 1, 2, 1); |
| lcd_ana_write(reg1, 0x41000000); |
| lcd_ana_setb(reg1, 1, 31, 1); |
| |
| lcd_ana_write(reg0, 0xfff20c4); |
| lcd_ana_setb(reg0, 1, 12, 1); |
| val1 = lcd_ana_getb(reg1, 12, 12); |
| |
| while (lcd_prbs_flag) { |
| if (s > 1) { /* when s=1, means always run */ |
| if (lcd_prbs_cnt++ >= timeout) |
| break; |
| } |
| usleep_range(5000, 5001); |
| ret = 1; |
| for (j = 0; j < 5; j++) { |
| val2 = lcd_ana_getb(reg1, 12, 12); |
| if (val2 != val1) { |
| ret = 0; |
| break; |
| } |
| } |
| if (ret) { |
| LCDERR("prbs check error 1, val:0x%03x, cnt:%d\n", |
| val2, lcd_prbs_cnt); |
| goto lcd_prbs_test_err; |
| } |
| val1 = val2; |
| if (lcd_ana_getb(reg1, 0, 12)) { |
| LCDERR("prbs check error 2, cnt:%d\n", |
| lcd_prbs_cnt); |
| goto lcd_prbs_test_err; |
| } |
| |
| if (lcd_prbs_clk_check(lcd_encl_clk_check_std, 9, |
| lcd_fifo_clk_check_std, 129, |
| lcd_prbs_cnt)) |
| clk_err_cnt++; |
| else |
| clk_err_cnt = 0; |
| if (clk_err_cnt >= 10) { |
| LCDERR("prbs check error 3(clkmsr), cnt: %d\n", |
| lcd_prbs_cnt); |
| goto lcd_prbs_test_err; |
| } |
| } |
| |
| lcd_ana_write(reg0, 0); |
| lcd_ana_write(reg1, 0); |
| |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_LVDS); |
| LCDPR("lvds prbs check ok\n"); |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_VX1); |
| LCDPR("vx1 prbs check ok\n"); |
| } else { |
| LCDPR("prbs check: unsupport mode\n"); |
| } |
| continue; |
| |
| lcd_prbs_test_err: |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err |= LCD_PRBS_MODE_LVDS; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err |= LCD_PRBS_MODE_VX1; |
| } |
| } |
| |
| lcd_prbs_test_end: |
| lcd_prbs_flag = 0; |
| } |
| |
| static void aml_lcd_prbs_test_t7(struct aml_lcd_drv_s *pdrv, |
| unsigned int ms, unsigned int mode_flag) |
| { |
| struct lcd_clk_config_s *cconf = get_lcd_clk_config(pdrv); |
| unsigned int reg_phy_tx_ctrl0, reg_phy_tx_ctrl1, reg_ctrl_out, bit_width; |
| int encl_msr_id, fifo_msr_id; |
| unsigned int lcd_prbs_mode, lcd_prbs_cnt; |
| unsigned int val1, val2, timeout; |
| unsigned int clk_err_cnt = 0; |
| int i, j, ret; |
| |
| if (!cconf) |
| return; |
| |
| switch (pdrv->index) { |
| case 0: |
| reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL0; |
| reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY0_CNTL1; |
| reg_ctrl_out = COMBO_DPHY_RO_EDP_LVDS_TX_PHY0_CNTL1; |
| bit_width = 8; |
| break; |
| case 1: |
| reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL0; |
| reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY1_CNTL1; |
| reg_ctrl_out = COMBO_DPHY_RO_EDP_LVDS_TX_PHY1_CNTL1; |
| bit_width = 8; |
| break; |
| case 2: |
| reg_phy_tx_ctrl0 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL0; |
| reg_phy_tx_ctrl1 = COMBO_DPHY_EDP_LVDS_TX_PHY2_CNTL1; |
| reg_ctrl_out = COMBO_DPHY_RO_EDP_LVDS_TX_PHY2_CNTL1; |
| bit_width = 10; |
| break; |
| default: |
| LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__); |
| return; |
| } |
| encl_msr_id = cconf->data->enc_clk_msr_id; |
| fifo_msr_id = cconf->data->fifo_clk_msr_id; |
| |
| timeout = (ms > 1000) ? 1000 : ms; |
| |
| for (i = 0; i < LCD_PRBS_MODE_MAX; i++) { |
| if ((mode_flag & (1 << i)) == 0) |
| continue; |
| |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl0, 0); |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl1, 0); |
| |
| lcd_prbs_cnt = 0; |
| clk_err_cnt = 0; |
| lcd_prbs_mode = (1 << i); |
| LCDPR("[%d]: lcd_prbs_mode: 0x%x\n", pdrv->index, lcd_prbs_mode); |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_encl_clk_check_std = 136000000; |
| lcd_fifo_clk_check_std = 48000000; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_encl_clk_check_std = 594000000; |
| lcd_fifo_clk_check_std = 297000000; |
| } |
| if (!cconf->data->prbs_clk_config) { |
| LCDERR("[%d]: %s: prbs_clk_config is null\n", |
| pdrv->index, __func__); |
| goto lcd_prbs_test_end_t7; |
| } |
| cconf->data->prbs_clk_config(pdrv, lcd_prbs_mode); |
| usleep_range(500, 510); |
| |
| /* set fifo_clk_sel: div 10 */ |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl0, (3 << 5)); |
| /* set cntl_ser_en: 10-channel */ |
| lcd_combo_dphy_setb(pdrv, reg_phy_tx_ctrl0, 0x3ff, 16, 10); |
| lcd_combo_dphy_setb(pdrv, reg_phy_tx_ctrl0, 1, 2, 1); |
| /* decoupling fifo enable, gated clock enable */ |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl1, (1 << 6) | (1 << 0)); |
| /* decoupling fifo write enable after fifo enable */ |
| lcd_combo_dphy_setb(pdrv, reg_phy_tx_ctrl1, 1, 7, 1); |
| |
| /* prbs_err en */ |
| lcd_combo_dphy_setb(pdrv, reg_phy_tx_ctrl0, 1, 13, 1); |
| lcd_combo_dphy_setb(pdrv, reg_phy_tx_ctrl0, 1, 12, 1); |
| |
| while (lcd_prbs_flag) { |
| if (lcd_prbs_cnt++ >= timeout) |
| break; |
| ret = 1; |
| val1 = lcd_combo_dphy_getb(pdrv, reg_ctrl_out, |
| bit_width, bit_width); |
| usleep_range(1000, 1001); |
| |
| for (j = 0; j < 20; j++) { |
| usleep_range(5, 10); |
| val2 = lcd_combo_dphy_getb(pdrv, reg_ctrl_out, |
| bit_width, bit_width); |
| if (val2 != val1) { |
| ret = 0; |
| break; |
| } |
| } |
| if (ret) { |
| LCDERR("[%d]: prbs check error 1, val:0x%03x, cnt:%d\n", |
| pdrv->index, val2, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t7; |
| } |
| if (lcd_combo_dphy_getb(pdrv, reg_ctrl_out, 0, bit_width)) { |
| LCDERR("[%d]: prbs check error 2, cnt:%d\n", |
| pdrv->index, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t7; |
| } |
| |
| if (lcd_prbs_clk_check(lcd_encl_clk_check_std, encl_msr_id, |
| lcd_fifo_clk_check_std, fifo_msr_id, |
| lcd_prbs_cnt)) |
| clk_err_cnt++; |
| else |
| clk_err_cnt = 0; |
| if (clk_err_cnt >= 10) { |
| LCDERR("[%d]: prbs check error 3(clkmsr), cnt: %d\n", |
| pdrv->index, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t7; |
| } |
| } |
| |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl0, 0); |
| lcd_combo_dphy_write(pdrv, reg_phy_tx_ctrl1, 0); |
| |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_LVDS); |
| LCDPR("[%d]: lvds prbs check ok\n", pdrv->index); |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_VX1); |
| LCDPR("[%d]: vx1 prbs check ok\n", pdrv->index); |
| } else { |
| LCDPR("[%d]: prbs check: unsupport mode\n", pdrv->index); |
| } |
| continue; |
| |
| lcd_prbs_test_err_t7: |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err |= LCD_PRBS_MODE_LVDS; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err |= LCD_PRBS_MODE_VX1; |
| } |
| } |
| |
| lcd_prbs_test_end_t7: |
| lcd_prbs_flag = 0; |
| } |
| |
| static void aml_lcd_prbs_test_t3(struct aml_lcd_drv_s *pdrv, |
| unsigned int ms, unsigned int mode_flag) |
| { |
| struct lcd_clk_config_s *cconf = get_lcd_clk_config(pdrv); |
| unsigned int reg_phy_tx_ctrl0, reg_phy_tx_ctrl1; |
| int encl_msr_id, fifo_msr_id; |
| unsigned int lcd_prbs_mode, lcd_prbs_cnt; |
| unsigned int val1, val2, timeout; |
| unsigned int clk_err_cnt = 0; |
| int i, j, ret; |
| |
| if (!cconf) |
| return; |
| |
| switch (pdrv->index) { |
| case 0: |
| reg_phy_tx_ctrl0 = ANACTRL_LVDS_TX_PHY_CNTL0; |
| reg_phy_tx_ctrl1 = ANACTRL_LVDS_TX_PHY_CNTL1; |
| break; |
| case 1: |
| reg_phy_tx_ctrl0 = ANACTRL_LVDS_TX_PHY_CNTL2; |
| reg_phy_tx_ctrl1 = ANACTRL_LVDS_TX_PHY_CNTL3; |
| break; |
| default: |
| LCDERR("[%d]: %s: invalid drv_index\n", pdrv->index, __func__); |
| return; |
| } |
| encl_msr_id = cconf->data->enc_clk_msr_id; |
| fifo_msr_id = cconf->data->fifo_clk_msr_id; |
| |
| timeout = (ms > 1000) ? 1000 : ms; |
| |
| for (i = 0; i < LCD_PRBS_MODE_MAX; i++) { |
| if ((mode_flag & (1 << i)) == 0) |
| continue; |
| |
| lcd_ana_write(reg_phy_tx_ctrl0, 0); |
| lcd_ana_write(reg_phy_tx_ctrl1, 0); |
| |
| lcd_prbs_cnt = 0; |
| clk_err_cnt = 0; |
| lcd_prbs_mode = (1 << i); |
| LCDPR("[%d]: lcd_prbs_mode: 0x%x\n", pdrv->index, lcd_prbs_mode); |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_encl_clk_check_std = 136000000; |
| lcd_fifo_clk_check_std = 48000000; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_encl_clk_check_std = 594000000; |
| lcd_fifo_clk_check_std = 297000000; |
| } |
| if (cconf->data->prbs_clk_config) { |
| cconf->data->prbs_clk_config(pdrv, lcd_prbs_mode); |
| } else { |
| LCDERR("[%d]: %s: prbs_clk_config is null\n", |
| pdrv->index, __func__); |
| goto lcd_prbs_test_end_t3; |
| } |
| usleep_range(500, 510); |
| |
| /* set fifo_clk_sel: div 10 */ |
| lcd_ana_write(reg_phy_tx_ctrl0, (3 << 6)); |
| /* set cntl_ser_en: 12-channel */ |
| lcd_ana_setb(reg_phy_tx_ctrl0, 0xfff, 16, 12); |
| lcd_ana_setb(reg_phy_tx_ctrl0, 1, 2, 1); |
| /* decoupling fifo enable, gated clock enable */ |
| lcd_ana_write(reg_phy_tx_ctrl1, (1 << 30) | (1 << 24)); |
| /* decoupling fifo write enable after fifo enable */ |
| lcd_ana_setb(reg_phy_tx_ctrl1, 1, 31, 1); |
| /* prbs_err en */ |
| lcd_ana_setb(reg_phy_tx_ctrl0, 1, 13, 1); |
| lcd_ana_setb(reg_phy_tx_ctrl0, 1, 12, 1); |
| |
| while (lcd_prbs_flag) { |
| if (lcd_prbs_cnt++ >= timeout) |
| break; |
| ret = 1; |
| val1 = lcd_ana_getb(reg_phy_tx_ctrl1, 12, 12); |
| usleep_range(1000, 1001); |
| |
| for (j = 0; j < 20; j++) { |
| usleep_range(5, 10); |
| val2 = lcd_ana_getb(reg_phy_tx_ctrl1, 12, 12); |
| if (val2 != val1) { |
| ret = 0; |
| break; |
| } |
| } |
| if (ret) { |
| LCDERR("[%d]: prbs check error 1, val:0x%03x, cnt:%d\n", |
| pdrv->index, val2, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t3; |
| } |
| if (lcd_ana_getb(reg_phy_tx_ctrl1, 0, 12)) { |
| LCDERR("[%d]: prbs check error 2, cnt:%d\n", |
| pdrv->index, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t3; |
| } |
| |
| if (lcd_prbs_clk_check(lcd_encl_clk_check_std, encl_msr_id, |
| lcd_fifo_clk_check_std, fifo_msr_id, |
| lcd_prbs_cnt)) |
| clk_err_cnt++; |
| else |
| clk_err_cnt = 0; |
| if (clk_err_cnt >= 10) { |
| LCDERR("[%d]: prbs check error 3(clkmsr), cnt: %d\n", |
| pdrv->index, lcd_prbs_cnt); |
| goto lcd_prbs_test_err_t3; |
| } |
| } |
| |
| lcd_ana_write(reg_phy_tx_ctrl0, 0); |
| lcd_ana_write(reg_phy_tx_ctrl1, 0); |
| |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_LVDS); |
| LCDPR("[%d]: lvds prbs check ok\n", pdrv->index); |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err &= ~(LCD_PRBS_MODE_VX1); |
| LCDPR("[%d]: vx1 prbs check ok\n", pdrv->index); |
| } else { |
| LCDPR("[%d]: prbs check: unsupport mode\n", pdrv->index); |
| } |
| continue; |
| |
| lcd_prbs_test_err_t3: |
| if (lcd_prbs_mode == LCD_PRBS_MODE_LVDS) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_LVDS; |
| lcd_prbs_err |= LCD_PRBS_MODE_LVDS; |
| } else if (lcd_prbs_mode == LCD_PRBS_MODE_VX1) { |
| lcd_prbs_performed |= LCD_PRBS_MODE_VX1; |
| lcd_prbs_err |= LCD_PRBS_MODE_VX1; |
| } |
| } |
| |
| lcd_prbs_test_end_t3: |
| lcd_prbs_flag = 0; |
| } |
| |
| static ssize_t lcd_debug_prbs_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, |
| "lvds prbs performed: %d, error: %d\n" |
| "vx1 prbs performed: %d, error: %d\n" |
| "lcd prbs flag: %d\n", |
| (lcd_prbs_performed & LCD_PRBS_MODE_LVDS) ? 1 : 0, |
| (lcd_prbs_err & LCD_PRBS_MODE_LVDS) ? 1 : 0, |
| (lcd_prbs_performed & LCD_PRBS_MODE_VX1) ? 1 : 0, |
| (lcd_prbs_err & LCD_PRBS_MODE_VX1) ? 1 : 0, |
| lcd_prbs_flag); |
| } |
| |
| static ssize_t lcd_debug_prbs_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int ret = 0; |
| unsigned int temp = 0; |
| unsigned int prbs_mode_flag; |
| |
| switch (buf[0]) { |
| case 'v': /* vx1 */ |
| ret = sscanf(buf, "vx1 %d", &temp); |
| if (ret) { |
| prbs_mode_flag = LCD_PRBS_MODE_VX1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'l': /* lvds */ |
| ret = sscanf(buf, "lvds %d", &temp); |
| if (ret) { |
| prbs_mode_flag = LCD_PRBS_MODE_LVDS; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| prbs_mode_flag = LCD_PRBS_MODE_LVDS | LCD_PRBS_MODE_VX1; |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| } |
| |
| if (temp) { |
| if (lcd_prbs_flag) { |
| LCDPR("lcd prbs check is already running\n"); |
| return count; |
| } |
| lcd_prbs_flag = 1; |
| if (lcd_debug_info_reg && lcd_debug_info_reg->prbs_test) |
| lcd_debug_info_reg->prbs_test(pdrv, temp, prbs_mode_flag); |
| } else { |
| if (lcd_prbs_flag == 0) { |
| LCDPR("lcd prbs check is already stopped\n"); |
| return count; |
| } |
| lcd_prbs_flag = 0; |
| } |
| |
| return count; |
| } |
| |
| static void lcd_debug_config_update(struct aml_lcd_drv_s *pdrv) |
| { |
| |
| pdrv->module_reset(pdrv); |
| |
| lcd_vinfo_update(pdrv); |
| } |
| |
| static void lcd_debug_clk_change(struct aml_lcd_drv_s *pdrv, unsigned int pclk) |
| { |
| struct lcd_config_s *pconf; |
| unsigned int sync_duration; |
| |
| lcd_vout_notify_mode_change_pre(pdrv); |
| |
| pconf = &pdrv->config; |
| sync_duration = pclk / pconf->basic.h_period; |
| sync_duration = sync_duration * 100 / pconf->basic.v_period; |
| pconf->timing.lcd_clk = pclk; |
| pconf->timing.lcd_clk_dft = pconf->timing.lcd_clk; |
| pconf->timing.sync_duration_num = sync_duration; |
| pconf->timing.sync_duration_den = 100; |
| |
| /* update vinfo */ |
| pdrv->vinfo.sync_duration_num = sync_duration; |
| pdrv->vinfo.sync_duration_den = 100; |
| pdrv->vinfo.video_clk = pclk; |
| |
| switch (pdrv->mode) { |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| case LCD_MODE_TV: |
| lcd_tv_clk_update(pdrv); |
| break; |
| #endif |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| case LCD_MODE_TABLET: |
| lcd_tablet_clk_update(pdrv); |
| break; |
| #endif |
| default: |
| LCDPR("invalid lcd mode\n"); |
| break; |
| } |
| |
| lcd_vout_notify_mode_change(pdrv); |
| } |
| |
| static void lcd_power_interface_ctrl(struct aml_lcd_drv_s *pdrv, int state) |
| { |
| mutex_lock(&lcd_power_mutex); |
| LCDPR("[%d]: %s: %d\n", pdrv->index, __func__, state); |
| if (state) { |
| if (pdrv->status & LCD_STATUS_ENCL_ON) { |
| aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, (void *)pdrv); |
| lcd_if_enable_retry(pdrv); |
| } else { |
| LCDERR("%s: can't power on when controller is off\n", __func__); |
| } |
| } else { |
| aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, (void *)pdrv); |
| } |
| mutex_unlock(&lcd_power_mutex); |
| } |
| |
| static ssize_t lcd_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int i, ret = 0; |
| unsigned int temp, val[6]; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lcd_config_s *pconf; |
| char *print_buf; |
| unsigned long flags = 0; |
| |
| pconf = &pdrv->config; |
| switch (buf[0]) { |
| case 'c': /* clk */ |
| ret = sscanf(buf, "clk %d", &temp); |
| if (ret == 1) { |
| if (temp > 200) { |
| pr_info("set clk: %dHz\n", temp); |
| } else { |
| pr_info("set frame_rate: %dHz\n", temp); |
| temp = pconf->basic.h_period * pconf->basic.v_period * temp; |
| pr_info("set clk: %dHz\n", temp); |
| } |
| lcd_debug_clk_change(pdrv, temp); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'b': |
| if (buf[1] == 'a') { /* basic */ |
| ret = sscanf(buf, "basic %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4]); |
| if (ret == 4) { |
| pconf->basic.h_active = val[0]; |
| pconf->basic.v_active = val[1]; |
| pconf->basic.h_period = val[2]; |
| pconf->basic.v_period = val[3]; |
| pconf->timing.h_period_dft = val[2]; |
| pconf->timing.v_period_dft = val[3]; |
| pr_info("set h_active=%d, v_active=%d\n", |
| val[0], val[1]); |
| pr_info("set h_period=%d, v_period=%d\n", |
| val[2], val[3]); |
| lcd_timing_init_config(pdrv); |
| lcd_debug_config_update(pdrv); |
| } else if (ret == 5) { |
| pconf->basic.h_active = val[0]; |
| pconf->basic.v_active = val[1]; |
| pconf->basic.h_period = val[2]; |
| pconf->basic.v_period = val[3]; |
| pconf->timing.h_period_dft = val[2]; |
| pconf->timing.v_period_dft = val[3]; |
| pconf->basic.lcd_bits = val[4]; |
| pr_info("set h_active=%d, v_active=%d\n", |
| val[0], val[1]); |
| pr_info("set h_period=%d, v_period=%d\n", |
| val[2], val[3]); |
| pr_info("set lcd_bits=%d\n", val[4]); |
| lcd_timing_init_config(pdrv); |
| lcd_debug_config_update(pdrv); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } else if (buf[1] == 'i') { /* bit */ |
| ret = sscanf(buf, "bit %d", &val[0]); |
| if (ret == 1) { |
| pconf->basic.lcd_bits = val[4]; |
| pr_info("set lcd_bits=%d\n", val[4]); |
| lcd_debug_config_update(pdrv); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| break; |
| case 's': /* sync */ |
| ret = sscanf(buf, "sync %d %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); |
| if (ret == 6) { |
| pconf->timing.hsync_width = val[0]; |
| pconf->timing.hsync_bp = val[1]; |
| pconf->timing.hsync_pol = val[2]; |
| pconf->timing.vsync_width = val[3]; |
| pconf->timing.vsync_bp = val[4]; |
| pconf->timing.vsync_pol = val[5]; |
| pr_info("set hsync width=%d, bp=%d, pol=%d\n", |
| val[0], val[1], val[2]); |
| pr_info("set vsync width=%d, bp=%d, pol=%d\n", |
| val[3], val[4], val[5]); |
| lcd_timing_init_config(pdrv); |
| lcd_debug_config_update(pdrv); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 't': /* test */ |
| ret = sscanf(buf, "test %d", &temp); |
| if (ret == 1) { |
| spin_lock_irqsave(&pdrv->isr_lock, flags); |
| pdrv->test_flag = (unsigned char)temp; |
| spin_unlock_irqrestore(&pdrv->isr_lock, flags); |
| LCDPR("%s: test %d\n", __func__, temp); |
| i = 0; |
| while (i++ < 5000) { |
| if (pdrv->test_state == temp) |
| break; |
| usleep_range(20, 30); |
| } |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'i': /* info */ |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) { |
| LCDERR("%s: buf malloc error\n", __func__); |
| return -EINVAL; |
| } |
| lcd_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| memset(print_buf, 0, PR_BUF_MAX); |
| lcd_power_step_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| kfree(print_buf); |
| break; |
| case 'r': |
| if (buf[2] == 'g') { /* reg */ |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), |
| GFP_KERNEL); |
| if (!print_buf) { |
| LCDERR("%s: buf malloc error\n", __func__); |
| return -EINVAL; |
| } |
| lcd_reg_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| kfree(print_buf); |
| } else if (buf[2] == 's') { /* reset */ |
| pdrv->module_reset(pdrv); |
| } else if (buf[2] == 'n') { /* range */ |
| ret = sscanf(buf, "range %d %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], |
| &val[4], &val[5]); |
| if (ret == 6) { |
| pconf->basic.h_period_min = val[0]; |
| pconf->basic.h_period_max = val[1]; |
| pconf->basic.h_period_min = val[2]; |
| pconf->basic.v_period_max = val[3]; |
| pconf->basic.lcd_clk_min = val[4]; |
| pconf->basic.lcd_clk_max = val[5]; |
| pr_info("set h_period min=%d, max=%d\n", |
| pconf->basic.h_period_min, |
| pconf->basic.h_period_max); |
| pr_info("set v_period min=%d, max=%d\n", |
| pconf->basic.v_period_min, |
| pconf->basic.v_period_max); |
| pr_info("set pclk min=%d, max=%d\n", |
| pconf->basic.lcd_clk_min, |
| pconf->basic.lcd_clk_max); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| break; |
| case 'd': /* dump */ |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) { |
| LCDERR("%s: buf malloc error\n", __func__); |
| return -EINVAL; |
| } |
| lcd_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| memset(print_buf, 0, PR_BUF_MAX); |
| lcd_power_step_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| memset(print_buf, 0, PR_BUF_MAX); |
| lcd_reg_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| memset(print_buf, 0, PR_BUF_MAX); |
| lcd_optical_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| kfree(print_buf); |
| break; |
| case 'k': /* key */ |
| LCDPR("key_valid: %d, config_load: %d\n", |
| pdrv->key_valid, pdrv->config_load); |
| if (pdrv->key_valid) |
| lcd_unifykey_print(); |
| break; |
| case 'h': /* hdr */ |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) { |
| LCDERR("%s: buf malloc error\n", __func__); |
| return -EINVAL; |
| } |
| lcd_optical_info_print(pdrv, print_buf, 0); |
| lcd_debug_info_print(print_buf); |
| kfree(print_buf); |
| break; |
| case 'p': /* power */ |
| ret = sscanf(buf, "power %d", &temp); |
| if (ret == 1) { |
| lcd_power_interface_ctrl(pdrv, temp); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'v': |
| ret = sscanf(buf, "vout %d", &temp); |
| if (ret == 1) { |
| LCDPR("vout_serve bypass: %d\n", temp); |
| lcd_vout_serve_bypass = temp; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'g': |
| ret = sscanf(buf, "gamma %d", &temp); |
| if (ret == 1) { |
| LCDPR("gamma en: %d\n", temp); |
| lcd_gamma_debug_test_en(pdrv, temp); |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| LCDERR("wrong command\n"); |
| break; |
| } |
| return count; |
| } |
| |
| static ssize_t lcd_debug_change_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%s\n", lcd_debug_change_usage_str); |
| } |
| |
| static void lcd_debug_change_clk_change(struct aml_lcd_drv_s *pdrv, unsigned int pclk) |
| { |
| struct lcd_config_s *pconf; |
| unsigned int sync_duration; |
| |
| pconf = &pdrv->config; |
| sync_duration = pclk / pconf->basic.h_period; |
| sync_duration = sync_duration * 100 / pconf->basic.v_period; |
| pconf->timing.lcd_clk = pclk; |
| pconf->timing.lcd_clk_dft = pconf->timing.lcd_clk; |
| pconf->timing.sync_duration_num = sync_duration; |
| pconf->timing.sync_duration_den = 100; |
| |
| switch (pdrv->mode) { |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| case LCD_MODE_TV: |
| lcd_tv_clk_config_change(pdrv); |
| break; |
| #endif |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| case LCD_MODE_TABLET: |
| lcd_tablet_clk_config_change(pdrv); |
| break; |
| #endif |
| default: |
| LCDPR("invalid lcd mode\n"); |
| break; |
| } |
| } |
| |
| static ssize_t lcd_debug_change_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| unsigned int temp, val[10]; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lcd_config_s *pconf; |
| union lcd_ctrl_config_u *pctrl; |
| |
| pconf = &pdrv->config; |
| pctrl = &pconf->control; |
| switch (buf[0]) { |
| case 'c': /* clk */ |
| ret = sscanf(buf, "clk %d", &temp); |
| if (ret == 1) { |
| if (temp > 200) { |
| pr_info("change clk=%dHz\n", temp); |
| } else { |
| pr_info("change frame_rate=%dHz\n", temp); |
| temp = pconf->basic.h_period * pconf->basic.v_period * temp; |
| pr_info("change clk=%dHz\n", temp); |
| } |
| lcd_debug_change_clk_change(pdrv, temp); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'b': |
| if (buf[1] == 'a') { /* basic */ |
| ret = sscanf(buf, "basic %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4]); |
| if (ret == 4) { |
| pconf->basic.h_active = val[0]; |
| pconf->basic.v_active = val[1]; |
| pconf->basic.h_period = val[2]; |
| pconf->basic.v_period = val[3]; |
| pconf->timing.h_period_dft = val[2]; |
| pconf->timing.v_period_dft = val[3]; |
| pr_info("change h_active=%d, v_active=%d\n", |
| val[0], val[1]); |
| pr_info("change h_period=%d, v_period=%d\n", |
| val[2], val[3]); |
| lcd_timing_init_config(pdrv); |
| pconf->change_flag = 1; |
| } else if (ret == 5) { |
| pconf->basic.h_active = val[0]; |
| pconf->basic.v_active = val[1]; |
| pconf->basic.h_period = val[2]; |
| pconf->basic.v_period = val[3]; |
| pconf->timing.h_period_dft = val[2]; |
| pconf->timing.v_period_dft = val[3]; |
| pconf->basic.lcd_bits = val[4]; |
| pr_info("change h_active=%d, v_active=%d\n", |
| val[0], val[1]); |
| pr_info("change h_period=%d, v_period=%d\n", |
| val[2], val[3]); |
| pr_info("change lcd_bits=%d\n", val[4]); |
| lcd_timing_init_config(pdrv); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } else if (buf[1] == 'i') { /* bit */ |
| ret = sscanf(buf, "bit %d", &val[0]); |
| if (ret == 1) { |
| pconf->basic.lcd_bits = val[4]; |
| pr_info("change lcd_bits=%d\n", val[4]); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| break; |
| case 's': |
| if (buf[1] == 'e') { /* set */ |
| if (pconf->change_flag) { |
| LCDPR("apply config changing\n"); |
| lcd_debug_config_update(pdrv); |
| } else { |
| LCDPR("config is no changing\n"); |
| } |
| } else if (buf[1] == 'y') { /* sync */ |
| ret = sscanf(buf, "sync %d %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], |
| &val[4], &val[5]); |
| if (ret == 6) { |
| pconf->timing.hsync_width = val[0]; |
| pconf->timing.hsync_bp = val[1]; |
| pconf->timing.hsync_pol = val[2]; |
| pconf->timing.vsync_width = val[3]; |
| pconf->timing.vsync_bp = val[4]; |
| pconf->timing.vsync_pol = val[5]; |
| pr_info("change hs width=%d, bp=%d, pol=%d\n", |
| val[0], val[1], val[2]); |
| pr_info("change vs width=%d, bp=%d, pol=%d\n", |
| val[3], val[4], val[5]); |
| lcd_timing_init_config(pdrv); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| break; |
| case 't': |
| ret = sscanf(buf, "ttl %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4]); |
| if (ret == 5) { |
| pctrl->ttl_cfg.clk_pol = val[0]; |
| pctrl->ttl_cfg.sync_valid = ((val[1] << 1) | val[2]); |
| pctrl->ttl_cfg.swap_ctrl = ((val[3] << 1) | val[4]); |
| pr_info("set ttl config:\n" |
| "clk_pol=%d, de_valid=%d, de_valid=%d, rb_swap=%d, bit_swap=%d\n", |
| val[0], val[1], val[2], val[3], val[4]); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'l': |
| ret = sscanf(buf, "lvds %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4]); |
| if (ret == 5) { |
| pctrl->lvds_cfg.lvds_repack = val[0]; |
| pctrl->lvds_cfg.dual_port = val[1]; |
| pctrl->lvds_cfg.pn_swap = val[2]; |
| pctrl->lvds_cfg.port_swap = val[3]; |
| pctrl->lvds_cfg.lane_reverse = val[4]; |
| pr_info("set lvds config:\n" |
| "repack=%d, dual_port=%d, pn_swap=%d, port_swap=%d, lane_reverse=%d\n", |
| pctrl->lvds_cfg.lvds_repack, |
| pctrl->lvds_cfg.dual_port, |
| pctrl->lvds_cfg.pn_swap, |
| pctrl->lvds_cfg.port_swap, |
| pctrl->lvds_cfg.lane_reverse); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else if (ret == 4) { |
| pctrl->lvds_cfg.lvds_repack = val[0]; |
| pctrl->lvds_cfg.dual_port = val[1]; |
| pctrl->lvds_cfg.pn_swap = val[2]; |
| pctrl->lvds_cfg.port_swap = val[3]; |
| pr_info("set lvds config:\n" |
| "repack=%d, dual_port=%d, pn_swap=%d, port_swap=%d\n", |
| pctrl->lvds_cfg.lvds_repack, |
| pctrl->lvds_cfg.dual_port, |
| pctrl->lvds_cfg.pn_swap, |
| pctrl->lvds_cfg.port_swap); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'v': |
| ret = sscanf(buf, "vbyone %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3]); |
| if (ret == 4 || ret == 3) { |
| pctrl->vbyone_cfg.lane_count = val[0]; |
| pctrl->vbyone_cfg.region_num = val[1]; |
| pctrl->vbyone_cfg.byte_mode = val[2]; |
| pr_info("set vbyone config:\n" |
| "lane_count=%d, region_num=%d, byte_mode=%d\n", |
| pctrl->vbyone_cfg.lane_count, |
| pctrl->vbyone_cfg.region_num, |
| pctrl->vbyone_cfg.byte_mode); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'm': |
| if (buf[1] == 'i') { |
| ret = sscanf(buf, "mipi %d %d %d %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], |
| &val[4], &val[5], &val[6], &val[7]); |
| if (ret == 8) { |
| pctrl->mipi_cfg.lane_num = (unsigned char)val[0]; |
| pctrl->mipi_cfg.bit_rate_max = val[1]; |
| pctrl->mipi_cfg.factor_numerator = val[2]; |
| pctrl->mipi_cfg.operation_mode_init = |
| (unsigned char)val[3]; |
| pctrl->mipi_cfg.operation_mode_display = |
| (unsigned char)val[4]; |
| pctrl->mipi_cfg.video_mode_type = |
| (unsigned char)val[5]; |
| pctrl->mipi_cfg.clk_always_hs = (unsigned char)val[6]; |
| pctrl->mipi_cfg.phy_switch = (unsigned char)val[7]; |
| pr_info("change mipi_dsi config:\n" |
| "lane_num=%d, bit_rate_max=%dMhz, factor_numerator=%d\n" |
| "operation_mode_init=%d, operation_mode_display=%d\n" |
| "video_mode_type=%d, clk_always_hs=%d, phy_switch=%d\n", |
| pctrl->mipi_cfg.lane_num, |
| pctrl->mipi_cfg.bit_rate_max, |
| pctrl->mipi_cfg.factor_numerator, |
| pctrl->mipi_cfg.operation_mode_init, |
| pctrl->mipi_cfg.operation_mode_display, |
| pctrl->mipi_cfg.video_mode_type, |
| pctrl->mipi_cfg.clk_always_hs, |
| pctrl->mipi_cfg.phy_switch); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } else if (buf[1] == 'l') { |
| ret = sscanf(buf, "mlvds %d %x %x %x %d %d", |
| &val[0], &val[1], &val[2], &val[3], |
| &val[4], &val[5]); |
| if (ret == 6) { |
| pctrl->mlvds_cfg.channel_num = val[0]; |
| pctrl->mlvds_cfg.channel_sel0 = val[1]; |
| pctrl->mlvds_cfg.channel_sel1 = val[2]; |
| pctrl->mlvds_cfg.clk_phase = val[3]; |
| pctrl->mlvds_cfg.pn_swap = val[4]; |
| pctrl->mlvds_cfg.bit_swap = val[5]; |
| pr_info("change mlvds config:\n" |
| "channel_num=%d,\n" |
| "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" |
| "clk_phase=0x%04x,\n" |
| "pn_swap=%d, bit_swap=%d\n", |
| pctrl->mlvds_cfg.channel_num, |
| pctrl->mlvds_cfg.channel_sel0, |
| pctrl->mlvds_cfg.channel_sel1, |
| pctrl->mlvds_cfg.clk_phase, |
| pctrl->mlvds_cfg.pn_swap, |
| pctrl->mlvds_cfg.bit_swap); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| break; |
| case 'p': |
| ret = sscanf(buf, "p2p %x %d %x %x %d %d", |
| &val[0], &val[1], &val[2], &val[3], &val[4], &val[5]); |
| if (ret == 6) { |
| pctrl->p2p_cfg.p2p_type = val[0]; |
| pctrl->p2p_cfg.lane_num = val[1]; |
| pctrl->p2p_cfg.channel_sel0 = val[2]; |
| pctrl->p2p_cfg.channel_sel1 = val[3]; |
| pctrl->p2p_cfg.pn_swap = val[4]; |
| pctrl->p2p_cfg.bit_swap = val[5]; |
| pr_info("change p2p config:\n" |
| "p2p_type=0x%x, lane_num=%d,\n" |
| "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" |
| "pn_swap=%d, bit_swap=%d\n", |
| pctrl->p2p_cfg.p2p_type, |
| pctrl->p2p_cfg.lane_num, |
| pctrl->p2p_cfg.channel_sel0, |
| pctrl->p2p_cfg.channel_sel1, |
| pctrl->p2p_cfg.pn_swap, |
| pctrl->p2p_cfg.bit_swap); |
| lcd_debug_change_clk_change(pdrv, pconf->timing.lcd_clk); |
| pconf->change_flag = 1; |
| } else { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'u': /* update */ |
| if (pconf->change_flag) { |
| LCDPR("apply config changing\n"); |
| lcd_debug_config_update(pdrv); |
| } else { |
| LCDPR("config is no changing\n"); |
| } |
| break; |
| default: |
| LCDERR("wrong command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_enable_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "lcd_status: 0x%x\n", pdrv->status); |
| } |
| |
| static ssize_t lcd_debug_enable_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int ret = 0; |
| unsigned int temp = 1; |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| if (temp) { |
| mutex_lock(&lcd_power_mutex); |
| aml_lcd_notifier_call_chain(LCD_EVENT_POWER_ON, (void *)pdrv); |
| lcd_if_enable_retry(pdrv); |
| mutex_unlock(&lcd_power_mutex); |
| } else { |
| mutex_lock(&lcd_power_mutex); |
| aml_lcd_notifier_call_chain(LCD_EVENT_POWER_OFF, (void *)pdrv); |
| mutex_unlock(&lcd_power_mutex); |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_resume_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "lcd resume type: %d(%s)\n", |
| pdrv->resume_type, |
| pdrv->resume_type ? "workqueue" : "directly"); |
| } |
| |
| static ssize_t lcd_debug_resume_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp = 1; |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| pdrv->resume_type = (unsigned char)temp; |
| LCDPR("set lcd resume flag: %d\n", pdrv->resume_type); |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_power_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int state; |
| |
| if ((pdrv->status & LCD_STATUS_ON) == 0) { |
| state = 0; |
| } else { |
| if (pdrv->status & LCD_STATUS_IF_ON) |
| state = 1; |
| else |
| state = 0; |
| } |
| return sprintf(buf, "lcd power state: %d\n", state); |
| } |
| |
| static ssize_t lcd_debug_power_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int ret = 0; |
| unsigned int temp = 1; |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| LCDERR("invalid data\n"); |
| return -EINVAL; |
| } |
| if (temp) { |
| mutex_lock(&lcd_power_mutex); |
| aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_ON, (void *)pdrv); |
| lcd_if_enable_retry(pdrv); |
| mutex_unlock(&lcd_power_mutex); |
| } else { |
| mutex_lock(&lcd_power_mutex); |
| aml_lcd_notifier_call_chain(LCD_EVENT_IF_POWER_OFF, (void *)pdrv); |
| mutex_unlock(&lcd_power_mutex); |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_power_step_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| char *print_buf; |
| int n = 0; |
| |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) |
| return sprintf(buf, "%s: buf malloc error\n", __func__); |
| |
| lcd_power_step_info_print(pdrv, print_buf, 0); |
| |
| n = sprintf(buf, "%s\n", print_buf); |
| kfree(print_buf); |
| |
| return n; |
| } |
| |
| static ssize_t lcd_debug_power_step_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| unsigned int i; |
| unsigned int tmp[2]; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lcd_power_ctrl_s *power_step; |
| |
| power_step = &pdrv->config.power; |
| switch (buf[1]) { |
| case 'n': /* on */ |
| ret = sscanf(buf, "on %d %d %d", &i, &tmp[0], &tmp[1]); |
| if (ret == 3) { |
| if (i >= power_step->power_on_step_max) { |
| pr_info("invalid power_on step: %d, step_max: %d\n", |
| i, power_step->power_on_step_max); |
| return -EINVAL; |
| } |
| power_step->power_on_step[i].value = tmp[0]; |
| power_step->power_on_step[i].delay = tmp[1]; |
| pr_info |
| ("set power_on step %d value %d delay: %dms\n", |
| i, tmp[0], tmp[1]); |
| } else if (ret == 2) { |
| if (i >= power_step->power_on_step_max) { |
| pr_info("invalid power_on step: %d\n", i); |
| return -EINVAL; |
| } |
| power_step->power_on_step[i].delay = tmp[0]; |
| pr_info("set power_on step %d delay: %dms\n", |
| i, tmp[0]); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'f': /* off */ |
| ret = sscanf(buf, "off %d %d %d\n", &i, &tmp[0], &tmp[1]); |
| if (ret == 3) { |
| if (i >= power_step->power_off_step_max) { |
| pr_info("invalid power_off step: %d\n", i); |
| return -EINVAL; |
| } |
| power_step->power_off_step[i].value = tmp[0]; |
| power_step->power_off_step[i].delay = tmp[1]; |
| pr_info |
| ("set power_off step %d value %d delay: %dms\n", |
| i, tmp[0], tmp[1]); |
| } else if (ret == 2) { |
| if (i >= power_step->power_off_step_max) { |
| pr_info("invalid power_off step: %d\n", i); |
| return -EINVAL; |
| } |
| power_step->power_off_step[i].delay = tmp[0]; |
| pr_info("set power_off step %d delay: %dms\n", |
| i, tmp[0]); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| pr_info("wrong command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_frame_rate_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| unsigned int sync_duration; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lcd_config_s *pconf; |
| |
| pconf = &pdrv->config; |
| sync_duration = pconf->timing.sync_duration_num * 100; |
| sync_duration = sync_duration / pconf->timing.sync_duration_den; |
| |
| return sprintf(buf, "get frame_rate: %u.%02uHz, fr_adjust_type: %d\n", |
| (sync_duration / 100), (sync_duration % 100), |
| pconf->timing.fr_adjust_type); |
| } |
| |
| static ssize_t lcd_debug_frame_rate_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| unsigned int temp = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| switch (buf[0]) { |
| case 't': |
| ret = sscanf(buf, "type %d", &temp); |
| if (ret == 1) { |
| pdrv->config.timing.fr_adjust_type = temp; |
| pr_info("set fr_adjust_type: %d\n", temp); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 's': |
| ret = sscanf(buf, "set %d", &temp); |
| if (ret == 1) { |
| pr_info("set frame rate(*100): %d\n", temp); |
| pdrv->fr_adjust(pdrv, temp); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| pr_info("wrong command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_fr_policy_show(struct device *dev, struct device_attribute *attr, |
| char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "fr_auto_policy: %d\n", pdrv->fr_auto_policy); |
| } |
| |
| static ssize_t lcd_debug_fr_policy_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp = 0; |
| int ret = 0; |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| pdrv->fr_auto_policy = temp; |
| pr_info("set fr_auto_policy: %d\n", temp); |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_ss_show(struct device *dev, struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int len; |
| |
| len = lcd_get_ss(pdrv, buf); |
| return len; |
| } |
| |
| static ssize_t lcd_debug_ss_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int value = 0, temp; |
| int ret = 0; |
| |
| temp = pdrv->config.timing.ss_level; |
| switch (buf[0]) { |
| case 'l': |
| ret = sscanf(buf, "level %d", &value); |
| if (ret == 1) { |
| value &= 0xff; |
| ret = lcd_set_ss(pdrv, value, 0xff, 0xff); |
| if (ret == 0) { |
| temp &= ~(0xff); |
| temp |= value; |
| pdrv->config.timing.ss_level = temp; |
| } |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'f': |
| ret = sscanf(buf, "freq %d", &value); |
| if (ret == 1) { |
| value &= 0xf; |
| ret = lcd_set_ss(pdrv, 0xff, value, 0xff); |
| if (ret == 0) { |
| temp &= ~((0xf << LCD_CLK_SS_BIT_FREQ) << 8); |
| temp |= ((value << LCD_CLK_SS_BIT_FREQ) << 8); |
| pdrv->config.timing.ss_level = temp; |
| } |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'm': |
| ret = sscanf(buf, "mode %d", &value); |
| if (ret == 1) { |
| value &= 0xf; |
| ret = lcd_set_ss(pdrv, 0xff, 0xff, value); |
| if (ret == 0) { |
| temp &= ~((0xf << LCD_CLK_SS_BIT_MODE) << 8); |
| temp |= ((value << LCD_CLK_SS_BIT_MODE) << 8); |
| pdrv->config.timing.ss_level = temp; |
| } |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| ret = kstrtouint(buf, 16, &value); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| value &= 0xffff; |
| temp = value >> 8; |
| ret = lcd_set_ss(pdrv, (value & 0xff), |
| ((temp >> LCD_CLK_SS_BIT_FREQ) & 0xf), |
| ((temp >> LCD_CLK_SS_BIT_MODE) & 0xf)); |
| if (ret == 0) |
| pdrv->config.timing.ss_level = value; |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_clk_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| char *print_buf; |
| int n = 0; |
| |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) |
| return sprintf(buf, "%s: buf malloc error\n", __func__); |
| |
| n = lcd_clk_config_print(pdrv, print_buf, 0); |
| lcd_clk_clkmsr_print(pdrv, (buf + n), n); |
| |
| n = sprintf(buf, "%s\n", print_buf); |
| kfree(print_buf); |
| |
| return n; |
| } |
| |
| static ssize_t lcd_debug_clk_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp = 0; |
| int ret = 0; |
| |
| switch (buf[0]) { |
| case 'p': |
| ret = sscanf(buf, "path %d", &temp); |
| if (ret == 1) { |
| ret = lcd_clk_path_change(pdrv, temp); |
| if (ret) { |
| pr_info("change clk_path error\n"); |
| } else { |
| pdrv->clk_path = temp; |
| lcd_clk_generate_parameter(pdrv); |
| pr_info("change clk_path: %d\n", temp); |
| } |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| pr_info("wrong command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_test_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "[%d]: test pattern: %d\n", pdrv->index, pdrv->test_state); |
| } |
| |
| static ssize_t lcd_debug_test_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp = 0, i = 0; |
| int ret = 0; |
| unsigned long flags = 0; |
| |
| if (buf[0] == 'f') { /* force test pattern */ |
| ret = sscanf(buf, "force %d", &temp); |
| if (ret == 0) |
| goto lcd_debug_test_store_next; |
| spin_lock_irqsave(&pdrv->isr_lock, flags); |
| temp = (temp >= LCD_ENC_TST_NUM_MAX) ? 0 : temp; |
| pdrv->test_flag = (unsigned char)temp; |
| pdrv->test_state = (unsigned char)temp; |
| lcd_debug_test(pdrv, pdrv->test_state); |
| spin_unlock_irqrestore(&pdrv->isr_lock, flags); |
| return count; |
| } |
| |
| lcd_debug_test_store_next: |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| spin_lock_irqsave(&pdrv->isr_lock, flags); |
| temp = (temp >= LCD_ENC_TST_NUM_MAX) ? 0 : temp; |
| pdrv->test_flag = (unsigned char)temp; |
| spin_unlock_irqrestore(&pdrv->isr_lock, flags); |
| |
| LCDPR("[%d]: %s: %d\n", pdrv->index, __func__, temp); |
| while (i++ < 5000) { |
| if (pdrv->test_state == temp) |
| break; |
| lcd_delay_us(20); |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_mute_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "get lcd mute state: %d\n", pdrv->mute_state); |
| } |
| |
| static ssize_t lcd_debug_mute_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp = 0, i = 0; |
| int ret = 0; |
| unsigned long flags = 0; |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| spin_lock_irqsave(&pdrv->isr_lock, flags); |
| temp = temp ? 1 : 0; |
| pdrv->mute_flag = (unsigned char)temp; |
| spin_unlock_irqrestore(&pdrv->isr_lock, flags); |
| |
| LCDPR("[%d]: %s: %d\n", pdrv->index, __func__, temp); |
| while (i++ < 5000) { |
| if (pdrv->mute_state == temp) |
| break; |
| lcd_delay_us(20); |
| } |
| |
| return count; |
| } |
| |
| static void lcd_debug_reg_write(struct aml_lcd_drv_s *pdrv, unsigned int reg, |
| unsigned int data, unsigned int bus) |
| { |
| switch (bus) { |
| case 0: /* vcbus */ |
| lcd_vcbus_write(reg, data); |
| pr_info("write vcbus [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_vcbus_read(reg)); |
| break; |
| case 1: /* ana */ |
| lcd_ana_write(reg, data); |
| pr_info("write ana [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_ana_read(reg)); |
| break; |
| case 2: /* clk */ |
| lcd_clk_write(reg, data); |
| pr_info("write clk [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_clk_read(reg)); |
| break; |
| case 3: /* periphs */ |
| lcd_periphs_write(pdrv, reg, data); |
| pr_info("write periphs [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_periphs_read(pdrv, reg)); |
| break; |
| case 4: /* mipi_dsi_host */ |
| dsi_host_write(pdrv, reg, data); |
| pr_info("write mipi_dsi_host [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, dsi_host_read(pdrv, reg)); |
| break; |
| case 5: /* mipi_dsi_phy */ |
| dsi_phy_write(pdrv, reg, data); |
| pr_info("write mipi_dsi_phy [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, dsi_phy_read(pdrv, reg)); |
| break; |
| case 6: /* tcon */ |
| lcd_tcon_reg_write(pdrv, reg, data); |
| if (reg < TCON_TOP_BASE) { |
| pr_info("write tcon [0x%04x] = 0x%02x, readback 0x%02x\n", |
| reg, data, lcd_tcon_reg_read(pdrv, reg)); |
| } else { |
| pr_info("write tcon [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_tcon_reg_read(pdrv, reg)); |
| } |
| break; |
| case 7: /* edp */ |
| dptx_reg_write(pdrv, reg, data); |
| pr_info("write edp [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, dptx_reg_read(pdrv, reg)); |
| break; |
| case 8: /* combo dphy */ |
| lcd_combo_dphy_write(pdrv, reg, data); |
| pr_info("write combo dphy [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_combo_dphy_read(pdrv, reg)); |
| break; |
| case 9: /* rst */ |
| lcd_reset_write(pdrv, reg, data); |
| pr_info("write rst [0x%04x] = 0x%08x, readback 0x%08x\n", |
| reg, data, lcd_reset_read(pdrv, reg)); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| static void lcd_debug_reg_read(struct aml_lcd_drv_s *pdrv, |
| unsigned int reg, unsigned int bus) |
| { |
| switch (bus) { |
| case 0: /* vcbus */ |
| pr_info("read vcbus [0x%04x] = 0x%08x\n", |
| reg, lcd_vcbus_read(reg)); |
| break; |
| case 1: /* ana */ |
| pr_info("read ana [0x%04x] = 0x%08x\n", |
| reg, lcd_ana_read(reg)); |
| break; |
| case 2: /* clk */ |
| pr_info("read clk [0x%04x] = 0x%08x\n", |
| reg, lcd_clk_read(reg)); |
| break; |
| case 3: /* periphs */ |
| pr_info("read periphs [0x%04x] = 0x%08x\n", |
| reg, lcd_periphs_read(pdrv, reg)); |
| break; |
| case 4: /* mipi_dsi_host */ |
| pr_info("read mipi_dsi_host [0x%04x] = 0x%08x\n", |
| reg, dsi_host_read(pdrv, reg)); |
| break; |
| case 5: /* mipi_dsi_phy */ |
| pr_info("read mipi_dsi_phy [0x%04x] = 0x%08x\n", |
| reg, dsi_phy_read(pdrv, reg)); |
| break; |
| case 6: /* tcon */ |
| if (reg < TCON_TOP_BASE) { |
| pr_info("read tcon [0x%04x] = 0x%02x\n", |
| reg, lcd_tcon_reg_read(pdrv, reg)); |
| } else { |
| pr_info("read tcon [0x%04x] = 0x%08x\n", |
| reg, lcd_tcon_reg_read(pdrv, reg)); |
| } |
| break; |
| case 7: /* edp */ |
| pr_info("read edp [0x%04x] = 0x%08x\n", |
| reg, dptx_reg_read(pdrv, reg)); |
| break; |
| case 8: /* combo dphy */ |
| pr_info("read combo dphy [0x%04x] = 0x%08x\n", |
| reg, lcd_combo_dphy_read(pdrv, reg)); |
| break; |
| case 9: /* rst */ |
| pr_info("read rst [0x%04x] = 0x%08x\n", |
| reg, lcd_reset_read(pdrv, reg)); |
| break; |
| default: |
| break; |
| } |
| } |
| |
| static void lcd_debug_reg_dump(struct aml_lcd_drv_s *pdrv, unsigned int reg, |
| unsigned int num, unsigned int bus) |
| { |
| int i; |
| |
| switch (bus) { |
| case 0: /* vcbus */ |
| pr_info("dump vcbus regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_vcbus_read(reg + i)); |
| } |
| break; |
| case 1: /* ana */ |
| pr_info("dump ana regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_ana_read(reg + i)); |
| } |
| break; |
| case 2: /* clk */ |
| pr_info("dump clk regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_clk_read(reg + i)); |
| } |
| break; |
| case 3: /* periphs */ |
| pr_info("dump periphs-bus regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_periphs_read(pdrv, reg + i)); |
| } |
| break; |
| case 4: /* mipi_dsi_host */ |
| pr_info("dump mipi_dsi_host regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), dsi_host_read(pdrv, reg + i)); |
| } |
| break; |
| case 5: /* mipi_dsi_phy */ |
| pr_info("dump mipi_dsi_phy regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), dsi_phy_read(pdrv, reg + i)); |
| } |
| break; |
| case 6: /* tcon */ |
| pr_info("dump tcon regs:\n"); |
| if (reg < TCON_TOP_BASE) { |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%02x\n", |
| (reg + i), lcd_tcon_reg_read(pdrv, reg + i)); |
| } |
| } else { |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_tcon_reg_read(pdrv, reg + i)); |
| } |
| } |
| break; |
| case 7: /* edp */ |
| pr_info("dump edp regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), dptx_reg_read(pdrv, reg + i)); |
| } |
| break; |
| case 8: /* combo dphy */ |
| pr_info("dump combo dphy regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_combo_dphy_read(pdrv, reg + i)); |
| } |
| break; |
| case 9: /* rst */ |
| pr_info("dump rst regs:\n"); |
| for (i = 0; i < num; i++) { |
| pr_info("[0x%04x] = 0x%08x\n", |
| (reg + i), lcd_reset_read(pdrv, reg + i)); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| static ssize_t lcd_debug_reg_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int bus = 0; |
| unsigned int reg32 = 0, data32 = 0; |
| int ret = 0; |
| |
| switch (buf[0]) { |
| case 'w': |
| if (buf[1] == 'v') { /* vcbus */ |
| ret = sscanf(buf, "wv %x %x", ®32, &data32); |
| bus = 0; |
| } else if (buf[1] == 'a') { /* ana */ |
| ret = sscanf(buf, "wa %x %x", ®32, &data32); |
| bus = 1; |
| } else if (buf[1] == 'c') { /* clk */ |
| ret = sscanf(buf, "wc %x %x", ®32, &data32); |
| bus = 2; |
| } else if (buf[1] == 'p') { /* periphs */ |
| ret = sscanf(buf, "wp %x %x", ®32, &data32); |
| bus = 3; |
| } else if (buf[1] == 'm') { |
| if (buf[2] == 'h') { /* mipi host */ |
| ret = sscanf(buf, "wmh %x %x", ®32, &data32); |
| bus = 4; |
| } else if (buf[2] == 'p') { /* mipi phy */ |
| ret = sscanf(buf, "wmp %x %x", ®32, &data32); |
| bus = 5; |
| } |
| } else if (buf[1] == 't') { /* tcon */ |
| ret = sscanf(buf, "wt %x %x", ®32, &data32); |
| bus = 6; |
| } else if (buf[1] == 'e') { /* edp */ |
| ret = sscanf(buf, "we %x %x", ®32, &data32); |
| bus = 7; |
| } else if (buf[1] == 'd') { /* combo dphy */ |
| ret = sscanf(buf, "wd %x %x", ®32, &data32); |
| bus = 8; |
| } else if (buf[1] == 'r') { /* rst */ |
| ret = sscanf(buf, "wr %x %x", ®32, &data32); |
| bus = 9; |
| } |
| if (ret == 2) { |
| lcd_debug_reg_write(pdrv, reg32, data32, bus); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'r': |
| if (buf[1] == 'v') { /* vcbus */ |
| ret = sscanf(buf, "rv %x", ®32); |
| bus = 0; |
| } else if (buf[1] == 'a') { /* ana */ |
| ret = sscanf(buf, "ra %x", ®32); |
| bus = 1; |
| } else if (buf[1] == 'c') { /* clk */ |
| ret = sscanf(buf, "rc %x", ®32); |
| bus = 2; |
| } else if (buf[1] == 'p') { /* periphs */ |
| ret = sscanf(buf, "rp %x", ®32); |
| bus = 3; |
| } else if (buf[1] == 'm') { |
| if (buf[2] == 'h') { /* mipi host */ |
| ret = sscanf(buf, "rmh %x", ®32); |
| bus = 4; |
| } else if (buf[2] == 'p') { /* mipi phy */ |
| ret = sscanf(buf, "rmp %x", ®32); |
| bus = 5; |
| } |
| } else if (buf[1] == 't') { /* tcon */ |
| ret = sscanf(buf, "rt %x", ®32); |
| bus = 6; |
| } else if (buf[1] == 'e') { /* edp */ |
| ret = sscanf(buf, "re %x", ®32); |
| bus = 7; |
| } else if (buf[1] == 'd') { /* combo dphy */ |
| ret = sscanf(buf, "rd %x", ®32); |
| bus = 8; |
| } else if (buf[1] == 'r') { /* rst */ |
| ret = sscanf(buf, "rr %x", ®32); |
| bus = 9; |
| } |
| if (ret == 1) { |
| lcd_debug_reg_read(pdrv, reg32, bus); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| case 'd': |
| if (buf[1] == 'v') { /* vcbus */ |
| ret = sscanf(buf, "dv %x %d", ®32, &data32); |
| bus = 0; |
| } else if (buf[1] == 'a') { /* ana */ |
| ret = sscanf(buf, "da %x %d", ®32, &data32); |
| bus = 1; |
| } else if (buf[1] == 'c') { /* clk */ |
| ret = sscanf(buf, "dc %x %d", ®32, &data32); |
| bus = 2; |
| } else if (buf[1] == 'p') { /* periphs */ |
| ret = sscanf(buf, "dp %x %d", ®32, &data32); |
| bus = 3; |
| } else if (buf[1] == 'm') { |
| if (buf[2] == 'h') { /* mipi host */ |
| ret = sscanf(buf, "dmh %x %d", ®32, &data32); |
| bus = 4; |
| } else if (buf[2] == 'p') { /* mipi phy */ |
| ret = sscanf(buf, "dmp %x %d", ®32, &data32); |
| bus = 5; |
| } |
| } else if (buf[1] == 't') { /* tcon */ |
| ret = sscanf(buf, "dt %x %d", ®32, &data32); |
| bus = 6; |
| } else if (buf[1] == 'e') { /* edp */ |
| ret = sscanf(buf, "de %x %x", ®32, &data32); |
| bus = 7; |
| } else if (buf[1] == 'd') { /* combo dphy */ |
| ret = sscanf(buf, "dd %x %x", ®32, &data32); |
| bus = 8; |
| } else if (buf[1] == 'r') { /* rst */ |
| ret = sscanf(buf, "dr %x %x", ®32, &data32); |
| bus = 9; |
| } |
| if (ret == 2) { |
| lcd_debug_reg_dump(pdrv, reg32, data32, bus); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| break; |
| default: |
| pr_info("wrong command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_vlock_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| ssize_t len = 0; |
| |
| len = sprintf(buf, "custome vlock attr:\n" |
| "vlock_valid: %d\n" |
| "vlock_en: %d\n" |
| "vlock_work_mode: %d\n" |
| "vlock_pll_m_limit: %d\n" |
| "vlock_line_limit: %d\n", |
| pdrv->config.vlock_param[0], |
| pdrv->config.vlock_param[1], |
| pdrv->config.vlock_param[2], |
| pdrv->config.vlock_param[3], |
| pdrv->config.vlock_param[4]); |
| |
| return len; |
| } |
| |
| #define LCD_DEBUG_DUMP_INFO 0 |
| #define LCD_DEBUG_DUMP_REG 1 |
| #define LCD_DEBUG_DUMP_HDR 2 |
| static int lcd_debug_dump_state; |
| static ssize_t lcd_debug_dump_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| char *print_buf; |
| int len = 0; |
| |
| print_buf = kcalloc(PR_BUF_MAX, sizeof(char), GFP_KERNEL); |
| if (!print_buf) |
| return sprintf(buf, "%s: buf malloc error\n", __func__); |
| |
| switch (lcd_debug_dump_state) { |
| case LCD_DEBUG_DUMP_INFO: |
| len = lcd_info_print(pdrv, print_buf, 0); |
| lcd_power_step_info_print(pdrv, (print_buf + len), len); |
| break; |
| case LCD_DEBUG_DUMP_REG: |
| lcd_reg_print(pdrv, print_buf, 0); |
| break; |
| case LCD_DEBUG_DUMP_HDR: |
| lcd_optical_info_print(pdrv, print_buf, 0); |
| break; |
| default: |
| sprintf(print_buf, "%s: invalid command\n", __func__); |
| break; |
| } |
| len = sprintf(buf, "%s\n", print_buf); |
| kfree(print_buf); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_debug_dump_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| char *buf_orig; |
| char *parm[47] = {NULL}; |
| |
| if (!buf) |
| return count; |
| buf_orig = kstrdup(buf, GFP_KERNEL); |
| if (!buf_orig) { |
| LCDERR("%s: buf malloc error\n", __func__); |
| return count; |
| } |
| lcd_debug_parse_param(buf_orig, (char **)&parm); |
| |
| if (strcmp(parm[0], "info") == 0) { |
| lcd_debug_dump_state = LCD_DEBUG_DUMP_INFO; |
| } else if (strcmp(parm[0], "reg") == 0) { |
| lcd_debug_dump_state = LCD_DEBUG_DUMP_REG; |
| } else if (strcmp(parm[0], "hdr") == 0) { |
| lcd_debug_dump_state = LCD_DEBUG_DUMP_HDR; |
| } else { |
| LCDERR("invalid command\n"); |
| kfree(buf_orig); |
| return -EINVAL; |
| } |
| |
| kfree(buf_orig); |
| return count; |
| } |
| |
| static ssize_t lcd_debug_print_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "get debug print flag: 0x%x\n", |
| lcd_debug_print_flag); |
| } |
| |
| static ssize_t lcd_debug_print_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| unsigned int temp = 0; |
| |
| ret = kstrtouint(buf, 16, &temp); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| lcd_debug_print_flag = (unsigned char)temp; |
| LCDPR("set debug print flag: 0x%x\n", lcd_debug_print_flag); |
| |
| return count; |
| } |
| |
| static ssize_t lcd_debug_vinfo_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| ssize_t len = 0; |
| |
| len = sprintf(buf, "lcd vinfo:\n" |
| " lcd_mode: %s\n" |
| " name: %s\n" |
| " mode: %d\n" |
| " frac: %d\n" |
| " width: %d\n" |
| " height: %d\n" |
| " field_height: %d\n" |
| " aspect_ratio_num: %d\n" |
| " aspect_ratio_den: %d\n" |
| " sync_duration_num: %d\n" |
| " sync_duration_den: %d\n" |
| " screen_real_width: %d\n" |
| " screen_real_height: %d\n" |
| " htotal: %d\n" |
| " vtotal: %d\n" |
| " fr_adj_type: %d\n" |
| " video_clk: %d\n" |
| " viu_color_fmt: %d\n" |
| " viu_mux: 0x%x\n\n", |
| lcd_mode_mode_to_str(pdrv->mode), |
| pdrv->vinfo.name, |
| pdrv->vinfo.mode, |
| pdrv->vinfo.frac, |
| pdrv->vinfo.width, |
| pdrv->vinfo.height, |
| pdrv->vinfo.field_height, |
| pdrv->vinfo.aspect_ratio_num, |
| pdrv->vinfo.aspect_ratio_den, |
| pdrv->vinfo.sync_duration_num, |
| pdrv->vinfo.sync_duration_den, |
| pdrv->vinfo.screen_real_width, |
| pdrv->vinfo.screen_real_height, |
| pdrv->vinfo.htotal, |
| pdrv->vinfo.vtotal, |
| pdrv->vinfo.fr_adj_type, |
| pdrv->vinfo.video_clk, |
| pdrv->vinfo.viu_color_fmt, |
| pdrv->vinfo.viu_mux); |
| |
| return len; |
| } |
| |
| static struct device_attribute lcd_debug_attrs[] = { |
| __ATTR(help, 0444, lcd_debug_common_help, NULL), |
| __ATTR(debug, 0644, lcd_debug_show, lcd_debug_store), |
| __ATTR(change, 0644, lcd_debug_change_show, lcd_debug_change_store), |
| __ATTR(enable, 0644, lcd_debug_enable_show, lcd_debug_enable_store), |
| __ATTR(resume_type, 0644, lcd_debug_resume_show, lcd_debug_resume_store), |
| __ATTR(power_on, 0644, lcd_debug_power_show, lcd_debug_power_store), |
| __ATTR(power_step, 0644, lcd_debug_power_step_show, lcd_debug_power_step_store), |
| __ATTR(frame_rate, 0644, lcd_debug_frame_rate_show, lcd_debug_frame_rate_store), |
| __ATTR(fr_policy, 0644, lcd_debug_fr_policy_show, lcd_debug_fr_policy_store), |
| __ATTR(ss, 0644, lcd_debug_ss_show, lcd_debug_ss_store), |
| __ATTR(clk, 0644, lcd_debug_clk_show, lcd_debug_clk_store), |
| __ATTR(test, 0644, lcd_debug_test_show, lcd_debug_test_store), |
| __ATTR(mute, 0644, lcd_debug_mute_show, lcd_debug_mute_store), |
| __ATTR(prbs, 0644, lcd_debug_prbs_show, lcd_debug_prbs_store), |
| __ATTR(reg, 0200, NULL, lcd_debug_reg_store), |
| __ATTR(vlock, 0444, lcd_debug_vlock_show, NULL), |
| __ATTR(dump, 0644, lcd_debug_dump_show, lcd_debug_dump_store), |
| __ATTR(print, 0644, lcd_debug_print_show, lcd_debug_print_store), |
| __ATTR(vinfo, 0444, lcd_debug_vinfo_show, NULL) |
| }; |
| |
| static const char *lcd_ttl_debug_usage_str = { |
| "Usage:\n" |
| " echo <clk_pol> <de_valid> <hvsync_valid> <rb_swpa> <bit_swap> > ttl ; set ttl config\n" |
| "data format:\n" |
| " <clk_pol> : 0=negative, 1=positive\n" |
| " <de_valid> : for DE, 0=invalid, 1=valid\n" |
| " <hvsync_valid> : for hvsync, 0=invalid, 1=valid\n" |
| " <rb_swpa> : for R/B port, 0=normal, 1=swap\n" |
| " <bit_swap> : for RGB MSB/LSB, 0=normal, 1=swap\n" |
| "\n" |
| }; |
| |
| static const char *lcd_lvds_debug_usage_str = { |
| "Usage:\n" |
| " echo <repack> <dual_port> <pn_swap> <port_swap> <lane_reverse> > lvds ; set lvds config\n" |
| "data format:\n" |
| " <repack> : 0=JEIDA mode, 1=VESA mode(8bit), 2=VESA mode(10bit)\n" |
| " <dual_port> : 0=single port, 1=dual port\n" |
| " <pn_swap> : 0=normal, 1=swap p/n channels\n" |
| " <port_swap> : 0=normal, 1=swap A/B port\n" |
| " <lane_reverse> : 0=normal, 1=swap A0-A4/B0-B4\n" |
| "\n" |
| " echo <vswing> <preem> > phy ; set vbyone phy config\n" |
| "data format:\n" |
| " <vswing> : vswing level, support 0~7\n" |
| " <preem> : preemphasis level, support 0~7\n" |
| "\n" |
| }; |
| |
| static const char *lcd_vbyone_debug_usage_str = { |
| "Usage:\n" |
| " echo <lane_count> <region_num> <byte_mode> > vbyone ; set vbyone config\n" |
| "data format:\n" |
| " <lane_count> : 4/8/16\n" |
| " <region_num> : 1/2\n" |
| " <byte_mode> : 3/4/5\n" |
| "\n" |
| " echo <vswing> <preem> > phy ; set vbyone phy config\n" |
| "data format:\n" |
| " <vswing> : vswing level, support 0~7\n" |
| " <preem> : preemphasis level, support 0~7\n" |
| " <byte_mode> : 3/4/5\n" |
| "\n" |
| " echo intr <state> <en> > vbyone; enable or disable vbyone interrupt\n" |
| "data format:\n" |
| " <state> : 0=temp no use intr, 1=temp use intr. keep effect until reset lcd driver\n" |
| " <en> : 0=disable intr, 1=enable intr\n" |
| "\n" |
| " echo vintr <en> > vbyone; enable or disable vbyone interrupt\n" |
| "data format:\n" |
| " <en> : 0=disable vsync monitor intr, 1=enable vsync monitor intr\n" |
| "\n" |
| " echo ctrl <ctrl_flag> <power_on_reset_delay> <hpd_data_delay> <cdr_training_hold> > vbyone; set ctrl adjust\n" |
| "data format:\n" |
| " <ctrl_flag> : bit[0]:power_on_reset_en, bit[1]:hpd_data_delay_en, bit[2]:cdr_training_hold_en\n" |
| " others : unit in ms\n" |
| "\n" |
| }; |
| |
| static const char *lcd_mipi_debug_usage_str = { |
| "Usage:\n" |
| " echo <lane_num> <bit_rate_max> <factor> <op_mode_init> <op_mode_disp> <vid_mode_type> <clk_always_hs> <phy_switch> > mipi ; set mpi config\n" |
| "data format:\n" |
| " <lane_num> : 1/2/3/4\n" |
| " <bit_rate_max> : unit in MHz\n" |
| " <factor>: : special adjust, 0 for default\n" |
| " <op_mode_init> : operation mode for init (0=video mode, 1=command mode)\n" |
| " <op_mode_disp> : operation mode for display (0=video mode, 1=command mode)\n" |
| " <vid_mode_type> : video mode type (0=sync_pulse, 1=sync_event, 2=burst)\n" |
| " <clk_always_hs> : 0=disable, 1=enable\n" |
| " <phy_switch> : 0=auto, 1=standard, 2=slow\n" |
| "\n" |
| }; |
| |
| static const char *lcd_mipi_cmd_debug_usage_str = { |
| "Usage:\n" |
| " echo <data_type> <N> <data0> <data1> <data2> ...... <dataN-1> > mpcmd ; send mipi cmd\n" |
| " support data_type:\n" |
| " DT_SHUT_DOWN = 0x22\n" |
| " DT_TURN_ON = 0x32\n" |
| " DT_GEN_SHORT_WR_0 = 0x03\n" |
| " DT_GEN_SHORT_WR_1 = 0x13\n" |
| " DT_GEN_SHORT_WR_2 = 0x23\n" |
| " DT_DCS_SHORT_WR_0 = 0x05\n" |
| " DT_DCS_SHORT_WR_1 = 0x15\n" |
| " DT_GEN_LONG_WR = 0x29\n" |
| " DT_DCS_LONG_WR = 0x39\n" |
| "\n" |
| }; |
| |
| static const char *lcd_edp_debug_usage_str = { |
| "Usage:\n" |
| " echo <lane_cnt_max> <link_rate_max> <training_mode> > edp ; set edp config\n" |
| "data format:\n" |
| " <lane_cnt_max> : 1/2/4\n" |
| " <link_rate_max> : 0=1.62G, 1=2.7G\n" |
| " <training_mode>: : 0=fast link training\n" |
| "\n" |
| }; |
| |
| static const char *lcd_mlvds_debug_usage_str = { |
| "Usage:\n" |
| " echo <channel_num> <channel_sel0> <channel_sel1> <clk_phase> <pn_swap> <bit_swap> > minilvds ; set minilvds config\n" |
| "data format:\n" |
| " <channel_sel> : minilvds 8 channels mapping in tx 10 channels\n" |
| " <clk_phase> : bit[13:12]=clk01_pi_sel, bit[11:8]=pi2, bit[7:4]=pi1, bit[3:0]=pi0\n" |
| " <pn_swap> : 0=normal, 1=swap p/n channels\n" |
| " <bit_swap> : 0=normal, 1=swap bit LSB/MSB\n" |
| "\n" |
| }; |
| |
| static const char *lcd_p2p_debug_usage_str = { |
| "Usage:\n" |
| " echo <p2p_type> <lane_num> <channel_sel0> <channel_sel1> <pn_swap> <bit_swap> > p2p ; set p2p config\n" |
| "data format:\n" |
| " <p2p_type> : 0x0=ceds, 0x1=cmpi, 0x2=isp, 0x3=epi,\n" |
| " 0x10=chpi, 0x11=cspi, 0x12=usit\n" |
| " <channel_sel> : 12 channels mapping\n" |
| " <pn_swap> : 0=normal, 1=swap p/n channels\n" |
| " <bit_swap> : 0=normal, 1=swap bit LSB/MSB\n" |
| "\n" |
| }; |
| |
| static const char *lcd_debug_tcon_usage_str = { |
| "Usage:\n" |
| " echo reg > tcon ; print tcon system regs\n" |
| " echo reg rb <reg> > tcon ; read tcon byte reg\n" |
| " echo reg wb <reg> <val> > tcon ; write tcon byte reg\n" |
| " echo reg db <reg> <cnt> > tcon ; dump tcon byte regs\n" |
| " echo reg r <reg> > tcon ; write tcon reg\n" |
| " echo reg w <reg> <val> > tcon ; write tcon reg\n" |
| " echo reg d <reg> <cnt> > tcon ; dump tcon regs\n" |
| "\n" |
| " echo table > tcon ; print tcon reg table\n" |
| " echo table r <index> > tcon ; read tcon reg table by specified index\n" |
| " echo table w <index> <value> > tcon ; write tcon reg table by specified index\n" |
| " echo table d <index> <len> > tcon ; dump tcon reg table\n" |
| "data format:\n" |
| " <index> : hex number\n" |
| " <value> : hex number\n" |
| " <len> : dec number\n" |
| "\n" |
| " echo table update > tcon ; update tcon reg table into tcon system regs\n" |
| "\n" |
| " echo od <en> > tcon ; tcon over driver control\n" |
| "data format:\n" |
| " <en> : 0=disable, 1=enable\n" |
| "\n" |
| " echo save <str> <path> > tcon ; tcon mem save to file\n" |
| "data format:\n" |
| " <str> : table, reg, vac, demura, acc\n" |
| " <path> : save file path\n" |
| "\n" |
| " echo gamma <bit_width> <gamma_r> <gamma_g> <gamma_b> > tcon ; tcon gamma pattern\n" |
| "data format:\n" |
| " <bit_width> : 12, 10, 8\n" |
| " <gamma_r/g/b> : gamma value in hex\n" |
| }; |
| |
| static ssize_t lcd_ttl_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct ttl_config_s *ttl_conf; |
| |
| ttl_conf = &pdrv->config.control.ttl_cfg; |
| |
| len += sprintf(buf + len, |
| "ttl config: clk_pol=%d, de_valid=%d, hvsync_valid=%d,", |
| ttl_conf->clk_pol, |
| (ttl_conf->sync_valid >> 1) & 0x1, |
| (ttl_conf->sync_valid >> 0) & 0x1); |
| len += sprintf(buf + len, "rb_swap=%d, bit_swap=%d\n\n", |
| (ttl_conf->swap_ctrl >> 1) & 0x1, |
| (ttl_conf->swap_ctrl >> 0) & 0x1); |
| len += sprintf(buf + len, "%s\n", lcd_ttl_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_lvds_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lvds_config_s *lvds_conf; |
| |
| lvds_conf = &pdrv->config.control.lvds_cfg; |
| |
| len += |
| sprintf(buf + len, "lvds config: repack=%d, dual_port=%d,", |
| lvds_conf->lvds_repack, lvds_conf->dual_port); |
| len += |
| sprintf(buf + len, "pn_swap=%d, port_swap=%d, lane_reverse=%d\n\n", |
| lvds_conf->pn_swap, lvds_conf->port_swap, |
| lvds_conf->lane_reverse); |
| len += sprintf(buf + len, "%s\n", lcd_lvds_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_vx1_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct vbyone_config_s *vx1_conf; |
| |
| vx1_conf = &pdrv->config.control.vbyone_cfg; |
| |
| len += sprintf(buf + len, "vbyone config: lane_count=%d,", |
| vx1_conf->lane_count); |
| len += sprintf(buf + len, "region_num=%d, byte_mode=%d\n\n", |
| vx1_conf->region_num, vx1_conf->byte_mode); |
| len += sprintf(buf + len, "%s\n", lcd_vbyone_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_mipi_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct dsi_config_s *dsi_conf; |
| |
| dsi_conf = &pdrv->config.control.mipi_cfg; |
| |
| len += sprintf(buf + len, "mipi_dsi config: lane_num=%d, ", |
| dsi_conf->lane_num); |
| len += sprintf(buf + len, "bit_rate_max=%dMhz, factor_numerator=%d, ", |
| dsi_conf->bit_rate_max, dsi_conf->factor_numerator); |
| len += sprintf(buf + len, |
| "operation_mode_init=%d, operation_mode_display=%d, ", |
| dsi_conf->operation_mode_init, |
| dsi_conf->operation_mode_display); |
| len += sprintf(buf + len, |
| "video_mode_type=%d, clk_always_hs=%d, phy_switch=%d\n\n", |
| dsi_conf->video_mode_type, dsi_conf->clk_always_hs, |
| dsi_conf->phy_switch); |
| len += sprintf(buf + len, "%s\n", lcd_mipi_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_edp_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct edp_config_s *edp_conf; |
| int len = 0; |
| |
| edp_conf = &pdrv->config.control.edp_cfg; |
| |
| len += sprintf(buf + len, "edp config: max_lane_count=%d, ", |
| edp_conf->max_lane_count); |
| len += sprintf(buf + len, "max_link_rate=%dMhz, training_mode=%d, ", |
| edp_conf->max_link_rate, edp_conf->training_mode); |
| len += sprintf(buf + len, "%s\n", lcd_edp_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_edp_edid_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct edp_config_s *edp_conf; |
| int len = 0; |
| |
| edp_conf = &pdrv->config.control.edp_cfg; |
| |
| len = sprintf(buf, "edid_en: %d, edid_state: 0x%x, edid_retry_cnt: %d\n", |
| edp_conf->edid_en, edp_conf->edid_state, edp_conf->edid_retry_cnt); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_mlvds_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct mlvds_config_s *mlvds_conf; |
| |
| mlvds_conf = &pdrv->config.control.mlvds_cfg; |
| |
| len += |
| sprintf(buf + len, "minilvds config: channel_num=%d, ", |
| mlvds_conf->channel_num); |
| len += |
| sprintf(buf + len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", |
| mlvds_conf->channel_sel0, mlvds_conf->channel_sel1); |
| len += |
| sprintf(buf + len, "clk_phase=0x%04x, pn_swap=%d, bit_swap=%d\n\n", |
| mlvds_conf->clk_phase, |
| mlvds_conf->pn_swap, mlvds_conf->bit_swap); |
| len += sprintf(buf + len, "%s\n", lcd_mlvds_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_p2p_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| int len = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct p2p_config_s *p2p_conf; |
| |
| p2p_conf = &pdrv->config.control.p2p_cfg; |
| |
| len += sprintf(buf + len, "p2p config: p2p_type=0x%x, lane_num=%d, ", |
| p2p_conf->p2p_type, p2p_conf->lane_num); |
| len += sprintf(buf + len, "channel_sel0=0x%08x, channel_sel1=0x%08x, ", |
| p2p_conf->channel_sel0, p2p_conf->channel_sel1); |
| len += sprintf(buf + len, "pn_swap=%d, bit_swap=%d\n\n", |
| p2p_conf->pn_swap, p2p_conf->bit_swap); |
| len += sprintf(buf + len, "%s\n", lcd_p2p_debug_usage_str); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_tcon_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%s\n", lcd_debug_tcon_usage_str); |
| } |
| |
| static ssize_t lcd_tcon_status_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| |
| return sprintf(buf, "%d\n", pdrv->tcon_status); |
| } |
| |
| static ssize_t lcd_tcon_adb_status_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| int len = 0; |
| unsigned int i, addr; |
| |
| mutex_lock(&lcd_tcon_adb_mutex); |
| |
| len += sprintf(buf + len, "for_tool:"); |
| if ((pdrv->status & LCD_STATUS_IF_ON) == 0) { |
| len += sprintf(buf + len, "ERROR\n"); |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return len; |
| } |
| switch (adb_reg.rw_mode) { |
| case LCD_ADB_TCON_REG_RW_MODE_NULL: |
| len += sprintf(buf + len, "NULL"); |
| break; |
| case LCD_ADB_TCON_REG_RW_MODE_RN: |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| for (i = 0; i < adb_reg.len; i++) { |
| addr = adb_reg.addr + i; |
| len += sprintf(buf + len, "%04x=%08x ", |
| addr, lcd_tcon_read(pdrv, addr)); |
| } |
| } else { |
| for (i = 0; i < adb_reg.len; i++) { |
| addr = adb_reg.addr + i; |
| len += sprintf(buf + len, "%04x=%02x ", |
| addr, lcd_tcon_read_byte(pdrv, addr)); |
| } |
| } |
| break; |
| case LCD_ADB_TCON_REG_RW_MODE_WM: |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| addr = adb_reg.addr; |
| len += sprintf(buf + len, "%04x=%08x ", |
| addr, lcd_tcon_read(pdrv, addr)); |
| } else { |
| addr = adb_reg.addr; |
| len += sprintf(buf + len, "%04x=%02x ", |
| addr, lcd_tcon_read_byte(pdrv, addr)); |
| } |
| break; |
| case LCD_ADB_TCON_REG_RW_MODE_WN: |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| for (i = 0; i < adb_reg.len; i++) { |
| addr = adb_reg.addr + i; |
| len += sprintf(buf + len, "%04x=%08x ", |
| addr, lcd_tcon_read(pdrv, addr)); |
| } |
| } else { |
| for (i = 0; i < adb_reg.len; i++) { |
| addr = adb_reg.addr + i; |
| len += sprintf(buf + len, "%04x=%02x ", |
| addr, lcd_tcon_read_byte(pdrv, addr)); |
| } |
| } |
| break; |
| case LCD_ADB_TCON_REG_RW_MODE_WS: |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| addr = adb_reg.addr; |
| for (i = 0; i < adb_reg.len; i++) { |
| len += sprintf(buf + len, "%04x=%08x ", |
| addr, lcd_tcon_read(pdrv, addr)); |
| } |
| } else { |
| addr = adb_reg.addr; |
| for (i = 0; i < adb_reg.len; i++) { |
| len += sprintf(buf + len, "%04x=%02x ", |
| addr, lcd_tcon_read_byte(pdrv, addr)); |
| } |
| } |
| break; |
| case LCD_ADB_TCON_REG_RW_MODE_ERR: |
| len += sprintf(buf + len, "ERROR"); |
| break; |
| default: |
| len += sprintf(buf + len, "ERROR"); |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_NULL; |
| adb_reg.addr = 0; |
| adb_reg.len = 0; |
| break; |
| } |
| len += sprintf(buf + len, "\n"); |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return len; |
| } |
| |
| static ssize_t lcd_ttl_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct ttl_config_s *ttl_conf; |
| unsigned int temp[5]; |
| |
| ttl_conf = &pdrv->config.control.ttl_cfg; |
| ret = sscanf(buf, "%d %d %d %d %d", |
| &temp[0], &temp[1], &temp[2], &temp[3], &temp[4]); |
| if (ret == 5) { |
| pr_info("set ttl config:\n" |
| "clk_pol=%d, de_valid=%d, hvsync_valid=%d\n" |
| "rb_swap=%d, bit_swap=%d\n", |
| temp[0], temp[1], temp[2], temp[3], temp[4]); |
| ttl_conf->clk_pol = temp[0]; |
| ttl_conf->sync_valid = ((temp[1] << 1) | temp[2]); |
| ttl_conf->swap_ctrl = ((temp[3] << 1) | temp[4]); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_lvds_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lvds_config_s *lvds_conf; |
| |
| lvds_conf = &pdrv->config.control.lvds_cfg; |
| ret = sscanf(buf, "%d %d %d %d %d", |
| &lvds_conf->lvds_repack, &lvds_conf->dual_port, |
| &lvds_conf->pn_swap, &lvds_conf->port_swap, |
| &lvds_conf->lane_reverse); |
| if (ret == 5 || ret == 4) { |
| pr_info("set lvds config:\n" |
| "repack=%d, dual_port=%d, pn_swap=%d, port_swap=%d, lane_reverse=%d\n", |
| lvds_conf->lvds_repack, lvds_conf->dual_port, |
| lvds_conf->pn_swap, lvds_conf->port_swap, |
| lvds_conf->lane_reverse); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| static int vx1_intr_state = 1; |
| #endif |
| static ssize_t lcd_vx1_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct vbyone_config_s *vx1_conf; |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| int val[5]; |
| #endif |
| unsigned int offset; |
| |
| offset = pdrv->data->offset_venc_if[pdrv->index]; |
| |
| vx1_conf = &pdrv->config.control.vbyone_cfg; |
| if (buf[0] == 'i') { /* intr */ |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| ret = sscanf(buf, "intr %d %d", &val[0], &val[1]); |
| if (ret == 1) { |
| pr_info("set vbyone interrupt enable: %d\n", val[0]); |
| vx1_intr_state = val[0]; |
| lcd_vbyone_interrupt_enable(pdrv, vx1_intr_state); |
| } else if (ret == 2) { |
| pr_info("set vbyone interrupt enable: %d %d\n", |
| val[0], val[1]); |
| vx1_intr_state = val[0]; |
| vx1_conf->intr_en = val[1]; |
| lcd_vbyone_interrupt_enable(pdrv, vx1_intr_state); |
| } else { |
| pr_info("vx1_intr_enable: %d %d\n", |
| vx1_intr_state, vx1_conf->intr_en); |
| return -EINVAL; |
| } |
| #else |
| return -EINVAL; |
| #endif |
| } else if (buf[0] == 'v') { /* vintr */ |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| ret = sscanf(buf, "vintr %d", &val[0]); |
| if (ret == 1) { |
| pr_info("set vbyone vsync interrupt enable: %d\n", |
| val[0]); |
| vx1_conf->vsync_intr_en = val[0]; |
| lcd_vbyone_interrupt_enable(pdrv, vx1_intr_state); |
| } else { |
| pr_info("vx1_vsync_intr_enable: %d\n", |
| vx1_conf->vsync_intr_en); |
| return -EINVAL; |
| } |
| #else |
| return -EINVAL; |
| #endif |
| } else if (buf[0] == 'c') { /* ctrl */ |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| if (buf[1] == 't') { /* ctrl */ |
| ret = sscanf(buf, "ctrl %x %d %d %d", |
| &val[0], &val[1], &val[2], &val[3]); |
| if (ret == 4) { |
| pr_info("set vbyone ctrl_flag: 0x%x\n", val[0]); |
| pr_info("power_on_reset_delay: %dms\n", val[1]); |
| pr_info("hpd_data_delay: %dms\n", val[2]); |
| pr_info("cdr_training_hold: %dms\n", val[3]); |
| vx1_conf->ctrl_flag = val[0]; |
| vx1_conf->power_on_reset_delay = val[1]; |
| vx1_conf->hpd_data_delay = val[2]; |
| vx1_conf->cdr_training_hold = val[3]; |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("vbyone ctrl_flag: 0x%x\n", |
| vx1_conf->ctrl_flag); |
| pr_info("power_on_reset_delay: %dms\n", |
| vx1_conf->power_on_reset_delay); |
| pr_info("hpd_data_delay: %dms\n", |
| vx1_conf->hpd_data_delay); |
| pr_info("cdr_training_hold: %dms\n", |
| vx1_conf->cdr_training_hold); |
| return -EINVAL; |
| } |
| } else if (buf[1] == 'd') { /* cdr */ |
| /* disable vx1 interrupt and vx1 vsync interrupt */ |
| vx1_conf->intr_en = 0; |
| vx1_conf->vsync_intr_en = 0; |
| lcd_vbyone_interrupt_enable(pdrv, 0); |
| |
| /*[5:0]: vx1 fsm status*/ |
| lcd_vcbus_setb(VBO_INSGN_CTRL + offset, 7, 0, 4); |
| msleep(100); |
| LCDPR("vx1 fsm status: 0x%08x", |
| lcd_vcbus_read(VBO_STATUS_L + offset)); |
| |
| } |
| #else |
| return -EINVAL; |
| #endif |
| } else if (buf[0] == 'f') { /* filter */ |
| #ifdef CONFIG_AMLOGIC_LCD_TV |
| ret = sscanf(buf, "filter %x %x", &val[0], &val[1]); |
| if (ret == 2) { |
| pr_info("set vbyone hw_filter_time: 0x%x, hw_filter_cnt: 0x%x\n", |
| val[0], val[1]); |
| vx1_conf->hw_filter_time = val[0]; |
| vx1_conf->hw_filter_cnt = val[1]; |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("vbyone hw_filter_time: 0x%x, hw_filter_cnt: 0x%x\n", |
| vx1_conf->hw_filter_time, |
| vx1_conf->hw_filter_cnt); |
| return -EINVAL; |
| } |
| #else |
| return -EINVAL; |
| #endif |
| } else if (buf[0] == 'r') { /* rst */ |
| /* disable vx1 interrupt and vx1 vsync interrupt */ |
| val[0] = vx1_conf->intr_en; |
| val[1] = vx1_conf->vsync_intr_en; |
| vx1_conf->intr_en = 0; |
| vx1_conf->vsync_intr_en = 0; |
| lcd_vbyone_interrupt_enable(pdrv, 0); |
| |
| lcd_vbyone_sw_reset(pdrv); |
| |
| /* recover vx1 interrupt and vx1 vsync interrupt */ |
| vx1_conf->intr_en = val[0]; |
| vx1_conf->vsync_intr_en = val[1]; |
| lcd_vbyone_interrupt_enable(pdrv, vx1_intr_state); |
| pr_info("vbyone reset\n"); |
| } else { |
| ret = sscanf(buf, "%d %d %d", &vx1_conf->lane_count, |
| &vx1_conf->region_num, &vx1_conf->byte_mode); |
| if (ret == 3) { |
| pr_info("set vbyone config:\n" |
| "lane_count=%d, region_num=%d, byte_mode=%d\n", |
| vx1_conf->lane_count, vx1_conf->region_num, |
| vx1_conf->byte_mode); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_mipi_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct dsi_config_s *dsi_conf; |
| int val[8]; |
| |
| dsi_conf = &pdrv->config.control.mipi_cfg; |
| ret = sscanf(buf, "%d %d %d %d %d %d %d %d", |
| &val[0], &val[1], &val[2], &val[3], |
| &val[4], &val[5], &val[6], &val[7]); |
| if (ret >= 2) { |
| dsi_conf->lane_num = (unsigned char)val[0]; |
| dsi_conf->bit_rate_max = val[1]; |
| dsi_conf->factor_numerator = val[2]; |
| dsi_conf->operation_mode_init = (unsigned char)val[3]; |
| dsi_conf->operation_mode_display = (unsigned char)val[4]; |
| dsi_conf->video_mode_type = (unsigned char)val[5]; |
| dsi_conf->clk_always_hs = (unsigned char)val[6]; |
| dsi_conf->phy_switch = (unsigned char)val[7]; |
| pr_info("set mipi_dsi config:\n" |
| "lane_num=%d, bit_rate_max=%dMhz, factor_numerator=%d\n" |
| "operation_mode_init=%d, operation_mode_display=%d\n" |
| "video_mode_type=%d\n" |
| "clk_always_hs=%d, phy_switch=%d\n\n", |
| dsi_conf->lane_num, |
| dsi_conf->bit_rate_max, |
| dsi_conf->factor_numerator, |
| dsi_conf->operation_mode_init, |
| dsi_conf->operation_mode_display, |
| dsi_conf->video_mode_type, |
| dsi_conf->clk_always_hs, |
| dsi_conf->phy_switch); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_edp_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct edp_config_s *edp_conf; |
| unsigned int val[3]; |
| int ret = 0; |
| |
| edp_conf = &pdrv->config.control.edp_cfg; |
| ret = sscanf(buf, "%d %d %d", &val[0], &val[1], &val[2]); |
| if (ret >= 2) { |
| edp_conf->max_lane_count = (unsigned char)val[0]; |
| edp_conf->max_link_rate = (unsigned char)val[1]; |
| edp_conf->training_mode = (unsigned char)val[2]; |
| pr_info("set edp config:\n" |
| "lane_num=%d, bit_rate_max=%dMhz, factor_numerator=%d\n\n", |
| edp_conf->max_lane_count, |
| edp_conf->max_link_rate, |
| edp_conf->training_mode); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_edp_edid_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct edp_config_s *edp_conf; |
| |
| edp_conf = &pdrv->config.control.edp_cfg; |
| switch (buf[0]) { |
| case 'r': /* read */ |
| dptx_edid_dump(pdrv); |
| break; |
| case 's': /* set */ |
| dptx_edid_timing_probe(pdrv); |
| break; |
| default: |
| LCDERR("invalid command\n"); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_mlvds_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct mlvds_config_s *mlvds_conf; |
| |
| mlvds_conf = &pdrv->config.control.mlvds_cfg; |
| ret = sscanf(buf, "%d %x %x %x %d %d", |
| &mlvds_conf->channel_num, |
| &mlvds_conf->channel_sel0, &mlvds_conf->channel_sel1, |
| &mlvds_conf->clk_phase, |
| &mlvds_conf->pn_swap, &mlvds_conf->bit_swap); |
| if (ret == 6) { |
| pr_info("set minilvds config:\n" |
| "channel_num=%d,\n" |
| "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" |
| "clk_phase=0x%04x,\n" |
| "pn_swap=%d, bit_swap=%d\n", |
| mlvds_conf->channel_num, |
| mlvds_conf->channel_sel0, mlvds_conf->channel_sel1, |
| mlvds_conf->clk_phase, |
| mlvds_conf->pn_swap, mlvds_conf->bit_swap); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| static ssize_t lcd_p2p_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| int ret = 0; |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct p2p_config_s *p2p_conf; |
| |
| p2p_conf = &pdrv->config.control.p2p_cfg; |
| ret = sscanf(buf, "%x %d %x %x %d %d", |
| &p2p_conf->p2p_type, &p2p_conf->lane_num, |
| &p2p_conf->channel_sel0, &p2p_conf->channel_sel1, |
| &p2p_conf->pn_swap, &p2p_conf->bit_swap); |
| if (ret == 6) { |
| pr_info("set p2p config:\n" |
| "p2p_type=0x%x, lane_num=%d,\n" |
| "channel_sel0=0x%08x, channel_sel1=0x%08x,\n" |
| "pn_swap=%d, bit_swap=%d\n", |
| p2p_conf->p2p_type, p2p_conf->lane_num, |
| p2p_conf->channel_sel0, p2p_conf->channel_sel1, |
| p2p_conf->pn_swap, p2p_conf->bit_swap); |
| lcd_debug_config_update(pdrv); |
| } else { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| return count; |
| } |
| |
| static void lcd_phy_config_update(struct aml_lcd_drv_s *pdrv, unsigned int *para, int cnt) |
| { |
| struct lcd_config_s *pconf; |
| struct lvds_config_s *lvds_conf; |
| |
| pconf = &pdrv->config; |
| switch (pconf->basic.lcd_type) { |
| case LCD_LVDS: |
| lvds_conf = &pconf->control.lvds_cfg; |
| if (cnt >= 2) { |
| lvds_conf->phy_vswing = para[0]; |
| lvds_conf->phy_preem = para[1]; |
| |
| if (pdrv->status & LCD_STATUS_IF_ON) |
| lcd_phy_set(pdrv, 1); |
| |
| LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", |
| __func__, para[0], para[1]); |
| } else { |
| LCDERR("%s: invalid parameters cnt: %d\n", |
| __func__, cnt); |
| } |
| break; |
| case LCD_VBYONE: |
| if (cnt >= 2) { |
| pconf->control.vbyone_cfg.phy_vswing = para[0]; |
| pconf->control.vbyone_cfg.phy_preem = para[1]; |
| |
| if (pdrv->status & LCD_STATUS_IF_ON) |
| lcd_phy_set(pdrv, 1); |
| |
| LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", |
| __func__, para[0], para[1]); |
| } else { |
| LCDERR("%s: invalid parameters cnt: %d\n", |
| __func__, cnt); |
| } |
| break; |
| case LCD_MLVDS: |
| if (cnt >= 2) { |
| pconf->control.mlvds_cfg.phy_vswing = para[0]; |
| pconf->control.mlvds_cfg.phy_preem = para[1]; |
| |
| if (pdrv->status & LCD_STATUS_IF_ON) |
| lcd_phy_set(pdrv, 1); |
| |
| LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", |
| __func__, para[0], para[1]); |
| } else { |
| LCDERR("%s: invalid parameters cnt: %d\n", |
| __func__, cnt); |
| } |
| break; |
| case LCD_P2P: |
| if (cnt >= 2) { |
| pconf->control.p2p_cfg.phy_vswing = para[0]; |
| pconf->control.p2p_cfg.phy_preem = para[1]; |
| |
| if (pdrv->status & LCD_STATUS_IF_ON) |
| lcd_phy_set(pdrv, 1); |
| |
| LCDPR("%s: vswing=0x%x, preemphasis=0x%x\n", |
| __func__, para[0], para[1]); |
| } else { |
| LCDERR("%s: invalid parameters cnt: %d\n", |
| __func__, cnt); |
| } |
| break; |
| default: |
| LCDERR("%s: not support lcd_type: %s\n", |
| __func__, |
| lcd_type_type_to_str(pconf->basic.lcd_type)); |
| break; |
| } |
| } |
| |
| static ssize_t lcd_phy_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| struct lcd_config_s *pconf; |
| unsigned int vswing = 0xff, preem = 0xff; |
| ssize_t len = 0; |
| |
| pconf = &pdrv->config; |
| switch (pconf->basic.lcd_type) { |
| case LCD_LVDS: |
| vswing = pconf->control.lvds_cfg.phy_vswing; |
| preem = pconf->control.lvds_cfg.phy_preem; |
| len += sprintf(buf + len, "vswing=0x%x, preemphasis=0x%x\n", |
| vswing, preem); |
| break; |
| case LCD_VBYONE: |
| vswing = pconf->control.vbyone_cfg.phy_vswing; |
| preem = pconf->control.vbyone_cfg.phy_preem; |
| len += sprintf(buf + len, "vswing=0x%x, preemphasis=0x%x\n", |
| vswing, preem); |
| break; |
| case LCD_MLVDS: |
| vswing = pconf->control.mlvds_cfg.phy_vswing; |
| preem = pconf->control.mlvds_cfg.phy_preem; |
| len += sprintf(buf + len, "vswing=0x%x, preemphasis=0x%x\n", |
| vswing, preem); |
| break; |
| case LCD_P2P: |
| vswing = pconf->control.p2p_cfg.phy_vswing; |
| preem = pconf->control.p2p_cfg.phy_preem; |
| len += sprintf(buf + len, "vswing=0x%x, preemphasis=0x%x\n", |
| vswing, preem); |
| break; |
| default: |
| len = sprintf(buf, "%s: invalid lcd_type: %d\n", |
| __func__, pconf->basic.lcd_type); |
| break; |
| } |
| return len; |
| } |
| |
| static ssize_t lcd_phy_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int para[2]; |
| int ret = 0; |
| |
| ret = sscanf(buf, "%x %x", ¶[0], ¶[1]); |
| |
| if (ret == 2) { |
| lcd_phy_config_update(pdrv, para, 2); |
| return count; |
| } |
| |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| |
| static ssize_t lcd_vx1_status_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int offset; |
| |
| offset = pdrv->data->offset_venc_if[pdrv->index]; |
| return sprintf(buf, "vbyone status: lockn = %d hpdn = %d\n", |
| ((lcd_vcbus_read(VBO_STATUS_L + offset) >> 7) & 0x1), |
| ((lcd_vcbus_read(VBO_STATUS_L + offset) >> 6) & 0x1)); |
| } |
| |
| static int lcd_tcon_buf_save(char *path, unsigned char *save_buf, unsigned int size) |
| { |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| void *buf = NULL; |
| mm_segment_t old_fs = get_fs(); |
| |
| if (!save_buf) { |
| LCDERR("%s: save_buf is null\n", __func__); |
| return -1; |
| } |
| if (size == 0) { |
| LCDERR("%s: size is zero\n", __func__); |
| return -1; |
| } |
| |
| set_fs(KERNEL_DS); |
| filp = filp_open(path, O_RDWR | O_CREAT, 0666); |
| |
| if (IS_ERR(filp)) { |
| LCDERR("%s: create %s error\n", __func__, path); |
| set_fs(old_fs); |
| return -1; |
| } |
| |
| pos = 0; |
| buf = (void *)save_buf; |
| vfs_write(filp, buf, size, &pos); |
| |
| vfs_fsync(filp, 0); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| |
| return 0; |
| } |
| |
| static void lcd_tcon_reg_table_save(char *path, unsigned char *reg_table, unsigned int size) |
| { |
| int ret; |
| |
| ret = lcd_tcon_buf_save(path, reg_table, size); |
| |
| LCDPR("save tcon reg table to %s finished\n", path); |
| } |
| |
| static void lcd_tcon_reg_save(struct aml_lcd_drv_s *pdrv, char *path, unsigned int size) |
| { |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| unsigned char *temp; |
| void *buf = NULL; |
| mm_segment_t old_fs = get_fs(); |
| int ret; |
| |
| set_fs(KERNEL_DS); |
| filp = filp_open(path, O_RDWR | O_CREAT, 0666); |
| |
| if (IS_ERR(filp)) { |
| LCDERR("%s: create %s error\n", __func__, path); |
| set_fs(old_fs); |
| return; |
| } |
| |
| temp = kcalloc(size, sizeof(unsigned char), GFP_KERNEL); |
| if (!temp) { |
| LCDERR("%s: Not enough memory\n", __func__); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| return; |
| } |
| ret = lcd_tcon_core_reg_get(pdrv, temp, size); |
| if (ret) { |
| LCDPR("save tcon reg failed\n"); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| kfree(temp); |
| return; |
| } |
| |
| pos = 0; |
| buf = (void *)temp; |
| vfs_write(filp, buf, size, &pos); |
| |
| vfs_fsync(filp, 0); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| kfree(temp); |
| |
| LCDPR("save tcon reg to %s success\n", path); |
| } |
| |
| static void lcd_tcon_axi_rmem_save(unsigned int index, char *path) |
| { |
| unsigned int mem_size; |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| mm_segment_t old_fs = get_fs(); |
| struct tcon_rmem_s *tcon_rmem = get_lcd_tcon_rmem(); |
| struct lcd_tcon_config_s *tcon_conf = get_lcd_tcon_config(); |
| unsigned int span = 0, remain = 0, count = 0; |
| unsigned long paddr, phys; |
| void *vaddr = NULL; |
| unsigned int highmem_flag = 0; |
| int i; |
| |
| if (!tcon_rmem || !tcon_rmem->axi_rmem) { |
| pr_info("axi_rmem is NULL\n"); |
| return; |
| } |
| if (!tcon_conf) |
| return; |
| if (index > tcon_conf->axi_bank) { |
| pr_info("axi_rmem index %d invalid\n", index); |
| return; |
| } |
| |
| mem_size = tcon_rmem->axi_rmem[index].mem_size; |
| pos = 0; |
| |
| set_fs(KERNEL_DS); |
| filp = filp_open(path, O_RDWR | O_CREAT, 0666); |
| if (IS_ERR(filp)) { |
| pr_info("%s: create %s error\n", __func__, path); |
| set_fs(old_fs); |
| return; |
| } |
| |
| paddr = tcon_rmem->axi_rmem[index].mem_paddr; |
| highmem_flag = PageHighMem(phys_to_page(paddr)); |
| if (highmem_flag == 0) { |
| vaddr = phys_to_virt(paddr); |
| if (!vaddr) |
| goto lcd_tcon_axi_rmem_save_end; |
| vfs_write(filp, vaddr, mem_size, &pos); |
| } else { |
| span = SZ_1M; |
| count = mem_size / PAGE_ALIGN(span); |
| remain = mem_size % PAGE_ALIGN(span); |
| |
| for (i = 0; i < count; i++) { |
| phys = paddr + i * span; |
| vaddr = lcd_vmap(phys, span); |
| if (!vaddr) |
| goto lcd_tcon_axi_rmem_save_end; |
| vfs_write(filp, vaddr, span, &pos); |
| lcd_unmap_phyaddr(vaddr); |
| } |
| if (remain) { |
| phys = paddr + count * span; |
| vaddr = lcd_vmap(phys, remain); |
| if (!vaddr) |
| goto lcd_tcon_axi_rmem_save_end; |
| vfs_write(filp, vaddr, remain, &pos); |
| lcd_unmap_phyaddr(vaddr); |
| } |
| } |
| |
| vfs_fsync(filp, 0); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| pr_info("save tcon vac to %s finished\n", path); |
| return; |
| |
| lcd_tcon_axi_rmem_save_end: |
| vfs_fsync(filp, 0); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| pr_info("tcon axi_rmem[%d] mapping failed: 0x%lx\n", index, paddr); |
| } |
| |
| static void lcd_tcon_rmem_save(char *path, unsigned int flag) |
| { |
| struct lcd_tcon_config_s *tcon_conf = get_lcd_tcon_config(); |
| struct tcon_rmem_s *rmem = get_lcd_tcon_rmem(); |
| struct tcon_mem_map_table_s *table = get_lcd_tcon_mm_table(); |
| struct lcd_tcon_data_block_header_s *block_header; |
| char *str = NULL; |
| int ret, i; |
| |
| if (!tcon_conf) { |
| LCDPR("%s: tcon_conf is null\n", __func__); |
| return; |
| } |
| if (!rmem) { |
| LCDPR("%s: tcon_rmem is null\n", __func__); |
| return; |
| } |
| if (!table) { |
| LCDPR("%s: tcon_mm_table is null\n", __func__); |
| return; |
| } |
| |
| str = kcalloc(512, sizeof(char), GFP_KERNEL); |
| if (!str) |
| return; |
| |
| switch (flag) { |
| case 0: /* bin path */ |
| if (rmem->bin_path_rmem.mem_vaddr) { |
| sprintf(str, "%s.bin", path); |
| ret = lcd_tcon_buf_save(str, rmem->bin_path_rmem.mem_vaddr, |
| rmem->bin_path_rmem.mem_size); |
| if (ret == 0) |
| LCDPR("save tcon bin_path to %s finished\n", str); |
| } else { |
| pr_info("bin_path invalid\n"); |
| } |
| break; |
| case 1: /* vac */ |
| if (table->valid_flag & LCD_TCON_DATA_VALID_VAC) { |
| sprintf(str, "%s.bin", path); |
| ret = lcd_tcon_buf_save(str, rmem->vac_rmem.mem_vaddr, |
| rmem->vac_rmem.mem_size); |
| if (ret == 0) |
| LCDPR("save tcon vac to %s finished\n", str); |
| } else { |
| pr_info("vac invalid\n"); |
| } |
| break; |
| case 2: /* demura */ |
| if (table->valid_flag & LCD_TCON_DATA_VALID_DEMURA) { |
| sprintf(str, "%s_set.bin", path); |
| ret = lcd_tcon_buf_save(str, rmem->demura_set_rmem.mem_vaddr, |
| rmem->demura_set_rmem.mem_size); |
| if (ret == 0) |
| LCDPR("save tcon demura_set to %s finished\n", str); |
| sprintf(str, "%s_lut.bin", path); |
| ret = lcd_tcon_buf_save(str, rmem->demura_lut_rmem.mem_vaddr, |
| rmem->demura_lut_rmem.mem_size); |
| if (ret == 0) |
| LCDPR("save tcon demura_lut to %s finished\n", str); |
| } else { |
| pr_info("demura invalid\n"); |
| } |
| break; |
| case 3: /* acc */ |
| if (table->valid_flag & LCD_TCON_DATA_VALID_ACC) { |
| sprintf(str, "%s.bin", path); |
| ret = lcd_tcon_buf_save(str, rmem->acc_lut_rmem.mem_vaddr, |
| rmem->acc_lut_rmem.mem_size); |
| if (ret == 0) |
| LCDPR("save tcon acc_lut to %s finished\n", str); |
| } else { |
| pr_info("acc invalid\n"); |
| } |
| break; |
| case 4: /* tcon_data*/ |
| if (table->version) { |
| pr_info("data_mem_block_cnt: %d\n", table->block_cnt); |
| |
| for (i = 0; i < table->block_cnt; i++) { |
| sprintf(str, "%s_%d.bin", path, i); |
| if (!table->data_mem_vaddr[i]) { |
| LCDERR("%s: data_mem_vaddr[%d] is null", |
| __func__, i); |
| continue; |
| } |
| |
| block_header = (struct lcd_tcon_data_block_header_s *) |
| table->data_mem_vaddr[i]; |
| ret = lcd_tcon_buf_save(str, table->data_mem_vaddr[i], |
| block_header->block_size); |
| if (ret == 0) |
| LCDPR("save tcon_data to %s finish", str); |
| } |
| } else { |
| pr_info("tcon_data invalid\n"); |
| } |
| break; |
| default: |
| break; |
| } |
| |
| kfree(str); |
| } |
| |
| static void lcd_tcon_reg_table_load(char *path, unsigned char *reg_table, unsigned int table_size) |
| { |
| unsigned int size = 0; |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| mm_segment_t old_fs = get_fs(); |
| |
| set_fs(KERNEL_DS); |
| filp = filp_open(path, O_RDONLY, 0); |
| if (IS_ERR_OR_NULL(filp)) { |
| pr_info("read %s error or filp is NULL.\n", path); |
| return; |
| } |
| |
| size = vfs_read(filp, reg_table, table_size, &pos); |
| if (size < table_size) { |
| pr_info("%s read size %u < %u error.\n", |
| __func__, size, table_size); |
| return; |
| } |
| vfs_fsync(filp, 0); |
| |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| |
| pr_info("load bin file path: %s finish\n", path); |
| } |
| |
| static void lcd_tcon_reg_setting_load(struct aml_lcd_drv_s *pdrv, char *path) |
| { |
| unsigned int size = 0, table_size = 0, len = 0; |
| char *reg_table; |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| mm_segment_t old_fs = get_fs(); |
| /*struct kstat stat;*/ |
| unsigned int i, n; |
| char *ps, *token; |
| char str[4] = {',', ' ', '\n', '\0'}; |
| unsigned int temp[2]; |
| |
| set_fs(KERNEL_DS); |
| |
| /*vfs_stat(path, &stat); |
| *table_size = stat.size; |
| */ |
| |
| filp = filp_open(path, O_RDONLY, 0); |
| if (IS_ERR_OR_NULL(filp)) { |
| pr_info("read %s error or filp is NULL.\n", path); |
| return; |
| } |
| table_size = filp->f_inode->i_size; |
| reg_table = kzalloc((table_size + 2), GFP_KERNEL); |
| if (!reg_table) { |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| return; |
| } |
| |
| size = vfs_read(filp, reg_table, table_size, &pos); |
| if (size < table_size) { |
| pr_info("%s read size %u < %u error.\n", |
| __func__, size, table_size); |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| kfree(reg_table); |
| return; |
| } |
| vfs_fsync(filp, 0); |
| |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| |
| ps = reg_table; |
| len = 0; |
| i = 0; |
| n = 0; |
| while (1) { |
| if (len >= table_size) |
| break; |
| if (!ps) |
| break; |
| token = strsep(&ps, str); |
| if (!token) |
| break; |
| if (*token == '\0') { |
| len++; |
| continue; |
| } |
| if (kstrtouint(token, 16, &temp[i % 2]) < 0) { |
| kfree(reg_table); |
| return; |
| } |
| if ((i % 2) == 1) { |
| if (lcd_debug_print_flag & LCD_DBG_PR_TEST) |
| pr_info("write tcon reg 0x%04x = 0x%08x\n", temp[0], temp[1]); |
| lcd_tcon_reg_write(pdrv, temp[0], temp[1]); |
| n++; |
| } |
| len += (strlen(token) + 1); |
| i++; |
| } |
| |
| pr_info("load setting file path: %s finish, total line %d\n", path, n); |
| kfree(reg_table); |
| } |
| |
| static void lcd_tcon_axi_rmem_load(unsigned int index, char *path) |
| { |
| unsigned int size = 0, mem_size; |
| struct file *filp = NULL; |
| loff_t pos = 0; |
| mm_segment_t old_fs = get_fs(); |
| unsigned char *buf; |
| struct tcon_rmem_s *tcon_rmem = get_lcd_tcon_rmem(); |
| struct lcd_tcon_config_s *tcon_conf = get_lcd_tcon_config(); |
| |
| if (!tcon_rmem || !tcon_rmem->axi_rmem) { |
| pr_info("axi_rmem is NULL\n"); |
| return; |
| } |
| if (!tcon_conf) |
| return; |
| if (index > tcon_conf->axi_bank) { |
| pr_info("axi_rmem index %d invalid\n", index); |
| return; |
| } |
| |
| mem_size = tcon_rmem->axi_rmem[index].mem_size; |
| buf = kcalloc(mem_size, sizeof(char), GFP_KERNEL); |
| if (!buf) |
| return; |
| |
| set_fs(KERNEL_DS); |
| filp = filp_open(path, O_RDONLY, 0); |
| if (IS_ERR_OR_NULL(filp)) { |
| pr_info("read %s error or filp is NULL.\n", path); |
| kfree(buf); |
| return; |
| } |
| |
| size = vfs_read(filp, buf, mem_size, &pos); |
| pr_info("%s read size %u\n", __func__, size); |
| vfs_fsync(filp, 0); |
| |
| filp_close(filp, NULL); |
| set_fs(old_fs); |
| |
| lcd_tcon_axi_rmem_lut_load(1, buf, size); |
| kfree(buf); |
| |
| pr_info("load bin file path: %s finish\n", path); |
| } |
| |
| static int lcd_tcon_reg_table_check(unsigned char *table, unsigned int size) |
| { |
| if (size == 0) |
| return -1; |
| if (!table) |
| return -1; |
| return 0; |
| } |
| |
| static ssize_t lcd_tcon_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| char *buf_orig; |
| char **parm = NULL; |
| unsigned int temp = 0, val, back_val, i, n, size = 0; |
| unsigned int gamma_r, gamma_g, gamma_b; |
| struct tcon_mem_map_table_s *mm_table = get_lcd_tcon_mm_table(); |
| unsigned char data; |
| unsigned char *table = NULL; |
| int ret = -1; |
| |
| if (mm_table) { |
| size = mm_table->core_reg_table_size; |
| table = mm_table->core_reg_table; |
| } |
| |
| if (!buf) |
| return count; |
| buf_orig = kstrdup(buf, GFP_KERNEL); |
| if (!buf_orig) |
| return count; |
| |
| parm = kcalloc(520, sizeof(char *), GFP_KERNEL); |
| if (!parm) { |
| kfree(buf_orig); |
| return count; |
| } |
| |
| lcd_debug_parse_param(buf_orig, parm); |
| |
| if (strcmp(parm[0], "reg") == 0) { |
| if (!parm[1]) { |
| lcd_tcon_reg_readback_print(pdrv); |
| goto lcd_tcon_debug_store_end; |
| } |
| if (strcmp(parm[1], "dump") == 0) { |
| lcd_tcon_reg_readback_print(pdrv); |
| goto lcd_tcon_debug_store_end; |
| } else if (strcmp(parm[1], "rb") == 0) { |
| if (!parm[2]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| pr_info("read tcon byte [0x%04x] = 0x%02x\n", |
| temp, lcd_tcon_read_byte(pdrv, temp)); |
| } else if (strcmp(parm[1], "wb") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &val); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| data = (unsigned char)val; |
| lcd_tcon_write_byte(pdrv, temp, data); |
| pr_info("write tcon byte [0x%04x] = 0x%02x\n", |
| temp, data); |
| } else if (strcmp(parm[1], "wlb") == 0) { /*long write byte*/ |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &size); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| |
| if (!parm[3 + size]) { |
| pr_info("size and data is not match\n"); |
| goto lcd_tcon_debug_store_err; |
| } |
| |
| for (i = 0; i < size; i++) { |
| ret = kstrtouint(parm[4 + i], 16, &val); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| data = (unsigned char)val; |
| lcd_tcon_write_byte(pdrv, (temp + i), data); |
| pr_info("write tcon byte [0x%04x] = 0x%02x\n", |
| (temp + i), data); |
| } |
| } else if (strcmp(parm[1], "db") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 10, &size); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| pr_info("dump tcon byte:\n"); |
| for (i = 0; i < size; i++) { |
| pr_info(" [0x%04x] = 0x%02x\n", |
| (temp + i), |
| lcd_tcon_read_byte(pdrv, temp + i)); |
| } |
| } else if (strcmp(parm[1], "r") == 0) { |
| if (!parm[2]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| pr_info("read tcon [0x%04x] = 0x%08x\n", |
| temp, lcd_tcon_read(pdrv, temp)); |
| } else if (strcmp(parm[1], "w") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &val); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| lcd_tcon_write(pdrv, temp, val); |
| pr_info("write tcon [0x%04x] = 0x%08x\n", |
| temp, val); |
| } else if (strcmp(parm[1], "wl") == 0) { /*long write*/ |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &size); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| |
| if (!parm[3 + size]) { |
| pr_info("size and data is not match\n"); |
| goto lcd_tcon_debug_store_err; |
| } |
| |
| for (i = 0; i < size; i++) { |
| ret = kstrtouint(parm[4 + i], 16, &val); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| lcd_tcon_write(pdrv, temp + i, val); |
| pr_info("write tcon [0x%04x] = 0x%08x\n", |
| (temp + i), val); |
| } |
| } else if (strcmp(parm[1], "d") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 10, &size); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| pr_info("dump tcon:\n"); |
| for (i = 0; i < size; i++) { |
| pr_info(" [0x%04x] = 0x%08x\n", |
| (temp + i), |
| lcd_tcon_read(pdrv, temp + i)); |
| } |
| } |
| } else if (strcmp(parm[0], "gamma") == 0) { /* save buf to bin */ |
| if (!parm[4]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[1], 10, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &gamma_r); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &gamma_g); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[4], 16, &gamma_b); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| lcd_tcon_gamma_set_pattern(pdrv, temp, gamma_r, gamma_g, gamma_b); |
| } else if (strcmp(parm[0], "table") == 0) { |
| if (lcd_tcon_reg_table_check(table, size)) |
| goto lcd_tcon_debug_store_end; |
| if (!parm[1]) { |
| lcd_tcon_reg_table_print(); |
| goto lcd_tcon_debug_store_end; |
| } |
| if (strcmp(parm[1], "dump") == 0) { |
| lcd_tcon_reg_table_print(); |
| goto lcd_tcon_debug_store_end; |
| } else if (strcmp(parm[1], "r") == 0) { |
| if (!parm[2]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| val = lcd_tcon_table_read(temp); |
| pr_info("read table 0x%x = 0x%x\n", temp, val); |
| } else if (strcmp(parm[1], "w") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &val); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| back_val = lcd_tcon_table_write(temp, val); |
| pr_info("write table 0x%x = 0x%x, readback 0x%x\n", |
| temp, val, back_val); |
| } else if (strcmp(parm[1], "d") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &n); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| pr_info("dump tcon table:\n"); |
| for (i = temp; i < (temp + n); i++) { |
| if (i > size) |
| break; |
| data = table[i]; |
| pr_info(" [0x%04x]=0x%02x\n", i, data); |
| } |
| } else if (strcmp(parm[1], "update") == 0) { |
| lcd_tcon_core_update(pdrv); |
| } else if (strcmp(parm[1], "load") == 0) { |
| if (!parm[2]) { |
| pr_info("invalid load path\n"); |
| goto lcd_tcon_debug_store_err; |
| } |
| lcd_tcon_reg_table_load(parm[2], table, size); |
| } else { |
| goto lcd_tcon_debug_store_err; |
| } |
| } else if (strcmp(parm[0], "od") == 0) { /* over drive */ |
| if (!parm[1]) { |
| temp = lcd_tcon_od_get(pdrv); |
| if (temp) |
| LCDPR("tcon od is enabled: %d\n", temp); |
| else |
| LCDPR("tcon od is disabled: %d\n", temp); |
| } else { |
| ret = kstrtouint(parm[1], 10, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| if (temp) |
| lcd_tcon_od_set(pdrv, 1); |
| else |
| lcd_tcon_od_set(pdrv, 0); |
| } |
| } else if (strcmp(parm[0], "save") == 0) { /* save buf to bin */ |
| if (!parm[2]) |
| goto lcd_tcon_debug_store_err; |
| |
| if (strcmp(parm[1], "table") == 0) { |
| if (lcd_tcon_reg_table_check(table, size)) |
| goto lcd_tcon_debug_store_end; |
| lcd_tcon_reg_table_save(parm[2], table, size); |
| } else if (strcmp(parm[1], "reg") == 0) { |
| lcd_tcon_reg_save(pdrv, parm[2], size); |
| } else if (strcmp(parm[1], "axi") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 10, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| /* parm[2]: axi index */ |
| /* parm[3]: save path */ |
| lcd_tcon_axi_rmem_save(temp, parm[3]); |
| } else if (strcmp(parm[1], "path") == 0) { |
| lcd_tcon_rmem_save(parm[2], 0); |
| } else if (strcmp(parm[1], "vac") == 0) { |
| lcd_tcon_rmem_save(parm[2], 1); |
| } else if (strcmp(parm[1], "demura") == 0) { |
| lcd_tcon_rmem_save(parm[2], 2); |
| } else if (strcmp(parm[1], "acc") == 0) { |
| lcd_tcon_rmem_save(parm[2], 3); |
| } else { |
| goto lcd_tcon_debug_store_err; |
| } |
| } else if (strcmp(parm[0], "tee") == 0) { |
| if (!parm[1]) |
| goto lcd_tcon_debug_store_err; |
| #ifdef CONFIG_AMLOGIC_TEE |
| if (strcmp(parm[1], "status") == 0) { |
| pr_info("tcon tee secure memory protect status %d\n", |
| lcd_tcon_mem_tee_get_status()); |
| } else if (strcmp(parm[1], "off") == 0) { |
| ret = lcd_tcon_mem_tee_unprotect(); |
| pr_info("%s: tcon tee unprotect %d\n", __func__, ret); |
| } else { |
| goto lcd_tcon_debug_store_err; |
| } |
| #endif |
| } else if (strcmp(parm[0], "load") == 0) { |
| if (!parm[2]) |
| goto lcd_tcon_debug_store_err; |
| |
| if (strcmp(parm[1], "axi") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_debug_store_err; |
| ret = kstrtouint(parm[2], 10, &temp); |
| if (ret) |
| goto lcd_tcon_debug_store_err; |
| lcd_tcon_axi_rmem_load(temp, parm[3]); |
| } else if (strcmp(parm[1], "table") == 0) { |
| lcd_tcon_reg_table_load(parm[2], table, size); |
| } else if (strcmp(parm[1], "setting") == 0) { |
| lcd_tcon_reg_setting_load(pdrv, parm[2]); |
| } else { |
| goto lcd_tcon_debug_store_err; |
| } |
| } else { |
| goto lcd_tcon_debug_store_err; |
| } |
| |
| lcd_tcon_debug_store_end: |
| kfree(parm); |
| kfree(buf_orig); |
| return count; |
| |
| lcd_tcon_debug_store_err: |
| pr_info("invalid parameters\n"); |
| kfree(parm); |
| kfree(buf_orig); |
| return count; |
| } |
| |
| static ssize_t lcd_tcon_adb_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| char *buf_orig; |
| char **parm = NULL; |
| unsigned int temp32 = 0, temp_reg = 0; |
| unsigned int temp_len = 0, temp_mask = 0, temp_val = 0; |
| unsigned char temp8 = 0; |
| int ret = -1, i; |
| |
| if ((pdrv->status & LCD_STATUS_IF_ON) == 0) |
| return count; |
| |
| if (!buf) |
| return count; |
| |
| mutex_lock(&lcd_tcon_adb_mutex); |
| |
| buf_orig = kstrdup(buf, GFP_KERNEL); |
| if (!buf_orig) { |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return count; |
| } |
| |
| parm = kcalloc(1500, sizeof(char *), GFP_KERNEL); |
| if (!parm) { |
| kfree(buf_orig); |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return count; |
| } |
| |
| lcd_debug_parse_param(buf_orig, parm); |
| |
| if (strcmp(parm[0], "wn") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (strcmp(parm[1], "8") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_8_bit; |
| else if (strcmp(parm[1], "32") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_32_bit; |
| else |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp_reg); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[3], 10, &temp_len); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (temp_len <= 0) |
| goto lcd_tcon_adb_debug_store_err; |
| if (!parm[4 + temp_len - 1]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| /*(4k - 9)/(8+1) ~=454*/ |
| if (temp_len > 454) |
| goto lcd_tcon_adb_debug_store_err; |
| } else { |
| /*(4k - 9)/(2+1) ~=1362*/ |
| if (temp_len > 1362) |
| goto lcd_tcon_adb_debug_store_err; |
| } |
| adb_reg.len = temp_len; /* for cat use */ |
| adb_reg.addr = temp_reg; |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_WN; |
| for (i = 0; i < temp_len; i++) { |
| ret = kstrtouint(parm[i + 4], 16, &temp_val); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) |
| lcd_tcon_write(pdrv, temp_reg, temp_val); |
| else |
| lcd_tcon_write_byte(pdrv, temp_reg, temp_val); |
| temp_reg++; |
| } |
| } else if (strcmp(parm[0], "wm") == 0) { |
| if (!parm[4]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (strcmp(parm[1], "8") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_8_bit; |
| else if (strcmp(parm[1], "32") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_32_bit; |
| else |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp_reg); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[3], 16, &temp_mask); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[4], 16, &temp_val); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| adb_reg.len = 1; /* for cat use */ |
| adb_reg.addr = temp_reg; |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_WM; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| temp32 = lcd_tcon_read(pdrv, temp_reg); |
| temp32 &= ~temp_mask; |
| temp32 |= temp_val & temp_mask; |
| lcd_tcon_write(pdrv, temp_reg, temp32); |
| } else { |
| temp8 = lcd_tcon_read_byte(pdrv, temp_reg); |
| temp8 &= ~temp_mask; |
| temp8 |= temp_val & temp_mask; |
| lcd_tcon_write_byte(pdrv, temp_reg, temp8); |
| } |
| } else if (strcmp(parm[0], "ws") == 0) { |
| if (!parm[3]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (strcmp(parm[1], "8") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_8_bit; |
| else if (strcmp(parm[1], "32") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_32_bit; |
| else |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp_reg); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[3], 10, &temp_len); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (temp_len <= 0) |
| goto lcd_tcon_adb_debug_store_err; |
| if (!parm[4 + temp_len - 1]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| /*(4k - 9)/(8+1) ~=454*/ |
| if (temp_len > 454) |
| goto lcd_tcon_adb_debug_store_err; |
| } else { |
| /*(4k - 9)/(2+1) ~=1362*/ |
| if (temp_len > 1362) |
| goto lcd_tcon_adb_debug_store_err; |
| } |
| adb_reg.len = temp_len; /* for cat use */ |
| adb_reg.addr = temp_reg; |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_WS; |
| for (i = 0; i < temp_len; i++) { |
| ret = kstrtouint(parm[i + 4], 16, &temp_val); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) |
| lcd_tcon_write(pdrv, temp_reg, temp_val); |
| else |
| lcd_tcon_write_byte(pdrv, temp_reg, temp_val); |
| } |
| } else if (strcmp(parm[0], "rn") == 0) { |
| if (!parm[2]) |
| goto lcd_tcon_adb_debug_store_err; |
| if (strcmp(parm[1], "8") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_8_bit; |
| else if (strcmp(parm[1], "32") == 0) |
| adb_reg.bit_width = ADB_TCON_REG_32_bit; |
| else |
| goto lcd_tcon_adb_debug_store_err; |
| ret = kstrtouint(parm[2], 16, &temp_reg); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (parm[3]) { |
| ret = kstrtouint(parm[3], 10, &temp_len); |
| if (ret) |
| goto lcd_tcon_adb_debug_store_err; |
| if (adb_reg.bit_width == ADB_TCON_REG_32_bit) { |
| /*(4k - 9)/(8+1) ~=454*/ |
| if (temp_len > 454) |
| goto lcd_tcon_adb_debug_store_err; |
| } else { |
| /*(4k - 9)/(2+1) ~=1362*/ |
| if (temp_len > 1362) |
| goto lcd_tcon_adb_debug_store_err; |
| } |
| adb_reg.len = temp_len; /* for cat use */ |
| adb_reg.addr = temp_reg; |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_RN; |
| } else { |
| adb_reg.len = 1; /* for cat use */ |
| adb_reg.addr = temp_reg; |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_RN; |
| } |
| } else { |
| goto lcd_tcon_adb_debug_store_err; |
| } |
| |
| kfree(parm); |
| kfree(buf_orig); |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return count; |
| |
| lcd_tcon_adb_debug_store_err: |
| adb_reg.rw_mode = LCD_ADB_TCON_REG_RW_MODE_ERR; |
| |
| kfree(parm); |
| kfree(buf_orig); |
| mutex_unlock(&lcd_tcon_adb_mutex); |
| return count; |
| } |
| |
| static ssize_t lcd_mipi_cmd_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| return sprintf(buf, "%s\n", lcd_mipi_cmd_debug_usage_str); |
| } |
| |
| static ssize_t lcd_mipi_cmd_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned char *cmd_table = NULL; |
| unsigned int para[24]; |
| int ret = 0; |
| int i; |
| |
| ret = sscanf(buf, |
| "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", |
| ¶[0], ¶[1], ¶[2], ¶[3], ¶[4], ¶[5], |
| ¶[6], ¶[7], ¶[8], ¶[9], ¶[10], ¶[11], |
| ¶[12], ¶[13], ¶[14], ¶[15], ¶[16], |
| ¶[17], ¶[18], ¶[19], ¶[20], ¶[21], |
| ¶[22], ¶[23]); |
| |
| if (ret < 2) { |
| pr_info("invalid mipi cmd\n"); |
| return count; |
| } |
| if (ret < (2 + para[1])) { |
| pr_info("invalid data num\n"); |
| return count; |
| } |
| |
| cmd_table = kcalloc((2 + para[1] + 2), sizeof(unsigned char), GFP_KERNEL); |
| if (!cmd_table) { |
| pr_err("error for mipi cmd\n"); |
| return -ENOMEM; |
| } |
| for (i = 0; i < (2 + para[1]); i++) |
| cmd_table[i] = (unsigned char)para[i]; |
| cmd_table[2 + para[1]] = 0xff; |
| cmd_table[2 + para[1] + 1] = 0xff; |
| |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| dsi_write_cmd(pdrv, cmd_table); |
| #endif |
| |
| kfree(cmd_table); |
| |
| return count; |
| } |
| |
| #define MIPI_RD_RET_CODE_MAX 5 |
| static char *mipi_read_ret_code_table[] = { |
| "success", |
| "read null", |
| "read error", |
| "read back cnt is wrong", |
| "timeout", |
| "unknown error", |
| }; |
| |
| static struct dsi_read_s dread = { |
| .flag = 0, |
| .reg = 0xff, |
| .cnt = 0, |
| .value = NULL, |
| .ret_code = 4, |
| |
| .line_start = 0x1fff, |
| .line_end = 0x1fff, |
| }; |
| |
| static ssize_t lcd_mipi_read_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int i = 0, len; |
| |
| if ((pdrv->status & LCD_STATUS_IF_ON) == 0) |
| return sprintf(buf, "error: panel is disabled\n"); |
| |
| if (dread.reg == 0xff) |
| return sprintf(buf, "error: reg address is invalid\n"); |
| if (dread.cnt == 0) |
| return sprintf(buf, "error: read count is invalid\n"); |
| |
| if (dread.cnt > DSI_READ_CNT_MAX) |
| return sprintf(buf, "error: mipi read cnt is out of support\n"); |
| if (!dread.value) |
| return sprintf(buf, "error: mipi read return value is null\n"); |
| |
| dread.line_start = 0x1fff; |
| dread.line_end = 0x1fff; |
| dread.ret_code = 4; |
| |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| if (pdrv->config.control.mipi_cfg.current_mode == 0) { |
| dread.flag = 1; |
| while (i++ < 5000) { |
| if (dread.flag == 0) |
| break; |
| lcd_delay_us(20); |
| } |
| } else { |
| lcd_mipi_test_read(pdrv, &dread); |
| } |
| #endif |
| |
| if (dread.ret_code) { |
| dread.ret_code = (dread.ret_code >= MIPI_RD_RET_CODE_MAX) ? |
| MIPI_RD_RET_CODE_MAX : dread.ret_code; |
| return sprintf(buf, "read error: %s(%d)\n", |
| mipi_read_ret_code_table[dread.ret_code], |
| dread.ret_code); |
| } |
| |
| len = sprintf(buf, "read reg 0x%02x: ", dread.reg); |
| for (i = 0; i < dread.cnt; i++) { |
| if (i == 0) |
| len += sprintf(buf + len, "0x%02x", dread.value[i]); |
| else |
| len += sprintf(buf + len, ",0x%02x", dread.value[i]); |
| } |
| |
| len += sprintf(buf + len, "\nread line start=%d, end=%d\n", |
| dread.line_start, dread.line_end); |
| |
| return len; |
| } |
| |
| static ssize_t lcd_mipi_read_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| unsigned int para[2]; |
| int ret = 0; |
| |
| ret = sscanf(buf, "%x %d", ¶[0], ¶[1]); |
| if (ret < 2) { |
| dread.reg = 0xff; |
| dread.cnt = 0; |
| pr_info("invalid data\n"); |
| return count; |
| } |
| dread.reg = (unsigned char)para[0]; |
| dread.cnt = (unsigned char)para[1]; |
| if (dread.cnt > DSI_READ_CNT_MAX) { |
| LCDERR("mipi read cnt is out of support\n"); |
| return count; |
| } |
| if (!dread.value) { |
| LCDERR("mipi read return value is null\n"); |
| return count; |
| } |
| |
| pr_info("set mipi read reg: 0x%02x, cnt: %d\n", dread.reg, dread.cnt); |
| |
| return count; |
| } |
| |
| static ssize_t lcd_mipi_state_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int state_save, offset; |
| |
| offset = pdrv->data->offset_venc_if[pdrv->index]; |
| state_save = lcd_vcbus_getb(L_VCOM_VS_ADDR + offset, 12, 1); |
| |
| return sprintf(buf, "state: %d, check_en: %d, state_save: %d\n", |
| pdrv->config.control.mipi_cfg.check_state, |
| pdrv->config.control.mipi_cfg.check_en, |
| state_save); |
| } |
| |
| static ssize_t lcd_mipi_mode_debug_show(struct device *dev, |
| struct device_attribute *attr, char *buf) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned char mode; |
| |
| if ((pdrv->status & LCD_STATUS_IF_ON) == 0) |
| return sprintf(buf, "error: panel is disabled\n"); |
| |
| mode = pdrv->config.control.mipi_cfg.current_mode; |
| return sprintf(buf, "current mipi-dsi operation mode: %s(%d)\n", |
| (mode ? "command" : "video"), mode); |
| } |
| |
| static ssize_t lcd_mipi_mode_debug_store(struct device *dev, struct device_attribute *attr, |
| const char *buf, size_t count) |
| { |
| struct aml_lcd_drv_s *pdrv = dev_get_drvdata(dev); |
| unsigned int temp; |
| unsigned char mode; |
| int ret = 0; |
| |
| if ((pdrv->status & LCD_STATUS_IF_ON) == 0) { |
| LCDERR("panel is disabled\n"); |
| return count; |
| } |
| |
| ret = kstrtouint(buf, 10, &temp); |
| if (ret) { |
| pr_info("invalid data\n"); |
| return -EINVAL; |
| } |
| mode = (unsigned char)temp; |
| #ifdef CONFIG_AMLOGIC_LCD_TABLET |
| dsi_set_operation_mode(pdrv, mode); |
| #endif |
| |
| return count; |
| } |
| |
| static struct device_attribute lcd_debug_attrs_ttl[] = { |
| __ATTR(ttl, 0644, lcd_ttl_debug_show, lcd_ttl_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_lvds[] = { |
| __ATTR(lvds, 0644, lcd_lvds_debug_show, lcd_lvds_debug_store), |
| __ATTR(phy, 0644, |
| lcd_phy_debug_show, lcd_phy_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_vbyone[] = { |
| __ATTR(vbyone, 0644, lcd_vx1_debug_show, lcd_vx1_debug_store), |
| __ATTR(phy, 0644, |
| lcd_phy_debug_show, lcd_phy_debug_store), |
| __ATTR(status, 0444, lcd_vx1_status_show, NULL), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_mlvds[] = { |
| __ATTR(mlvds, 0644, lcd_mlvds_debug_show, lcd_mlvds_debug_store), |
| __ATTR(phy, 0644, lcd_phy_debug_show, lcd_phy_debug_store), |
| __ATTR(tcon, 0644, lcd_tcon_debug_show, lcd_tcon_debug_store), |
| __ATTR(tcon_status, 0444, lcd_tcon_status_show, NULL), |
| __ATTR(tcon_reg, 0644, lcd_tcon_adb_status_show, lcd_tcon_adb_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_p2p[] = { |
| __ATTR(p2p, 0644, lcd_p2p_debug_show, lcd_p2p_debug_store), |
| __ATTR(phy, 0644, lcd_phy_debug_show, lcd_phy_debug_store), |
| __ATTR(tcon, 0644, lcd_tcon_debug_show, lcd_tcon_debug_store), |
| __ATTR(tcon_status, 0444, lcd_tcon_status_show, NULL), |
| __ATTR(tcon_reg, 0644, lcd_tcon_adb_status_show, lcd_tcon_adb_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_mipi[] = { |
| __ATTR(mipi, 0644, lcd_mipi_debug_show, lcd_mipi_debug_store), |
| __ATTR(mpcmd, 0644, lcd_mipi_cmd_debug_show, lcd_mipi_cmd_debug_store), |
| __ATTR(mpread, 0644, lcd_mipi_read_debug_show, lcd_mipi_read_debug_store), |
| __ATTR(mpstate, 0444, lcd_mipi_state_debug_show, NULL), |
| __ATTR(mpmode, 0644, lcd_mipi_mode_debug_show, lcd_mipi_mode_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static struct device_attribute lcd_debug_attrs_edp[] = { |
| __ATTR(edp, 0644, lcd_edp_debug_show, lcd_edp_debug_store), |
| __ATTR(phy, 0644, lcd_phy_debug_show, lcd_phy_debug_store), |
| __ATTR(edid, 0644, lcd_edp_edid_debug_show, lcd_edp_edid_debug_store), |
| __ATTR(null, 0644, NULL, NULL) |
| }; |
| |
| static int lcd_debug_file_creat(struct aml_lcd_drv_s *pdrv) |
| { |
| struct device_attribute *lcd_attr; |
| int i; |
| |
| pdrv->lcd_screen_restore = lcd_screen_restore; |
| pdrv->lcd_screen_black = lcd_screen_black; |
| |
| INIT_WORK(&pdrv->test_check_work, lcd_test_pattern_check); |
| |
| for (i = 0; i < ARRAY_SIZE(lcd_debug_attrs); i++) { |
| if (device_create_file(pdrv->dev, &lcd_debug_attrs[i])) { |
| LCDERR("create lcd debug attribute %s fail\n", |
| lcd_debug_attrs[i].attr.name); |
| } |
| } |
| |
| if (!lcd_debug_info_if || !lcd_debug_info_if->attrs) |
| return 0; |
| |
| lcd_attr = lcd_debug_info_if->attrs; |
| while (lcd_attr) { |
| if (strcmp(lcd_attr->attr.name, "null") == 0) |
| break; |
| if (device_create_file(pdrv->dev, lcd_attr)) { |
| LCDERR("create interface debug attribute %s fail\n", |
| lcd_attr->attr.name); |
| } |
| lcd_attr++; |
| } |
| |
| return 0; |
| } |
| |
| static int lcd_debug_file_remove(struct aml_lcd_drv_s *pdrv) |
| { |
| struct device_attribute *lcd_attr; |
| int i; |
| |
| for (i = 0; i < ARRAY_SIZE(lcd_debug_attrs); i++) |
| device_remove_file(pdrv->dev, &lcd_debug_attrs[i]); |
| |
| if (!lcd_debug_info_if || !lcd_debug_info_if->attrs) |
| return 0; |
| |
| lcd_attr = lcd_debug_info_if->attrs; |
| while (lcd_attr) { |
| if (strcmp(lcd_attr->attr.name, "null") == 0) |
| break; |
| device_remove_file(pdrv->dev, lcd_attr); |
| lcd_attr++; |
| } |
| |
| return 0; |
| } |
| |
| /* ********************************** |
| * lcd debug match data |
| * ********************************** |
| */ |
| /* chip_type data */ |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_g12a_clk_path0 = { |
| .reg_pll_table = NULL, |
| .reg_clk_table = lcd_reg_dump_clk_hpll_g12a, |
| .reg_encl_table = lcd_reg_dump_encl_dft, |
| .reg_pinmux_table = NULL, |
| .prbs_test = NULL, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_g12a_clk_path1 = { |
| .reg_pll_table = NULL, |
| .reg_clk_table = lcd_reg_dump_clk_gp0_g12a, |
| .reg_encl_table = lcd_reg_dump_encl_dft, |
| .reg_pinmux_table = NULL, |
| .prbs_test = NULL, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_tl1 = { |
| .reg_pll_table = NULL, |
| .reg_clk_table = lcd_reg_dump_clk_tl1, |
| .reg_encl_table = lcd_reg_dump_encl_tl1, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_tl1, |
| .prbs_test = aml_lcd_prbs_test, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t5 = { |
| .reg_pll_table = lcd_reg_dump_pll_t5, |
| .reg_clk_table = lcd_reg_dump_clk_t5, |
| .reg_encl_table = lcd_reg_dump_encl_tl1, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t5, |
| .prbs_test = aml_lcd_prbs_test, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t7_0 = { |
| .reg_pll_table = lcd_reg_dump_pll_t7_0, |
| .reg_clk_table = lcd_reg_dump_clk_t7_0, |
| .reg_encl_table = lcd_reg_dump_encl_t7_0, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t7, |
| .prbs_test = aml_lcd_prbs_test_t7, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t7_1 = { |
| .reg_pll_table = lcd_reg_dump_pll_t7_1, |
| .reg_clk_table = lcd_reg_dump_clk_t7_1, |
| .reg_encl_table = lcd_reg_dump_encl_t7_1, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t7, |
| .prbs_test = aml_lcd_prbs_test_t7, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t7_2 = { |
| .reg_pll_table = lcd_reg_dump_pll_t7_2, |
| .reg_clk_table = lcd_reg_dump_clk_t7_2, |
| .reg_encl_table = lcd_reg_dump_encl_t7_2, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t7, |
| .prbs_test = aml_lcd_prbs_test_t7, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t3_0 = { |
| .reg_pll_table = lcd_reg_dump_pll_t3_0, |
| .reg_clk_table = lcd_reg_dump_clk_t7_0, |
| .reg_encl_table = lcd_reg_dump_encl_t7_0, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t3, |
| .prbs_test = aml_lcd_prbs_test_t3, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t3_1 = { |
| .reg_pll_table = lcd_reg_dump_pll_t3_0, |
| .reg_clk_table = lcd_reg_dump_clk_t7_1, |
| .reg_encl_table = lcd_reg_dump_encl_t7_1, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_t3, |
| .prbs_test = aml_lcd_prbs_test_t3, |
| }; |
| |
| static struct lcd_debug_info_reg_s lcd_debug_info_reg_t5w = { |
| .reg_pll_table = lcd_reg_dump_pll_t5, |
| .reg_clk_table = lcd_reg_dump_clk_t5w, |
| .reg_encl_table = lcd_reg_dump_encl_t7_0, |
| .reg_pinmux_table = lcd_reg_dump_pinmux_tl1, |
| .prbs_test = aml_lcd_prbs_test, |
| }; |
| |
| /* interface data */ |
| static struct lcd_debug_info_if_s lcd_debug_info_if_ttl = { |
| .interface_print = lcd_info_print_ttl, |
| .reg_dump_interface = lcd_reg_print_ttl, |
| .reg_dump_phy = NULL, |
| .attrs = lcd_debug_attrs_ttl, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_lvds = { |
| .interface_print = lcd_info_print_lvds, |
| .reg_dump_interface = lcd_reg_print_lvds, |
| .reg_dump_phy = lcd_reg_print_phy_analog, |
| .attrs = lcd_debug_attrs_lvds, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_vbyone = { |
| .interface_print = lcd_info_print_vbyone, |
| .reg_dump_interface = lcd_reg_print_vbyone, |
| .reg_dump_phy = lcd_reg_print_phy_analog, |
| .attrs = lcd_debug_attrs_vbyone, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_mipi = { |
| .interface_print = lcd_info_print_mipi, |
| .reg_dump_interface = lcd_reg_print_mipi, |
| .reg_dump_phy = lcd_reg_print_mipi_phy_analog, |
| .attrs = lcd_debug_attrs_mipi, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_edp = { |
| .interface_print = lcd_info_print_edp, |
| .reg_dump_interface = lcd_reg_print_edp, |
| .reg_dump_phy = lcd_reg_print_phy_analog_t7, |
| .attrs = lcd_debug_attrs_edp, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_mlvds = { |
| .interface_print = lcd_info_print_mlvds, |
| .reg_dump_interface = lcd_reg_print_tcon, |
| .reg_dump_phy = lcd_reg_print_phy_analog, |
| .attrs = lcd_debug_attrs_mlvds, |
| }; |
| |
| static struct lcd_debug_info_if_s lcd_debug_info_if_p2p = { |
| .interface_print = lcd_info_print_p2p, |
| .reg_dump_interface = lcd_reg_print_tcon, |
| .reg_dump_phy = lcd_reg_print_phy_analog, |
| .attrs = lcd_debug_attrs_p2p, |
| }; |
| |
| int lcd_debug_probe(struct aml_lcd_drv_s *pdrv) |
| { |
| int lcd_type; |
| |
| lcd_type = pdrv->config.basic.lcd_type; |
| |
| switch (pdrv->data->chip_type) { |
| case LCD_CHIP_TL1: |
| case LCD_CHIP_TM2: |
| lcd_debug_info_reg = &lcd_debug_info_reg_tl1; |
| break; |
| case LCD_CHIP_T5: |
| case LCD_CHIP_T5D: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t5; |
| break; |
| case LCD_CHIP_T5W: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t5w; |
| break; |
| case LCD_CHIP_T7: |
| switch (pdrv->index) { |
| case 1: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t7_1; |
| break; |
| case 2: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t7_2; |
| break; |
| case 0: |
| default: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t7_0; |
| break; |
| } |
| lcd_debug_info_if_lvds.reg_dump_interface = lcd_reg_print_lvds_t7; |
| lcd_debug_info_if_lvds.reg_dump_phy = lcd_reg_print_phy_analog_t7; |
| lcd_debug_info_if_vbyone.reg_dump_interface = lcd_reg_print_vbyone_t7; |
| lcd_debug_info_if_vbyone.reg_dump_phy = lcd_reg_print_phy_analog_t7; |
| lcd_debug_info_if_mipi.reg_dump_phy = lcd_reg_print_phy_analog_t7; |
| break; |
| case LCD_CHIP_T3: |
| switch (pdrv->index) { |
| case 1: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t3_1; |
| break; |
| default: |
| lcd_debug_info_reg = &lcd_debug_info_reg_t3_0; |
| break; |
| } |
| lcd_debug_info_if_lvds.reg_dump_interface = lcd_reg_print_lvds_t7; |
| lcd_debug_info_if_lvds.reg_dump_phy = lcd_reg_print_phy_analog_t3; |
| lcd_debug_info_if_vbyone.reg_dump_interface = lcd_reg_print_vbyone_t7; |
| lcd_debug_info_if_vbyone.reg_dump_phy = lcd_reg_print_phy_analog_t3; |
| lcd_debug_info_if_mlvds.reg_dump_interface = lcd_reg_print_tcon_t3; |
| lcd_debug_info_if_mlvds.reg_dump_phy = lcd_reg_print_phy_analog_t3; |
| lcd_debug_info_if_p2p.reg_dump_interface = lcd_reg_print_tcon_t3; |
| lcd_debug_info_if_p2p.reg_dump_phy = lcd_reg_print_phy_analog_t3; |
| break; |
| case LCD_CHIP_G12A: |
| case LCD_CHIP_G12B: |
| case LCD_CHIP_SM1: |
| if (pdrv->clk_path) |
| lcd_debug_info_reg = &lcd_debug_info_reg_g12a_clk_path1; |
| else |
| lcd_debug_info_reg = &lcd_debug_info_reg_g12a_clk_path0; |
| break; |
| default: |
| lcd_debug_info_reg = NULL; |
| break; |
| } |
| |
| switch (lcd_type) { |
| case LCD_TTL: |
| lcd_debug_info_if = &lcd_debug_info_if_ttl; |
| break; |
| case LCD_LVDS: |
| lcd_debug_info_if = &lcd_debug_info_if_lvds; |
| break; |
| case LCD_VBYONE: |
| lcd_debug_info_if = &lcd_debug_info_if_vbyone; |
| break; |
| case LCD_MIPI: |
| lcd_debug_info_if = &lcd_debug_info_if_mipi; |
| break; |
| case LCD_EDP: |
| lcd_debug_info_if = &lcd_debug_info_if_edp; |
| break; |
| case LCD_MLVDS: |
| mutex_init(&lcd_tcon_adb_mutex); |
| lcd_debug_info_if = &lcd_debug_info_if_mlvds; |
| break; |
| case LCD_P2P: |
| mutex_init(&lcd_tcon_adb_mutex); |
| lcd_debug_info_if = &lcd_debug_info_if_p2p; |
| break; |
| default: |
| lcd_debug_info_if = NULL; |
| break; |
| } |
| |
| return lcd_debug_file_creat(pdrv); |
| } |
| |
| int lcd_debug_remove(struct aml_lcd_drv_s *pdrv) |
| { |
| return lcd_debug_file_remove(pdrv); |
| } |