2 * linux/drivers/video/omap2/dss/sdi.c
4 * Copyright (C) 2009 Nokia Corporation
5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
20 #define DSS_SUBSYS_NAME "SDI"
22 #include <linux/kernel.h>
23 #include <linux/clk.h>
24 #include <linux/delay.h>
25 #include <linux/err.h>
27 #include <mach/board.h>
28 #include <mach/display.h>
37 static void sdi_basic_init(void)
39 dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS);
41 dispc_set_lcd_display_type(OMAP_DSS_LCD_DISPLAY_TFT);
42 dispc_set_tft_data_lines(24);
43 dispc_lcd_enable_signal_polarity(1);
46 static int sdi_display_enable(struct omap_display *display)
48 struct dispc_clock_info cinfo;
51 struct omap_panel *panel = display->panel;
55 if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
56 DSSERR("display already enabled\n");
60 /* In case of skip_init sdi_init has already enabled the clocks */
62 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
67 panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;
69 dispc_set_pol_freq(panel);
72 r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
75 r = dispc_get_clock_div(&cinfo);
81 lck_div = cinfo.lck_div;
82 pck_div = cinfo.pck_div;
84 pck = fck / lck_div / pck_div / 1000;
86 if (pck != panel->timings.pixel_clock) {
87 DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
89 panel->timings.pixel_clock, pck);
91 panel->timings.pixel_clock = pck;
95 dispc_set_lcd_timings(&panel->timings);
97 r = dispc_set_clock_div(&cinfo);
101 if (!sdi.skip_init) {
102 dss_sdi_init(display->hw_config.u.sdi.datapairs);
107 dispc_enable_lcd_out(1);
109 r = panel->enable(display);
113 display->state = OMAP_DSS_DISPLAY_ACTIVE;
119 dispc_enable_lcd_out(0);
122 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
126 static int sdi_display_resume(struct omap_display *display);
128 static void sdi_display_disable(struct omap_display *display)
130 if (display->state == OMAP_DSS_DISPLAY_DISABLED)
133 if (display->state == OMAP_DSS_DISPLAY_SUSPENDED)
134 sdi_display_resume(display);
136 display->panel->disable(display);
138 dispc_enable_lcd_out(0);
142 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
144 display->state = OMAP_DSS_DISPLAY_DISABLED;
147 static int sdi_display_suspend(struct omap_display *display)
149 if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
152 if (display->panel->suspend)
153 display->panel->suspend(display);
155 dispc_enable_lcd_out(0);
159 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
161 display->state = OMAP_DSS_DISPLAY_SUSPENDED;
166 static int sdi_display_resume(struct omap_display *display)
168 if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
171 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
176 dispc_enable_lcd_out(1);
178 if (display->panel->resume)
179 display->panel->resume(display);
181 display->state = OMAP_DSS_DISPLAY_ACTIVE;
186 static int sdi_display_set_update_mode(struct omap_display *display,
187 enum omap_dss_update_mode mode)
189 if (mode == OMAP_DSS_UPDATE_MANUAL)
192 if (mode == OMAP_DSS_UPDATE_DISABLED) {
193 dispc_enable_lcd_out(0);
194 sdi.update_enabled = 0;
196 dispc_enable_lcd_out(1);
197 sdi.update_enabled = 1;
203 static enum omap_dss_update_mode sdi_display_get_update_mode(
204 struct omap_display *display)
206 return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
207 OMAP_DSS_UPDATE_DISABLED;
210 static void sdi_get_timings(struct omap_display *display,
211 struct omap_video_timings *timings)
213 *timings = display->panel->timings;
216 void sdi_init_display(struct omap_display *display)
218 DSSDBG("SDI init\n");
220 display->enable = sdi_display_enable;
221 display->disable = sdi_display_disable;
222 display->suspend = sdi_display_suspend;
223 display->resume = sdi_display_resume;
224 display->set_update_mode = sdi_display_set_update_mode;
225 display->get_update_mode = sdi_display_get_update_mode;
226 display->get_timings = sdi_get_timings;
229 int sdi_init(bool skip_init)
231 /* we store this for first display enable, then clear it */
232 sdi.skip_init = skip_init;
235 * Enable clocks already here, otherwise there would be a toggle
236 * of them until sdi_display_enable is called.
239 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);