diff options
Diffstat (limited to 'drivers/video/samsung/extension/s5p_fimd_lite.c')
-rw-r--r-- | drivers/video/samsung/extension/s5p_fimd_lite.c | 502 |
1 files changed, 0 insertions, 502 deletions
diff --git a/drivers/video/samsung/extension/s5p_fimd_lite.c b/drivers/video/samsung/extension/s5p_fimd_lite.c deleted file mode 100644 index 3e128b8..0000000 --- a/drivers/video/samsung/extension/s5p_fimd_lite.c +++ /dev/null @@ -1,502 +0,0 @@ -/* /linux/driver/video/samsung/s5p_fimd_lite.c - * - * Samsung SoC FIMD Lite driver. - * - * Author: InKi Dae <inki.dae@samsung.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/irq.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/fb.h> - -#include <plat/clock.h> -#include <plat/fb.h> -#include <plat/cpu.h> -#include <plat/fimd_lite_ext.h> -#include <plat/regs-fb.h> - -#include <mach/map.h> - -#include "s5p_fimd_ext.h" -#include "s5p_fimd_lite.h" -#include "regs_fimd_lite.h" - -static void *to_fimd_lite_platform_data(struct s5p_fimd_ext_device *fx_dev) -{ - return fx_dev->dev.platform_data ? (void *)fx_dev->dev.platform_data : - NULL; -} - -static void s5p_fimd_lite_set_par(struct s5p_fimd_lite *fimd_lite, - unsigned int win_id) -{ - struct exynos_drm_fimd_pdata *lcd; - struct fb_videomode timing; - unsigned int cfg; - - lcd = fimd_lite->lcd; - timing = lcd->panel.timing; - - /* set window control */ - cfg = readl(fimd_lite->iomem_base + S5P_WINCON(win_id)); - - cfg &= ~(S5P_WINCON_BITSWP_ENABLE | S5P_WINCON_BYTESWP_ENABLE | \ - S5P_WINCON_HAWSWP_ENABLE | S5P_WINCON_WSWP_ENABLE | \ - S5P_WINCON_BURSTLEN_MASK | S5P_WINCON_BPPMODE_MASK | \ - S5P_WINCON_INRGB_MASK | S5P_WINCON_DATAPATH_MASK); - - /* DATAPATH is LOCAL */ - cfg |= S5P_WINCON_DATAPATH_LOCAL; - - /* pixel format is unpacked RGB888 */ - cfg |= S5P_WINCON_INRGB_RGB | S5P_WINCON_BPPMODE_32BPP; - - writel(cfg, fimd_lite->iomem_base + S5P_WINCON(win_id)); - - /* set window position to x=0, y=0*/ - cfg = S5P_VIDOSD_LEFT_X(0) | S5P_VIDOSD_TOP_Y(0); - writel(cfg, fimd_lite->iomem_base + S5P_VIDOSD_A(win_id)); - - cfg = S5P_VIDOSD_RIGHT_X(timing.xres - 1) | - S5P_VIDOSD_BOTTOM_Y(timing.yres - 1); - writel(cfg, fimd_lite->iomem_base + S5P_VIDOSD_B(win_id)); - - /* set window size for window0*/ - cfg = S5P_VIDOSD_SIZE(timing.xres * timing.yres); - writel(cfg, fimd_lite->iomem_base + S5P_VIDOSD_C(win_id)); - - return; -} - -static void s5p_fimd_lite_set_clock(struct s5p_fimd_lite *fimd_lite) -{ - unsigned int cfg = 0, div = 0; - unsigned int pixel_clock, src_clock, max_clock; - struct clk *clk; - struct exynos_drm_fimd_pdata *lcd; - struct fb_videomode timing; - - lcd = fimd_lite->lcd; - timing = lcd->panel.timing; - - clk = fimd_lite->clk; - - max_clock = 86 * 1000000; - - pixel_clock = timing.refresh * - (timing.left_margin + timing.right_margin + - timing.hsync_len + timing.xres) * (timing.upper_margin + - timing.lower_margin + timing.vsync_len + timing.yres); - - src_clock = clk_get_rate(clk->parent); - - cfg = readl(fimd_lite->iomem_base + S5P_VIDCON0); - cfg &= ~(S5P_VIDCON0_VCLKEN_MASK | S5P_VIDCON0_CLKVALUP_MASK | - S5P_VIDCON0_CLKVAL_F(0xFF)); - cfg |= (S5P_VIDCON0_CLKVALUP_ALWAYS | S5P_VIDCON0_VCLKEN_NORMAL); - - cfg |= S5P_VIDCON0_CLKSEL_HCLK; - - if (pixel_clock > max_clock) - pixel_clock = max_clock; - - div = (unsigned int)(src_clock / pixel_clock); - if (src_clock % pixel_clock) - div++; - - cfg |= S5P_VIDCON0_CLKVAL_F(div - 1); - writel(cfg, fimd_lite->iomem_base + S5P_VIDCON0); - - return; -} - -static void s5p_fimd_lite_window_on(struct s5p_fimd_lite *fimd_lite, - unsigned int win_id, unsigned int enable) -{ - unsigned int cfg; - - /* enable window */ - cfg = readl(fimd_lite->iomem_base + S5P_WINCON(win_id)); - - cfg &= ~S5P_WINCON_ENWIN_ENABLE; - - if (enable) - cfg |= S5P_WINCON_ENWIN_ENABLE; - - writel(cfg, fimd_lite->iomem_base + S5P_WINCON(win_id)); -} - -static void s5p_fimd_lite_lcd_on(struct s5p_fimd_lite *fimd_lite, - unsigned int enable) -{ - unsigned int cfg; - - cfg = readl(fimd_lite->iomem_base + S5P_VIDCON0); - - cfg &= ~(S5P_VIDCON0_ENVID_ENABLE | S5P_VIDCON0_ENVID_F_ENABLE); - - if (enable) - cfg |= (S5P_VIDCON0_ENVID_ENABLE | S5P_VIDCON0_ENVID_F_ENABLE); - - writel(cfg, fimd_lite->iomem_base + S5P_VIDCON0); -} - -void s5p_fimd_lite_get_vsync_interrupt(struct s5p_fimd_lite *fimd_lite, - unsigned int enable) -{ - unsigned int cfg; - - cfg = readl(fimd_lite->iomem_base + S5P_VIDINTCON0); - cfg &= ~(S5P_VIDINTCON0_INTFRMEN_ENABLE | S5P_VIDINTCON0_INT_ENABLE | - S5P_VIDINTCON0_FRAMESEL0_VSYNC); - - if (enable) { - cfg |= (S5P_VIDINTCON0_INTFRMEN_ENABLE | - S5P_VIDINTCON0_INT_ENABLE | - S5P_VIDINTCON0_FRAMESEL0_VSYNC); - } else { - cfg |= (S5P_VIDINTCON0_INTFRMEN_DISABLE | - S5P_VIDINTCON0_INT_DISABLE); - - cfg &= ~S5P_VIDINTCON0_FRAMESEL0_VSYNC; - } - - writel(cfg, fimd_lite->iomem_base + S5P_VIDINTCON0); -} - -static void s5p_change_dynamic_refresh(struct s5p_fimd_dynamic_refresh - *fimd_refresh, struct s5p_fimd_ext_device *fx_dev) -{ - unsigned int cfg = 0, ret = 0; - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - struct exynos_drm_fimd_pdata *lcd; - struct fb_videomode timing; - unsigned long flags; - u32 vclk, src_clk, refresh; - - lcd = fimd_lite->lcd; - timing = lcd->panel.timing; - - cfg = readl(fimd_lite->iomem_base + S5P_VIDCON0); - cfg &= ~(S5P_VIDCON0_CLKVALUP_START_FRAME | S5P_VIDCON0_CLKVAL_F(0xFF)); - cfg |= (S5P_VIDCON0_CLKVALUP_ALWAYS | S5P_VIDCON0_VCLKEN_NORMAL); - cfg |= S5P_VIDCON0_CLKVAL_F(fimd_refresh->clkdiv - 1); - - if (!irqs_disabled()) - local_irq_save(flags); - - if (timing.refresh == 60) { - while (1) { - ret = (__raw_readl(fimd_lite->iomem_base + - S5P_VIDCON1) >> 13) & - S5P_VIDCON1_VSTATUS_MASK; - if (ret == S5P_VIDCON1_VSTATUS_BACKPORCH) { - __raw_writel(cfg, fimd_lite->iomem_base + - S5P_VIDCON0); - ret = (__raw_readl(fimd_refresh->regs + - VIDCON1) >> 13) & - S5P_VIDCON1_VSTATUS_MASK; - if (ret == S5P_VIDCON1_VSTATUS_ACTIVE) { - __raw_writel(cfg, - fimd_refresh->regs + VIDCON0); - break; - } - } - } - } else { - while (1) { - ret = (__raw_readl(fimd_refresh->regs + VIDCON1) >> 13) - & S5P_VIDCON1_VSTATUS_MASK; - if (ret == S5P_VIDCON1_VSTATUS_ACTIVE) { - ret = (__raw_readl(fimd_lite->iomem_base + - S5P_VIDCON1) >> 13) & - S5P_VIDCON1_VSTATUS_MASK; - if (ret == S5P_VIDCON1_VSTATUS_FRONTPORCH) { - __raw_writel(cfg, - fimd_refresh->regs + VIDCON0); - __raw_writel(cfg, - fimd_lite->iomem_base + - S5P_VIDCON0); - break; - } - } - } - } - if (irqs_disabled()) - local_irq_restore(flags); - - src_clk = clk_get_rate(fimd_lite->clk->parent); - vclk = timing.refresh * (timing.left_margin + timing.hsync_len + - timing.right_margin + timing.xres) * - (timing.upper_margin + timing.vsync_len + - timing.lower_margin + timing.yres); - - refresh = timing.refresh - - ((vclk - (src_clk / fimd_refresh->clkdiv)) / MHZ); - dev_dbg(fimd_lite->dev, "expected refresh rate: %d fps\n", refresh); -} - -static irqreturn_t s5p_fimd_lite_irq_frame(int irq, void *dev_id) -{ - struct s5p_fimd_lite *fimd_lite; - - fimd_lite = (struct s5p_fimd_lite *)dev_id; - - disable_irq_nosync(fimd_lite->irq); - - enable_irq(fimd_lite->irq); - - return IRQ_HANDLED; -} - -static void s5p_fimd_lite_logic_start(struct s5p_fimd_lite *fimd_lite, - unsigned int enable) -{ - unsigned int cfg; - - cfg = 0x2ff47; - - if (enable) - writel(cfg, fimd_lite->iomem_base + S5P_GPOUTCON0); - else - writel(0, fimd_lite->iomem_base + S5P_GPOUTCON0); -} - -static void s5p_fimd_lite_lcd_init(struct s5p_fimd_lite *fimd_lite) -{ - unsigned int cfg, rgb_mode, win_id = 0; - struct exynos_drm_fimd_pdata *lcd; - struct fb_videomode timing; - - lcd = fimd_lite->lcd; - timing = lcd->panel.timing; - - cfg = 0; - cfg |= lcd->vidcon1; - - writel(cfg, fimd_lite->iomem_base + S5P_VIDCON1); - - /* set timing */ - cfg = 0; - cfg |= S5P_VIDTCON0_VBPD(timing.upper_margin - 1); - cfg |= S5P_VIDTCON0_VFPD(timing.lower_margin - 1); - cfg |= S5P_VIDTCON0_VSPW(timing.vsync_len - 1); - writel(cfg, fimd_lite->iomem_base + S5P_VIDTCON0); - - cfg = 0; - cfg |= S5P_VIDTCON1_HBPD(timing.left_margin - 1); - cfg |= S5P_VIDTCON1_HFPD(timing.right_margin - 1); - cfg |= S5P_VIDTCON1_HSPW(timing.hsync_len - 1); - - writel(cfg, fimd_lite->iomem_base + S5P_VIDTCON1); - - /* set lcd size */ - cfg = 0; - cfg |= S5P_VIDTCON2_HOZVAL(timing.xres - 1); - cfg |= S5P_VIDTCON2_LINEVAL(timing.yres - 1); - - writel(cfg, fimd_lite->iomem_base + S5P_VIDTCON2); - - writel(0, fimd_lite->iomem_base + S5P_DITHMODE); - - /* set output to RGB */ - rgb_mode = 0; /* MODE_RGB_P */ - cfg = readl(fimd_lite->iomem_base + S5P_VIDCON0); - cfg &= ~S5P_VIDCON0_VIDOUT_MASK; - - cfg |= S5P_VIDCON0_VIDOUT_RGB; - writel(cfg, fimd_lite->iomem_base + S5P_VIDCON0); - - /* set display mode */ - cfg = readl(fimd_lite->iomem_base + S5P_VIDCON0); - cfg &= ~S5P_VIDCON0_PNRMODE_MASK; - cfg |= (rgb_mode << S5P_VIDCON0_PNRMODE_SHIFT); - writel(cfg, fimd_lite->iomem_base + S5P_VIDCON0); - - s5p_fimd_lite_get_vsync_interrupt(fimd_lite, 0); - - /* set par */ - s5p_fimd_lite_set_par(fimd_lite, win_id); - - /* set buffer size */ - cfg = S5P_VIDADDR_PAGEWIDTH(timing.xres * lcd->bpp / 8); - writel(cfg, fimd_lite->iomem_base + S5P_VIDADDR_SIZE(win_id)); - - /* set clock */ - s5p_fimd_lite_set_clock(fimd_lite); - - return; -} - -static int s5p_fimd_lite_setup(struct s5p_fimd_ext_device *fx_dev, - unsigned int enable) -{ - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - - s5p_fimd_lite_logic_start(fimd_lite, enable); - - s5p_fimd_lite_lcd_init(fimd_lite); - - - s5p_fimd_lite_window_on(fimd_lite, 0, 1); - - return 0; -} - -static int s5p_fimd_lite_start(struct s5p_fimd_ext_device *fx_dev) -{ - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - - s5p_fimd_lite_lcd_on(fimd_lite, 1); - - return 0; -} - -static void s5p_fimd_lite_stop(struct s5p_fimd_ext_device *fx_dev) -{ - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - - s5p_fimd_lite_lcd_on(fimd_lite, 0); -} - -static void s5p_fimd_lite_power_on(struct s5p_fimd_ext_device *fx_dev) -{ - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - - clk_enable(fimd_lite->clk); -} - -static void s5p_fimd_lite_power_off(struct s5p_fimd_ext_device *fx_dev) -{ - struct s5p_fimd_lite *fimd_lite = fimd_ext_get_drvdata(fx_dev); - - clk_disable(fimd_lite->clk); -} - -static int s5p_fimd_lite_probe(struct s5p_fimd_ext_device *fx_dev) -{ - struct clk *sclk = NULL; - struct resource *res; - struct s5p_fimd_lite *fimd_lite; - int ret = -1; - - fimd_lite = kzalloc(sizeof(struct s5p_fimd_lite), GFP_KERNEL); - if (!fimd_lite) { - dev_err(&fx_dev->dev, "failed to alloc fimd_lite object.\n"); - return -EFAULT; - } - - fimd_lite->dev = &fx_dev->dev; - fimd_lite->lcd = (struct exynos_drm_fimd_pdata *) - to_fimd_lite_platform_data(fx_dev); - - res = s5p_fimd_ext_get_resource(fx_dev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&fx_dev->dev, "failed to get io memory region.\n"); - ret = -EINVAL; - goto err0; - } - - fimd_lite->iomem_base = ioremap(res->start, resource_size(res)); - if (!fimd_lite->iomem_base) { - dev_err(&fx_dev->dev, "failed to remap io region\n"); - ret = -EFAULT; - goto err0; - } - - fimd_lite->clk = clk_get(&fx_dev->dev, "mdnie0"); - if (IS_ERR(fimd_lite->clk)) { - dev_err(&fx_dev->dev, "failed to get FIMD LITE clock source\n"); - ret = -EINVAL; - goto err1; - } - - sclk = clk_get(&fx_dev->dev, "sclk_mdnie"); - if (IS_ERR(sclk)) { - dev_err(&fx_dev->dev, "failed to get sclk_mdnie clock\n"); - ret = -EINVAL; - goto err2; - } - fimd_lite->clk->parent = sclk; - - fimd_lite->irq = s5p_fimd_ext_get_irq(fx_dev, 0); - - /* register interrupt handler for fimd-lite. */ - if (request_irq(fimd_lite->irq, s5p_fimd_lite_irq_frame, IRQF_DISABLED, - fx_dev->name, (void *)fimd_lite)) { - dev_err(&fx_dev->dev, "request_irq failed\n"); - ret = -EINVAL; - goto err3; - } - - fimd_ext_set_drvdata(fx_dev, fimd_lite); - - dev_info(&fx_dev->dev, "fimd lite driver has been probed.\n"); - - return 0; - -err3: - free_irq(fimd_lite->irq, fx_dev); -err2: - clk_put(sclk); -err1: - iounmap(fimd_lite->iomem_base); - clk_put(fimd_lite->clk); -err0: - kfree(fimd_lite); - - return ret; - -} - -static struct s5p_fimd_ext_driver fimd_ext_driver = { - .driver = { - .name = "fimd_lite", - .owner = THIS_MODULE, - }, - .change_clock = s5p_change_dynamic_refresh, - .power_on = s5p_fimd_lite_power_on, - .power_off = s5p_fimd_lite_power_off, - .setup = s5p_fimd_lite_setup, - .start = s5p_fimd_lite_start, - .stop = s5p_fimd_lite_stop, - .probe = s5p_fimd_lite_probe, -}; - -static int __init s5p_fimd_lite_init(void) -{ - return s5p_fimd_ext_driver_register(&fimd_ext_driver); -} - -static void __exit s5p_fimd_lite_exit(void) -{ -} - -arch_initcall(s5p_fimd_lite_init); -module_exit(s5p_fimd_lite_exit); - -MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>"); -MODULE_DESCRIPTION("FIMD Lite Driver"); -MODULE_LICENSE("GPL"); - |