diff options
Diffstat (limited to 'drivers/video/omap2/dss/dpi.c')
-rw-r--r-- | drivers/video/omap2/dss/dpi.c | 180 |
1 files changed, 106 insertions, 74 deletions
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 960e977a8bf0..ff6bd30132df 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -30,47 +30,73 @@ | |||
30 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | 32 | ||
33 | #include <plat/display.h> | 33 | #include <video/omapdss.h> |
34 | #include <plat/cpu.h> | 34 | #include <plat/cpu.h> |
35 | 35 | ||
36 | #include "dss.h" | 36 | #include "dss.h" |
37 | 37 | ||
38 | static struct { | 38 | static struct { |
39 | struct regulator *vdds_dsi_reg; | 39 | struct regulator *vdds_dsi_reg; |
40 | struct platform_device *dsidev; | ||
40 | } dpi; | 41 | } dpi; |
41 | 42 | ||
42 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 43 | static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk) |
43 | static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req, | 44 | { |
44 | unsigned long *fck, int *lck_div, int *pck_div) | 45 | int dsi_module; |
46 | |||
47 | dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1; | ||
48 | |||
49 | return dsi_get_dsidev_from_id(dsi_module); | ||
50 | } | ||
51 | |||
52 | static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev) | ||
53 | { | ||
54 | if (dssdev->clocks.dispc.dispc_fclk_src == | ||
55 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
56 | dssdev->clocks.dispc.dispc_fclk_src == | ||
57 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC || | ||
58 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
59 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC || | ||
60 | dssdev->clocks.dispc.channel.lcd_clk_src == | ||
61 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC) | ||
62 | return true; | ||
63 | else | ||
64 | return false; | ||
65 | } | ||
66 | |||
67 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | ||
68 | unsigned long pck_req, unsigned long *fck, int *lck_div, | ||
69 | int *pck_div) | ||
45 | { | 70 | { |
46 | struct dsi_clock_info dsi_cinfo; | 71 | struct dsi_clock_info dsi_cinfo; |
47 | struct dispc_clock_info dispc_cinfo; | 72 | struct dispc_clock_info dispc_cinfo; |
48 | int r; | 73 | int r; |
49 | 74 | ||
50 | r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo, | 75 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req, |
51 | &dispc_cinfo); | 76 | &dsi_cinfo, &dispc_cinfo); |
52 | if (r) | 77 | if (r) |
53 | return r; | 78 | return r; |
54 | 79 | ||
55 | r = dsi_pll_set_clock_div(&dsi_cinfo); | 80 | r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); |
56 | if (r) | 81 | if (r) |
57 | return r; | 82 | return r; |
58 | 83 | ||
59 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 84 | dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src); |
60 | 85 | ||
61 | r = dispc_set_clock_div(&dispc_cinfo); | 86 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
62 | if (r) | 87 | if (r) |
63 | return r; | 88 | return r; |
64 | 89 | ||
65 | *fck = dsi_cinfo.dsi1_pll_fclk; | 90 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
66 | *lck_div = dispc_cinfo.lck_div; | 91 | *lck_div = dispc_cinfo.lck_div; |
67 | *pck_div = dispc_cinfo.pck_div; | 92 | *pck_div = dispc_cinfo.pck_div; |
68 | 93 | ||
69 | return 0; | 94 | return 0; |
70 | } | 95 | } |
71 | #else | 96 | |
72 | static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | 97 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft, |
73 | unsigned long *fck, int *lck_div, int *pck_div) | 98 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
99 | int *pck_div) | ||
74 | { | 100 | { |
75 | struct dss_clock_info dss_cinfo; | 101 | struct dss_clock_info dss_cinfo; |
76 | struct dispc_clock_info dispc_cinfo; | 102 | struct dispc_clock_info dispc_cinfo; |
@@ -84,7 +110,7 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | |||
84 | if (r) | 110 | if (r) |
85 | return r; | 111 | return r; |
86 | 112 | ||
87 | r = dispc_set_clock_div(&dispc_cinfo); | 113 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
88 | if (r) | 114 | if (r) |
89 | return r; | 115 | return r; |
90 | 116 | ||
@@ -94,31 +120,29 @@ static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req, | |||
94 | 120 | ||
95 | return 0; | 121 | return 0; |
96 | } | 122 | } |
97 | #endif | ||
98 | 123 | ||
99 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 124 | static int dpi_set_mode(struct omap_dss_device *dssdev) |
100 | { | 125 | { |
101 | struct omap_video_timings *t = &dssdev->panel.timings; | 126 | struct omap_video_timings *t = &dssdev->panel.timings; |
102 | int lck_div, pck_div; | 127 | int lck_div = 0, pck_div = 0; |
103 | unsigned long fck; | 128 | unsigned long fck = 0; |
104 | unsigned long pck; | 129 | unsigned long pck; |
105 | bool is_tft; | 130 | bool is_tft; |
106 | int r = 0; | 131 | int r = 0; |
107 | 132 | ||
108 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 133 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
109 | 134 | ||
110 | dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi, | 135 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
111 | dssdev->panel.acb); | 136 | dssdev->panel.acbi, dssdev->panel.acb); |
112 | 137 | ||
113 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 138 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
114 | 139 | ||
115 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 140 | if (dpi_use_dsi_pll(dssdev)) |
116 | r = dpi_set_dsi_clk(is_tft, t->pixel_clock * 1000, | 141 | r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, |
117 | &fck, &lck_div, &pck_div); | 142 | &fck, &lck_div, &pck_div); |
118 | #else | 143 | else |
119 | r = dpi_set_dispc_clk(is_tft, t->pixel_clock * 1000, | 144 | r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, |
120 | &fck, &lck_div, &pck_div); | 145 | &fck, &lck_div, &pck_div); |
121 | #endif | ||
122 | if (r) | 146 | if (r) |
123 | goto err0; | 147 | goto err0; |
124 | 148 | ||
@@ -132,10 +156,10 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
132 | t->pixel_clock = pck; | 156 | t->pixel_clock = pck; |
133 | } | 157 | } |
134 | 158 | ||
135 | dispc_set_lcd_timings(t); | 159 | dispc_set_lcd_timings(dssdev->manager->id, t); |
136 | 160 | ||
137 | err0: | 161 | err0: |
138 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 162 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
139 | return r; | 163 | return r; |
140 | } | 164 | } |
141 | 165 | ||
@@ -145,10 +169,12 @@ static int dpi_basic_init(struct omap_dss_device *dssdev) | |||
145 | 169 | ||
146 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 170 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
147 | 171 | ||
148 | dispc_set_parallel_interface_mode(OMAP_DSS_PARALLELMODE_BYPASS); | 172 | dispc_set_parallel_interface_mode(dssdev->manager->id, |
149 | dispc_set_lcd_display_type(is_tft ? OMAP_DSS_LCD_DISPLAY_TFT : | 173 | OMAP_DSS_PARALLELMODE_BYPASS); |
150 | OMAP_DSS_LCD_DISPLAY_STN); | 174 | dispc_set_lcd_display_type(dssdev->manager->id, is_tft ? |
151 | dispc_set_tft_data_lines(dssdev->phy.dpi.data_lines); | 175 | OMAP_DSS_LCD_DISPLAY_TFT : OMAP_DSS_LCD_DISPLAY_STN); |
176 | dispc_set_tft_data_lines(dssdev->manager->id, | ||
177 | dssdev->phy.dpi.data_lines); | ||
152 | 178 | ||
153 | return 0; | 179 | return 0; |
154 | } | 180 | } |
@@ -169,18 +195,19 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
169 | goto err1; | 195 | goto err1; |
170 | } | 196 | } |
171 | 197 | ||
172 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 198 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
173 | 199 | ||
174 | r = dpi_basic_init(dssdev); | 200 | r = dpi_basic_init(dssdev); |
175 | if (r) | 201 | if (r) |
176 | goto err2; | 202 | goto err2; |
177 | 203 | ||
178 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 204 | if (dpi_use_dsi_pll(dssdev)) { |
179 | dss_clk_enable(DSS_CLK_FCK2); | 205 | dss_clk_enable(DSS_CLK_SYSCK); |
180 | r = dsi_pll_init(dssdev, 0, 1); | 206 | r = dsi_pll_init(dpi.dsidev, 0, 1); |
181 | if (r) | 207 | if (r) |
182 | goto err3; | 208 | goto err3; |
183 | #endif | 209 | } |
210 | |||
184 | r = dpi_set_mode(dssdev); | 211 | r = dpi_set_mode(dssdev); |
185 | if (r) | 212 | if (r) |
186 | goto err4; | 213 | goto err4; |
@@ -192,13 +219,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
192 | return 0; | 219 | return 0; |
193 | 220 | ||
194 | err4: | 221 | err4: |
195 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 222 | if (dpi_use_dsi_pll(dssdev)) |
196 | dsi_pll_uninit(); | 223 | dsi_pll_uninit(dpi.dsidev, true); |
197 | err3: | 224 | err3: |
198 | dss_clk_disable(DSS_CLK_FCK2); | 225 | if (dpi_use_dsi_pll(dssdev)) |
199 | #endif | 226 | dss_clk_disable(DSS_CLK_SYSCK); |
200 | err2: | 227 | err2: |
201 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 228 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
202 | if (cpu_is_omap34xx()) | 229 | if (cpu_is_omap34xx()) |
203 | regulator_disable(dpi.vdds_dsi_reg); | 230 | regulator_disable(dpi.vdds_dsi_reg); |
204 | err1: | 231 | err1: |
@@ -212,13 +239,13 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
212 | { | 239 | { |
213 | dssdev->manager->disable(dssdev->manager); | 240 | dssdev->manager->disable(dssdev->manager); |
214 | 241 | ||
215 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 242 | if (dpi_use_dsi_pll(dssdev)) { |
216 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 243 | dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); |
217 | dsi_pll_uninit(); | 244 | dsi_pll_uninit(dpi.dsidev, true); |
218 | dss_clk_disable(DSS_CLK_FCK2); | 245 | dss_clk_disable(DSS_CLK_SYSCK); |
219 | #endif | 246 | } |
220 | 247 | ||
221 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 248 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
222 | 249 | ||
223 | if (cpu_is_omap34xx()) | 250 | if (cpu_is_omap34xx()) |
224 | regulator_disable(dpi.vdds_dsi_reg); | 251 | regulator_disable(dpi.vdds_dsi_reg); |
@@ -234,7 +261,7 @@ void dpi_set_timings(struct omap_dss_device *dssdev, | |||
234 | dssdev->panel.timings = *timings; | 261 | dssdev->panel.timings = *timings; |
235 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | 262 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { |
236 | dpi_set_mode(dssdev); | 263 | dpi_set_mode(dssdev); |
237 | dispc_go(OMAP_DSS_CHANNEL_LCD); | 264 | dispc_go(dssdev->manager->id); |
238 | } | 265 | } |
239 | } | 266 | } |
240 | EXPORT_SYMBOL(dpi_set_timings); | 267 | EXPORT_SYMBOL(dpi_set_timings); |
@@ -247,6 +274,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
247 | int lck_div, pck_div; | 274 | int lck_div, pck_div; |
248 | unsigned long fck; | 275 | unsigned long fck; |
249 | unsigned long pck; | 276 | unsigned long pck; |
277 | struct dispc_clock_info dispc_cinfo; | ||
250 | 278 | ||
251 | if (!dispc_lcd_timings_ok(timings)) | 279 | if (!dispc_lcd_timings_ok(timings)) |
252 | return -EINVAL; | 280 | return -EINVAL; |
@@ -256,25 +284,18 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
256 | 284 | ||
257 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; | 285 | is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0; |
258 | 286 | ||
259 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 287 | if (dpi_use_dsi_pll(dssdev)) { |
260 | { | ||
261 | struct dsi_clock_info dsi_cinfo; | 288 | struct dsi_clock_info dsi_cinfo; |
262 | struct dispc_clock_info dispc_cinfo; | 289 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, |
263 | r = dsi_pll_calc_clock_div_pck(is_tft, | ||
264 | timings->pixel_clock * 1000, | 290 | timings->pixel_clock * 1000, |
265 | &dsi_cinfo, &dispc_cinfo); | 291 | &dsi_cinfo, &dispc_cinfo); |
266 | 292 | ||
267 | if (r) | 293 | if (r) |
268 | return r; | 294 | return r; |
269 | 295 | ||
270 | fck = dsi_cinfo.dsi1_pll_fclk; | 296 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
271 | lck_div = dispc_cinfo.lck_div; | 297 | } else { |
272 | pck_div = dispc_cinfo.pck_div; | ||
273 | } | ||
274 | #else | ||
275 | { | ||
276 | struct dss_clock_info dss_cinfo; | 298 | struct dss_clock_info dss_cinfo; |
277 | struct dispc_clock_info dispc_cinfo; | ||
278 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, | 299 | r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000, |
279 | &dss_cinfo, &dispc_cinfo); | 300 | &dss_cinfo, &dispc_cinfo); |
280 | 301 | ||
@@ -282,10 +303,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
282 | return r; | 303 | return r; |
283 | 304 | ||
284 | fck = dss_cinfo.fck; | 305 | fck = dss_cinfo.fck; |
285 | lck_div = dispc_cinfo.lck_div; | ||
286 | pck_div = dispc_cinfo.pck_div; | ||
287 | } | 306 | } |
288 | #endif | 307 | |
308 | lck_div = dispc_cinfo.lck_div; | ||
309 | pck_div = dispc_cinfo.pck_div; | ||
289 | 310 | ||
290 | pck = fck / lck_div / pck_div / 1000; | 311 | pck = fck / lck_div / pck_div / 1000; |
291 | 312 | ||
@@ -299,22 +320,33 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
299 | { | 320 | { |
300 | DSSDBG("init_display\n"); | 321 | DSSDBG("init_display\n"); |
301 | 322 | ||
302 | return 0; | 323 | if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { |
303 | } | 324 | struct regulator *vdds_dsi; |
304 | 325 | ||
305 | int dpi_init(struct platform_device *pdev) | 326 | vdds_dsi = dss_get_vdds_dsi(); |
306 | { | 327 | |
307 | if (cpu_is_omap34xx()) { | 328 | if (IS_ERR(vdds_dsi)) { |
308 | dpi.vdds_dsi_reg = dss_get_vdds_dsi(); | ||
309 | if (IS_ERR(dpi.vdds_dsi_reg)) { | ||
310 | DSSERR("can't get VDDS_DSI regulator\n"); | 329 | DSSERR("can't get VDDS_DSI regulator\n"); |
311 | return PTR_ERR(dpi.vdds_dsi_reg); | 330 | return PTR_ERR(vdds_dsi); |
312 | } | 331 | } |
332 | |||
333 | dpi.vdds_dsi_reg = vdds_dsi; | ||
334 | } | ||
335 | |||
336 | if (dpi_use_dsi_pll(dssdev)) { | ||
337 | enum omap_dss_clk_source dispc_fclk_src = | ||
338 | dssdev->clocks.dispc.dispc_fclk_src; | ||
339 | dpi.dsidev = dpi_get_dsidev(dispc_fclk_src); | ||
313 | } | 340 | } |
314 | 341 | ||
315 | return 0; | 342 | return 0; |
316 | } | 343 | } |
317 | 344 | ||
345 | int dpi_init(void) | ||
346 | { | ||
347 | return 0; | ||
348 | } | ||
349 | |||
318 | void dpi_exit(void) | 350 | void dpi_exit(void) |
319 | { | 351 | { |
320 | } | 352 | } |