/*! * @brief Disable LCD controller. * @param info framebuffer information pointer */ static void _disable_lcdc(struct fb_info *info) { struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par; if (mx2fbi->type == MX2FB_TYPE_GW) _disable_graphic_window(info); else { if (fb_enabled) { gpio_lcdc_inactive(); board_power_lcd(0); clk_disable(lcdc_clk); fb_enabled = 0; } #ifdef CONFIG_FB_MXC_TVOUT if (fb_mode) { int enable = 0; if ((strcmp(fb_mode, MODE_VGA) == 0) || (strcmp(fb_mode, MODE_NTSC) == 0) || (strcmp(fb_mode, MODE_PAL) == 0)) fs453_ioctl(ENCODER_ENABLE_OUTPUT, &enable); } #endif } }
/*! * @brief Enable LCD controller. * @param info framebuffer information pointer */ static void _enable_lcdc(struct fb_info *info) { static int first_enable = 1; struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par; /* * Graphic window can only be enabled while the HCLK to the LCDC * is disabled. Once enabled it can subsequently be disabled and * enabled without turning off the HCLK. * The graphic window is enabled and then disabled here. So next * time to enable graphic window the HCLK to LCDC does not need * to be disabled, and the flicker (due to disabling of HCLK to * LCDC) is avoided. */ if (first_enable) { _enable_graphic_window(info); _disable_graphic_window(info); first_enable = 0; } if (mx2fbi->type == MX2FB_TYPE_GW) _enable_graphic_window(info); else if (!fb_enabled) { clk_enable(lcdc_clk); gpio_lcdc_active(); board_power_lcd(1); _set_brightness(brightness); fb_enabled++; #ifdef CONFIG_FB_MXC_TVOUT if (fb_mode) { unsigned long mode = 0; if (strcmp(fb_mode, MODE_VGA) == 0) mode = VIDEO_ENCODER_VGA; else if (strcmp(fb_mode, MODE_NTSC) == 0) mode = VIDEO_ENCODER_NTSC; else if (strcmp(fb_mode, MODE_PAL) == 0) mode = VIDEO_ENCODER_PAL; if (mode) fs453_ioctl(ENCODER_SET_NORM, &mode); } #endif } }
/*! * @brief Setup graphic window properties. * @param gwinfo graphic window information pointer */ void mx2_gw_set(struct fb_gwinfo *gwinfo) { int width, height, xpos, ypos; int width_bg, height_bg; unsigned long lgwcr = 0x00400000; /* Graphic window control register */ if (!gwinfo->enabled) { _disable_graphic_window(0); return; } /* Graphic window start address register */ __raw_writel(gwinfo->base, LCDC_REG(LCDC_LGWSAR)); /* * The graphic window width, height, x position and y position * must be synced up width the background window, otherwise there * may be flickering. */ width_bg = (__raw_readl(LCDC_REG(LCDC_LSR)) & 0x03F00000) >> 16; height_bg = __raw_readl(LCDC_REG(LCDC_LSR)) & 0x000003FF; width = (gwinfo->xres > width_bg) ? width_bg : gwinfo->xres; height = (gwinfo->yres > height_bg) ? height_bg : gwinfo->yres; xpos = gwinfo->xpos; ypos = gwinfo->ypos; if (xpos + width > width_bg) xpos = width_bg - width; if (ypos + height > height_bg) ypos = height_bg - height; /* Graphic window size register */ __raw_writel(((width >> 4) << 20) + height, LCDC_REG(LCDC_LGWSR)); /* Graphic window virtual page width register */ __raw_writel(gwinfo->xres_virtual >> 1, LCDC_REG(LCDC_LGWVPWR)); /* Graphic window position register */ __raw_writel(((xpos & 0x000003FF) << 16) | (ypos & 0x000003FF), LCDC_REG(LCDC_LGWPR)); /* Graphic window panning offset register */ __raw_writel(0, LCDC_REG(LCDC_LGWPOR)); /* Graphic window DMA control register */ if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) __raw_writel(0x00040060, LCDC_REG(LCDC_LGWDCR)); else __raw_writel(0x00020010, LCDC_REG(LCDC_LGWDCR)); /* Graphic window control register */ lgwcr |= (gwinfo->alpha_value & 0x000000FF) << 24; lgwcr |= gwinfo->ck_enabled ? 0x00800000 : 0; lgwcr |= gwinfo->vs_reversed ? 0x00200000 : 0; /* * Color keying value * Todo: assume always use RGB565 */ lgwcr |= (gwinfo->ck_red & 0x0000003F) << 12; lgwcr |= (gwinfo->ck_green & 0x0000003F) << 6; lgwcr |= gwinfo->ck_blue & 0x0000003F; __raw_writel(lgwcr, LCDC_REG(LCDC_LGWCR)); pr_debug("Graphic window enabled.\n"); }
/*! * @brief Ioctl function to support customized ioctl operations. * * @param info Framebuffer structure that represents a single frame buffer * @param cmd The command number * @param arg Argument which depends on cmd * * @return Negative errno on error, or zero on success. */ static int mx2fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct mx2fb_info *mx2fbi = (struct mx2fb_info *)info->par; struct mx2fb_gbl_alpha ga; struct mx2fb_color_key ck; switch (cmd) { case MX2FB_SET_GBL_ALPHA: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&ga, (void *)arg, sizeof(ga))) return -EFAULT; g_gwinfo.alpha_value = ga.alpha; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; case MX2FB_SET_CLR_KEY: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&ck, (void *)arg, sizeof(ck))) return -EFAULT; g_gwinfo.ck_enabled = ck.enable; g_gwinfo.ck_red = (ck.color_key & 0x003F0000) >> 16; g_gwinfo.ck_green = (ck.color_key & 0x00003F00) >> 8; g_gwinfo.ck_blue = ck.color_key & 0x0000003F; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; case FBIOGET_GWINFO: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* get graphic window information */ if (copy_to_user((void *)arg, (void *)&g_gwinfo, sizeof(g_gwinfo))) return -EFAULT; break; case FBIOPUT_GWINFO: if (mx2fbi->type != MX2FB_TYPE_GW) return -ENODEV; if (!arg) return -EINVAL; /* set graphic window information */ if (copy_from_user((void *)&g_gwinfo, (void *)arg, sizeof(g_gwinfo))) return -EFAULT; if (g_gwinfo.enabled) _enable_graphic_window(info); else _disable_graphic_window(info); break; #ifdef CONFIG_FB_MXC_TVOUT case ENCODER_GET_CAPABILITIES:{ int ret; struct video_encoder_capability cap; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; ret = fs453_ioctl(cmd, &cap); if (ret) return ret; if (copy_to_user((void *)arg, &cap, sizeof(cap))) return -EFAULT; break; } case ENCODER_SET_NORM:{ int ret; unsigned long mode; char *smode; struct fb_var_screeninfo var; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; if (copy_from_user(&mode, (void *)arg, sizeof(mode))) return -EFAULT; if ((ret = fs453_ioctl(cmd, &mode))) return ret; if (mode == VIDEO_ENCODER_PAL) smode = MODE_PAL; else if (mode == VIDEO_ENCODER_NTSC) smode = MODE_NTSC; else smode = MODE_VGA; var = info->var; var.nonstd = 0; ret = fb_find_mode(&var, info, smode, mxcfb_modedb, mxcfb_modedb_sz, NULL, default_bpp); if ((ret != 1) && (ret != 2)) /* specified mode not found */ return -ENODEV; info->var = var; fb_mode = smode; return mx2fb_set_par(info); } case ENCODER_SET_INPUT: case ENCODER_SET_OUTPUT: case ENCODER_ENABLE_OUTPUT:{ unsigned long varg; if (mx2fbi->type != MX2FB_TYPE_BG) return -ENODEV; if (copy_from_user(&varg, (void *)arg, sizeof(varg))) return -EFAULT; return fs453_ioctl(cmd, &varg); } #endif default: dev_dbg(info->device, "Unknown ioctl command (0x%08X)\n", cmd); return -EINVAL; } return 0; }