int hisi_lcd_backlight_off(struct platform_device *pdev) { struct hisi_fb_data_type *hisifd = NULL; int ret = 0; BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); HISI_FB_INFO("fb%d, +!\n", hisifd->index); if (hisifd->panel_info.bl_set_type & BL_SET_BY_PWM) { ret = hisi_pwm_off(pdev); #ifdef CONFIG_BACKLIGHT_10000 ret = hisi_blpwm_off(pdev); #endif } else if (hisifd->panel_info.bl_set_type & BL_SET_BY_BLPWM) { ret = hisi_blpwm_off(pdev); } else if (hisifd->panel_info.bl_set_type & BL_SET_BY_MIPI) { ; } else { HISI_FB_ERR("No such bl_set_type(%d)!\n", hisifd->panel_info.bl_set_type); } HISI_FB_INFO("fb%d, -!\n", hisifd->index); return ret; }
int hisi_pwm_set_backlight(struct hisi_fb_data_type *hisifd) { char __iomem *pwm_base = NULL; uint32_t bl_max = 0; uint32_t bl_level = 0; BUG_ON(hisifd == NULL); pwm_base = hisifd_pwm_base; BUG_ON(pwm_base == NULL); #ifdef CONFIG_BACKLIGHT_10000 g_bl_info.bl_max = hisifd->panel_info.bl_max; #endif bl_level = hisifd->bl_level; bl_max = hisifd->panel_info.bl_max; if (bl_level > hisifd->panel_info.bl_max) { bl_level = hisifd->panel_info.bl_max; } if (bl_max < 1) { HISI_FB_ERR("bl_max=%d is invalid!\n", bl_max); return -EINVAL; } if ((bl_level > 0) && (bl_level < PWM_BL_LEVEL_MIN)) { bl_level = PWM_BL_LEVEL_MIN; } #ifdef CONFIG_BACKLIGHT_10000 if(bl_level > 0){ bl_level= bl_level * g_bl_info.current_cabc_pwm / CABC_PWM_DUTY_MAX_LEVEL; bl_level = bl_level < PWM_BL_LEVEL_MIN ? PWM_BL_LEVEL_MIN : bl_level ; } g_bl_info.ap_brightness = bl_level; HISI_FB_INFO("g_bl_info.ap_brightness= %d\n",bl_level); if(bl_level > 0 && g_bl_info.index_cabc_dimming > 0 && g_bl_info.index_cabc_dimming < 33 ) { HISI_FB_INFO("cabc is dimming and g_bl_info.index_cabc_dimming = %d\n",g_bl_info.index_cabc_dimming); return; } #endif bl_level = (bl_level * PWM_OUT_PRECISION) / bl_max; outp32(pwm_base + PWM_LOCK_OFFSET, 0x1acce551); outp32(pwm_base + PWM_CTL_OFFSET, 0x0); outp32(pwm_base + PWM_CFG_OFFSET, 0x2); outp32(pwm_base + PWM_PR0_OFFSET, 0x1); outp32(pwm_base + PWM_PR1_OFFSET, 0x2); outp32(pwm_base + PWM_CTL_OFFSET, 0x1); outp32(pwm_base + PWM_C0_MR_OFFSET, (PWM_OUT_PRECISION - 1)); outp32(pwm_base + PWM_C0_MR0_OFFSET, bl_level); return 0; }
int mipi_dsi_read_compare(struct mipi_dsi_read_compare_data *data, char __iomem *dsi_base) { u32 *read_value = data->read_value; u32 *expected_value = data->expected_value; u32 *read_mask = data->read_mask; char **reg_name = data->reg_name; int log_on = data->log_on; struct dsi_cmd_desc *cmds = data->cmds; int cnt = data->cnt; int cnt_not_match = 0; int read_ret = 0; int i; read_ret = mipi_dsi_cmds_rx(read_value, cmds, cnt, dsi_base); if(read_ret){ HISI_FB_ERR("Read error number: %d\n", read_ret); return cnt; } for(i=0; i<cnt; i++) { if (log_on) { HISI_FB_INFO("Read reg %s: 0x%X, value = 0x%X\n", reg_name[i], cmds[i].payload[0], read_value[i]); } if(expected_value[i] != (read_value[i] & read_mask[i])){ cnt_not_match++; } } return cnt_not_match; }
static int cabc_pwm_thread(void *p) { while(!kthread_should_stop()) { if(g_bl_info.index_cabc_dimming > CABC_DIMMING_STEP_TOTAL_NUM) { set_current_state(TASK_INTERRUPTIBLE); schedule(); g_bl_info.index_cabc_dimming =1 ; } else { if(g_bl_info.cabc_pwm_in != 0) { g_bl_info.cabc_pwm = g_bl_info.cabc_pwm_in; g_bl_info.cabc_pwm_in = 0; g_bl_info.index_cabc_dimming = 1; g_bl_info.prev_cabc_pwm = g_bl_info.current_cabc_pwm; } int32_t delta_cabc_pwm = g_bl_info.cabc_pwm - g_bl_info.prev_cabc_pwm; int32_t pwm_duty=delta_cabc_pwm*g_bl_info.index_cabc_dimming/32 + delta_cabc_pwm *g_bl_info.index_cabc_dimming % 32 /16; g_bl_info.current_cabc_pwm = g_bl_info.prev_cabc_pwm + pwm_duty; HISI_FB_INFO("g_bl_info.current_cabc_pwm = %d,g_bl_info.index_cabc_dimming= %d,pwm_duty= %d,g_bl_info.index_cabc_dimming= %d!\n",g_bl_info.current_cabc_pwm ,g_bl_info.index_cabc_dimming,pwm_duty,g_bl_info.index_cabc_dimming); int32_t backlight = g_bl_info.current_cabc_pwm * g_bl_info.ap_brightness / CABC_PWM_DUTY_MAX_LEVEL; if (backlight > 0 && backlight < PWM_BL_LEVEL_MIN) { backlight = PWM_BL_LEVEL_MIN; } update_backlight(backlight); g_bl_info.index_cabc_dimming++; msleep(16); } } return 0; }
void dss_underflow_stop_perf_state(struct hisi_fb_data_type *hisifd) { #ifdef DSS_DEVMEM_PERF_BASE void __iomem * perf_stat_base; if (inp32(hisifd->peri_crg_base + CRG_PERIPH_APB_PERRSTSTAT0_REG) & (1 << CRG_PERIPH_APB_IP_RST_PERF_STAT_BIT)) { HISI_FB_INFO("Failed : perf might not be used"); return ; } perf_stat_base = ioremap(DSS_DEVMEM_PERF_BASE, DEVMEM_PERF_SIZE); outp32(perf_stat_base + PERF_SAMPSTOP_REG, 0x1); iounmap(perf_stat_base); HISI_FB_INFO("OK : perf state stop succ"); #endif }
static int hisi_pwm_probe(struct platform_device *pdev) { struct device_node *np = NULL; int ret = 0; HISI_FB_DEBUG("+.\n"); BUG_ON(pdev == NULL); np = of_find_compatible_node(NULL, NULL, DTS_COMP_PWM_NAME); if (!np) { HISI_FB_ERR("NOT FOUND device node %s!\n", DTS_COMP_PWM_NAME); ret = -ENXIO; goto err_return; } /* get pwm reg base */ hisifd_pwm_base = of_iomap(np, 0); #if !defined(CONFIG_ARCH_HI3630FPGA) && !defined(CONFIG_HISI_3635_FPGA) \ && !defined(CONFIG_HISI_3650_FPGA) /* pwm pinctrl init */ ret = pinctrl_cmds_tx(pdev, pwm_pinctrl_init_cmds, ARRAY_SIZE(pwm_pinctrl_init_cmds)); if (ret != 0) { HISI_FB_ERR("Init pwm pinctrl failed! ret=%d.\n", ret); goto err_return; } /* get blpwm clk resource */ g_dss_pwm_clk = of_clk_get(np, 0); if (IS_ERR(g_dss_pwm_clk)) { HISI_FB_ERR("%s clock not found: %d!\n", np->name, (int)PTR_ERR(g_dss_pwm_clk)); ret = -ENXIO; goto err_return; } ret = clk_set_rate(g_dss_pwm_clk, DEFAULT_PWM_CLK_RATE); if (ret != 0) { HISI_FB_ERR("dss_pwm_clk clk_set_rate(%lu) failed, error=%d!\n", DEFAULT_PWM_CLK_RATE, ret); ret = -EINVAL; goto err_return; } HISI_FB_INFO("dss_pwm_clk:[%lu]->[%lu].\n", DEFAULT_PWM_CLK_RATE, clk_get_rate(g_dss_pwm_clk)); #endif hisi_fb_device_set_status0(DTS_PWM_READY); HISI_FB_DEBUG("-.\n"); return 0; err_return: return ret; }
static int mipi_dsi_clk_irq_setup(struct platform_device *pdev) { struct hisi_fb_data_type *hisifd = NULL; int ret = 0; BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); hisifd->dss_dphy0_clk = devm_clk_get(&pdev->dev, hisifd->dss_dphy0_clk_name); if (IS_ERR(hisifd->dss_dphy0_clk)) { ret = PTR_ERR(hisifd->dss_dphy0_clk); return ret; } else { ret = clk_set_rate(hisifd->dss_dphy0_clk, DEFAULT_MIPI_CLK_RATE); if (ret < 0) { HISI_FB_ERR("fb%d dss_dphy0_clk clk_set_rate(%lu) failed, error=%d!\n", hisifd->index, DEFAULT_MIPI_CLK_RATE, ret); return -EINVAL; } HISI_FB_INFO("dss_dphy0_clk:[%lu]->[%lu].\n", DEFAULT_MIPI_CLK_RATE, clk_get_rate(hisifd->dss_dphy0_clk)); } if (is_dual_mipi_panel(hisifd)) { hisifd->dss_dphy1_clk = devm_clk_get(&pdev->dev, hisifd->dss_dphy1_clk_name); if (IS_ERR(hisifd->dss_dphy1_clk)) { ret = PTR_ERR(hisifd->dss_dphy1_clk); return ret; } else { ret = clk_set_rate(hisifd->dss_dphy1_clk, DEFAULT_MIPI_CLK_RATE); if (ret < 0) { HISI_FB_ERR("fb%d dss_dphy1_clk clk_set_rate(%lu) failed, error=%d!\n", hisifd->index, DEFAULT_MIPI_CLK_RATE, ret); return -EINVAL; } HISI_FB_INFO("dss_dphy1_clk:[%lu]->[%lu].\n", DEFAULT_MIPI_CLK_RATE, clk_get_rate(hisifd->dss_dphy1_clk)); } } return ret; }
int hisifb_vsync_ctrl(struct fb_info *info, void __user *argp) { int ret = 0; struct hisi_fb_data_type *hisifd = NULL; struct hisi_fb_panel_data *pdata = NULL; struct hisifb_vsync *vsync_ctrl = NULL; int enable = 0; BUG_ON(info == NULL); hisifd = (struct hisi_fb_data_type *)info->par; BUG_ON(hisifd == NULL); pdata = dev_get_platdata(&hisifd->pdev->dev); BUG_ON(pdata == NULL); vsync_ctrl = &(hisifd->vsync_ctrl); BUG_ON(vsync_ctrl == NULL); ret = copy_from_user(&enable, argp, sizeof(enable)); if (ret) { HISI_FB_ERR("hisifb_vsync_ctrl ioctl failed!\n"); return ret; } enable = (enable) ? 1 : 0; mutex_lock(&(vsync_ctrl->vsync_lock)); if (vsync_ctrl->vsync_enabled == enable) { mutex_unlock(&(vsync_ctrl->vsync_lock)); return 0; } if (g_debug_online_vsync) HISI_FB_INFO("fb%d, enable=%d!\n", hisifd->index, enable); vsync_ctrl->vsync_enabled = enable; mutex_unlock(&(vsync_ctrl->vsync_lock)); down(&hisifd->blank_sem); if (!hisifd->panel_power_on) { HISI_FB_DEBUG("fb%d, panel is power off!", hisifd->index); up(&hisifd->blank_sem); return 0; } if (enable) { hisifb_activate_vsync(hisifd); } else { hisifb_deactivate_vsync(hisifd); } up(&hisifd->blank_sem); return 0; }
void hisifb_adjust_block_rect(int block_num, dss_rect_t *ov_block_rects[], dss_wb_layer_t *wb_layer) { int i = 0; dss_rect_t block_rect; bool need_adjust_block = false; BUG_ON(ov_block_rects == NULL); BUG_ON(wb_layer == NULL); if ((block_num > 1) && (ov_block_rects[block_num - 1]->w < HISI_DSS_MIN_ROT_AFBCE_BLOCK_SIZE)) { if ((wb_layer->transform == (HISI_FB_TRANSFORM_ROT_90 | HISI_FB_TRANSFORM_FLIP_V)) && (wb_layer->need_cap == CAP_AFBCE)) { if (g_debug_ovl_block_composer) { HISI_FB_INFO("before_adjust:ov_block_rects[%d]:[%d:%d:%d:%d]\n", block_num - 1, ov_block_rects[block_num-1]->x, ov_block_rects[block_num-1]->y, ov_block_rects[block_num-1]->w, ov_block_rects[block_num-1]->h); } block_rect = *ov_block_rects[block_num - 1]; ov_block_rects[block_num - 1]->w += HISI_DSS_MIN_ROT_AFBCE_BLOCK_SIZE; if (ov_block_rects[block_num - 1]->w > HISI_DSS_MAX_ROT_AFBCE_BLOCK_SIZE) { ov_block_rects[block_num - 1]->w = HISI_DSS_MAX_ROT_AFBCE_BLOCK_SIZE; } block_rect.x -= ov_block_rects[block_num - 1]->w - block_rect.w; ov_block_rects[block_num - 1]->x = ALIGN_UP(block_rect.x, AFBC_BLOCK_ALIGN); ov_block_rects[block_num - 1]->w -= ov_block_rects[block_num - 1]->x - block_rect.x; need_adjust_block = true; } } if (need_adjust_block && g_debug_ovl_block_composer) { for (i = 0; i < block_num; i++) { HISI_FB_INFO("after_adjust:ov_block_rects[%d]:[%d:%d:%d:%d]\n", i, ov_block_rects[i]->x, ov_block_rects[i]->y, ov_block_rects[i]->w, ov_block_rects[i]->h); } } }
static void update_backlight(uint32_t backlight) { uint32_t bl_level = (backlight * PWM_OUT_PRECISION) / g_bl_info.bl_max; HISI_FB_INFO("update_backlight: backlight = %d!\n", backlight); BUG_ON(hisifd_pwm_base == NULL); outp32(hisifd_pwm_base + PWM_LOCK_OFFSET, 0x1acce551); outp32(hisifd_pwm_base + PWM_CTL_OFFSET, 0x0); outp32(hisifd_pwm_base + PWM_CFG_OFFSET, 0x2); outp32(hisifd_pwm_base + PWM_PR0_OFFSET, 0x1); outp32(hisifd_pwm_base + PWM_PR1_OFFSET, 0x2); outp32(hisifd_pwm_base + PWM_CTL_OFFSET, 0x1); outp32(hisifd_pwm_base + PWM_C0_MR_OFFSET, (PWM_OUT_PRECISION - 1)); outp32(hisifd_pwm_base + PWM_C0_MR0_OFFSET, bl_level); }
void hisifb_vsync_isr_handler(struct hisi_fb_data_type *hisifd) { struct hisifb_vsync *vsync_ctrl = NULL; int buffer_updated = 0; ktime_t pre_vsync_timestamp; BUG_ON(hisifd == NULL); vsync_ctrl = &(hisifd->vsync_ctrl); BUG_ON(vsync_ctrl == NULL); pre_vsync_timestamp = vsync_ctrl->vsync_timestamp; vsync_ctrl->vsync_timestamp = ktime_get(); wake_up_interruptible_all(&(vsync_ctrl->vsync_wait)); if (hisifd->panel_info.vsync_ctrl_type != VSYNC_CTRL_NONE) { spin_lock(&vsync_ctrl->spin_lock); if (vsync_ctrl->vsync_ctrl_expire_count) { vsync_ctrl->vsync_ctrl_expire_count--; if (vsync_ctrl->vsync_ctrl_expire_count == 0) schedule_work(&vsync_ctrl->vsync_ctrl_work); } spin_unlock(&vsync_ctrl->spin_lock); } if (vsync_ctrl->vsync_report_fnc) { if (hisifd->vsync_ctrl.vsync_enabled) { buffer_updated = atomic_dec_return(&(vsync_ctrl->buffer_updated)); } else { buffer_updated = 1; } if (buffer_updated < 0) { atomic_cmpxchg(&(vsync_ctrl->buffer_updated), buffer_updated, 1); } else { vsync_ctrl->vsync_report_fnc(buffer_updated); } } if (g_debug_online_vsync) { HISI_FB_INFO("fb%d, VSYNC=%llu, time_diff=%llu.\n", hisifd->index, ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp), (ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp) - ktime_to_ns(pre_vsync_timestamp))); } }
static void hisifb_vsync_ctrl_workqueue_handler(struct work_struct *work) { struct hisi_fb_data_type *hisifd = NULL; struct hisifb_vsync *vsync_ctrl = NULL; struct hisi_fb_panel_data *pdata = NULL; unsigned long flags = 0; vsync_ctrl = container_of(work, typeof(*vsync_ctrl), vsync_ctrl_work); BUG_ON(vsync_ctrl == NULL); hisifd = vsync_ctrl->hisifd; BUG_ON(hisifd == NULL); pdata = dev_get_platdata(&hisifd->pdev->dev); BUG_ON(pdata == NULL); down(&(hisifd->blank_sem)); if (!hisifd->panel_power_on) { HISI_FB_INFO("fb%d, panel is power off!", hisifd->index); up(&(hisifd->blank_sem)); return; } mutex_lock(&(vsync_ctrl->vsync_lock)); if (vsync_ctrl->vsync_ctrl_disabled_set && (vsync_ctrl->vsync_ctrl_expire_count == 0) && vsync_ctrl->vsync_ctrl_enabled && !vsync_ctrl->vsync_enabled && !vsync_ctrl->vsync_ctrl_offline_enabled) { HISI_FB_DEBUG("fb%d, dss clk off!\n", hisifd->index); spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags); if (pdata->vsync_ctrl) { pdata->vsync_ctrl(hisifd->pdev, 0); } else { HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n", hisifd->index); } vsync_ctrl->vsync_ctrl_enabled = 0; vsync_ctrl->vsync_ctrl_disabled_set = 0; spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags); if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) { mipi_dsi_ulps_cfg(hisifd, 0); } if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) { if (hisifd->lp_fnc) hisifd->lp_fnc(hisifd, true); } if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) { dpe_inner_clk_disable(hisifd); dpe_common_clk_disable(hisifd); mipi_dsi_clk_disable(hisifd); } if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) { dpe_regulator_disable(hisifd); } } mutex_unlock(&(vsync_ctrl->vsync_lock)); if (vsync_ctrl->vsync_report_fnc) { vsync_ctrl->vsync_report_fnc(1); } up(&(hisifd->blank_sem)); }
static ssize_t vsync_show_event(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; int vsync_flag = 0; int secure_flag = 0; struct fb_info *fbi = NULL; struct hisi_fb_data_type *hisifd = NULL; struct hisifb_secure *secure_ctrl = NULL; ktime_t prev_timestamp; if (NULL == dev) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } fbi = dev_get_drvdata(dev); if (NULL == fbi) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } hisifd = (struct hisi_fb_data_type *)fbi->par; if (NULL == hisifd) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } secure_ctrl = &(hisifd->secure_ctrl); if (NULL == secure_ctrl) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } if (NULL == buf) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } prev_timestamp = hisifd->vsync_ctrl.vsync_timestamp; /*lint -e666*/ ret = wait_event_interruptible(hisifd->vsync_ctrl.vsync_wait, (vsync_timestamp_changed(hisifd, prev_timestamp) && hisifd->vsync_ctrl.vsync_enabled) || (secure_ctrl->tui_need_switch)); /*lint +e666*/ vsync_flag = (vsync_timestamp_changed(hisifd, prev_timestamp) && hisifd->vsync_ctrl.vsync_enabled); secure_flag = secure_ctrl->tui_need_switch; if (vsync_flag && secure_flag) { HISI_FB_INFO("report (secure_event = %d) to hwc with vsync at (frame_no = %d).\n", \ secure_ctrl->secure_event, hisifd->ov_req.frame_no); ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu, SecureEvent=%d \n", ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp), secure_ctrl->secure_event); buf[strlen(buf) + 1] = '\0'; if (secure_ctrl->secure_event == DSS_SEC_DISABLE) { secure_ctrl->tui_need_switch = 0; } } else if (vsync_flag) { ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu, xxxxxxevent=x \n", ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp)); buf[strlen(buf) + 1] = '\0'; secure_ctrl->tui_need_skip_report = 0; } else if (secure_flag && !secure_ctrl->tui_need_skip_report) { HISI_FB_INFO("report (secure_event = %d) to hwc at (frame_no = %d).\n", \ secure_ctrl->secure_event, hisifd->ov_req.frame_no); ret = snprintf(buf, PAGE_SIZE, "xxxxx=%llu, SecureEvent=%d \n", ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp), secure_ctrl->secure_event); buf[strlen(buf) + 1] = '\0'; secure_ctrl->tui_need_skip_report = 1; if (secure_ctrl->secure_event == DSS_SEC_DISABLE) { secure_ctrl->tui_need_switch = 0; } } else { ;//do nothing } return ret; }
void panel_check_status_and_report_by_dsm(struct lcd_reg_read_t *lcd_status_reg, int cnt, char __iomem *mipi_dsi0_base) { u32 read_value = 0, expected_value = 0, read_mask = 0; u8 reg_addr = 0; char *reg_name = NULL; int dsm_error_found = 0, dsm_client_ready = 0; u32 pkg_status = 0, try_times = 100, i = 0; struct dsi_cmd_desc packet_size_set_cmd = {DTYPE_MAX_PKTSIZE, 0, 10, WAIT_TYPE_US, 1, NULL}; if (!dsm_client_ocuppy(lcd_dclient)) { dsm_client_ready = 1; } mipi_dsi_max_return_packet_size(&packet_size_set_cmd, mipi_dsi0_base); for (i = 0; i < cnt; i++) { /*Each iteration read a registers*/ reg_addr = lcd_status_reg[i].reg_addr; reg_name = lcd_status_reg[i].reg_name; expected_value = lcd_status_reg[i].expected_value; read_mask = lcd_status_reg[i].read_mask; /*Send MIPI read command, and wait the return value no longer than 100*30us*/ try_times = 100; outp32(mipi_dsi0_base + MIPIDSI_GEN_HDR_OFFSET, reg_addr << 8 | 0x06); udelay(20); do { pkg_status = inp32(mipi_dsi0_base + MIPIDSI_CMD_PKT_STATUS_OFFSET); if (!(pkg_status & 0x10)) break; udelay(30); } while (--try_times); /*Read the return value, report error if read timeout or read value is not expected*/ read_value = inp32(mipi_dsi0_base + MIPIDSI_GEN_PLD_DATA_OFFSET); if (read_mask != 0) read_value &= read_mask; if (!try_times) { HISI_FB_ERR("Read %s timeout!\n", reg_name); if (dsm_client_ready) { dsm_client_record(lcd_dclient, "Read %s timeout!\n", reg_name); dsm_error_found++; } break; } else if (read_value != expected_value && read_mask != 0) { HISI_FB_ERR("ERROR: read %s = 0x%X, but expect: 0x%X\n", reg_name, read_value, expected_value); if (dsm_client_ready) { dsm_client_record(lcd_dclient, "ERROR: read %s = 0x%X, but expect: 0x%X\n", reg_name, read_value, expected_value); dsm_error_found++; } break; } else if (read_value == expected_value && read_mask == 0) { /*In this case read_mask == 0, read value equal to expected_value is a LCD error*/ HISI_FB_ERR("ERROR: read %s = 0x%X, but expect NOT equal to: 0x%X\n", reg_name, read_value, expected_value); if (dsm_client_ready) { dsm_client_record(lcd_dclient, "ERROR: read %s = 0x%X, but expect NOT equal to: 0x%X\n", reg_name, read_value, expected_value); dsm_error_found++; } break; } else { HISI_FB_INFO("Read %s = 0x%x\n", reg_name, read_value); } } /*Report error to Device Status Monitor*/ if (dsm_error_found > 0) { dsm_client_notify(lcd_dclient, DSM_LCD_STATUS_ERROR_NO); } else if (dsm_client_ready) { dsm_client_unocuppy(lcd_dclient); } else { HISI_FB_INFO("dsm lcd_dclient ocuppy failed!\n"); } }
int hisi_dss_aif1_ch_config(struct hisi_fb_data_type *hisifd, dss_overlay_t *pov_req, dss_layer_t *layer, dss_wb_layer_t *wb_layer, int ovl_idx) { dss_aif_t *aif1 = NULL; dss_aif_bw_t *aif1_bw = NULL; int chn_idx = 0; uint32_t need_cap = 0; int mid = 0; uint32_t credit_step = 0; uint64_t dss_core_rate = 0; uint32_t scfd_h = 0; uint32_t scfd_v = 0; BUG_ON(hisifd == NULL); BUG_ON(pov_req == NULL); BUG_ON((layer == NULL) && (wb_layer == NULL)); BUG_ON((ovl_idx < DSS_OVL0) || (ovl_idx >= DSS_OVL_IDX_MAX)); if (wb_layer) { chn_idx = wb_layer->chn_idx; need_cap = wb_layer->need_cap; } else { chn_idx = layer->chn_idx; need_cap = layer->need_cap; } if (!(need_cap & CAP_AFBCD)) return 0; aif1 = &(hisifd->dss_module.aif1[chn_idx]); hisifd->dss_module.aif1_ch_used[chn_idx] = 1; aif1_bw = &(hisifd->dss_module.aif1_bw[chn_idx]); BUG_ON(aif1_bw->is_used != 1); mid = 0x9 - chn_idx; BUG_ON(mid < 0); aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, aif1_bw->axi_sel, 1, 0); aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, mid, 4, 4); if (g_fpga_flag == 0) { if ((ovl_idx == DSS_OVL0) || (ovl_idx == DSS_OVL1)) { if (layer && (layer->need_cap & CAP_AFBCD)) { dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate; if (dss_core_rate == 0) { HISI_FB_ERR("fb%d, dss_core_rate(%llu) is invalid!", hisifd->index, dss_core_rate); dss_core_rate = DEFAULT_DSS_CORE_CLK_RATE; } if ((layer->src_rect.w > layer->dst_rect.w) && (layer->src_rect.w > get_panel_xres(hisifd))) { scfd_h = layer->src_rect.w * 100 / get_panel_xres(hisifd); } else { scfd_h = 100; } //after stretch if (layer->src_rect.h > layer->dst_rect.h) { scfd_v = layer->src_rect.h * 100 / layer->dst_rect.h; } else { scfd_v = 100; } //credit_step = pix_f*128/(core_f*16/4)*1.25*scfd_h*scfd_v credit_step = hisifd->panel_info.pxl_clk_rate * 32 * 150 * scfd_h * scfd_v / dss_core_rate / (100 * 100 * 100); if (g_debug_ovl_online_composer || g_debug_ovl_offline_composer || g_debug_ovl_credit_step) { HISI_FB_INFO("fb%d, layer_idx(%d), chn_idx(%d), src_rect(%d,%d,%d,%d)," "dst_rect(%d,%d,%d,%d), scfd_h=%d, scfd_v=%d, credit_step=%d.\n", hisifd->index, layer->layer_idx, layer->chn_idx, layer->src_rect.x, layer->src_rect.y, layer->src_rect.w, layer->src_rect.h, layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w, layer->dst_rect.h, scfd_h, scfd_v, credit_step); } if (credit_step < 32) { credit_step = 32; } if (credit_step > 64) { credit_step = 0; } aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, 0x1, 1, 11); aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, credit_step, 7, 16); } } else { if (layer && (layer->need_cap & CAP_AFBCD)) { dss_core_rate = hisifd->dss_clk_rate.dss_pri_clk_rate; if (dss_core_rate == 0) { HISI_FB_ERR("fb%d, dss_core_rate(%llu is invalid!", hisifd->index, dss_core_rate); dss_core_rate = DEFAULT_DSS_CORE_CLK_RATE; } if ((layer->src_rect.w > layer->dst_rect.w) && (layer->src_rect.w > get_panel_xres(hisifd))) { scfd_h = layer->src_rect.w * 100 / get_panel_xres(hisifd); } else { scfd_h = 100; } //after stretch if (layer->src_rect.h > layer->dst_rect.h) { scfd_v = layer->src_rect.h * 100 / layer->dst_rect.h; } else { scfd_v = 100; } //credit_step = pix_f*128/(core_f*16/4)*scfd_h*scfd_v credit_step = hisifd->panel_info.pxl_clk_rate * 32 * scfd_h * scfd_v / dss_core_rate / (100 * 100); if (g_debug_ovl_online_composer || g_debug_ovl_offline_composer || g_debug_ovl_credit_step) { HISI_FB_INFO("fb%d, layer_idx(%d), chn_idx(%d), src_rect(%d,%d,%d,%d)," "dst_rect(%d,%d,%d,%d), scfd_h=%d, scfd_v=%d, credit_step=%d.\n", hisifd->index, layer->layer_idx, layer->chn_idx, layer->src_rect.x, layer->src_rect.y, layer->src_rect.w, layer->src_rect.h, layer->dst_rect.x, layer->dst_rect.y, layer->dst_rect.w, layer->dst_rect.h, scfd_h, scfd_v, credit_step); } if (credit_step < 32) { credit_step = 32; } if (credit_step > 64) { credit_step = 0; } aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, 0x1, 1, 11); aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, credit_step, 7, 16); } } } else { if ((ovl_idx == DSS_OVL2) || (ovl_idx == DSS_OVL3)) { aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, 0x1, 1, 11); aif1->aif_ch_ctl = set_bits32(aif1->aif_ch_ctl, 0x10, 7, 16); } } return 0; }
static void mipi_init(struct hisi_fb_data_type *hisifd, char __iomem *mipi_dsi_base) { uint32_t hline_time = 0; uint32_t hsa_time = 0; uint32_t hbp_time = 0; uint32_t pixel_clk = 0; unsigned long dw_jiffies = 0; struct mipi_dsi_phy_ctrl phy_ctrl = {0}; uint32_t tmp = 0; bool is_ready = false; struct hisi_panel_info *pinfo = NULL; BUG_ON(hisifd == NULL); BUG_ON(mipi_dsi_base == NULL); pinfo = &(hisifd->panel_info); get_dsi_phy_ctrl(pinfo->mipi.dsi_bit_clk, &phy_ctrl); /* config TE */ if (is_mipi_cmd_panel(hisifd)) { /* config to command mode */ set_reg(mipi_dsi_base + MIPIDSI_MODE_CFG_OFFSET, 0x1, 1, 0); /* ALLOWED_CMD_SIZE */ set_reg(mipi_dsi_base + MIPIDSI_EDPI_CMD_SIZE_OFFSET, pinfo->xres, 16, 0); /* cnt=2 in update-patial scene, cnt nees to be checked for different panels*/ set_reg(mipi_dsi_base + MIPIDSI_HS_WR_TO_CNT_OFFSET, 0x1000002, 25, 0); /* phy_stop_wait_time */ set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, 0x30, 8, 8); /* FIXME: test tearing effect, if use gpio, no need */ /*set_reg(mipi_dsi_base + MIPIDSI_CMD_MODE_CFG_OFFSET, 0x1, 1, 0);*/ } /*--------------configuring the DPI packet transmission----------------*/ /* ** 1. Global configuration ** Configure Register PHY_IF_CFG with the correct number of lanes ** to be used by the controller. */ set_reg(mipi_dsi_base + MIPIDSI_PHY_IF_CFG_OFFSET, pinfo->mipi.lane_nums, 2, 0); /* ** 2. Configure the DPI Interface: ** This defines how the DPI interface interacts with the controller. */ set_reg(mipi_dsi_base + MIPIDSI_DPI_VCID_OFFSET, pinfo->mipi.vc, 2, 0); set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET, pinfo->mipi.color_mode, 4, 0); set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, pinfo->ldi.data_en_plr, 1, 0); set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, pinfo->ldi.vsync_plr, 1, 1); set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, pinfo->ldi.hsync_plr, 1, 2); set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 3); set_reg(mipi_dsi_base + MIPIDSI_DPI_CFG_POL_OFFSET, 0x0, 1, 4); if (pinfo->bpp == LCD_RGB666) { set_reg(mipi_dsi_base + MIPIDSI_DPI_COLOR_CODING_OFFSET, 0x1, 1, 8); } /* ** 3. Select the Video Transmission Mode: ** This defines how the processor requires the video line to be ** transported through the DSI link. */ /* video mode: low power mode */ set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x3f, 6, 8); /* set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, 0x0, 1, 14); */ /* burst mode */ set_reg(mipi_dsi_base + MIPIDSI_VID_MODE_CFG_OFFSET, phy_ctrl.burst_mode, 2, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_PKT_SIZE_OFFSET, pinfo->xres, 14, 0); /* for dsi read, BTA enable*/ set_reg(mipi_dsi_base + MIPIDSI_PCKHDL_CFG_OFFSET, 0x1, 1, 2); /* ** 4. Define the DPI Horizontal timing configuration: ** ** Hsa_time = HSA*(PCLK period/Clk Lane Byte Period); ** Hbp_time = HBP*(PCLK period/Clk Lane Byte Period); ** Hline_time = (HSA+HBP+HACT+HFP)*(PCLK period/Clk Lane Byte Period); */ pixel_clk = pinfo->pxl_clk_rate / 1000000; hsa_time = pinfo->ldi.h_pulse_width * phy_ctrl.lane_byte_clk / pixel_clk; hbp_time = pinfo->ldi.h_back_porch * phy_ctrl.lane_byte_clk / pixel_clk; hline_time = (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch + pinfo->xres + pinfo->ldi.h_front_porch) * phy_ctrl.lane_byte_clk / pixel_clk; set_reg(mipi_dsi_base + MIPIDSI_VID_HSA_TIME_OFFSET, hsa_time, 12, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_HBP_TIME_OFFSET, hbp_time, 12, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time, 15, 0); /* ** 5. Define the Vertical line configuration: */ set_reg(mipi_dsi_base + MIPIDSI_VID_VSA_LINES_OFFSET, pinfo->ldi.v_pulse_width, 10, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_VBP_LINES_OFFSET, pinfo->ldi.v_back_porch, 10, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_VFP_LINES_OFFSET, pinfo->ldi.v_front_porch, 10, 0); set_reg(mipi_dsi_base + MIPIDSI_VID_VACTIVE_LINES_OFFSET, pinfo->yres, 14, 0); set_reg(mipi_dsi_base + MIPIDSI_TO_CNT_CFG_OFFSET, 0x7FF, 16, 0); /* Configure core's phy parameters */ set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, 4095, 15, 0); set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, phy_ctrl.clk_lane_lp2hs_time, 10, 0); set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_LPCLK_CFG_OFFSET, phy_ctrl.clk_lane_hs2lp_time, 10, 16); set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, phy_ctrl.data_lane_lp2hs_time, 8, 16); set_reg(mipi_dsi_base + MIPIDSI_PHY_TMR_CFG_OFFSET, phy_ctrl.data_lane_hs2lp_time, 8, 24); /*------------DSI and D-PHY Initialization-----------------*/ /* 1. Waking up Core */ set_reg(mipi_dsi_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0); /* ** 3. Configure the TX_ESC clock frequency to a frequency lower than 20 MHz ** that is the maximum allowed frequency for D-PHY ESCAPE mode. */ set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, phy_ctrl.clk_division, 8, 0); set_reg(mipi_dsi_base + MIPIDSI_CLKMGR_CFG_OFFSET, phy_ctrl.clk_division, 8, 8); /* ** 4. Configure the DPHY PLL clock frequency through the TEST Interface to ** operate at XX Hz, */ /* Write CP current */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010011); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.cp_current); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Write LPF Control */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010012); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.lpf_ctrl); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /*Configured N and M factors effective*/ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010019); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.factors_effective); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Write N Pll */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010017); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.n_pll-1); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Write M Pll part 1 */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010018); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.m_pll_1); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Write M Pll part 2 */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010018); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.m_pll_2); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Set hsfreqrange */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010044); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.hsfreqrange); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); /* Set PLL unlocking filter */ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00010016); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, phy_ctrl.pll_unlocking_filter); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); #if 0 /* Set the phy direction*/ outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x000100b0); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL1_OFFSET, 0x00000001); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000002); outp32(mipi_dsi_base + MIPIDSI_PHY_TST_CTRL0_OFFSET, 0x00000000); #endif outp32(mipi_dsi_base + MIPIDSI_PHY_RSTZ_OFFSET, 0x0000000F); is_ready = false; dw_jiffies = jiffies + HZ / 2; do { tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET); if ((tmp & 0x00000001) == 0x00000001) { is_ready = true; break; } } while (time_after(dw_jiffies, jiffies)); if (!is_ready) { HISI_FB_INFO("fb%d, phylock is not ready!MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n", hisifd->index, tmp); } is_ready = false; dw_jiffies = jiffies + HZ / 2; do { tmp = inp32(mipi_dsi_base + MIPIDSI_PHY_STATUS_OFFSET); if ((tmp & 0x00000004) == 0x00000004) { is_ready = true; break; } } while (time_after(dw_jiffies, jiffies)); if (!is_ready) { HISI_FB_INFO("fb%d, phystopstateclklane is not ready! MIPIDSI_PHY_STATUS_OFFSET=0x%x.\n", hisifd->index, tmp); } }