int s3cfb_init_win(s3c_fb_info_t *fbi, int bpp, int left_x, int top_y, int width, int height, int onoff) { s3cfb_onoff_win(fbi, OFF); s3cfb_set_bpp(fbi, bpp); s3cfb_set_win_position(fbi, left_x, top_y, width, height); s3cfb_set_win_size(fbi, width, height); s3cfb_set_fb_size(fbi); s3cfb_onoff_win(fbi, onoff); return 0; }
int s3cfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { s3cfb_info_t *fbi = container_of(info, s3cfb_info_t, fb); s3cfb_win_info_t win_info; s3cfb_color_key_info_t colkey_info; s3cfb_color_val_info_t colval_info; s3cfb_dma_info_t dma_info; s3cfb_next_info_t next_fb_info; struct fb_var_screeninfo *var= &fbi->fb.var; unsigned int crt, alpha_level, alpha_mode; #if defined(CONFIG_S3C6410_PWM) int brightness; #endif #if defined(CONFIG_FB_S3C_DOUBLE_BUFFERING) unsigned int f_num_val; #endif #if defined(CONFIG_FB_S3C_VIRTUAL_SCREEN) s3cfb_vs_info_t vs_info; #endif switch(cmd){ case S3CFB_GET_INFO: dma_info.map_dma_f1 = fbi->map_dma_f1; dma_info.map_dma_f2 = fbi->map_dma_f2; if(copy_to_user((void *) arg, (const void *) &dma_info, sizeof(s3cfb_dma_info_t))) return -EFAULT; break; case S3CFB_OSD_SET_INFO: if (copy_from_user(&win_info, (s3cfb_win_info_t *) arg, sizeof(s3cfb_win_info_t))) return -EFAULT; s3cfb_init_win(fbi, win_info.bpp, win_info.left_x, win_info.top_y, win_info.width, win_info.height, OFF); break; case S3CFB_OSD_START: s3cfb_onoff_win(fbi, ON); break; case S3CFB_OSD_STOP: s3cfb_onoff_win(fbi, OFF); break; case S3CFB_OSD_ALPHA_UP: alpha_level = readl(S3C_VIDOSD0C + (0x10 * fbi->win_id)) & 0xf; if (alpha_level < S3CFB_MAX_ALPHA_LEVEL) alpha_level++; s3cfb_set_alpha_level(fbi, alpha_level, 1); break; case S3CFB_OSD_ALPHA_DOWN: alpha_level = readl(S3C_VIDOSD0C + (0x10 * fbi->win_id)) & 0xf; if (alpha_level > 0) alpha_level--; s3cfb_set_alpha_level(fbi, alpha_level, 1); break; case S3CFB_OSD_ALPHA0_SET: alpha_level = (unsigned int) arg; if (alpha_level > S3CFB_MAX_ALPHA_LEVEL) alpha_level = S3CFB_MAX_ALPHA_LEVEL; s3cfb_set_alpha_level(fbi, alpha_level, 0); break; case S3CFB_OSD_ALPHA1_SET: alpha_level = (unsigned int) arg; if (alpha_level > S3CFB_MAX_ALPHA_LEVEL) alpha_level = S3CFB_MAX_ALPHA_LEVEL; s3cfb_set_alpha_level(fbi, alpha_level, 1); break; case S3CFB_OSD_ALPHA_MODE: alpha_mode = (unsigned int) arg; s3cfb_set_alpha_mode(fbi, alpha_mode); break; case S3CFB_OSD_MOVE_LEFT: if (var->xoffset > 0) var->xoffset--; s3cfb_set_win_position(fbi, var->xoffset, var->yoffset, var->xres, var->yres); break; case S3CFB_OSD_MOVE_RIGHT: if (var->xoffset < (s3cfb_fimd.width - var->xres)) var->xoffset++; s3cfb_set_win_position(fbi, var->xoffset, var->yoffset, var->xres, var->yres); break; case S3CFB_OSD_MOVE_UP: if (var->yoffset > 0) var->yoffset--; s3cfb_set_win_position(fbi, var->xoffset, var->yoffset, var->xres, var->yres); break; case S3CFB_OSD_MOVE_DOWN: if (var->yoffset < (s3cfb_fimd.height - var->yres)) var->yoffset++; s3cfb_set_win_position(fbi, var->xoffset, var->yoffset, var->xres, var->yres); break; case FBIO_WAITFORVSYNC: if (get_user(crt, (unsigned int __user *)arg)) return -EFAULT; return s3cfb_wait_for_vsync(); case S3CFB_COLOR_KEY_START: s3cfb_onoff_color_key(fbi, ON); break; case S3CFB_COLOR_KEY_STOP: s3cfb_onoff_color_key(fbi, OFF); break; case S3CFB_COLOR_KEY_ALPHA_START: s3cfb_onoff_color_key_alpha(fbi, ON); break; case S3CFB_COLOR_KEY_ALPHA_STOP: s3cfb_onoff_color_key_alpha(fbi, OFF); break; case S3CFB_COLOR_KEY_SET_INFO: if (copy_from_user(&colkey_info, (s3cfb_color_key_info_t *) arg, sizeof(s3cfb_color_key_info_t))) return -EFAULT; s3cfb_set_color_key_registers(fbi, colkey_info); break; case S3CFB_COLOR_KEY_VALUE: if (copy_from_user(&colval_info, (s3cfb_color_val_info_t *) arg, sizeof(s3cfb_color_val_info_t))) return -EFAULT; s3cfb_set_color_value(fbi, colval_info); break; case S3CFB_SET_VSYNC_INT: s3cfb_fimd.vidintcon0 &= ~S3C_VIDINTCON0_FRAMESEL0_MASK; s3cfb_fimd.vidintcon0 |= S3C_VIDINTCON0_FRAMESEL0_VSYNC; if (arg) s3cfb_fimd.vidintcon0 |= S3C_VIDINTCON0_INTFRMEN_ENABLE; else s3cfb_fimd.vidintcon0 &= ~S3C_VIDINTCON0_INTFRMEN_ENABLE; writel(s3cfb_fimd.vidintcon0, S3C_VIDINTCON0); break; case S3CFB_SET_NEXT_FB_INFO: if (copy_from_user(&next_fb_info, (s3cfb_next_info_t *) arg, sizeof(s3cfb_next_info_t))) return -EFAULT; if ((next_fb_info.xres + next_fb_info.xoffset) > next_fb_info.xres_virtual || (next_fb_info.yres + next_fb_info.yoffset) > next_fb_info.yres_virtual || (next_fb_info.xres + next_fb_info.lcd_offset_x ) > s3cfb_fimd.width || (next_fb_info.yres + next_fb_info.lcd_offset_y ) > s3cfb_fimd.height) { printk("Error : S3CFB_SET_NEXT_FB_INFO\n"); return -EINVAL; } fbi->next_fb_info = next_fb_info; fbi->next_fb_info_change_req = 1; break; case S3CFB_GET_CURR_FB_INFO: next_fb_info.phy_start_addr = fbi->fb.fix.smem_start; next_fb_info.xres = fbi->fb.var.xres; next_fb_info.yres = fbi->fb.var.yres; next_fb_info.xres_virtual = fbi->fb.var.xres_virtual; next_fb_info.yres_virtual = fbi->fb.var.yres_virtual; next_fb_info.xoffset = fbi->fb.var.xoffset; next_fb_info.yoffset = fbi->fb.var.yoffset; next_fb_info.lcd_offset_x = fbi->lcd_offset_x; next_fb_info.lcd_offset_y = fbi->lcd_offset_y; if (copy_to_user((void *)arg, (s3cfb_next_info_t *) &next_fb_info, sizeof(s3cfb_next_info_t))) return -EFAULT; break; case S3CFB_GET_BRIGHTNESS: if (copy_to_user((void *)arg, (const void *) &s3cfb_fimd.brightness, sizeof(int))) return -EFAULT; break; #if defined(CONFIG_S3C6410_PWM) case S3CFB_SET_BRIGHTNESS: if (copy_from_user(&brightness, (int *) arg, sizeof(int))) return -EFAULT; s3cfb_set_brightness(brightness); break; #endif #if defined(CONFIG_FB_S3C_VIRTUAL_SCREEN) case S3CFB_VS_START: s3cfb_fimd.wincon0 &= ~(S3C_WINCONx_ENWIN_F_ENABLE); writel(s3cfb_fimd.wincon0 | S3C_WINCONx_ENWIN_F_ENABLE, S3C_WINCON0); fbi->fb.var.xoffset = s3cfb_fimd.xoffset; fbi->fb.var.yoffset = s3cfb_fimd.yoffset; break; case S3CFB_VS_STOP: s3cfb_fimd.vidw00add0b0 = fbi->screen_dma_f1; s3cfb_fimd.vidw00add0b1 = fbi->screen_dma_f2; fbi->fb.var.xoffset = 0; fbi->fb.var.yoffset = 0; writel(s3cfb_fimd.vidw00add0b0, S3C_VIDW00ADD0B0); writel(s3cfb_fimd.vidw00add0b1, S3C_VIDW00ADD0B1); break; case S3CFB_VS_SET_INFO: if (copy_from_user(&vs_info, (s3cfb_vs_info_t *) arg, sizeof(s3cfb_vs_info_t))) return -EFAULT; if (s3cfb_set_vs_info(vs_info)) { printk("Error S3CFB_VS_SET_INFO\n"); return -EINVAL; } s3cfb_set_vs_registers(S3CFB_VS_SET); fbi->fb.var.xoffset = s3cfb_fimd.xoffset; fbi->fb.var.yoffset = s3cfb_fimd.yoffset; break; case S3CFB_VS_MOVE: s3cfb_set_vs_registers(arg); fbi->fb.var.xoffset = s3cfb_fimd.xoffset; fbi->fb.var.yoffset = s3cfb_fimd.yoffset; break; #endif #if defined(CONFIG_FB_S3C_DOUBLE_BUFFERING) case S3CFB_GET_NUM: if (copy_from_user((void *)&f_num_val, (const void *)arg, sizeof(u_int))) return -EFAULT; if (copy_to_user((void *)arg, (const void *) &f_num_val, sizeof(u_int))) return -EFAULT; break; case S3CFB_CHANGE_REQ: s3cfb_change_buff(0, (int) arg); break; #endif default: return -EINVAL; } return 0; }
int s3cfb_init_registers(s3cfb_info_t *fbi) { struct clk *lcd_clock; struct fb_var_screeninfo *var = &fbi->fb.var; unsigned long flags = 0, page_width = 0, offset = 0; unsigned long video_phy_temp_f1 = fbi->screen_dma_f1; unsigned long video_phy_temp_f2 = fbi->screen_dma_f2; int win_num = fbi->win_id; local_irq_save(flags); page_width = var->xres * s3cfb_fimd.bytes_per_pixel; offset = (var->xres_virtual - var->xres) * s3cfb_fimd.bytes_per_pixel; if (win_num == 0) { #if defined(CONFIG_MACH_VOLANS) s3cfb_fimd.vidcon0 = s3cfb_fimd.vidcon0 | (S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); #else s3cfb_fimd.vidcon0 = s3cfb_fimd.vidcon0 & ~(S3C_VIDCON0_ENVID_ENABLE | S3C_VIDCON0_ENVID_F_ENABLE); #endif writel(s3cfb_fimd.vidcon0, S3C_VIDCON0); lcd_clock = clk_get(NULL, "lcd"); s3cfb_fimd.vidcon0 |= S3C_VIDCON0_CLKVAL_F((int) ((clk_get_rate(lcd_clock) / s3cfb_fimd.pixclock) - 1)); #if defined(CONFIG_FB_S3C_VIRTUAL_SCREEN) offset = 0; s3cfb_fimd.vidw00add0b0 = video_phy_temp_f1; s3cfb_fimd.vidw00add0b1 = video_phy_temp_f2; s3cfb_fimd.vidw00add1b0 = S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f1 + (page_width + offset) * (var->yres)); s3cfb_fimd.vidw00add1b1 = S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f2 + (page_width + offset) * (var->yres)); #endif } writel(video_phy_temp_f1, S3C_VIDW00ADD0B0 + (0x08 * win_num)); writel(S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f1 + (page_width + offset) * (var->yres)), S3C_VIDW00ADD1B0 + (0x08 * win_num)); writel(S3C_VIDWxxADD2_OFFSIZE_F(offset) | (S3C_VIDWxxADD2_PAGEWIDTH_F(page_width)), S3C_VIDW00ADD2 + (0x04 * win_num)); if (win_num < 2) { writel(video_phy_temp_f2, S3C_VIDW00ADD0B1 + (0x08 * win_num)); writel(S3C_VIDWxxADD1_VBASEL_F((unsigned long) video_phy_temp_f2 + (page_width + offset) * (var->yres)), S3C_VIDW00ADD1B1 + (0x08 * win_num)); } switch (win_num) { case 0: writel(s3cfb_fimd.wincon0, S3C_WINCON0); writel(s3cfb_fimd.vidcon0, S3C_VIDCON0); writel(s3cfb_fimd.vidcon1, S3C_VIDCON1); writel(s3cfb_fimd.vidtcon0, S3C_VIDTCON0); writel(s3cfb_fimd.vidtcon1, S3C_VIDTCON1); writel(s3cfb_fimd.vidtcon2, S3C_VIDTCON2); writel(s3cfb_fimd.dithmode, S3C_DITHMODE); writel(s3cfb_fimd.vidintcon0, S3C_VIDINTCON0); writel(s3cfb_fimd.vidintcon1, S3C_VIDINTCON1); writel(s3cfb_fimd.vidosd0a, S3C_VIDOSD0A); writel(s3cfb_fimd.vidosd0b, S3C_VIDOSD0B); writel(s3cfb_fimd.vidosd0c, S3C_VIDOSD0C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 0) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 1: writel(s3cfb_fimd.wincon1, S3C_WINCON1); writel(s3cfb_fimd.vidosd1a, S3C_VIDOSD1A); writel(s3cfb_fimd.vidosd1b, S3C_VIDOSD1B); writel(s3cfb_fimd.vidosd1c, S3C_VIDOSD1C); writel(s3cfb_fimd.vidosd1d, S3C_VIDOSD1D); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 1) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 2: writel(s3cfb_fimd.wincon2, S3C_WINCON2); writel(s3cfb_fimd.vidosd2a, S3C_VIDOSD2A); writel(s3cfb_fimd.vidosd2b, S3C_VIDOSD2B); writel(s3cfb_fimd.vidosd2c, S3C_VIDOSD2C); writel(s3cfb_fimd.vidosd2d, S3C_VIDOSD2D); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 2) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 3: writel(s3cfb_fimd.wincon3, S3C_WINCON3); writel(s3cfb_fimd.vidosd3a, S3C_VIDOSD3A); writel(s3cfb_fimd.vidosd3b, S3C_VIDOSD3B); writel(s3cfb_fimd.vidosd3c, S3C_VIDOSD3C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 3) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; case 4: writel(s3cfb_fimd.wincon4, S3C_WINCON4); writel(s3cfb_fimd.vidosd4a, S3C_VIDOSD4A); writel(s3cfb_fimd.vidosd4b, S3C_VIDOSD4B); writel(s3cfb_fimd.vidosd4c, S3C_VIDOSD4C); writel(s3cfb_fimd.wpalcon, S3C_WPALCON); if(FB_WIN_ID == 4) s3cfb_onoff_win(fbi, ON); else s3cfb_onoff_win(fbi, OFF); break; } local_irq_restore(flags); return 0; }