int hisi_pwm_on(struct platform_device *pdev) { int ret = 0; struct clk *clk_tmp = NULL; BUG_ON(pdev == NULL); clk_tmp = g_dss_pwm_clk; if (clk_tmp) { ret = clk_prepare(clk_tmp); if (ret) { HISI_FB_ERR("dss_pwm_clk clk_prepare failed, error=%d!\n", ret); return -EINVAL; } ret = clk_enable(clk_tmp); if (ret) { HISI_FB_ERR("dss_pwm_clk clk_enable failed, error=%d!\n", ret); return -EINVAL; } } ret = pinctrl_cmds_tx(pdev, pwm_pinctrl_normal_cmds, ARRAY_SIZE(pwm_pinctrl_normal_cmds)); return ret; }
static ssize_t vsync_timestamp_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t ret = 0; struct fb_info *fbi = NULL; struct hisi_fb_data_type *hisifd = NULL; 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; } if (NULL == buf) { HISI_FB_ERR("NULL Pointer.\n"); return 0; } ret = snprintf(buf, PAGE_SIZE, "%llu \n", ktime_to_ns(hisifd->vsync_ctrl.vsync_timestamp)); buf[strlen(buf) + 1] = '\0'; return ret; }
int resource_cmds_tx(struct platform_device *pdev, struct resource_desc *cmds, int cnt) { int ret = 0; struct resource *res = NULL; struct resource_desc *cm = NULL; int i = 0; BUG_ON(pdev == NULL); cm = cmds; for (i = 0; i < cnt; i++) { if ((cm == NULL) || (cm->name == NULL)) { HISI_FB_ERR("cm or cm->name is null! index=%d\n", i); ret = -1; goto error; } res = platform_get_resource_byname(pdev, cm->flag, cm->name); if (!res) { HISI_FB_ERR("failed to get %s resource!\n", cm->name); ret = -1; goto error; } *(cm->value) = res->start; cm++; } return 0; error: return cnt; }
void hisifb_backlight_register(struct platform_device *pdev) { struct hisi_fb_data_type *hisifd = NULL; #ifdef CONFIG_FB_BACKLIGHT struct backlight_device *pbd = NULL; struct fb_info *fbi = NULL; char name[16] = {0}; struct backlight_properties props; #endif BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); hisifd->backlight.bl_updated = 0; hisifd->backlight.bl_level_old = 0; hisifd->backlight.frame_updated = 0; sema_init(&hisifd->backlight.bl_sem, 1); #ifdef CONFIG_HISI_FB_BACKLIGHT_DELAY INIT_DELAYED_WORK(&hisifd->backlight.bl_worker, hisifb_bl_workqueue_handler); #endif if (lcd_backlight_registered) return; is_recovery_mode = (int)get_boot_into_recovery_flag(); #ifdef CONFIG_FB_BACKLIGHT fbi = hisifd->fbi; snprintf(name, sizeof(name), "hisifb%d_bl", hisifd->index); props.max_brightness = FB_BACKLIGHT_LEVELS - 1; props.brightness = FB_BACKLIGHT_LEVELS - 1; pbd = backlight_device_register(name, fbi->dev, hisifd, &hisi_fb_bl_ops, &props); if (IS_ERR(pbd)) { fbi->bl_dev = NULL; HISI_FB_ERR("backlight_device_register failed!\n"); } fbi->bl_dev = pbd; fb_bl_default_curve(fbi, 0, hisifd->panel_info.bl_min, hisifd->panel_info.bl_max); #else /* android supports only one lcd-backlight/lcd for now */ if (led_classdev_register(&pdev->dev, &backlight_led)) { HISI_FB_ERR("led_classdev_register failed!\n"); return; } #endif INIT_WORK(&(hisifd->backlight.sbl_work), hisifb_sbl_work); hisifd->backlight.sbl_queue = create_singlethread_workqueue(K3_DSS_SBL_WORKQUEUE); if (!hisifd->backlight.sbl_queue) { HISI_FB_ERR("failed to create sbl_queue!\n"); return ; } lcd_backlight_registered = 1; }
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; }
int set_dss_clk_rate(struct hisi_fb_data_type *hisifd) { int ret = 0; BUG_ON(hisifd == NULL); if (hisifd->dss_pri_clk && (hisifd->dss_clk_rate.dss_pri_clk_rate > 0)) { if (hisifd->dss_clk_rate.dss_pri_clk_rate > DSS_PRI_CLK_RATE_MAX) hisifd->dss_clk_rate.dss_pri_clk_rate = DSS_PRI_CLK_RATE_MAX; ret = clk_set_rate(hisifd->dss_pri_clk, hisifd->dss_clk_rate.dss_pri_clk_rate); if (ret < 0) { HISI_FB_ERR("fb%d dss_pri_clk clk_set_rate(%llu) failed, error=%d!\n", hisifd->index, hisifd->dss_clk_rate.dss_pri_clk_rate, ret); return -EINVAL; } //HISI_FB_INFO("dss_pri_clk:[%llu]->[%llu].\n", // hisifd->dss_clk_rate.dss_pri_clk_rate, clk_get_rate(hisifd->dss_pri_clk)); } if (hisifd->dss_aux_clk && (hisifd->dss_clk_rate.dss_aux_clk_rate > 0)) { if (hisifd->dss_clk_rate.dss_aux_clk_rate > DSS_AUX_CLK_RATE_MAX) hisifd->dss_clk_rate.dss_aux_clk_rate = DSS_AUX_CLK_RATE_MAX; ret = clk_set_rate(hisifd->dss_aux_clk, hisifd->dss_clk_rate.dss_aux_clk_rate); if (ret < 0) { HISI_FB_ERR("fb%d dss_aux_clk_rate clk_set_rate(%llu) failed, error=%d!\n", hisifd->index, hisifd->dss_clk_rate.dss_aux_clk_rate, ret); return -EINVAL; } //HISI_FB_INFO("dss_aux_clk:[%lu]->[%lu].\n", // hisifd->dss_clk_rate.dss_aux_clk_rate, clk_get_rate(hisifd->dss_aux_clk)); } if (hisifd->dss_pclk_clk && (hisifd->dss_clk_rate.dss_pclk_clk_rate > 0)) { if (hisifd->dss_clk_rate.dss_pclk_clk_rate > DSS_PCLK_CLK_RATE_MAX) hisifd->dss_clk_rate.dss_pclk_clk_rate = DSS_PCLK_CLK_RATE_MAX; ret = clk_set_rate(hisifd->dss_pclk_clk, hisifd->dss_clk_rate.dss_pclk_clk_rate); if (ret < 0) { HISI_FB_ERR("fb%d dss_pclk_clk clk_set_rate(%llu) failed, error=%d!\n", hisifd->index, hisifd->dss_clk_rate.dss_pclk_clk_rate, ret); return -EINVAL; } //HISI_FB_INFO("dss_pclk_clk:[%llu]->[%llu].\n", // hisifd->dss_clk_rate.dss_pclk_clk_rate, clk_get_rate(hisifd->dss_pclk_clk)); } return ret; }
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; }
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); 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; } 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; }
static int rgb2mipi_cmd_add(struct spi_device *spi_dev, struct dsi_cmd_desc *cm) { int len = 0; BUG_ON(spi_dev == NULL); BUG_ON(cm == NULL); switch (cm->dtype) { case DTYPE_GEN_WRITE: case DTYPE_GEN_WRITE1: case DTYPE_GEN_WRITE2: case DTYPE_DCS_WRITE: case DTYPE_DCS_WRITE1: len = rgb2mipi_swrite(spi_dev, cm); break; case DTYPE_GEN_LWRITE: case DTYPE_DCS_LWRITE: len = rgb2mipi_lwrite(spi_dev, cm); break; default: HISI_FB_ERR("dtype=%x NOT supported!\n", cm->dtype); break; } return len; }
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_DEBUG("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) { 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_CLK_OFF) { dpe_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)); }
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; }
void init_ifbc(struct hisi_fb_data_type *hisifd) { char __iomem *ifbc_base = NULL; BUG_ON(hisifd == NULL); if (hisifd->index == PRIMARY_PANEL_IDX) { ifbc_base = hisifd->dss_base + DSS_DPP_IFBC_OFFSET; } else { HISI_FB_ERR("fb%d, not support!", hisifd->index); return ; } set_reg(ifbc_base + IFBC_SIZE, ((DSS_WIDTH(hisifd->panel_info.xres) << 16) | DSS_HEIGHT(hisifd->panel_info.yres)), 32, 0); set_reg(ifbc_base + IFBC_CTRL, hisifd->panel_info.ifbc_type, 10, 0); if (hisifd->panel_info.ifbc_type != IFBC_TYPE_NON) { set_reg(ifbc_base + IFBC_EN, 0x3, 2, 0); } else { set_reg(ifbc_base + IFBC_EN, 0x0, 2, 0); } #if 0 set_reg(ifbc_base + IFBC_Himax_CTRL0, 32, 0); set_reg(ifbc_base + IFBC_Himax_CTRL1, 32, 0); set_reg(ifbc_base + IFBC_Himax_CTRL2, 32, 0); set_reg(ifbc_base + IFBC_Himax_CTRL3, 32, 0); set_reg(ifbc_base + IFBC_PM_CTRL, 32, 0); set_reg(ifbc_base + IFBC_MEM_CTRL, 32, 0); set_reg(ifbc_base + IFBC_HIMAX_TEST_MODE, 32, 0); set_reg(ifbc_base + IFBC_CORE_GT, 32, 0); #endif }
struct platform_device *hisi_fb_device_alloc(struct hisi_fb_panel_data *pdata, uint32_t type, uint32_t id) { struct platform_device *this_dev = NULL; char dev_name[32] = {0}; BUG_ON(pdata == NULL); switch (type) { case PANEL_MIPI_VIDEO: case PANEL_MIPI_CMD: snprintf(dev_name, sizeof(dev_name), DEV_NAME_MIPIDSI); break; case PANEL_EDP: snprintf(dev_name, sizeof(dev_name), DEV_NAME_EDP); break; case PANEL_NO: case PANEL_LCDC: case PANEL_HDMI: case PANEL_OFFLINECOMPOSER: case PANEL_WRITEBACK: snprintf(dev_name, sizeof(dev_name), DEV_NAME_DSS_DPE); break; case PANEL_RGB2MIPI: snprintf(dev_name, sizeof(dev_name), DEV_NAME_RGB2MIPI); break; default: HISI_FB_ERR("invalid panel type = %d!\n", type); return NULL; } if (pdata != NULL) pdata->next = NULL; else return NULL; this_dev = platform_device_alloc(dev_name, (((uint32_t)type << 16) | (uint32_t)id)); if (this_dev) { if (platform_device_add_data(this_dev, pdata, sizeof(struct hisi_fb_panel_data))) { HISI_FB_ERR("failed to platform_device_add_data!\n"); platform_device_put(this_dev); return NULL; } } return this_dev; }
static int mipi_dsi_frc_handle(struct platform_device *pdev, int fps) { int ret = 0; #if 0 struct hisi_fb_data_type *hisifd = NULL; struct hisi_panel_info *pinfo = NULL; uint32_t hline_time = 0; uint32_t pixel_clk = 0; uint32_t vertical_timing = 0; uint32_t horizontal_timing = 0; uint32_t h_front_porch = 0; BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); if (hisifd->index != PRIMARY_PANEL_IDX) { HISI_FB_ERR("fb%d, not support!", hisifd->index); return 0; } HISI_FB_DEBUG("fb%d, +.\n", hisifd->index); pinfo = &(hisifd->panel_info); /* calculate new HFP based on target_fps */ vertical_timing = pinfo->yres + pinfo->ldi.v_back_porch + pinfo->ldi.v_front_porch + pinfo->ldi.v_pulse_width; horizontal_timing = pinfo->pxl_clk_rate / (vertical_timing * fps); /* new HFP*/ /* pinfo->ldi.h_front_porch = horizontal_timing - pinfo->xres -pinfo->ldi.h_back_porch - pinfo->ldi.h_pulse_width; */ h_front_porch = horizontal_timing - pinfo->xres -pinfo->ldi.h_back_porch - pinfo->ldi.h_pulse_width; pixel_clk = pinfo->pxl_clk_rate / 1000000; /* update hline_time */ hline_time = (pinfo->ldi.h_pulse_width + pinfo->ldi.h_back_porch + pinfo->xres + h_front_porch) * (pinfo->mipi.dsi_bit_clk / 4) / pixel_clk; /* reset dsi core */ set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x0, 1, 0); set_reg(hisifd->mipi_dsi0_base + MIPIDSI_VID_HLINE_TIME_OFFSET, hline_time, 15, 0); outp32(hisifd->dss_base + PDP_LDI_DPI0_HRZ_CTRL0, h_front_porch | (pinfo->ldi.h_back_porch << 16)); /* power on dsi core */ set_reg(hisifd->mipi_dsi0_base + MIPIDSI_PWR_UP_OFFSET, 0x1, 1, 0); HISI_FB_DEBUG("fb%d, -.\n", hisifd->index); #endif 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 mipi_dsi_clk_enable(struct hisi_fb_data_type *hisifd) { int ret = 0; struct clk *clk_tmp = NULL; BUG_ON(hisifd == NULL); clk_tmp = hisifd->dss_dphy0_clk; if (clk_tmp) { ret = clk_prepare(clk_tmp); if (ret) { HISI_FB_ERR("fb%d dss_dphy0_clk clk_prepare failed, error=%d!\n", hisifd->index, ret); return -EINVAL; } ret = clk_enable(clk_tmp); if (ret) { HISI_FB_ERR("fb%d dss_dphy0_clk clk_enable failed, error=%d!\n", hisifd->index, ret); return -EINVAL; } } if (is_dual_mipi_panel(hisifd)) { clk_tmp = hisifd->dss_dphy1_clk; if (clk_tmp) { ret = clk_prepare(clk_tmp); if (ret) { HISI_FB_ERR("fb%d dss_dphy1_clk clk_prepare failed, error=%d!\n", hisifd->index, ret); return -EINVAL; } ret = clk_enable(clk_tmp); if (ret) { HISI_FB_ERR("fb%d dss_dphy1_clk clk_enable failed, error=%d!\n", hisifd->index, ret); return -EINVAL; } } } return 0; }
void hisifb_vsync_register(struct platform_device *pdev) { struct hisi_fb_data_type *hisifd = NULL; struct hisifb_vsync *vsync_ctrl = NULL; #if defined(CONFIG_HISI_FB_VSYNC_THREAD) char name[64] = {0}; #endif BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); vsync_ctrl = &(hisifd->vsync_ctrl); BUG_ON(vsync_ctrl == NULL); if (vsync_ctrl->vsync_created) return; vsync_ctrl->hisifd = hisifd; vsync_ctrl->vsync_enabled = 0; vsync_ctrl->vsync_timestamp = ktime_get(); init_waitqueue_head(&(vsync_ctrl->vsync_wait)); spin_lock_init(&(vsync_ctrl->spin_lock)); INIT_WORK(&vsync_ctrl->vsync_ctrl_work, hisifb_vsync_ctrl_workqueue_handler); mutex_init(&(vsync_ctrl->vsync_lock)); atomic_set(&(vsync_ctrl->buffer_updated), 1); #ifdef CONFIG_REPORT_VSYNC vsync_ctrl->vsync_report_fnc = mali_kbase_pm_report_vsync; #else vsync_ctrl->vsync_report_fnc = NULL; #endif #ifdef CONFIG_FAKE_VSYNC_USED /* hrtimer for fake vsync timing */ hisifd->fake_vsync_used = false; hrtimer_init(&hisifd->fake_vsync_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); hisifd->fake_vsync_hrtimer.function = hisifb_fake_vsync; hrtimer_start(&hisifd->fake_vsync_hrtimer, ktime_set(0, NSEC_PER_SEC / 60), HRTIMER_MODE_REL); #endif #if defined(CONFIG_HISI_FB_VSYNC_THREAD) snprintf(name, sizeof(name), "hisifb%d_vsync", hisifd->index); vsync_ctrl->vsync_thread = kthread_run(wait_for_vsync_thread, hisifd, name); if (IS_ERR(vsync_ctrl->vsync_thread)) { vsync_ctrl->vsync_thread = NULL; HISI_FB_ERR("failed to run vsync thread!\n"); return; } #else if (hisifd->sysfs_attrs_append_fnc) hisifd->sysfs_attrs_append_fnc(hisifd, &dev_attr_vsync_event.attr); #endif vsync_ctrl->vsync_created = 1; }
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; }
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; }
/******************************************************************************* ** handle isr */ irqreturn_t dss_pdp_isr(int irq, void *ptr) { struct hisi_fb_data_type *hisifd = NULL; uint32_t isr_s1 = 0; uint32_t mask = 0; hisifd = (struct hisi_fb_data_type *)ptr; BUG_ON(hisifd == NULL); isr_s1 = inp32(hisifd->dss_base + GLB_CPU_PDP_INTS); outp32(hisifd->dss_base + GLB_CPU_PDP_INTS, ~0); if (isr_s1 & BIT_VACTIVE0_START) { if (hisifd->ov_vactive0_start_isr_handler) hisifd->ov_vactive0_start_isr_handler(hisifd); } if (isr_s1 & BIT_VSYNC) { if (hisifd->vsync_isr_handler) { hisifd->vsync_isr_handler(hisifd); } if (g_enable_ovl_optimized) { if (hisifd->ov_optimized) hisifd->ov_optimized(hisifd, DSS_OVL0); } if (hisifd->buf_sync_signal) { hisifd->buf_sync_signal(hisifd); } } if (isr_s1 & BIT_BACKLIGHT) { if (hisifd->sbl_isr_handler) { hisifd->sbl_isr_handler(hisifd); } } if (isr_s1 & BIT_LDI_UNFLOW) { if (g_debug_ldi_underflow) { /* ldi disable */ set_reg(hisifd->dss_base + DSS_LDI0_OFFSET + LDI_CTRL, 0, 1, 0); } mask = inp32(hisifd->dss_base + GLB_CPU_PDP_INT_MSK); mask |= BIT_LDI_UNFLOW; outp32(hisifd->dss_base + GLB_CPU_PDP_INT_MSK, mask); HISI_FB_ERR("ldi underflow!\n"); } return IRQ_HANDLED; }
static int __init lcdc_fake_panel_init(void) { int ret = 0; ret = platform_driver_register(&this_driver); if (ret) { HISI_FB_ERR("platform_driver_register failed, error=%d!\n", ret); return ret; } return ret; }
static int __init hisi_spi_init(void) { int ret = 0; ret = spi_register_driver(&this_driver); if (ret) { HISI_FB_ERR("spi_register_driver failed, error=%d!\n", ret); return ret; } return ret; }
void hisifb_activate_vsync(struct hisi_fb_data_type *hisifd) { struct hisi_fb_panel_data *pdata = NULL; struct hisifb_vsync *vsync_ctrl = NULL; unsigned long flags = 0; int clk_enabled = 0; 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); if (hisifd->panel_info.vsync_ctrl_type == VSYNC_CTRL_NONE) return; mutex_lock(&(vsync_ctrl->vsync_lock)); if (vsync_ctrl->vsync_ctrl_enabled == 0) { HISI_FB_DEBUG("fb%d, dss clk on!\n", hisifd->index); if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_VCC_OFF) { dpe_regulator_enable(hisifd); } if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_CLK_OFF) { mipi_dsi_clk_enable(hisifd); dpe_clk_enable(hisifd); } if (hisifd->panel_info.vsync_ctrl_type & VSYNC_CTRL_MIPI_ULPS) { mipi_dsi_ulps_cfg(hisifd, 1); } vsync_ctrl->vsync_ctrl_enabled = 1; clk_enabled = 1; } spin_lock_irqsave(&(vsync_ctrl->spin_lock), flags); vsync_ctrl->vsync_ctrl_disabled_set = 0; vsync_ctrl->vsync_ctrl_expire_count = 0; if (clk_enabled) { if (pdata->vsync_ctrl) { pdata->vsync_ctrl(hisifd->pdev, 1); } else { HISI_FB_ERR("fb%d, vsync_ctrl not supported!\n", hisifd->index); } } spin_unlock_irqrestore(&(vsync_ctrl->spin_lock), flags); mutex_unlock(&(vsync_ctrl->vsync_lock)); }
bool hisi_fb_device_probe_defer(uint32_t panel_type) { bool flag = true; down(&hisi_fb_dts_resource_sem); switch (panel_type) { case PANEL_NO: if(g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) { flag = false; } break; case PANEL_LCDC: case PANEL_MIPI2RGB: case PANEL_RGB2MIPI: if ((g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) && (g_dts_resouce_ready & DTS_PWM_READY) && (g_dts_resouce_ready & DTS_SPI_READY)) { flag = false; } break; case PANEL_MIPI_VIDEO: case PANEL_MIPI_CMD: case PANEL_DUAL_MIPI_VIDEO: case PANEL_DUAL_MIPI_CMD: case PANEL_EDP: if ((g_dts_resouce_ready & DTS_FB_RESOURCE_INIT_READY) && (g_dts_resouce_ready & DTS_PWM_READY)) { flag = false; } break; case PANEL_HDMI: if (g_dts_resouce_ready & DTS_PANEL_PRIMARY_READY) flag = false; break; case PANEL_OFFLINECOMPOSER: if (g_dts_resouce_ready & DTS_PANEL_EXTERNAL_READY) flag = false; break; case PANEL_WRITEBACK: if (g_dts_resouce_ready & DTS_PANEL_OFFLINECOMPOSER_READY) flag = false; break; default: HISI_FB_ERR("not support this panel type(%d).\n", panel_type); break; } up(&hisi_fb_dts_resource_sem); return flag; }
int hisi_pwm_on(struct platform_device *pdev) { int ret = 0; struct clk *clk_tmp = NULL; BUG_ON(pdev == NULL); clk_tmp = g_dss_pwm_clk; if (clk_tmp) { ret = clk_prepare(clk_tmp); if (ret) { HISI_FB_ERR("dss_pwm_clk clk_prepare failed, error=%d!\n", ret); return -EINVAL; } ret = clk_enable(clk_tmp); if (ret) { HISI_FB_ERR("dss_pwm_clk clk_enable failed, error=%d!\n", ret); return -EINVAL; } } ret = pinctrl_cmds_tx(g_pwm_pdev, pwm_pinctrl_normal_cmds, ARRAY_SIZE(pwm_pinctrl_normal_cmds)); #ifdef CONFIG_BACKLIGHT_10000 init_bl_info(); cabc_pwm_task = kthread_create(cabc_pwm_thread, NULL, "cabc_pwm_task"); if(IS_ERR(cabc_pwm_task)) { HISI_FB_ERR("Unable to start kernel cabc_pwm_task./n"); cabc_pwm_task = NULL; return -EINVAL; } #endif return ret; }
static ssize_t mipi_dsi_bit_clk_upt_store(struct platform_device *pdev, const char *buf, size_t count) { struct hisi_fb_data_type *hisifd = NULL; struct hisi_panel_info *pinfo = NULL; BUG_ON(pdev == NULL); hisifd = platform_get_drvdata(pdev); BUG_ON(hisifd == NULL); pinfo = &(hisifd->panel_info); if (!hisifd->panel_info.dsi_bit_clk_upt_support) { HISI_FB_ERR("fb%d, not support!", hisifd->index); return count; } HISI_FB_DEBUG("fb%d, +.\n", hisifd->index); if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR1, count)) { pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val1; } else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR2, count)) { pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val2; } else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR3, count)) { pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val3; } else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR4, count)) { pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val4; } else if (!strncmp(buf, MIPI_DSI_BIT_CLK_STR5, count)) { pinfo->mipi.dsi_bit_clk_upt = pinfo->mipi.dsi_bit_clk_val5; } else { HISI_FB_ERR("fb%d, unknown dsi_bit_clk_index!\n", hisifd->index); } HISI_FB_DEBUG("fb%d, -.\n", hisifd->index); return count; }
void hisi_dss_mctl_ov_set_ctl_dbg_reg(struct hisi_fb_data_type *hisifd, char __iomem *mctl_dgb) { if (hisifd == NULL) { HISI_FB_ERR("hisifd is null"); return; } if (is_mipi_cmd_panel(hisifd) && (hisifd->ldi_data_gate_en == 1)) { //open underflow clear set_reg(mctl_dgb, 0x782620, 32, 0); } else { //open underflow clear set_reg(mctl_dgb, 0x70A620, 32, 0); //set_reg(mctl_dgb, 0xB02620, 32, 0); } }
void init_dpp(struct hisi_fb_data_type *hisifd) { char __iomem *dpp_base = NULL; BUG_ON(hisifd == NULL); if (hisifd->index == PRIMARY_PANEL_IDX) { dpp_base = hisifd->dss_base + DSS_DPP0_CTRL_OFFSET; } else { HISI_FB_ERR("fb%d, not support!", hisifd->index); return ; } set_reg(dpp_base + DPP_IMG_HRZ, DSS_WIDTH(hisifd->panel_info.xres), 13, 0); set_reg(dpp_base + DPP_IMG_VRT, DSS_HEIGHT(hisifd->panel_info.yres), 13, 0); #ifdef CONFIG_FIX_DIRTY_REGION_UPDT if (is_mipi_cmd_panel(hisifd)) { outp32(dpp_base + DPP_CLK_GT, 0xA); } #endif }
int hisi_fb_device_set_status1(struct hisi_fb_data_type *hisifd) { int ret = 0; BUG_ON(hisifd == NULL); down(&hisi_fb_dts_resource_sem); switch (hisifd->panel_info.type) { case PANEL_LCDC: case PANEL_MIPI_VIDEO: case PANEL_MIPI_CMD: case PANEL_DUAL_MIPI_VIDEO: case PANEL_DUAL_MIPI_CMD: case PANEL_EDP: case PANEL_MIPI2RGB: case PANEL_RGB2MIPI: g_dts_resouce_ready |= DTS_PANEL_PRIMARY_READY; break; case PANEL_HDMI: g_dts_resouce_ready |= DTS_PANEL_EXTERNAL_READY; break; case PANEL_OFFLINECOMPOSER: g_dts_resouce_ready |= DTS_PANEL_OFFLINECOMPOSER_READY; break; case PANEL_WRITEBACK: g_dts_resouce_ready |= DTS_PANEL_WRITEBACK_READY; break; default: HISI_FB_ERR("not support this panel type(%d).\n", hisifd->panel_info.type); ret = -1; break; } up(&hisi_fb_dts_resource_sem); return ret; }
void dss_underflow_debug_func(struct work_struct *work) { struct clk *ddr_clk = NULL; unsigned long curr_ddr = 0; struct hisi_fb_data_type *hisifd = NULL; static u32 underflow_index = 0; static ktime_t underflow_timestamp[UNDERFLOW_EXPIRE_COUNT]; s64 underflow_msecs = 0; static bool init_underflow_timestamp = false; int i; if (!init_underflow_timestamp) { underflow_timestamp[underflow_index] = ktime_get(); underflow_index ++; } if (underflow_index == UNDERFLOW_EXPIRE_COUNT) { init_underflow_timestamp = true; underflow_timestamp[UNDERFLOW_EXPIRE_COUNT - 1] = ktime_get(); underflow_msecs = ktime_to_ms(underflow_timestamp[UNDERFLOW_EXPIRE_COUNT - 1]) - ktime_to_ms(underflow_timestamp[0]); for(i = 0; i < UNDERFLOW_EXPIRE_COUNT - 1; i ++) underflow_timestamp[i] = underflow_timestamp[i+1]; } ddr_clk = clk_get(NULL, "clk_ddrc_freq"); if (ddr_clk) { curr_ddr = clk_get_rate(ddr_clk); clk_put(ddr_clk); } else { HISI_FB_ERR("Get ddr clk failed"); } if (work) { hisifd = container_of(work, struct hisi_fb_data_type, dss_underflow_debug_work); if (g_underflow_stop_perf_stat) { dumpDssOverlay(hisifd, &hisifd->ov_req, false); } } else {