int s3cfb_open_fifo(int id, int ch, int (*do_priv) (void *), void *param) { struct s3cfb_global *fbdev = get_fimd_global(id); struct s3cfb_window *win = fbdev->fb[id]->par; dev_dbg(fbdev->dev, "[fb%d] open fifo\n", win->id); if (win->path == DATA_PATH_DMA) { dev_err(fbdev->dev, "WIN%d is busy.\n", id); return -EFAULT; } win->local_channel = ch; if (do_priv) { if (do_priv(param)) { dev_err(fbdev->dev, "failed to run for " "private fifo open\n"); s3cfb_enable_window(fbdev, id); return -EFAULT; } } s3cfb_set_window_control(fbdev, id); s3cfb_enable_window(fbdev, id); s3cfb_enable_localpath(fbdev, id); return 0; }
static int lcdfreq_lock(struct device *dev) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; int ret; if (!atomic_read(&lcdfreq->usage)) ret = set_lcdfreq_div(dev, LEVEL_LIMIT); else { dev_err(dev, "lcd freq is already limit state\n"); return -EINVAL; } if (!ret) { mutex_lock(&lcdfreq->lock); atomic_inc(&lcdfreq->usage); mutex_unlock(&lcdfreq->lock); schedule_delayed_work(&lcdfreq->work, 0); } return ret; }
static int lcdfreq_lock_free(struct device *dev) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; int ret; if (atomic_read(&lcdfreq->usage)) ret = set_lcdfreq_div(dev, LEVEL_NORMAL); else { dev_err(dev, "lcd freq is already normal state\n"); return -EINVAL; } if (!ret) { mutex_lock(&lcdfreq->lock); atomic_dec(&lcdfreq->usage); mutex_unlock(&lcdfreq->lock); cancel_delayed_work(&lcdfreq->work); } return ret; }
int s3cfb_open(struct fb_info *fb, int user) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); int ret = 0; mutex_lock(&fbdev->lock); if (atomic_read(&win->in_use)) { if (win->id == pdata->default_win) { dev_dbg(fbdev->dev, "mutiple open for default window\n"); ret = 0; } else { dev_dbg(fbdev->dev, "do not allow multiple open for non-default window\n"); ret = -EBUSY; } } else { atomic_inc(&win->in_use); } mutex_unlock(&fbdev->lock); return ret; }
int s3cfb_close_fifo(int id, int (*do_priv) (void *), void *param) { struct s3cfb_global *fbdev = get_fimd_global(id); struct s3cfb_window *win = fbdev->fb[id]->par; win->path = DATA_PATH_DMA; dev_dbg(fbdev->dev, "[fb%d] close fifo\n", win->id); if (do_priv) { s3cfb_display_off(fbdev); if (do_priv(param)) { dev_err(fbdev->dev, "failed to run for" "private fifo close\n"); s3cfb_enable_window(fbdev, id); s3cfb_display_on(fbdev); return -EFAULT; } s3cfb_disable_window(fbdev, id); s3cfb_disable_localpath(fbdev, id); s3cfb_display_on(fbdev); } else { s3cfb_disable_window(fbdev, id); s3cfb_disable_localpath(fbdev, id); } return 0; }
static ssize_t freq_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct s3cfb_lcd *lcd = fbdev->lcd; struct s3cfb_lcd_timing *timing = &lcd->timing; struct fb_var_screeninfo *var = &fb->var; lcd->freq_limit = 0; sscanf(buf, "%d %d %d %d", &lcd->freq, &timing->h_fp, &timing->h_bp, &timing->h_sw); var->hsync_len = timing->h_sw; var->left_margin = timing->h_bp; var->right_margin = timing->h_fp; var->pixclock = (lcd->freq * (var->left_margin + var->right_margin + var->hsync_len + var->xres) * (var->upper_margin + var->lower_margin + var->vsync_len + var->yres)); var->pixclock = KHZ2PICOS(var->pixclock/1000); s5p_dsim_set_lcd_freq_change(timing); return count; }
int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) { struct s3cfb_global *fbdev = get_fimd_global(fb->node); s3cfb_check_var_window(fbdev, var, fb); return 0; }
int s3cfb_set_par(struct fb_info *fb) { struct s3cfb_global *fbdev = get_fimd_global(fb->node); s3cfb_set_par_window(fbdev, fb); return 0; }
int s3cfb_set_par(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); s3cfb_set_par_window(fbdev, fb); return 0; }
int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); s3cfb_check_var_window(fbdev, var, fb); return 0; }
static ssize_t usage_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; return sprintf(buf, "%d\n", atomic_read(&lcdfreq->usage)); }
static ssize_t freq_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct s3cfb_lcd *lcd = fbdev->lcd; return sprintf(buf, "%dhz, hfp=%d, hbp=%d, hsw=%d, div=%d\n", lcd->freq, lcd->timing.h_fp, lcd->timing.h_bp, lcd->timing.h_sw, get_div(fbdev)+1); }
int fb_is_primary_device(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); dev_dbg(fbdev->dev, "[fb%d] checking for primary device\n", win->id); if (win->id == pdata->default_win) return 1; else return 0; }
int s3cfb_release(struct fb_info *fb, int user) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); s3cfb_release_window(fb); mutex_lock(&fbdev->lock); atomic_dec(&win->in_use); mutex_unlock(&fbdev->lock); return 0; }
static ssize_t time_in_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; do_time_slice(lcdfreq->level); return sprintf(buf, "%llu %d (60Hz)\n%llu %d (40Hz)\n", (unsigned long long)time_in_state[LEVEL_NORMAL], LEVEL_NORMAL, (unsigned long long)time_in_state[LEVEL_LIMIT], LEVEL_LIMIT); }
static ssize_t level_show(struct device *dev, struct device_attribute *attr, char *buf) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) { dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable); return -EINVAL; } return sprintf(buf, "%dhz, div=%d\n", lcdfreq->table[lcdfreq->level].hz, get_div(fbdev)); }
int s3cfb_set_par(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); int ret = 0; #ifdef CONFIG_EXYNOS_DEV_PD struct platform_device *pdev = to_platform_device(fbdev->dev); pm_runtime_get_sync(&pdev->dev); #endif ret = s3cfb_set_par_window(fbdev, fb); #ifdef CONFIG_EXYNOS_DEV_PD pm_runtime_put(&pdev->dev); #endif return ret; }
int s3cfb_release_window(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); if (win->id != pdata->default_win) { s3cfb_disable_window(fbdev, win->id); s3cfb_unmap_video_memory(fbdev, fb); s3cfb_set_buffer_address(fbdev, win->id); } win->x = 0; win->y = 0; return 0; }
int s3cfb_set_par(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); int ret = 0; #ifdef CONFIG_EXYNOS_DEV_PD if (unlikely(fbdev->system_state == POWER_OFF)) { dev_err(fbdev->dev, "%s::system_state is POWER_OFF, fb%d\n", __func__, win->id); return 0; } #endif ret = s3cfb_set_par_window(fbdev, fb); return ret; }
int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); if (var->yoffset + var->yres > var->yres_virtual) { dev_err(fbdev->dev, "invalid yoffset value\n"); return -EINVAL; } fb->var.yoffset = var->yoffset; dev_dbg(fbdev->dev, "[fb%d] yoffset for pan display: %d\n", win->id, var->yoffset); s3cfb_set_buffer_address(fbdev, win->id); return 0; }
static int set_lcdfreq_div(struct device *dev, enum lcdfreq_level_idx level) { struct fb_info *fb = dev_get_drvdata(dev); struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; u32 div, ret; mutex_lock(&lcdfreq->lock); if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) { dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable); ret = -EINVAL; goto exit; } div = lcdfreq->table[level].cmu_clkdiv; ret = set_div(fbdev, div); if (ret) { dev_err(dev, "fail to change lcd freq\n"); goto exit; } #ifdef CONFIG_LCD_FREQ_SWITCH_ACCOUNTING do_time_slice(lcdfreq->level); #endif lcdfreq->level = level; exit: mutex_unlock(&lcdfreq->lock); return ret; }
int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) { struct fb_var_screeninfo *var = &fb->var; struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(fb->node); struct s3cfb_lcd *lcd = fbdev->lcd; int ret = 0; union { struct s3cfb_user_window user_window; struct s3cfb_user_plane_alpha user_alpha; struct s3cfb_user_chroma user_chroma; int vsync; } p; switch (cmd) { case FBIO_WAITFORVSYNC: s3cfb_wait_for_vsync(fbdev); break; case S3CFB_WIN_POSITION: if (copy_from_user(&p.user_window, (struct s3cfb_user_window __user *)arg, sizeof(p.user_window))) ret = -EFAULT; else { if (p.user_window.x < 0) p.user_window.x = 0; if (p.user_window.y < 0) p.user_window.y = 0; if (p.user_window.x + var->xres > lcd->width) win->x = lcd->width - var->xres; else win->x = p.user_window.x; if (p.user_window.y + var->yres > lcd->height) win->y = lcd->height - var->yres; else win->y = p.user_window.y; s3cfb_set_window_position(fbdev, win->id); } break; case S3CFB_WIN_SET_PLANE_ALPHA: if (copy_from_user(&p.user_alpha, (struct s3cfb_user_plane_alpha __user *)arg, sizeof(p.user_alpha))) ret = -EFAULT; else { win->alpha.mode = PLANE_BLENDING; win->alpha.channel = p.user_alpha.channel; win->alpha.value = S3CFB_AVALUE(p.user_alpha.red, p.user_alpha.green, p.user_alpha.blue); s3cfb_set_alpha_blending(fbdev, win->id); } break; case S3CFB_WIN_SET_CHROMA: if (copy_from_user(&p.user_chroma, (struct s3cfb_user_chroma __user *)arg, sizeof(p.user_chroma))) ret = -EFAULT; else { win->chroma.enabled = p.user_chroma.enabled; win->chroma.key = S3CFB_CHROMA(p.user_chroma.red, p.user_chroma.green, p.user_chroma.blue); s3cfb_set_chroma_key(fbdev, win->id); } break; case S3CFB_SET_VSYNC_INT: if (get_user(p.vsync, (int __user *)arg)) ret = -EFAULT; else { if (p.vsync) s3cfb_set_global_interrupt(fbdev, 1); s3cfb_set_vsync_interrupt(fbdev, p.vsync); } break; #if MALI_USE_UNIFIED_MEMORY_PROVIDER case S3CFB_GET_FB_UMP_SECURE_ID_0: { u32 __user *psecureid = (u32 __user *) arg; ump_secure_id secure_id; dev_info(fbdev->dev, "ump_dd_secure_id_get\n"); secure_id = ump_dd_secure_id_get(ump_wrapped_buffer); dev_info(fbdev->dev, "Saving secure id 0x%x in userptr %p\n" , (unsigned int)secure_id, psecureid); dev_dbg(fbdev->dev, "Saving secure id 0x%x in userptr %p\n" , (unsigned int)secure_id, psecureid); return put_user((unsigned int)secure_id, psecureid); } break; #endif } return ret; }
int s3cfb_direct_ioctl(int id, unsigned int cmd, unsigned long arg) { struct s3cfb_global *fbdev = get_fimd_global(id); struct fb_info *fb = fbdev->fb[id]; struct fb_var_screeninfo *var = &fb->var; struct fb_fix_screeninfo *fix = &fb->fix; struct s3cfb_window *win = fb->par; struct s3cfb_lcd *lcd = fbdev->lcd; struct s3cfb_user_window user_win; void *argp = (void *)arg; int ret = 0; switch (cmd) { case FBIOGET_FSCREENINFO: ret = memcpy(argp, &fb->fix, sizeof(fb->fix)) ? 0 : -EFAULT; break; case FBIOGET_VSCREENINFO: ret = memcpy(argp, &fb->var, sizeof(fb->var)) ? 0 : -EFAULT; break; case FBIOPUT_VSCREENINFO: ret = s3cfb_check_var((struct fb_var_screeninfo *)argp, fb); if (ret) { dev_err(fbdev->dev, "invalid vscreeninfo\n"); break; } ret = memcpy(&fb->var, (struct fb_var_screeninfo *)argp, sizeof(fb->var)) ? 0 : -EFAULT; if (ret) { dev_err(fbdev->dev, "failed to put new vscreeninfo\n"); break; } fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; fix->smem_len = fix->line_length * var->yres_virtual; s3cfb_set_win_params(fbdev, id); break; case S3CFB_WIN_POSITION: ret = memcpy(&user_win, (struct s3cfb_user_window __user *)arg, sizeof(user_win)) ? 0 : -EFAULT; if (ret) { dev_err(fbdev->dev, "failed to S3CFB_WIN_POSITION\n"); break; } if (user_win.x < 0) user_win.x = 0; if (user_win.y < 0) user_win.y = 0; if (user_win.x + var->xres > lcd->width) win->x = lcd->width - var->xres; else win->x = user_win.x; if (user_win.y + var->yres > lcd->height) win->y = lcd->height - var->yres; else win->y = user_win.y; s3cfb_set_window_position(fbdev, win->id); break; case S3CFB_GET_LCD_WIDTH: ret = memcpy(argp, &lcd->width, sizeof(int)) ? 0 : -EFAULT; if (ret) { dev_err(fbdev->dev, "failed to S3CFB_GET_LCD_WIDTH\n"); break; } break; case S3CFB_GET_LCD_HEIGHT: ret = memcpy(argp, &lcd->height, sizeof(int)) ? 0 : -EFAULT; if (ret) { dev_err(fbdev->dev, "failed to S3CFB_GET_LCD_HEIGHT\n"); break; } break; case S3CFB_SET_WRITEBACK: if ((u32)argp == 1) fbdev->output = OUTPUT_WB_RGB; else fbdev->output = OUTPUT_RGB; s3cfb_set_output(fbdev); break; case S3CFB_SET_WIN_ON: s3cfb_enable_window(fbdev, id); break; case S3CFB_SET_WIN_OFF: s3cfb_disable_window(fbdev, id); break; case S3CFB_SET_WIN_PATH: win->path = (enum s3cfb_data_path_t)argp; break; case S3CFB_SET_WIN_ADDR: fix->smem_start = (unsigned long)argp; s3cfb_set_buffer_address(fbdev, id); break; case S3CFB_SET_WIN_MEM: win->owner = (enum s3cfb_mem_owner_t)argp; break; case S3CFB_SET_VSYNC_INT: if (argp) s3cfb_set_global_interrupt(fbdev, 1); s3cfb_set_vsync_interrupt(fbdev, (int)argp); break; case S3CFB_GET_VSYNC_INT_STATUS: ret = s3cfb_get_vsync_interrupt(fbdev); break; default: ret = s3cfb_ioctl(fb, cmd, arg); break; } return ret; }
int get_divider(struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_global *fbdev = get_fimd_global(win->id); struct lcdfreq_info *lcdfreq = fbdev->data; struct clksrc_clk *sclk; struct clk *clk; u32 rate, reg, i; u8 fimd_div; sclk = container_of(fbdev->clock, struct clksrc_clk, clk); clk = clk_get_parent(clk_get_parent(fbdev->clock)); rate = clk_get_rate(clk); lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_NORMAL].vclk); lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv = DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_LIMIT].vclk); fimd_div = gcd(lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv, lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv); if ((!fimd_div) || (fimd_div > 16)) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv /= fimd_div; lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv /= fimd_div; dev_info(fb->dev, "%s rate is %d, fimd divider=%d\n", clk->name, rate, fimd_div); fimd_div--; for (i = 0; i < LCDFREQ_LEVEL_END; i++) { if (lcdfreq->table[i].cmu_clkdiv > 16) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } dev_info(fb->dev, "%dhz div is %d\n", lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv); lcdfreq->table[i].cmu_clkdiv--; } reg = (readl(fbdev->regs + S3C_VIDCON0) & (S3C_VIDCON0_CLKVAL_F(0xff))) >> 6; if (fimd_div != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } reg = (readl(sclk->reg_div.reg)) >> sclk->reg_div.shift; reg &= 0xf; if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) { dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__); goto err; } return 0; err: return -EINVAL; }
int s3cfb_blank(int blank_mode, struct fb_info *fb) { struct s3cfb_window *win = fb->par; struct s3cfb_window *tmp_win; struct s3cfb_global *fbdev = get_fimd_global(fb->node); struct platform_device *pdev = to_platform_device(fbdev->dev); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); int enabled_win = 0; int i; dev_dbg(fbdev->dev, "change blank mode\n"); switch (blank_mode) { case FB_BLANK_UNBLANK: if (!fb->fix.smem_start) { dev_info(fbdev->dev, \ "[fb%d] no allocated memory for unblank\n", win->id); break; } if (win->power_state == FB_BLANK_UNBLANK) { dev_info(fbdev->dev, \ "[fb%d] already in FB_BLANK_UNBLANK\n", win->id); break; } else { s3cfb_update_power_state(fbdev, win->id, FB_BLANK_UNBLANK); } enabled_win = atomic_read(&fbdev->enabled_win); if (enabled_win == 0) { pdata->clk_on(pdev, &fbdev->clock); s3cfb_init_global(fbdev); s3cfb_set_clock(fbdev); for (i = 0; i < pdata->nr_wins; i++) { tmp_win = fbdev->fb[i]->par; if (tmp_win->owner == DMA_MEM_FIMD) s3cfb_set_win_params(fbdev, tmp_win->id); } } if (win->enabled) /* from FB_BLANK_NORMAL */ s3cfb_win_map_off(fbdev, win->id); else /* from FB_BLANK_POWERDOWN */ s3cfb_enable_window(fbdev, win->id); if (enabled_win == 0) { s3cfb_display_on(fbdev); if (pdata->backlight_on) pdata->backlight_on(pdev); if (pdata->lcd_on) pdata->lcd_on(pdev); if (fbdev->lcd->init_ldi) fbdev->lcd->init_ldi(); } break; case FB_BLANK_NORMAL: if (win->power_state == FB_BLANK_NORMAL) { dev_info(fbdev->dev, \ "[fb%d] already in FB_BLANK_NORMAL\n", win->id); break; } else { s3cfb_update_power_state(fbdev, win->id, FB_BLANK_NORMAL); } enabled_win = atomic_read(&fbdev->enabled_win); if (enabled_win == 0) { pdata->clk_on(pdev, &fbdev->clock); s3cfb_init_global(fbdev); s3cfb_set_clock(fbdev); for (i = 0; i < pdata->nr_wins; i++) { tmp_win = fbdev->fb[i]->par; if (tmp_win->owner == DMA_MEM_FIMD) s3cfb_set_win_params(fbdev, tmp_win->id); } } s3cfb_win_map_on(fbdev, win->id, 0x0); if (!win->enabled) /* from FB_BLANK_POWERDOWN */ s3cfb_enable_window(fbdev, win->id); if (enabled_win == 0) { s3cfb_display_on(fbdev); if (pdata->backlight_on) pdata->backlight_on(pdev); if (pdata->lcd_on) pdata->lcd_on(pdev); if (fbdev->lcd->init_ldi) fbdev->lcd->init_ldi(); } break; case FB_BLANK_POWERDOWN: if (win->power_state == FB_BLANK_POWERDOWN) { dev_info(fbdev->dev, \ "[fb%d] already in FB_BLANK_POWERDOWN\n", win->id); break; } else { s3cfb_update_power_state(fbdev, win->id, FB_BLANK_POWERDOWN); } s3cfb_disable_window(fbdev, win->id); s3cfb_win_map_off(fbdev, win->id); if (atomic_read(&fbdev->enabled_win) == 0) { if (pdata->backlight_off) pdata->backlight_off(pdev); if (fbdev->lcd->deinit_ldi) fbdev->lcd->deinit_ldi(); if (pdata->lcd_off) pdata->lcd_off(pdev); s3cfb_display_off(fbdev); pdata->clk_off(pdev, &fbdev->clock); } break; case FB_BLANK_VSYNC_SUSPEND: /* fall through */ case FB_BLANK_HSYNC_SUSPEND: /* fall through */ default: dev_dbg(fbdev->dev, "unsupported blank mode\n"); return -EINVAL; } return 0; }