static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; r = dsi_pll_set_clock_div(&dsi_cinfo); if (r) return r; dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) return r; *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; int r; r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo); if (r) return r; r = dss_set_clock_div(&dss_cinfo); if (r) return r; r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) return r; *fck = dss_cinfo.fck; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dispc_clk(int lcd_channel_ix, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; int r; if (cpu_is_omap44xx()) { printk(KERN_INFO "dpi set dispc clk"); /*OMAP4: check this later?*/ return 0; } r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo); if (r) return r; r = dss_set_clock_div(&dss_cinfo); if (r) return r; r = dispc_set_clock_div(lcd_channel_ix, &dispc_cinfo); if (r) return r; *fck = dss_cinfo.fck; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); if (r) return r; dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) return r; *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; r = dsi_pll_set_clock_div(&dsi_cinfo); if (r) return r; dss_select_clk_source(0, 1); r = dispc_set_clock_div(&dispc_cinfo); if (r) return r; *fck = dsi_cinfo.dsi1_pll_fclk; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dsi_clk(enum omap_channel channel, bool is_tft, unsigned long pck_req, unsigned long *pck) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; enum omap_dsi_index ix; DSSDBG("DPI clk source is DSI PLL\n"); ix = (channel == OMAP_DSS_CHANNEL_LCD) ? DSI1 : DSI2; if (!cpu_is_omap44xx()) { r = dsi_pll_calc_clock_div_pck(ix, is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; } else { dsi_cinfo.regn = 16; dsi_cinfo.regm = 115; dsi_cinfo.regm_dispc = 3; dsi_cinfo.regm_dsi = 3; dsi_cinfo.use_dss2_fck = true; r = dsi_calc_clock_rates(channel, &dsi_cinfo); DSSDBG("dpi_set_dsi_clk: dsi_calc_clock_rates=%d\n", r); if (r) return r; dispc_find_clk_divs(is_tft, pck_req, dsi_cinfo.dsi_pll_dispc_fclk, &dispc_cinfo); } r = dsi_pll_set_clock_div(ix, &dsi_cinfo); DSSDBG("dpi_set_dsi_clk: dsi_pll_set_clock_div=%d\n", r); if (r) return r; if (cpu_is_omap44xx()){ dss_select_dispc_clk_source(ix, (ix == DSI1) ? DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1); dss_select_lcd_clk_source(ix, (ix == DSI1) ? DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1); }else{ dss_select_dispc_clk_source(ix, DSS_SRC_DSI1_PLL_FCLK); } dispc_set_clock_div(channel, &dispc_cinfo); *pck = dispc_cinfo.pck; return 0; }
static int dpi_set_dsi_clk(int lcd_channel_ix, bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; printk(KERN_INFO "DPI set dsi clk"); if (!cpu_is_omap44xx()) { r = dsi_pll_calc_clock_div_pck(lcd_channel_ix, is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; } else { dispc_cinfo.lck_div = 1; dispc_cinfo.pck_div = 4; dsi_cinfo.regn = 19; dsi_cinfo.regm = 150; dsi_cinfo.regm3 = 4; dsi_cinfo.regm4 = 4; dsi_cinfo.use_dss2_fck = true; dsi_cinfo.highfreq = 0; dsi_calc_clock_rates(&dsi_cinfo); } r = dsi_pll_set_clock_div(lcd_channel_ix, &dsi_cinfo); if (r) return r; if (cpu_is_omap44xx()) dss_select_clk_source_dsi(lcd_channel_ix, 1, 1); else dss_select_clk_source(0, 1); r = dispc_set_clock_div(lcd_channel_ix, &dispc_cinfo); if (r) return r; *fck = dsi_cinfo.dsi1_pll_fclk; *lck_div = dispc_cinfo.lck_div; *pck_div = dispc_cinfo.pck_div; return 0; }
static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, unsigned long *fck, int *lck_div, int *pck_div) { struct dispc_clock_info cinfo; int r; r = dispc_calc_clock_div(is_tft, pck_req, &cinfo); if (r) return r; r = dispc_set_clock_div(&cinfo); if (r) return r; *fck = cinfo.fck; *lck_div = cinfo.lck_div; *pck_div = cinfo.pck_div; return 0; }
/* * linux/drivers/video/omap2/dss/dpi.c * * Copyright (C) 2009 Nokia Corporation * Author: Tomi Valkeinen <*****@*****.**> * * Some code and ideas taken from drivers/video/omap/ driver * by Imre Deak. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * 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, see <http://www.gnu.org/licenses/>. */ #define DSS_SUBSYS_NAME "DPI" #include <linux/kernel.h> #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/platform_device.h> #include <linux/regulator/consumer.h> #include <plat/display.h> #include <plat/cpu.h> #include <plat/omap-pm.h> #include "dss.h" static struct { struct regulator *vdds_dsi_reg; } dpi; #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL static int dpi_set_dsi_clk(enum omap_channel channel, bool is_tft, unsigned long pck_req, unsigned long *pck) { struct dsi_clock_info dsi_cinfo; struct dispc_clock_info dispc_cinfo; int r; enum omap_dsi_index ix; DSSDBG("DPI clk source is DSI PLL\n"); ix = (channel == OMAP_DSS_CHANNEL_LCD) ? DSI1 : DSI2; if (!cpu_is_omap44xx()) { r = dsi_pll_calc_clock_div_pck(ix, is_tft, pck_req, &dsi_cinfo, &dispc_cinfo); if (r) return r; } else { dsi_cinfo.regn = 16; dsi_cinfo.regm = 115; dsi_cinfo.regm_dispc = 3; dsi_cinfo.regm_dsi = 3; dsi_cinfo.use_dss2_fck = true; r = dsi_calc_clock_rates(channel, &dsi_cinfo); DSSDBG("dpi_set_dsi_clk: dsi_calc_clock_rates=%d\n", r); if (r) return r; dispc_find_clk_divs(is_tft, pck_req, dsi_cinfo.dsi_pll_dispc_fclk, &dispc_cinfo); } r = dsi_pll_set_clock_div(ix, &dsi_cinfo); DSSDBG("dpi_set_dsi_clk: dsi_pll_set_clock_div=%d\n", r); if (r) return r; if (cpu_is_omap44xx()){ dss_select_dispc_clk_source(ix, (ix == DSI1) ? DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1); dss_select_lcd_clk_source(ix, (ix == DSI1) ? DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1); }else{ dss_select_dispc_clk_source(ix, DSS_SRC_DSI1_PLL_FCLK); } dispc_set_clock_div(channel, &dispc_cinfo); *pck = dispc_cinfo.pck; return 0; } #else /* #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL */ static int dpi_set_dispc_clk(enum omap_channel channel, bool is_tft, unsigned long pck_req, unsigned long *pck) { struct dispc_clock_info dispc_cinfo; enum omap_dsi_index ix; DSSDBG("DPI clk source is DISPC\n"); ix = (channel == OMAP_DSS_CHANNEL_LCD) ? DSI1 : DSI2; if (cpu_is_omap44xx()) dispc_find_clk_divs(is_tft, pck_req, dss_clk_get_rate(DSS_CLK_FCK1), &dispc_cinfo); else { struct dss_clock_info dss_cinfo; int r; r = dss_calc_clock_div(is_tft, pck_req, &dss_cinfo, &dispc_cinfo); if (r) return r; r = dss_set_clock_div(&dss_cinfo); if (r) return r; } dss_select_dispc_clk_source(ix, DSS_SRC_DSS1_ALWON_FCLK); if (cpu_is_omap44xx()) dss_select_lcd_clk_source(ix, DSS_SRC_DSS1_ALWON_FCLK); dispc_set_clock_div(channel, &dispc_cinfo); *pck = dispc_cinfo.pck; return 0; }
static int sdi_display_enable(struct omap_display *display) { struct dispc_clock_info cinfo; u16 lck_div, pck_div; unsigned long fck; struct omap_panel *panel = display->panel; unsigned long pck; int r; if (display->state != OMAP_DSS_DISPLAY_DISABLED) { DSSERR("display already enabled\n"); return -EINVAL; } twl4030_enable_regulator(RES_VAUX1); sdi_pad_config(display, 1); /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); sdi_basic_init(); /* 15.5.9.1.2 */ panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; dispc_set_pol_freq(panel); if (!sdi.skip_init) r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000, &cinfo); else r = dispc_get_clock_div(&cinfo); if (r) goto err0; fck = cinfo.fck; lck_div = cinfo.lck_div; pck_div = cinfo.pck_div; pck = fck / lck_div / pck_div / 1000; if (pck != panel->timings.pixel_clock) { DSSWARN("Could not find exact pixel clock. Requested %d kHz, " "got %lu kHz\n", panel->timings.pixel_clock, pck); panel->timings.pixel_clock = pck; } dispc_set_lcd_timings(&panel->timings); r = dispc_set_clock_div(&cinfo); if (r) goto err1; if (!sdi.skip_init) { dss_sdi_init(display->hw_config.u.sdi.datapairs); r = dss_sdi_enable(); if (r) goto err1; mdelay(2); } dispc_enable_lcd_out(1); r = panel->enable(display); if (r) goto err2; display->state = OMAP_DSS_DISPLAY_ACTIVE; sdi.skip_init = 0; return 0; err2: dispc_enable_lcd_out(0); err1: err0: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); twl4030_disable_regulator(RES_VAUX1); return r; }
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_video_timings *t = &dssdev->panel.timings; struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; u16 lck_div, pck_div; unsigned long fck; unsigned long pck; int r; r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); goto err0; } r = regulator_enable(sdi.vdds_sdi_reg); if (r) goto err1; /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); sdi_basic_init(); /* 15.5.9.1.2 */ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); if (!sdi.skip_init) { r = dss_calc_clock_div(1, t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); } else { r = dss_get_clock_div(&dss_cinfo); r = dispc_get_clock_div(&dispc_cinfo); } if (r) goto err2; fck = dss_cinfo.fck; lck_div = dispc_cinfo.lck_div; pck_div = dispc_cinfo.pck_div; pck = fck / lck_div / pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. Requested %d kHz, " "got %lu kHz\n", t->pixel_clock, pck); t->pixel_clock = pck; } dispc_set_lcd_timings(t); r = dss_set_clock_div(&dss_cinfo); if (r) goto err2; r = dispc_set_clock_div(&dispc_cinfo); if (r) goto err2; if (!sdi.skip_init) { dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) goto err1; mdelay(2); } dssdev->manager->enable(dssdev->manager); sdi.skip_init = 0; return 0; err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); regulator_disable(sdi.vdds_sdi_reg); err1: omap_dss_stop_device(dssdev); err0: return r; }
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) { int r; struct dispc_clock_info dispc_cinfo; struct omap_video_timings timings = { .hsw = 1, .hfp = 1, .hbp = 1, .vsw = 1, .vfp = 0, .vbp = 0, }; r = omap_dss_start_device(dssdev); if (r) { DSSERR("RFBI: failed to start device\n"); return r; } r = rfbi_runtime_get(); if (r) { DSSERR("RFBI: failed to get runtime\n"); goto err0; } r = omap_dispc_register_isr(framedone_callback, NULL, DISPC_IRQ_FRAMEDONE); if (r) { DSSERR("RFBI: can't get FRAMEDONE irq\n"); goto err1; } dispc_set_parallel_interface_mode(dssdev->manager->id, OMAP_DSS_PARALLELMODE_RFBI); dispc_enable_fifohandcheck(dssdev->manager->id, 1); dispc_set_lcd_display_type(dssdev->manager->id, OMAP_DSS_LCD_DISPLAY_TFT); dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); dispc_set_lcd_timings(dssdev->manager->id, &timings); r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); if (r) { DSSERR("RFBI: Failed to set dispc clocks\n"); goto err1; } rfbi_configure(dssdev->phy.rfbi.channel, dssdev->ctrl.pixel_size, dssdev->phy.rfbi.data_lines); rfbi_set_timings(dssdev->phy.rfbi.channel, &dssdev->ctrl.rfbi_timings); return 0; err1: rfbi_runtime_put(); err0: omap_dss_stop_device(dssdev); return r; } EXPORT_SYMBOL(omapdss_rfbi_display_enable); void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) { omap_dispc_unregister_isr(framedone_callback, NULL, DISPC_IRQ_FRAMEDONE); omap_dss_stop_device(dssdev); rfbi_runtime_put(); }
static int sdi_display_enable(struct omap_dss_device *dssdev) { struct omap_video_timings *t = &dssdev->panel.timings; struct dss_clock_info dss_cinfo; struct dispc_clock_info dispc_cinfo; u16 lck_div, pck_div; unsigned long fck; unsigned long pck; int r; r = omap_dss_start_device(dssdev); if (r) { DSSERR("failed to start device\n"); goto err0; } if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { DSSERR("dssdev already enabled\n"); r = -EINVAL; goto err1; } /* In case of skip_init sdi_init has already enabled the clocks */ if (!sdi.skip_init) dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); sdi_basic_init(); /* 15.5.9.1.2 */ dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF; /* TODO: update for LCD2 here */ dispc_set_pol_freq(OMAP_DSS_CHANNEL_LCD, dssdev->panel.config, dssdev->panel.acbi, dssdev->panel.acb); if (!sdi.skip_init) { r = dss_calc_clock_div(1, t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); } else { r = dss_get_clock_div(&dss_cinfo); r = dispc_get_clock_div(&dispc_cinfo); } if (r) goto err2; fck = dss_cinfo.fck; lck_div = dispc_cinfo.lck_div; pck_div = dispc_cinfo.pck_div; pck = fck / lck_div / pck_div / 1000; if (pck != t->pixel_clock) { DSSWARN("Could not find exact pixel clock. Requested %d kHz, " "got %lu kHz\n", t->pixel_clock, pck); t->pixel_clock = pck; } /* TODO: if needed, add LCD2 support here*/ dispc_set_lcd_timings(OMAP_DSS_CHANNEL_LCD, t); r = dss_set_clock_div(&dss_cinfo); if (r) goto err2; r = dispc_set_clock_div(&dispc_cinfo); if (r) goto err2; if (!sdi.skip_init) { dss_sdi_init(dssdev->phy.sdi.datapairs); r = dss_sdi_enable(); if (r) goto err1; mdelay(2); } /* TODO: change here if LCD2 support is needed */ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1); if (dssdev->driver->enable) { r = dssdev->driver->enable(dssdev); if (r) goto err3; } dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; sdi.skip_init = 0; return 0; err3: /* TODO: change here if LCD2 support is needed */ dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0); err2: dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); err1: omap_dss_stop_device(dssdev); err0: return r; }