static int init_panel(struct device *dev, dma_addr_t phys, int memsize, struct mxs_platform_fb_entry *pentry) { int ret = 0; lcd_clk = clk_get(dev, "dis_lcdif"); if (IS_ERR(lcd_clk)) { ret = PTR_ERR(lcd_clk); goto out; } ret = clk_enable(lcd_clk); if (ret) { clk_put(lcd_clk); goto out; } ret = clk_set_rate(lcd_clk, 1000000 / pentry->cycle_time_ns); /* kHz */ if (ret) { clk_disable(lcd_clk); clk_put(lcd_clk); goto out; } /* * Make sure we do a high-to-low transition to reset the panel. * First make it low for 100 msec, hi for 10 msec, low for 10 msec, * then hi. */ __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */ mdelay(100); __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */ mdelay(10); __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */ /* For the Samsung, Reset must be held low at least 30 uSec * Therefore, we'll hold it low for about 10 mSec just to be sure. * Then we'll wait 1 mSec afterwards. */ mdelay(10); __raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */ mdelay(1); setup_dotclk_panel(DOTCLK_V_PULSE_WIDTH, DOTCLK_V_PERIOD, DOTCLK_V_WAIT_CNT, DOTCLK_V_ACTIVE, DOTCLK_H_PULSE_WIDTH, DOTCLK_H_PERIOD, DOTCLK_H_WAIT_CNT, DOTCLK_H_ACTIVE, 0); ret = mxs_lcdif_dma_init(dev, phys, memsize); if (ret) goto out; mxs_lcd_set_bl_pdata(pentry->bl_data); mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_INIT, pentry); return 0; out: return ret; }
static int init_panel(struct device *dev, dma_addr_t phys, int memsize, struct stmp3xxx_platform_fb_entry *pentry) { int ret = 0; lcd_clk = clk_get(dev, "lcdif"); if (IS_ERR(lcd_clk)) { ret = PTR_ERR(lcd_clk); goto out_1; } ret = clk_enable(lcd_clk); if (ret) { clk_put(lcd_clk); goto out_1; } ret = clk_set_rate(lcd_clk, 1000000/pentry->cycle_time_ns); /* kHz */ if (ret) { clk_disable(lcd_clk); clk_put(lcd_clk); goto out_1; } ret = init_pinmux(); if (ret) goto out_1; ret = init_pinmux_spi(); if (ret) goto out_2; init_panel_hw(); ret = stmp3xxx_lcdif_dma_init(dev, phys, memsize, 0); if (ret) goto out_3; setup_dotclk_panel(DOTCLK_V_PULSE_WIDTH, DOTCLK_V_PERIOD, DOTCLK_V_WAIT_CNT, DOTCLK_V_ACTIVE, DOTCLK_H_PULSE_WIDTH, DOTCLK_H_PERIOD, DOTCLK_V_WAIT_CNT, DOTCLK_H_ACTIVE, 1); stmp3xxx_lcd_set_bl_pdata(pentry->bl_data); stmp3xxx_lcdif_notify_clients(STMP3XXX_LCDIF_PANEL_INIT, pentry); return 0; out_3: uninit_pinmux_spi(); out_2: uninit_pinmux(); out_1: return ret; }
/* * This routine actually sets the video mode. It's in here where we * the hardware state info->par and fix which can be affected by the * change in par. For this driver it doesn't do much. * */ static int mxc_elcdif_fb_set_par(struct fb_info *fbi) { struct mxc_elcdif_fb_data *data = (struct mxc_elcdif_fb_data *)fbi->par; struct elcdif_signal_cfg sig_cfg; int mem_len; dev_dbg(fbi->device, "Reconfiguring framebuffer\n"); /* If parameter no change, don't reconfigure. */ if (mxc_elcdif_fb_par_equal(fbi, data)) return 0; sema_init(&data->flip_sem, 1); /* release prev panel */ if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } mxc_elcdif_blank_panel(FB_BLANK_POWERDOWN); mxc_elcdif_stop(); release_dotclk_panel(); mxc_elcdif_dma_release(); mxc_elcdif_fb_set_fix(fbi); if (g_elcdif_pix_clk_enable) { clk_disable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = false; } mem_len = fbi->var.yres_virtual * fbi->fix.line_length; if (!fbi->fix.smem_start || (mem_len > fbi->fix.smem_len)) { if (fbi->fix.smem_start) mxc_elcdif_fb_unmap_video_memory(fbi); if (mxc_elcdif_fb_map_video_memory(fbi) < 0) return -ENOMEM; } if (data->next_blank != FB_BLANK_UNBLANK) return 0; /* init next panel */ if (!g_elcdif_pix_clk_enable) { clk_enable(g_elcdif_pix_clk); g_elcdif_pix_clk_enable = true; } mxc_init_elcdif(); mxc_elcdif_init_panel(); dev_dbg(fbi->device, "pixclock = %u Hz\n", (u32) (PICOS2KHZ(fbi->var.pixclock) * 1000UL)); memset(&sig_cfg, 0, sizeof(sig_cfg)); if (fbi->var.sync & FB_SYNC_HOR_HIGH_ACT) sig_cfg.Hsync_pol = true; if (fbi->var.sync & FB_SYNC_VERT_HIGH_ACT) sig_cfg.Vsync_pol = true; if (fbi->var.sync & FB_SYNC_CLK_LAT_FALL) sig_cfg.clk_pol = true; if (!(fbi->var.sync & FB_SYNC_OE_LOW_ACT)) sig_cfg.enable_pol = true; setup_dotclk_panel((PICOS2KHZ(fbi->var.pixclock)) * 1000UL, fbi->var.vsync_len, fbi->var.upper_margin + fbi->var.yres + fbi->var.lower_margin, fbi->var.upper_margin, fbi->var.yres, fbi->var.hsync_len, fbi->var.left_margin + fbi->var.xres + fbi->var.right_margin, fbi->var.left_margin, fbi->var.xres, bpp_to_pixfmt(fbi), data->output_pix_fmt, sig_cfg, 1); mxc_elcdif_frame_addr_setup(fbi->fix.smem_start); mxc_elcdif_run(); mxc_elcdif_blank_panel(FB_BLANK_UNBLANK); fbi->mode = (struct fb_videomode *)fb_match_mode(&fbi->var, &fbi->modelist); data->var = fbi->var; return 0; }