int s5ptvfb_set_par(struct fb_info *fb) { struct s5ptvfb_window *win = fb->par; dev_dbg(s5ptv_status.dev_fb, "[fb%d] set_par\n", win->id); if (!fb->fix.smem_start) { #ifndef CONFIG_USER_ALLOC_TVOUT GRPPRINTK(" The frame buffer is allocated here\n"); s5ptvfb_map_video_memory(fb); #else printk(KERN_ERR "[Warning] The frame buffer should be allocated by ioctl\n"); #endif } // ((struct fb_var_screeninfo) (s5ptv_status.fb->var)).bits_per_pixel = (s5ptv_status.fb->var).bits_per_pixel = ((struct fb_var_screeninfo) (fb->var)).bits_per_pixel; s5ptvfb_set_display_mode(&s5ptv_status); s5ptvfb_set_window_control(&s5ptv_status, win->id); s5ptvfb_set_window_position(&s5ptv_status, win->id); s5ptvfb_set_window_size(&s5ptv_status, win->id); s5ptvfb_set_buffer_address(&s5ptv_status, win->id); s5ptvfb_set_buffer_size(&s5ptv_status, win->id); if (win->id > 0) s5ptvfb_set_alpha_blending(&s5ptv_status, win->id); return 0; }
static int s5ptvfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb) { struct s5ptvfb_window *win = fb->par; if (var->yoffset + var->yres > var->yres_virtual) { dev_err(s5ptv_status.dev_fb, "invalid yoffset value\n"); return -EINVAL; } fb->var.yoffset = var->yoffset; dev_dbg(s5ptv_status.dev_fb, "[fb%d] yoffset for pan display: %d\n", win->id, var->yoffset); s5ptvfb_set_buffer_address(&s5ptv_status,win->id); return 0; }
int s5ptvfb_direct_ioctl(int id, unsigned int cmd, unsigned long arg) { struct fb_info *fb = s5ptv_status.fb; struct fb_fix_screeninfo *fix = &fb->fix; struct s5ptvfb_window *win = fb->par; void *argp = (void *) arg; int ret = 0; switch (cmd) { case FBIO_ALLOC: win->path = (enum s5ptvfb_data_path_t) argp; break; 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 = s5ptvfb_check_var((struct fb_var_screeninfo *) argp, fb); if (ret) { dev_err(s5ptv_status.dev_fb, "invalid vscreeninfo\n"); break; } ret = memcpy(&fb->var, (struct fb_var_screeninfo *) argp, sizeof(fb->var)) ? 0 : -EFAULT; if (ret) { dev_err(s5ptv_status.dev_fb, "failed to put new vscreeninfo\n"); break; } ret = s5ptvfb_set_par(fb); break; case S5PTVFB_SET_WIN_ON: #ifdef CONFIG_USER_ALLOC_TVOUT s5ptvfb_display_on(&s5ptv_status); s5ptvfb_enable_window(0); #endif break; case S5PTVFB_SET_WIN_OFF: #ifdef CONFIG_USER_ALLOC_TVOUT s5ptvfb_display_off(&s5ptv_status); s5ptvfb_disable_window(0); #endif break; case S5PTVFB_POWER_ON: s5p_tv_clk_gate(true); tv_phy_power(true); _s5p_tv_if_init_param(); s5p_tv_v4l2_init_param(); /* s5ptv_status.tvout_param.disp_mode = TVOUT_720P_60; */ s5ptv_status.tvout_param.out_mode = TVOUT_OUTPUT_HDMI; _s5p_tv_if_set_disp(); break; case S5PTVFB_POWER_OFF: _s5p_vlayer_stop(); _s5p_tv_if_stop(); s5p_tv_clk_gate(false); tv_phy_power(false); break; case S5PTVFB_WIN_SET_ADDR: fix->smem_start = (unsigned long)argp; s5ptvfb_set_buffer_address(&s5ptv_status, win->id); break; default: ret = s5ptvfb_ioctl(fb, cmd, arg); break; } return ret; }
static int s5ptvfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg) { struct fb_var_screeninfo *var = &fb->var; struct s5ptvfb_window *win = fb->par; struct s5ptvfb_lcd *lcd = s5ptv_status.lcd; int ret = 0; void *argp = (void *) arg; union { struct s5ptvfb_user_window user_window; struct s5ptvfb_user_plane_alpha user_alpha; struct s5ptvfb_user_chroma user_chroma; int vsync; } p; switch (cmd) { case FBIO_ALLOC: win->path = (enum s5ptvfb_data_path_t) argp; break; 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 = s5ptvfb_check_var((struct fb_var_screeninfo *) argp, fb); if (ret) { dev_err(s5ptv_status.dev_fb, "invalid vscreeninfo\n"); break; } ret = memcpy(&fb->var, (struct fb_var_screeninfo *) argp, sizeof(fb->var)) ? 0 : -EFAULT; if (ret) { dev_err(s5ptv_status.dev_fb, "failed to put new vscreeninfo\n"); break; } ret = s5ptvfb_set_par(fb); break; case S5PTVFB_WIN_POSITION: if (copy_from_user(&p.user_window, (struct s5ptvfb_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; s5ptvfb_set_window_position(&s5ptv_status, win->id); } break; case S5PTVFB_WIN_SET_PLANE_ALPHA: if (copy_from_user(&p.user_alpha, (struct s5ptvfb_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 = S5PTVFB_AVALUE(p.user_alpha.red, p.user_alpha.green, p.user_alpha.blue); s5ptvfb_set_alpha_blending(&s5ptv_status, win->id); } break; case S5PTVFB_WIN_SET_CHROMA: if (copy_from_user(&p.user_chroma, (struct s5ptvfb_user_chroma __user *) arg, sizeof(p.user_chroma))) ret = -EFAULT; else { win->chroma.enabled = p.user_chroma.enabled; win->chroma.key = S5PTVFB_CHROMA(p.user_chroma.red, p.user_chroma.green, p.user_chroma.blue); s5ptvfb_set_chroma_key(&s5ptv_status, win->id); } break; case S5PTVFB_WIN_SET_ADDR: fb->fix.smem_start = (unsigned long)argp; s5ptvfb_set_buffer_address(&s5ptv_status, win->id); break; case S5PTVFB_SET_WIN_ON: #ifdef CONFIG_USER_ALLOC_TVOUT s5ptvfb_display_on(&s5ptv_status); s5ptvfb_enable_window(0); #endif break; case S5PTVFB_SET_WIN_OFF: #ifdef CONFIG_USER_ALLOC_TVOUT s5ptvfb_display_off(&s5ptv_status); s5ptvfb_disable_window(0); #endif break; } return 0; }