diff options
author | Paul Mundt <lethal@linux-sh.org> | 2011-03-22 01:27:36 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2011-03-22 01:27:36 -0400 |
commit | da49252fb0392d8196833ef3da92e48fb371f8d7 (patch) | |
tree | 1299899f7513a900b2229b8cde289bca8c41d2f5 /drivers | |
parent | eddecbb601c9ea3fab7e67d7892010fc9426d1e6 (diff) | |
parent | b295d6e593e02168fdafc5db11464b6d51cf239d (diff) |
Merge branch 'for-paul' of git://gitorious.org/linux-omap-dss2/linux
Conflicts:
arch/arm/mach-omap2/board-overo.c
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers')
27 files changed, 4520 insertions, 1244 deletions
diff --git a/drivers/video/omap/Kconfig b/drivers/video/omap/Kconfig index 083c8fe53e24..15e7f1912af9 100644 --- a/drivers/video/omap/Kconfig +++ b/drivers/video/omap/Kconfig | |||
@@ -5,13 +5,18 @@ config FB_OMAP | |||
5 | select FB_CFB_FILLRECT | 5 | select FB_CFB_FILLRECT |
6 | select FB_CFB_COPYAREA | 6 | select FB_CFB_COPYAREA |
7 | select FB_CFB_IMAGEBLIT | 7 | select FB_CFB_IMAGEBLIT |
8 | select TWL4030_CORE if MACH_OMAP_2430SDP | ||
8 | help | 9 | help |
9 | Frame buffer driver for OMAP based boards. | 10 | Frame buffer driver for OMAP based boards. |
10 | 11 | ||
11 | config FB_OMAP_LCD_VGA | 12 | config FB_OMAP_LCD_VGA |
12 | bool "Use LCD in VGA mode" | 13 | bool "Use LCD in VGA mode" |
13 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP | 14 | depends on MACH_OMAP_3430SDP || MACH_OMAP_LDP |
14 | 15 | help | |
16 | Set LCD resolution as VGA (640 X 480). | ||
17 | Default resolution without this option is QVGA(320 X 240). | ||
18 | Please take a look at drivers/video/omap/lcd_ldp.c file | ||
19 | for lcd driver code. | ||
15 | choice | 20 | choice |
16 | depends on FB_OMAP && MACH_OVERO | 21 | depends on FB_OMAP && MACH_OVERO |
17 | prompt "Screen resolution" | 22 | prompt "Screen resolution" |
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig index 940cab394c2e..d18ad6b2372a 100644 --- a/drivers/video/omap2/displays/Kconfig +++ b/drivers/video/omap2/displays/Kconfig | |||
@@ -9,6 +9,12 @@ config PANEL_GENERIC_DPI | |||
9 | Supports LCD Panel used in TI SDP3430 and EVM boards, | 9 | Supports LCD Panel used in TI SDP3430 and EVM boards, |
10 | OMAP3517 EVM boards and CM-T35. | 10 | OMAP3517 EVM boards and CM-T35. |
11 | 11 | ||
12 | config PANEL_LGPHILIPS_LB035Q02 | ||
13 | tristate "LG.Philips LB035Q02 LCD Panel" | ||
14 | depends on OMAP2_DSS && SPI | ||
15 | help | ||
16 | LCD Panel used on the Gumstix Overo Palo35 | ||
17 | |||
12 | config PANEL_SHARP_LS037V7DW01 | 18 | config PANEL_SHARP_LS037V7DW01 |
13 | tristate "Sharp LS037V7DW01 LCD Panel" | 19 | tristate "Sharp LS037V7DW01 LCD Panel" |
14 | depends on OMAP2_DSS | 20 | depends on OMAP2_DSS |
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile index 861f0255ec6b..0f601ab3abf4 100644 --- a/drivers/video/omap2/displays/Makefile +++ b/drivers/video/omap2/displays/Makefile | |||
@@ -1,4 +1,5 @@ | |||
1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o | 1 | obj-$(CONFIG_PANEL_GENERIC_DPI) += panel-generic-dpi.o |
2 | obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o | ||
2 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o | 3 | obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o |
3 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o | 4 | obj-$(CONFIG_PANEL_NEC_NL8048HL11_01B) += panel-nec-nl8048hl11-01b.o |
4 | 5 | ||
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index 07eb30ee59c8..4a9b9ff59467 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -156,6 +156,31 @@ static struct panel_config generic_dpi_panels[] = { | |||
156 | .power_off_delay = 0, | 156 | .power_off_delay = 0, |
157 | .name = "toppoly_tdo35s", | 157 | .name = "toppoly_tdo35s", |
158 | }, | 158 | }, |
159 | |||
160 | /* Samsung LTE430WQ-F0C */ | ||
161 | { | ||
162 | { | ||
163 | .x_res = 480, | ||
164 | .y_res = 272, | ||
165 | |||
166 | .pixel_clock = 9200, | ||
167 | |||
168 | .hfp = 8, | ||
169 | .hsw = 41, | ||
170 | .hbp = 45 - 41, | ||
171 | |||
172 | .vfp = 4, | ||
173 | .vsw = 10, | ||
174 | .vbp = 12 - 10, | ||
175 | }, | ||
176 | .acbi = 0x0, | ||
177 | .acb = 0x0, | ||
178 | .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
179 | OMAP_DSS_LCD_IHS, | ||
180 | .power_on_delay = 0, | ||
181 | .power_off_delay = 0, | ||
182 | .name = "samsung_lte430wq_f0c", | ||
183 | }, | ||
159 | }; | 184 | }; |
160 | 185 | ||
161 | struct panel_drv_data { | 186 | struct panel_drv_data { |
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c new file mode 100644 index 000000000000..271324db2436 --- /dev/null +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c | |||
@@ -0,0 +1,279 @@ | |||
1 | /* | ||
2 | * LCD panel driver for LG.Philips LB035Q02 | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/spi/spi.h> | ||
22 | #include <linux/mutex.h> | ||
23 | |||
24 | #include <plat/display.h> | ||
25 | |||
26 | struct lb035q02_data { | ||
27 | struct mutex lock; | ||
28 | }; | ||
29 | |||
30 | static struct omap_video_timings lb035q02_timings = { | ||
31 | .x_res = 320, | ||
32 | .y_res = 240, | ||
33 | |||
34 | .pixel_clock = 6500, | ||
35 | |||
36 | .hsw = 2, | ||
37 | .hfp = 20, | ||
38 | .hbp = 68, | ||
39 | |||
40 | .vsw = 2, | ||
41 | .vfp = 4, | ||
42 | .vbp = 18, | ||
43 | }; | ||
44 | |||
45 | static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) | ||
46 | { | ||
47 | int r; | ||
48 | |||
49 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
50 | return 0; | ||
51 | |||
52 | r = omapdss_dpi_display_enable(dssdev); | ||
53 | if (r) | ||
54 | goto err0; | ||
55 | |||
56 | if (dssdev->platform_enable) { | ||
57 | r = dssdev->platform_enable(dssdev); | ||
58 | if (r) | ||
59 | goto err1; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | err1: | ||
64 | omapdss_dpi_display_disable(dssdev); | ||
65 | err0: | ||
66 | return r; | ||
67 | } | ||
68 | |||
69 | static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) | ||
70 | { | ||
71 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | ||
72 | return; | ||
73 | |||
74 | if (dssdev->platform_disable) | ||
75 | dssdev->platform_disable(dssdev); | ||
76 | |||
77 | omapdss_dpi_display_disable(dssdev); | ||
78 | } | ||
79 | |||
80 | static int lb035q02_panel_probe(struct omap_dss_device *dssdev) | ||
81 | { | ||
82 | struct lb035q02_data *ld; | ||
83 | int r; | ||
84 | |||
85 | dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS | | ||
86 | OMAP_DSS_LCD_IHS; | ||
87 | dssdev->panel.timings = lb035q02_timings; | ||
88 | |||
89 | ld = kzalloc(sizeof(*ld), GFP_KERNEL); | ||
90 | if (!ld) { | ||
91 | r = -ENOMEM; | ||
92 | goto err; | ||
93 | } | ||
94 | mutex_init(&ld->lock); | ||
95 | dev_set_drvdata(&dssdev->dev, ld); | ||
96 | return 0; | ||
97 | err: | ||
98 | return r; | ||
99 | } | ||
100 | |||
101 | static void lb035q02_panel_remove(struct omap_dss_device *dssdev) | ||
102 | { | ||
103 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
104 | |||
105 | kfree(ld); | ||
106 | } | ||
107 | |||
108 | static int lb035q02_panel_enable(struct omap_dss_device *dssdev) | ||
109 | { | ||
110 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
111 | int r; | ||
112 | |||
113 | mutex_lock(&ld->lock); | ||
114 | |||
115 | r = lb035q02_panel_power_on(dssdev); | ||
116 | if (r) | ||
117 | goto err; | ||
118 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
119 | |||
120 | mutex_unlock(&ld->lock); | ||
121 | return 0; | ||
122 | err: | ||
123 | mutex_unlock(&ld->lock); | ||
124 | return r; | ||
125 | } | ||
126 | |||
127 | static void lb035q02_panel_disable(struct omap_dss_device *dssdev) | ||
128 | { | ||
129 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
130 | |||
131 | mutex_lock(&ld->lock); | ||
132 | |||
133 | lb035q02_panel_power_off(dssdev); | ||
134 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
135 | |||
136 | mutex_unlock(&ld->lock); | ||
137 | } | ||
138 | |||
139 | static int lb035q02_panel_suspend(struct omap_dss_device *dssdev) | ||
140 | { | ||
141 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
142 | |||
143 | mutex_lock(&ld->lock); | ||
144 | |||
145 | lb035q02_panel_power_off(dssdev); | ||
146 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
147 | |||
148 | mutex_unlock(&ld->lock); | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int lb035q02_panel_resume(struct omap_dss_device *dssdev) | ||
153 | { | ||
154 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
155 | int r; | ||
156 | |||
157 | mutex_lock(&ld->lock); | ||
158 | |||
159 | r = lb035q02_panel_power_on(dssdev); | ||
160 | if (r) | ||
161 | goto err; | ||
162 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
163 | |||
164 | mutex_unlock(&ld->lock); | ||
165 | return 0; | ||
166 | err: | ||
167 | mutex_unlock(&ld->lock); | ||
168 | return r; | ||
169 | } | ||
170 | |||
171 | static struct omap_dss_driver lb035q02_driver = { | ||
172 | .probe = lb035q02_panel_probe, | ||
173 | .remove = lb035q02_panel_remove, | ||
174 | |||
175 | .enable = lb035q02_panel_enable, | ||
176 | .disable = lb035q02_panel_disable, | ||
177 | .suspend = lb035q02_panel_suspend, | ||
178 | .resume = lb035q02_panel_resume, | ||
179 | |||
180 | .driver = { | ||
181 | .name = "lgphilips_lb035q02_panel", | ||
182 | .owner = THIS_MODULE, | ||
183 | }, | ||
184 | }; | ||
185 | |||
186 | static int lb035q02_write_reg(struct spi_device *spi, u8 reg, u16 val) | ||
187 | { | ||
188 | struct spi_message msg; | ||
189 | struct spi_transfer index_xfer = { | ||
190 | .len = 3, | ||
191 | .cs_change = 1, | ||
192 | }; | ||
193 | struct spi_transfer value_xfer = { | ||
194 | .len = 3, | ||
195 | }; | ||
196 | u8 buffer[16]; | ||
197 | |||
198 | spi_message_init(&msg); | ||
199 | |||
200 | /* register index */ | ||
201 | buffer[0] = 0x70; | ||
202 | buffer[1] = 0x00; | ||
203 | buffer[2] = reg & 0x7f; | ||
204 | index_xfer.tx_buf = buffer; | ||
205 | spi_message_add_tail(&index_xfer, &msg); | ||
206 | |||
207 | /* register value */ | ||
208 | buffer[4] = 0x72; | ||
209 | buffer[5] = val >> 8; | ||
210 | buffer[6] = val; | ||
211 | value_xfer.tx_buf = buffer + 4; | ||
212 | spi_message_add_tail(&value_xfer, &msg); | ||
213 | |||
214 | return spi_sync(spi, &msg); | ||
215 | } | ||
216 | |||
217 | static void init_lb035q02_panel(struct spi_device *spi) | ||
218 | { | ||
219 | /* Init sequence from page 28 of the lb035q02 spec */ | ||
220 | lb035q02_write_reg(spi, 0x01, 0x6300); | ||
221 | lb035q02_write_reg(spi, 0x02, 0x0200); | ||
222 | lb035q02_write_reg(spi, 0x03, 0x0177); | ||
223 | lb035q02_write_reg(spi, 0x04, 0x04c7); | ||
224 | lb035q02_write_reg(spi, 0x05, 0xffc0); | ||
225 | lb035q02_write_reg(spi, 0x06, 0xe806); | ||
226 | lb035q02_write_reg(spi, 0x0a, 0x4008); | ||
227 | lb035q02_write_reg(spi, 0x0b, 0x0000); | ||
228 | lb035q02_write_reg(spi, 0x0d, 0x0030); | ||
229 | lb035q02_write_reg(spi, 0x0e, 0x2800); | ||
230 | lb035q02_write_reg(spi, 0x0f, 0x0000); | ||
231 | lb035q02_write_reg(spi, 0x16, 0x9f80); | ||
232 | lb035q02_write_reg(spi, 0x17, 0x0a0f); | ||
233 | lb035q02_write_reg(spi, 0x1e, 0x00c1); | ||
234 | lb035q02_write_reg(spi, 0x30, 0x0300); | ||
235 | lb035q02_write_reg(spi, 0x31, 0x0007); | ||
236 | lb035q02_write_reg(spi, 0x32, 0x0000); | ||
237 | lb035q02_write_reg(spi, 0x33, 0x0000); | ||
238 | lb035q02_write_reg(spi, 0x34, 0x0707); | ||
239 | lb035q02_write_reg(spi, 0x35, 0x0004); | ||
240 | lb035q02_write_reg(spi, 0x36, 0x0302); | ||
241 | lb035q02_write_reg(spi, 0x37, 0x0202); | ||
242 | lb035q02_write_reg(spi, 0x3a, 0x0a0d); | ||
243 | lb035q02_write_reg(spi, 0x3b, 0x0806); | ||
244 | } | ||
245 | |||
246 | static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi) | ||
247 | { | ||
248 | init_lb035q02_panel(spi); | ||
249 | return omap_dss_register_driver(&lb035q02_driver); | ||
250 | } | ||
251 | |||
252 | static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi) | ||
253 | { | ||
254 | omap_dss_unregister_driver(&lb035q02_driver); | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static struct spi_driver lb035q02_spi_driver = { | ||
259 | .driver = { | ||
260 | .name = "lgphilips_lb035q02_panel-spi", | ||
261 | .owner = THIS_MODULE, | ||
262 | }, | ||
263 | .probe = lb035q02_panel_spi_probe, | ||
264 | .remove = __devexit_p(lb035q02_panel_spi_remove), | ||
265 | }; | ||
266 | |||
267 | static int __init lb035q02_panel_drv_init(void) | ||
268 | { | ||
269 | return spi_register_driver(&lb035q02_spi_driver); | ||
270 | } | ||
271 | |||
272 | static void __exit lb035q02_panel_drv_exit(void) | ||
273 | { | ||
274 | spi_unregister_driver(&lb035q02_spi_driver); | ||
275 | } | ||
276 | |||
277 | module_init(lb035q02_panel_drv_init); | ||
278 | module_exit(lb035q02_panel_drv_exit); | ||
279 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index 61026f96ad20..abdfdd81001f 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -218,6 +218,8 @@ struct taal_data { | |||
218 | u16 w; | 218 | u16 w; |
219 | u16 h; | 219 | u16 h; |
220 | } update_region; | 220 | } update_region; |
221 | int channel; | ||
222 | |||
221 | struct delayed_work te_timeout_work; | 223 | struct delayed_work te_timeout_work; |
222 | 224 | ||
223 | bool use_dsi_bl; | 225 | bool use_dsi_bl; |
@@ -257,12 +259,12 @@ static void hw_guard_wait(struct taal_data *td) | |||
257 | } | 259 | } |
258 | } | 260 | } |
259 | 261 | ||
260 | static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | 262 | static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data) |
261 | { | 263 | { |
262 | int r; | 264 | int r; |
263 | u8 buf[1]; | 265 | u8 buf[1]; |
264 | 266 | ||
265 | r = dsi_vc_dcs_read(TCH, dcs_cmd, buf, 1); | 267 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1); |
266 | 268 | ||
267 | if (r < 0) | 269 | if (r < 0) |
268 | return r; | 270 | return r; |
@@ -272,17 +274,17 @@ static int taal_dcs_read_1(u8 dcs_cmd, u8 *data) | |||
272 | return 0; | 274 | return 0; |
273 | } | 275 | } |
274 | 276 | ||
275 | static int taal_dcs_write_0(u8 dcs_cmd) | 277 | static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd) |
276 | { | 278 | { |
277 | return dsi_vc_dcs_write(TCH, &dcs_cmd, 1); | 279 | return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1); |
278 | } | 280 | } |
279 | 281 | ||
280 | static int taal_dcs_write_1(u8 dcs_cmd, u8 param) | 282 | static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param) |
281 | { | 283 | { |
282 | u8 buf[2]; | 284 | u8 buf[2]; |
283 | buf[0] = dcs_cmd; | 285 | buf[0] = dcs_cmd; |
284 | buf[1] = param; | 286 | buf[1] = param; |
285 | return dsi_vc_dcs_write(TCH, buf, 2); | 287 | return dsi_vc_dcs_write(td->channel, buf, 2); |
286 | } | 288 | } |
287 | 289 | ||
288 | static int taal_sleep_in(struct taal_data *td) | 290 | static int taal_sleep_in(struct taal_data *td) |
@@ -294,7 +296,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
294 | hw_guard_wait(td); | 296 | hw_guard_wait(td); |
295 | 297 | ||
296 | cmd = DCS_SLEEP_IN; | 298 | cmd = DCS_SLEEP_IN; |
297 | r = dsi_vc_dcs_write_nosync(TCH, &cmd, 1); | 299 | r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1); |
298 | if (r) | 300 | if (r) |
299 | return r; | 301 | return r; |
300 | 302 | ||
@@ -312,7 +314,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
312 | 314 | ||
313 | hw_guard_wait(td); | 315 | hw_guard_wait(td); |
314 | 316 | ||
315 | r = taal_dcs_write_0(DCS_SLEEP_OUT); | 317 | r = taal_dcs_write_0(td, DCS_SLEEP_OUT); |
316 | if (r) | 318 | if (r) |
317 | return r; | 319 | return r; |
318 | 320 | ||
@@ -324,30 +326,30 @@ static int taal_sleep_out(struct taal_data *td) | |||
324 | return 0; | 326 | return 0; |
325 | } | 327 | } |
326 | 328 | ||
327 | static int taal_get_id(u8 *id1, u8 *id2, u8 *id3) | 329 | static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) |
328 | { | 330 | { |
329 | int r; | 331 | int r; |
330 | 332 | ||
331 | r = taal_dcs_read_1(DCS_GET_ID1, id1); | 333 | r = taal_dcs_read_1(td, DCS_GET_ID1, id1); |
332 | if (r) | 334 | if (r) |
333 | return r; | 335 | return r; |
334 | r = taal_dcs_read_1(DCS_GET_ID2, id2); | 336 | r = taal_dcs_read_1(td, DCS_GET_ID2, id2); |
335 | if (r) | 337 | if (r) |
336 | return r; | 338 | return r; |
337 | r = taal_dcs_read_1(DCS_GET_ID3, id3); | 339 | r = taal_dcs_read_1(td, DCS_GET_ID3, id3); |
338 | if (r) | 340 | if (r) |
339 | return r; | 341 | return r; |
340 | 342 | ||
341 | return 0; | 343 | return 0; |
342 | } | 344 | } |
343 | 345 | ||
344 | static int taal_set_addr_mode(u8 rotate, bool mirror) | 346 | static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) |
345 | { | 347 | { |
346 | int r; | 348 | int r; |
347 | u8 mode; | 349 | u8 mode; |
348 | int b5, b6, b7; | 350 | int b5, b6, b7; |
349 | 351 | ||
350 | r = taal_dcs_read_1(DCS_READ_MADCTL, &mode); | 352 | r = taal_dcs_read_1(td, DCS_READ_MADCTL, &mode); |
351 | if (r) | 353 | if (r) |
352 | return r; | 354 | return r; |
353 | 355 | ||
@@ -381,10 +383,11 @@ static int taal_set_addr_mode(u8 rotate, bool mirror) | |||
381 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | 383 | mode &= ~((1<<7) | (1<<6) | (1<<5)); |
382 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | 384 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); |
383 | 385 | ||
384 | return taal_dcs_write_1(DCS_MEM_ACC_CTRL, mode); | 386 | return taal_dcs_write_1(td, DCS_MEM_ACC_CTRL, mode); |
385 | } | 387 | } |
386 | 388 | ||
387 | static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | 389 | static int taal_set_update_window(struct taal_data *td, |
390 | u16 x, u16 y, u16 w, u16 h) | ||
388 | { | 391 | { |
389 | int r; | 392 | int r; |
390 | u16 x1 = x; | 393 | u16 x1 = x; |
@@ -399,7 +402,7 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
399 | buf[3] = (x2 >> 8) & 0xff; | 402 | buf[3] = (x2 >> 8) & 0xff; |
400 | buf[4] = (x2 >> 0) & 0xff; | 403 | buf[4] = (x2 >> 0) & 0xff; |
401 | 404 | ||
402 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 405 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); |
403 | if (r) | 406 | if (r) |
404 | return r; | 407 | return r; |
405 | 408 | ||
@@ -409,11 +412,11 @@ static int taal_set_update_window(u16 x, u16 y, u16 w, u16 h) | |||
409 | buf[3] = (y2 >> 8) & 0xff; | 412 | buf[3] = (y2 >> 8) & 0xff; |
410 | buf[4] = (y2 >> 0) & 0xff; | 413 | buf[4] = (y2 >> 0) & 0xff; |
411 | 414 | ||
412 | r = dsi_vc_dcs_write_nosync(TCH, buf, sizeof(buf)); | 415 | r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf)); |
413 | if (r) | 416 | if (r) |
414 | return r; | 417 | return r; |
415 | 418 | ||
416 | dsi_vc_send_bta_sync(TCH); | 419 | dsi_vc_send_bta_sync(td->channel); |
417 | 420 | ||
418 | return r; | 421 | return r; |
419 | } | 422 | } |
@@ -439,7 +442,7 @@ static int taal_bl_update_status(struct backlight_device *dev) | |||
439 | if (td->use_dsi_bl) { | 442 | if (td->use_dsi_bl) { |
440 | if (td->enabled) { | 443 | if (td->enabled) { |
441 | dsi_bus_lock(); | 444 | dsi_bus_lock(); |
442 | r = taal_dcs_write_1(DCS_BRIGHTNESS, level); | 445 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level); |
443 | dsi_bus_unlock(); | 446 | dsi_bus_unlock(); |
444 | } else { | 447 | } else { |
445 | r = 0; | 448 | r = 0; |
@@ -502,7 +505,7 @@ static ssize_t taal_num_errors_show(struct device *dev, | |||
502 | 505 | ||
503 | if (td->enabled) { | 506 | if (td->enabled) { |
504 | dsi_bus_lock(); | 507 | dsi_bus_lock(); |
505 | r = taal_dcs_read_1(DCS_READ_NUM_ERRORS, &errors); | 508 | r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors); |
506 | dsi_bus_unlock(); | 509 | dsi_bus_unlock(); |
507 | } else { | 510 | } else { |
508 | r = -ENODEV; | 511 | r = -ENODEV; |
@@ -528,7 +531,7 @@ static ssize_t taal_hw_revision_show(struct device *dev, | |||
528 | 531 | ||
529 | if (td->enabled) { | 532 | if (td->enabled) { |
530 | dsi_bus_lock(); | 533 | dsi_bus_lock(); |
531 | r = taal_get_id(&id1, &id2, &id3); | 534 | r = taal_get_id(td, &id1, &id2, &id3); |
532 | dsi_bus_unlock(); | 535 | dsi_bus_unlock(); |
533 | } else { | 536 | } else { |
534 | r = -ENODEV; | 537 | r = -ENODEV; |
@@ -590,7 +593,7 @@ static ssize_t store_cabc_mode(struct device *dev, | |||
590 | if (td->enabled) { | 593 | if (td->enabled) { |
591 | dsi_bus_lock(); | 594 | dsi_bus_lock(); |
592 | if (!td->cabc_broken) | 595 | if (!td->cabc_broken) |
593 | taal_dcs_write_1(DCS_WRITE_CABC, i); | 596 | taal_dcs_write_1(td, DCS_WRITE_CABC, i); |
594 | dsi_bus_unlock(); | 597 | dsi_bus_unlock(); |
595 | } | 598 | } |
596 | 599 | ||
@@ -774,14 +777,29 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
774 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); | 777 | dev_dbg(&dssdev->dev, "Using GPIO TE\n"); |
775 | } | 778 | } |
776 | 779 | ||
780 | r = omap_dsi_request_vc(dssdev, &td->channel); | ||
781 | if (r) { | ||
782 | dev_err(&dssdev->dev, "failed to get virtual channel\n"); | ||
783 | goto err_req_vc; | ||
784 | } | ||
785 | |||
786 | r = omap_dsi_set_vc_id(dssdev, td->channel, TCH); | ||
787 | if (r) { | ||
788 | dev_err(&dssdev->dev, "failed to set VC_ID\n"); | ||
789 | goto err_vc_id; | ||
790 | } | ||
791 | |||
777 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); | 792 | r = sysfs_create_group(&dssdev->dev.kobj, &taal_attr_group); |
778 | if (r) { | 793 | if (r) { |
779 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); | 794 | dev_err(&dssdev->dev, "failed to create sysfs files\n"); |
780 | goto err_sysfs; | 795 | goto err_vc_id; |
781 | } | 796 | } |
782 | 797 | ||
783 | return 0; | 798 | return 0; |
784 | err_sysfs: | 799 | |
800 | err_vc_id: | ||
801 | omap_dsi_release_vc(dssdev, td->channel); | ||
802 | err_req_vc: | ||
785 | if (panel_data->use_ext_te) | 803 | if (panel_data->use_ext_te) |
786 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); | 804 | free_irq(gpio_to_irq(panel_data->ext_te_gpio), dssdev); |
787 | err_irq: | 805 | err_irq: |
@@ -808,6 +826,7 @@ static void taal_remove(struct omap_dss_device *dssdev) | |||
808 | dev_dbg(&dssdev->dev, "remove\n"); | 826 | dev_dbg(&dssdev->dev, "remove\n"); |
809 | 827 | ||
810 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); | 828 | sysfs_remove_group(&dssdev->dev.kobj, &taal_attr_group); |
829 | omap_dsi_release_vc(dssdev, td->channel); | ||
811 | 830 | ||
812 | if (panel_data->use_ext_te) { | 831 | if (panel_data->use_ext_te) { |
813 | int gpio = panel_data->ext_te_gpio; | 832 | int gpio = panel_data->ext_te_gpio; |
@@ -846,13 +865,13 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
846 | 865 | ||
847 | taal_hw_reset(dssdev); | 866 | taal_hw_reset(dssdev); |
848 | 867 | ||
849 | omapdss_dsi_vc_enable_hs(TCH, false); | 868 | omapdss_dsi_vc_enable_hs(td->channel, false); |
850 | 869 | ||
851 | r = taal_sleep_out(td); | 870 | r = taal_sleep_out(td); |
852 | if (r) | 871 | if (r) |
853 | goto err; | 872 | goto err; |
854 | 873 | ||
855 | r = taal_get_id(&id1, &id2, &id3); | 874 | r = taal_get_id(td, &id1, &id2, &id3); |
856 | if (r) | 875 | if (r) |
857 | goto err; | 876 | goto err; |
858 | 877 | ||
@@ -861,30 +880,30 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
861 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | 880 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) |
862 | td->cabc_broken = true; | 881 | td->cabc_broken = true; |
863 | 882 | ||
864 | r = taal_dcs_write_1(DCS_BRIGHTNESS, 0xff); | 883 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); |
865 | if (r) | 884 | if (r) |
866 | goto err; | 885 | goto err; |
867 | 886 | ||
868 | r = taal_dcs_write_1(DCS_CTRL_DISPLAY, | 887 | r = taal_dcs_write_1(td, DCS_CTRL_DISPLAY, |
869 | (1<<2) | (1<<5)); /* BL | BCTRL */ | 888 | (1<<2) | (1<<5)); /* BL | BCTRL */ |
870 | if (r) | 889 | if (r) |
871 | goto err; | 890 | goto err; |
872 | 891 | ||
873 | r = taal_dcs_write_1(DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ | 892 | r = taal_dcs_write_1(td, DCS_PIXEL_FORMAT, 0x7); /* 24bit/pixel */ |
874 | if (r) | 893 | if (r) |
875 | goto err; | 894 | goto err; |
876 | 895 | ||
877 | r = taal_set_addr_mode(td->rotate, td->mirror); | 896 | r = taal_set_addr_mode(td, td->rotate, td->mirror); |
878 | if (r) | 897 | if (r) |
879 | goto err; | 898 | goto err; |
880 | 899 | ||
881 | if (!td->cabc_broken) { | 900 | if (!td->cabc_broken) { |
882 | r = taal_dcs_write_1(DCS_WRITE_CABC, td->cabc_mode); | 901 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); |
883 | if (r) | 902 | if (r) |
884 | goto err; | 903 | goto err; |
885 | } | 904 | } |
886 | 905 | ||
887 | r = taal_dcs_write_0(DCS_DISPLAY_ON); | 906 | r = taal_dcs_write_0(td, DCS_DISPLAY_ON); |
888 | if (r) | 907 | if (r) |
889 | goto err; | 908 | goto err; |
890 | 909 | ||
@@ -903,7 +922,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
903 | td->intro_printed = true; | 922 | td->intro_printed = true; |
904 | } | 923 | } |
905 | 924 | ||
906 | omapdss_dsi_vc_enable_hs(TCH, true); | 925 | omapdss_dsi_vc_enable_hs(td->channel, true); |
907 | 926 | ||
908 | return 0; | 927 | return 0; |
909 | err: | 928 | err: |
@@ -921,7 +940,7 @@ static void taal_power_off(struct omap_dss_device *dssdev) | |||
921 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 940 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
922 | int r; | 941 | int r; |
923 | 942 | ||
924 | r = taal_dcs_write_0(DCS_DISPLAY_OFF); | 943 | r = taal_dcs_write_0(td, DCS_DISPLAY_OFF); |
925 | if (!r) { | 944 | if (!r) { |
926 | r = taal_sleep_in(td); | 945 | r = taal_sleep_in(td); |
927 | /* HACK: wait a bit so that the message goes through */ | 946 | /* HACK: wait a bit so that the message goes through */ |
@@ -1089,7 +1108,7 @@ static irqreturn_t taal_te_isr(int irq, void *data) | |||
1089 | if (old) { | 1108 | if (old) { |
1090 | cancel_delayed_work(&td->te_timeout_work); | 1109 | cancel_delayed_work(&td->te_timeout_work); |
1091 | 1110 | ||
1092 | r = omap_dsi_update(dssdev, TCH, | 1111 | r = omap_dsi_update(dssdev, td->channel, |
1093 | td->update_region.x, | 1112 | td->update_region.x, |
1094 | td->update_region.y, | 1113 | td->update_region.y, |
1095 | td->update_region.w, | 1114 | td->update_region.w, |
@@ -1139,7 +1158,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1139 | if (r) | 1158 | if (r) |
1140 | goto err; | 1159 | goto err; |
1141 | 1160 | ||
1142 | r = taal_set_update_window(x, y, w, h); | 1161 | r = taal_set_update_window(td, x, y, w, h); |
1143 | if (r) | 1162 | if (r) |
1144 | goto err; | 1163 | goto err; |
1145 | 1164 | ||
@@ -1153,7 +1172,7 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1153 | msecs_to_jiffies(250)); | 1172 | msecs_to_jiffies(250)); |
1154 | atomic_set(&td->do_update, 1); | 1173 | atomic_set(&td->do_update, 1); |
1155 | } else { | 1174 | } else { |
1156 | r = omap_dsi_update(dssdev, TCH, x, y, w, h, | 1175 | r = omap_dsi_update(dssdev, td->channel, x, y, w, h, |
1157 | taal_framedone_cb, dssdev); | 1176 | taal_framedone_cb, dssdev); |
1158 | if (r) | 1177 | if (r) |
1159 | goto err; | 1178 | goto err; |
@@ -1191,9 +1210,9 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1191 | int r; | 1210 | int r; |
1192 | 1211 | ||
1193 | if (enable) | 1212 | if (enable) |
1194 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1213 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1195 | else | 1214 | else |
1196 | r = taal_dcs_write_0(DCS_TEAR_OFF); | 1215 | r = taal_dcs_write_0(td, DCS_TEAR_OFF); |
1197 | 1216 | ||
1198 | if (!panel_data->use_ext_te) | 1217 | if (!panel_data->use_ext_te) |
1199 | omapdss_dsi_enable_te(dssdev, enable); | 1218 | omapdss_dsi_enable_te(dssdev, enable); |
@@ -1263,7 +1282,7 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | |||
1263 | dsi_bus_lock(); | 1282 | dsi_bus_lock(); |
1264 | 1283 | ||
1265 | if (td->enabled) { | 1284 | if (td->enabled) { |
1266 | r = taal_set_addr_mode(rotate, td->mirror); | 1285 | r = taal_set_addr_mode(td, rotate, td->mirror); |
1267 | if (r) | 1286 | if (r) |
1268 | goto err; | 1287 | goto err; |
1269 | } | 1288 | } |
@@ -1306,7 +1325,7 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | |||
1306 | 1325 | ||
1307 | dsi_bus_lock(); | 1326 | dsi_bus_lock(); |
1308 | if (td->enabled) { | 1327 | if (td->enabled) { |
1309 | r = taal_set_addr_mode(td->rotate, enable); | 1328 | r = taal_set_addr_mode(td, td->rotate, enable); |
1310 | if (r) | 1329 | if (r) |
1311 | goto err; | 1330 | goto err; |
1312 | } | 1331 | } |
@@ -1350,13 +1369,13 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | |||
1350 | 1369 | ||
1351 | dsi_bus_lock(); | 1370 | dsi_bus_lock(); |
1352 | 1371 | ||
1353 | r = taal_dcs_read_1(DCS_GET_ID1, &id1); | 1372 | r = taal_dcs_read_1(td, DCS_GET_ID1, &id1); |
1354 | if (r) | 1373 | if (r) |
1355 | goto err2; | 1374 | goto err2; |
1356 | r = taal_dcs_read_1(DCS_GET_ID2, &id2); | 1375 | r = taal_dcs_read_1(td, DCS_GET_ID2, &id2); |
1357 | if (r) | 1376 | if (r) |
1358 | goto err2; | 1377 | goto err2; |
1359 | r = taal_dcs_read_1(DCS_GET_ID3, &id3); | 1378 | r = taal_dcs_read_1(td, DCS_GET_ID3, &id3); |
1360 | if (r) | 1379 | if (r) |
1361 | goto err2; | 1380 | goto err2; |
1362 | 1381 | ||
@@ -1404,9 +1423,9 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1404 | else | 1423 | else |
1405 | plen = 2; | 1424 | plen = 2; |
1406 | 1425 | ||
1407 | taal_set_update_window(x, y, w, h); | 1426 | taal_set_update_window(td, x, y, w, h); |
1408 | 1427 | ||
1409 | r = dsi_vc_set_max_rx_packet_size(TCH, plen); | 1428 | r = dsi_vc_set_max_rx_packet_size(td->channel, plen); |
1410 | if (r) | 1429 | if (r) |
1411 | goto err2; | 1430 | goto err2; |
1412 | 1431 | ||
@@ -1414,7 +1433,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1414 | u8 dcs_cmd = first ? 0x2e : 0x3e; | 1433 | u8 dcs_cmd = first ? 0x2e : 0x3e; |
1415 | first = 0; | 1434 | first = 0; |
1416 | 1435 | ||
1417 | r = dsi_vc_dcs_read(TCH, dcs_cmd, | 1436 | r = dsi_vc_dcs_read(td->channel, dcs_cmd, |
1418 | buf + buf_used, size - buf_used); | 1437 | buf + buf_used, size - buf_used); |
1419 | 1438 | ||
1420 | if (r < 0) { | 1439 | if (r < 0) { |
@@ -1440,7 +1459,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev, | |||
1440 | r = buf_used; | 1459 | r = buf_used; |
1441 | 1460 | ||
1442 | err3: | 1461 | err3: |
1443 | dsi_vc_set_max_rx_packet_size(TCH, 1); | 1462 | dsi_vc_set_max_rx_packet_size(td->channel, 1); |
1444 | err2: | 1463 | err2: |
1445 | dsi_bus_unlock(); | 1464 | dsi_bus_unlock(); |
1446 | err1: | 1465 | err1: |
@@ -1466,7 +1485,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1466 | 1485 | ||
1467 | dsi_bus_lock(); | 1486 | dsi_bus_lock(); |
1468 | 1487 | ||
1469 | r = taal_dcs_read_1(DCS_RDDSDR, &state1); | 1488 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state1); |
1470 | if (r) { | 1489 | if (r) { |
1471 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1490 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1472 | goto err; | 1491 | goto err; |
@@ -1479,7 +1498,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1479 | goto err; | 1498 | goto err; |
1480 | } | 1499 | } |
1481 | 1500 | ||
1482 | r = taal_dcs_read_1(DCS_RDDSDR, &state2); | 1501 | r = taal_dcs_read_1(td, DCS_RDDSDR, &state2); |
1483 | if (r) { | 1502 | if (r) { |
1484 | dev_err(&dssdev->dev, "failed to read Taal status\n"); | 1503 | dev_err(&dssdev->dev, "failed to read Taal status\n"); |
1485 | goto err; | 1504 | goto err; |
@@ -1495,7 +1514,7 @@ static void taal_esd_work(struct work_struct *work) | |||
1495 | /* Self-diagnostics result is also shown on TE GPIO line. We need | 1514 | /* Self-diagnostics result is also shown on TE GPIO line. We need |
1496 | * to re-enable TE after self diagnostics */ | 1515 | * to re-enable TE after self diagnostics */ |
1497 | if (td->te_enabled && panel_data->use_ext_te) { | 1516 | if (td->te_enabled && panel_data->use_ext_te) { |
1498 | r = taal_dcs_write_1(DCS_TEAR_ON, 0); | 1517 | r = taal_dcs_write_1(td, DCS_TEAR_ON, 0); |
1499 | if (r) | 1518 | if (r) |
1500 | goto err; | 1519 | goto err; |
1501 | } | 1520 | } |
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig index 43b64403eaa4..bfc5da0e9700 100644 --- a/drivers/video/omap2/dss/Kconfig +++ b/drivers/video/omap2/dss/Kconfig | |||
@@ -1,8 +1,8 @@ | |||
1 | menuconfig OMAP2_DSS | 1 | menuconfig OMAP2_DSS |
2 | tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ Display Subsystem support (EXPERIMENTAL)" |
3 | depends on ARCH_OMAP2 || ARCH_OMAP3 | 3 | depends on ARCH_OMAP2PLUS |
4 | help | 4 | help |
5 | OMAP2/3 Display Subsystem support. | 5 | OMAP2+ Display Subsystem support. |
6 | 6 | ||
7 | if OMAP2_DSS | 7 | if OMAP2_DSS |
8 | 8 | ||
@@ -60,6 +60,14 @@ config OMAP2_DSS_VENC | |||
60 | help | 60 | help |
61 | OMAP Video Encoder support for S-Video and composite TV-out. | 61 | OMAP Video Encoder support for S-Video and composite TV-out. |
62 | 62 | ||
63 | config OMAP4_DSS_HDMI | ||
64 | bool "HDMI support" | ||
65 | depends on ARCH_OMAP4 | ||
66 | default y | ||
67 | help | ||
68 | HDMI Interface. This adds the High Definition Multimedia Interface. | ||
69 | See http://www.hdmi.org/ for HDMI specification. | ||
70 | |||
63 | config OMAP2_DSS_SDI | 71 | config OMAP2_DSS_SDI |
64 | bool "SDI support" | 72 | bool "SDI support" |
65 | depends on ARCH_OMAP3 | 73 | depends on ARCH_OMAP3 |
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile index 7db17b5e570c..10d9d3bb3e24 100644 --- a/drivers/video/omap2/dss/Makefile +++ b/drivers/video/omap2/dss/Makefile | |||
@@ -5,3 +5,5 @@ omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o | |||
5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o | 5 | omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o |
6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o | 6 | omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o |
7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o | 7 | omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o |
8 | omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi.o \ | ||
9 | hdmi_omap4_panel.o | ||
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index 8e89f6049280..1aa2ed1e786e 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -34,332 +34,26 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | 35 | ||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include <plat/clock.h> | ||
38 | 37 | ||
39 | #include "dss.h" | 38 | #include "dss.h" |
40 | #include "dss_features.h" | 39 | #include "dss_features.h" |
41 | 40 | ||
42 | static struct { | 41 | static struct { |
43 | struct platform_device *pdev; | 42 | struct platform_device *pdev; |
44 | int ctx_id; | ||
45 | |||
46 | struct clk *dss_ick; | ||
47 | struct clk *dss1_fck; | ||
48 | struct clk *dss2_fck; | ||
49 | struct clk *dss_54m_fck; | ||
50 | struct clk *dss_96m_fck; | ||
51 | unsigned num_clks_enabled; | ||
52 | 43 | ||
53 | struct regulator *vdds_dsi_reg; | 44 | struct regulator *vdds_dsi_reg; |
54 | struct regulator *vdds_sdi_reg; | 45 | struct regulator *vdds_sdi_reg; |
55 | struct regulator *vdda_dac_reg; | ||
56 | } core; | 46 | } core; |
57 | 47 | ||
58 | static void dss_clk_enable_all_no_ctx(void); | ||
59 | static void dss_clk_disable_all_no_ctx(void); | ||
60 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
61 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
62 | |||
63 | static char *def_disp_name; | 48 | static char *def_disp_name; |
64 | module_param_named(def_disp, def_disp_name, charp, 0); | 49 | module_param_named(def_disp, def_disp_name, charp, 0); |
65 | MODULE_PARM_DESC(def_disp_name, "default display name"); | 50 | MODULE_PARM_DESC(def_disp, "default display name"); |
66 | 51 | ||
67 | #ifdef DEBUG | 52 | #ifdef DEBUG |
68 | unsigned int dss_debug; | 53 | unsigned int dss_debug; |
69 | module_param_named(debug, dss_debug, bool, 0644); | 54 | module_param_named(debug, dss_debug, bool, 0644); |
70 | #endif | 55 | #endif |
71 | 56 | ||
72 | /* CONTEXT */ | ||
73 | static int dss_get_ctx_id(void) | ||
74 | { | ||
75 | struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; | ||
76 | int r; | ||
77 | |||
78 | if (!pdata->get_last_off_on_transaction_id) | ||
79 | return 0; | ||
80 | r = pdata->get_last_off_on_transaction_id(&core.pdev->dev); | ||
81 | if (r < 0) { | ||
82 | dev_err(&core.pdev->dev, "getting transaction ID failed, " | ||
83 | "will force context restore\n"); | ||
84 | r = -1; | ||
85 | } | ||
86 | return r; | ||
87 | } | ||
88 | |||
89 | int dss_need_ctx_restore(void) | ||
90 | { | ||
91 | int id = dss_get_ctx_id(); | ||
92 | |||
93 | if (id < 0 || id != core.ctx_id) { | ||
94 | DSSDBG("ctx id %d -> id %d\n", | ||
95 | core.ctx_id, id); | ||
96 | core.ctx_id = id; | ||
97 | return 1; | ||
98 | } else { | ||
99 | return 0; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static void save_all_ctx(void) | ||
104 | { | ||
105 | DSSDBG("save context\n"); | ||
106 | |||
107 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
108 | |||
109 | dss_save_context(); | ||
110 | dispc_save_context(); | ||
111 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
112 | dsi_save_context(); | ||
113 | #endif | ||
114 | |||
115 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
116 | } | ||
117 | |||
118 | static void restore_all_ctx(void) | ||
119 | { | ||
120 | DSSDBG("restore context\n"); | ||
121 | |||
122 | dss_clk_enable_all_no_ctx(); | ||
123 | |||
124 | dss_restore_context(); | ||
125 | dispc_restore_context(); | ||
126 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
127 | dsi_restore_context(); | ||
128 | #endif | ||
129 | |||
130 | dss_clk_disable_all_no_ctx(); | ||
131 | } | ||
132 | |||
133 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
134 | /* CLOCKS */ | ||
135 | static void core_dump_clocks(struct seq_file *s) | ||
136 | { | ||
137 | int i; | ||
138 | struct clk *clocks[5] = { | ||
139 | core.dss_ick, | ||
140 | core.dss1_fck, | ||
141 | core.dss2_fck, | ||
142 | core.dss_54m_fck, | ||
143 | core.dss_96m_fck | ||
144 | }; | ||
145 | |||
146 | seq_printf(s, "- CORE -\n"); | ||
147 | |||
148 | seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled); | ||
149 | |||
150 | for (i = 0; i < 5; i++) { | ||
151 | if (!clocks[i]) | ||
152 | continue; | ||
153 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
154 | clocks[i]->name, | ||
155 | clk_get_rate(clocks[i]), | ||
156 | clocks[i]->usecount); | ||
157 | } | ||
158 | } | ||
159 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
160 | |||
161 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
162 | { | ||
163 | struct clk *clk; | ||
164 | |||
165 | clk = clk_get(&core.pdev->dev, clk_name); | ||
166 | |||
167 | if (IS_ERR(clk)) { | ||
168 | DSSERR("can't get clock %s", clk_name); | ||
169 | return PTR_ERR(clk); | ||
170 | } | ||
171 | |||
172 | *clock = clk; | ||
173 | |||
174 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int dss_get_clocks(void) | ||
180 | { | ||
181 | int r; | ||
182 | |||
183 | core.dss_ick = NULL; | ||
184 | core.dss1_fck = NULL; | ||
185 | core.dss2_fck = NULL; | ||
186 | core.dss_54m_fck = NULL; | ||
187 | core.dss_96m_fck = NULL; | ||
188 | |||
189 | r = dss_get_clock(&core.dss_ick, "ick"); | ||
190 | if (r) | ||
191 | goto err; | ||
192 | |||
193 | r = dss_get_clock(&core.dss1_fck, "dss1_fck"); | ||
194 | if (r) | ||
195 | goto err; | ||
196 | |||
197 | r = dss_get_clock(&core.dss2_fck, "dss2_fck"); | ||
198 | if (r) | ||
199 | goto err; | ||
200 | |||
201 | r = dss_get_clock(&core.dss_54m_fck, "tv_fck"); | ||
202 | if (r) | ||
203 | goto err; | ||
204 | |||
205 | r = dss_get_clock(&core.dss_96m_fck, "video_fck"); | ||
206 | if (r) | ||
207 | goto err; | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err: | ||
212 | if (core.dss_ick) | ||
213 | clk_put(core.dss_ick); | ||
214 | if (core.dss1_fck) | ||
215 | clk_put(core.dss1_fck); | ||
216 | if (core.dss2_fck) | ||
217 | clk_put(core.dss2_fck); | ||
218 | if (core.dss_54m_fck) | ||
219 | clk_put(core.dss_54m_fck); | ||
220 | if (core.dss_96m_fck) | ||
221 | clk_put(core.dss_96m_fck); | ||
222 | |||
223 | return r; | ||
224 | } | ||
225 | |||
226 | static void dss_put_clocks(void) | ||
227 | { | ||
228 | if (core.dss_96m_fck) | ||
229 | clk_put(core.dss_96m_fck); | ||
230 | clk_put(core.dss_54m_fck); | ||
231 | clk_put(core.dss1_fck); | ||
232 | clk_put(core.dss2_fck); | ||
233 | clk_put(core.dss_ick); | ||
234 | } | ||
235 | |||
236 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
237 | { | ||
238 | switch (clk) { | ||
239 | case DSS_CLK_ICK: | ||
240 | return clk_get_rate(core.dss_ick); | ||
241 | case DSS_CLK_FCK1: | ||
242 | return clk_get_rate(core.dss1_fck); | ||
243 | case DSS_CLK_FCK2: | ||
244 | return clk_get_rate(core.dss2_fck); | ||
245 | case DSS_CLK_54M: | ||
246 | return clk_get_rate(core.dss_54m_fck); | ||
247 | case DSS_CLK_96M: | ||
248 | return clk_get_rate(core.dss_96m_fck); | ||
249 | } | ||
250 | |||
251 | BUG(); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static unsigned count_clk_bits(enum dss_clock clks) | ||
256 | { | ||
257 | unsigned num_clks = 0; | ||
258 | |||
259 | if (clks & DSS_CLK_ICK) | ||
260 | ++num_clks; | ||
261 | if (clks & DSS_CLK_FCK1) | ||
262 | ++num_clks; | ||
263 | if (clks & DSS_CLK_FCK2) | ||
264 | ++num_clks; | ||
265 | if (clks & DSS_CLK_54M) | ||
266 | ++num_clks; | ||
267 | if (clks & DSS_CLK_96M) | ||
268 | ++num_clks; | ||
269 | |||
270 | return num_clks; | ||
271 | } | ||
272 | |||
273 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
274 | { | ||
275 | unsigned num_clks = count_clk_bits(clks); | ||
276 | |||
277 | if (clks & DSS_CLK_ICK) | ||
278 | clk_enable(core.dss_ick); | ||
279 | if (clks & DSS_CLK_FCK1) | ||
280 | clk_enable(core.dss1_fck); | ||
281 | if (clks & DSS_CLK_FCK2) | ||
282 | clk_enable(core.dss2_fck); | ||
283 | if (clks & DSS_CLK_54M) | ||
284 | clk_enable(core.dss_54m_fck); | ||
285 | if (clks & DSS_CLK_96M) | ||
286 | clk_enable(core.dss_96m_fck); | ||
287 | |||
288 | core.num_clks_enabled += num_clks; | ||
289 | } | ||
290 | |||
291 | void dss_clk_enable(enum dss_clock clks) | ||
292 | { | ||
293 | bool check_ctx = core.num_clks_enabled == 0; | ||
294 | |||
295 | dss_clk_enable_no_ctx(clks); | ||
296 | |||
297 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
298 | restore_all_ctx(); | ||
299 | } | ||
300 | |||
301 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
302 | { | ||
303 | unsigned num_clks = count_clk_bits(clks); | ||
304 | |||
305 | if (clks & DSS_CLK_ICK) | ||
306 | clk_disable(core.dss_ick); | ||
307 | if (clks & DSS_CLK_FCK1) | ||
308 | clk_disable(core.dss1_fck); | ||
309 | if (clks & DSS_CLK_FCK2) | ||
310 | clk_disable(core.dss2_fck); | ||
311 | if (clks & DSS_CLK_54M) | ||
312 | clk_disable(core.dss_54m_fck); | ||
313 | if (clks & DSS_CLK_96M) | ||
314 | clk_disable(core.dss_96m_fck); | ||
315 | |||
316 | core.num_clks_enabled -= num_clks; | ||
317 | } | ||
318 | |||
319 | void dss_clk_disable(enum dss_clock clks) | ||
320 | { | ||
321 | if (cpu_is_omap34xx()) { | ||
322 | unsigned num_clks = count_clk_bits(clks); | ||
323 | |||
324 | BUG_ON(core.num_clks_enabled < num_clks); | ||
325 | |||
326 | if (core.num_clks_enabled == num_clks) | ||
327 | save_all_ctx(); | ||
328 | } | ||
329 | |||
330 | dss_clk_disable_no_ctx(clks); | ||
331 | } | ||
332 | |||
333 | static void dss_clk_enable_all_no_ctx(void) | ||
334 | { | ||
335 | enum dss_clock clks; | ||
336 | |||
337 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
338 | if (cpu_is_omap34xx()) | ||
339 | clks |= DSS_CLK_96M; | ||
340 | dss_clk_enable_no_ctx(clks); | ||
341 | } | ||
342 | |||
343 | static void dss_clk_disable_all_no_ctx(void) | ||
344 | { | ||
345 | enum dss_clock clks; | ||
346 | |||
347 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
348 | if (cpu_is_omap34xx()) | ||
349 | clks |= DSS_CLK_96M; | ||
350 | dss_clk_disable_no_ctx(clks); | ||
351 | } | ||
352 | |||
353 | static void dss_clk_disable_all(void) | ||
354 | { | ||
355 | enum dss_clock clks; | ||
356 | |||
357 | clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M; | ||
358 | if (cpu_is_omap34xx()) | ||
359 | clks |= DSS_CLK_96M; | ||
360 | dss_clk_disable(clks); | ||
361 | } | ||
362 | |||
363 | /* REGULATORS */ | 57 | /* REGULATORS */ |
364 | 58 | ||
365 | struct regulator *dss_get_vdds_dsi(void) | 59 | struct regulator *dss_get_vdds_dsi(void) |
@@ -390,32 +84,7 @@ struct regulator *dss_get_vdds_sdi(void) | |||
390 | return reg; | 84 | return reg; |
391 | } | 85 | } |
392 | 86 | ||
393 | struct regulator *dss_get_vdda_dac(void) | ||
394 | { | ||
395 | struct regulator *reg; | ||
396 | |||
397 | if (core.vdda_dac_reg != NULL) | ||
398 | return core.vdda_dac_reg; | ||
399 | |||
400 | reg = regulator_get(&core.pdev->dev, "vdda_dac"); | ||
401 | if (!IS_ERR(reg)) | ||
402 | core.vdda_dac_reg = reg; | ||
403 | |||
404 | return reg; | ||
405 | } | ||
406 | |||
407 | /* DEBUGFS */ | ||
408 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | 87 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) |
409 | static void dss_debug_dump_clocks(struct seq_file *s) | ||
410 | { | ||
411 | core_dump_clocks(s); | ||
412 | dss_dump_clocks(s); | ||
413 | dispc_dump_clocks(s); | ||
414 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
415 | dsi_dump_clocks(s); | ||
416 | #endif | ||
417 | } | ||
418 | |||
419 | static int dss_debug_show(struct seq_file *s, void *unused) | 88 | static int dss_debug_show(struct seq_file *s, void *unused) |
420 | { | 89 | { |
421 | void (*func)(struct seq_file *) = s->private; | 90 | void (*func)(struct seq_file *) = s->private; |
@@ -497,7 +166,6 @@ static inline void dss_uninitialize_debugfs(void) | |||
497 | static int omap_dss_probe(struct platform_device *pdev) | 166 | static int omap_dss_probe(struct platform_device *pdev) |
498 | { | 167 | { |
499 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 168 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
500 | int skip_init = 0; | ||
501 | int r; | 169 | int r; |
502 | int i; | 170 | int i; |
503 | 171 | ||
@@ -508,63 +176,43 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
508 | dss_init_overlay_managers(pdev); | 176 | dss_init_overlay_managers(pdev); |
509 | dss_init_overlays(pdev); | 177 | dss_init_overlays(pdev); |
510 | 178 | ||
511 | r = dss_get_clocks(); | 179 | r = dss_init_platform_driver(); |
512 | if (r) | ||
513 | goto err_clocks; | ||
514 | |||
515 | dss_clk_enable_all_no_ctx(); | ||
516 | |||
517 | core.ctx_id = dss_get_ctx_id(); | ||
518 | DSSDBG("initial ctx id %u\n", core.ctx_id); | ||
519 | |||
520 | #ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT | ||
521 | /* DISPC_CONTROL */ | ||
522 | if (omap_readl(0x48050440) & 1) /* LCD enabled? */ | ||
523 | skip_init = 1; | ||
524 | #endif | ||
525 | |||
526 | r = dss_init(skip_init); | ||
527 | if (r) { | 180 | if (r) { |
528 | DSSERR("Failed to initialize DSS\n"); | 181 | DSSERR("Failed to initialize DSS platform driver\n"); |
529 | goto err_dss; | 182 | goto err_dss; |
530 | } | 183 | } |
531 | 184 | ||
532 | r = rfbi_init(); | 185 | /* keep clocks enabled to prevent context saves/restores during init */ |
533 | if (r) { | 186 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
534 | DSSERR("Failed to initialize rfbi\n"); | ||
535 | goto err_rfbi; | ||
536 | } | ||
537 | 187 | ||
538 | r = dpi_init(pdev); | 188 | r = rfbi_init_platform_driver(); |
539 | if (r) { | 189 | if (r) { |
540 | DSSERR("Failed to initialize dpi\n"); | 190 | DSSERR("Failed to initialize rfbi platform driver\n"); |
541 | goto err_dpi; | 191 | goto err_rfbi; |
542 | } | 192 | } |
543 | 193 | ||
544 | r = dispc_init(); | 194 | r = dispc_init_platform_driver(); |
545 | if (r) { | 195 | if (r) { |
546 | DSSERR("Failed to initialize dispc\n"); | 196 | DSSERR("Failed to initialize dispc platform driver\n"); |
547 | goto err_dispc; | 197 | goto err_dispc; |
548 | } | 198 | } |
549 | 199 | ||
550 | r = venc_init(pdev); | 200 | r = venc_init_platform_driver(); |
551 | if (r) { | 201 | if (r) { |
552 | DSSERR("Failed to initialize venc\n"); | 202 | DSSERR("Failed to initialize venc platform driver\n"); |
553 | goto err_venc; | 203 | goto err_venc; |
554 | } | 204 | } |
555 | 205 | ||
556 | if (cpu_is_omap34xx()) { | 206 | r = dsi_init_platform_driver(); |
557 | r = sdi_init(skip_init); | 207 | if (r) { |
558 | if (r) { | 208 | DSSERR("Failed to initialize DSI platform driver\n"); |
559 | DSSERR("Failed to initialize SDI\n"); | 209 | goto err_dsi; |
560 | goto err_sdi; | 210 | } |
561 | } | ||
562 | 211 | ||
563 | r = dsi_init(pdev); | 212 | r = hdmi_init_platform_driver(); |
564 | if (r) { | 213 | if (r) { |
565 | DSSERR("Failed to initialize DSI\n"); | 214 | DSSERR("Failed to initialize hdmi\n"); |
566 | goto err_dsi; | 215 | goto err_hdmi; |
567 | } | ||
568 | } | 216 | } |
569 | 217 | ||
570 | r = dss_initialize_debugfs(); | 218 | r = dss_initialize_debugfs(); |
@@ -589,32 +237,25 @@ static int omap_dss_probe(struct platform_device *pdev) | |||
589 | pdata->default_device = dssdev; | 237 | pdata->default_device = dssdev; |
590 | } | 238 | } |
591 | 239 | ||
592 | dss_clk_disable_all(); | 240 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
593 | 241 | ||
594 | return 0; | 242 | return 0; |
595 | 243 | ||
596 | err_register: | 244 | err_register: |
597 | dss_uninitialize_debugfs(); | 245 | dss_uninitialize_debugfs(); |
598 | err_debugfs: | 246 | err_debugfs: |
599 | if (cpu_is_omap34xx()) | 247 | hdmi_uninit_platform_driver(); |
600 | dsi_exit(); | 248 | err_hdmi: |
249 | dsi_uninit_platform_driver(); | ||
601 | err_dsi: | 250 | err_dsi: |
602 | if (cpu_is_omap34xx()) | 251 | venc_uninit_platform_driver(); |
603 | sdi_exit(); | ||
604 | err_sdi: | ||
605 | venc_exit(); | ||
606 | err_venc: | 252 | err_venc: |
607 | dispc_exit(); | 253 | dispc_uninit_platform_driver(); |
608 | err_dispc: | 254 | err_dispc: |
609 | dpi_exit(); | 255 | rfbi_uninit_platform_driver(); |
610 | err_dpi: | ||
611 | rfbi_exit(); | ||
612 | err_rfbi: | 256 | err_rfbi: |
613 | dss_exit(); | 257 | dss_uninit_platform_driver(); |
614 | err_dss: | 258 | err_dss: |
615 | dss_clk_disable_all_no_ctx(); | ||
616 | dss_put_clocks(); | ||
617 | err_clocks: | ||
618 | 259 | ||
619 | return r; | 260 | return r; |
620 | } | 261 | } |
@@ -623,61 +264,15 @@ static int omap_dss_remove(struct platform_device *pdev) | |||
623 | { | 264 | { |
624 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 265 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
625 | int i; | 266 | int i; |
626 | int c; | ||
627 | 267 | ||
628 | dss_uninitialize_debugfs(); | 268 | dss_uninitialize_debugfs(); |
629 | 269 | ||
630 | venc_exit(); | 270 | venc_uninit_platform_driver(); |
631 | dispc_exit(); | 271 | dispc_uninit_platform_driver(); |
632 | dpi_exit(); | 272 | rfbi_uninit_platform_driver(); |
633 | rfbi_exit(); | 273 | dsi_uninit_platform_driver(); |
634 | if (cpu_is_omap34xx()) { | 274 | hdmi_uninit_platform_driver(); |
635 | dsi_exit(); | 275 | dss_uninit_platform_driver(); |
636 | sdi_exit(); | ||
637 | } | ||
638 | |||
639 | dss_exit(); | ||
640 | |||
641 | /* these should be removed at some point */ | ||
642 | c = core.dss_ick->usecount; | ||
643 | if (c > 0) { | ||
644 | DSSERR("warning: dss_ick usecount %d, disabling\n", c); | ||
645 | while (c-- > 0) | ||
646 | clk_disable(core.dss_ick); | ||
647 | } | ||
648 | |||
649 | c = core.dss1_fck->usecount; | ||
650 | if (c > 0) { | ||
651 | DSSERR("warning: dss1_fck usecount %d, disabling\n", c); | ||
652 | while (c-- > 0) | ||
653 | clk_disable(core.dss1_fck); | ||
654 | } | ||
655 | |||
656 | c = core.dss2_fck->usecount; | ||
657 | if (c > 0) { | ||
658 | DSSERR("warning: dss2_fck usecount %d, disabling\n", c); | ||
659 | while (c-- > 0) | ||
660 | clk_disable(core.dss2_fck); | ||
661 | } | ||
662 | |||
663 | c = core.dss_54m_fck->usecount; | ||
664 | if (c > 0) { | ||
665 | DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c); | ||
666 | while (c-- > 0) | ||
667 | clk_disable(core.dss_54m_fck); | ||
668 | } | ||
669 | |||
670 | if (core.dss_96m_fck) { | ||
671 | c = core.dss_96m_fck->usecount; | ||
672 | if (c > 0) { | ||
673 | DSSERR("warning: dss_96m_fck usecount %d, disabling\n", | ||
674 | c); | ||
675 | while (c-- > 0) | ||
676 | clk_disable(core.dss_96m_fck); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | dss_put_clocks(); | ||
681 | 276 | ||
682 | dss_uninit_overlays(pdev); | 277 | dss_uninit_overlays(pdev); |
683 | dss_uninit_overlay_managers(pdev); | 278 | dss_uninit_overlay_managers(pdev); |
@@ -965,11 +560,6 @@ static void __exit omap_dss_exit(void) | |||
965 | core.vdds_sdi_reg = NULL; | 560 | core.vdds_sdi_reg = NULL; |
966 | } | 561 | } |
967 | 562 | ||
968 | if (core.vdda_dac_reg != NULL) { | ||
969 | regulator_put(core.vdda_dac_reg); | ||
970 | core.vdda_dac_reg = NULL; | ||
971 | } | ||
972 | |||
973 | platform_driver_unregister(&omap_dss_driver); | 563 | platform_driver_unregister(&omap_dss_driver); |
974 | 564 | ||
975 | omap_dss_bus_unregister(); | 565 | omap_dss_bus_unregister(); |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 9f8c69f16e61..7804779c9da1 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
35 | #include <linux/interrupt.h> | ||
35 | 36 | ||
36 | #include <plat/sram.h> | 37 | #include <plat/sram.h> |
37 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
@@ -42,8 +43,6 @@ | |||
42 | #include "dss_features.h" | 43 | #include "dss_features.h" |
43 | 44 | ||
44 | /* DISPC */ | 45 | /* DISPC */ |
45 | #define DISPC_BASE 0x48050400 | ||
46 | |||
47 | #define DISPC_SZ_REGS SZ_4K | 46 | #define DISPC_SZ_REGS SZ_4K |
48 | 47 | ||
49 | struct dispc_reg { u16 idx; }; | 48 | struct dispc_reg { u16 idx; }; |
@@ -74,7 +73,7 @@ struct dispc_reg { u16 idx; }; | |||
74 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) | 73 | #define DISPC_TIMING_H(ch) DISPC_REG(ch != 2 ? 0x0064 : 0x0400) |
75 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) | 74 | #define DISPC_TIMING_V(ch) DISPC_REG(ch != 2 ? 0x0068 : 0x0404) |
76 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) | 75 | #define DISPC_POL_FREQ(ch) DISPC_REG(ch != 2 ? 0x006C : 0x0408) |
77 | #define DISPC_DIVISOR(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) | 76 | #define DISPC_DIVISORo(ch) DISPC_REG(ch != 2 ? 0x0070 : 0x040C) |
78 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) | 77 | #define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) |
79 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) | 78 | #define DISPC_SIZE_DIG DISPC_REG(0x0078) |
80 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) | 79 | #define DISPC_SIZE_LCD(ch) DISPC_REG(ch != 2 ? 0x007C : 0x03CC) |
@@ -129,6 +128,7 @@ struct dispc_reg { u16 idx; }; | |||
129 | 128 | ||
130 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) | 129 | #define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) |
131 | 130 | ||
131 | #define DISPC_DIVISOR DISPC_REG(0x0804) | ||
132 | 132 | ||
133 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ | 133 | #define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ |
134 | DISPC_IRQ_OCP_ERR | \ | 134 | DISPC_IRQ_OCP_ERR | \ |
@@ -178,7 +178,9 @@ struct dispc_irq_stats { | |||
178 | }; | 178 | }; |
179 | 179 | ||
180 | static struct { | 180 | static struct { |
181 | struct platform_device *pdev; | ||
181 | void __iomem *base; | 182 | void __iomem *base; |
183 | int irq; | ||
182 | 184 | ||
183 | u32 fifo_size[3]; | 185 | u32 fifo_size[3]; |
184 | 186 | ||
@@ -230,7 +232,7 @@ void dispc_save_context(void) | |||
230 | SR(TIMING_H(0)); | 232 | SR(TIMING_H(0)); |
231 | SR(TIMING_V(0)); | 233 | SR(TIMING_V(0)); |
232 | SR(POL_FREQ(0)); | 234 | SR(POL_FREQ(0)); |
233 | SR(DIVISOR(0)); | 235 | SR(DIVISORo(0)); |
234 | SR(GLOBAL_ALPHA); | 236 | SR(GLOBAL_ALPHA); |
235 | SR(SIZE_DIG); | 237 | SR(SIZE_DIG); |
236 | SR(SIZE_LCD(0)); | 238 | SR(SIZE_LCD(0)); |
@@ -242,7 +244,7 @@ void dispc_save_context(void) | |||
242 | SR(TIMING_H(2)); | 244 | SR(TIMING_H(2)); |
243 | SR(TIMING_V(2)); | 245 | SR(TIMING_V(2)); |
244 | SR(POL_FREQ(2)); | 246 | SR(POL_FREQ(2)); |
245 | SR(DIVISOR(2)); | 247 | SR(DIVISORo(2)); |
246 | SR(CONFIG2); | 248 | SR(CONFIG2); |
247 | } | 249 | } |
248 | 250 | ||
@@ -373,6 +375,9 @@ void dispc_save_context(void) | |||
373 | SR(VID_FIR_COEF_V(1, 7)); | 375 | SR(VID_FIR_COEF_V(1, 7)); |
374 | 376 | ||
375 | SR(VID_PRELOAD(1)); | 377 | SR(VID_PRELOAD(1)); |
378 | |||
379 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
380 | SR(DIVISOR); | ||
376 | } | 381 | } |
377 | 382 | ||
378 | void dispc_restore_context(void) | 383 | void dispc_restore_context(void) |
@@ -389,7 +394,7 @@ void dispc_restore_context(void) | |||
389 | RR(TIMING_H(0)); | 394 | RR(TIMING_H(0)); |
390 | RR(TIMING_V(0)); | 395 | RR(TIMING_V(0)); |
391 | RR(POL_FREQ(0)); | 396 | RR(POL_FREQ(0)); |
392 | RR(DIVISOR(0)); | 397 | RR(DIVISORo(0)); |
393 | RR(GLOBAL_ALPHA); | 398 | RR(GLOBAL_ALPHA); |
394 | RR(SIZE_DIG); | 399 | RR(SIZE_DIG); |
395 | RR(SIZE_LCD(0)); | 400 | RR(SIZE_LCD(0)); |
@@ -400,7 +405,7 @@ void dispc_restore_context(void) | |||
400 | RR(TIMING_H(2)); | 405 | RR(TIMING_H(2)); |
401 | RR(TIMING_V(2)); | 406 | RR(TIMING_V(2)); |
402 | RR(POL_FREQ(2)); | 407 | RR(POL_FREQ(2)); |
403 | RR(DIVISOR(2)); | 408 | RR(DIVISORo(2)); |
404 | RR(CONFIG2); | 409 | RR(CONFIG2); |
405 | } | 410 | } |
406 | 411 | ||
@@ -532,6 +537,9 @@ void dispc_restore_context(void) | |||
532 | 537 | ||
533 | RR(VID_PRELOAD(1)); | 538 | RR(VID_PRELOAD(1)); |
534 | 539 | ||
540 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
541 | RR(DIVISOR); | ||
542 | |||
535 | /* enable last, because LCD & DIGIT enable are here */ | 543 | /* enable last, because LCD & DIGIT enable are here */ |
536 | RR(CONTROL); | 544 | RR(CONTROL); |
537 | if (dss_has_feature(FEAT_MGR_LCD2)) | 545 | if (dss_has_feature(FEAT_MGR_LCD2)) |
@@ -552,9 +560,9 @@ void dispc_restore_context(void) | |||
552 | static inline void enable_clocks(bool enable) | 560 | static inline void enable_clocks(bool enable) |
553 | { | 561 | { |
554 | if (enable) | 562 | if (enable) |
555 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 563 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
556 | else | 564 | else |
557 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 565 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
558 | } | 566 | } |
559 | 567 | ||
560 | bool dispc_go_busy(enum omap_channel channel) | 568 | bool dispc_go_busy(enum omap_channel channel) |
@@ -1000,6 +1008,20 @@ void dispc_set_burst_size(enum omap_plane plane, | |||
1000 | enable_clocks(0); | 1008 | enable_clocks(0); |
1001 | } | 1009 | } |
1002 | 1010 | ||
1011 | void dispc_enable_gamma_table(bool enable) | ||
1012 | { | ||
1013 | /* | ||
1014 | * This is partially implemented to support only disabling of | ||
1015 | * the gamma table. | ||
1016 | */ | ||
1017 | if (enable) { | ||
1018 | DSSWARN("Gamma table enabling for TV not yet supported"); | ||
1019 | return; | ||
1020 | } | ||
1021 | |||
1022 | REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); | ||
1023 | } | ||
1024 | |||
1003 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) | 1025 | static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) |
1004 | { | 1026 | { |
1005 | u32 val; | 1027 | u32 val; |
@@ -1129,10 +1151,16 @@ static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) | |||
1129 | u32 val; | 1151 | u32 val; |
1130 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), | 1152 | const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), |
1131 | DISPC_VID_ACCU0(1) }; | 1153 | DISPC_VID_ACCU0(1) }; |
1154 | u8 hor_start, hor_end, vert_start, vert_end; | ||
1132 | 1155 | ||
1133 | BUG_ON(plane == OMAP_DSS_GFX); | 1156 | BUG_ON(plane == OMAP_DSS_GFX); |
1134 | 1157 | ||
1135 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1158 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1159 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1160 | |||
1161 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1162 | FLD_VAL(haccu, hor_start, hor_end); | ||
1163 | |||
1136 | dispc_write_reg(ac0_reg[plane-1], val); | 1164 | dispc_write_reg(ac0_reg[plane-1], val); |
1137 | } | 1165 | } |
1138 | 1166 | ||
@@ -1141,10 +1169,16 @@ static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) | |||
1141 | u32 val; | 1169 | u32 val; |
1142 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), | 1170 | const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), |
1143 | DISPC_VID_ACCU1(1) }; | 1171 | DISPC_VID_ACCU1(1) }; |
1172 | u8 hor_start, hor_end, vert_start, vert_end; | ||
1144 | 1173 | ||
1145 | BUG_ON(plane == OMAP_DSS_GFX); | 1174 | BUG_ON(plane == OMAP_DSS_GFX); |
1146 | 1175 | ||
1147 | val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); | 1176 | dss_feat_get_reg_field(FEAT_REG_HORIZONTALACCU, &hor_start, &hor_end); |
1177 | dss_feat_get_reg_field(FEAT_REG_VERTICALACCU, &vert_start, &vert_end); | ||
1178 | |||
1179 | val = FLD_VAL(vaccu, vert_start, vert_end) | | ||
1180 | FLD_VAL(haccu, hor_start, hor_end); | ||
1181 | |||
1148 | dispc_write_reg(ac1_reg[plane-1], val); | 1182 | dispc_write_reg(ac1_reg[plane-1], val); |
1149 | } | 1183 | } |
1150 | 1184 | ||
@@ -1182,16 +1216,25 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1182 | _dispc_set_fir(plane, fir_hinc, fir_vinc); | 1216 | _dispc_set_fir(plane, fir_hinc, fir_vinc); |
1183 | 1217 | ||
1184 | l = dispc_read_reg(dispc_reg_att[plane]); | 1218 | l = dispc_read_reg(dispc_reg_att[plane]); |
1185 | l &= ~((0x0f << 5) | (0x3 << 21)); | ||
1186 | 1219 | ||
1220 | /* RESIZEENABLE and VERTICALTAPS */ | ||
1221 | l &= ~((0x3 << 5) | (0x1 << 21)); | ||
1187 | l |= fir_hinc ? (1 << 5) : 0; | 1222 | l |= fir_hinc ? (1 << 5) : 0; |
1188 | l |= fir_vinc ? (1 << 6) : 0; | 1223 | l |= fir_vinc ? (1 << 6) : 0; |
1224 | l |= five_taps ? (1 << 21) : 0; | ||
1189 | 1225 | ||
1190 | l |= hscaleup ? 0 : (1 << 7); | 1226 | /* VRESIZECONF and HRESIZECONF */ |
1191 | l |= vscaleup ? 0 : (1 << 8); | 1227 | if (dss_has_feature(FEAT_RESIZECONF)) { |
1228 | l &= ~(0x3 << 7); | ||
1229 | l |= hscaleup ? 0 : (1 << 7); | ||
1230 | l |= vscaleup ? 0 : (1 << 8); | ||
1231 | } | ||
1192 | 1232 | ||
1193 | l |= five_taps ? (1 << 21) : 0; | 1233 | /* LINEBUFFERSPLIT */ |
1194 | l |= five_taps ? (1 << 22) : 0; | 1234 | if (dss_has_feature(FEAT_LINEBUFFERSPLIT)) { |
1235 | l &= ~(0x1 << 22); | ||
1236 | l |= five_taps ? (1 << 22) : 0; | ||
1237 | } | ||
1195 | 1238 | ||
1196 | dispc_write_reg(dispc_reg_att[plane], l); | 1239 | dispc_write_reg(dispc_reg_att[plane], l); |
1197 | 1240 | ||
@@ -1215,9 +1258,11 @@ static void _dispc_set_scaling(enum omap_plane plane, | |||
1215 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1258 | static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1216 | bool mirroring, enum omap_color_mode color_mode) | 1259 | bool mirroring, enum omap_color_mode color_mode) |
1217 | { | 1260 | { |
1261 | bool row_repeat = false; | ||
1262 | int vidrot = 0; | ||
1263 | |||
1218 | if (color_mode == OMAP_DSS_COLOR_YUV2 || | 1264 | if (color_mode == OMAP_DSS_COLOR_YUV2 || |
1219 | color_mode == OMAP_DSS_COLOR_UYVY) { | 1265 | color_mode == OMAP_DSS_COLOR_UYVY) { |
1220 | int vidrot = 0; | ||
1221 | 1266 | ||
1222 | if (mirroring) { | 1267 | if (mirroring) { |
1223 | switch (rotation) { | 1268 | switch (rotation) { |
@@ -1251,16 +1296,15 @@ static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
1251 | } | 1296 | } |
1252 | } | 1297 | } |
1253 | 1298 | ||
1254 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | ||
1255 | |||
1256 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) | 1299 | if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) |
1257 | REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); | 1300 | row_repeat = true; |
1258 | else | 1301 | else |
1259 | REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); | 1302 | row_repeat = false; |
1260 | } else { | ||
1261 | REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); | ||
1262 | REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); | ||
1263 | } | 1303 | } |
1304 | |||
1305 | REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); | ||
1306 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | ||
1307 | REG_FLD_MOD(dispc_reg_att[plane], row_repeat ? 1 : 0, 18, 18); | ||
1264 | } | 1308 | } |
1265 | 1309 | ||
1266 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1310 | static int color_mode_to_bpp(enum omap_color_mode color_mode) |
@@ -2293,7 +2337,7 @@ static void dispc_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | |||
2293 | BUG_ON(pck_div < 2); | 2337 | BUG_ON(pck_div < 2); |
2294 | 2338 | ||
2295 | enable_clocks(1); | 2339 | enable_clocks(1); |
2296 | dispc_write_reg(DISPC_DIVISOR(channel), | 2340 | dispc_write_reg(DISPC_DIVISORo(channel), |
2297 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2341 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2298 | enable_clocks(0); | 2342 | enable_clocks(0); |
2299 | } | 2343 | } |
@@ -2302,7 +2346,7 @@ static void dispc_get_lcd_divisor(enum omap_channel channel, int *lck_div, | |||
2302 | int *pck_div) | 2346 | int *pck_div) |
2303 | { | 2347 | { |
2304 | u32 l; | 2348 | u32 l; |
2305 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2349 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2306 | *lck_div = FLD_GET(l, 23, 16); | 2350 | *lck_div = FLD_GET(l, 23, 16); |
2307 | *pck_div = FLD_GET(l, 7, 0); | 2351 | *pck_div = FLD_GET(l, 7, 0); |
2308 | } | 2352 | } |
@@ -2311,14 +2355,17 @@ unsigned long dispc_fclk_rate(void) | |||
2311 | { | 2355 | { |
2312 | unsigned long r = 0; | 2356 | unsigned long r = 0; |
2313 | 2357 | ||
2314 | if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) | 2358 | switch (dss_get_dispc_clk_source()) { |
2315 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 2359 | case DSS_CLK_SRC_FCK: |
2316 | else | 2360 | r = dss_clk_get_rate(DSS_CLK_FCK); |
2317 | #ifdef CONFIG_OMAP2_DSS_DSI | 2361 | break; |
2318 | r = dsi_get_dsi1_pll_rate(); | 2362 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
2319 | #else | 2363 | r = dsi_get_pll_hsdiv_dispc_rate(); |
2320 | BUG(); | 2364 | break; |
2321 | #endif | 2365 | default: |
2366 | BUG(); | ||
2367 | } | ||
2368 | |||
2322 | return r; | 2369 | return r; |
2323 | } | 2370 | } |
2324 | 2371 | ||
@@ -2328,47 +2375,72 @@ unsigned long dispc_lclk_rate(enum omap_channel channel) | |||
2328 | unsigned long r; | 2375 | unsigned long r; |
2329 | u32 l; | 2376 | u32 l; |
2330 | 2377 | ||
2331 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2378 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2332 | 2379 | ||
2333 | lcd = FLD_GET(l, 23, 16); | 2380 | lcd = FLD_GET(l, 23, 16); |
2334 | 2381 | ||
2335 | r = dispc_fclk_rate(); | 2382 | switch (dss_get_lcd_clk_source(channel)) { |
2383 | case DSS_CLK_SRC_FCK: | ||
2384 | r = dss_clk_get_rate(DSS_CLK_FCK); | ||
2385 | break; | ||
2386 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
2387 | r = dsi_get_pll_hsdiv_dispc_rate(); | ||
2388 | break; | ||
2389 | default: | ||
2390 | BUG(); | ||
2391 | } | ||
2336 | 2392 | ||
2337 | return r / lcd; | 2393 | return r / lcd; |
2338 | } | 2394 | } |
2339 | 2395 | ||
2340 | unsigned long dispc_pclk_rate(enum omap_channel channel) | 2396 | unsigned long dispc_pclk_rate(enum omap_channel channel) |
2341 | { | 2397 | { |
2342 | int lcd, pcd; | 2398 | int pcd; |
2343 | unsigned long r; | 2399 | unsigned long r; |
2344 | u32 l; | 2400 | u32 l; |
2345 | 2401 | ||
2346 | l = dispc_read_reg(DISPC_DIVISOR(channel)); | 2402 | l = dispc_read_reg(DISPC_DIVISORo(channel)); |
2347 | 2403 | ||
2348 | lcd = FLD_GET(l, 23, 16); | ||
2349 | pcd = FLD_GET(l, 7, 0); | 2404 | pcd = FLD_GET(l, 7, 0); |
2350 | 2405 | ||
2351 | r = dispc_fclk_rate(); | 2406 | r = dispc_lclk_rate(channel); |
2352 | 2407 | ||
2353 | return r / lcd / pcd; | 2408 | return r / pcd; |
2354 | } | 2409 | } |
2355 | 2410 | ||
2356 | void dispc_dump_clocks(struct seq_file *s) | 2411 | void dispc_dump_clocks(struct seq_file *s) |
2357 | { | 2412 | { |
2358 | int lcd, pcd; | 2413 | int lcd, pcd; |
2414 | u32 l; | ||
2415 | enum dss_clk_source dispc_clk_src = dss_get_dispc_clk_source(); | ||
2416 | enum dss_clk_source lcd_clk_src; | ||
2359 | 2417 | ||
2360 | enable_clocks(1); | 2418 | enable_clocks(1); |
2361 | 2419 | ||
2362 | seq_printf(s, "- DISPC -\n"); | 2420 | seq_printf(s, "- DISPC -\n"); |
2363 | 2421 | ||
2364 | seq_printf(s, "dispc fclk source = %s\n", | 2422 | seq_printf(s, "dispc fclk source = %s (%s)\n", |
2365 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 2423 | dss_get_generic_clk_source_name(dispc_clk_src), |
2366 | "dss1_alwon_fclk" : "dsi1_pll_fclk"); | 2424 | dss_feat_get_clk_source_name(dispc_clk_src)); |
2367 | 2425 | ||
2368 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); | 2426 | seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); |
2369 | 2427 | ||
2428 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
2429 | seq_printf(s, "- DISPC-CORE-CLK -\n"); | ||
2430 | l = dispc_read_reg(DISPC_DIVISOR); | ||
2431 | lcd = FLD_GET(l, 23, 16); | ||
2432 | |||
2433 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | ||
2434 | (dispc_fclk_rate()/lcd), lcd); | ||
2435 | } | ||
2370 | seq_printf(s, "- LCD1 -\n"); | 2436 | seq_printf(s, "- LCD1 -\n"); |
2371 | 2437 | ||
2438 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD); | ||
2439 | |||
2440 | seq_printf(s, "lcd1_clk source = %s (%s)\n", | ||
2441 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2442 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2443 | |||
2372 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); | 2444 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD, &lcd, &pcd); |
2373 | 2445 | ||
2374 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2446 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
@@ -2378,6 +2450,12 @@ void dispc_dump_clocks(struct seq_file *s) | |||
2378 | if (dss_has_feature(FEAT_MGR_LCD2)) { | 2450 | if (dss_has_feature(FEAT_MGR_LCD2)) { |
2379 | seq_printf(s, "- LCD2 -\n"); | 2451 | seq_printf(s, "- LCD2 -\n"); |
2380 | 2452 | ||
2453 | lcd_clk_src = dss_get_lcd_clk_source(OMAP_DSS_CHANNEL_LCD2); | ||
2454 | |||
2455 | seq_printf(s, "lcd2_clk source = %s (%s)\n", | ||
2456 | dss_get_generic_clk_source_name(lcd_clk_src), | ||
2457 | dss_feat_get_clk_source_name(lcd_clk_src)); | ||
2458 | |||
2381 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); | 2459 | dispc_get_lcd_divisor(OMAP_DSS_CHANNEL_LCD2, &lcd, &pcd); |
2382 | 2460 | ||
2383 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", | 2461 | seq_printf(s, "lck\t\t%-16lulck div\t%u\n", |
@@ -2440,7 +2518,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2440 | { | 2518 | { |
2441 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) | 2519 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) |
2442 | 2520 | ||
2443 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2521 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
2444 | 2522 | ||
2445 | DUMPREG(DISPC_REVISION); | 2523 | DUMPREG(DISPC_REVISION); |
2446 | DUMPREG(DISPC_SYSCONFIG); | 2524 | DUMPREG(DISPC_SYSCONFIG); |
@@ -2459,7 +2537,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2459 | DUMPREG(DISPC_TIMING_H(0)); | 2537 | DUMPREG(DISPC_TIMING_H(0)); |
2460 | DUMPREG(DISPC_TIMING_V(0)); | 2538 | DUMPREG(DISPC_TIMING_V(0)); |
2461 | DUMPREG(DISPC_POL_FREQ(0)); | 2539 | DUMPREG(DISPC_POL_FREQ(0)); |
2462 | DUMPREG(DISPC_DIVISOR(0)); | 2540 | DUMPREG(DISPC_DIVISORo(0)); |
2463 | DUMPREG(DISPC_GLOBAL_ALPHA); | 2541 | DUMPREG(DISPC_GLOBAL_ALPHA); |
2464 | DUMPREG(DISPC_SIZE_DIG); | 2542 | DUMPREG(DISPC_SIZE_DIG); |
2465 | DUMPREG(DISPC_SIZE_LCD(0)); | 2543 | DUMPREG(DISPC_SIZE_LCD(0)); |
@@ -2471,7 +2549,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2471 | DUMPREG(DISPC_TIMING_H(2)); | 2549 | DUMPREG(DISPC_TIMING_H(2)); |
2472 | DUMPREG(DISPC_TIMING_V(2)); | 2550 | DUMPREG(DISPC_TIMING_V(2)); |
2473 | DUMPREG(DISPC_POL_FREQ(2)); | 2551 | DUMPREG(DISPC_POL_FREQ(2)); |
2474 | DUMPREG(DISPC_DIVISOR(2)); | 2552 | DUMPREG(DISPC_DIVISORo(2)); |
2475 | DUMPREG(DISPC_SIZE_LCD(2)); | 2553 | DUMPREG(DISPC_SIZE_LCD(2)); |
2476 | } | 2554 | } |
2477 | 2555 | ||
@@ -2597,7 +2675,7 @@ void dispc_dump_regs(struct seq_file *s) | |||
2597 | DUMPREG(DISPC_VID_PRELOAD(0)); | 2675 | DUMPREG(DISPC_VID_PRELOAD(0)); |
2598 | DUMPREG(DISPC_VID_PRELOAD(1)); | 2676 | DUMPREG(DISPC_VID_PRELOAD(1)); |
2599 | 2677 | ||
2600 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 2678 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
2601 | #undef DUMPREG | 2679 | #undef DUMPREG |
2602 | } | 2680 | } |
2603 | 2681 | ||
@@ -2713,8 +2791,8 @@ int dispc_get_clock_div(enum omap_channel channel, | |||
2713 | 2791 | ||
2714 | fck = dispc_fclk_rate(); | 2792 | fck = dispc_fclk_rate(); |
2715 | 2793 | ||
2716 | cinfo->lck_div = REG_GET(DISPC_DIVISOR(channel), 23, 16); | 2794 | cinfo->lck_div = REG_GET(DISPC_DIVISORo(channel), 23, 16); |
2717 | cinfo->pck_div = REG_GET(DISPC_DIVISOR(channel), 7, 0); | 2795 | cinfo->pck_div = REG_GET(DISPC_DIVISORo(channel), 7, 0); |
2718 | 2796 | ||
2719 | cinfo->lck = fck / cinfo->lck_div; | 2797 | cinfo->lck = fck / cinfo->lck_div; |
2720 | cinfo->pck = cinfo->lck / cinfo->pck_div; | 2798 | cinfo->pck = cinfo->lck / cinfo->pck_div; |
@@ -2791,6 +2869,9 @@ int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) | |||
2791 | break; | 2869 | break; |
2792 | } | 2870 | } |
2793 | 2871 | ||
2872 | if (ret) | ||
2873 | goto err; | ||
2874 | |||
2794 | _omap_dispc_set_irqs(); | 2875 | _omap_dispc_set_irqs(); |
2795 | 2876 | ||
2796 | spin_unlock_irqrestore(&dispc.irq_lock, flags); | 2877 | spin_unlock_irqrestore(&dispc.irq_lock, flags); |
@@ -2866,10 +2947,10 @@ static void print_irq_status(u32 status) | |||
2866 | * but we presume they are on because we got an IRQ. However, | 2947 | * but we presume they are on because we got an IRQ. However, |
2867 | * an irq handler may turn the clocks off, so we may not have | 2948 | * an irq handler may turn the clocks off, so we may not have |
2868 | * clock later in the function. */ | 2949 | * clock later in the function. */ |
2869 | void dispc_irq_handler(void) | 2950 | static irqreturn_t omap_dispc_irq_handler(int irq, void *arg) |
2870 | { | 2951 | { |
2871 | int i; | 2952 | int i; |
2872 | u32 irqstatus; | 2953 | u32 irqstatus, irqenable; |
2873 | u32 handledirqs = 0; | 2954 | u32 handledirqs = 0; |
2874 | u32 unhandled_errors; | 2955 | u32 unhandled_errors; |
2875 | struct omap_dispc_isr_data *isr_data; | 2956 | struct omap_dispc_isr_data *isr_data; |
@@ -2878,6 +2959,13 @@ void dispc_irq_handler(void) | |||
2878 | spin_lock(&dispc.irq_lock); | 2959 | spin_lock(&dispc.irq_lock); |
2879 | 2960 | ||
2880 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); | 2961 | irqstatus = dispc_read_reg(DISPC_IRQSTATUS); |
2962 | irqenable = dispc_read_reg(DISPC_IRQENABLE); | ||
2963 | |||
2964 | /* IRQ is not for us */ | ||
2965 | if (!(irqstatus & irqenable)) { | ||
2966 | spin_unlock(&dispc.irq_lock); | ||
2967 | return IRQ_NONE; | ||
2968 | } | ||
2881 | 2969 | ||
2882 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 2970 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
2883 | spin_lock(&dispc.irq_stats_lock); | 2971 | spin_lock(&dispc.irq_stats_lock); |
@@ -2929,6 +3017,8 @@ void dispc_irq_handler(void) | |||
2929 | } | 3017 | } |
2930 | 3018 | ||
2931 | spin_unlock(&dispc.irq_lock); | 3019 | spin_unlock(&dispc.irq_lock); |
3020 | |||
3021 | return IRQ_HANDLED; | ||
2932 | } | 3022 | } |
2933 | 3023 | ||
2934 | static void dispc_error_worker(struct work_struct *work) | 3024 | static void dispc_error_worker(struct work_struct *work) |
@@ -3253,6 +3343,15 @@ static void _omap_dispc_initial_config(void) | |||
3253 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ | 3343 | l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ |
3254 | dispc_write_reg(DISPC_SYSCONFIG, l); | 3344 | dispc_write_reg(DISPC_SYSCONFIG, l); |
3255 | 3345 | ||
3346 | /* Exclusively enable DISPC_CORE_CLK and set divider to 1 */ | ||
3347 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) { | ||
3348 | l = dispc_read_reg(DISPC_DIVISOR); | ||
3349 | /* Use DISPC_DIVISOR.LCD, instead of DISPC_DIVISOR1.LCD */ | ||
3350 | l = FLD_MOD(l, 1, 0, 0); | ||
3351 | l = FLD_MOD(l, 1, 23, 16); | ||
3352 | dispc_write_reg(DISPC_DIVISOR, l); | ||
3353 | } | ||
3354 | |||
3256 | /* FUNCGATED */ | 3355 | /* FUNCGATED */ |
3257 | if (dss_has_feature(FEAT_FUNCGATED)) | 3356 | if (dss_has_feature(FEAT_FUNCGATED)) |
3258 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); | 3357 | REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); |
@@ -3269,47 +3368,6 @@ static void _omap_dispc_initial_config(void) | |||
3269 | dispc_read_plane_fifo_sizes(); | 3368 | dispc_read_plane_fifo_sizes(); |
3270 | } | 3369 | } |
3271 | 3370 | ||
3272 | int dispc_init(void) | ||
3273 | { | ||
3274 | u32 rev; | ||
3275 | |||
3276 | spin_lock_init(&dispc.irq_lock); | ||
3277 | |||
3278 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3279 | spin_lock_init(&dispc.irq_stats_lock); | ||
3280 | dispc.irq_stats.last_reset = jiffies; | ||
3281 | #endif | ||
3282 | |||
3283 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3284 | |||
3285 | dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); | ||
3286 | if (!dispc.base) { | ||
3287 | DSSERR("can't ioremap DISPC\n"); | ||
3288 | return -ENOMEM; | ||
3289 | } | ||
3290 | |||
3291 | enable_clocks(1); | ||
3292 | |||
3293 | _omap_dispc_initial_config(); | ||
3294 | |||
3295 | _omap_dispc_initialize_irq(); | ||
3296 | |||
3297 | dispc_save_context(); | ||
3298 | |||
3299 | rev = dispc_read_reg(DISPC_REVISION); | ||
3300 | printk(KERN_INFO "OMAP DISPC rev %d.%d\n", | ||
3301 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3302 | |||
3303 | enable_clocks(0); | ||
3304 | |||
3305 | return 0; | ||
3306 | } | ||
3307 | |||
3308 | void dispc_exit(void) | ||
3309 | { | ||
3310 | iounmap(dispc.base); | ||
3311 | } | ||
3312 | |||
3313 | int dispc_enable_plane(enum omap_plane plane, bool enable) | 3371 | int dispc_enable_plane(enum omap_plane plane, bool enable) |
3314 | { | 3372 | { |
3315 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); | 3373 | DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); |
@@ -3359,3 +3417,94 @@ int dispc_setup_plane(enum omap_plane plane, | |||
3359 | 3417 | ||
3360 | return r; | 3418 | return r; |
3361 | } | 3419 | } |
3420 | |||
3421 | /* DISPC HW IP initialisation */ | ||
3422 | static int omap_dispchw_probe(struct platform_device *pdev) | ||
3423 | { | ||
3424 | u32 rev; | ||
3425 | int r = 0; | ||
3426 | struct resource *dispc_mem; | ||
3427 | |||
3428 | dispc.pdev = pdev; | ||
3429 | |||
3430 | spin_lock_init(&dispc.irq_lock); | ||
3431 | |||
3432 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
3433 | spin_lock_init(&dispc.irq_stats_lock); | ||
3434 | dispc.irq_stats.last_reset = jiffies; | ||
3435 | #endif | ||
3436 | |||
3437 | INIT_WORK(&dispc.error_work, dispc_error_worker); | ||
3438 | |||
3439 | dispc_mem = platform_get_resource(dispc.pdev, IORESOURCE_MEM, 0); | ||
3440 | if (!dispc_mem) { | ||
3441 | DSSERR("can't get IORESOURCE_MEM DISPC\n"); | ||
3442 | r = -EINVAL; | ||
3443 | goto fail0; | ||
3444 | } | ||
3445 | dispc.base = ioremap(dispc_mem->start, resource_size(dispc_mem)); | ||
3446 | if (!dispc.base) { | ||
3447 | DSSERR("can't ioremap DISPC\n"); | ||
3448 | r = -ENOMEM; | ||
3449 | goto fail0; | ||
3450 | } | ||
3451 | dispc.irq = platform_get_irq(dispc.pdev, 0); | ||
3452 | if (dispc.irq < 0) { | ||
3453 | DSSERR("platform_get_irq failed\n"); | ||
3454 | r = -ENODEV; | ||
3455 | goto fail1; | ||
3456 | } | ||
3457 | |||
3458 | r = request_irq(dispc.irq, omap_dispc_irq_handler, IRQF_SHARED, | ||
3459 | "OMAP DISPC", dispc.pdev); | ||
3460 | if (r < 0) { | ||
3461 | DSSERR("request_irq failed\n"); | ||
3462 | goto fail1; | ||
3463 | } | ||
3464 | |||
3465 | enable_clocks(1); | ||
3466 | |||
3467 | _omap_dispc_initial_config(); | ||
3468 | |||
3469 | _omap_dispc_initialize_irq(); | ||
3470 | |||
3471 | dispc_save_context(); | ||
3472 | |||
3473 | rev = dispc_read_reg(DISPC_REVISION); | ||
3474 | dev_dbg(&pdev->dev, "OMAP DISPC rev %d.%d\n", | ||
3475 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
3476 | |||
3477 | enable_clocks(0); | ||
3478 | |||
3479 | return 0; | ||
3480 | fail1: | ||
3481 | iounmap(dispc.base); | ||
3482 | fail0: | ||
3483 | return r; | ||
3484 | } | ||
3485 | |||
3486 | static int omap_dispchw_remove(struct platform_device *pdev) | ||
3487 | { | ||
3488 | free_irq(dispc.irq, dispc.pdev); | ||
3489 | iounmap(dispc.base); | ||
3490 | return 0; | ||
3491 | } | ||
3492 | |||
3493 | static struct platform_driver omap_dispchw_driver = { | ||
3494 | .probe = omap_dispchw_probe, | ||
3495 | .remove = omap_dispchw_remove, | ||
3496 | .driver = { | ||
3497 | .name = "omapdss_dispc", | ||
3498 | .owner = THIS_MODULE, | ||
3499 | }, | ||
3500 | }; | ||
3501 | |||
3502 | int dispc_init_platform_driver(void) | ||
3503 | { | ||
3504 | return platform_driver_register(&omap_dispchw_driver); | ||
3505 | } | ||
3506 | |||
3507 | void dispc_uninit_platform_driver(void) | ||
3508 | { | ||
3509 | return platform_driver_unregister(&omap_dispchw_driver); | ||
3510 | } | ||
diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/omap2/dss/display.c index 22dd7a474f79..a85a6f38b40c 100644 --- a/drivers/video/omap2/dss/display.c +++ b/drivers/video/omap2/dss/display.c | |||
@@ -25,14 +25,11 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/list.h> | ||
29 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
30 | 29 | ||
31 | #include <plat/display.h> | 30 | #include <plat/display.h> |
32 | #include "dss.h" | 31 | #include "dss.h" |
33 | 32 | ||
34 | static LIST_HEAD(display_list); | ||
35 | |||
36 | static ssize_t display_enabled_show(struct device *dev, | 33 | static ssize_t display_enabled_show(struct device *dev, |
37 | struct device_attribute *attr, char *buf) | 34 | struct device_attribute *attr, char *buf) |
38 | { | 35 | { |
@@ -345,6 +342,7 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) | |||
345 | return 16; | 342 | return 16; |
346 | case OMAP_DISPLAY_TYPE_VENC: | 343 | case OMAP_DISPLAY_TYPE_VENC: |
347 | case OMAP_DISPLAY_TYPE_SDI: | 344 | case OMAP_DISPLAY_TYPE_SDI: |
345 | case OMAP_DISPLAY_TYPE_HDMI: | ||
348 | return 24; | 346 | return 24; |
349 | default: | 347 | default: |
350 | BUG(); | 348 | BUG(); |
@@ -371,6 +369,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev, | |||
371 | case OMAP_DISPLAY_TYPE_DPI: | 369 | case OMAP_DISPLAY_TYPE_DPI: |
372 | bpp = dssdev->phy.dpi.data_lines; | 370 | bpp = dssdev->phy.dpi.data_lines; |
373 | break; | 371 | break; |
372 | case OMAP_DISPLAY_TYPE_HDMI: | ||
374 | case OMAP_DISPLAY_TYPE_VENC: | 373 | case OMAP_DISPLAY_TYPE_VENC: |
375 | case OMAP_DISPLAY_TYPE_SDI: | 374 | case OMAP_DISPLAY_TYPE_SDI: |
376 | bpp = 24; | 375 | bpp = 24; |
@@ -396,29 +395,6 @@ void dss_init_device(struct platform_device *pdev, | |||
396 | switch (dssdev->type) { | 395 | switch (dssdev->type) { |
397 | #ifdef CONFIG_OMAP2_DSS_DPI | 396 | #ifdef CONFIG_OMAP2_DSS_DPI |
398 | case OMAP_DISPLAY_TYPE_DPI: | 397 | case OMAP_DISPLAY_TYPE_DPI: |
399 | #endif | ||
400 | #ifdef CONFIG_OMAP2_DSS_RFBI | ||
401 | case OMAP_DISPLAY_TYPE_DBI: | ||
402 | #endif | ||
403 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
404 | case OMAP_DISPLAY_TYPE_SDI: | ||
405 | #endif | ||
406 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
407 | case OMAP_DISPLAY_TYPE_DSI: | ||
408 | #endif | ||
409 | #ifdef CONFIG_OMAP2_DSS_VENC | ||
410 | case OMAP_DISPLAY_TYPE_VENC: | ||
411 | #endif | ||
412 | break; | ||
413 | default: | ||
414 | DSSERR("Support for display '%s' not compiled in.\n", | ||
415 | dssdev->name); | ||
416 | return; | ||
417 | } | ||
418 | |||
419 | switch (dssdev->type) { | ||
420 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
421 | case OMAP_DISPLAY_TYPE_DPI: | ||
422 | r = dpi_init_display(dssdev); | 398 | r = dpi_init_display(dssdev); |
423 | break; | 399 | break; |
424 | #endif | 400 | #endif |
@@ -442,8 +418,13 @@ void dss_init_device(struct platform_device *pdev, | |||
442 | r = dsi_init_display(dssdev); | 418 | r = dsi_init_display(dssdev); |
443 | break; | 419 | break; |
444 | #endif | 420 | #endif |
421 | case OMAP_DISPLAY_TYPE_HDMI: | ||
422 | r = hdmi_init_display(dssdev); | ||
423 | break; | ||
445 | default: | 424 | default: |
446 | BUG(); | 425 | DSSERR("Support for display '%s' not compiled in.\n", |
426 | dssdev->name); | ||
427 | return; | ||
447 | } | 428 | } |
448 | 429 | ||
449 | if (r) { | 430 | if (r) { |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 75fb0a515430..2d3ca4ca4a05 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -57,13 +57,13 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft, | |||
57 | if (r) | 57 | if (r) |
58 | return r; | 58 | return r; |
59 | 59 | ||
60 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 60 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); |
61 | 61 | ||
62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); | 62 | r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo); |
63 | if (r) | 63 | if (r) |
64 | return r; | 64 | return r; |
65 | 65 | ||
66 | *fck = dsi_cinfo.dsi1_pll_fclk; | 66 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
67 | *lck_div = dispc_cinfo.lck_div; | 67 | *lck_div = dispc_cinfo.lck_div; |
68 | *pck_div = dispc_cinfo.pck_div; | 68 | *pck_div = dispc_cinfo.pck_div; |
69 | 69 | ||
@@ -107,7 +107,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
107 | bool is_tft; | 107 | bool is_tft; |
108 | int r = 0; | 108 | int r = 0; |
109 | 109 | ||
110 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 110 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
111 | 111 | ||
112 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 112 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
113 | dssdev->panel.acbi, dssdev->panel.acb); | 113 | dssdev->panel.acbi, dssdev->panel.acb); |
@@ -137,7 +137,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
137 | dispc_set_lcd_timings(dssdev->manager->id, t); | 137 | dispc_set_lcd_timings(dssdev->manager->id, t); |
138 | 138 | ||
139 | err0: | 139 | err0: |
140 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 140 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
141 | return r; | 141 | return r; |
142 | } | 142 | } |
143 | 143 | ||
@@ -173,14 +173,14 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
173 | goto err1; | 173 | goto err1; |
174 | } | 174 | } |
175 | 175 | ||
176 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 176 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
177 | 177 | ||
178 | r = dpi_basic_init(dssdev); | 178 | r = dpi_basic_init(dssdev); |
179 | if (r) | 179 | if (r) |
180 | goto err2; | 180 | goto err2; |
181 | 181 | ||
182 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 182 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
183 | dss_clk_enable(DSS_CLK_FCK2); | 183 | dss_clk_enable(DSS_CLK_SYSCK); |
184 | r = dsi_pll_init(dssdev, 0, 1); | 184 | r = dsi_pll_init(dssdev, 0, 1); |
185 | if (r) | 185 | if (r) |
186 | goto err3; | 186 | goto err3; |
@@ -199,10 +199,10 @@ err4: | |||
199 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 199 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
200 | dsi_pll_uninit(); | 200 | dsi_pll_uninit(); |
201 | err3: | 201 | err3: |
202 | dss_clk_disable(DSS_CLK_FCK2); | 202 | dss_clk_disable(DSS_CLK_SYSCK); |
203 | #endif | 203 | #endif |
204 | err2: | 204 | err2: |
205 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 205 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
206 | if (cpu_is_omap34xx()) | 206 | if (cpu_is_omap34xx()) |
207 | regulator_disable(dpi.vdds_dsi_reg); | 207 | regulator_disable(dpi.vdds_dsi_reg); |
208 | err1: | 208 | err1: |
@@ -217,12 +217,12 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | |||
217 | dssdev->manager->disable(dssdev->manager); | 217 | dssdev->manager->disable(dssdev->manager); |
218 | 218 | ||
219 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | 219 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL |
220 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 220 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
221 | dsi_pll_uninit(); | 221 | dsi_pll_uninit(); |
222 | dss_clk_disable(DSS_CLK_FCK2); | 222 | dss_clk_disable(DSS_CLK_SYSCK); |
223 | #endif | 223 | #endif |
224 | 224 | ||
225 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 225 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
226 | 226 | ||
227 | if (cpu_is_omap34xx()) | 227 | if (cpu_is_omap34xx()) |
228 | regulator_disable(dpi.vdds_dsi_reg); | 228 | regulator_disable(dpi.vdds_dsi_reg); |
@@ -271,7 +271,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
271 | if (r) | 271 | if (r) |
272 | return r; | 272 | return r; |
273 | 273 | ||
274 | fck = dsi_cinfo.dsi1_pll_fclk; | 274 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
275 | lck_div = dispc_cinfo.lck_div; | 275 | lck_div = dispc_cinfo.lck_div; |
276 | pck_div = dispc_cinfo.pck_div; | 276 | pck_div = dispc_cinfo.pck_div; |
277 | } | 277 | } |
@@ -303,22 +303,27 @@ int dpi_init_display(struct omap_dss_device *dssdev) | |||
303 | { | 303 | { |
304 | DSSDBG("init_display\n"); | 304 | DSSDBG("init_display\n"); |
305 | 305 | ||
306 | return 0; | 306 | if (cpu_is_omap34xx() && dpi.vdds_dsi_reg == NULL) { |
307 | } | 307 | struct regulator *vdds_dsi; |
308 | 308 | ||
309 | int dpi_init(struct platform_device *pdev) | 309 | vdds_dsi = dss_get_vdds_dsi(); |
310 | { | 310 | |
311 | if (cpu_is_omap34xx()) { | 311 | if (IS_ERR(vdds_dsi)) { |
312 | dpi.vdds_dsi_reg = dss_get_vdds_dsi(); | ||
313 | if (IS_ERR(dpi.vdds_dsi_reg)) { | ||
314 | DSSERR("can't get VDDS_DSI regulator\n"); | 312 | DSSERR("can't get VDDS_DSI regulator\n"); |
315 | return PTR_ERR(dpi.vdds_dsi_reg); | 313 | return PTR_ERR(vdds_dsi); |
316 | } | 314 | } |
315 | |||
316 | dpi.vdds_dsi_reg = vdds_dsi; | ||
317 | } | 317 | } |
318 | 318 | ||
319 | return 0; | 319 | return 0; |
320 | } | 320 | } |
321 | 321 | ||
322 | int dpi_init(void) | ||
323 | { | ||
324 | return 0; | ||
325 | } | ||
326 | |||
322 | void dpi_exit(void) | 327 | void dpi_exit(void) |
323 | { | 328 | { |
324 | } | 329 | } |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index ddf3a0560822..0a7f1a47f8e3 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -38,12 +38,11 @@ | |||
38 | #include <plat/clock.h> | 38 | #include <plat/clock.h> |
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | #include "dss_features.h" | ||
41 | 42 | ||
42 | /*#define VERBOSE_IRQ*/ | 43 | /*#define VERBOSE_IRQ*/ |
43 | #define DSI_CATCH_MISSING_TE | 44 | #define DSI_CATCH_MISSING_TE |
44 | 45 | ||
45 | #define DSI_BASE 0x4804FC00 | ||
46 | |||
47 | struct dsi_reg { u16 idx; }; | 46 | struct dsi_reg { u16 idx; }; |
48 | 47 | ||
49 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) | 48 | #define DSI_REG(idx) ((const struct dsi_reg) { idx }) |
@@ -186,13 +185,15 @@ struct dsi_reg { u16 idx; }; | |||
186 | #define DSI_DT_RX_SHORT_READ_1 0x21 | 185 | #define DSI_DT_RX_SHORT_READ_1 0x21 |
187 | #define DSI_DT_RX_SHORT_READ_2 0x22 | 186 | #define DSI_DT_RX_SHORT_READ_2 0x22 |
188 | 187 | ||
189 | #define FINT_MAX 2100000 | 188 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
190 | #define FINT_MIN 750000 | 189 | |
191 | #define REGN_MAX (1 << 7) | 190 | #define DSI_MAX_NR_ISRS 2 |
192 | #define REGM_MAX ((1 << 11) - 1) | 191 | |
193 | #define REGM3_MAX (1 << 4) | 192 | struct dsi_isr_data { |
194 | #define REGM4_MAX (1 << 4) | 193 | omap_dsi_isr_t isr; |
195 | #define LP_DIV_MAX ((1 << 13) - 1) | 194 | void *arg; |
195 | u32 mask; | ||
196 | }; | ||
196 | 197 | ||
197 | enum fifo_size { | 198 | enum fifo_size { |
198 | DSI_FIFO_SIZE_0 = 0, | 199 | DSI_FIFO_SIZE_0 = 0, |
@@ -220,9 +221,17 @@ struct dsi_irq_stats { | |||
220 | unsigned cio_irqs[32]; | 221 | unsigned cio_irqs[32]; |
221 | }; | 222 | }; |
222 | 223 | ||
224 | struct dsi_isr_tables { | ||
225 | struct dsi_isr_data isr_table[DSI_MAX_NR_ISRS]; | ||
226 | struct dsi_isr_data isr_table_vc[4][DSI_MAX_NR_ISRS]; | ||
227 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | ||
228 | }; | ||
229 | |||
223 | static struct | 230 | static struct |
224 | { | 231 | { |
232 | struct platform_device *pdev; | ||
225 | void __iomem *base; | 233 | void __iomem *base; |
234 | int irq; | ||
226 | 235 | ||
227 | struct dsi_clock_info current_cinfo; | 236 | struct dsi_clock_info current_cinfo; |
228 | 237 | ||
@@ -232,6 +241,7 @@ static struct | |||
232 | enum dsi_vc_mode mode; | 241 | enum dsi_vc_mode mode; |
233 | struct omap_dss_device *dssdev; | 242 | struct omap_dss_device *dssdev; |
234 | enum fifo_size fifo_size; | 243 | enum fifo_size fifo_size; |
244 | int vc_id; | ||
235 | } vc[4]; | 245 | } vc[4]; |
236 | 246 | ||
237 | struct mutex lock; | 247 | struct mutex lock; |
@@ -239,8 +249,10 @@ static struct | |||
239 | 249 | ||
240 | unsigned pll_locked; | 250 | unsigned pll_locked; |
241 | 251 | ||
242 | struct completion bta_completion; | 252 | spinlock_t irq_lock; |
243 | void (*bta_callback)(void); | 253 | struct dsi_isr_tables isr_tables; |
254 | /* space for a copy used by the interrupt handler */ | ||
255 | struct dsi_isr_tables isr_tables_copy; | ||
244 | 256 | ||
245 | int update_channel; | 257 | int update_channel; |
246 | struct dsi_update_region update_region; | 258 | struct dsi_update_region update_region; |
@@ -275,6 +287,11 @@ static struct | |||
275 | spinlock_t irq_stats_lock; | 287 | spinlock_t irq_stats_lock; |
276 | struct dsi_irq_stats irq_stats; | 288 | struct dsi_irq_stats irq_stats; |
277 | #endif | 289 | #endif |
290 | /* DSI PLL Parameter Ranges */ | ||
291 | unsigned long regm_max, regn_max; | ||
292 | unsigned long regm_dispc_max, regm_dsi_max; | ||
293 | unsigned long fint_min, fint_max; | ||
294 | unsigned long lpdiv_max; | ||
278 | } dsi; | 295 | } dsi; |
279 | 296 | ||
280 | #ifdef DEBUG | 297 | #ifdef DEBUG |
@@ -318,6 +335,11 @@ static bool dsi_bus_is_locked(void) | |||
318 | return dsi.bus_lock.count == 0; | 335 | return dsi.bus_lock.count == 0; |
319 | } | 336 | } |
320 | 337 | ||
338 | static void dsi_completion_handler(void *data, u32 mask) | ||
339 | { | ||
340 | complete((struct completion *)data); | ||
341 | } | ||
342 | |||
321 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, | 343 | static inline int wait_for_bit_change(const struct dsi_reg idx, int bitnum, |
322 | int value) | 344 | int value) |
323 | { | 345 | { |
@@ -387,6 +409,9 @@ static void dsi_perf_show(const char *name) | |||
387 | 409 | ||
388 | static void print_irq_status(u32 status) | 410 | static void print_irq_status(u32 status) |
389 | { | 411 | { |
412 | if (status == 0) | ||
413 | return; | ||
414 | |||
390 | #ifndef VERBOSE_IRQ | 415 | #ifndef VERBOSE_IRQ |
391 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) | 416 | if ((status & ~DSI_IRQ_CHANNEL_MASK) == 0) |
392 | return; | 417 | return; |
@@ -422,6 +447,9 @@ static void print_irq_status(u32 status) | |||
422 | 447 | ||
423 | static void print_irq_status_vc(int channel, u32 status) | 448 | static void print_irq_status_vc(int channel, u32 status) |
424 | { | 449 | { |
450 | if (status == 0) | ||
451 | return; | ||
452 | |||
425 | #ifndef VERBOSE_IRQ | 453 | #ifndef VERBOSE_IRQ |
426 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) | 454 | if ((status & ~DSI_VC_IRQ_PACKET_SENT) == 0) |
427 | return; | 455 | return; |
@@ -448,6 +476,9 @@ static void print_irq_status_vc(int channel, u32 status) | |||
448 | 476 | ||
449 | static void print_irq_status_cio(u32 status) | 477 | static void print_irq_status_cio(u32 status) |
450 | { | 478 | { |
479 | if (status == 0) | ||
480 | return; | ||
481 | |||
451 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); | 482 | printk(KERN_DEBUG "DSI CIO IRQ 0x%x: ", status); |
452 | 483 | ||
453 | #define PIS(x) \ | 484 | #define PIS(x) \ |
@@ -478,22 +509,33 @@ static void print_irq_status_cio(u32 status) | |||
478 | printk("\n"); | 509 | printk("\n"); |
479 | } | 510 | } |
480 | 511 | ||
481 | static int debug_irq; | 512 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS |
482 | 513 | static void dsi_collect_irq_stats(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | |
483 | /* called from dss */ | ||
484 | void dsi_irq_handler(void) | ||
485 | { | 514 | { |
486 | u32 irqstatus, vcstatus, ciostatus; | ||
487 | int i; | 515 | int i; |
488 | 516 | ||
489 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); | ||
490 | |||
491 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
492 | spin_lock(&dsi.irq_stats_lock); | 517 | spin_lock(&dsi.irq_stats_lock); |
518 | |||
493 | dsi.irq_stats.irq_count++; | 519 | dsi.irq_stats.irq_count++; |
494 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); | 520 | dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs); |
521 | |||
522 | for (i = 0; i < 4; ++i) | ||
523 | dss_collect_irq_stats(vcstatus[i], dsi.irq_stats.vc_irqs[i]); | ||
524 | |||
525 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
526 | |||
527 | spin_unlock(&dsi.irq_stats_lock); | ||
528 | } | ||
529 | #else | ||
530 | #define dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus) | ||
495 | #endif | 531 | #endif |
496 | 532 | ||
533 | static int debug_irq; | ||
534 | |||
535 | static void dsi_handle_irq_errors(u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
536 | { | ||
537 | int i; | ||
538 | |||
497 | if (irqstatus & DSI_IRQ_ERROR_MASK) { | 539 | if (irqstatus & DSI_IRQ_ERROR_MASK) { |
498 | DSSERR("DSI error, irqstatus %x\n", irqstatus); | 540 | DSSERR("DSI error, irqstatus %x\n", irqstatus); |
499 | print_irq_status(irqstatus); | 541 | print_irq_status(irqstatus); |
@@ -504,37 +546,88 @@ void dsi_irq_handler(void) | |||
504 | print_irq_status(irqstatus); | 546 | print_irq_status(irqstatus); |
505 | } | 547 | } |
506 | 548 | ||
507 | #ifdef DSI_CATCH_MISSING_TE | 549 | for (i = 0; i < 4; ++i) { |
508 | if (irqstatus & DSI_IRQ_TE_TRIGGER) | 550 | if (vcstatus[i] & DSI_VC_IRQ_ERROR_MASK) { |
509 | del_timer(&dsi.te_timer); | 551 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", |
510 | #endif | 552 | i, vcstatus[i]); |
553 | print_irq_status_vc(i, vcstatus[i]); | ||
554 | } else if (debug_irq) { | ||
555 | print_irq_status_vc(i, vcstatus[i]); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | ||
560 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | ||
561 | print_irq_status_cio(ciostatus); | ||
562 | } else if (debug_irq) { | ||
563 | print_irq_status_cio(ciostatus); | ||
564 | } | ||
565 | } | ||
566 | |||
567 | static void dsi_call_isrs(struct dsi_isr_data *isr_array, | ||
568 | unsigned isr_array_size, u32 irqstatus) | ||
569 | { | ||
570 | struct dsi_isr_data *isr_data; | ||
571 | int i; | ||
572 | |||
573 | for (i = 0; i < isr_array_size; i++) { | ||
574 | isr_data = &isr_array[i]; | ||
575 | if (isr_data->isr && isr_data->mask & irqstatus) | ||
576 | isr_data->isr(isr_data->arg, irqstatus); | ||
577 | } | ||
578 | } | ||
579 | |||
580 | static void dsi_handle_isrs(struct dsi_isr_tables *isr_tables, | ||
581 | u32 irqstatus, u32 *vcstatus, u32 ciostatus) | ||
582 | { | ||
583 | int i; | ||
584 | |||
585 | dsi_call_isrs(isr_tables->isr_table, | ||
586 | ARRAY_SIZE(isr_tables->isr_table), | ||
587 | irqstatus); | ||
511 | 588 | ||
512 | for (i = 0; i < 4; ++i) { | 589 | for (i = 0; i < 4; ++i) { |
513 | if ((irqstatus & (1<<i)) == 0) | 590 | if (vcstatus[i] == 0) |
514 | continue; | 591 | continue; |
592 | dsi_call_isrs(isr_tables->isr_table_vc[i], | ||
593 | ARRAY_SIZE(isr_tables->isr_table_vc[i]), | ||
594 | vcstatus[i]); | ||
595 | } | ||
515 | 596 | ||
516 | vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 597 | if (ciostatus != 0) |
598 | dsi_call_isrs(isr_tables->isr_table_cio, | ||
599 | ARRAY_SIZE(isr_tables->isr_table_cio), | ||
600 | ciostatus); | ||
601 | } | ||
517 | 602 | ||
518 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 603 | static irqreturn_t omap_dsi_irq_handler(int irq, void *arg) |
519 | dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]); | 604 | { |
520 | #endif | 605 | u32 irqstatus, vcstatus[4], ciostatus; |
606 | int i; | ||
521 | 607 | ||
522 | if (vcstatus & DSI_VC_IRQ_BTA) { | 608 | spin_lock(&dsi.irq_lock); |
523 | complete(&dsi.bta_completion); | ||
524 | 609 | ||
525 | if (dsi.bta_callback) | 610 | irqstatus = dsi_read_reg(DSI_IRQSTATUS); |
526 | dsi.bta_callback(); | ||
527 | } | ||
528 | 611 | ||
529 | if (vcstatus & DSI_VC_IRQ_ERROR_MASK) { | 612 | /* IRQ is not for us */ |
530 | DSSERR("DSI VC(%d) error, vc irqstatus %x\n", | 613 | if (!irqstatus) { |
531 | i, vcstatus); | 614 | spin_unlock(&dsi.irq_lock); |
532 | print_irq_status_vc(i, vcstatus); | 615 | return IRQ_NONE; |
533 | } else if (debug_irq) { | 616 | } |
534 | print_irq_status_vc(i, vcstatus); | 617 | |
618 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | ||
619 | /* flush posted write */ | ||
620 | dsi_read_reg(DSI_IRQSTATUS); | ||
621 | |||
622 | for (i = 0; i < 4; ++i) { | ||
623 | if ((irqstatus & (1 << i)) == 0) { | ||
624 | vcstatus[i] = 0; | ||
625 | continue; | ||
535 | } | 626 | } |
536 | 627 | ||
537 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus); | 628 | vcstatus[i] = dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
629 | |||
630 | dsi_write_reg(DSI_VC_IRQSTATUS(i), vcstatus[i]); | ||
538 | /* flush posted write */ | 631 | /* flush posted write */ |
539 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 632 | dsi_read_reg(DSI_VC_IRQSTATUS(i)); |
540 | } | 633 | } |
@@ -542,117 +635,307 @@ void dsi_irq_handler(void) | |||
542 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { | 635 | if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { |
543 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 636 | ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
544 | 637 | ||
545 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | ||
546 | dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs); | ||
547 | #endif | ||
548 | |||
549 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); | 638 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); |
550 | /* flush posted write */ | 639 | /* flush posted write */ |
551 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 640 | dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); |
641 | } else { | ||
642 | ciostatus = 0; | ||
643 | } | ||
552 | 644 | ||
553 | if (ciostatus & DSI_CIO_IRQ_ERROR_MASK) { | 645 | #ifdef DSI_CATCH_MISSING_TE |
554 | DSSERR("DSI CIO error, cio irqstatus %x\n", ciostatus); | 646 | if (irqstatus & DSI_IRQ_TE_TRIGGER) |
555 | print_irq_status_cio(ciostatus); | 647 | del_timer(&dsi.te_timer); |
556 | } else if (debug_irq) { | 648 | #endif |
557 | print_irq_status_cio(ciostatus); | 649 | |
558 | } | 650 | /* make a copy and unlock, so that isrs can unregister |
651 | * themselves */ | ||
652 | memcpy(&dsi.isr_tables_copy, &dsi.isr_tables, sizeof(dsi.isr_tables)); | ||
653 | |||
654 | spin_unlock(&dsi.irq_lock); | ||
655 | |||
656 | dsi_handle_isrs(&dsi.isr_tables_copy, irqstatus, vcstatus, ciostatus); | ||
657 | |||
658 | dsi_handle_irq_errors(irqstatus, vcstatus, ciostatus); | ||
659 | |||
660 | dsi_collect_irq_stats(irqstatus, vcstatus, ciostatus); | ||
661 | |||
662 | return IRQ_HANDLED; | ||
663 | } | ||
664 | |||
665 | /* dsi.irq_lock has to be locked by the caller */ | ||
666 | static void _omap_dsi_configure_irqs(struct dsi_isr_data *isr_array, | ||
667 | unsigned isr_array_size, u32 default_mask, | ||
668 | const struct dsi_reg enable_reg, | ||
669 | const struct dsi_reg status_reg) | ||
670 | { | ||
671 | struct dsi_isr_data *isr_data; | ||
672 | u32 mask; | ||
673 | u32 old_mask; | ||
674 | int i; | ||
675 | |||
676 | mask = default_mask; | ||
677 | |||
678 | for (i = 0; i < isr_array_size; i++) { | ||
679 | isr_data = &isr_array[i]; | ||
680 | |||
681 | if (isr_data->isr == NULL) | ||
682 | continue; | ||
683 | |||
684 | mask |= isr_data->mask; | ||
559 | } | 685 | } |
560 | 686 | ||
561 | dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); | 687 | old_mask = dsi_read_reg(enable_reg); |
562 | /* flush posted write */ | 688 | /* clear the irqstatus for newly enabled irqs */ |
563 | dsi_read_reg(DSI_IRQSTATUS); | 689 | dsi_write_reg(status_reg, (mask ^ old_mask) & mask); |
690 | dsi_write_reg(enable_reg, mask); | ||
564 | 691 | ||
565 | #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS | 692 | /* flush posted writes */ |
566 | spin_unlock(&dsi.irq_stats_lock); | 693 | dsi_read_reg(enable_reg); |
694 | dsi_read_reg(status_reg); | ||
695 | } | ||
696 | |||
697 | /* dsi.irq_lock has to be locked by the caller */ | ||
698 | static void _omap_dsi_set_irqs(void) | ||
699 | { | ||
700 | u32 mask = DSI_IRQ_ERROR_MASK; | ||
701 | #ifdef DSI_CATCH_MISSING_TE | ||
702 | mask |= DSI_IRQ_TE_TRIGGER; | ||
567 | #endif | 703 | #endif |
704 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table, | ||
705 | ARRAY_SIZE(dsi.isr_tables.isr_table), mask, | ||
706 | DSI_IRQENABLE, DSI_IRQSTATUS); | ||
707 | } | ||
708 | |||
709 | /* dsi.irq_lock has to be locked by the caller */ | ||
710 | static void _omap_dsi_set_irqs_vc(int vc) | ||
711 | { | ||
712 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_vc[vc], | ||
713 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[vc]), | ||
714 | DSI_VC_IRQ_ERROR_MASK, | ||
715 | DSI_VC_IRQENABLE(vc), DSI_VC_IRQSTATUS(vc)); | ||
568 | } | 716 | } |
569 | 717 | ||
718 | /* dsi.irq_lock has to be locked by the caller */ | ||
719 | static void _omap_dsi_set_irqs_cio(void) | ||
720 | { | ||
721 | _omap_dsi_configure_irqs(dsi.isr_tables.isr_table_cio, | ||
722 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio), | ||
723 | DSI_CIO_IRQ_ERROR_MASK, | ||
724 | DSI_COMPLEXIO_IRQ_ENABLE, DSI_COMPLEXIO_IRQ_STATUS); | ||
725 | } | ||
570 | 726 | ||
571 | static void _dsi_initialize_irq(void) | 727 | static void _dsi_initialize_irq(void) |
572 | { | 728 | { |
573 | u32 l; | 729 | unsigned long flags; |
730 | int vc; | ||
731 | |||
732 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
733 | |||
734 | memset(&dsi.isr_tables, 0, sizeof(dsi.isr_tables)); | ||
735 | |||
736 | _omap_dsi_set_irqs(); | ||
737 | for (vc = 0; vc < 4; ++vc) | ||
738 | _omap_dsi_set_irqs_vc(vc); | ||
739 | _omap_dsi_set_irqs_cio(); | ||
740 | |||
741 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
742 | } | ||
743 | |||
744 | static int _dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
745 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
746 | { | ||
747 | struct dsi_isr_data *isr_data; | ||
748 | int free_idx; | ||
574 | int i; | 749 | int i; |
575 | 750 | ||
576 | /* disable all interrupts */ | 751 | BUG_ON(isr == NULL); |
577 | dsi_write_reg(DSI_IRQENABLE, 0); | ||
578 | for (i = 0; i < 4; ++i) | ||
579 | dsi_write_reg(DSI_VC_IRQENABLE(i), 0); | ||
580 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, 0); | ||
581 | 752 | ||
582 | /* clear interrupt status */ | 753 | /* check for duplicate entry and find a free slot */ |
583 | l = dsi_read_reg(DSI_IRQSTATUS); | 754 | free_idx = -1; |
584 | dsi_write_reg(DSI_IRQSTATUS, l & ~DSI_IRQ_CHANNEL_MASK); | 755 | for (i = 0; i < isr_array_size; i++) { |
756 | isr_data = &isr_array[i]; | ||
585 | 757 | ||
586 | for (i = 0; i < 4; ++i) { | 758 | if (isr_data->isr == isr && isr_data->arg == arg && |
587 | l = dsi_read_reg(DSI_VC_IRQSTATUS(i)); | 759 | isr_data->mask == mask) { |
588 | dsi_write_reg(DSI_VC_IRQSTATUS(i), l); | 760 | return -EINVAL; |
761 | } | ||
762 | |||
763 | if (isr_data->isr == NULL && free_idx == -1) | ||
764 | free_idx = i; | ||
589 | } | 765 | } |
590 | 766 | ||
591 | l = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); | 767 | if (free_idx == -1) |
592 | dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, l); | 768 | return -EBUSY; |
593 | 769 | ||
594 | /* enable error irqs */ | 770 | isr_data = &isr_array[free_idx]; |
595 | l = DSI_IRQ_ERROR_MASK; | 771 | isr_data->isr = isr; |
596 | #ifdef DSI_CATCH_MISSING_TE | 772 | isr_data->arg = arg; |
597 | l |= DSI_IRQ_TE_TRIGGER; | 773 | isr_data->mask = mask; |
598 | #endif | ||
599 | dsi_write_reg(DSI_IRQENABLE, l); | ||
600 | 774 | ||
601 | l = DSI_VC_IRQ_ERROR_MASK; | 775 | return 0; |
602 | for (i = 0; i < 4; ++i) | 776 | } |
603 | dsi_write_reg(DSI_VC_IRQENABLE(i), l); | 777 | |
778 | static int _dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask, | ||
779 | struct dsi_isr_data *isr_array, unsigned isr_array_size) | ||
780 | { | ||
781 | struct dsi_isr_data *isr_data; | ||
782 | int i; | ||
783 | |||
784 | for (i = 0; i < isr_array_size; i++) { | ||
785 | isr_data = &isr_array[i]; | ||
786 | if (isr_data->isr != isr || isr_data->arg != arg || | ||
787 | isr_data->mask != mask) | ||
788 | continue; | ||
789 | |||
790 | isr_data->isr = NULL; | ||
791 | isr_data->arg = NULL; | ||
792 | isr_data->mask = 0; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
604 | 796 | ||
605 | l = DSI_CIO_IRQ_ERROR_MASK; | 797 | return -EINVAL; |
606 | dsi_write_reg(DSI_COMPLEXIO_IRQ_ENABLE, l); | ||
607 | } | 798 | } |
608 | 799 | ||
609 | static u32 dsi_get_errors(void) | 800 | static int dsi_register_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
610 | { | 801 | { |
611 | unsigned long flags; | 802 | unsigned long flags; |
612 | u32 e; | 803 | int r; |
613 | spin_lock_irqsave(&dsi.errors_lock, flags); | 804 | |
614 | e = dsi.errors; | 805 | spin_lock_irqsave(&dsi.irq_lock, flags); |
615 | dsi.errors = 0; | 806 | |
616 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | 807 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table, |
617 | return e; | 808 | ARRAY_SIZE(dsi.isr_tables.isr_table)); |
809 | |||
810 | if (r == 0) | ||
811 | _omap_dsi_set_irqs(); | ||
812 | |||
813 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
814 | |||
815 | return r; | ||
618 | } | 816 | } |
619 | 817 | ||
620 | static void dsi_vc_enable_bta_irq(int channel) | 818 | static int dsi_unregister_isr(omap_dsi_isr_t isr, void *arg, u32 mask) |
621 | { | 819 | { |
622 | u32 l; | 820 | unsigned long flags; |
821 | int r; | ||
822 | |||
823 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
824 | |||
825 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table, | ||
826 | ARRAY_SIZE(dsi.isr_tables.isr_table)); | ||
827 | |||
828 | if (r == 0) | ||
829 | _omap_dsi_set_irqs(); | ||
623 | 830 | ||
624 | dsi_write_reg(DSI_VC_IRQSTATUS(channel), DSI_VC_IRQ_BTA); | 831 | spin_unlock_irqrestore(&dsi.irq_lock, flags); |
625 | 832 | ||
626 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 833 | return r; |
627 | l |= DSI_VC_IRQ_BTA; | ||
628 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
629 | } | 834 | } |
630 | 835 | ||
631 | static void dsi_vc_disable_bta_irq(int channel) | 836 | static int dsi_register_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, |
837 | u32 mask) | ||
632 | { | 838 | { |
633 | u32 l; | 839 | unsigned long flags; |
840 | int r; | ||
841 | |||
842 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
843 | |||
844 | r = _dsi_register_isr(isr, arg, mask, | ||
845 | dsi.isr_tables.isr_table_vc[channel], | ||
846 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
847 | |||
848 | if (r == 0) | ||
849 | _omap_dsi_set_irqs_vc(channel); | ||
850 | |||
851 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
852 | |||
853 | return r; | ||
854 | } | ||
855 | |||
856 | static int dsi_unregister_isr_vc(int channel, omap_dsi_isr_t isr, void *arg, | ||
857 | u32 mask) | ||
858 | { | ||
859 | unsigned long flags; | ||
860 | int r; | ||
861 | |||
862 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
863 | |||
864 | r = _dsi_unregister_isr(isr, arg, mask, | ||
865 | dsi.isr_tables.isr_table_vc[channel], | ||
866 | ARRAY_SIZE(dsi.isr_tables.isr_table_vc[channel])); | ||
867 | |||
868 | if (r == 0) | ||
869 | _omap_dsi_set_irqs_vc(channel); | ||
870 | |||
871 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
872 | |||
873 | return r; | ||
874 | } | ||
875 | |||
876 | static int dsi_register_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
877 | { | ||
878 | unsigned long flags; | ||
879 | int r; | ||
880 | |||
881 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
882 | |||
883 | r = _dsi_register_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
884 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
885 | |||
886 | if (r == 0) | ||
887 | _omap_dsi_set_irqs_cio(); | ||
888 | |||
889 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
890 | |||
891 | return r; | ||
892 | } | ||
893 | |||
894 | static int dsi_unregister_isr_cio(omap_dsi_isr_t isr, void *arg, u32 mask) | ||
895 | { | ||
896 | unsigned long flags; | ||
897 | int r; | ||
898 | |||
899 | spin_lock_irqsave(&dsi.irq_lock, flags); | ||
900 | |||
901 | r = _dsi_unregister_isr(isr, arg, mask, dsi.isr_tables.isr_table_cio, | ||
902 | ARRAY_SIZE(dsi.isr_tables.isr_table_cio)); | ||
903 | |||
904 | if (r == 0) | ||
905 | _omap_dsi_set_irqs_cio(); | ||
906 | |||
907 | spin_unlock_irqrestore(&dsi.irq_lock, flags); | ||
634 | 908 | ||
635 | l = dsi_read_reg(DSI_VC_IRQENABLE(channel)); | 909 | return r; |
636 | l &= ~DSI_VC_IRQ_BTA; | ||
637 | dsi_write_reg(DSI_VC_IRQENABLE(channel), l); | ||
638 | } | 910 | } |
639 | 911 | ||
640 | /* DSI func clock. this could also be DSI2_PLL_FCLK */ | 912 | static u32 dsi_get_errors(void) |
913 | { | ||
914 | unsigned long flags; | ||
915 | u32 e; | ||
916 | spin_lock_irqsave(&dsi.errors_lock, flags); | ||
917 | e = dsi.errors; | ||
918 | dsi.errors = 0; | ||
919 | spin_unlock_irqrestore(&dsi.errors_lock, flags); | ||
920 | return e; | ||
921 | } | ||
922 | |||
923 | /* DSI func clock. this could also be dsi_pll_hsdiv_dsi_clk */ | ||
641 | static inline void enable_clocks(bool enable) | 924 | static inline void enable_clocks(bool enable) |
642 | { | 925 | { |
643 | if (enable) | 926 | if (enable) |
644 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 927 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
645 | else | 928 | else |
646 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 929 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
647 | } | 930 | } |
648 | 931 | ||
649 | /* source clock for DSI PLL. this could also be PCLKFREE */ | 932 | /* source clock for DSI PLL. this could also be PCLKFREE */ |
650 | static inline void dsi_enable_pll_clock(bool enable) | 933 | static inline void dsi_enable_pll_clock(bool enable) |
651 | { | 934 | { |
652 | if (enable) | 935 | if (enable) |
653 | dss_clk_enable(DSS_CLK_FCK2); | 936 | dss_clk_enable(DSS_CLK_SYSCK); |
654 | else | 937 | else |
655 | dss_clk_disable(DSS_CLK_FCK2); | 938 | dss_clk_disable(DSS_CLK_SYSCK); |
656 | 939 | ||
657 | if (enable && dsi.pll_locked) { | 940 | if (enable && dsi.pll_locked) { |
658 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) | 941 | if (wait_for_bit_change(DSI_PLL_STATUS, 1, 1) != 1) |
@@ -707,14 +990,14 @@ static inline int dsi_if_enable(bool enable) | |||
707 | return 0; | 990 | return 0; |
708 | } | 991 | } |
709 | 992 | ||
710 | unsigned long dsi_get_dsi1_pll_rate(void) | 993 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void) |
711 | { | 994 | { |
712 | return dsi.current_cinfo.dsi1_pll_fclk; | 995 | return dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk; |
713 | } | 996 | } |
714 | 997 | ||
715 | static unsigned long dsi_get_dsi2_pll_rate(void) | 998 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(void) |
716 | { | 999 | { |
717 | return dsi.current_cinfo.dsi2_pll_fclk; | 1000 | return dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk; |
718 | } | 1001 | } |
719 | 1002 | ||
720 | static unsigned long dsi_get_txbyteclkhs(void) | 1003 | static unsigned long dsi_get_txbyteclkhs(void) |
@@ -726,12 +1009,12 @@ static unsigned long dsi_fclk_rate(void) | |||
726 | { | 1009 | { |
727 | unsigned long r; | 1010 | unsigned long r; |
728 | 1011 | ||
729 | if (dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) { | 1012 | if (dss_get_dsi_clk_source() == DSS_CLK_SRC_FCK) { |
730 | /* DSI FCLK source is DSS1_ALWON_FCK, which is dss1_fck */ | 1013 | /* DSI FCLK source is DSS_CLK_FCK */ |
731 | r = dss_clk_get_rate(DSS_CLK_FCK1); | 1014 | r = dss_clk_get_rate(DSS_CLK_FCK); |
732 | } else { | 1015 | } else { |
733 | /* DSI FCLK source is DSI2_PLL_FCLK */ | 1016 | /* DSI FCLK source is dsi_pll_hsdiv_dsi_clk */ |
734 | r = dsi_get_dsi2_pll_rate(); | 1017 | r = dsi_get_pll_hsdiv_dsi_rate(); |
735 | } | 1018 | } |
736 | 1019 | ||
737 | return r; | 1020 | return r; |
@@ -745,7 +1028,7 @@ static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | |||
745 | 1028 | ||
746 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; | 1029 | lp_clk_div = dssdev->phy.dsi.div.lp_clk_div; |
747 | 1030 | ||
748 | if (lp_clk_div == 0 || lp_clk_div > LP_DIV_MAX) | 1031 | if (lp_clk_div == 0 || lp_clk_div > dsi.lpdiv_max) |
749 | return -EINVAL; | 1032 | return -EINVAL; |
750 | 1033 | ||
751 | dsi_fclk = dsi_fclk_rate(); | 1034 | dsi_fclk = dsi_fclk_rate(); |
@@ -795,22 +1078,22 @@ static int dsi_pll_power(enum dsi_pll_power_state state) | |||
795 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | 1078 | static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, |
796 | struct dsi_clock_info *cinfo) | 1079 | struct dsi_clock_info *cinfo) |
797 | { | 1080 | { |
798 | if (cinfo->regn == 0 || cinfo->regn > REGN_MAX) | 1081 | if (cinfo->regn == 0 || cinfo->regn > dsi.regn_max) |
799 | return -EINVAL; | 1082 | return -EINVAL; |
800 | 1083 | ||
801 | if (cinfo->regm == 0 || cinfo->regm > REGM_MAX) | 1084 | if (cinfo->regm == 0 || cinfo->regm > dsi.regm_max) |
802 | return -EINVAL; | 1085 | return -EINVAL; |
803 | 1086 | ||
804 | if (cinfo->regm3 > REGM3_MAX) | 1087 | if (cinfo->regm_dispc > dsi.regm_dispc_max) |
805 | return -EINVAL; | 1088 | return -EINVAL; |
806 | 1089 | ||
807 | if (cinfo->regm4 > REGM4_MAX) | 1090 | if (cinfo->regm_dsi > dsi.regm_dsi_max) |
808 | return -EINVAL; | 1091 | return -EINVAL; |
809 | 1092 | ||
810 | if (cinfo->use_dss2_fck) { | 1093 | if (cinfo->use_sys_clk) { |
811 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_FCK2); | 1094 | cinfo->clkin = dss_clk_get_rate(DSS_CLK_SYSCK); |
812 | /* XXX it is unclear if highfreq should be used | 1095 | /* XXX it is unclear if highfreq should be used |
813 | * with DSS2_FCK source also */ | 1096 | * with DSS_SYS_CLK source also */ |
814 | cinfo->highfreq = 0; | 1097 | cinfo->highfreq = 0; |
815 | } else { | 1098 | } else { |
816 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); | 1099 | cinfo->clkin = dispc_pclk_rate(dssdev->manager->id); |
@@ -823,7 +1106,7 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
823 | 1106 | ||
824 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); | 1107 | cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1)); |
825 | 1108 | ||
826 | if (cinfo->fint > FINT_MAX || cinfo->fint < FINT_MIN) | 1109 | if (cinfo->fint > dsi.fint_max || cinfo->fint < dsi.fint_min) |
827 | return -EINVAL; | 1110 | return -EINVAL; |
828 | 1111 | ||
829 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; | 1112 | cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint; |
@@ -831,15 +1114,17 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev, | |||
831 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) | 1114 | if (cinfo->clkin4ddr > 1800 * 1000 * 1000) |
832 | return -EINVAL; | 1115 | return -EINVAL; |
833 | 1116 | ||
834 | if (cinfo->regm3 > 0) | 1117 | if (cinfo->regm_dispc > 0) |
835 | cinfo->dsi1_pll_fclk = cinfo->clkin4ddr / cinfo->regm3; | 1118 | cinfo->dsi_pll_hsdiv_dispc_clk = |
1119 | cinfo->clkin4ddr / cinfo->regm_dispc; | ||
836 | else | 1120 | else |
837 | cinfo->dsi1_pll_fclk = 0; | 1121 | cinfo->dsi_pll_hsdiv_dispc_clk = 0; |
838 | 1122 | ||
839 | if (cinfo->regm4 > 0) | 1123 | if (cinfo->regm_dsi > 0) |
840 | cinfo->dsi2_pll_fclk = cinfo->clkin4ddr / cinfo->regm4; | 1124 | cinfo->dsi_pll_hsdiv_dsi_clk = |
1125 | cinfo->clkin4ddr / cinfo->regm_dsi; | ||
841 | else | 1126 | else |
842 | cinfo->dsi2_pll_fclk = 0; | 1127 | cinfo->dsi_pll_hsdiv_dsi_clk = 0; |
843 | 1128 | ||
844 | return 0; | 1129 | return 0; |
845 | } | 1130 | } |
@@ -852,23 +1137,25 @@ int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | |||
852 | struct dispc_clock_info best_dispc; | 1137 | struct dispc_clock_info best_dispc; |
853 | int min_fck_per_pck; | 1138 | int min_fck_per_pck; |
854 | int match = 0; | 1139 | int match = 0; |
855 | unsigned long dss_clk_fck2; | 1140 | unsigned long dss_sys_clk, max_dss_fck; |
1141 | |||
1142 | dss_sys_clk = dss_clk_get_rate(DSS_CLK_SYSCK); | ||
856 | 1143 | ||
857 | dss_clk_fck2 = dss_clk_get_rate(DSS_CLK_FCK2); | 1144 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
858 | 1145 | ||
859 | if (req_pck == dsi.cache_req_pck && | 1146 | if (req_pck == dsi.cache_req_pck && |
860 | dsi.cache_cinfo.clkin == dss_clk_fck2) { | 1147 | dsi.cache_cinfo.clkin == dss_sys_clk) { |
861 | DSSDBG("DSI clock info found from cache\n"); | 1148 | DSSDBG("DSI clock info found from cache\n"); |
862 | *dsi_cinfo = dsi.cache_cinfo; | 1149 | *dsi_cinfo = dsi.cache_cinfo; |
863 | dispc_find_clk_divs(is_tft, req_pck, dsi_cinfo->dsi1_pll_fclk, | 1150 | dispc_find_clk_divs(is_tft, req_pck, |
864 | dispc_cinfo); | 1151 | dsi_cinfo->dsi_pll_hsdiv_dispc_clk, dispc_cinfo); |
865 | return 0; | 1152 | return 0; |
866 | } | 1153 | } |
867 | 1154 | ||
868 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 1155 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
869 | 1156 | ||
870 | if (min_fck_per_pck && | 1157 | if (min_fck_per_pck && |
871 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 1158 | req_pck * min_fck_per_pck > max_dss_fck) { |
872 | DSSERR("Requested pixel clock not possible with the current " | 1159 | DSSERR("Requested pixel clock not possible with the current " |
873 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 1160 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
874 | "the constraint off.\n"); | 1161 | "the constraint off.\n"); |
@@ -882,24 +1169,24 @@ retry: | |||
882 | memset(&best_dispc, 0, sizeof(best_dispc)); | 1169 | memset(&best_dispc, 0, sizeof(best_dispc)); |
883 | 1170 | ||
884 | memset(&cur, 0, sizeof(cur)); | 1171 | memset(&cur, 0, sizeof(cur)); |
885 | cur.clkin = dss_clk_fck2; | 1172 | cur.clkin = dss_sys_clk; |
886 | cur.use_dss2_fck = 1; | 1173 | cur.use_sys_clk = 1; |
887 | cur.highfreq = 0; | 1174 | cur.highfreq = 0; |
888 | 1175 | ||
889 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ | 1176 | /* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */ |
890 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ | 1177 | /* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */ |
891 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | 1178 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ |
892 | for (cur.regn = 1; cur.regn < REGN_MAX; ++cur.regn) { | 1179 | for (cur.regn = 1; cur.regn < dsi.regn_max; ++cur.regn) { |
893 | if (cur.highfreq == 0) | 1180 | if (cur.highfreq == 0) |
894 | cur.fint = cur.clkin / cur.regn; | 1181 | cur.fint = cur.clkin / cur.regn; |
895 | else | 1182 | else |
896 | cur.fint = cur.clkin / (2 * cur.regn); | 1183 | cur.fint = cur.clkin / (2 * cur.regn); |
897 | 1184 | ||
898 | if (cur.fint > FINT_MAX || cur.fint < FINT_MIN) | 1185 | if (cur.fint > dsi.fint_max || cur.fint < dsi.fint_min) |
899 | continue; | 1186 | continue; |
900 | 1187 | ||
901 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ | 1188 | /* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */ |
902 | for (cur.regm = 1; cur.regm < REGM_MAX; ++cur.regm) { | 1189 | for (cur.regm = 1; cur.regm < dsi.regm_max; ++cur.regm) { |
903 | unsigned long a, b; | 1190 | unsigned long a, b; |
904 | 1191 | ||
905 | a = 2 * cur.regm * (cur.clkin/1000); | 1192 | a = 2 * cur.regm * (cur.clkin/1000); |
@@ -909,30 +1196,32 @@ retry: | |||
909 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | 1196 | if (cur.clkin4ddr > 1800 * 1000 * 1000) |
910 | break; | 1197 | break; |
911 | 1198 | ||
912 | /* DSI1_PLL_FCLK(MHz) = DSIPHY(MHz) / regm3 < 173MHz */ | 1199 | /* dsi_pll_hsdiv_dispc_clk(MHz) = |
913 | for (cur.regm3 = 1; cur.regm3 < REGM3_MAX; | 1200 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ |
914 | ++cur.regm3) { | 1201 | for (cur.regm_dispc = 1; cur.regm_dispc < dsi.regm_dispc_max; |
1202 | ++cur.regm_dispc) { | ||
915 | struct dispc_clock_info cur_dispc; | 1203 | struct dispc_clock_info cur_dispc; |
916 | cur.dsi1_pll_fclk = cur.clkin4ddr / cur.regm3; | 1204 | cur.dsi_pll_hsdiv_dispc_clk = |
1205 | cur.clkin4ddr / cur.regm_dispc; | ||
917 | 1206 | ||
918 | /* this will narrow down the search a bit, | 1207 | /* this will narrow down the search a bit, |
919 | * but still give pixclocks below what was | 1208 | * but still give pixclocks below what was |
920 | * requested */ | 1209 | * requested */ |
921 | if (cur.dsi1_pll_fclk < req_pck) | 1210 | if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) |
922 | break; | 1211 | break; |
923 | 1212 | ||
924 | if (cur.dsi1_pll_fclk > DISPC_MAX_FCK) | 1213 | if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) |
925 | continue; | 1214 | continue; |
926 | 1215 | ||
927 | if (min_fck_per_pck && | 1216 | if (min_fck_per_pck && |
928 | cur.dsi1_pll_fclk < | 1217 | cur.dsi_pll_hsdiv_dispc_clk < |
929 | req_pck * min_fck_per_pck) | 1218 | req_pck * min_fck_per_pck) |
930 | continue; | 1219 | continue; |
931 | 1220 | ||
932 | match = 1; | 1221 | match = 1; |
933 | 1222 | ||
934 | dispc_find_clk_divs(is_tft, req_pck, | 1223 | dispc_find_clk_divs(is_tft, req_pck, |
935 | cur.dsi1_pll_fclk, | 1224 | cur.dsi_pll_hsdiv_dispc_clk, |
936 | &cur_dispc); | 1225 | &cur_dispc); |
937 | 1226 | ||
938 | if (abs(cur_dispc.pck - req_pck) < | 1227 | if (abs(cur_dispc.pck - req_pck) < |
@@ -961,9 +1250,9 @@ found: | |||
961 | return -EINVAL; | 1250 | return -EINVAL; |
962 | } | 1251 | } |
963 | 1252 | ||
964 | /* DSI2_PLL_FCLK (regm4) is not used */ | 1253 | /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ |
965 | best.regm4 = 0; | 1254 | best.regm_dsi = 0; |
966 | best.dsi2_pll_fclk = 0; | 1255 | best.dsi_pll_hsdiv_dsi_clk = 0; |
967 | 1256 | ||
968 | if (dsi_cinfo) | 1257 | if (dsi_cinfo) |
969 | *dsi_cinfo = best; | 1258 | *dsi_cinfo = best; |
@@ -982,23 +1271,27 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
982 | int r = 0; | 1271 | int r = 0; |
983 | u32 l; | 1272 | u32 l; |
984 | int f; | 1273 | int f; |
1274 | u8 regn_start, regn_end, regm_start, regm_end; | ||
1275 | u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end; | ||
985 | 1276 | ||
986 | DSSDBGF(); | 1277 | DSSDBGF(); |
987 | 1278 | ||
988 | dsi.current_cinfo.fint = cinfo->fint; | 1279 | dsi.current_cinfo.fint = cinfo->fint; |
989 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; | 1280 | dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr; |
990 | dsi.current_cinfo.dsi1_pll_fclk = cinfo->dsi1_pll_fclk; | 1281 | dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk = |
991 | dsi.current_cinfo.dsi2_pll_fclk = cinfo->dsi2_pll_fclk; | 1282 | cinfo->dsi_pll_hsdiv_dispc_clk; |
1283 | dsi.current_cinfo.dsi_pll_hsdiv_dsi_clk = | ||
1284 | cinfo->dsi_pll_hsdiv_dsi_clk; | ||
992 | 1285 | ||
993 | dsi.current_cinfo.regn = cinfo->regn; | 1286 | dsi.current_cinfo.regn = cinfo->regn; |
994 | dsi.current_cinfo.regm = cinfo->regm; | 1287 | dsi.current_cinfo.regm = cinfo->regm; |
995 | dsi.current_cinfo.regm3 = cinfo->regm3; | 1288 | dsi.current_cinfo.regm_dispc = cinfo->regm_dispc; |
996 | dsi.current_cinfo.regm4 = cinfo->regm4; | 1289 | dsi.current_cinfo.regm_dsi = cinfo->regm_dsi; |
997 | 1290 | ||
998 | DSSDBG("DSI Fint %ld\n", cinfo->fint); | 1291 | DSSDBG("DSI Fint %ld\n", cinfo->fint); |
999 | 1292 | ||
1000 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", | 1293 | DSSDBG("clkin (%s) rate %ld, highfreq %d\n", |
1001 | cinfo->use_dss2_fck ? "dss2_fck" : "pclkfree", | 1294 | cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree", |
1002 | cinfo->clkin, | 1295 | cinfo->clkin, |
1003 | cinfo->highfreq); | 1296 | cinfo->highfreq); |
1004 | 1297 | ||
@@ -1015,24 +1308,39 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1015 | 1308 | ||
1016 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); | 1309 | DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4); |
1017 | 1310 | ||
1018 | DSSDBG("regm3 = %d, dsi1_pll_fclk = %lu\n", | 1311 | DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc, |
1019 | cinfo->regm3, cinfo->dsi1_pll_fclk); | 1312 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1020 | DSSDBG("regm4 = %d, dsi2_pll_fclk = %lu\n", | 1313 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), |
1021 | cinfo->regm4, cinfo->dsi2_pll_fclk); | 1314 | cinfo->dsi_pll_hsdiv_dispc_clk); |
1315 | DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi, | ||
1316 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1317 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
1318 | cinfo->dsi_pll_hsdiv_dsi_clk); | ||
1319 | |||
1320 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, ®n_start, ®n_end); | ||
1321 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); | ||
1322 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, | ||
1323 | ®m_dispc_end); | ||
1324 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | ||
1325 | ®m_dsi_end); | ||
1022 | 1326 | ||
1023 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ | 1327 | REG_FLD_MOD(DSI_PLL_CONTROL, 0, 0, 0); /* DSI_PLL_AUTOMODE = manual */ |
1024 | 1328 | ||
1025 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); | 1329 | l = dsi_read_reg(DSI_PLL_CONFIGURATION1); |
1026 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ | 1330 | l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */ |
1027 | l = FLD_MOD(l, cinfo->regn - 1, 7, 1); /* DSI_PLL_REGN */ | 1331 | /* DSI_PLL_REGN */ |
1028 | l = FLD_MOD(l, cinfo->regm, 18, 8); /* DSI_PLL_REGM */ | 1332 | l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end); |
1029 | l = FLD_MOD(l, cinfo->regm3 > 0 ? cinfo->regm3 - 1 : 0, | 1333 | /* DSI_PLL_REGM */ |
1030 | 22, 19); /* DSI_CLOCK_DIV */ | 1334 | l = FLD_MOD(l, cinfo->regm, regm_start, regm_end); |
1031 | l = FLD_MOD(l, cinfo->regm4 > 0 ? cinfo->regm4 - 1 : 0, | 1335 | /* DSI_CLOCK_DIV */ |
1032 | 26, 23); /* DSIPROTO_CLOCK_DIV */ | 1336 | l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0, |
1337 | regm_dispc_start, regm_dispc_end); | ||
1338 | /* DSIPROTO_CLOCK_DIV */ | ||
1339 | l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0, | ||
1340 | regm_dsi_start, regm_dsi_end); | ||
1033 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); | 1341 | dsi_write_reg(DSI_PLL_CONFIGURATION1, l); |
1034 | 1342 | ||
1035 | BUG_ON(cinfo->fint < 750000 || cinfo->fint > 2100000); | 1343 | BUG_ON(cinfo->fint < dsi.fint_min || cinfo->fint > dsi.fint_max); |
1036 | if (cinfo->fint < 1000000) | 1344 | if (cinfo->fint < 1000000) |
1037 | f = 0x3; | 1345 | f = 0x3; |
1038 | else if (cinfo->fint < 1250000) | 1346 | else if (cinfo->fint < 1250000) |
@@ -1046,7 +1354,7 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo) | |||
1046 | 1354 | ||
1047 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); | 1355 | l = dsi_read_reg(DSI_PLL_CONFIGURATION2); |
1048 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ | 1356 | l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */ |
1049 | l = FLD_MOD(l, cinfo->use_dss2_fck ? 0 : 1, | 1357 | l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1, |
1050 | 11, 11); /* DSI_PLL_CLKSEL */ | 1358 | 11, 11); /* DSI_PLL_CLKSEL */ |
1051 | l = FLD_MOD(l, cinfo->highfreq, | 1359 | l = FLD_MOD(l, cinfo->highfreq, |
1052 | 12, 12); /* DSI_PLL_HIGHFREQ */ | 1360 | 12, 12); /* DSI_PLL_HIGHFREQ */ |
@@ -1101,6 +1409,26 @@ int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk, | |||
1101 | 1409 | ||
1102 | DSSDBG("PLL init\n"); | 1410 | DSSDBG("PLL init\n"); |
1103 | 1411 | ||
1412 | #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL | ||
1413 | /* | ||
1414 | * HACK: this is just a quick hack to get the USE_DSI_PLL | ||
1415 | * option working. USE_DSI_PLL is itself a big hack, and | ||
1416 | * should be removed. | ||
1417 | */ | ||
1418 | if (dsi.vdds_dsi_reg == NULL) { | ||
1419 | struct regulator *vdds_dsi; | ||
1420 | |||
1421 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
1422 | |||
1423 | if (IS_ERR(vdds_dsi)) { | ||
1424 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
1425 | return PTR_ERR(vdds_dsi); | ||
1426 | } | ||
1427 | |||
1428 | dsi.vdds_dsi_reg = vdds_dsi; | ||
1429 | } | ||
1430 | #endif | ||
1431 | |||
1104 | enable_clocks(1); | 1432 | enable_clocks(1); |
1105 | dsi_enable_pll_clock(1); | 1433 | dsi_enable_pll_clock(1); |
1106 | 1434 | ||
@@ -1162,6 +1490,10 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1162 | { | 1490 | { |
1163 | int clksel; | 1491 | int clksel; |
1164 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; | 1492 | struct dsi_clock_info *cinfo = &dsi.current_cinfo; |
1493 | enum dss_clk_source dispc_clk_src, dsi_clk_src; | ||
1494 | |||
1495 | dispc_clk_src = dss_get_dispc_clk_source(); | ||
1496 | dsi_clk_src = dss_get_dsi_clk_source(); | ||
1165 | 1497 | ||
1166 | enable_clocks(1); | 1498 | enable_clocks(1); |
1167 | 1499 | ||
@@ -1171,30 +1503,34 @@ void dsi_dump_clocks(struct seq_file *s) | |||
1171 | 1503 | ||
1172 | seq_printf(s, "dsi pll source = %s\n", | 1504 | seq_printf(s, "dsi pll source = %s\n", |
1173 | clksel == 0 ? | 1505 | clksel == 0 ? |
1174 | "dss2_alwon_fclk" : "pclkfree"); | 1506 | "dss_sys_clk" : "pclkfree"); |
1175 | 1507 | ||
1176 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); | 1508 | seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); |
1177 | 1509 | ||
1178 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", | 1510 | seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", |
1179 | cinfo->clkin4ddr, cinfo->regm); | 1511 | cinfo->clkin4ddr, cinfo->regm); |
1180 | 1512 | ||
1181 | seq_printf(s, "dsi1_pll_fck\t%-16luregm3 %u\t(%s)\n", | 1513 | seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", |
1182 | cinfo->dsi1_pll_fclk, | 1514 | dss_get_generic_clk_source_name(dispc_clk_src), |
1183 | cinfo->regm3, | 1515 | dss_feat_get_clk_source_name(dispc_clk_src), |
1184 | dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1516 | cinfo->dsi_pll_hsdiv_dispc_clk, |
1517 | cinfo->regm_dispc, | ||
1518 | dispc_clk_src == DSS_CLK_SRC_FCK ? | ||
1185 | "off" : "on"); | 1519 | "off" : "on"); |
1186 | 1520 | ||
1187 | seq_printf(s, "dsi2_pll_fck\t%-16luregm4 %u\t(%s)\n", | 1521 | seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", |
1188 | cinfo->dsi2_pll_fclk, | 1522 | dss_get_generic_clk_source_name(dsi_clk_src), |
1189 | cinfo->regm4, | 1523 | dss_feat_get_clk_source_name(dsi_clk_src), |
1190 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1524 | cinfo->dsi_pll_hsdiv_dsi_clk, |
1525 | cinfo->regm_dsi, | ||
1526 | dsi_clk_src == DSS_CLK_SRC_FCK ? | ||
1191 | "off" : "on"); | 1527 | "off" : "on"); |
1192 | 1528 | ||
1193 | seq_printf(s, "- DSI -\n"); | 1529 | seq_printf(s, "- DSI -\n"); |
1194 | 1530 | ||
1195 | seq_printf(s, "dsi fclk source = %s\n", | 1531 | seq_printf(s, "dsi fclk source = %s (%s)\n", |
1196 | dss_get_dsi_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? | 1532 | dss_get_generic_clk_source_name(dsi_clk_src), |
1197 | "dss1_alwon_fclk" : "dsi2_pll_fclk"); | 1533 | dss_feat_get_clk_source_name(dsi_clk_src)); |
1198 | 1534 | ||
1199 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); | 1535 | seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate()); |
1200 | 1536 | ||
@@ -1306,7 +1642,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1306 | { | 1642 | { |
1307 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) | 1643 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) |
1308 | 1644 | ||
1309 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1645 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1310 | 1646 | ||
1311 | DUMPREG(DSI_REVISION); | 1647 | DUMPREG(DSI_REVISION); |
1312 | DUMPREG(DSI_SYSCONFIG); | 1648 | DUMPREG(DSI_SYSCONFIG); |
@@ -1378,7 +1714,7 @@ void dsi_dump_regs(struct seq_file *s) | |||
1378 | DUMPREG(DSI_PLL_CONFIGURATION1); | 1714 | DUMPREG(DSI_PLL_CONFIGURATION1); |
1379 | DUMPREG(DSI_PLL_CONFIGURATION2); | 1715 | DUMPREG(DSI_PLL_CONFIGURATION2); |
1380 | 1716 | ||
1381 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1717 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1382 | #undef DUMPREG | 1718 | #undef DUMPREG |
1383 | } | 1719 | } |
1384 | 1720 | ||
@@ -1622,20 +1958,6 @@ static int _dsi_reset(void) | |||
1622 | return _dsi_wait_reset(); | 1958 | return _dsi_wait_reset(); |
1623 | } | 1959 | } |
1624 | 1960 | ||
1625 | static void dsi_reset_tx_fifo(int channel) | ||
1626 | { | ||
1627 | u32 mask; | ||
1628 | u32 l; | ||
1629 | |||
1630 | /* set fifosize of the channel to 0, then return the old size */ | ||
1631 | l = dsi_read_reg(DSI_TX_FIFO_VC_SIZE); | ||
1632 | |||
1633 | mask = FLD_MASK((8 * channel) + 7, (8 * channel) + 4); | ||
1634 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l & ~mask); | ||
1635 | |||
1636 | dsi_write_reg(DSI_TX_FIFO_VC_SIZE, l); | ||
1637 | } | ||
1638 | |||
1639 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, | 1961 | static void dsi_config_tx_fifo(enum fifo_size size1, enum fifo_size size2, |
1640 | enum fifo_size size3, enum fifo_size size4) | 1962 | enum fifo_size size3, enum fifo_size size4) |
1641 | { | 1963 | { |
@@ -1753,8 +2075,6 @@ static void dsi_vc_initial_config(int channel) | |||
1753 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2075 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
1754 | 2076 | ||
1755 | dsi_write_reg(DSI_VC_CTRL(channel), r); | 2077 | dsi_write_reg(DSI_VC_CTRL(channel), r); |
1756 | |||
1757 | dsi.vc[channel].mode = DSI_VC_MODE_L4; | ||
1758 | } | 2078 | } |
1759 | 2079 | ||
1760 | static int dsi_vc_config_l4(int channel) | 2080 | static int dsi_vc_config_l4(int channel) |
@@ -1922,33 +2242,44 @@ static int dsi_vc_send_bta(int channel) | |||
1922 | 2242 | ||
1923 | int dsi_vc_send_bta_sync(int channel) | 2243 | int dsi_vc_send_bta_sync(int channel) |
1924 | { | 2244 | { |
2245 | DECLARE_COMPLETION_ONSTACK(completion); | ||
1925 | int r = 0; | 2246 | int r = 0; |
1926 | u32 err; | 2247 | u32 err; |
1927 | 2248 | ||
1928 | INIT_COMPLETION(dsi.bta_completion); | 2249 | r = dsi_register_isr_vc(channel, dsi_completion_handler, |
2250 | &completion, DSI_VC_IRQ_BTA); | ||
2251 | if (r) | ||
2252 | goto err0; | ||
1929 | 2253 | ||
1930 | dsi_vc_enable_bta_irq(channel); | 2254 | r = dsi_register_isr(dsi_completion_handler, &completion, |
2255 | DSI_IRQ_ERROR_MASK); | ||
2256 | if (r) | ||
2257 | goto err1; | ||
1931 | 2258 | ||
1932 | r = dsi_vc_send_bta(channel); | 2259 | r = dsi_vc_send_bta(channel); |
1933 | if (r) | 2260 | if (r) |
1934 | goto err; | 2261 | goto err2; |
1935 | 2262 | ||
1936 | if (wait_for_completion_timeout(&dsi.bta_completion, | 2263 | if (wait_for_completion_timeout(&completion, |
1937 | msecs_to_jiffies(500)) == 0) { | 2264 | msecs_to_jiffies(500)) == 0) { |
1938 | DSSERR("Failed to receive BTA\n"); | 2265 | DSSERR("Failed to receive BTA\n"); |
1939 | r = -EIO; | 2266 | r = -EIO; |
1940 | goto err; | 2267 | goto err2; |
1941 | } | 2268 | } |
1942 | 2269 | ||
1943 | err = dsi_get_errors(); | 2270 | err = dsi_get_errors(); |
1944 | if (err) { | 2271 | if (err) { |
1945 | DSSERR("Error while sending BTA: %x\n", err); | 2272 | DSSERR("Error while sending BTA: %x\n", err); |
1946 | r = -EIO; | 2273 | r = -EIO; |
1947 | goto err; | 2274 | goto err2; |
1948 | } | 2275 | } |
1949 | err: | 2276 | err2: |
1950 | dsi_vc_disable_bta_irq(channel); | 2277 | dsi_unregister_isr(dsi_completion_handler, &completion, |
1951 | 2278 | DSI_IRQ_ERROR_MASK); | |
2279 | err1: | ||
2280 | dsi_unregister_isr_vc(channel, dsi_completion_handler, | ||
2281 | &completion, DSI_VC_IRQ_BTA); | ||
2282 | err0: | ||
1952 | return r; | 2283 | return r; |
1953 | } | 2284 | } |
1954 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); | 2285 | EXPORT_SYMBOL(dsi_vc_send_bta_sync); |
@@ -1961,7 +2292,7 @@ static inline void dsi_vc_write_long_header(int channel, u8 data_type, | |||
1961 | 2292 | ||
1962 | WARN_ON(!dsi_bus_is_locked()); | 2293 | WARN_ON(!dsi_bus_is_locked()); |
1963 | 2294 | ||
1964 | data_id = data_type | channel << 6; | 2295 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
1965 | 2296 | ||
1966 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | | 2297 | val = FLD_VAL(data_id, 7, 0) | FLD_VAL(len, 23, 8) | |
1967 | FLD_VAL(ecc, 31, 24); | 2298 | FLD_VAL(ecc, 31, 24); |
@@ -2064,7 +2395,7 @@ static int dsi_vc_send_short(int channel, u8 data_type, u16 data, u8 ecc) | |||
2064 | return -EINVAL; | 2395 | return -EINVAL; |
2065 | } | 2396 | } |
2066 | 2397 | ||
2067 | data_id = data_type | channel << 6; | 2398 | data_id = data_type | dsi.vc[channel].vc_id << 6; |
2068 | 2399 | ||
2069 | r = (data_id << 0) | (data << 8) | (ecc << 24); | 2400 | r = (data_id << 0) | (data << 8) | (ecc << 24); |
2070 | 2401 | ||
@@ -2762,19 +3093,20 @@ static void dsi_te_timeout(unsigned long arg) | |||
2762 | } | 3093 | } |
2763 | #endif | 3094 | #endif |
2764 | 3095 | ||
3096 | static void dsi_framedone_bta_callback(void *data, u32 mask); | ||
3097 | |||
2765 | static void dsi_handle_framedone(int error) | 3098 | static void dsi_handle_framedone(int error) |
2766 | { | 3099 | { |
2767 | const int channel = dsi.update_channel; | 3100 | const int channel = dsi.update_channel; |
2768 | 3101 | ||
2769 | cancel_delayed_work(&dsi.framedone_timeout_work); | 3102 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, |
3103 | NULL, DSI_VC_IRQ_BTA); | ||
2770 | 3104 | ||
2771 | dsi_vc_disable_bta_irq(channel); | 3105 | cancel_delayed_work(&dsi.framedone_timeout_work); |
2772 | 3106 | ||
2773 | /* SIDLEMODE back to smart-idle */ | 3107 | /* SIDLEMODE back to smart-idle */ |
2774 | dispc_enable_sidle(); | 3108 | dispc_enable_sidle(); |
2775 | 3109 | ||
2776 | dsi.bta_callback = NULL; | ||
2777 | |||
2778 | if (dsi.te_enabled) { | 3110 | if (dsi.te_enabled) { |
2779 | /* enable LP_RX_TO again after the TE */ | 3111 | /* enable LP_RX_TO again after the TE */ |
2780 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ | 3112 | REG_FLD_MOD(DSI_TIMING2, 1, 15, 15); /* LP_RX_TO */ |
@@ -2808,7 +3140,7 @@ static void dsi_framedone_timeout_work_callback(struct work_struct *work) | |||
2808 | dsi_handle_framedone(-ETIMEDOUT); | 3140 | dsi_handle_framedone(-ETIMEDOUT); |
2809 | } | 3141 | } |
2810 | 3142 | ||
2811 | static void dsi_framedone_bta_callback(void) | 3143 | static void dsi_framedone_bta_callback(void *data, u32 mask) |
2812 | { | 3144 | { |
2813 | dsi_handle_framedone(0); | 3145 | dsi_handle_framedone(0); |
2814 | 3146 | ||
@@ -2848,15 +3180,19 @@ static void dsi_framedone_irq_callback(void *data, u32 mask) | |||
2848 | * asynchronously. | 3180 | * asynchronously. |
2849 | * */ | 3181 | * */ |
2850 | 3182 | ||
2851 | dsi.bta_callback = dsi_framedone_bta_callback; | 3183 | r = dsi_register_isr_vc(channel, dsi_framedone_bta_callback, |
2852 | 3184 | NULL, DSI_VC_IRQ_BTA); | |
2853 | barrier(); | 3185 | if (r) { |
2854 | 3186 | DSSERR("Failed to register BTA ISR\n"); | |
2855 | dsi_vc_enable_bta_irq(channel); | 3187 | dsi_handle_framedone(-EIO); |
3188 | return; | ||
3189 | } | ||
2856 | 3190 | ||
2857 | r = dsi_vc_send_bta(channel); | 3191 | r = dsi_vc_send_bta(channel); |
2858 | if (r) { | 3192 | if (r) { |
2859 | DSSERR("BTA after framedone failed\n"); | 3193 | DSSERR("BTA after framedone failed\n"); |
3194 | dsi_unregister_isr_vc(channel, dsi_framedone_bta_callback, | ||
3195 | NULL, DSI_VC_IRQ_BTA); | ||
2860 | dsi_handle_framedone(-EIO); | 3196 | dsi_handle_framedone(-EIO); |
2861 | } | 3197 | } |
2862 | } | 3198 | } |
@@ -2984,12 +3320,12 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
2984 | struct dsi_clock_info cinfo; | 3320 | struct dsi_clock_info cinfo; |
2985 | int r; | 3321 | int r; |
2986 | 3322 | ||
2987 | /* we always use DSS2_FCK as input clock */ | 3323 | /* we always use DSS_CLK_SYSCK as input clock */ |
2988 | cinfo.use_dss2_fck = true; | 3324 | cinfo.use_sys_clk = true; |
2989 | cinfo.regn = dssdev->phy.dsi.div.regn; | 3325 | cinfo.regn = dssdev->phy.dsi.div.regn; |
2990 | cinfo.regm = dssdev->phy.dsi.div.regm; | 3326 | cinfo.regm = dssdev->phy.dsi.div.regm; |
2991 | cinfo.regm3 = dssdev->phy.dsi.div.regm3; | 3327 | cinfo.regm_dispc = dssdev->phy.dsi.div.regm_dispc; |
2992 | cinfo.regm4 = dssdev->phy.dsi.div.regm4; | 3328 | cinfo.regm_dsi = dssdev->phy.dsi.div.regm_dsi; |
2993 | r = dsi_calc_clock_rates(dssdev, &cinfo); | 3329 | r = dsi_calc_clock_rates(dssdev, &cinfo); |
2994 | if (r) { | 3330 | if (r) { |
2995 | DSSERR("Failed to calc dsi clocks\n"); | 3331 | DSSERR("Failed to calc dsi clocks\n"); |
@@ -3011,7 +3347,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
3011 | int r; | 3347 | int r; |
3012 | unsigned long long fck; | 3348 | unsigned long long fck; |
3013 | 3349 | ||
3014 | fck = dsi_get_dsi1_pll_rate(); | 3350 | fck = dsi_get_pll_hsdiv_dispc_rate(); |
3015 | 3351 | ||
3016 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; | 3352 | dispc_cinfo.lck_div = dssdev->phy.dsi.div.lck_div; |
3017 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; | 3353 | dispc_cinfo.pck_div = dssdev->phy.dsi.div.pck_div; |
@@ -3045,8 +3381,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3045 | if (r) | 3381 | if (r) |
3046 | goto err1; | 3382 | goto err1; |
3047 | 3383 | ||
3048 | dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK); | 3384 | dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC); |
3049 | dss_select_dsi_clk_source(DSS_SRC_DSI2_PLL_FCLK); | 3385 | dss_select_dsi_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI); |
3050 | 3386 | ||
3051 | DSSDBG("PLL OK\n"); | 3387 | DSSDBG("PLL OK\n"); |
3052 | 3388 | ||
@@ -3082,8 +3418,8 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
3082 | err3: | 3418 | err3: |
3083 | dsi_complexio_uninit(); | 3419 | dsi_complexio_uninit(); |
3084 | err2: | 3420 | err2: |
3085 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3421 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3086 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3422 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3087 | err1: | 3423 | err1: |
3088 | dsi_pll_uninit(); | 3424 | dsi_pll_uninit(); |
3089 | err0: | 3425 | err0: |
@@ -3099,8 +3435,8 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev) | |||
3099 | dsi_vc_enable(2, 0); | 3435 | dsi_vc_enable(2, 0); |
3100 | dsi_vc_enable(3, 0); | 3436 | dsi_vc_enable(3, 0); |
3101 | 3437 | ||
3102 | dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3438 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); |
3103 | dss_select_dsi_clk_source(DSS_SRC_DSS1_ALWON_FCLK); | 3439 | dss_select_dsi_clk_source(DSS_CLK_SRC_FCK); |
3104 | dsi_complexio_uninit(); | 3440 | dsi_complexio_uninit(); |
3105 | dsi_pll_uninit(); | 3441 | dsi_pll_uninit(); |
3106 | } | 3442 | } |
@@ -3220,29 +3556,107 @@ int dsi_init_display(struct omap_dss_device *dssdev) | |||
3220 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 3556 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
3221 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 3557 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
3222 | 3558 | ||
3223 | dsi.vc[0].dssdev = dssdev; | 3559 | if (dsi.vdds_dsi_reg == NULL) { |
3224 | dsi.vc[1].dssdev = dssdev; | 3560 | struct regulator *vdds_dsi; |
3561 | |||
3562 | vdds_dsi = regulator_get(&dsi.pdev->dev, "vdds_dsi"); | ||
3563 | |||
3564 | if (IS_ERR(vdds_dsi)) { | ||
3565 | DSSERR("can't get VDDS_DSI regulator\n"); | ||
3566 | return PTR_ERR(vdds_dsi); | ||
3567 | } | ||
3568 | |||
3569 | dsi.vdds_dsi_reg = vdds_dsi; | ||
3570 | } | ||
3225 | 3571 | ||
3226 | return 0; | 3572 | return 0; |
3227 | } | 3573 | } |
3228 | 3574 | ||
3229 | void dsi_wait_dsi1_pll_active(void) | 3575 | int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel) |
3576 | { | ||
3577 | int i; | ||
3578 | |||
3579 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3580 | if (!dsi.vc[i].dssdev) { | ||
3581 | dsi.vc[i].dssdev = dssdev; | ||
3582 | *channel = i; | ||
3583 | return 0; | ||
3584 | } | ||
3585 | } | ||
3586 | |||
3587 | DSSERR("cannot get VC for display %s", dssdev->name); | ||
3588 | return -ENOSPC; | ||
3589 | } | ||
3590 | EXPORT_SYMBOL(omap_dsi_request_vc); | ||
3591 | |||
3592 | int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id) | ||
3593 | { | ||
3594 | if (vc_id < 0 || vc_id > 3) { | ||
3595 | DSSERR("VC ID out of range\n"); | ||
3596 | return -EINVAL; | ||
3597 | } | ||
3598 | |||
3599 | if (channel < 0 || channel > 3) { | ||
3600 | DSSERR("Virtual Channel out of range\n"); | ||
3601 | return -EINVAL; | ||
3602 | } | ||
3603 | |||
3604 | if (dsi.vc[channel].dssdev != dssdev) { | ||
3605 | DSSERR("Virtual Channel not allocated to display %s\n", | ||
3606 | dssdev->name); | ||
3607 | return -EINVAL; | ||
3608 | } | ||
3609 | |||
3610 | dsi.vc[channel].vc_id = vc_id; | ||
3611 | |||
3612 | return 0; | ||
3613 | } | ||
3614 | EXPORT_SYMBOL(omap_dsi_set_vc_id); | ||
3615 | |||
3616 | void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel) | ||
3617 | { | ||
3618 | if ((channel >= 0 && channel <= 3) && | ||
3619 | dsi.vc[channel].dssdev == dssdev) { | ||
3620 | dsi.vc[channel].dssdev = NULL; | ||
3621 | dsi.vc[channel].vc_id = 0; | ||
3622 | } | ||
3623 | } | ||
3624 | EXPORT_SYMBOL(omap_dsi_release_vc); | ||
3625 | |||
3626 | void dsi_wait_pll_hsdiv_dispc_active(void) | ||
3230 | { | 3627 | { |
3231 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) | 3628 | if (wait_for_bit_change(DSI_PLL_STATUS, 7, 1) != 1) |
3232 | DSSERR("DSI1 PLL clock not active\n"); | 3629 | DSSERR("%s (%s) not active\n", |
3630 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC), | ||
3631 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC)); | ||
3233 | } | 3632 | } |
3234 | 3633 | ||
3235 | void dsi_wait_dsi2_pll_active(void) | 3634 | void dsi_wait_pll_hsdiv_dsi_active(void) |
3236 | { | 3635 | { |
3237 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) | 3636 | if (wait_for_bit_change(DSI_PLL_STATUS, 8, 1) != 1) |
3238 | DSSERR("DSI2 PLL clock not active\n"); | 3637 | DSSERR("%s (%s) not active\n", |
3638 | dss_get_generic_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI), | ||
3639 | dss_feat_get_clk_source_name(DSS_CLK_SRC_DSI_PLL_HSDIV_DSI)); | ||
3640 | } | ||
3641 | |||
3642 | static void dsi_calc_clock_param_ranges(void) | ||
3643 | { | ||
3644 | dsi.regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN); | ||
3645 | dsi.regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM); | ||
3646 | dsi.regm_dispc_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC); | ||
3647 | dsi.regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI); | ||
3648 | dsi.fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT); | ||
3649 | dsi.fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT); | ||
3650 | dsi.lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV); | ||
3239 | } | 3651 | } |
3240 | 3652 | ||
3241 | int dsi_init(struct platform_device *pdev) | 3653 | static int dsi_init(struct platform_device *pdev) |
3242 | { | 3654 | { |
3243 | u32 rev; | 3655 | u32 rev; |
3244 | int r; | 3656 | int r, i; |
3657 | struct resource *dsi_mem; | ||
3245 | 3658 | ||
3659 | spin_lock_init(&dsi.irq_lock); | ||
3246 | spin_lock_init(&dsi.errors_lock); | 3660 | spin_lock_init(&dsi.errors_lock); |
3247 | dsi.errors = 0; | 3661 | dsi.errors = 0; |
3248 | 3662 | ||
@@ -3251,8 +3665,6 @@ int dsi_init(struct platform_device *pdev) | |||
3251 | dsi.irq_stats.last_reset = jiffies; | 3665 | dsi.irq_stats.last_reset = jiffies; |
3252 | #endif | 3666 | #endif |
3253 | 3667 | ||
3254 | init_completion(&dsi.bta_completion); | ||
3255 | |||
3256 | mutex_init(&dsi.lock); | 3668 | mutex_init(&dsi.lock); |
3257 | sema_init(&dsi.bus_lock, 1); | 3669 | sema_init(&dsi.bus_lock, 1); |
3258 | 3670 | ||
@@ -3268,24 +3680,45 @@ int dsi_init(struct platform_device *pdev) | |||
3268 | dsi.te_timer.function = dsi_te_timeout; | 3680 | dsi.te_timer.function = dsi_te_timeout; |
3269 | dsi.te_timer.data = 0; | 3681 | dsi.te_timer.data = 0; |
3270 | #endif | 3682 | #endif |
3271 | dsi.base = ioremap(DSI_BASE, DSI_SZ_REGS); | 3683 | dsi_mem = platform_get_resource(dsi.pdev, IORESOURCE_MEM, 0); |
3684 | if (!dsi_mem) { | ||
3685 | DSSERR("can't get IORESOURCE_MEM DSI\n"); | ||
3686 | r = -EINVAL; | ||
3687 | goto err1; | ||
3688 | } | ||
3689 | dsi.base = ioremap(dsi_mem->start, resource_size(dsi_mem)); | ||
3272 | if (!dsi.base) { | 3690 | if (!dsi.base) { |
3273 | DSSERR("can't ioremap DSI\n"); | 3691 | DSSERR("can't ioremap DSI\n"); |
3274 | r = -ENOMEM; | 3692 | r = -ENOMEM; |
3275 | goto err1; | 3693 | goto err1; |
3276 | } | 3694 | } |
3695 | dsi.irq = platform_get_irq(dsi.pdev, 0); | ||
3696 | if (dsi.irq < 0) { | ||
3697 | DSSERR("platform_get_irq failed\n"); | ||
3698 | r = -ENODEV; | ||
3699 | goto err2; | ||
3700 | } | ||
3277 | 3701 | ||
3278 | dsi.vdds_dsi_reg = dss_get_vdds_dsi(); | 3702 | r = request_irq(dsi.irq, omap_dsi_irq_handler, IRQF_SHARED, |
3279 | if (IS_ERR(dsi.vdds_dsi_reg)) { | 3703 | "OMAP DSI1", dsi.pdev); |
3280 | DSSERR("can't get VDDS_DSI regulator\n"); | 3704 | if (r < 0) { |
3281 | r = PTR_ERR(dsi.vdds_dsi_reg); | 3705 | DSSERR("request_irq failed\n"); |
3282 | goto err2; | 3706 | goto err2; |
3283 | } | 3707 | } |
3284 | 3708 | ||
3709 | /* DSI VCs initialization */ | ||
3710 | for (i = 0; i < ARRAY_SIZE(dsi.vc); i++) { | ||
3711 | dsi.vc[i].mode = DSI_VC_MODE_L4; | ||
3712 | dsi.vc[i].dssdev = NULL; | ||
3713 | dsi.vc[i].vc_id = 0; | ||
3714 | } | ||
3715 | |||
3716 | dsi_calc_clock_param_ranges(); | ||
3717 | |||
3285 | enable_clocks(1); | 3718 | enable_clocks(1); |
3286 | 3719 | ||
3287 | rev = dsi_read_reg(DSI_REVISION); | 3720 | rev = dsi_read_reg(DSI_REVISION); |
3288 | printk(KERN_INFO "OMAP DSI rev %d.%d\n", | 3721 | dev_dbg(&pdev->dev, "OMAP DSI rev %d.%d\n", |
3289 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 3722 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
3290 | 3723 | ||
3291 | enable_clocks(0); | 3724 | enable_clocks(0); |
@@ -3298,8 +3731,14 @@ err1: | |||
3298 | return r; | 3731 | return r; |
3299 | } | 3732 | } |
3300 | 3733 | ||
3301 | void dsi_exit(void) | 3734 | static void dsi_exit(void) |
3302 | { | 3735 | { |
3736 | if (dsi.vdds_dsi_reg != NULL) { | ||
3737 | regulator_put(dsi.vdds_dsi_reg); | ||
3738 | dsi.vdds_dsi_reg = NULL; | ||
3739 | } | ||
3740 | |||
3741 | free_irq(dsi.irq, dsi.pdev); | ||
3303 | iounmap(dsi.base); | 3742 | iounmap(dsi.base); |
3304 | 3743 | ||
3305 | destroy_workqueue(dsi.workqueue); | 3744 | destroy_workqueue(dsi.workqueue); |
@@ -3307,3 +3746,41 @@ void dsi_exit(void) | |||
3307 | DSSDBG("omap_dsi_exit\n"); | 3746 | DSSDBG("omap_dsi_exit\n"); |
3308 | } | 3747 | } |
3309 | 3748 | ||
3749 | /* DSI1 HW IP initialisation */ | ||
3750 | static int omap_dsi1hw_probe(struct platform_device *pdev) | ||
3751 | { | ||
3752 | int r; | ||
3753 | dsi.pdev = pdev; | ||
3754 | r = dsi_init(pdev); | ||
3755 | if (r) { | ||
3756 | DSSERR("Failed to initialize DSI\n"); | ||
3757 | goto err_dsi; | ||
3758 | } | ||
3759 | err_dsi: | ||
3760 | return r; | ||
3761 | } | ||
3762 | |||
3763 | static int omap_dsi1hw_remove(struct platform_device *pdev) | ||
3764 | { | ||
3765 | dsi_exit(); | ||
3766 | return 0; | ||
3767 | } | ||
3768 | |||
3769 | static struct platform_driver omap_dsi1hw_driver = { | ||
3770 | .probe = omap_dsi1hw_probe, | ||
3771 | .remove = omap_dsi1hw_remove, | ||
3772 | .driver = { | ||
3773 | .name = "omapdss_dsi1", | ||
3774 | .owner = THIS_MODULE, | ||
3775 | }, | ||
3776 | }; | ||
3777 | |||
3778 | int dsi_init_platform_driver(void) | ||
3779 | { | ||
3780 | return platform_driver_register(&omap_dsi1hw_driver); | ||
3781 | } | ||
3782 | |||
3783 | void dsi_uninit_platform_driver(void) | ||
3784 | { | ||
3785 | return platform_driver_unregister(&omap_dsi1hw_driver); | ||
3786 | } | ||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 77c3621c9171..3f1fee63c678 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -26,14 +26,13 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/seq_file.h> | 29 | #include <linux/seq_file.h> |
31 | #include <linux/clk.h> | 30 | #include <linux/clk.h> |
32 | 31 | ||
33 | #include <plat/display.h> | 32 | #include <plat/display.h> |
33 | #include <plat/clock.h> | ||
34 | #include "dss.h" | 34 | #include "dss.h" |
35 | 35 | #include "dss_features.h" | |
36 | #define DSS_BASE 0x48050000 | ||
37 | 36 | ||
38 | #define DSS_SZ_REGS SZ_512 | 37 | #define DSS_SZ_REGS SZ_512 |
39 | 38 | ||
@@ -59,9 +58,17 @@ struct dss_reg { | |||
59 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) | 58 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) |
60 | 59 | ||
61 | static struct { | 60 | static struct { |
61 | struct platform_device *pdev; | ||
62 | void __iomem *base; | 62 | void __iomem *base; |
63 | int ctx_id; | ||
63 | 64 | ||
64 | struct clk *dpll4_m4_ck; | 65 | struct clk *dpll4_m4_ck; |
66 | struct clk *dss_ick; | ||
67 | struct clk *dss_fck; | ||
68 | struct clk *dss_sys_clk; | ||
69 | struct clk *dss_tv_fck; | ||
70 | struct clk *dss_video_fck; | ||
71 | unsigned num_clks_enabled; | ||
65 | 72 | ||
66 | unsigned long cache_req_pck; | 73 | unsigned long cache_req_pck; |
67 | unsigned long cache_prate; | 74 | unsigned long cache_prate; |
@@ -70,10 +77,22 @@ static struct { | |||
70 | 77 | ||
71 | enum dss_clk_source dsi_clk_source; | 78 | enum dss_clk_source dsi_clk_source; |
72 | enum dss_clk_source dispc_clk_source; | 79 | enum dss_clk_source dispc_clk_source; |
80 | enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; | ||
73 | 81 | ||
74 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 82 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
75 | } dss; | 83 | } dss; |
76 | 84 | ||
85 | static const char * const dss_generic_clk_source_names[] = { | ||
86 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", | ||
87 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", | ||
88 | [DSS_CLK_SRC_FCK] = "DSS_FCK", | ||
89 | }; | ||
90 | |||
91 | static void dss_clk_enable_all_no_ctx(void); | ||
92 | static void dss_clk_disable_all_no_ctx(void); | ||
93 | static void dss_clk_enable_no_ctx(enum dss_clock clks); | ||
94 | static void dss_clk_disable_no_ctx(enum dss_clock clks); | ||
95 | |||
77 | static int _omap_dss_wait_reset(void); | 96 | static int _omap_dss_wait_reset(void); |
78 | 97 | ||
79 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) | 98 | static inline void dss_write_reg(const struct dss_reg idx, u32 val) |
@@ -99,10 +118,11 @@ void dss_save_context(void) | |||
99 | SR(SYSCONFIG); | 118 | SR(SYSCONFIG); |
100 | SR(CONTROL); | 119 | SR(CONTROL); |
101 | 120 | ||
102 | #ifdef CONFIG_OMAP2_DSS_SDI | 121 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
103 | SR(SDI_CONTROL); | 122 | OMAP_DISPLAY_TYPE_SDI) { |
104 | SR(PLL_CONTROL); | 123 | SR(SDI_CONTROL); |
105 | #endif | 124 | SR(PLL_CONTROL); |
125 | } | ||
106 | } | 126 | } |
107 | 127 | ||
108 | void dss_restore_context(void) | 128 | void dss_restore_context(void) |
@@ -113,10 +133,11 @@ void dss_restore_context(void) | |||
113 | RR(SYSCONFIG); | 133 | RR(SYSCONFIG); |
114 | RR(CONTROL); | 134 | RR(CONTROL); |
115 | 135 | ||
116 | #ifdef CONFIG_OMAP2_DSS_SDI | 136 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
117 | RR(SDI_CONTROL); | 137 | OMAP_DISPLAY_TYPE_SDI) { |
118 | RR(PLL_CONTROL); | 138 | RR(SDI_CONTROL); |
119 | #endif | 139 | RR(PLL_CONTROL); |
140 | } | ||
120 | } | 141 | } |
121 | 142 | ||
122 | #undef SR | 143 | #undef SR |
@@ -209,66 +230,96 @@ void dss_sdi_disable(void) | |||
209 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ | 230 | REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ |
210 | } | 231 | } |
211 | 232 | ||
233 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src) | ||
234 | { | ||
235 | return dss_generic_clk_source_names[clk_src]; | ||
236 | } | ||
237 | |||
212 | void dss_dump_clocks(struct seq_file *s) | 238 | void dss_dump_clocks(struct seq_file *s) |
213 | { | 239 | { |
214 | unsigned long dpll4_ck_rate; | 240 | unsigned long dpll4_ck_rate; |
215 | unsigned long dpll4_m4_ck_rate; | 241 | unsigned long dpll4_m4_ck_rate; |
242 | const char *fclk_name, *fclk_real_name; | ||
243 | unsigned long fclk_rate; | ||
216 | 244 | ||
217 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 245 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
218 | |||
219 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | ||
220 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); | ||
221 | 246 | ||
222 | seq_printf(s, "- DSS -\n"); | 247 | seq_printf(s, "- DSS -\n"); |
223 | 248 | ||
224 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); | 249 | fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK); |
250 | fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK); | ||
251 | fclk_rate = dss_clk_get_rate(DSS_CLK_FCK); | ||
225 | 252 | ||
226 | if (cpu_is_omap3630()) | 253 | if (dss.dpll4_m4_ck) { |
227 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu = %lu\n", | 254 | dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
228 | dpll4_ck_rate, | 255 | dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck); |
229 | dpll4_ck_rate / dpll4_m4_ck_rate, | 256 | |
230 | dss_clk_get_rate(DSS_CLK_FCK1)); | 257 | seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate); |
231 | else | ||
232 | seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n", | ||
233 | dpll4_ck_rate, | ||
234 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
235 | dss_clk_get_rate(DSS_CLK_FCK1)); | ||
236 | 258 | ||
237 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 259 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
260 | seq_printf(s, "%s (%s) = %lu / %lu = %lu\n", | ||
261 | fclk_name, fclk_real_name, | ||
262 | dpll4_ck_rate, | ||
263 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
264 | fclk_rate); | ||
265 | else | ||
266 | seq_printf(s, "%s (%s) = %lu / %lu * 2 = %lu\n", | ||
267 | fclk_name, fclk_real_name, | ||
268 | dpll4_ck_rate, | ||
269 | dpll4_ck_rate / dpll4_m4_ck_rate, | ||
270 | fclk_rate); | ||
271 | } else { | ||
272 | seq_printf(s, "%s (%s) = %lu\n", | ||
273 | fclk_name, fclk_real_name, | ||
274 | fclk_rate); | ||
275 | } | ||
276 | |||
277 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
238 | } | 278 | } |
239 | 279 | ||
240 | void dss_dump_regs(struct seq_file *s) | 280 | void dss_dump_regs(struct seq_file *s) |
241 | { | 281 | { |
242 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) | 282 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) |
243 | 283 | ||
244 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 284 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
245 | 285 | ||
246 | DUMPREG(DSS_REVISION); | 286 | DUMPREG(DSS_REVISION); |
247 | DUMPREG(DSS_SYSCONFIG); | 287 | DUMPREG(DSS_SYSCONFIG); |
248 | DUMPREG(DSS_SYSSTATUS); | 288 | DUMPREG(DSS_SYSSTATUS); |
249 | DUMPREG(DSS_IRQSTATUS); | 289 | DUMPREG(DSS_IRQSTATUS); |
250 | DUMPREG(DSS_CONTROL); | 290 | DUMPREG(DSS_CONTROL); |
251 | DUMPREG(DSS_SDI_CONTROL); | ||
252 | DUMPREG(DSS_PLL_CONTROL); | ||
253 | DUMPREG(DSS_SDI_STATUS); | ||
254 | 291 | ||
255 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 292 | if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & |
293 | OMAP_DISPLAY_TYPE_SDI) { | ||
294 | DUMPREG(DSS_SDI_CONTROL); | ||
295 | DUMPREG(DSS_PLL_CONTROL); | ||
296 | DUMPREG(DSS_SDI_STATUS); | ||
297 | } | ||
298 | |||
299 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); | ||
256 | #undef DUMPREG | 300 | #undef DUMPREG |
257 | } | 301 | } |
258 | 302 | ||
259 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) | 303 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src) |
260 | { | 304 | { |
261 | int b; | 305 | int b; |
306 | u8 start, end; | ||
307 | |||
308 | switch (clk_src) { | ||
309 | case DSS_CLK_SRC_FCK: | ||
310 | b = 0; | ||
311 | break; | ||
312 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
313 | b = 1; | ||
314 | dsi_wait_pll_hsdiv_dispc_active(); | ||
315 | break; | ||
316 | default: | ||
317 | BUG(); | ||
318 | } | ||
262 | 319 | ||
263 | BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK && | 320 | dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); |
264 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | ||
265 | |||
266 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | ||
267 | |||
268 | if (clk_src == DSS_SRC_DSI1_PLL_FCLK) | ||
269 | dsi_wait_dsi1_pll_active(); | ||
270 | 321 | ||
271 | REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */ | 322 | REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ |
272 | 323 | ||
273 | dss.dispc_clk_source = clk_src; | 324 | dss.dispc_clk_source = clk_src; |
274 | } | 325 | } |
@@ -277,19 +328,51 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src) | |||
277 | { | 328 | { |
278 | int b; | 329 | int b; |
279 | 330 | ||
280 | BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK && | 331 | switch (clk_src) { |
281 | clk_src != DSS_SRC_DSS1_ALWON_FCLK); | 332 | case DSS_CLK_SRC_FCK: |
282 | 333 | b = 0; | |
283 | b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1; | 334 | break; |
284 | 335 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: | |
285 | if (clk_src == DSS_SRC_DSI2_PLL_FCLK) | 336 | b = 1; |
286 | dsi_wait_dsi2_pll_active(); | 337 | dsi_wait_pll_hsdiv_dsi_active(); |
338 | break; | ||
339 | default: | ||
340 | BUG(); | ||
341 | } | ||
287 | 342 | ||
288 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ | 343 | REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */ |
289 | 344 | ||
290 | dss.dsi_clk_source = clk_src; | 345 | dss.dsi_clk_source = clk_src; |
291 | } | 346 | } |
292 | 347 | ||
348 | void dss_select_lcd_clk_source(enum omap_channel channel, | ||
349 | enum dss_clk_source clk_src) | ||
350 | { | ||
351 | int b, ix, pos; | ||
352 | |||
353 | if (!dss_has_feature(FEAT_LCD_CLK_SRC)) | ||
354 | return; | ||
355 | |||
356 | switch (clk_src) { | ||
357 | case DSS_CLK_SRC_FCK: | ||
358 | b = 0; | ||
359 | break; | ||
360 | case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | ||
361 | BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); | ||
362 | b = 1; | ||
363 | dsi_wait_pll_hsdiv_dispc_active(); | ||
364 | break; | ||
365 | default: | ||
366 | BUG(); | ||
367 | } | ||
368 | |||
369 | pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12; | ||
370 | REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ | ||
371 | |||
372 | ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
373 | dss.lcd_clk_source[ix] = clk_src; | ||
374 | } | ||
375 | |||
293 | enum dss_clk_source dss_get_dispc_clk_source(void) | 376 | enum dss_clk_source dss_get_dispc_clk_source(void) |
294 | { | 377 | { |
295 | return dss.dispc_clk_source; | 378 | return dss.dispc_clk_source; |
@@ -300,34 +383,52 @@ enum dss_clk_source dss_get_dsi_clk_source(void) | |||
300 | return dss.dsi_clk_source; | 383 | return dss.dsi_clk_source; |
301 | } | 384 | } |
302 | 385 | ||
386 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) | ||
387 | { | ||
388 | int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1; | ||
389 | return dss.lcd_clk_source[ix]; | ||
390 | } | ||
391 | |||
303 | /* calculate clock rates using dividers in cinfo */ | 392 | /* calculate clock rates using dividers in cinfo */ |
304 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) | 393 | int dss_calc_clock_rates(struct dss_clock_info *cinfo) |
305 | { | 394 | { |
306 | unsigned long prate; | 395 | if (dss.dpll4_m4_ck) { |
396 | unsigned long prate; | ||
397 | u16 fck_div_max = 16; | ||
307 | 398 | ||
308 | if (cinfo->fck_div > (cpu_is_omap3630() ? 32 : 16) || | 399 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
309 | cinfo->fck_div == 0) | 400 | fck_div_max = 32; |
310 | return -EINVAL; | 401 | |
402 | if (cinfo->fck_div > fck_div_max || cinfo->fck_div == 0) | ||
403 | return -EINVAL; | ||
311 | 404 | ||
312 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 405 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
313 | 406 | ||
314 | cinfo->fck = prate / cinfo->fck_div; | 407 | cinfo->fck = prate / cinfo->fck_div; |
408 | } else { | ||
409 | if (cinfo->fck_div != 0) | ||
410 | return -EINVAL; | ||
411 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
412 | } | ||
315 | 413 | ||
316 | return 0; | 414 | return 0; |
317 | } | 415 | } |
318 | 416 | ||
319 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 417 | int dss_set_clock_div(struct dss_clock_info *cinfo) |
320 | { | 418 | { |
321 | unsigned long prate; | 419 | if (dss.dpll4_m4_ck) { |
322 | int r; | 420 | unsigned long prate; |
421 | int r; | ||
323 | 422 | ||
324 | if (cpu_is_omap34xx()) { | ||
325 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 423 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
326 | DSSDBG("dpll4_m4 = %ld\n", prate); | 424 | DSSDBG("dpll4_m4 = %ld\n", prate); |
327 | 425 | ||
328 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); | 426 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); |
329 | if (r) | 427 | if (r) |
330 | return r; | 428 | return r; |
429 | } else { | ||
430 | if (cinfo->fck_div != 0) | ||
431 | return -EINVAL; | ||
331 | } | 432 | } |
332 | 433 | ||
333 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); | 434 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); |
@@ -337,12 +438,14 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
337 | 438 | ||
338 | int dss_get_clock_div(struct dss_clock_info *cinfo) | 439 | int dss_get_clock_div(struct dss_clock_info *cinfo) |
339 | { | 440 | { |
340 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1); | 441 | cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK); |
341 | 442 | ||
342 | if (cpu_is_omap34xx()) { | 443 | if (dss.dpll4_m4_ck) { |
343 | unsigned long prate; | 444 | unsigned long prate; |
445 | |||
344 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 446 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
345 | if (cpu_is_omap3630()) | 447 | |
448 | if (cpu_is_omap3630() || cpu_is_omap44xx()) | ||
346 | cinfo->fck_div = prate / (cinfo->fck); | 449 | cinfo->fck_div = prate / (cinfo->fck); |
347 | else | 450 | else |
348 | cinfo->fck_div = prate / (cinfo->fck / 2); | 451 | cinfo->fck_div = prate / (cinfo->fck / 2); |
@@ -355,7 +458,7 @@ int dss_get_clock_div(struct dss_clock_info *cinfo) | |||
355 | 458 | ||
356 | unsigned long dss_get_dpll4_rate(void) | 459 | unsigned long dss_get_dpll4_rate(void) |
357 | { | 460 | { |
358 | if (cpu_is_omap34xx()) | 461 | if (dss.dpll4_m4_ck) |
359 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 462 | return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
360 | else | 463 | else |
361 | return 0; | 464 | return 0; |
@@ -369,16 +472,18 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
369 | struct dss_clock_info best_dss; | 472 | struct dss_clock_info best_dss; |
370 | struct dispc_clock_info best_dispc; | 473 | struct dispc_clock_info best_dispc; |
371 | 474 | ||
372 | unsigned long fck; | 475 | unsigned long fck, max_dss_fck; |
373 | 476 | ||
374 | u16 fck_div; | 477 | u16 fck_div, fck_div_max = 16; |
375 | 478 | ||
376 | int match = 0; | 479 | int match = 0; |
377 | int min_fck_per_pck; | 480 | int min_fck_per_pck; |
378 | 481 | ||
379 | prate = dss_get_dpll4_rate(); | 482 | prate = dss_get_dpll4_rate(); |
380 | 483 | ||
381 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 484 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
485 | |||
486 | fck = dss_clk_get_rate(DSS_CLK_FCK); | ||
382 | if (req_pck == dss.cache_req_pck && | 487 | if (req_pck == dss.cache_req_pck && |
383 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || | 488 | ((cpu_is_omap34xx() && prate == dss.cache_prate) || |
384 | dss.cache_dss_cinfo.fck == fck)) { | 489 | dss.cache_dss_cinfo.fck == fck)) { |
@@ -391,7 +496,7 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
391 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | 496 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
392 | 497 | ||
393 | if (min_fck_per_pck && | 498 | if (min_fck_per_pck && |
394 | req_pck * min_fck_per_pck > DISPC_MAX_FCK) { | 499 | req_pck * min_fck_per_pck > max_dss_fck) { |
395 | DSSERR("Requested pixel clock not possible with the current " | 500 | DSSERR("Requested pixel clock not possible with the current " |
396 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | 501 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " |
397 | "the constraint off.\n"); | 502 | "the constraint off.\n"); |
@@ -402,10 +507,10 @@ retry: | |||
402 | memset(&best_dss, 0, sizeof(best_dss)); | 507 | memset(&best_dss, 0, sizeof(best_dss)); |
403 | memset(&best_dispc, 0, sizeof(best_dispc)); | 508 | memset(&best_dispc, 0, sizeof(best_dispc)); |
404 | 509 | ||
405 | if (cpu_is_omap24xx()) { | 510 | if (dss.dpll4_m4_ck == NULL) { |
406 | struct dispc_clock_info cur_dispc; | 511 | struct dispc_clock_info cur_dispc; |
407 | /* XXX can we change the clock on omap2? */ | 512 | /* XXX can we change the clock on omap2? */ |
408 | fck = dss_clk_get_rate(DSS_CLK_FCK1); | 513 | fck = dss_clk_get_rate(DSS_CLK_FCK); |
409 | fck_div = 1; | 514 | fck_div = 1; |
410 | 515 | ||
411 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); | 516 | dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc); |
@@ -417,17 +522,19 @@ retry: | |||
417 | best_dispc = cur_dispc; | 522 | best_dispc = cur_dispc; |
418 | 523 | ||
419 | goto found; | 524 | goto found; |
420 | } else if (cpu_is_omap34xx()) { | 525 | } else { |
421 | for (fck_div = (cpu_is_omap3630() ? 32 : 16); | 526 | if (cpu_is_omap3630() || cpu_is_omap44xx()) |
422 | fck_div > 0; --fck_div) { | 527 | fck_div_max = 32; |
528 | |||
529 | for (fck_div = fck_div_max; fck_div > 0; --fck_div) { | ||
423 | struct dispc_clock_info cur_dispc; | 530 | struct dispc_clock_info cur_dispc; |
424 | 531 | ||
425 | if (cpu_is_omap3630()) | 532 | if (fck_div_max == 32) |
426 | fck = prate / fck_div; | 533 | fck = prate / fck_div; |
427 | else | 534 | else |
428 | fck = prate / fck_div * 2; | 535 | fck = prate / fck_div * 2; |
429 | 536 | ||
430 | if (fck > DISPC_MAX_FCK) | 537 | if (fck > max_dss_fck) |
431 | continue; | 538 | continue; |
432 | 539 | ||
433 | if (min_fck_per_pck && | 540 | if (min_fck_per_pck && |
@@ -450,8 +557,6 @@ retry: | |||
450 | goto found; | 557 | goto found; |
451 | } | 558 | } |
452 | } | 559 | } |
453 | } else { | ||
454 | BUG(); | ||
455 | } | 560 | } |
456 | 561 | ||
457 | found: | 562 | found: |
@@ -482,31 +587,6 @@ found: | |||
482 | return 0; | 587 | return 0; |
483 | } | 588 | } |
484 | 589 | ||
485 | |||
486 | |||
487 | static irqreturn_t dss_irq_handler_omap2(int irq, void *arg) | ||
488 | { | ||
489 | dispc_irq_handler(); | ||
490 | |||
491 | return IRQ_HANDLED; | ||
492 | } | ||
493 | |||
494 | static irqreturn_t dss_irq_handler_omap3(int irq, void *arg) | ||
495 | { | ||
496 | u32 irqstatus; | ||
497 | |||
498 | irqstatus = dss_read_reg(DSS_IRQSTATUS); | ||
499 | |||
500 | if (irqstatus & (1<<0)) /* DISPC_IRQ */ | ||
501 | dispc_irq_handler(); | ||
502 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
503 | if (irqstatus & (1<<1)) /* DSI_IRQ */ | ||
504 | dsi_irq_handler(); | ||
505 | #endif | ||
506 | |||
507 | return IRQ_HANDLED; | ||
508 | } | ||
509 | |||
510 | static int _omap_dss_wait_reset(void) | 590 | static int _omap_dss_wait_reset(void) |
511 | { | 591 | { |
512 | int t = 0; | 592 | int t = 0; |
@@ -549,34 +629,45 @@ void dss_set_dac_pwrdn_bgz(bool enable) | |||
549 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ | 629 | REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ |
550 | } | 630 | } |
551 | 631 | ||
552 | int dss_init(bool skip_init) | 632 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select hdmi) |
633 | { | ||
634 | REG_FLD_MOD(DSS_CONTROL, hdmi, 15, 15); /* VENC_HDMI_SWITCH */ | ||
635 | } | ||
636 | |||
637 | static int dss_init(void) | ||
553 | { | 638 | { |
554 | int r; | 639 | int r; |
555 | u32 rev; | 640 | u32 rev; |
641 | struct resource *dss_mem; | ||
642 | struct clk *dpll4_m4_ck; | ||
556 | 643 | ||
557 | dss.base = ioremap(DSS_BASE, DSS_SZ_REGS); | 644 | dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); |
645 | if (!dss_mem) { | ||
646 | DSSERR("can't get IORESOURCE_MEM DSS\n"); | ||
647 | r = -EINVAL; | ||
648 | goto fail0; | ||
649 | } | ||
650 | dss.base = ioremap(dss_mem->start, resource_size(dss_mem)); | ||
558 | if (!dss.base) { | 651 | if (!dss.base) { |
559 | DSSERR("can't ioremap DSS\n"); | 652 | DSSERR("can't ioremap DSS\n"); |
560 | r = -ENOMEM; | 653 | r = -ENOMEM; |
561 | goto fail0; | 654 | goto fail0; |
562 | } | 655 | } |
563 | 656 | ||
564 | if (!skip_init) { | 657 | /* disable LCD and DIGIT output. This seems to fix the synclost |
565 | /* disable LCD and DIGIT output. This seems to fix the synclost | 658 | * problem that we get, if the bootloader starts the DSS and |
566 | * problem that we get, if the bootloader starts the DSS and | 659 | * the kernel resets it */ |
567 | * the kernel resets it */ | 660 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); |
568 | omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440); | ||
569 | 661 | ||
570 | /* We need to wait here a bit, otherwise we sometimes start to | 662 | /* We need to wait here a bit, otherwise we sometimes start to |
571 | * get synclost errors, and after that only power cycle will | 663 | * get synclost errors, and after that only power cycle will |
572 | * restore DSS functionality. I have no idea why this happens. | 664 | * restore DSS functionality. I have no idea why this happens. |
573 | * And we have to wait _before_ resetting the DSS, but after | 665 | * And we have to wait _before_ resetting the DSS, but after |
574 | * enabling clocks. | 666 | * enabling clocks. |
575 | */ | 667 | */ |
576 | msleep(50); | 668 | msleep(50); |
577 | 669 | ||
578 | _omap_dss_reset(); | 670 | _omap_dss_reset(); |
579 | } | ||
580 | 671 | ||
581 | /* autoidle */ | 672 | /* autoidle */ |
582 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); | 673 | REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0); |
@@ -589,29 +680,30 @@ int dss_init(bool skip_init) | |||
589 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ | 680 | REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ |
590 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ | 681 | REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ |
591 | #endif | 682 | #endif |
592 | |||
593 | r = request_irq(INT_24XX_DSS_IRQ, | ||
594 | cpu_is_omap24xx() | ||
595 | ? dss_irq_handler_omap2 | ||
596 | : dss_irq_handler_omap3, | ||
597 | 0, "OMAP DSS", NULL); | ||
598 | |||
599 | if (r < 0) { | ||
600 | DSSERR("omap2 dss: request_irq failed\n"); | ||
601 | goto fail1; | ||
602 | } | ||
603 | |||
604 | if (cpu_is_omap34xx()) { | 683 | if (cpu_is_omap34xx()) { |
605 | dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); | 684 | dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck"); |
606 | if (IS_ERR(dss.dpll4_m4_ck)) { | 685 | if (IS_ERR(dpll4_m4_ck)) { |
607 | DSSERR("Failed to get dpll4_m4_ck\n"); | 686 | DSSERR("Failed to get dpll4_m4_ck\n"); |
608 | r = PTR_ERR(dss.dpll4_m4_ck); | 687 | r = PTR_ERR(dpll4_m4_ck); |
609 | goto fail2; | 688 | goto fail1; |
610 | } | 689 | } |
690 | } else if (cpu_is_omap44xx()) { | ||
691 | dpll4_m4_ck = clk_get(NULL, "dpll_per_m5x2_ck"); | ||
692 | if (IS_ERR(dpll4_m4_ck)) { | ||
693 | DSSERR("Failed to get dpll4_m4_ck\n"); | ||
694 | r = PTR_ERR(dpll4_m4_ck); | ||
695 | goto fail1; | ||
696 | } | ||
697 | } else { /* omap24xx */ | ||
698 | dpll4_m4_ck = NULL; | ||
611 | } | 699 | } |
612 | 700 | ||
613 | dss.dsi_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 701 | dss.dpll4_m4_ck = dpll4_m4_ck; |
614 | dss.dispc_clk_source = DSS_SRC_DSS1_ALWON_FCLK; | 702 | |
703 | dss.dsi_clk_source = DSS_CLK_SRC_FCK; | ||
704 | dss.dispc_clk_source = DSS_CLK_SRC_FCK; | ||
705 | dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK; | ||
706 | dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; | ||
615 | 707 | ||
616 | dss_save_context(); | 708 | dss_save_context(); |
617 | 709 | ||
@@ -621,21 +713,416 @@ int dss_init(bool skip_init) | |||
621 | 713 | ||
622 | return 0; | 714 | return 0; |
623 | 715 | ||
624 | fail2: | ||
625 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
626 | fail1: | 716 | fail1: |
627 | iounmap(dss.base); | 717 | iounmap(dss.base); |
628 | fail0: | 718 | fail0: |
629 | return r; | 719 | return r; |
630 | } | 720 | } |
631 | 721 | ||
632 | void dss_exit(void) | 722 | static void dss_exit(void) |
633 | { | 723 | { |
634 | if (cpu_is_omap34xx()) | 724 | if (dss.dpll4_m4_ck) |
635 | clk_put(dss.dpll4_m4_ck); | 725 | clk_put(dss.dpll4_m4_ck); |
636 | 726 | ||
637 | free_irq(INT_24XX_DSS_IRQ, NULL); | ||
638 | |||
639 | iounmap(dss.base); | 727 | iounmap(dss.base); |
640 | } | 728 | } |
641 | 729 | ||
730 | /* CONTEXT */ | ||
731 | static int dss_get_ctx_id(void) | ||
732 | { | ||
733 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
734 | int r; | ||
735 | |||
736 | if (!pdata->board_data->get_last_off_on_transaction_id) | ||
737 | return 0; | ||
738 | r = pdata->board_data->get_last_off_on_transaction_id(&dss.pdev->dev); | ||
739 | if (r < 0) { | ||
740 | dev_err(&dss.pdev->dev, "getting transaction ID failed, " | ||
741 | "will force context restore\n"); | ||
742 | r = -1; | ||
743 | } | ||
744 | return r; | ||
745 | } | ||
746 | |||
747 | int dss_need_ctx_restore(void) | ||
748 | { | ||
749 | int id = dss_get_ctx_id(); | ||
750 | |||
751 | if (id < 0 || id != dss.ctx_id) { | ||
752 | DSSDBG("ctx id %d -> id %d\n", | ||
753 | dss.ctx_id, id); | ||
754 | dss.ctx_id = id; | ||
755 | return 1; | ||
756 | } else { | ||
757 | return 0; | ||
758 | } | ||
759 | } | ||
760 | |||
761 | static void save_all_ctx(void) | ||
762 | { | ||
763 | DSSDBG("save context\n"); | ||
764 | |||
765 | dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
766 | |||
767 | dss_save_context(); | ||
768 | dispc_save_context(); | ||
769 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
770 | dsi_save_context(); | ||
771 | #endif | ||
772 | |||
773 | dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK); | ||
774 | } | ||
775 | |||
776 | static void restore_all_ctx(void) | ||
777 | { | ||
778 | DSSDBG("restore context\n"); | ||
779 | |||
780 | dss_clk_enable_all_no_ctx(); | ||
781 | |||
782 | dss_restore_context(); | ||
783 | dispc_restore_context(); | ||
784 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
785 | dsi_restore_context(); | ||
786 | #endif | ||
787 | |||
788 | dss_clk_disable_all_no_ctx(); | ||
789 | } | ||
790 | |||
791 | static int dss_get_clock(struct clk **clock, const char *clk_name) | ||
792 | { | ||
793 | struct clk *clk; | ||
794 | |||
795 | clk = clk_get(&dss.pdev->dev, clk_name); | ||
796 | |||
797 | if (IS_ERR(clk)) { | ||
798 | DSSERR("can't get clock %s", clk_name); | ||
799 | return PTR_ERR(clk); | ||
800 | } | ||
801 | |||
802 | *clock = clk; | ||
803 | |||
804 | DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk)); | ||
805 | |||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | static int dss_get_clocks(void) | ||
810 | { | ||
811 | int r; | ||
812 | struct omap_display_platform_data *pdata = dss.pdev->dev.platform_data; | ||
813 | |||
814 | dss.dss_ick = NULL; | ||
815 | dss.dss_fck = NULL; | ||
816 | dss.dss_sys_clk = NULL; | ||
817 | dss.dss_tv_fck = NULL; | ||
818 | dss.dss_video_fck = NULL; | ||
819 | |||
820 | r = dss_get_clock(&dss.dss_ick, "ick"); | ||
821 | if (r) | ||
822 | goto err; | ||
823 | |||
824 | r = dss_get_clock(&dss.dss_fck, "fck"); | ||
825 | if (r) | ||
826 | goto err; | ||
827 | |||
828 | if (!pdata->opt_clock_available) { | ||
829 | r = -ENODEV; | ||
830 | goto err; | ||
831 | } | ||
832 | |||
833 | if (pdata->opt_clock_available("sys_clk")) { | ||
834 | r = dss_get_clock(&dss.dss_sys_clk, "sys_clk"); | ||
835 | if (r) | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | if (pdata->opt_clock_available("tv_clk")) { | ||
840 | r = dss_get_clock(&dss.dss_tv_fck, "tv_clk"); | ||
841 | if (r) | ||
842 | goto err; | ||
843 | } | ||
844 | |||
845 | if (pdata->opt_clock_available("video_clk")) { | ||
846 | r = dss_get_clock(&dss.dss_video_fck, "video_clk"); | ||
847 | if (r) | ||
848 | goto err; | ||
849 | } | ||
850 | |||
851 | return 0; | ||
852 | |||
853 | err: | ||
854 | if (dss.dss_ick) | ||
855 | clk_put(dss.dss_ick); | ||
856 | if (dss.dss_fck) | ||
857 | clk_put(dss.dss_fck); | ||
858 | if (dss.dss_sys_clk) | ||
859 | clk_put(dss.dss_sys_clk); | ||
860 | if (dss.dss_tv_fck) | ||
861 | clk_put(dss.dss_tv_fck); | ||
862 | if (dss.dss_video_fck) | ||
863 | clk_put(dss.dss_video_fck); | ||
864 | |||
865 | return r; | ||
866 | } | ||
867 | |||
868 | static void dss_put_clocks(void) | ||
869 | { | ||
870 | if (dss.dss_video_fck) | ||
871 | clk_put(dss.dss_video_fck); | ||
872 | if (dss.dss_tv_fck) | ||
873 | clk_put(dss.dss_tv_fck); | ||
874 | if (dss.dss_sys_clk) | ||
875 | clk_put(dss.dss_sys_clk); | ||
876 | clk_put(dss.dss_fck); | ||
877 | clk_put(dss.dss_ick); | ||
878 | } | ||
879 | |||
880 | unsigned long dss_clk_get_rate(enum dss_clock clk) | ||
881 | { | ||
882 | switch (clk) { | ||
883 | case DSS_CLK_ICK: | ||
884 | return clk_get_rate(dss.dss_ick); | ||
885 | case DSS_CLK_FCK: | ||
886 | return clk_get_rate(dss.dss_fck); | ||
887 | case DSS_CLK_SYSCK: | ||
888 | return clk_get_rate(dss.dss_sys_clk); | ||
889 | case DSS_CLK_TVFCK: | ||
890 | return clk_get_rate(dss.dss_tv_fck); | ||
891 | case DSS_CLK_VIDFCK: | ||
892 | return clk_get_rate(dss.dss_video_fck); | ||
893 | } | ||
894 | |||
895 | BUG(); | ||
896 | return 0; | ||
897 | } | ||
898 | |||
899 | static unsigned count_clk_bits(enum dss_clock clks) | ||
900 | { | ||
901 | unsigned num_clks = 0; | ||
902 | |||
903 | if (clks & DSS_CLK_ICK) | ||
904 | ++num_clks; | ||
905 | if (clks & DSS_CLK_FCK) | ||
906 | ++num_clks; | ||
907 | if (clks & DSS_CLK_SYSCK) | ||
908 | ++num_clks; | ||
909 | if (clks & DSS_CLK_TVFCK) | ||
910 | ++num_clks; | ||
911 | if (clks & DSS_CLK_VIDFCK) | ||
912 | ++num_clks; | ||
913 | |||
914 | return num_clks; | ||
915 | } | ||
916 | |||
917 | static void dss_clk_enable_no_ctx(enum dss_clock clks) | ||
918 | { | ||
919 | unsigned num_clks = count_clk_bits(clks); | ||
920 | |||
921 | if (clks & DSS_CLK_ICK) | ||
922 | clk_enable(dss.dss_ick); | ||
923 | if (clks & DSS_CLK_FCK) | ||
924 | clk_enable(dss.dss_fck); | ||
925 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
926 | clk_enable(dss.dss_sys_clk); | ||
927 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
928 | clk_enable(dss.dss_tv_fck); | ||
929 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
930 | clk_enable(dss.dss_video_fck); | ||
931 | |||
932 | dss.num_clks_enabled += num_clks; | ||
933 | } | ||
934 | |||
935 | void dss_clk_enable(enum dss_clock clks) | ||
936 | { | ||
937 | bool check_ctx = dss.num_clks_enabled == 0; | ||
938 | |||
939 | dss_clk_enable_no_ctx(clks); | ||
940 | |||
941 | /* | ||
942 | * HACK: On omap4 the registers may not be accessible right after | ||
943 | * enabling the clocks. At some point this will be handled by | ||
944 | * pm_runtime, but for the time begin this should make things work. | ||
945 | */ | ||
946 | if (cpu_is_omap44xx() && check_ctx) | ||
947 | udelay(10); | ||
948 | |||
949 | if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore()) | ||
950 | restore_all_ctx(); | ||
951 | } | ||
952 | |||
953 | static void dss_clk_disable_no_ctx(enum dss_clock clks) | ||
954 | { | ||
955 | unsigned num_clks = count_clk_bits(clks); | ||
956 | |||
957 | if (clks & DSS_CLK_ICK) | ||
958 | clk_disable(dss.dss_ick); | ||
959 | if (clks & DSS_CLK_FCK) | ||
960 | clk_disable(dss.dss_fck); | ||
961 | if ((clks & DSS_CLK_SYSCK) && dss.dss_sys_clk) | ||
962 | clk_disable(dss.dss_sys_clk); | ||
963 | if ((clks & DSS_CLK_TVFCK) && dss.dss_tv_fck) | ||
964 | clk_disable(dss.dss_tv_fck); | ||
965 | if ((clks & DSS_CLK_VIDFCK) && dss.dss_video_fck) | ||
966 | clk_disable(dss.dss_video_fck); | ||
967 | |||
968 | dss.num_clks_enabled -= num_clks; | ||
969 | } | ||
970 | |||
971 | void dss_clk_disable(enum dss_clock clks) | ||
972 | { | ||
973 | if (cpu_is_omap34xx()) { | ||
974 | unsigned num_clks = count_clk_bits(clks); | ||
975 | |||
976 | BUG_ON(dss.num_clks_enabled < num_clks); | ||
977 | |||
978 | if (dss.num_clks_enabled == num_clks) | ||
979 | save_all_ctx(); | ||
980 | } | ||
981 | |||
982 | dss_clk_disable_no_ctx(clks); | ||
983 | } | ||
984 | |||
985 | static void dss_clk_enable_all_no_ctx(void) | ||
986 | { | ||
987 | enum dss_clock clks; | ||
988 | |||
989 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
990 | if (cpu_is_omap34xx()) | ||
991 | clks |= DSS_CLK_VIDFCK; | ||
992 | dss_clk_enable_no_ctx(clks); | ||
993 | } | ||
994 | |||
995 | static void dss_clk_disable_all_no_ctx(void) | ||
996 | { | ||
997 | enum dss_clock clks; | ||
998 | |||
999 | clks = DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_SYSCK | DSS_CLK_TVFCK; | ||
1000 | if (cpu_is_omap34xx()) | ||
1001 | clks |= DSS_CLK_VIDFCK; | ||
1002 | dss_clk_disable_no_ctx(clks); | ||
1003 | } | ||
1004 | |||
1005 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1006 | /* CLOCKS */ | ||
1007 | static void core_dump_clocks(struct seq_file *s) | ||
1008 | { | ||
1009 | int i; | ||
1010 | struct clk *clocks[5] = { | ||
1011 | dss.dss_ick, | ||
1012 | dss.dss_fck, | ||
1013 | dss.dss_sys_clk, | ||
1014 | dss.dss_tv_fck, | ||
1015 | dss.dss_video_fck | ||
1016 | }; | ||
1017 | |||
1018 | seq_printf(s, "- CORE -\n"); | ||
1019 | |||
1020 | seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled); | ||
1021 | |||
1022 | for (i = 0; i < 5; i++) { | ||
1023 | if (!clocks[i]) | ||
1024 | continue; | ||
1025 | seq_printf(s, "%-15s\t%lu\t%d\n", | ||
1026 | clocks[i]->name, | ||
1027 | clk_get_rate(clocks[i]), | ||
1028 | clocks[i]->usecount); | ||
1029 | } | ||
1030 | } | ||
1031 | #endif /* defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) */ | ||
1032 | |||
1033 | /* DEBUGFS */ | ||
1034 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
1035 | void dss_debug_dump_clocks(struct seq_file *s) | ||
1036 | { | ||
1037 | core_dump_clocks(s); | ||
1038 | dss_dump_clocks(s); | ||
1039 | dispc_dump_clocks(s); | ||
1040 | #ifdef CONFIG_OMAP2_DSS_DSI | ||
1041 | dsi_dump_clocks(s); | ||
1042 | #endif | ||
1043 | } | ||
1044 | #endif | ||
1045 | |||
1046 | |||
1047 | /* DSS HW IP initialisation */ | ||
1048 | static int omap_dsshw_probe(struct platform_device *pdev) | ||
1049 | { | ||
1050 | int r; | ||
1051 | |||
1052 | dss.pdev = pdev; | ||
1053 | |||
1054 | r = dss_get_clocks(); | ||
1055 | if (r) | ||
1056 | goto err_clocks; | ||
1057 | |||
1058 | dss_clk_enable_all_no_ctx(); | ||
1059 | |||
1060 | dss.ctx_id = dss_get_ctx_id(); | ||
1061 | DSSDBG("initial ctx id %u\n", dss.ctx_id); | ||
1062 | |||
1063 | r = dss_init(); | ||
1064 | if (r) { | ||
1065 | DSSERR("Failed to initialize DSS\n"); | ||
1066 | goto err_dss; | ||
1067 | } | ||
1068 | |||
1069 | r = dpi_init(); | ||
1070 | if (r) { | ||
1071 | DSSERR("Failed to initialize DPI\n"); | ||
1072 | goto err_dpi; | ||
1073 | } | ||
1074 | |||
1075 | r = sdi_init(); | ||
1076 | if (r) { | ||
1077 | DSSERR("Failed to initialize SDI\n"); | ||
1078 | goto err_sdi; | ||
1079 | } | ||
1080 | |||
1081 | dss_clk_disable_all_no_ctx(); | ||
1082 | return 0; | ||
1083 | err_sdi: | ||
1084 | dpi_exit(); | ||
1085 | err_dpi: | ||
1086 | dss_exit(); | ||
1087 | err_dss: | ||
1088 | dss_clk_disable_all_no_ctx(); | ||
1089 | dss_put_clocks(); | ||
1090 | err_clocks: | ||
1091 | return r; | ||
1092 | } | ||
1093 | |||
1094 | static int omap_dsshw_remove(struct platform_device *pdev) | ||
1095 | { | ||
1096 | |||
1097 | dss_exit(); | ||
1098 | |||
1099 | /* | ||
1100 | * As part of hwmod changes, DSS is not the only controller of dss | ||
1101 | * clocks; hwmod framework itself will also enable clocks during hwmod | ||
1102 | * init for dss, and autoidle is set in h/w for DSS. Hence, there's no | ||
1103 | * need to disable clocks if their usecounts > 1. | ||
1104 | */ | ||
1105 | WARN_ON(dss.num_clks_enabled > 0); | ||
1106 | |||
1107 | dss_put_clocks(); | ||
1108 | return 0; | ||
1109 | } | ||
1110 | |||
1111 | static struct platform_driver omap_dsshw_driver = { | ||
1112 | .probe = omap_dsshw_probe, | ||
1113 | .remove = omap_dsshw_remove, | ||
1114 | .driver = { | ||
1115 | .name = "omapdss_dss", | ||
1116 | .owner = THIS_MODULE, | ||
1117 | }, | ||
1118 | }; | ||
1119 | |||
1120 | int dss_init_platform_driver(void) | ||
1121 | { | ||
1122 | return platform_driver_register(&omap_dsshw_driver); | ||
1123 | } | ||
1124 | |||
1125 | void dss_uninit_platform_driver(void) | ||
1126 | { | ||
1127 | return platform_driver_unregister(&omap_dsshw_driver); | ||
1128 | } | ||
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index b394951120ac..c2f582bb19c0 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -97,8 +97,6 @@ extern unsigned int dss_debug; | |||
97 | #define FLD_MOD(orig, val, start, end) \ | 97 | #define FLD_MOD(orig, val, start, end) \ |
98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) | 98 | (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end)) |
99 | 99 | ||
100 | #define DISPC_MAX_FCK 173000000 | ||
101 | |||
102 | enum omap_burst_size { | 100 | enum omap_burst_size { |
103 | OMAP_DSS_BURST_4x32 = 0, | 101 | OMAP_DSS_BURST_4x32 = 0, |
104 | OMAP_DSS_BURST_8x32 = 1, | 102 | OMAP_DSS_BURST_8x32 = 1, |
@@ -112,17 +110,25 @@ enum omap_parallel_interface_mode { | |||
112 | }; | 110 | }; |
113 | 111 | ||
114 | enum dss_clock { | 112 | enum dss_clock { |
115 | DSS_CLK_ICK = 1 << 0, | 113 | DSS_CLK_ICK = 1 << 0, /* DSS_L3_ICLK and DSS_L4_ICLK */ |
116 | DSS_CLK_FCK1 = 1 << 1, | 114 | DSS_CLK_FCK = 1 << 1, /* DSS1_ALWON_FCLK */ |
117 | DSS_CLK_FCK2 = 1 << 2, | 115 | DSS_CLK_SYSCK = 1 << 2, /* DSS2_ALWON_FCLK */ |
118 | DSS_CLK_54M = 1 << 3, | 116 | DSS_CLK_TVFCK = 1 << 3, /* DSS_TV_FCLK */ |
119 | DSS_CLK_96M = 1 << 4, | 117 | DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/ |
120 | }; | 118 | }; |
121 | 119 | ||
122 | enum dss_clk_source { | 120 | enum dss_clk_source { |
123 | DSS_SRC_DSI1_PLL_FCLK, | 121 | DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK |
124 | DSS_SRC_DSI2_PLL_FCLK, | 122 | * OMAP4: PLL1_CLK1 */ |
125 | DSS_SRC_DSS1_ALWON_FCLK, | 123 | DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK |
124 | * OMAP4: PLL1_CLK2 */ | ||
125 | DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK | ||
126 | * OMAP4: DSS_FCLK */ | ||
127 | }; | ||
128 | |||
129 | enum dss_hdmi_venc_clk_source_select { | ||
130 | DSS_VENC_TV_CLK = 0, | ||
131 | DSS_HDMI_M_PCLK = 1, | ||
126 | }; | 132 | }; |
127 | 133 | ||
128 | struct dss_clock_info { | 134 | struct dss_clock_info { |
@@ -148,36 +154,42 @@ struct dsi_clock_info { | |||
148 | unsigned long fint; | 154 | unsigned long fint; |
149 | unsigned long clkin4ddr; | 155 | unsigned long clkin4ddr; |
150 | unsigned long clkin; | 156 | unsigned long clkin; |
151 | unsigned long dsi1_pll_fclk; | 157 | unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK |
152 | unsigned long dsi2_pll_fclk; | 158 | * OMAP4: PLLx_CLK1 */ |
153 | 159 | unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK | |
160 | * OMAP4: PLLx_CLK2 */ | ||
154 | unsigned long lp_clk; | 161 | unsigned long lp_clk; |
155 | 162 | ||
156 | /* dividers */ | 163 | /* dividers */ |
157 | u16 regn; | 164 | u16 regn; |
158 | u16 regm; | 165 | u16 regm; |
159 | u16 regm3; | 166 | u16 regm_dispc; /* OMAP3: REGM3 |
160 | u16 regm4; | 167 | * OMAP4: REGM4 */ |
161 | 168 | u16 regm_dsi; /* OMAP3: REGM4 | |
169 | * OMAP4: REGM5 */ | ||
162 | u16 lp_clk_div; | 170 | u16 lp_clk_div; |
163 | 171 | ||
164 | u8 highfreq; | 172 | u8 highfreq; |
165 | bool use_dss2_fck; | 173 | bool use_sys_clk; |
174 | }; | ||
175 | |||
176 | /* HDMI PLL structure */ | ||
177 | struct hdmi_pll_info { | ||
178 | u16 regn; | ||
179 | u16 regm; | ||
180 | u32 regmf; | ||
181 | u16 regm2; | ||
182 | u16 regsd; | ||
183 | u16 dcofreq; | ||
166 | }; | 184 | }; |
167 | 185 | ||
168 | struct seq_file; | 186 | struct seq_file; |
169 | struct platform_device; | 187 | struct platform_device; |
170 | 188 | ||
171 | /* core */ | 189 | /* core */ |
172 | void dss_clk_enable(enum dss_clock clks); | ||
173 | void dss_clk_disable(enum dss_clock clks); | ||
174 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
175 | int dss_need_ctx_restore(void); | ||
176 | void dss_dump_clocks(struct seq_file *s); | ||
177 | struct bus_type *dss_get_bus(void); | 190 | struct bus_type *dss_get_bus(void); |
178 | struct regulator *dss_get_vdds_dsi(void); | 191 | struct regulator *dss_get_vdds_dsi(void); |
179 | struct regulator *dss_get_vdds_sdi(void); | 192 | struct regulator *dss_get_vdds_sdi(void); |
180 | struct regulator *dss_get_vdda_dac(void); | ||
181 | 193 | ||
182 | /* display */ | 194 | /* display */ |
183 | int dss_suspend_all_devices(void); | 195 | int dss_suspend_all_devices(void); |
@@ -214,13 +226,23 @@ void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); | |||
214 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); | 226 | void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); |
215 | 227 | ||
216 | /* DSS */ | 228 | /* DSS */ |
217 | int dss_init(bool skip_init); | 229 | int dss_init_platform_driver(void); |
218 | void dss_exit(void); | 230 | void dss_uninit_platform_driver(void); |
219 | 231 | ||
232 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | ||
220 | void dss_save_context(void); | 233 | void dss_save_context(void); |
221 | void dss_restore_context(void); | 234 | void dss_restore_context(void); |
235 | void dss_clk_enable(enum dss_clock clks); | ||
236 | void dss_clk_disable(enum dss_clock clks); | ||
237 | unsigned long dss_clk_get_rate(enum dss_clock clk); | ||
238 | int dss_need_ctx_restore(void); | ||
239 | const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src); | ||
240 | void dss_dump_clocks(struct seq_file *s); | ||
222 | 241 | ||
223 | void dss_dump_regs(struct seq_file *s); | 242 | void dss_dump_regs(struct seq_file *s); |
243 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) | ||
244 | void dss_debug_dump_clocks(struct seq_file *s); | ||
245 | #endif | ||
224 | 246 | ||
225 | void dss_sdi_init(u8 datapairs); | 247 | void dss_sdi_init(u8 datapairs); |
226 | int dss_sdi_enable(void); | 248 | int dss_sdi_enable(void); |
@@ -228,8 +250,11 @@ void dss_sdi_disable(void); | |||
228 | 250 | ||
229 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); | 251 | void dss_select_dispc_clk_source(enum dss_clk_source clk_src); |
230 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); | 252 | void dss_select_dsi_clk_source(enum dss_clk_source clk_src); |
253 | void dss_select_lcd_clk_source(enum omap_channel channel, | ||
254 | enum dss_clk_source clk_src); | ||
231 | enum dss_clk_source dss_get_dispc_clk_source(void); | 255 | enum dss_clk_source dss_get_dispc_clk_source(void); |
232 | enum dss_clk_source dss_get_dsi_clk_source(void); | 256 | enum dss_clk_source dss_get_dsi_clk_source(void); |
257 | enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel); | ||
233 | 258 | ||
234 | void dss_set_venc_output(enum omap_dss_venc_type type); | 259 | void dss_set_venc_output(enum omap_dss_venc_type type); |
235 | void dss_set_dac_pwrdn_bgz(bool enable); | 260 | void dss_set_dac_pwrdn_bgz(bool enable); |
@@ -244,11 +269,11 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck, | |||
244 | 269 | ||
245 | /* SDI */ | 270 | /* SDI */ |
246 | #ifdef CONFIG_OMAP2_DSS_SDI | 271 | #ifdef CONFIG_OMAP2_DSS_SDI |
247 | int sdi_init(bool skip_init); | 272 | int sdi_init(void); |
248 | void sdi_exit(void); | 273 | void sdi_exit(void); |
249 | int sdi_init_display(struct omap_dss_device *display); | 274 | int sdi_init_display(struct omap_dss_device *display); |
250 | #else | 275 | #else |
251 | static inline int sdi_init(bool skip_init) | 276 | static inline int sdi_init(void) |
252 | { | 277 | { |
253 | return 0; | 278 | return 0; |
254 | } | 279 | } |
@@ -259,8 +284,8 @@ static inline void sdi_exit(void) | |||
259 | 284 | ||
260 | /* DSI */ | 285 | /* DSI */ |
261 | #ifdef CONFIG_OMAP2_DSS_DSI | 286 | #ifdef CONFIG_OMAP2_DSS_DSI |
262 | int dsi_init(struct platform_device *pdev); | 287 | int dsi_init_platform_driver(void); |
263 | void dsi_exit(void); | 288 | void dsi_uninit_platform_driver(void); |
264 | 289 | ||
265 | void dsi_dump_clocks(struct seq_file *s); | 290 | void dsi_dump_clocks(struct seq_file *s); |
266 | void dsi_dump_irqs(struct seq_file *s); | 291 | void dsi_dump_irqs(struct seq_file *s); |
@@ -271,7 +296,7 @@ void dsi_restore_context(void); | |||
271 | 296 | ||
272 | int dsi_init_display(struct omap_dss_device *display); | 297 | int dsi_init_display(struct omap_dss_device *display); |
273 | void dsi_irq_handler(void); | 298 | void dsi_irq_handler(void); |
274 | unsigned long dsi_get_dsi1_pll_rate(void); | 299 | unsigned long dsi_get_pll_hsdiv_dispc_rate(void); |
275 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); | 300 | int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo); |
276 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, | 301 | int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck, |
277 | struct dsi_clock_info *cinfo, | 302 | struct dsi_clock_info *cinfo, |
@@ -282,31 +307,36 @@ void dsi_pll_uninit(void); | |||
282 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, | 307 | void dsi_get_overlay_fifo_thresholds(enum omap_plane plane, |
283 | u32 fifo_size, enum omap_burst_size *burst_size, | 308 | u32 fifo_size, enum omap_burst_size *burst_size, |
284 | u32 *fifo_low, u32 *fifo_high); | 309 | u32 *fifo_low, u32 *fifo_high); |
285 | void dsi_wait_dsi1_pll_active(void); | 310 | void dsi_wait_pll_hsdiv_dispc_active(void); |
286 | void dsi_wait_dsi2_pll_active(void); | 311 | void dsi_wait_pll_hsdiv_dsi_active(void); |
287 | #else | 312 | #else |
288 | static inline int dsi_init(struct platform_device *pdev) | 313 | static inline int dsi_init_platform_driver(void) |
289 | { | 314 | { |
290 | return 0; | 315 | return 0; |
291 | } | 316 | } |
292 | static inline void dsi_exit(void) | 317 | static inline void dsi_uninit_platform_driver(void) |
293 | { | 318 | { |
294 | } | 319 | } |
295 | static inline void dsi_wait_dsi1_pll_active(void) | 320 | static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void) |
296 | { | 321 | { |
322 | WARN("%s: DSI not compiled in, returning rate as 0\n", __func__); | ||
323 | return 0; | ||
297 | } | 324 | } |
298 | static inline void dsi_wait_dsi2_pll_active(void) | 325 | static inline void dsi_wait_pll_hsdiv_dispc_active(void) |
326 | { | ||
327 | } | ||
328 | static inline void dsi_wait_pll_hsdiv_dsi_active(void) | ||
299 | { | 329 | { |
300 | } | 330 | } |
301 | #endif | 331 | #endif |
302 | 332 | ||
303 | /* DPI */ | 333 | /* DPI */ |
304 | #ifdef CONFIG_OMAP2_DSS_DPI | 334 | #ifdef CONFIG_OMAP2_DSS_DPI |
305 | int dpi_init(struct platform_device *pdev); | 335 | int dpi_init(void); |
306 | void dpi_exit(void); | 336 | void dpi_exit(void); |
307 | int dpi_init_display(struct omap_dss_device *dssdev); | 337 | int dpi_init_display(struct omap_dss_device *dssdev); |
308 | #else | 338 | #else |
309 | static inline int dpi_init(struct platform_device *pdev) | 339 | static inline int dpi_init(void) |
310 | { | 340 | { |
311 | return 0; | 341 | return 0; |
312 | } | 342 | } |
@@ -316,8 +346,8 @@ static inline void dpi_exit(void) | |||
316 | #endif | 346 | #endif |
317 | 347 | ||
318 | /* DISPC */ | 348 | /* DISPC */ |
319 | int dispc_init(void); | 349 | int dispc_init_platform_driver(void); |
320 | void dispc_exit(void); | 350 | void dispc_uninit_platform_driver(void); |
321 | void dispc_dump_clocks(struct seq_file *s); | 351 | void dispc_dump_clocks(struct seq_file *s); |
322 | void dispc_dump_irqs(struct seq_file *s); | 352 | void dispc_dump_irqs(struct seq_file *s); |
323 | void dispc_dump_regs(struct seq_file *s); | 353 | void dispc_dump_regs(struct seq_file *s); |
@@ -350,6 +380,7 @@ void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height); | |||
350 | void dispc_set_channel_out(enum omap_plane plane, | 380 | void dispc_set_channel_out(enum omap_plane plane, |
351 | enum omap_channel channel_out); | 381 | enum omap_channel channel_out); |
352 | 382 | ||
383 | void dispc_enable_gamma_table(bool enable); | ||
353 | int dispc_setup_plane(enum omap_plane plane, | 384 | int dispc_setup_plane(enum omap_plane plane, |
354 | u32 paddr, u16 screen_width, | 385 | u32 paddr, u16 screen_width, |
355 | u16 pos_x, u16 pos_y, | 386 | u16 pos_x, u16 pos_y, |
@@ -409,24 +440,50 @@ int dispc_get_clock_div(enum omap_channel channel, | |||
409 | 440 | ||
410 | /* VENC */ | 441 | /* VENC */ |
411 | #ifdef CONFIG_OMAP2_DSS_VENC | 442 | #ifdef CONFIG_OMAP2_DSS_VENC |
412 | int venc_init(struct platform_device *pdev); | 443 | int venc_init_platform_driver(void); |
413 | void venc_exit(void); | 444 | void venc_uninit_platform_driver(void); |
414 | void venc_dump_regs(struct seq_file *s); | 445 | void venc_dump_regs(struct seq_file *s); |
415 | int venc_init_display(struct omap_dss_device *display); | 446 | int venc_init_display(struct omap_dss_device *display); |
416 | #else | 447 | #else |
417 | static inline int venc_init(struct platform_device *pdev) | 448 | static inline int venc_init_platform_driver(void) |
449 | { | ||
450 | return 0; | ||
451 | } | ||
452 | static inline void venc_uninit_platform_driver(void) | ||
453 | { | ||
454 | } | ||
455 | #endif | ||
456 | |||
457 | /* HDMI */ | ||
458 | #ifdef CONFIG_OMAP4_DSS_HDMI | ||
459 | int hdmi_init_platform_driver(void); | ||
460 | void hdmi_uninit_platform_driver(void); | ||
461 | int hdmi_init_display(struct omap_dss_device *dssdev); | ||
462 | #else | ||
463 | static inline int hdmi_init_display(struct omap_dss_device *dssdev) | ||
464 | { | ||
465 | return 0; | ||
466 | } | ||
467 | static inline int hdmi_init_platform_driver(void) | ||
418 | { | 468 | { |
419 | return 0; | 469 | return 0; |
420 | } | 470 | } |
421 | static inline void venc_exit(void) | 471 | static inline void hdmi_uninit_platform_driver(void) |
422 | { | 472 | { |
423 | } | 473 | } |
424 | #endif | 474 | #endif |
475 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev); | ||
476 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev); | ||
477 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev); | ||
478 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
479 | struct omap_video_timings *timings); | ||
480 | int hdmi_panel_init(void); | ||
481 | void hdmi_panel_exit(void); | ||
425 | 482 | ||
426 | /* RFBI */ | 483 | /* RFBI */ |
427 | #ifdef CONFIG_OMAP2_DSS_RFBI | 484 | #ifdef CONFIG_OMAP2_DSS_RFBI |
428 | int rfbi_init(void); | 485 | int rfbi_init_platform_driver(void); |
429 | void rfbi_exit(void); | 486 | void rfbi_uninit_platform_driver(void); |
430 | void rfbi_dump_regs(struct seq_file *s); | 487 | void rfbi_dump_regs(struct seq_file *s); |
431 | 488 | ||
432 | int rfbi_configure(int rfbi_module, int bpp, int lines); | 489 | int rfbi_configure(int rfbi_module, int bpp, int lines); |
@@ -437,11 +494,11 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t); | |||
437 | unsigned long rfbi_get_max_tx_rate(void); | 494 | unsigned long rfbi_get_max_tx_rate(void); |
438 | int rfbi_init_display(struct omap_dss_device *display); | 495 | int rfbi_init_display(struct omap_dss_device *display); |
439 | #else | 496 | #else |
440 | static inline int rfbi_init(void) | 497 | static inline int rfbi_init_platform_driver(void) |
441 | { | 498 | { |
442 | return 0; | 499 | return 0; |
443 | } | 500 | } |
444 | static inline void rfbi_exit(void) | 501 | static inline void rfbi_uninit_platform_driver(void) |
445 | { | 502 | { |
446 | } | 503 | } |
447 | #endif | 504 | #endif |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index cf3ef696e141..aa1622241d0d 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -25,14 +25,18 @@ | |||
25 | #include <plat/display.h> | 25 | #include <plat/display.h> |
26 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
27 | 27 | ||
28 | #include "dss.h" | ||
28 | #include "dss_features.h" | 29 | #include "dss_features.h" |
29 | 30 | ||
30 | /* Defines a generic omap register field */ | 31 | /* Defines a generic omap register field */ |
31 | struct dss_reg_field { | 32 | struct dss_reg_field { |
32 | enum dss_feat_reg_field id; | ||
33 | u8 start, end; | 33 | u8 start, end; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct dss_param_range { | ||
37 | int min, max; | ||
38 | }; | ||
39 | |||
36 | struct omap_dss_features { | 40 | struct omap_dss_features { |
37 | const struct dss_reg_field *reg_fields; | 41 | const struct dss_reg_field *reg_fields; |
38 | const int num_reg_fields; | 42 | const int num_reg_fields; |
@@ -43,29 +47,68 @@ struct omap_dss_features { | |||
43 | const int num_ovls; | 47 | const int num_ovls; |
44 | const enum omap_display_type *supported_displays; | 48 | const enum omap_display_type *supported_displays; |
45 | const enum omap_color_mode *supported_color_modes; | 49 | const enum omap_color_mode *supported_color_modes; |
50 | const char * const *clksrc_names; | ||
51 | const struct dss_param_range *dss_params; | ||
46 | }; | 52 | }; |
47 | 53 | ||
48 | /* This struct is assigned to one of the below during initialization */ | 54 | /* This struct is assigned to one of the below during initialization */ |
49 | static struct omap_dss_features *omap_current_dss_features; | 55 | static struct omap_dss_features *omap_current_dss_features; |
50 | 56 | ||
51 | static const struct dss_reg_field omap2_dss_reg_fields[] = { | 57 | static const struct dss_reg_field omap2_dss_reg_fields[] = { |
52 | { FEAT_REG_FIRHINC, 11, 0 }, | 58 | [FEAT_REG_FIRHINC] = { 11, 0 }, |
53 | { FEAT_REG_FIRVINC, 27, 16 }, | 59 | [FEAT_REG_FIRVINC] = { 27, 16 }, |
54 | { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 }, | 60 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 8, 0 }, |
55 | { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 }, | 61 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 24, 16 }, |
56 | { FEAT_REG_FIFOSIZE, 8, 0 }, | 62 | [FEAT_REG_FIFOSIZE] = { 8, 0 }, |
63 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
64 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
65 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
66 | [FEAT_REG_DSIPLL_REGN] = { 0, 0 }, | ||
67 | [FEAT_REG_DSIPLL_REGM] = { 0, 0 }, | ||
68 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
69 | [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
57 | }; | 70 | }; |
58 | 71 | ||
59 | static const struct dss_reg_field omap3_dss_reg_fields[] = { | 72 | static const struct dss_reg_field omap3_dss_reg_fields[] = { |
60 | { FEAT_REG_FIRHINC, 12, 0 }, | 73 | [FEAT_REG_FIRHINC] = { 12, 0 }, |
61 | { FEAT_REG_FIRVINC, 28, 16 }, | 74 | [FEAT_REG_FIRVINC] = { 28, 16 }, |
62 | { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 }, | 75 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 11, 0 }, |
63 | { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 }, | 76 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 27, 16 }, |
64 | { FEAT_REG_FIFOSIZE, 10, 0 }, | 77 | [FEAT_REG_FIFOSIZE] = { 10, 0 }, |
78 | [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, | ||
79 | [FEAT_REG_VERTICALACCU] = { 25, 16 }, | ||
80 | [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, | ||
81 | [FEAT_REG_DSIPLL_REGN] = { 7, 1 }, | ||
82 | [FEAT_REG_DSIPLL_REGM] = { 18, 8 }, | ||
83 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 }, | ||
84 | [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 }, | ||
85 | }; | ||
86 | |||
87 | static const struct dss_reg_field omap4_dss_reg_fields[] = { | ||
88 | [FEAT_REG_FIRHINC] = { 12, 0 }, | ||
89 | [FEAT_REG_FIRVINC] = { 28, 16 }, | ||
90 | [FEAT_REG_FIFOLOWTHRESHOLD] = { 15, 0 }, | ||
91 | [FEAT_REG_FIFOHIGHTHRESHOLD] = { 31, 16 }, | ||
92 | [FEAT_REG_FIFOSIZE] = { 15, 0 }, | ||
93 | [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, | ||
94 | [FEAT_REG_VERTICALACCU] = { 26, 16 }, | ||
95 | [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, | ||
96 | [FEAT_REG_DSIPLL_REGN] = { 8, 1 }, | ||
97 | [FEAT_REG_DSIPLL_REGM] = { 20, 9 }, | ||
98 | [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 }, | ||
99 | [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 }, | ||
65 | }; | 100 | }; |
66 | 101 | ||
67 | static const enum omap_display_type omap2_dss_supported_displays[] = { | 102 | static const enum omap_display_type omap2_dss_supported_displays[] = { |
68 | /* OMAP_DSS_CHANNEL_LCD */ | 103 | /* OMAP_DSS_CHANNEL_LCD */ |
104 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI, | ||
105 | |||
106 | /* OMAP_DSS_CHANNEL_DIGIT */ | ||
107 | OMAP_DISPLAY_TYPE_VENC, | ||
108 | }; | ||
109 | |||
110 | static const enum omap_display_type omap3430_dss_supported_displays[] = { | ||
111 | /* OMAP_DSS_CHANNEL_LCD */ | ||
69 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 112 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
70 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, | 113 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, |
71 | 114 | ||
@@ -73,10 +116,10 @@ static const enum omap_display_type omap2_dss_supported_displays[] = { | |||
73 | OMAP_DISPLAY_TYPE_VENC, | 116 | OMAP_DISPLAY_TYPE_VENC, |
74 | }; | 117 | }; |
75 | 118 | ||
76 | static const enum omap_display_type omap3_dss_supported_displays[] = { | 119 | static const enum omap_display_type omap3630_dss_supported_displays[] = { |
77 | /* OMAP_DSS_CHANNEL_LCD */ | 120 | /* OMAP_DSS_CHANNEL_LCD */ |
78 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 121 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
79 | OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI, | 122 | OMAP_DISPLAY_TYPE_DSI, |
80 | 123 | ||
81 | /* OMAP_DSS_CHANNEL_DIGIT */ | 124 | /* OMAP_DSS_CHANNEL_DIGIT */ |
82 | OMAP_DISPLAY_TYPE_VENC, | 125 | OMAP_DISPLAY_TYPE_VENC, |
@@ -87,7 +130,7 @@ static const enum omap_display_type omap4_dss_supported_displays[] = { | |||
87 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, | 130 | OMAP_DISPLAY_TYPE_DBI | OMAP_DISPLAY_TYPE_DSI, |
88 | 131 | ||
89 | /* OMAP_DSS_CHANNEL_DIGIT */ | 132 | /* OMAP_DSS_CHANNEL_DIGIT */ |
90 | OMAP_DISPLAY_TYPE_VENC, | 133 | OMAP_DISPLAY_TYPE_VENC | OMAP_DISPLAY_TYPE_HDMI, |
91 | 134 | ||
92 | /* OMAP_DSS_CHANNEL_LCD2 */ | 135 | /* OMAP_DSS_CHANNEL_LCD2 */ |
93 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | | 136 | OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI | |
@@ -134,6 +177,54 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = { | |||
134 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, | 177 | OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32, |
135 | }; | 178 | }; |
136 | 179 | ||
180 | static const char * const omap2_dss_clk_source_names[] = { | ||
181 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A", | ||
182 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A", | ||
183 | [DSS_CLK_SRC_FCK] = "DSS_FCLK1", | ||
184 | }; | ||
185 | |||
186 | static const char * const omap3_dss_clk_source_names[] = { | ||
187 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK", | ||
188 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK", | ||
189 | [DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK", | ||
190 | }; | ||
191 | |||
192 | static const char * const omap4_dss_clk_source_names[] = { | ||
193 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1", | ||
194 | [DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2", | ||
195 | [DSS_CLK_SRC_FCK] = "DSS_FCLK", | ||
196 | }; | ||
197 | |||
198 | static const struct dss_param_range omap2_dss_param_range[] = { | ||
199 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
200 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | ||
201 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | ||
202 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 }, | ||
203 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 }, | ||
204 | [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, | ||
205 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, | ||
206 | }; | ||
207 | |||
208 | static const struct dss_param_range omap3_dss_param_range[] = { | ||
209 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | ||
210 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 }, | ||
211 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 }, | ||
212 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 }, | ||
213 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 }, | ||
214 | [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, | ||
215 | [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, | ||
216 | }; | ||
217 | |||
218 | static const struct dss_param_range omap4_dss_param_range[] = { | ||
219 | [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, | ||
220 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | ||
221 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | ||
222 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | ||
223 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | ||
224 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | ||
225 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | ||
226 | }; | ||
227 | |||
137 | /* OMAP2 DSS Features */ | 228 | /* OMAP2 DSS Features */ |
138 | static struct omap_dss_features omap2_dss_features = { | 229 | static struct omap_dss_features omap2_dss_features = { |
139 | .reg_fields = omap2_dss_reg_fields, | 230 | .reg_fields = omap2_dss_reg_fields, |
@@ -141,12 +232,15 @@ static struct omap_dss_features omap2_dss_features = { | |||
141 | 232 | ||
142 | .has_feature = | 233 | .has_feature = |
143 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | | 234 | FEAT_LCDENABLEPOL | FEAT_LCDENABLESIGNAL | |
144 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED, | 235 | FEAT_PCKFREEENABLE | FEAT_FUNCGATED | |
236 | FEAT_ROWREPEATENABLE | FEAT_RESIZECONF, | ||
145 | 237 | ||
146 | .num_mgrs = 2, | 238 | .num_mgrs = 2, |
147 | .num_ovls = 3, | 239 | .num_ovls = 3, |
148 | .supported_displays = omap2_dss_supported_displays, | 240 | .supported_displays = omap2_dss_supported_displays, |
149 | .supported_color_modes = omap2_dss_supported_color_modes, | 241 | .supported_color_modes = omap2_dss_supported_color_modes, |
242 | .clksrc_names = omap2_dss_clk_source_names, | ||
243 | .dss_params = omap2_dss_param_range, | ||
150 | }; | 244 | }; |
151 | 245 | ||
152 | /* OMAP3 DSS Features */ | 246 | /* OMAP3 DSS Features */ |
@@ -157,12 +251,15 @@ static struct omap_dss_features omap3430_dss_features = { | |||
157 | .has_feature = | 251 | .has_feature = |
158 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 252 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | |
159 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 253 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
160 | FEAT_FUNCGATED, | 254 | FEAT_FUNCGATED | FEAT_ROWREPEATENABLE | |
255 | FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF, | ||
161 | 256 | ||
162 | .num_mgrs = 2, | 257 | .num_mgrs = 2, |
163 | .num_ovls = 3, | 258 | .num_ovls = 3, |
164 | .supported_displays = omap3_dss_supported_displays, | 259 | .supported_displays = omap3430_dss_supported_displays, |
165 | .supported_color_modes = omap3_dss_supported_color_modes, | 260 | .supported_color_modes = omap3_dss_supported_color_modes, |
261 | .clksrc_names = omap3_dss_clk_source_names, | ||
262 | .dss_params = omap3_dss_param_range, | ||
166 | }; | 263 | }; |
167 | 264 | ||
168 | static struct omap_dss_features omap3630_dss_features = { | 265 | static struct omap_dss_features omap3630_dss_features = { |
@@ -172,27 +269,34 @@ static struct omap_dss_features omap3630_dss_features = { | |||
172 | .has_feature = | 269 | .has_feature = |
173 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | | 270 | FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL | |
174 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | | 271 | FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE | |
175 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED, | 272 | FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED | |
273 | FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT | | ||
274 | FEAT_RESIZECONF, | ||
176 | 275 | ||
177 | .num_mgrs = 2, | 276 | .num_mgrs = 2, |
178 | .num_ovls = 3, | 277 | .num_ovls = 3, |
179 | .supported_displays = omap3_dss_supported_displays, | 278 | .supported_displays = omap3630_dss_supported_displays, |
180 | .supported_color_modes = omap3_dss_supported_color_modes, | 279 | .supported_color_modes = omap3_dss_supported_color_modes, |
280 | .clksrc_names = omap3_dss_clk_source_names, | ||
281 | .dss_params = omap3_dss_param_range, | ||
181 | }; | 282 | }; |
182 | 283 | ||
183 | /* OMAP4 DSS Features */ | 284 | /* OMAP4 DSS Features */ |
184 | static struct omap_dss_features omap4_dss_features = { | 285 | static struct omap_dss_features omap4_dss_features = { |
185 | .reg_fields = omap3_dss_reg_fields, | 286 | .reg_fields = omap4_dss_reg_fields, |
186 | .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields), | 287 | .num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields), |
187 | 288 | ||
188 | .has_feature = | 289 | .has_feature = |
189 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | | 290 | FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA | |
190 | FEAT_MGR_LCD2, | 291 | FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 | |
292 | FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC, | ||
191 | 293 | ||
192 | .num_mgrs = 3, | 294 | .num_mgrs = 3, |
193 | .num_ovls = 3, | 295 | .num_ovls = 3, |
194 | .supported_displays = omap4_dss_supported_displays, | 296 | .supported_displays = omap4_dss_supported_displays, |
195 | .supported_color_modes = omap3_dss_supported_color_modes, | 297 | .supported_color_modes = omap3_dss_supported_color_modes, |
298 | .clksrc_names = omap4_dss_clk_source_names, | ||
299 | .dss_params = omap4_dss_param_range, | ||
196 | }; | 300 | }; |
197 | 301 | ||
198 | /* Functions returning values related to a DSS feature */ | 302 | /* Functions returning values related to a DSS feature */ |
@@ -206,6 +310,16 @@ int dss_feat_get_num_ovls(void) | |||
206 | return omap_current_dss_features->num_ovls; | 310 | return omap_current_dss_features->num_ovls; |
207 | } | 311 | } |
208 | 312 | ||
313 | unsigned long dss_feat_get_param_min(enum dss_range_param param) | ||
314 | { | ||
315 | return omap_current_dss_features->dss_params[param].min; | ||
316 | } | ||
317 | |||
318 | unsigned long dss_feat_get_param_max(enum dss_range_param param) | ||
319 | { | ||
320 | return omap_current_dss_features->dss_params[param].max; | ||
321 | } | ||
322 | |||
209 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) | 323 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel) |
210 | { | 324 | { |
211 | return omap_current_dss_features->supported_displays[channel]; | 325 | return omap_current_dss_features->supported_displays[channel]; |
@@ -223,6 +337,11 @@ bool dss_feat_color_mode_supported(enum omap_plane plane, | |||
223 | color_mode; | 337 | color_mode; |
224 | } | 338 | } |
225 | 339 | ||
340 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id) | ||
341 | { | ||
342 | return omap_current_dss_features->clksrc_names[id]; | ||
343 | } | ||
344 | |||
226 | /* DSS has_feature check */ | 345 | /* DSS has_feature check */ |
227 | bool dss_has_feature(enum dss_feat_id id) | 346 | bool dss_has_feature(enum dss_feat_id id) |
228 | { | 347 | { |
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h index b9c70be92588..12e9c4ef0dec 100644 --- a/drivers/video/omap2/dss/dss_features.h +++ b/drivers/video/omap2/dss/dss_features.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #define MAX_DSS_MANAGERS 3 | 23 | #define MAX_DSS_MANAGERS 3 |
24 | #define MAX_DSS_OVERLAYS 3 | 24 | #define MAX_DSS_OVERLAYS 3 |
25 | #define MAX_DSS_LCD_MANAGERS 2 | ||
25 | 26 | ||
26 | /* DSS has feature id */ | 27 | /* DSS has feature id */ |
27 | enum dss_feat_id { | 28 | enum dss_feat_id { |
@@ -33,6 +34,12 @@ enum dss_feat_id { | |||
33 | FEAT_PCKFREEENABLE = 1 << 5, | 34 | FEAT_PCKFREEENABLE = 1 << 5, |
34 | FEAT_FUNCGATED = 1 << 6, | 35 | FEAT_FUNCGATED = 1 << 6, |
35 | FEAT_MGR_LCD2 = 1 << 7, | 36 | FEAT_MGR_LCD2 = 1 << 7, |
37 | FEAT_LINEBUFFERSPLIT = 1 << 8, | ||
38 | FEAT_ROWREPEATENABLE = 1 << 9, | ||
39 | FEAT_RESIZECONF = 1 << 10, | ||
40 | /* Independent core clk divider */ | ||
41 | FEAT_CORE_CLK_DIV = 1 << 11, | ||
42 | FEAT_LCD_CLK_SRC = 1 << 12, | ||
36 | }; | 43 | }; |
37 | 44 | ||
38 | /* DSS register field id */ | 45 | /* DSS register field id */ |
@@ -42,15 +49,35 @@ enum dss_feat_reg_field { | |||
42 | FEAT_REG_FIFOHIGHTHRESHOLD, | 49 | FEAT_REG_FIFOHIGHTHRESHOLD, |
43 | FEAT_REG_FIFOLOWTHRESHOLD, | 50 | FEAT_REG_FIFOLOWTHRESHOLD, |
44 | FEAT_REG_FIFOSIZE, | 51 | FEAT_REG_FIFOSIZE, |
52 | FEAT_REG_HORIZONTALACCU, | ||
53 | FEAT_REG_VERTICALACCU, | ||
54 | FEAT_REG_DISPC_CLK_SWITCH, | ||
55 | FEAT_REG_DSIPLL_REGN, | ||
56 | FEAT_REG_DSIPLL_REGM, | ||
57 | FEAT_REG_DSIPLL_REGM_DISPC, | ||
58 | FEAT_REG_DSIPLL_REGM_DSI, | ||
59 | }; | ||
60 | |||
61 | enum dss_range_param { | ||
62 | FEAT_PARAM_DSS_FCK, | ||
63 | FEAT_PARAM_DSIPLL_REGN, | ||
64 | FEAT_PARAM_DSIPLL_REGM, | ||
65 | FEAT_PARAM_DSIPLL_REGM_DISPC, | ||
66 | FEAT_PARAM_DSIPLL_REGM_DSI, | ||
67 | FEAT_PARAM_DSIPLL_FINT, | ||
68 | FEAT_PARAM_DSIPLL_LPDIV, | ||
45 | }; | 69 | }; |
46 | 70 | ||
47 | /* DSS Feature Functions */ | 71 | /* DSS Feature Functions */ |
48 | int dss_feat_get_num_mgrs(void); | 72 | int dss_feat_get_num_mgrs(void); |
49 | int dss_feat_get_num_ovls(void); | 73 | int dss_feat_get_num_ovls(void); |
74 | unsigned long dss_feat_get_param_min(enum dss_range_param param); | ||
75 | unsigned long dss_feat_get_param_max(enum dss_range_param param); | ||
50 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); | 76 | enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); |
51 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); | 77 | enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); |
52 | bool dss_feat_color_mode_supported(enum omap_plane plane, | 78 | bool dss_feat_color_mode_supported(enum omap_plane plane, |
53 | enum omap_color_mode color_mode); | 79 | enum omap_color_mode color_mode); |
80 | const char *dss_feat_get_clk_source_name(enum dss_clk_source id); | ||
54 | 81 | ||
55 | bool dss_has_feature(enum dss_feat_id id); | 82 | bool dss_has_feature(enum dss_feat_id id); |
56 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); | 83 | void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end); |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c new file mode 100644 index 000000000000..0d44f070ef36 --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -0,0 +1,1332 @@ | |||
1 | /* | ||
2 | * hdmi.c | ||
3 | * | ||
4 | * HDMI interface DSS driver setting for TI's OMAP4 family of processor. | ||
5 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * Authors: Yong Zhi | ||
7 | * Mythri pk <mythripk@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #define DSS_SUBSYS_NAME "HDMI" | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/mutex.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <plat/display.h> | ||
33 | |||
34 | #include "dss.h" | ||
35 | #include "hdmi.h" | ||
36 | |||
37 | static struct { | ||
38 | struct mutex lock; | ||
39 | struct omap_display_platform_data *pdata; | ||
40 | struct platform_device *pdev; | ||
41 | void __iomem *base_wp; /* HDMI wrapper */ | ||
42 | int code; | ||
43 | int mode; | ||
44 | u8 edid[HDMI_EDID_MAX_LENGTH]; | ||
45 | u8 edid_set; | ||
46 | bool custom_set; | ||
47 | struct hdmi_config cfg; | ||
48 | } hdmi; | ||
49 | |||
50 | /* | ||
51 | * Logic for the below structure : | ||
52 | * user enters the CEA or VESA timings by specifying the HDMI/DVI code. | ||
53 | * There is a correspondence between CEA/VESA timing and code, please | ||
54 | * refer to section 6.3 in HDMI 1.3 specification for timing code. | ||
55 | * | ||
56 | * In the below structure, cea_vesa_timings corresponds to all OMAP4 | ||
57 | * supported CEA and VESA timing values.code_cea corresponds to the CEA | ||
58 | * code, It is used to get the timing from cea_vesa_timing array.Similarly | ||
59 | * with code_vesa. Code_index is used for back mapping, that is once EDID | ||
60 | * is read from the TV, EDID is parsed to find the timing values and then | ||
61 | * map it to corresponding CEA or VESA index. | ||
62 | */ | ||
63 | |||
64 | static const struct hdmi_timings cea_vesa_timings[OMAP_HDMI_TIMINGS_NB] = { | ||
65 | { {640, 480, 25200, 96, 16, 48, 2, 10, 33} , 0 , 0}, | ||
66 | { {1280, 720, 74250, 40, 440, 220, 5, 5, 20}, 1, 1}, | ||
67 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1}, | ||
68 | { {720, 480, 27027, 62, 16, 60, 6, 9, 30}, 0, 0}, | ||
69 | { {2880, 576, 108000, 256, 48, 272, 5, 5, 39}, 0, 0}, | ||
70 | { {1440, 240, 27027, 124, 38, 114, 3, 4, 15}, 0, 0}, | ||
71 | { {1440, 288, 27000, 126, 24, 138, 3, 2, 19}, 0, 0}, | ||
72 | { {1920, 540, 74250, 44, 528, 148, 5, 2, 15}, 1, 1}, | ||
73 | { {1920, 540, 74250, 44, 88, 148, 5, 2, 15}, 1, 1}, | ||
74 | { {1920, 1080, 148500, 44, 88, 148, 5, 4, 36}, 1, 1}, | ||
75 | { {720, 576, 27000, 64, 12, 68, 5, 5, 39}, 0, 0}, | ||
76 | { {1440, 576, 54000, 128, 24, 136, 5, 5, 39}, 0, 0}, | ||
77 | { {1920, 1080, 148500, 44, 528, 148, 5, 4, 36}, 1, 1}, | ||
78 | { {2880, 480, 108108, 248, 64, 240, 6, 9, 30}, 0, 0}, | ||
79 | { {1920, 1080, 74250, 44, 638, 148, 5, 4, 36}, 1, 1}, | ||
80 | /* VESA From Here */ | ||
81 | { {640, 480, 25175, 96, 16, 48, 2 , 11, 31}, 0, 0}, | ||
82 | { {800, 600, 40000, 128, 40, 88, 4 , 1, 23}, 1, 1}, | ||
83 | { {848, 480, 33750, 112, 16, 112, 8 , 6, 23}, 1, 1}, | ||
84 | { {1280, 768, 79500, 128, 64, 192, 7 , 3, 20}, 1, 0}, | ||
85 | { {1280, 800, 83500, 128, 72, 200, 6 , 3, 22}, 1, 0}, | ||
86 | { {1360, 768, 85500, 112, 64, 256, 6 , 3, 18}, 1, 1}, | ||
87 | { {1280, 960, 108000, 112, 96, 312, 3 , 1, 36}, 1, 1}, | ||
88 | { {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38}, 1, 1}, | ||
89 | { {1024, 768, 65000, 136, 24, 160, 6, 3, 29}, 0, 0}, | ||
90 | { {1400, 1050, 121750, 144, 88, 232, 4, 3, 32}, 1, 0}, | ||
91 | { {1440, 900, 106500, 152, 80, 232, 6, 3, 25}, 1, 0}, | ||
92 | { {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30}, 1, 0}, | ||
93 | { {1366, 768, 85500, 143, 70, 213, 3, 3, 24}, 1, 1}, | ||
94 | { {1920, 1080, 148500, 44, 148, 80, 5, 4, 36}, 1, 1}, | ||
95 | { {1280, 768, 68250, 32, 48, 80, 7, 3, 12}, 0, 1}, | ||
96 | { {1400, 1050, 101000, 32, 48, 80, 4, 3, 23}, 0, 1}, | ||
97 | { {1680, 1050, 119000, 32, 48, 80, 6, 3, 21}, 0, 1}, | ||
98 | { {1280, 800, 79500, 32, 48, 80, 6, 3, 14}, 0, 1}, | ||
99 | { {1280, 720, 74250, 40, 110, 220, 5, 5, 20}, 1, 1} | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * This is a static mapping array which maps the timing values | ||
104 | * with corresponding CEA / VESA code | ||
105 | */ | ||
106 | static const int code_index[OMAP_HDMI_TIMINGS_NB] = { | ||
107 | 1, 19, 4, 2, 37, 6, 21, 20, 5, 16, 17, 29, 31, 35, 32, | ||
108 | /* <--15 CEA 17--> vesa*/ | ||
109 | 4, 9, 0xE, 0x17, 0x1C, 0x27, 0x20, 0x23, 0x10, 0x2A, | ||
110 | 0X2F, 0x3A, 0X51, 0X52, 0x16, 0x29, 0x39, 0x1B | ||
111 | }; | ||
112 | |||
113 | /* | ||
114 | * This is reverse static mapping which maps the CEA / VESA code | ||
115 | * to the corresponding timing values | ||
116 | */ | ||
117 | static const int code_cea[39] = { | ||
118 | -1, 0, 3, 3, 2, 8, 5, 5, -1, -1, | ||
119 | -1, -1, -1, -1, -1, -1, 9, 10, 10, 1, | ||
120 | 7, 6, 6, -1, -1, -1, -1, -1, -1, 11, | ||
121 | 11, 12, 14, -1, -1, 13, 13, 4, 4 | ||
122 | }; | ||
123 | |||
124 | static const int code_vesa[85] = { | ||
125 | -1, -1, -1, -1, 15, -1, -1, -1, -1, 16, | ||
126 | -1, -1, -1, -1, 17, -1, 23, -1, -1, -1, | ||
127 | -1, -1, 29, 18, -1, -1, -1, 32, 19, -1, | ||
128 | -1, -1, 21, -1, -1, 22, -1, -1, -1, 20, | ||
129 | -1, 30, 24, -1, -1, -1, -1, 25, -1, -1, | ||
130 | -1, -1, -1, -1, -1, -1, -1, 31, 26, -1, | ||
131 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
132 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, | ||
133 | -1, 27, 28, -1, 33}; | ||
134 | |||
135 | static const u8 edid_header[8] = {0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0}; | ||
136 | |||
137 | static inline void hdmi_write_reg(const struct hdmi_reg idx, u32 val) | ||
138 | { | ||
139 | __raw_writel(val, hdmi.base_wp + idx.idx); | ||
140 | } | ||
141 | |||
142 | static inline u32 hdmi_read_reg(const struct hdmi_reg idx) | ||
143 | { | ||
144 | return __raw_readl(hdmi.base_wp + idx.idx); | ||
145 | } | ||
146 | |||
147 | static inline int hdmi_wait_for_bit_change(const struct hdmi_reg idx, | ||
148 | int b2, int b1, u32 val) | ||
149 | { | ||
150 | u32 t = 0; | ||
151 | while (val != REG_GET(idx, b2, b1)) { | ||
152 | udelay(1); | ||
153 | if (t++ > 10000) | ||
154 | return !val; | ||
155 | } | ||
156 | return val; | ||
157 | } | ||
158 | |||
159 | int hdmi_init_display(struct omap_dss_device *dssdev) | ||
160 | { | ||
161 | DSSDBG("init_display\n"); | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static int hdmi_pll_init(enum hdmi_clk_refsel refsel, int dcofreq, | ||
167 | struct hdmi_pll_info *fmt, u16 sd) | ||
168 | { | ||
169 | u32 r; | ||
170 | |||
171 | /* PLL start always use manual mode */ | ||
172 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 0, 0); | ||
173 | |||
174 | r = hdmi_read_reg(PLLCTRL_CFG1); | ||
175 | r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */ | ||
176 | r = FLD_MOD(r, fmt->regn, 8, 1); /* CFG1_PLL_REGN */ | ||
177 | |||
178 | hdmi_write_reg(PLLCTRL_CFG1, r); | ||
179 | |||
180 | r = hdmi_read_reg(PLLCTRL_CFG2); | ||
181 | |||
182 | r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */ | ||
183 | r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */ | ||
184 | r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */ | ||
185 | |||
186 | if (dcofreq) { | ||
187 | /* divider programming for frequency beyond 1000Mhz */ | ||
188 | REG_FLD_MOD(PLLCTRL_CFG3, sd, 17, 10); | ||
189 | r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */ | ||
190 | } else { | ||
191 | r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ | ||
192 | } | ||
193 | |||
194 | hdmi_write_reg(PLLCTRL_CFG2, r); | ||
195 | |||
196 | r = hdmi_read_reg(PLLCTRL_CFG4); | ||
197 | r = FLD_MOD(r, fmt->regm2, 24, 18); | ||
198 | r = FLD_MOD(r, fmt->regmf, 17, 0); | ||
199 | |||
200 | hdmi_write_reg(PLLCTRL_CFG4, r); | ||
201 | |||
202 | /* go now */ | ||
203 | REG_FLD_MOD(PLLCTRL_PLL_GO, 0x1, 0, 0); | ||
204 | |||
205 | /* wait for bit change */ | ||
206 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_GO, 0, 0, 1) != 1) { | ||
207 | DSSERR("PLL GO bit not set\n"); | ||
208 | return -ETIMEDOUT; | ||
209 | } | ||
210 | |||
211 | /* Wait till the lock bit is set in PLL status */ | ||
212 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { | ||
213 | DSSWARN("cannot lock PLL\n"); | ||
214 | DSSWARN("CFG1 0x%x\n", | ||
215 | hdmi_read_reg(PLLCTRL_CFG1)); | ||
216 | DSSWARN("CFG2 0x%x\n", | ||
217 | hdmi_read_reg(PLLCTRL_CFG2)); | ||
218 | DSSWARN("CFG4 0x%x\n", | ||
219 | hdmi_read_reg(PLLCTRL_CFG4)); | ||
220 | return -ETIMEDOUT; | ||
221 | } | ||
222 | |||
223 | DSSDBG("PLL locked!\n"); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /* PHY_PWR_CMD */ | ||
229 | static int hdmi_set_phy_pwr(enum hdmi_phy_pwr val) | ||
230 | { | ||
231 | /* Command for power control of HDMI PHY */ | ||
232 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 7, 6); | ||
233 | |||
234 | /* Status of the power control of HDMI PHY */ | ||
235 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 5, 4, val) != val) { | ||
236 | DSSERR("Failed to set PHY power mode to %d\n", val); | ||
237 | return -ETIMEDOUT; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | /* PLL_PWR_CMD */ | ||
244 | static int hdmi_set_pll_pwr(enum hdmi_pll_pwr val) | ||
245 | { | ||
246 | /* Command for power control of HDMI PLL */ | ||
247 | REG_FLD_MOD(HDMI_WP_PWR_CTRL, val, 3, 2); | ||
248 | |||
249 | /* wait till PHY_PWR_STATUS is set */ | ||
250 | if (hdmi_wait_for_bit_change(HDMI_WP_PWR_CTRL, 1, 0, val) != val) { | ||
251 | DSSERR("Failed to set PHY_PWR_STATUS\n"); | ||
252 | return -ETIMEDOUT; | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static int hdmi_pll_reset(void) | ||
259 | { | ||
260 | /* SYSRESET controlled by power FSM */ | ||
261 | REG_FLD_MOD(PLLCTRL_PLL_CONTROL, 0x0, 3, 3); | ||
262 | |||
263 | /* READ 0x0 reset is in progress */ | ||
264 | if (hdmi_wait_for_bit_change(PLLCTRL_PLL_STATUS, 0, 0, 1) != 1) { | ||
265 | DSSERR("Failed to sysreset PLL\n"); | ||
266 | return -ETIMEDOUT; | ||
267 | } | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int hdmi_phy_init(void) | ||
273 | { | ||
274 | u16 r = 0; | ||
275 | |||
276 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON); | ||
277 | if (r) | ||
278 | return r; | ||
279 | |||
280 | r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON); | ||
281 | if (r) | ||
282 | return r; | ||
283 | |||
284 | /* | ||
285 | * Read address 0 in order to get the SCP reset done completed | ||
286 | * Dummy access performed to make sure reset is done | ||
287 | */ | ||
288 | hdmi_read_reg(HDMI_TXPHY_TX_CTRL); | ||
289 | |||
290 | /* | ||
291 | * Write to phy address 0 to configure the clock | ||
292 | * use HFBITCLK write HDMI_TXPHY_TX_CONTROL_FREQOUT field | ||
293 | */ | ||
294 | REG_FLD_MOD(HDMI_TXPHY_TX_CTRL, 0x1, 31, 30); | ||
295 | |||
296 | /* Write to phy address 1 to start HDMI line (TXVALID and TMDSCLKEN) */ | ||
297 | hdmi_write_reg(HDMI_TXPHY_DIGITAL_CTRL, 0xF0000000); | ||
298 | |||
299 | /* Setup max LDO voltage */ | ||
300 | REG_FLD_MOD(HDMI_TXPHY_POWER_CTRL, 0xB, 3, 0); | ||
301 | |||
302 | /* Write to phy address 3 to change the polarity control */ | ||
303 | REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int hdmi_wait_softreset(void) | ||
309 | { | ||
310 | /* reset W1 */ | ||
311 | REG_FLD_MOD(HDMI_WP_SYSCONFIG, 0x1, 0, 0); | ||
312 | |||
313 | /* wait till SOFTRESET == 0 */ | ||
314 | if (hdmi_wait_for_bit_change(HDMI_WP_SYSCONFIG, 0, 0, 0) != 0) { | ||
315 | DSSERR("sysconfig reset failed\n"); | ||
316 | return -ETIMEDOUT; | ||
317 | } | ||
318 | |||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int hdmi_pll_program(struct hdmi_pll_info *fmt) | ||
323 | { | ||
324 | u16 r = 0; | ||
325 | enum hdmi_clk_refsel refsel; | ||
326 | |||
327 | /* wait for wrapper reset */ | ||
328 | r = hdmi_wait_softreset(); | ||
329 | if (r) | ||
330 | return r; | ||
331 | |||
332 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
333 | if (r) | ||
334 | return r; | ||
335 | |||
336 | r = hdmi_set_pll_pwr(HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | ||
337 | if (r) | ||
338 | return r; | ||
339 | |||
340 | r = hdmi_pll_reset(); | ||
341 | if (r) | ||
342 | return r; | ||
343 | |||
344 | refsel = HDMI_REFSEL_SYSCLK; | ||
345 | |||
346 | r = hdmi_pll_init(refsel, fmt->dcofreq, fmt, fmt->regsd); | ||
347 | if (r) | ||
348 | return r; | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static void hdmi_phy_off(void) | ||
354 | { | ||
355 | hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF); | ||
356 | } | ||
357 | |||
358 | static int hdmi_core_ddc_edid(u8 *pedid, int ext) | ||
359 | { | ||
360 | u32 i, j; | ||
361 | char checksum = 0; | ||
362 | u32 offset = 0; | ||
363 | |||
364 | /* Turn on CLK for DDC */ | ||
365 | REG_FLD_MOD(HDMI_CORE_AV_DPD, 0x7, 2, 0); | ||
366 | |||
367 | /* | ||
368 | * SW HACK : Without the Delay DDC(i2c bus) reads 0 values / | ||
369 | * right shifted values( The behavior is not consistent and seen only | ||
370 | * with some TV's) | ||
371 | */ | ||
372 | usleep_range(800, 1000); | ||
373 | |||
374 | if (!ext) { | ||
375 | /* Clk SCL Devices */ | ||
376 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0xA, 3, 0); | ||
377 | |||
378 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
379 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
380 | 4, 4, 0) != 0) { | ||
381 | DSSERR("Failed to program DDC\n"); | ||
382 | return -ETIMEDOUT; | ||
383 | } | ||
384 | |||
385 | /* Clear FIFO */ | ||
386 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x9, 3, 0); | ||
387 | |||
388 | /* HDMI_CORE_DDC_STATUS_IN_PROG */ | ||
389 | if (hdmi_wait_for_bit_change(HDMI_CORE_DDC_STATUS, | ||
390 | 4, 4, 0) != 0) { | ||
391 | DSSERR("Failed to program DDC\n"); | ||
392 | return -ETIMEDOUT; | ||
393 | } | ||
394 | |||
395 | } else { | ||
396 | if (ext % 2 != 0) | ||
397 | offset = 0x80; | ||
398 | } | ||
399 | |||
400 | /* Load Segment Address Register */ | ||
401 | REG_FLD_MOD(HDMI_CORE_DDC_SEGM, ext/2, 7, 0); | ||
402 | |||
403 | /* Load Slave Address Register */ | ||
404 | REG_FLD_MOD(HDMI_CORE_DDC_ADDR, 0xA0 >> 1, 7, 1); | ||
405 | |||
406 | /* Load Offset Address Register */ | ||
407 | REG_FLD_MOD(HDMI_CORE_DDC_OFFSET, offset, 7, 0); | ||
408 | |||
409 | /* Load Byte Count */ | ||
410 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT1, 0x80, 7, 0); | ||
411 | REG_FLD_MOD(HDMI_CORE_DDC_COUNT2, 0x0, 1, 0); | ||
412 | |||
413 | /* Set DDC_CMD */ | ||
414 | if (ext) | ||
415 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x4, 3, 0); | ||
416 | else | ||
417 | REG_FLD_MOD(HDMI_CORE_DDC_CMD, 0x2, 3, 0); | ||
418 | |||
419 | /* HDMI_CORE_DDC_STATUS_BUS_LOW */ | ||
420 | if (REG_GET(HDMI_CORE_DDC_STATUS, 6, 6) == 1) { | ||
421 | DSSWARN("I2C Bus Low?\n"); | ||
422 | return -EIO; | ||
423 | } | ||
424 | /* HDMI_CORE_DDC_STATUS_NO_ACK */ | ||
425 | if (REG_GET(HDMI_CORE_DDC_STATUS, 5, 5) == 1) { | ||
426 | DSSWARN("I2C No Ack\n"); | ||
427 | return -EIO; | ||
428 | } | ||
429 | |||
430 | i = ext * 128; | ||
431 | j = 0; | ||
432 | while (((REG_GET(HDMI_CORE_DDC_STATUS, 4, 4) == 1) || | ||
433 | (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0)) && | ||
434 | j < 128) { | ||
435 | |||
436 | if (REG_GET(HDMI_CORE_DDC_STATUS, 2, 2) == 0) { | ||
437 | /* FIFO not empty */ | ||
438 | pedid[i++] = REG_GET(HDMI_CORE_DDC_DATA, 7, 0); | ||
439 | j++; | ||
440 | } | ||
441 | } | ||
442 | |||
443 | for (j = 0; j < 128; j++) | ||
444 | checksum += pedid[j]; | ||
445 | |||
446 | if (checksum != 0) { | ||
447 | DSSERR("E-EDID checksum failed!!\n"); | ||
448 | return -EIO; | ||
449 | } | ||
450 | |||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static int read_edid(u8 *pedid, u16 max_length) | ||
455 | { | ||
456 | int r = 0, n = 0, i = 0; | ||
457 | int max_ext_blocks = (max_length / 128) - 1; | ||
458 | |||
459 | r = hdmi_core_ddc_edid(pedid, 0); | ||
460 | if (r) { | ||
461 | return r; | ||
462 | } else { | ||
463 | n = pedid[0x7e]; | ||
464 | |||
465 | /* | ||
466 | * README: need to comply with max_length set by the caller. | ||
467 | * Better implementation should be to allocate necessary | ||
468 | * memory to store EDID according to nb_block field found | ||
469 | * in first block | ||
470 | */ | ||
471 | if (n > max_ext_blocks) | ||
472 | n = max_ext_blocks; | ||
473 | |||
474 | for (i = 1; i <= n; i++) { | ||
475 | r = hdmi_core_ddc_edid(pedid, i); | ||
476 | if (r) | ||
477 | return r; | ||
478 | } | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | |||
483 | static int get_timings_index(void) | ||
484 | { | ||
485 | int code; | ||
486 | |||
487 | if (hdmi.mode == 0) | ||
488 | code = code_vesa[hdmi.code]; | ||
489 | else | ||
490 | code = code_cea[hdmi.code]; | ||
491 | |||
492 | if (code == -1) { | ||
493 | /* HDMI code 4 corresponds to 640 * 480 VGA */ | ||
494 | hdmi.code = 4; | ||
495 | /* DVI mode 1 corresponds to HDMI 0 to DVI */ | ||
496 | hdmi.mode = HDMI_DVI; | ||
497 | |||
498 | code = code_vesa[hdmi.code]; | ||
499 | } | ||
500 | return code; | ||
501 | } | ||
502 | |||
503 | static struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing) | ||
504 | { | ||
505 | int i = 0, code = -1, temp_vsync = 0, temp_hsync = 0; | ||
506 | int timing_vsync = 0, timing_hsync = 0; | ||
507 | struct omap_video_timings temp; | ||
508 | struct hdmi_cm cm = {-1}; | ||
509 | DSSDBG("hdmi_get_code\n"); | ||
510 | |||
511 | for (i = 0; i < OMAP_HDMI_TIMINGS_NB; i++) { | ||
512 | temp = cea_vesa_timings[i].timings; | ||
513 | if ((temp.pixel_clock == timing->pixel_clock) && | ||
514 | (temp.x_res == timing->x_res) && | ||
515 | (temp.y_res == timing->y_res)) { | ||
516 | |||
517 | temp_hsync = temp.hfp + temp.hsw + temp.hbp; | ||
518 | timing_hsync = timing->hfp + timing->hsw + timing->hbp; | ||
519 | temp_vsync = temp.vfp + temp.vsw + temp.vbp; | ||
520 | timing_vsync = timing->vfp + timing->vsw + timing->vbp; | ||
521 | |||
522 | DSSDBG("temp_hsync = %d , temp_vsync = %d" | ||
523 | "timing_hsync = %d, timing_vsync = %d\n", | ||
524 | temp_hsync, temp_hsync, | ||
525 | timing_hsync, timing_vsync); | ||
526 | |||
527 | if ((temp_hsync == timing_hsync) && | ||
528 | (temp_vsync == timing_vsync)) { | ||
529 | code = i; | ||
530 | cm.code = code_index[i]; | ||
531 | if (code < 14) | ||
532 | cm.mode = HDMI_HDMI; | ||
533 | else | ||
534 | cm.mode = HDMI_DVI; | ||
535 | DSSDBG("Hdmi_code = %d mode = %d\n", | ||
536 | cm.code, cm.mode); | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return cm; | ||
543 | } | ||
544 | |||
545 | static void get_horz_vert_timing_info(int current_descriptor_addrs, u8 *edid , | ||
546 | struct omap_video_timings *timings) | ||
547 | { | ||
548 | /* X and Y resolution */ | ||
549 | timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4) | | ||
550 | edid[current_descriptor_addrs + 2]); | ||
551 | timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4) | | ||
552 | edid[current_descriptor_addrs + 5]); | ||
553 | |||
554 | timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8) | | ||
555 | edid[current_descriptor_addrs]); | ||
556 | |||
557 | timings->pixel_clock = 10 * timings->pixel_clock; | ||
558 | |||
559 | /* HORIZONTAL FRONT PORCH */ | ||
560 | timings->hfp = edid[current_descriptor_addrs + 8] | | ||
561 | ((edid[current_descriptor_addrs + 11] & 0xc0) << 2); | ||
562 | /* HORIZONTAL SYNC WIDTH */ | ||
563 | timings->hsw = edid[current_descriptor_addrs + 9] | | ||
564 | ((edid[current_descriptor_addrs + 11] & 0x30) << 4); | ||
565 | /* HORIZONTAL BACK PORCH */ | ||
566 | timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8) | | ||
567 | edid[current_descriptor_addrs + 3]) - | ||
568 | (timings->hfp + timings->hsw); | ||
569 | /* VERTICAL FRONT PORCH */ | ||
570 | timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4) | | ||
571 | ((edid[current_descriptor_addrs + 11] & 0x0f) << 2); | ||
572 | /* VERTICAL SYNC WIDTH */ | ||
573 | timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F) | | ||
574 | ((edid[current_descriptor_addrs + 11] & 0x03) << 4); | ||
575 | /* VERTICAL BACK PORCH */ | ||
576 | timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8) | | ||
577 | edid[current_descriptor_addrs + 6]) - | ||
578 | (timings->vfp + timings->vsw); | ||
579 | |||
580 | } | ||
581 | |||
582 | /* Description : This function gets the resolution information from EDID */ | ||
583 | static void get_edid_timing_data(u8 *edid) | ||
584 | { | ||
585 | u8 count; | ||
586 | u16 current_descriptor_addrs; | ||
587 | struct hdmi_cm cm; | ||
588 | struct omap_video_timings edid_timings; | ||
589 | |||
590 | /* seach block 0, there are 4 DTDs arranged in priority order */ | ||
591 | for (count = 0; count < EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR; count++) { | ||
592 | current_descriptor_addrs = | ||
593 | EDID_DESCRIPTOR_BLOCK0_ADDRESS + | ||
594 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
595 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
596 | edid, &edid_timings); | ||
597 | cm = hdmi_get_code(&edid_timings); | ||
598 | DSSDBG("Block0[%d] value matches code = %d , mode = %d\n", | ||
599 | count, cm.code, cm.mode); | ||
600 | if (cm.code == -1) { | ||
601 | continue; | ||
602 | } else { | ||
603 | hdmi.code = cm.code; | ||
604 | hdmi.mode = cm.mode; | ||
605 | DSSDBG("code = %d , mode = %d\n", | ||
606 | hdmi.code, hdmi.mode); | ||
607 | return; | ||
608 | } | ||
609 | } | ||
610 | if (edid[0x7e] != 0x00) { | ||
611 | for (count = 0; count < EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR; | ||
612 | count++) { | ||
613 | current_descriptor_addrs = | ||
614 | EDID_DESCRIPTOR_BLOCK1_ADDRESS + | ||
615 | count * EDID_TIMING_DESCRIPTOR_SIZE; | ||
616 | get_horz_vert_timing_info(current_descriptor_addrs, | ||
617 | edid, &edid_timings); | ||
618 | cm = hdmi_get_code(&edid_timings); | ||
619 | DSSDBG("Block1[%d] value matches code = %d, mode = %d", | ||
620 | count, cm.code, cm.mode); | ||
621 | if (cm.code == -1) { | ||
622 | continue; | ||
623 | } else { | ||
624 | hdmi.code = cm.code; | ||
625 | hdmi.mode = cm.mode; | ||
626 | DSSDBG("code = %d , mode = %d\n", | ||
627 | hdmi.code, hdmi.mode); | ||
628 | return; | ||
629 | } | ||
630 | } | ||
631 | } | ||
632 | |||
633 | DSSINFO("no valid timing found , falling back to VGA\n"); | ||
634 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
635 | hdmi.mode = HDMI_DVI; | ||
636 | } | ||
637 | |||
638 | static void hdmi_read_edid(struct omap_video_timings *dp) | ||
639 | { | ||
640 | int ret = 0, code; | ||
641 | |||
642 | memset(hdmi.edid, 0, HDMI_EDID_MAX_LENGTH); | ||
643 | |||
644 | if (!hdmi.edid_set) | ||
645 | ret = read_edid(hdmi.edid, HDMI_EDID_MAX_LENGTH); | ||
646 | |||
647 | if (!ret) { | ||
648 | if (!memcmp(hdmi.edid, edid_header, sizeof(edid_header))) { | ||
649 | /* search for timings of default resolution */ | ||
650 | get_edid_timing_data(hdmi.edid); | ||
651 | hdmi.edid_set = true; | ||
652 | } | ||
653 | } else { | ||
654 | DSSWARN("failed to read E-EDID\n"); | ||
655 | } | ||
656 | |||
657 | if (!hdmi.edid_set) { | ||
658 | DSSINFO("fallback to VGA\n"); | ||
659 | hdmi.code = 4; /* setting default value of 640 480 VGA */ | ||
660 | hdmi.mode = HDMI_DVI; | ||
661 | } | ||
662 | |||
663 | code = get_timings_index(); | ||
664 | |||
665 | *dp = cea_vesa_timings[code].timings; | ||
666 | } | ||
667 | |||
668 | static void hdmi_core_init(struct hdmi_core_video_config *video_cfg, | ||
669 | struct hdmi_core_infoframe_avi *avi_cfg, | ||
670 | struct hdmi_core_packet_enable_repeat *repeat_cfg) | ||
671 | { | ||
672 | DSSDBG("Enter hdmi_core_init\n"); | ||
673 | |||
674 | /* video core */ | ||
675 | video_cfg->ip_bus_width = HDMI_INPUT_8BIT; | ||
676 | video_cfg->op_dither_truc = HDMI_OUTPUTTRUNCATION_8BIT; | ||
677 | video_cfg->deep_color_pkt = HDMI_DEEPCOLORPACKECTDISABLE; | ||
678 | video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE; | ||
679 | video_cfg->hdmi_dvi = HDMI_DVI; | ||
680 | video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; | ||
681 | |||
682 | /* info frame */ | ||
683 | avi_cfg->db1_format = 0; | ||
684 | avi_cfg->db1_active_info = 0; | ||
685 | avi_cfg->db1_bar_info_dv = 0; | ||
686 | avi_cfg->db1_scan_info = 0; | ||
687 | avi_cfg->db2_colorimetry = 0; | ||
688 | avi_cfg->db2_aspect_ratio = 0; | ||
689 | avi_cfg->db2_active_fmt_ar = 0; | ||
690 | avi_cfg->db3_itc = 0; | ||
691 | avi_cfg->db3_ec = 0; | ||
692 | avi_cfg->db3_q_range = 0; | ||
693 | avi_cfg->db3_nup_scaling = 0; | ||
694 | avi_cfg->db4_videocode = 0; | ||
695 | avi_cfg->db5_pixel_repeat = 0; | ||
696 | avi_cfg->db6_7_line_eoftop = 0 ; | ||
697 | avi_cfg->db8_9_line_sofbottom = 0; | ||
698 | avi_cfg->db10_11_pixel_eofleft = 0; | ||
699 | avi_cfg->db12_13_pixel_sofright = 0; | ||
700 | |||
701 | /* packet enable and repeat */ | ||
702 | repeat_cfg->audio_pkt = 0; | ||
703 | repeat_cfg->audio_pkt_repeat = 0; | ||
704 | repeat_cfg->avi_infoframe = 0; | ||
705 | repeat_cfg->avi_infoframe_repeat = 0; | ||
706 | repeat_cfg->gen_cntrl_pkt = 0; | ||
707 | repeat_cfg->gen_cntrl_pkt_repeat = 0; | ||
708 | repeat_cfg->generic_pkt = 0; | ||
709 | repeat_cfg->generic_pkt_repeat = 0; | ||
710 | } | ||
711 | |||
712 | static void hdmi_core_powerdown_disable(void) | ||
713 | { | ||
714 | DSSDBG("Enter hdmi_core_powerdown_disable\n"); | ||
715 | REG_FLD_MOD(HDMI_CORE_CTRL1, 0x0, 0, 0); | ||
716 | } | ||
717 | |||
718 | static void hdmi_core_swreset_release(void) | ||
719 | { | ||
720 | DSSDBG("Enter hdmi_core_swreset_release\n"); | ||
721 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x0, 0, 0); | ||
722 | } | ||
723 | |||
724 | static void hdmi_core_swreset_assert(void) | ||
725 | { | ||
726 | DSSDBG("Enter hdmi_core_swreset_assert\n"); | ||
727 | REG_FLD_MOD(HDMI_CORE_SYS_SRST, 0x1, 0, 0); | ||
728 | } | ||
729 | |||
730 | /* DSS_HDMI_CORE_VIDEO_CONFIG */ | ||
731 | static void hdmi_core_video_config(struct hdmi_core_video_config *cfg) | ||
732 | { | ||
733 | u32 r = 0; | ||
734 | |||
735 | /* sys_ctrl1 default configuration not tunable */ | ||
736 | r = hdmi_read_reg(HDMI_CORE_CTRL1); | ||
737 | r = FLD_MOD(r, HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC, 5, 5); | ||
738 | r = FLD_MOD(r, HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC, 4, 4); | ||
739 | r = FLD_MOD(r, HDMI_CORE_CTRL1_BSEL_24BITBUS, 2, 2); | ||
740 | r = FLD_MOD(r, HDMI_CORE_CTRL1_EDGE_RISINGEDGE, 1, 1); | ||
741 | hdmi_write_reg(HDMI_CORE_CTRL1, r); | ||
742 | |||
743 | REG_FLD_MOD(HDMI_CORE_SYS_VID_ACEN, cfg->ip_bus_width, 7, 6); | ||
744 | |||
745 | /* Vid_Mode */ | ||
746 | r = hdmi_read_reg(HDMI_CORE_SYS_VID_MODE); | ||
747 | |||
748 | /* dither truncation configuration */ | ||
749 | if (cfg->op_dither_truc > HDMI_OUTPUTTRUNCATION_12BIT) { | ||
750 | r = FLD_MOD(r, cfg->op_dither_truc - 3, 7, 6); | ||
751 | r = FLD_MOD(r, 1, 5, 5); | ||
752 | } else { | ||
753 | r = FLD_MOD(r, cfg->op_dither_truc, 7, 6); | ||
754 | r = FLD_MOD(r, 0, 5, 5); | ||
755 | } | ||
756 | hdmi_write_reg(HDMI_CORE_SYS_VID_MODE, r); | ||
757 | |||
758 | /* HDMI_Ctrl */ | ||
759 | r = hdmi_read_reg(HDMI_CORE_AV_HDMI_CTRL); | ||
760 | r = FLD_MOD(r, cfg->deep_color_pkt, 6, 6); | ||
761 | r = FLD_MOD(r, cfg->pkt_mode, 5, 3); | ||
762 | r = FLD_MOD(r, cfg->hdmi_dvi, 0, 0); | ||
763 | hdmi_write_reg(HDMI_CORE_AV_HDMI_CTRL, r); | ||
764 | |||
765 | /* TMDS_CTRL */ | ||
766 | REG_FLD_MOD(HDMI_CORE_SYS_TMDS_CTRL, | ||
767 | cfg->tclk_sel_clkmult, 6, 5); | ||
768 | } | ||
769 | |||
770 | static void hdmi_core_aux_infoframe_avi_config( | ||
771 | struct hdmi_core_infoframe_avi info_avi) | ||
772 | { | ||
773 | u32 val; | ||
774 | char sum = 0, checksum = 0; | ||
775 | |||
776 | sum += 0x82 + 0x002 + 0x00D; | ||
777 | hdmi_write_reg(HDMI_CORE_AV_AVI_TYPE, 0x082); | ||
778 | hdmi_write_reg(HDMI_CORE_AV_AVI_VERS, 0x002); | ||
779 | hdmi_write_reg(HDMI_CORE_AV_AVI_LEN, 0x00D); | ||
780 | |||
781 | val = (info_avi.db1_format << 5) | | ||
782 | (info_avi.db1_active_info << 4) | | ||
783 | (info_avi.db1_bar_info_dv << 2) | | ||
784 | (info_avi.db1_scan_info); | ||
785 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(0), val); | ||
786 | sum += val; | ||
787 | |||
788 | val = (info_avi.db2_colorimetry << 6) | | ||
789 | (info_avi.db2_aspect_ratio << 4) | | ||
790 | (info_avi.db2_active_fmt_ar); | ||
791 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(1), val); | ||
792 | sum += val; | ||
793 | |||
794 | val = (info_avi.db3_itc << 7) | | ||
795 | (info_avi.db3_ec << 4) | | ||
796 | (info_avi.db3_q_range << 2) | | ||
797 | (info_avi.db3_nup_scaling); | ||
798 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(2), val); | ||
799 | sum += val; | ||
800 | |||
801 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(3), info_avi.db4_videocode); | ||
802 | sum += info_avi.db4_videocode; | ||
803 | |||
804 | val = info_avi.db5_pixel_repeat; | ||
805 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(4), val); | ||
806 | sum += val; | ||
807 | |||
808 | val = info_avi.db6_7_line_eoftop & 0x00FF; | ||
809 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(5), val); | ||
810 | sum += val; | ||
811 | |||
812 | val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF); | ||
813 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(6), val); | ||
814 | sum += val; | ||
815 | |||
816 | val = info_avi.db8_9_line_sofbottom & 0x00FF; | ||
817 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(7), val); | ||
818 | sum += val; | ||
819 | |||
820 | val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF); | ||
821 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(8), val); | ||
822 | sum += val; | ||
823 | |||
824 | val = info_avi.db10_11_pixel_eofleft & 0x00FF; | ||
825 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(9), val); | ||
826 | sum += val; | ||
827 | |||
828 | val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF); | ||
829 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(10), val); | ||
830 | sum += val; | ||
831 | |||
832 | val = info_avi.db12_13_pixel_sofright & 0x00FF; | ||
833 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(11), val); | ||
834 | sum += val; | ||
835 | |||
836 | val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF); | ||
837 | hdmi_write_reg(HDMI_CORE_AV_AVI_DBYTE(12), val); | ||
838 | sum += val; | ||
839 | |||
840 | checksum = 0x100 - sum; | ||
841 | hdmi_write_reg(HDMI_CORE_AV_AVI_CHSUM, checksum); | ||
842 | } | ||
843 | |||
844 | static void hdmi_core_av_packet_config( | ||
845 | struct hdmi_core_packet_enable_repeat repeat_cfg) | ||
846 | { | ||
847 | /* enable/repeat the infoframe */ | ||
848 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL1, | ||
849 | (repeat_cfg.audio_pkt << 5) | | ||
850 | (repeat_cfg.audio_pkt_repeat << 4) | | ||
851 | (repeat_cfg.avi_infoframe << 1) | | ||
852 | (repeat_cfg.avi_infoframe_repeat)); | ||
853 | |||
854 | /* enable/repeat the packet */ | ||
855 | hdmi_write_reg(HDMI_CORE_AV_PB_CTRL2, | ||
856 | (repeat_cfg.gen_cntrl_pkt << 3) | | ||
857 | (repeat_cfg.gen_cntrl_pkt_repeat << 2) | | ||
858 | (repeat_cfg.generic_pkt << 1) | | ||
859 | (repeat_cfg.generic_pkt_repeat)); | ||
860 | } | ||
861 | |||
862 | static void hdmi_wp_init(struct omap_video_timings *timings, | ||
863 | struct hdmi_video_format *video_fmt, | ||
864 | struct hdmi_video_interface *video_int) | ||
865 | { | ||
866 | DSSDBG("Enter hdmi_wp_init\n"); | ||
867 | |||
868 | timings->hbp = 0; | ||
869 | timings->hfp = 0; | ||
870 | timings->hsw = 0; | ||
871 | timings->vbp = 0; | ||
872 | timings->vfp = 0; | ||
873 | timings->vsw = 0; | ||
874 | |||
875 | video_fmt->packing_mode = HDMI_PACK_10b_RGB_YUV444; | ||
876 | video_fmt->y_res = 0; | ||
877 | video_fmt->x_res = 0; | ||
878 | |||
879 | video_int->vsp = 0; | ||
880 | video_int->hsp = 0; | ||
881 | |||
882 | video_int->interlacing = 0; | ||
883 | video_int->tm = 0; /* HDMI_TIMING_SLAVE */ | ||
884 | |||
885 | } | ||
886 | |||
887 | static void hdmi_wp_video_start(bool start) | ||
888 | { | ||
889 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, start, 31, 31); | ||
890 | } | ||
891 | |||
892 | static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt, | ||
893 | struct omap_video_timings *timings, struct hdmi_config *param) | ||
894 | { | ||
895 | DSSDBG("Enter hdmi_wp_video_init_format\n"); | ||
896 | |||
897 | video_fmt->y_res = param->timings.timings.y_res; | ||
898 | video_fmt->x_res = param->timings.timings.x_res; | ||
899 | |||
900 | timings->hbp = param->timings.timings.hbp; | ||
901 | timings->hfp = param->timings.timings.hfp; | ||
902 | timings->hsw = param->timings.timings.hsw; | ||
903 | timings->vbp = param->timings.timings.vbp; | ||
904 | timings->vfp = param->timings.timings.vfp; | ||
905 | timings->vsw = param->timings.timings.vsw; | ||
906 | } | ||
907 | |||
908 | static void hdmi_wp_video_config_format( | ||
909 | struct hdmi_video_format *video_fmt) | ||
910 | { | ||
911 | u32 l = 0; | ||
912 | |||
913 | REG_FLD_MOD(HDMI_WP_VIDEO_CFG, video_fmt->packing_mode, 10, 8); | ||
914 | |||
915 | l |= FLD_VAL(video_fmt->y_res, 31, 16); | ||
916 | l |= FLD_VAL(video_fmt->x_res, 15, 0); | ||
917 | hdmi_write_reg(HDMI_WP_VIDEO_SIZE, l); | ||
918 | } | ||
919 | |||
920 | static void hdmi_wp_video_config_interface( | ||
921 | struct hdmi_video_interface *video_int) | ||
922 | { | ||
923 | u32 r; | ||
924 | DSSDBG("Enter hdmi_wp_video_config_interface\n"); | ||
925 | |||
926 | r = hdmi_read_reg(HDMI_WP_VIDEO_CFG); | ||
927 | r = FLD_MOD(r, video_int->vsp, 7, 7); | ||
928 | r = FLD_MOD(r, video_int->hsp, 6, 6); | ||
929 | r = FLD_MOD(r, video_int->interlacing, 3, 3); | ||
930 | r = FLD_MOD(r, video_int->tm, 1, 0); | ||
931 | hdmi_write_reg(HDMI_WP_VIDEO_CFG, r); | ||
932 | } | ||
933 | |||
934 | static void hdmi_wp_video_config_timing( | ||
935 | struct omap_video_timings *timings) | ||
936 | { | ||
937 | u32 timing_h = 0; | ||
938 | u32 timing_v = 0; | ||
939 | |||
940 | DSSDBG("Enter hdmi_wp_video_config_timing\n"); | ||
941 | |||
942 | timing_h |= FLD_VAL(timings->hbp, 31, 20); | ||
943 | timing_h |= FLD_VAL(timings->hfp, 19, 8); | ||
944 | timing_h |= FLD_VAL(timings->hsw, 7, 0); | ||
945 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_H, timing_h); | ||
946 | |||
947 | timing_v |= FLD_VAL(timings->vbp, 31, 20); | ||
948 | timing_v |= FLD_VAL(timings->vfp, 19, 8); | ||
949 | timing_v |= FLD_VAL(timings->vsw, 7, 0); | ||
950 | hdmi_write_reg(HDMI_WP_VIDEO_TIMING_V, timing_v); | ||
951 | } | ||
952 | |||
953 | static void hdmi_basic_configure(struct hdmi_config *cfg) | ||
954 | { | ||
955 | /* HDMI */ | ||
956 | struct omap_video_timings video_timing; | ||
957 | struct hdmi_video_format video_format; | ||
958 | struct hdmi_video_interface video_interface; | ||
959 | /* HDMI core */ | ||
960 | struct hdmi_core_infoframe_avi avi_cfg; | ||
961 | struct hdmi_core_video_config v_core_cfg; | ||
962 | struct hdmi_core_packet_enable_repeat repeat_cfg; | ||
963 | |||
964 | hdmi_wp_init(&video_timing, &video_format, | ||
965 | &video_interface); | ||
966 | |||
967 | hdmi_core_init(&v_core_cfg, | ||
968 | &avi_cfg, | ||
969 | &repeat_cfg); | ||
970 | |||
971 | hdmi_wp_video_init_format(&video_format, | ||
972 | &video_timing, cfg); | ||
973 | |||
974 | hdmi_wp_video_config_timing(&video_timing); | ||
975 | |||
976 | /* video config */ | ||
977 | video_format.packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422; | ||
978 | |||
979 | hdmi_wp_video_config_format(&video_format); | ||
980 | |||
981 | video_interface.vsp = cfg->timings.vsync_pol; | ||
982 | video_interface.hsp = cfg->timings.hsync_pol; | ||
983 | video_interface.interlacing = cfg->interlace; | ||
984 | video_interface.tm = 1 ; /* HDMI_TIMING_MASTER_24BIT */ | ||
985 | |||
986 | hdmi_wp_video_config_interface(&video_interface); | ||
987 | |||
988 | /* | ||
989 | * configure core video part | ||
990 | * set software reset in the core | ||
991 | */ | ||
992 | hdmi_core_swreset_assert(); | ||
993 | |||
994 | /* power down off */ | ||
995 | hdmi_core_powerdown_disable(); | ||
996 | |||
997 | v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; | ||
998 | v_core_cfg.hdmi_dvi = cfg->cm.mode; | ||
999 | |||
1000 | hdmi_core_video_config(&v_core_cfg); | ||
1001 | |||
1002 | /* release software reset in the core */ | ||
1003 | hdmi_core_swreset_release(); | ||
1004 | |||
1005 | /* | ||
1006 | * configure packet | ||
1007 | * info frame video see doc CEA861-D page 65 | ||
1008 | */ | ||
1009 | avi_cfg.db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB; | ||
1010 | avi_cfg.db1_active_info = | ||
1011 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF; | ||
1012 | avi_cfg.db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO; | ||
1013 | avi_cfg.db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0; | ||
1014 | avi_cfg.db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO; | ||
1015 | avi_cfg.db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO; | ||
1016 | avi_cfg.db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME; | ||
1017 | avi_cfg.db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO; | ||
1018 | avi_cfg.db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601; | ||
1019 | avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT; | ||
1020 | avi_cfg.db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO; | ||
1021 | avi_cfg.db4_videocode = cfg->cm.code; | ||
1022 | avi_cfg.db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO; | ||
1023 | avi_cfg.db6_7_line_eoftop = 0; | ||
1024 | avi_cfg.db8_9_line_sofbottom = 0; | ||
1025 | avi_cfg.db10_11_pixel_eofleft = 0; | ||
1026 | avi_cfg.db12_13_pixel_sofright = 0; | ||
1027 | |||
1028 | hdmi_core_aux_infoframe_avi_config(avi_cfg); | ||
1029 | |||
1030 | /* enable/repeat the infoframe */ | ||
1031 | repeat_cfg.avi_infoframe = HDMI_PACKETENABLE; | ||
1032 | repeat_cfg.avi_infoframe_repeat = HDMI_PACKETREPEATON; | ||
1033 | /* wakeup */ | ||
1034 | repeat_cfg.audio_pkt = HDMI_PACKETENABLE; | ||
1035 | repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON; | ||
1036 | hdmi_core_av_packet_config(repeat_cfg); | ||
1037 | } | ||
1038 | |||
1039 | static void update_hdmi_timings(struct hdmi_config *cfg, | ||
1040 | struct omap_video_timings *timings, int code) | ||
1041 | { | ||
1042 | cfg->timings.timings.x_res = timings->x_res; | ||
1043 | cfg->timings.timings.y_res = timings->y_res; | ||
1044 | cfg->timings.timings.hbp = timings->hbp; | ||
1045 | cfg->timings.timings.hfp = timings->hfp; | ||
1046 | cfg->timings.timings.hsw = timings->hsw; | ||
1047 | cfg->timings.timings.vbp = timings->vbp; | ||
1048 | cfg->timings.timings.vfp = timings->vfp; | ||
1049 | cfg->timings.timings.vsw = timings->vsw; | ||
1050 | cfg->timings.timings.pixel_clock = timings->pixel_clock; | ||
1051 | cfg->timings.vsync_pol = cea_vesa_timings[code].vsync_pol; | ||
1052 | cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol; | ||
1053 | } | ||
1054 | |||
1055 | static void hdmi_compute_pll(unsigned long clkin, int phy, | ||
1056 | int n, struct hdmi_pll_info *pi) | ||
1057 | { | ||
1058 | unsigned long refclk; | ||
1059 | u32 mf; | ||
1060 | |||
1061 | /* | ||
1062 | * Input clock is predivided by N + 1 | ||
1063 | * out put of which is reference clk | ||
1064 | */ | ||
1065 | refclk = clkin / (n + 1); | ||
1066 | pi->regn = n; | ||
1067 | |||
1068 | /* | ||
1069 | * multiplier is pixel_clk/ref_clk | ||
1070 | * Multiplying by 100 to avoid fractional part removal | ||
1071 | */ | ||
1072 | pi->regm = (phy * 100/(refclk))/100; | ||
1073 | pi->regm2 = 1; | ||
1074 | |||
1075 | /* | ||
1076 | * fractional multiplier is remainder of the difference between | ||
1077 | * multiplier and actual phy(required pixel clock thus should be | ||
1078 | * multiplied by 2^18(262144) divided by the reference clock | ||
1079 | */ | ||
1080 | mf = (phy - pi->regm * refclk) * 262144; | ||
1081 | pi->regmf = mf/(refclk); | ||
1082 | |||
1083 | /* | ||
1084 | * Dcofreq should be set to 1 if required pixel clock | ||
1085 | * is greater than 1000MHz | ||
1086 | */ | ||
1087 | pi->dcofreq = phy > 1000 * 100; | ||
1088 | pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10; | ||
1089 | |||
1090 | DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf); | ||
1091 | DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd); | ||
1092 | } | ||
1093 | |||
1094 | static void hdmi_enable_clocks(int enable) | ||
1095 | { | ||
1096 | if (enable) | ||
1097 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1098 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1099 | else | ||
1100 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | | ||
1101 | DSS_CLK_SYSCK | DSS_CLK_VIDFCK); | ||
1102 | } | ||
1103 | |||
1104 | static int hdmi_power_on(struct omap_dss_device *dssdev) | ||
1105 | { | ||
1106 | int r, code = 0; | ||
1107 | struct hdmi_pll_info pll_data; | ||
1108 | struct omap_video_timings *p; | ||
1109 | int clkin, n, phy; | ||
1110 | |||
1111 | hdmi_enable_clocks(1); | ||
1112 | |||
1113 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1114 | |||
1115 | p = &dssdev->panel.timings; | ||
1116 | |||
1117 | DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", | ||
1118 | dssdev->panel.timings.x_res, | ||
1119 | dssdev->panel.timings.y_res); | ||
1120 | |||
1121 | if (!hdmi.custom_set) { | ||
1122 | DSSDBG("Read EDID as no EDID is not set on poweron\n"); | ||
1123 | hdmi_read_edid(p); | ||
1124 | } | ||
1125 | code = get_timings_index(); | ||
1126 | dssdev->panel.timings = cea_vesa_timings[code].timings; | ||
1127 | update_hdmi_timings(&hdmi.cfg, p, code); | ||
1128 | |||
1129 | clkin = 3840; /* 38.4 MHz */ | ||
1130 | n = 15; /* this is a constant for our math */ | ||
1131 | phy = p->pixel_clock; | ||
1132 | |||
1133 | hdmi_compute_pll(clkin, phy, n, &pll_data); | ||
1134 | |||
1135 | hdmi_wp_video_start(0); | ||
1136 | |||
1137 | /* config the PLL and PHY first */ | ||
1138 | r = hdmi_pll_program(&pll_data); | ||
1139 | if (r) { | ||
1140 | DSSDBG("Failed to lock PLL\n"); | ||
1141 | goto err; | ||
1142 | } | ||
1143 | |||
1144 | r = hdmi_phy_init(); | ||
1145 | if (r) { | ||
1146 | DSSDBG("Failed to start PHY\n"); | ||
1147 | goto err; | ||
1148 | } | ||
1149 | |||
1150 | hdmi.cfg.cm.mode = hdmi.mode; | ||
1151 | hdmi.cfg.cm.code = hdmi.code; | ||
1152 | hdmi_basic_configure(&hdmi.cfg); | ||
1153 | |||
1154 | /* Make selection of HDMI in DSS */ | ||
1155 | dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); | ||
1156 | |||
1157 | /* Select the dispc clock source as PRCM clock, to ensure that it is not | ||
1158 | * DSI PLL source as the clock selected by DSI PLL might not be | ||
1159 | * sufficient for the resolution selected / that can be changed | ||
1160 | * dynamically by user. This can be moved to single location , say | ||
1161 | * Boardfile. | ||
1162 | */ | ||
1163 | dss_select_dispc_clk_source(DSS_CLK_SRC_FCK); | ||
1164 | |||
1165 | /* bypass TV gamma table */ | ||
1166 | dispc_enable_gamma_table(0); | ||
1167 | |||
1168 | /* tv size */ | ||
1169 | dispc_set_digit_size(dssdev->panel.timings.x_res, | ||
1170 | dssdev->panel.timings.y_res); | ||
1171 | |||
1172 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 1); | ||
1173 | |||
1174 | hdmi_wp_video_start(1); | ||
1175 | |||
1176 | return 0; | ||
1177 | err: | ||
1178 | hdmi_enable_clocks(0); | ||
1179 | return -EIO; | ||
1180 | } | ||
1181 | |||
1182 | static void hdmi_power_off(struct omap_dss_device *dssdev) | ||
1183 | { | ||
1184 | dispc_enable_channel(OMAP_DSS_CHANNEL_DIGIT, 0); | ||
1185 | |||
1186 | hdmi_wp_video_start(0); | ||
1187 | hdmi_phy_off(); | ||
1188 | hdmi_set_pll_pwr(HDMI_PLLPWRCMD_ALLOFF); | ||
1189 | hdmi_enable_clocks(0); | ||
1190 | |||
1191 | hdmi.edid_set = 0; | ||
1192 | } | ||
1193 | |||
1194 | int omapdss_hdmi_display_check_timing(struct omap_dss_device *dssdev, | ||
1195 | struct omap_video_timings *timings) | ||
1196 | { | ||
1197 | struct hdmi_cm cm; | ||
1198 | |||
1199 | cm = hdmi_get_code(timings); | ||
1200 | if (cm.code == -1) { | ||
1201 | DSSERR("Invalid timing entered\n"); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | |||
1205 | return 0; | ||
1206 | |||
1207 | } | ||
1208 | |||
1209 | void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev) | ||
1210 | { | ||
1211 | struct hdmi_cm cm; | ||
1212 | |||
1213 | hdmi.custom_set = 1; | ||
1214 | cm = hdmi_get_code(&dssdev->panel.timings); | ||
1215 | hdmi.code = cm.code; | ||
1216 | hdmi.mode = cm.mode; | ||
1217 | omapdss_hdmi_display_enable(dssdev); | ||
1218 | hdmi.custom_set = 0; | ||
1219 | } | ||
1220 | |||
1221 | int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev) | ||
1222 | { | ||
1223 | int r = 0; | ||
1224 | |||
1225 | DSSDBG("ENTER hdmi_display_enable\n"); | ||
1226 | |||
1227 | mutex_lock(&hdmi.lock); | ||
1228 | |||
1229 | r = omap_dss_start_device(dssdev); | ||
1230 | if (r) { | ||
1231 | DSSERR("failed to start device\n"); | ||
1232 | goto err0; | ||
1233 | } | ||
1234 | |||
1235 | if (dssdev->platform_enable) { | ||
1236 | r = dssdev->platform_enable(dssdev); | ||
1237 | if (r) { | ||
1238 | DSSERR("failed to enable GPIO's\n"); | ||
1239 | goto err1; | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | r = hdmi_power_on(dssdev); | ||
1244 | if (r) { | ||
1245 | DSSERR("failed to power on device\n"); | ||
1246 | goto err2; | ||
1247 | } | ||
1248 | |||
1249 | mutex_unlock(&hdmi.lock); | ||
1250 | return 0; | ||
1251 | |||
1252 | err2: | ||
1253 | if (dssdev->platform_disable) | ||
1254 | dssdev->platform_disable(dssdev); | ||
1255 | err1: | ||
1256 | omap_dss_stop_device(dssdev); | ||
1257 | err0: | ||
1258 | mutex_unlock(&hdmi.lock); | ||
1259 | return r; | ||
1260 | } | ||
1261 | |||
1262 | void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev) | ||
1263 | { | ||
1264 | DSSDBG("Enter hdmi_display_disable\n"); | ||
1265 | |||
1266 | mutex_lock(&hdmi.lock); | ||
1267 | |||
1268 | hdmi_power_off(dssdev); | ||
1269 | |||
1270 | if (dssdev->platform_disable) | ||
1271 | dssdev->platform_disable(dssdev); | ||
1272 | |||
1273 | omap_dss_stop_device(dssdev); | ||
1274 | |||
1275 | mutex_unlock(&hdmi.lock); | ||
1276 | } | ||
1277 | |||
1278 | /* HDMI HW IP initialisation */ | ||
1279 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | ||
1280 | { | ||
1281 | struct resource *hdmi_mem; | ||
1282 | |||
1283 | hdmi.pdata = pdev->dev.platform_data; | ||
1284 | hdmi.pdev = pdev; | ||
1285 | |||
1286 | mutex_init(&hdmi.lock); | ||
1287 | |||
1288 | hdmi_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0); | ||
1289 | if (!hdmi_mem) { | ||
1290 | DSSERR("can't get IORESOURCE_MEM HDMI\n"); | ||
1291 | return -EINVAL; | ||
1292 | } | ||
1293 | |||
1294 | /* Base address taken from platform */ | ||
1295 | hdmi.base_wp = ioremap(hdmi_mem->start, resource_size(hdmi_mem)); | ||
1296 | if (!hdmi.base_wp) { | ||
1297 | DSSERR("can't ioremap WP\n"); | ||
1298 | return -ENOMEM; | ||
1299 | } | ||
1300 | |||
1301 | hdmi_panel_init(); | ||
1302 | |||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | static int omapdss_hdmihw_remove(struct platform_device *pdev) | ||
1307 | { | ||
1308 | hdmi_panel_exit(); | ||
1309 | |||
1310 | iounmap(hdmi.base_wp); | ||
1311 | |||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | static struct platform_driver omapdss_hdmihw_driver = { | ||
1316 | .probe = omapdss_hdmihw_probe, | ||
1317 | .remove = omapdss_hdmihw_remove, | ||
1318 | .driver = { | ||
1319 | .name = "omapdss_hdmi", | ||
1320 | .owner = THIS_MODULE, | ||
1321 | }, | ||
1322 | }; | ||
1323 | |||
1324 | int hdmi_init_platform_driver(void) | ||
1325 | { | ||
1326 | return platform_driver_register(&omapdss_hdmihw_driver); | ||
1327 | } | ||
1328 | |||
1329 | void hdmi_uninit_platform_driver(void) | ||
1330 | { | ||
1331 | return platform_driver_unregister(&omapdss_hdmihw_driver); | ||
1332 | } | ||
diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/omap2/dss/hdmi.h new file mode 100644 index 000000000000..9887ab96da3c --- /dev/null +++ b/drivers/video/omap2/dss/hdmi.h | |||
@@ -0,0 +1,415 @@ | |||
1 | /* | ||
2 | * hdmi.h | ||
3 | * | ||
4 | * HDMI driver definition for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | */ | ||
20 | |||
21 | #ifndef _OMAP4_DSS_HDMI_H_ | ||
22 | #define _OMAP4_DSS_HDMI_H_ | ||
23 | |||
24 | #include <linux/string.h> | ||
25 | #include <plat/display.h> | ||
26 | |||
27 | #define HDMI_WP 0x0 | ||
28 | #define HDMI_CORE_SYS 0x400 | ||
29 | #define HDMI_CORE_AV 0x900 | ||
30 | #define HDMI_PLLCTRL 0x200 | ||
31 | #define HDMI_PHY 0x300 | ||
32 | |||
33 | struct hdmi_reg { u16 idx; }; | ||
34 | |||
35 | #define HDMI_REG(idx) ((const struct hdmi_reg) { idx }) | ||
36 | |||
37 | /* HDMI Wrapper */ | ||
38 | #define HDMI_WP_REG(idx) HDMI_REG(HDMI_WP + idx) | ||
39 | |||
40 | #define HDMI_WP_REVISION HDMI_WP_REG(0x0) | ||
41 | #define HDMI_WP_SYSCONFIG HDMI_WP_REG(0x10) | ||
42 | #define HDMI_WP_IRQSTATUS_RAW HDMI_WP_REG(0x24) | ||
43 | #define HDMI_WP_IRQSTATUS HDMI_WP_REG(0x28) | ||
44 | #define HDMI_WP_PWR_CTRL HDMI_WP_REG(0x40) | ||
45 | #define HDMI_WP_IRQENABLE_SET HDMI_WP_REG(0x2C) | ||
46 | #define HDMI_WP_VIDEO_CFG HDMI_WP_REG(0x50) | ||
47 | #define HDMI_WP_VIDEO_SIZE HDMI_WP_REG(0x60) | ||
48 | #define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68) | ||
49 | #define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C) | ||
50 | #define HDMI_WP_WP_CLK HDMI_WP_REG(0x70) | ||
51 | |||
52 | /* HDMI IP Core System */ | ||
53 | #define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx) | ||
54 | |||
55 | #define HDMI_CORE_SYS_VND_IDL HDMI_CORE_SYS_REG(0x0) | ||
56 | #define HDMI_CORE_SYS_DEV_IDL HDMI_CORE_SYS_REG(0x8) | ||
57 | #define HDMI_CORE_SYS_DEV_IDH HDMI_CORE_SYS_REG(0xC) | ||
58 | #define HDMI_CORE_SYS_DEV_REV HDMI_CORE_SYS_REG(0x10) | ||
59 | #define HDMI_CORE_SYS_SRST HDMI_CORE_SYS_REG(0x14) | ||
60 | #define HDMI_CORE_CTRL1 HDMI_CORE_SYS_REG(0x20) | ||
61 | #define HDMI_CORE_SYS_SYS_STAT HDMI_CORE_SYS_REG(0x24) | ||
62 | #define HDMI_CORE_SYS_VID_ACEN HDMI_CORE_SYS_REG(0x124) | ||
63 | #define HDMI_CORE_SYS_VID_MODE HDMI_CORE_SYS_REG(0x128) | ||
64 | #define HDMI_CORE_SYS_INTR_STATE HDMI_CORE_SYS_REG(0x1C0) | ||
65 | #define HDMI_CORE_SYS_INTR1 HDMI_CORE_SYS_REG(0x1C4) | ||
66 | #define HDMI_CORE_SYS_INTR2 HDMI_CORE_SYS_REG(0x1C8) | ||
67 | #define HDMI_CORE_SYS_INTR3 HDMI_CORE_SYS_REG(0x1CC) | ||
68 | #define HDMI_CORE_SYS_INTR4 HDMI_CORE_SYS_REG(0x1D0) | ||
69 | #define HDMI_CORE_SYS_UMASK1 HDMI_CORE_SYS_REG(0x1D4) | ||
70 | #define HDMI_CORE_SYS_TMDS_CTRL HDMI_CORE_SYS_REG(0x208) | ||
71 | #define HDMI_CORE_SYS_DE_DLY HDMI_CORE_SYS_REG(0xC8) | ||
72 | #define HDMI_CORE_SYS_DE_CTRL HDMI_CORE_SYS_REG(0xCC) | ||
73 | #define HDMI_CORE_SYS_DE_TOP HDMI_CORE_SYS_REG(0xD0) | ||
74 | #define HDMI_CORE_SYS_DE_CNTL HDMI_CORE_SYS_REG(0xD8) | ||
75 | #define HDMI_CORE_SYS_DE_CNTH HDMI_CORE_SYS_REG(0xDC) | ||
76 | #define HDMI_CORE_SYS_DE_LINL HDMI_CORE_SYS_REG(0xE0) | ||
77 | #define HDMI_CORE_SYS_DE_LINH_1 HDMI_CORE_SYS_REG(0xE4) | ||
78 | #define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1 | ||
79 | #define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1 | ||
80 | #define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1 | ||
81 | #define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1 | ||
82 | |||
83 | /* HDMI DDC E-DID */ | ||
84 | #define HDMI_CORE_DDC_CMD HDMI_CORE_SYS_REG(0x3CC) | ||
85 | #define HDMI_CORE_DDC_STATUS HDMI_CORE_SYS_REG(0x3C8) | ||
86 | #define HDMI_CORE_DDC_ADDR HDMI_CORE_SYS_REG(0x3B4) | ||
87 | #define HDMI_CORE_DDC_OFFSET HDMI_CORE_SYS_REG(0x3BC) | ||
88 | #define HDMI_CORE_DDC_COUNT1 HDMI_CORE_SYS_REG(0x3C0) | ||
89 | #define HDMI_CORE_DDC_COUNT2 HDMI_CORE_SYS_REG(0x3C4) | ||
90 | #define HDMI_CORE_DDC_DATA HDMI_CORE_SYS_REG(0x3D0) | ||
91 | #define HDMI_CORE_DDC_SEGM HDMI_CORE_SYS_REG(0x3B8) | ||
92 | |||
93 | /* HDMI IP Core Audio Video */ | ||
94 | #define HDMI_CORE_AV_REG(idx) HDMI_REG(HDMI_CORE_AV + idx) | ||
95 | |||
96 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
97 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
98 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
99 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
100 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
101 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
102 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
103 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
104 | #define HDMI_CORE_AV_AVI_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x110) | ||
105 | #define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15) | ||
106 | #define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190) | ||
107 | #define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
108 | #define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290) | ||
109 | #define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27) | ||
110 | #define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300) | ||
111 | #define HDMI_CORE_AV_GEN_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
112 | #define HDMI_CORE_AV_GEN2_DBYTE HDMI_CORE_AV_REG(0x380) | ||
113 | #define HDMI_CORE_AV_GEN2_DBYTE_NELEMS HDMI_CORE_AV_REG(31) | ||
114 | #define HDMI_CORE_AV_ACR_CTRL HDMI_CORE_AV_REG(0x4) | ||
115 | #define HDMI_CORE_AV_FREQ_SVAL HDMI_CORE_AV_REG(0x8) | ||
116 | #define HDMI_CORE_AV_N_SVAL1 HDMI_CORE_AV_REG(0xC) | ||
117 | #define HDMI_CORE_AV_N_SVAL2 HDMI_CORE_AV_REG(0x10) | ||
118 | #define HDMI_CORE_AV_N_SVAL3 HDMI_CORE_AV_REG(0x14) | ||
119 | #define HDMI_CORE_AV_CTS_SVAL1 HDMI_CORE_AV_REG(0x18) | ||
120 | #define HDMI_CORE_AV_CTS_SVAL2 HDMI_CORE_AV_REG(0x1C) | ||
121 | #define HDMI_CORE_AV_CTS_SVAL3 HDMI_CORE_AV_REG(0x20) | ||
122 | #define HDMI_CORE_AV_CTS_HVAL1 HDMI_CORE_AV_REG(0x24) | ||
123 | #define HDMI_CORE_AV_CTS_HVAL2 HDMI_CORE_AV_REG(0x28) | ||
124 | #define HDMI_CORE_AV_CTS_HVAL3 HDMI_CORE_AV_REG(0x2C) | ||
125 | #define HDMI_CORE_AV_AUD_MODE HDMI_CORE_AV_REG(0x50) | ||
126 | #define HDMI_CORE_AV_SPDIF_CTRL HDMI_CORE_AV_REG(0x54) | ||
127 | #define HDMI_CORE_AV_HW_SPDIF_FS HDMI_CORE_AV_REG(0x60) | ||
128 | #define HDMI_CORE_AV_SWAP_I2S HDMI_CORE_AV_REG(0x64) | ||
129 | #define HDMI_CORE_AV_SPDIF_ERTH HDMI_CORE_AV_REG(0x6C) | ||
130 | #define HDMI_CORE_AV_I2S_IN_MAP HDMI_CORE_AV_REG(0x70) | ||
131 | #define HDMI_CORE_AV_I2S_IN_CTRL HDMI_CORE_AV_REG(0x74) | ||
132 | #define HDMI_CORE_AV_I2S_CHST0 HDMI_CORE_AV_REG(0x78) | ||
133 | #define HDMI_CORE_AV_I2S_CHST1 HDMI_CORE_AV_REG(0x7C) | ||
134 | #define HDMI_CORE_AV_I2S_CHST2 HDMI_CORE_AV_REG(0x80) | ||
135 | #define HDMI_CORE_AV_I2S_CHST4 HDMI_CORE_AV_REG(0x84) | ||
136 | #define HDMI_CORE_AV_I2S_CHST5 HDMI_CORE_AV_REG(0x88) | ||
137 | #define HDMI_CORE_AV_ASRC HDMI_CORE_AV_REG(0x8C) | ||
138 | #define HDMI_CORE_AV_I2S_IN_LEN HDMI_CORE_AV_REG(0x90) | ||
139 | #define HDMI_CORE_AV_HDMI_CTRL HDMI_CORE_AV_REG(0xBC) | ||
140 | #define HDMI_CORE_AV_AUDO_TXSTAT HDMI_CORE_AV_REG(0xC0) | ||
141 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_1 HDMI_CORE_AV_REG(0xCC) | ||
142 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_2 HDMI_CORE_AV_REG(0xD0) | ||
143 | #define HDMI_CORE_AV_AUD_PAR_BUSCLK_3 HDMI_CORE_AV_REG(0xD4) | ||
144 | #define HDMI_CORE_AV_TEST_TXCTRL HDMI_CORE_AV_REG(0xF0) | ||
145 | #define HDMI_CORE_AV_DPD HDMI_CORE_AV_REG(0xF4) | ||
146 | #define HDMI_CORE_AV_PB_CTRL1 HDMI_CORE_AV_REG(0xF8) | ||
147 | #define HDMI_CORE_AV_PB_CTRL2 HDMI_CORE_AV_REG(0xFC) | ||
148 | #define HDMI_CORE_AV_AVI_TYPE HDMI_CORE_AV_REG(0x100) | ||
149 | #define HDMI_CORE_AV_AVI_VERS HDMI_CORE_AV_REG(0x104) | ||
150 | #define HDMI_CORE_AV_AVI_LEN HDMI_CORE_AV_REG(0x108) | ||
151 | #define HDMI_CORE_AV_AVI_CHSUM HDMI_CORE_AV_REG(0x10C) | ||
152 | #define HDMI_CORE_AV_SPD_TYPE HDMI_CORE_AV_REG(0x180) | ||
153 | #define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184) | ||
154 | #define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188) | ||
155 | #define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C) | ||
156 | #define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280) | ||
157 | #define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284) | ||
158 | #define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288) | ||
159 | #define HDMI_CORE_AV_MPEG_CHSUM HDMI_CORE_AV_REG(0x28C) | ||
160 | #define HDMI_CORE_AV_CP_BYTE1 HDMI_CORE_AV_REG(0x37C) | ||
161 | #define HDMI_CORE_AV_CEC_ADDR_ID HDMI_CORE_AV_REG(0x3FC) | ||
162 | #define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4 | ||
163 | #define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4 | ||
164 | #define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4 | ||
165 | #define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4 | ||
166 | |||
167 | /* PLL */ | ||
168 | #define HDMI_PLL_REG(idx) HDMI_REG(HDMI_PLLCTRL + idx) | ||
169 | |||
170 | #define PLLCTRL_PLL_CONTROL HDMI_PLL_REG(0x0) | ||
171 | #define PLLCTRL_PLL_STATUS HDMI_PLL_REG(0x4) | ||
172 | #define PLLCTRL_PLL_GO HDMI_PLL_REG(0x8) | ||
173 | #define PLLCTRL_CFG1 HDMI_PLL_REG(0xC) | ||
174 | #define PLLCTRL_CFG2 HDMI_PLL_REG(0x10) | ||
175 | #define PLLCTRL_CFG3 HDMI_PLL_REG(0x14) | ||
176 | #define PLLCTRL_CFG4 HDMI_PLL_REG(0x20) | ||
177 | |||
178 | /* HDMI PHY */ | ||
179 | #define HDMI_PHY_REG(idx) HDMI_REG(HDMI_PHY + idx) | ||
180 | |||
181 | #define HDMI_TXPHY_TX_CTRL HDMI_PHY_REG(0x0) | ||
182 | #define HDMI_TXPHY_DIGITAL_CTRL HDMI_PHY_REG(0x4) | ||
183 | #define HDMI_TXPHY_POWER_CTRL HDMI_PHY_REG(0x8) | ||
184 | #define HDMI_TXPHY_PAD_CFG_CTRL HDMI_PHY_REG(0xC) | ||
185 | |||
186 | /* HDMI EDID Length */ | ||
187 | #define HDMI_EDID_MAX_LENGTH 256 | ||
188 | #define EDID_TIMING_DESCRIPTOR_SIZE 0x12 | ||
189 | #define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36 | ||
190 | #define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80 | ||
191 | #define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4 | ||
192 | #define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4 | ||
193 | |||
194 | #define OMAP_HDMI_TIMINGS_NB 34 | ||
195 | |||
196 | #define REG_FLD_MOD(idx, val, start, end) \ | ||
197 | hdmi_write_reg(idx, FLD_MOD(hdmi_read_reg(idx), val, start, end)) | ||
198 | #define REG_GET(idx, start, end) \ | ||
199 | FLD_GET(hdmi_read_reg(idx), start, end) | ||
200 | |||
201 | /* HDMI timing structure */ | ||
202 | struct hdmi_timings { | ||
203 | struct omap_video_timings timings; | ||
204 | int vsync_pol; | ||
205 | int hsync_pol; | ||
206 | }; | ||
207 | |||
208 | enum hdmi_phy_pwr { | ||
209 | HDMI_PHYPWRCMD_OFF = 0, | ||
210 | HDMI_PHYPWRCMD_LDOON = 1, | ||
211 | HDMI_PHYPWRCMD_TXON = 2 | ||
212 | }; | ||
213 | |||
214 | enum hdmi_pll_pwr { | ||
215 | HDMI_PLLPWRCMD_ALLOFF = 0, | ||
216 | HDMI_PLLPWRCMD_PLLONLY = 1, | ||
217 | HDMI_PLLPWRCMD_BOTHON_ALLCLKS = 2, | ||
218 | HDMI_PLLPWRCMD_BOTHON_NOPHYCLK = 3 | ||
219 | }; | ||
220 | |||
221 | enum hdmi_clk_refsel { | ||
222 | HDMI_REFSEL_PCLK = 0, | ||
223 | HDMI_REFSEL_REF1 = 1, | ||
224 | HDMI_REFSEL_REF2 = 2, | ||
225 | HDMI_REFSEL_SYSCLK = 3 | ||
226 | }; | ||
227 | |||
228 | enum hdmi_core_inputbus_width { | ||
229 | HDMI_INPUT_8BIT = 0, | ||
230 | HDMI_INPUT_10BIT = 1, | ||
231 | HDMI_INPUT_12BIT = 2 | ||
232 | }; | ||
233 | |||
234 | enum hdmi_core_dither_trunc { | ||
235 | HDMI_OUTPUTTRUNCATION_8BIT = 0, | ||
236 | HDMI_OUTPUTTRUNCATION_10BIT = 1, | ||
237 | HDMI_OUTPUTTRUNCATION_12BIT = 2, | ||
238 | HDMI_OUTPUTDITHER_8BIT = 3, | ||
239 | HDMI_OUTPUTDITHER_10BIT = 4, | ||
240 | HDMI_OUTPUTDITHER_12BIT = 5 | ||
241 | }; | ||
242 | |||
243 | enum hdmi_core_deepcolor_ed { | ||
244 | HDMI_DEEPCOLORPACKECTDISABLE = 0, | ||
245 | HDMI_DEEPCOLORPACKECTENABLE = 1 | ||
246 | }; | ||
247 | |||
248 | enum hdmi_core_packet_mode { | ||
249 | HDMI_PACKETMODERESERVEDVALUE = 0, | ||
250 | HDMI_PACKETMODE24BITPERPIXEL = 4, | ||
251 | HDMI_PACKETMODE30BITPERPIXEL = 5, | ||
252 | HDMI_PACKETMODE36BITPERPIXEL = 6, | ||
253 | HDMI_PACKETMODE48BITPERPIXEL = 7 | ||
254 | }; | ||
255 | |||
256 | enum hdmi_core_hdmi_dvi { | ||
257 | HDMI_DVI = 0, | ||
258 | HDMI_HDMI = 1 | ||
259 | }; | ||
260 | |||
261 | enum hdmi_core_tclkselclkmult { | ||
262 | HDMI_FPLL05IDCK = 0, | ||
263 | HDMI_FPLL10IDCK = 1, | ||
264 | HDMI_FPLL20IDCK = 2, | ||
265 | HDMI_FPLL40IDCK = 3 | ||
266 | }; | ||
267 | |||
268 | enum hdmi_core_packet_ctrl { | ||
269 | HDMI_PACKETENABLE = 1, | ||
270 | HDMI_PACKETDISABLE = 0, | ||
271 | HDMI_PACKETREPEATON = 1, | ||
272 | HDMI_PACKETREPEATOFF = 0 | ||
273 | }; | ||
274 | |||
275 | /* INFOFRAME_AVI_ definitions */ | ||
276 | enum hdmi_core_infoframe { | ||
277 | HDMI_INFOFRAME_AVI_DB1Y_RGB = 0, | ||
278 | HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1, | ||
279 | HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2, | ||
280 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0, | ||
281 | HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1, | ||
282 | HDMI_INFOFRAME_AVI_DB1B_NO = 0, | ||
283 | HDMI_INFOFRAME_AVI_DB1B_VERT = 1, | ||
284 | HDMI_INFOFRAME_AVI_DB1B_HORI = 2, | ||
285 | HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3, | ||
286 | HDMI_INFOFRAME_AVI_DB1S_0 = 0, | ||
287 | HDMI_INFOFRAME_AVI_DB1S_1 = 1, | ||
288 | HDMI_INFOFRAME_AVI_DB1S_2 = 2, | ||
289 | HDMI_INFOFRAME_AVI_DB2C_NO = 0, | ||
290 | HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1, | ||
291 | HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2, | ||
292 | HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3, | ||
293 | HDMI_INFOFRAME_AVI_DB2M_NO = 0, | ||
294 | HDMI_INFOFRAME_AVI_DB2M_43 = 1, | ||
295 | HDMI_INFOFRAME_AVI_DB2M_169 = 2, | ||
296 | HDMI_INFOFRAME_AVI_DB2R_SAME = 8, | ||
297 | HDMI_INFOFRAME_AVI_DB2R_43 = 9, | ||
298 | HDMI_INFOFRAME_AVI_DB2R_169 = 10, | ||
299 | HDMI_INFOFRAME_AVI_DB2R_149 = 11, | ||
300 | HDMI_INFOFRAME_AVI_DB3ITC_NO = 0, | ||
301 | HDMI_INFOFRAME_AVI_DB3ITC_YES = 1, | ||
302 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0, | ||
303 | HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1, | ||
304 | HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0, | ||
305 | HDMI_INFOFRAME_AVI_DB3Q_LR = 1, | ||
306 | HDMI_INFOFRAME_AVI_DB3Q_FR = 2, | ||
307 | HDMI_INFOFRAME_AVI_DB3SC_NO = 0, | ||
308 | HDMI_INFOFRAME_AVI_DB3SC_HORI = 1, | ||
309 | HDMI_INFOFRAME_AVI_DB3SC_VERT = 2, | ||
310 | HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3, | ||
311 | HDMI_INFOFRAME_AVI_DB5PR_NO = 0, | ||
312 | HDMI_INFOFRAME_AVI_DB5PR_2 = 1, | ||
313 | HDMI_INFOFRAME_AVI_DB5PR_3 = 2, | ||
314 | HDMI_INFOFRAME_AVI_DB5PR_4 = 3, | ||
315 | HDMI_INFOFRAME_AVI_DB5PR_5 = 4, | ||
316 | HDMI_INFOFRAME_AVI_DB5PR_6 = 5, | ||
317 | HDMI_INFOFRAME_AVI_DB5PR_7 = 6, | ||
318 | HDMI_INFOFRAME_AVI_DB5PR_8 = 7, | ||
319 | HDMI_INFOFRAME_AVI_DB5PR_9 = 8, | ||
320 | HDMI_INFOFRAME_AVI_DB5PR_10 = 9 | ||
321 | }; | ||
322 | |||
323 | enum hdmi_packing_mode { | ||
324 | HDMI_PACK_10b_RGB_YUV444 = 0, | ||
325 | HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, | ||
326 | HDMI_PACK_20b_YUV422 = 2, | ||
327 | HDMI_PACK_ALREADYPACKED = 7 | ||
328 | }; | ||
329 | |||
330 | struct hdmi_core_video_config { | ||
331 | enum hdmi_core_inputbus_width ip_bus_width; | ||
332 | enum hdmi_core_dither_trunc op_dither_truc; | ||
333 | enum hdmi_core_deepcolor_ed deep_color_pkt; | ||
334 | enum hdmi_core_packet_mode pkt_mode; | ||
335 | enum hdmi_core_hdmi_dvi hdmi_dvi; | ||
336 | enum hdmi_core_tclkselclkmult tclk_sel_clkmult; | ||
337 | }; | ||
338 | |||
339 | /* | ||
340 | * Refer to section 8.2 in HDMI 1.3 specification for | ||
341 | * details about infoframe databytes | ||
342 | */ | ||
343 | struct hdmi_core_infoframe_avi { | ||
344 | u8 db1_format; | ||
345 | /* Y0, Y1 rgb,yCbCr */ | ||
346 | u8 db1_active_info; | ||
347 | /* A0 Active information Present */ | ||
348 | u8 db1_bar_info_dv; | ||
349 | /* B0, B1 Bar info data valid */ | ||
350 | u8 db1_scan_info; | ||
351 | /* S0, S1 scan information */ | ||
352 | u8 db2_colorimetry; | ||
353 | /* C0, C1 colorimetry */ | ||
354 | u8 db2_aspect_ratio; | ||
355 | /* M0, M1 Aspect ratio (4:3, 16:9) */ | ||
356 | u8 db2_active_fmt_ar; | ||
357 | /* R0...R3 Active format aspect ratio */ | ||
358 | u8 db3_itc; | ||
359 | /* ITC IT content. */ | ||
360 | u8 db3_ec; | ||
361 | /* EC0, EC1, EC2 Extended colorimetry */ | ||
362 | u8 db3_q_range; | ||
363 | /* Q1, Q0 Quantization range */ | ||
364 | u8 db3_nup_scaling; | ||
365 | /* SC1, SC0 Non-uniform picture scaling */ | ||
366 | u8 db4_videocode; | ||
367 | /* VIC0..6 Video format identification */ | ||
368 | u8 db5_pixel_repeat; | ||
369 | /* PR0..PR3 Pixel repetition factor */ | ||
370 | u16 db6_7_line_eoftop; | ||
371 | /* Line number end of top bar */ | ||
372 | u16 db8_9_line_sofbottom; | ||
373 | /* Line number start of bottom bar */ | ||
374 | u16 db10_11_pixel_eofleft; | ||
375 | /* Pixel number end of left bar */ | ||
376 | u16 db12_13_pixel_sofright; | ||
377 | /* Pixel number start of right bar */ | ||
378 | }; | ||
379 | |||
380 | struct hdmi_core_packet_enable_repeat { | ||
381 | u32 audio_pkt; | ||
382 | u32 audio_pkt_repeat; | ||
383 | u32 avi_infoframe; | ||
384 | u32 avi_infoframe_repeat; | ||
385 | u32 gen_cntrl_pkt; | ||
386 | u32 gen_cntrl_pkt_repeat; | ||
387 | u32 generic_pkt; | ||
388 | u32 generic_pkt_repeat; | ||
389 | }; | ||
390 | |||
391 | struct hdmi_video_format { | ||
392 | enum hdmi_packing_mode packing_mode; | ||
393 | u32 y_res; /* Line per panel */ | ||
394 | u32 x_res; /* pixel per line */ | ||
395 | }; | ||
396 | |||
397 | struct hdmi_video_interface { | ||
398 | int vsp; /* Vsync polarity */ | ||
399 | int hsp; /* Hsync polarity */ | ||
400 | int interlacing; | ||
401 | int tm; /* Timing mode */ | ||
402 | }; | ||
403 | |||
404 | struct hdmi_cm { | ||
405 | int code; | ||
406 | int mode; | ||
407 | }; | ||
408 | |||
409 | struct hdmi_config { | ||
410 | struct hdmi_timings timings; | ||
411 | u16 interlace; | ||
412 | struct hdmi_cm cm; | ||
413 | }; | ||
414 | |||
415 | #endif | ||
diff --git a/drivers/video/omap2/dss/hdmi_omap4_panel.c b/drivers/video/omap2/dss/hdmi_omap4_panel.c new file mode 100644 index 000000000000..ffb5de94131f --- /dev/null +++ b/drivers/video/omap2/dss/hdmi_omap4_panel.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* | ||
2 | * hdmi_omap4_panel.c | ||
3 | * | ||
4 | * HDMI library support functions for TI OMAP4 processors. | ||
5 | * | ||
6 | * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ | ||
7 | * Authors: Mythri P k <mythripk@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License version 2 as published by | ||
11 | * the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
14 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
15 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
16 | * more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along with | ||
19 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/err.h> | ||
24 | #include <linux/io.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <plat/display.h> | ||
28 | |||
29 | #include "dss.h" | ||
30 | |||
31 | static struct { | ||
32 | struct mutex hdmi_lock; | ||
33 | } hdmi; | ||
34 | |||
35 | |||
36 | static int hdmi_panel_probe(struct omap_dss_device *dssdev) | ||
37 | { | ||
38 | DSSDBG("ENTER hdmi_panel_probe\n"); | ||
39 | |||
40 | dssdev->panel.config = OMAP_DSS_LCD_TFT | | ||
41 | OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IHS; | ||
42 | |||
43 | /* | ||
44 | * Initialize the timings to 640 * 480 | ||
45 | * This is only for framebuffer update not for TV timing setting | ||
46 | * Setting TV timing will be done only on enable | ||
47 | */ | ||
48 | dssdev->panel.timings.x_res = 640; | ||
49 | dssdev->panel.timings.y_res = 480; | ||
50 | |||
51 | DSSDBG("hdmi_panel_probe x_res= %d y_res = %d\n", | ||
52 | dssdev->panel.timings.x_res, | ||
53 | dssdev->panel.timings.y_res); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void hdmi_panel_remove(struct omap_dss_device *dssdev) | ||
58 | { | ||
59 | |||
60 | } | ||
61 | |||
62 | static int hdmi_panel_enable(struct omap_dss_device *dssdev) | ||
63 | { | ||
64 | int r = 0; | ||
65 | DSSDBG("ENTER hdmi_panel_enable\n"); | ||
66 | |||
67 | mutex_lock(&hdmi.hdmi_lock); | ||
68 | |||
69 | if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) { | ||
70 | r = -EINVAL; | ||
71 | goto err; | ||
72 | } | ||
73 | |||
74 | r = omapdss_hdmi_display_enable(dssdev); | ||
75 | if (r) { | ||
76 | DSSERR("failed to power on\n"); | ||
77 | goto err; | ||
78 | } | ||
79 | |||
80 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
81 | |||
82 | err: | ||
83 | mutex_unlock(&hdmi.hdmi_lock); | ||
84 | |||
85 | return r; | ||
86 | } | ||
87 | |||
88 | static void hdmi_panel_disable(struct omap_dss_device *dssdev) | ||
89 | { | ||
90 | mutex_lock(&hdmi.hdmi_lock); | ||
91 | |||
92 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | ||
93 | omapdss_hdmi_display_disable(dssdev); | ||
94 | |||
95 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
96 | |||
97 | mutex_unlock(&hdmi.hdmi_lock); | ||
98 | } | ||
99 | |||
100 | static int hdmi_panel_suspend(struct omap_dss_device *dssdev) | ||
101 | { | ||
102 | int r = 0; | ||
103 | |||
104 | mutex_lock(&hdmi.hdmi_lock); | ||
105 | |||
106 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) { | ||
107 | r = -EINVAL; | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED; | ||
112 | |||
113 | omapdss_hdmi_display_disable(dssdev); | ||
114 | |||
115 | err: | ||
116 | mutex_unlock(&hdmi.hdmi_lock); | ||
117 | |||
118 | return r; | ||
119 | } | ||
120 | |||
121 | static int hdmi_panel_resume(struct omap_dss_device *dssdev) | ||
122 | { | ||
123 | int r = 0; | ||
124 | |||
125 | mutex_lock(&hdmi.hdmi_lock); | ||
126 | |||
127 | if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) { | ||
128 | r = -EINVAL; | ||
129 | goto err; | ||
130 | } | ||
131 | |||
132 | r = omapdss_hdmi_display_enable(dssdev); | ||
133 | if (r) { | ||
134 | DSSERR("failed to power on\n"); | ||
135 | goto err; | ||
136 | } | ||
137 | |||
138 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
139 | |||
140 | err: | ||
141 | mutex_unlock(&hdmi.hdmi_lock); | ||
142 | |||
143 | return r; | ||
144 | } | ||
145 | |||
146 | static void hdmi_get_timings(struct omap_dss_device *dssdev, | ||
147 | struct omap_video_timings *timings) | ||
148 | { | ||
149 | mutex_lock(&hdmi.hdmi_lock); | ||
150 | |||
151 | *timings = dssdev->panel.timings; | ||
152 | |||
153 | mutex_unlock(&hdmi.hdmi_lock); | ||
154 | } | ||
155 | |||
156 | static void hdmi_set_timings(struct omap_dss_device *dssdev, | ||
157 | struct omap_video_timings *timings) | ||
158 | { | ||
159 | DSSDBG("hdmi_set_timings\n"); | ||
160 | |||
161 | mutex_lock(&hdmi.hdmi_lock); | ||
162 | |||
163 | dssdev->panel.timings = *timings; | ||
164 | |||
165 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { | ||
166 | /* turn the hdmi off and on to get new timings to use */ | ||
167 | omapdss_hdmi_display_disable(dssdev); | ||
168 | omapdss_hdmi_display_set_timing(dssdev); | ||
169 | } | ||
170 | |||
171 | mutex_unlock(&hdmi.hdmi_lock); | ||
172 | } | ||
173 | |||
174 | static int hdmi_check_timings(struct omap_dss_device *dssdev, | ||
175 | struct omap_video_timings *timings) | ||
176 | { | ||
177 | int r = 0; | ||
178 | |||
179 | DSSDBG("hdmi_check_timings\n"); | ||
180 | |||
181 | mutex_lock(&hdmi.hdmi_lock); | ||
182 | |||
183 | r = omapdss_hdmi_display_check_timing(dssdev, timings); | ||
184 | if (r) { | ||
185 | DSSERR("Timing cannot be applied\n"); | ||
186 | goto err; | ||
187 | } | ||
188 | err: | ||
189 | mutex_unlock(&hdmi.hdmi_lock); | ||
190 | return r; | ||
191 | } | ||
192 | |||
193 | static struct omap_dss_driver hdmi_driver = { | ||
194 | .probe = hdmi_panel_probe, | ||
195 | .remove = hdmi_panel_remove, | ||
196 | .enable = hdmi_panel_enable, | ||
197 | .disable = hdmi_panel_disable, | ||
198 | .suspend = hdmi_panel_suspend, | ||
199 | .resume = hdmi_panel_resume, | ||
200 | .get_timings = hdmi_get_timings, | ||
201 | .set_timings = hdmi_set_timings, | ||
202 | .check_timings = hdmi_check_timings, | ||
203 | .driver = { | ||
204 | .name = "hdmi_panel", | ||
205 | .owner = THIS_MODULE, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | int hdmi_panel_init(void) | ||
210 | { | ||
211 | mutex_init(&hdmi.hdmi_lock); | ||
212 | |||
213 | omap_dss_register_driver(&hdmi_driver); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | void hdmi_panel_exit(void) | ||
219 | { | ||
220 | omap_dss_unregister_driver(&hdmi_driver); | ||
221 | |||
222 | } | ||
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c index 172d4e697309..bcd37ec86952 100644 --- a/drivers/video/omap2/dss/manager.c +++ b/drivers/video/omap2/dss/manager.c | |||
@@ -515,6 +515,8 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | |||
515 | 515 | ||
516 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { | 516 | if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) { |
517 | irq = DISPC_IRQ_EVSYNC_ODD; | 517 | irq = DISPC_IRQ_EVSYNC_ODD; |
518 | } else if (mgr->device->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
519 | irq = DISPC_IRQ_EVSYNC_EVEN; | ||
518 | } else { | 520 | } else { |
519 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) | 521 | if (mgr->id == OMAP_DSS_CHANNEL_LCD) |
520 | irq = DISPC_IRQ_VSYNC; | 522 | irq = DISPC_IRQ_VSYNC; |
@@ -536,7 +538,8 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) | |||
536 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 538 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
537 | return 0; | 539 | return 0; |
538 | 540 | ||
539 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 541 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
542 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
540 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 543 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
541 | } else { | 544 | } else { |
542 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 545 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
@@ -613,7 +616,8 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) | |||
613 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 616 | if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
614 | return 0; | 617 | return 0; |
615 | 618 | ||
616 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 619 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
620 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
617 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; | 621 | irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; |
618 | } else { | 622 | } else { |
619 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { | 623 | if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) { |
@@ -1377,6 +1381,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1377 | case OMAP_DISPLAY_TYPE_DBI: | 1381 | case OMAP_DISPLAY_TYPE_DBI: |
1378 | case OMAP_DISPLAY_TYPE_SDI: | 1382 | case OMAP_DISPLAY_TYPE_SDI: |
1379 | case OMAP_DISPLAY_TYPE_VENC: | 1383 | case OMAP_DISPLAY_TYPE_VENC: |
1384 | case OMAP_DISPLAY_TYPE_HDMI: | ||
1380 | default_get_overlay_fifo_thresholds(ovl->id, size, | 1385 | default_get_overlay_fifo_thresholds(ovl->id, size, |
1381 | &oc->burst_size, &oc->fifo_low, | 1386 | &oc->burst_size, &oc->fifo_low, |
1382 | &oc->fifo_high); | 1387 | &oc->fifo_high); |
@@ -1394,7 +1399,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1394 | } | 1399 | } |
1395 | 1400 | ||
1396 | r = 0; | 1401 | r = 0; |
1397 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1402 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
1398 | if (!dss_cache.irq_enabled) { | 1403 | if (!dss_cache.irq_enabled) { |
1399 | u32 mask; | 1404 | u32 mask; |
1400 | 1405 | ||
@@ -1407,7 +1412,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) | |||
1407 | dss_cache.irq_enabled = true; | 1412 | dss_cache.irq_enabled = true; |
1408 | } | 1413 | } |
1409 | configure_dispc(); | 1414 | configure_dispc(); |
1410 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 1415 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
1411 | 1416 | ||
1412 | spin_unlock_irqrestore(&dss_cache.lock, flags); | 1417 | spin_unlock_irqrestore(&dss_cache.lock, flags); |
1413 | 1418 | ||
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c index 456efef03c20..f1aca6d04011 100644 --- a/drivers/video/omap2/dss/overlay.c +++ b/drivers/video/omap2/dss/overlay.c | |||
@@ -490,7 +490,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
490 | 490 | ||
491 | ovl->manager = mgr; | 491 | ovl->manager = mgr; |
492 | 492 | ||
493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 493 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
494 | /* XXX: on manual update display, in auto update mode, a bug happens | 494 | /* XXX: on manual update display, in auto update mode, a bug happens |
495 | * here. When an overlay is first enabled on LCD, then it's disabled, | 495 | * here. When an overlay is first enabled on LCD, then it's disabled, |
496 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT | 496 | * and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT |
@@ -499,7 +499,7 @@ static int omap_dss_set_manager(struct omap_overlay *ovl, | |||
499 | * but I don't understand how or why. */ | 499 | * but I don't understand how or why. */ |
500 | msleep(40); | 500 | msleep(40); |
501 | dispc_set_channel_out(ovl->id, mgr->id); | 501 | dispc_set_channel_out(ovl->id, mgr->id); |
502 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 502 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
503 | 503 | ||
504 | return 0; | 504 | return 0; |
505 | } | 505 | } |
@@ -679,7 +679,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
679 | lcd2_mgr->set_device(lcd2_mgr, dssdev); | 679 | lcd2_mgr->set_device(lcd2_mgr, dssdev); |
680 | mgr = lcd2_mgr; | 680 | mgr = lcd2_mgr; |
681 | } | 681 | } |
682 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC) { | 682 | } else if (dssdev->type != OMAP_DISPLAY_TYPE_VENC |
683 | && dssdev->type != OMAP_DISPLAY_TYPE_HDMI) { | ||
683 | if (!lcd_mgr->device || force) { | 684 | if (!lcd_mgr->device || force) { |
684 | if (lcd_mgr->device) | 685 | if (lcd_mgr->device) |
685 | lcd_mgr->unset_device(lcd_mgr); | 686 | lcd_mgr->unset_device(lcd_mgr); |
@@ -688,7 +689,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force) | |||
688 | } | 689 | } |
689 | } | 690 | } |
690 | 691 | ||
691 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) { | 692 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC |
693 | || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { | ||
692 | if (!tv_mgr->device || force) { | 694 | if (!tv_mgr->device || force) { |
693 | if (tv_mgr->device) | 695 | if (tv_mgr->device) |
694 | tv_mgr->unset_device(tv_mgr); | 696 | tv_mgr->unset_device(tv_mgr); |
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index 10a2ffe02882..5ea17f49c611 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -36,8 +36,6 @@ | |||
36 | #include <plat/display.h> | 36 | #include <plat/display.h> |
37 | #include "dss.h" | 37 | #include "dss.h" |
38 | 38 | ||
39 | #define RFBI_BASE 0x48050800 | ||
40 | |||
41 | struct rfbi_reg { u16 idx; }; | 39 | struct rfbi_reg { u16 idx; }; |
42 | 40 | ||
43 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) | 41 | #define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) |
@@ -100,6 +98,7 @@ static int rfbi_convert_timings(struct rfbi_timings *t); | |||
100 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); | 98 | static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); |
101 | 99 | ||
102 | static struct { | 100 | static struct { |
101 | struct platform_device *pdev; | ||
103 | void __iomem *base; | 102 | void __iomem *base; |
104 | 103 | ||
105 | unsigned long l4_khz; | 104 | unsigned long l4_khz; |
@@ -142,9 +141,9 @@ static inline u32 rfbi_read_reg(const struct rfbi_reg idx) | |||
142 | static void rfbi_enable_clocks(bool enable) | 141 | static void rfbi_enable_clocks(bool enable) |
143 | { | 142 | { |
144 | if (enable) | 143 | if (enable) |
145 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 144 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
146 | else | 145 | else |
147 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 146 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
148 | } | 147 | } |
149 | 148 | ||
150 | void omap_rfbi_write_command(const void *buf, u32 len) | 149 | void omap_rfbi_write_command(const void *buf, u32 len) |
@@ -497,7 +496,7 @@ unsigned long rfbi_get_max_tx_rate(void) | |||
497 | }; | 496 | }; |
498 | 497 | ||
499 | l4_rate = rfbi.l4_khz / 1000; | 498 | l4_rate = rfbi.l4_khz / 1000; |
500 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000; | 499 | dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000; |
501 | 500 | ||
502 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { | 501 | for (i = 0; i < ARRAY_SIZE(ftab); i++) { |
503 | /* Use a window instead of an exact match, to account | 502 | /* Use a window instead of an exact match, to account |
@@ -922,7 +921,7 @@ void rfbi_dump_regs(struct seq_file *s) | |||
922 | { | 921 | { |
923 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) | 922 | #define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) |
924 | 923 | ||
925 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | 924 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
926 | 925 | ||
927 | DUMPREG(RFBI_REVISION); | 926 | DUMPREG(RFBI_REVISION); |
928 | DUMPREG(RFBI_SYSCONFIG); | 927 | DUMPREG(RFBI_SYSCONFIG); |
@@ -953,54 +952,10 @@ void rfbi_dump_regs(struct seq_file *s) | |||
953 | DUMPREG(RFBI_VSYNC_WIDTH); | 952 | DUMPREG(RFBI_VSYNC_WIDTH); |
954 | DUMPREG(RFBI_HSYNC_WIDTH); | 953 | DUMPREG(RFBI_HSYNC_WIDTH); |
955 | 954 | ||
956 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 955 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
957 | #undef DUMPREG | 956 | #undef DUMPREG |
958 | } | 957 | } |
959 | 958 | ||
960 | int rfbi_init(void) | ||
961 | { | ||
962 | u32 rev; | ||
963 | u32 l; | ||
964 | |||
965 | spin_lock_init(&rfbi.cmd_lock); | ||
966 | |||
967 | init_completion(&rfbi.cmd_done); | ||
968 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
969 | atomic_set(&rfbi.cmd_pending, 0); | ||
970 | |||
971 | rfbi.base = ioremap(RFBI_BASE, SZ_256); | ||
972 | if (!rfbi.base) { | ||
973 | DSSERR("can't ioremap RFBI\n"); | ||
974 | return -ENOMEM; | ||
975 | } | ||
976 | |||
977 | rfbi_enable_clocks(1); | ||
978 | |||
979 | msleep(10); | ||
980 | |||
981 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
982 | |||
983 | /* Enable autoidle and smart-idle */ | ||
984 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
985 | l |= (1 << 0) | (2 << 3); | ||
986 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
987 | |||
988 | rev = rfbi_read_reg(RFBI_REVISION); | ||
989 | printk(KERN_INFO "OMAP RFBI rev %d.%d\n", | ||
990 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
991 | |||
992 | rfbi_enable_clocks(0); | ||
993 | |||
994 | return 0; | ||
995 | } | ||
996 | |||
997 | void rfbi_exit(void) | ||
998 | { | ||
999 | DSSDBG("rfbi_exit\n"); | ||
1000 | |||
1001 | iounmap(rfbi.base); | ||
1002 | } | ||
1003 | |||
1004 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) | 959 | int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) |
1005 | { | 960 | { |
1006 | int r; | 961 | int r; |
@@ -1056,3 +1011,74 @@ int rfbi_init_display(struct omap_dss_device *dssdev) | |||
1056 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; | 1011 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; |
1057 | return 0; | 1012 | return 0; |
1058 | } | 1013 | } |
1014 | |||
1015 | /* RFBI HW IP initialisation */ | ||
1016 | static int omap_rfbihw_probe(struct platform_device *pdev) | ||
1017 | { | ||
1018 | u32 rev; | ||
1019 | u32 l; | ||
1020 | struct resource *rfbi_mem; | ||
1021 | |||
1022 | rfbi.pdev = pdev; | ||
1023 | |||
1024 | spin_lock_init(&rfbi.cmd_lock); | ||
1025 | |||
1026 | init_completion(&rfbi.cmd_done); | ||
1027 | atomic_set(&rfbi.cmd_fifo_full, 0); | ||
1028 | atomic_set(&rfbi.cmd_pending, 0); | ||
1029 | |||
1030 | rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); | ||
1031 | if (!rfbi_mem) { | ||
1032 | DSSERR("can't get IORESOURCE_MEM RFBI\n"); | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); | ||
1036 | if (!rfbi.base) { | ||
1037 | DSSERR("can't ioremap RFBI\n"); | ||
1038 | return -ENOMEM; | ||
1039 | } | ||
1040 | |||
1041 | rfbi_enable_clocks(1); | ||
1042 | |||
1043 | msleep(10); | ||
1044 | |||
1045 | rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000; | ||
1046 | |||
1047 | /* Enable autoidle and smart-idle */ | ||
1048 | l = rfbi_read_reg(RFBI_SYSCONFIG); | ||
1049 | l |= (1 << 0) | (2 << 3); | ||
1050 | rfbi_write_reg(RFBI_SYSCONFIG, l); | ||
1051 | |||
1052 | rev = rfbi_read_reg(RFBI_REVISION); | ||
1053 | dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", | ||
1054 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | ||
1055 | |||
1056 | rfbi_enable_clocks(0); | ||
1057 | |||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | static int omap_rfbihw_remove(struct platform_device *pdev) | ||
1062 | { | ||
1063 | iounmap(rfbi.base); | ||
1064 | return 0; | ||
1065 | } | ||
1066 | |||
1067 | static struct platform_driver omap_rfbihw_driver = { | ||
1068 | .probe = omap_rfbihw_probe, | ||
1069 | .remove = omap_rfbihw_remove, | ||
1070 | .driver = { | ||
1071 | .name = "omapdss_rfbi", | ||
1072 | .owner = THIS_MODULE, | ||
1073 | }, | ||
1074 | }; | ||
1075 | |||
1076 | int rfbi_init_platform_driver(void) | ||
1077 | { | ||
1078 | return platform_driver_register(&omap_rfbihw_driver); | ||
1079 | } | ||
1080 | |||
1081 | void rfbi_uninit_platform_driver(void) | ||
1082 | { | ||
1083 | return platform_driver_unregister(&omap_rfbihw_driver); | ||
1084 | } | ||
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index b64adf7dfc88..54a53e648180 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include "dss.h" | 30 | #include "dss.h" |
31 | 31 | ||
32 | static struct { | 32 | static struct { |
33 | bool skip_init; | ||
34 | bool update_enabled; | 33 | bool update_enabled; |
35 | struct regulator *vdds_sdi_reg; | 34 | struct regulator *vdds_sdi_reg; |
36 | } sdi; | 35 | } sdi; |
@@ -68,9 +67,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
68 | if (r) | 67 | if (r) |
69 | goto err1; | 68 | goto err1; |
70 | 69 | ||
71 | /* In case of skip_init sdi_init has already enabled the clocks */ | 70 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK); |
72 | if (!sdi.skip_init) | ||
73 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
74 | 71 | ||
75 | sdi_basic_init(dssdev); | 72 | sdi_basic_init(dssdev); |
76 | 73 | ||
@@ -80,14 +77,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
80 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, | 77 | dispc_set_pol_freq(dssdev->manager->id, dssdev->panel.config, |
81 | dssdev->panel.acbi, dssdev->panel.acb); | 78 | dssdev->panel.acbi, dssdev->panel.acb); |
82 | 79 | ||
83 | if (!sdi.skip_init) { | 80 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, |
84 | r = dss_calc_clock_div(1, t->pixel_clock * 1000, | 81 | &dss_cinfo, &dispc_cinfo); |
85 | &dss_cinfo, &dispc_cinfo); | ||
86 | } else { | ||
87 | r = dss_get_clock_div(&dss_cinfo); | ||
88 | r = dispc_get_clock_div(dssdev->manager->id, &dispc_cinfo); | ||
89 | } | ||
90 | |||
91 | if (r) | 82 | if (r) |
92 | goto err2; | 83 | goto err2; |
93 | 84 | ||
@@ -116,21 +107,17 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
116 | if (r) | 107 | if (r) |
117 | goto err2; | 108 | goto err2; |
118 | 109 | ||
119 | if (!sdi.skip_init) { | 110 | dss_sdi_init(dssdev->phy.sdi.datapairs); |
120 | dss_sdi_init(dssdev->phy.sdi.datapairs); | 111 | r = dss_sdi_enable(); |
121 | r = dss_sdi_enable(); | 112 | if (r) |
122 | if (r) | 113 | goto err1; |
123 | goto err1; | 114 | mdelay(2); |
124 | mdelay(2); | ||
125 | } | ||
126 | 115 | ||
127 | dssdev->manager->enable(dssdev->manager); | 116 | dssdev->manager->enable(dssdev->manager); |
128 | 117 | ||
129 | sdi.skip_init = 0; | ||
130 | |||
131 | return 0; | 118 | return 0; |
132 | err2: | 119 | err2: |
133 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 120 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
134 | regulator_disable(sdi.vdds_sdi_reg); | 121 | regulator_disable(sdi.vdds_sdi_reg); |
135 | err1: | 122 | err1: |
136 | omap_dss_stop_device(dssdev); | 123 | omap_dss_stop_device(dssdev); |
@@ -145,7 +132,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
145 | 132 | ||
146 | dss_sdi_disable(); | 133 | dss_sdi_disable(); |
147 | 134 | ||
148 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); | 135 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK); |
149 | 136 | ||
150 | regulator_disable(sdi.vdds_sdi_reg); | 137 | regulator_disable(sdi.vdds_sdi_reg); |
151 | 138 | ||
@@ -157,25 +144,24 @@ int sdi_init_display(struct omap_dss_device *dssdev) | |||
157 | { | 144 | { |
158 | DSSDBG("SDI init\n"); | 145 | DSSDBG("SDI init\n"); |
159 | 146 | ||
147 | if (sdi.vdds_sdi_reg == NULL) { | ||
148 | struct regulator *vdds_sdi; | ||
149 | |||
150 | vdds_sdi = dss_get_vdds_sdi(); | ||
151 | |||
152 | if (IS_ERR(vdds_sdi)) { | ||
153 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
154 | return PTR_ERR(vdds_sdi); | ||
155 | } | ||
156 | |||
157 | sdi.vdds_sdi_reg = vdds_sdi; | ||
158 | } | ||
159 | |||
160 | return 0; | 160 | return 0; |
161 | } | 161 | } |
162 | 162 | ||
163 | int sdi_init(bool skip_init) | 163 | int sdi_init(void) |
164 | { | 164 | { |
165 | /* we store this for first display enable, then clear it */ | ||
166 | sdi.skip_init = skip_init; | ||
167 | |||
168 | sdi.vdds_sdi_reg = dss_get_vdds_sdi(); | ||
169 | if (IS_ERR(sdi.vdds_sdi_reg)) { | ||
170 | DSSERR("can't get VDDS_SDI regulator\n"); | ||
171 | return PTR_ERR(sdi.vdds_sdi_reg); | ||
172 | } | ||
173 | /* | ||
174 | * Enable clocks already here, otherwise there would be a toggle | ||
175 | * of them until sdi_display_enable is called. | ||
176 | */ | ||
177 | if (skip_init) | ||
178 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); | ||
179 | return 0; | 165 | return 0; |
180 | } | 166 | } |
181 | 167 | ||
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index eff35050e28a..8e35a5bae429 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -39,8 +39,6 @@ | |||
39 | 39 | ||
40 | #include "dss.h" | 40 | #include "dss.h" |
41 | 41 | ||
42 | #define VENC_BASE 0x48050C00 | ||
43 | |||
44 | /* Venc registers */ | 42 | /* Venc registers */ |
45 | #define VENC_REV_ID 0x00 | 43 | #define VENC_REV_ID 0x00 |
46 | #define VENC_STATUS 0x04 | 44 | #define VENC_STATUS 0x04 |
@@ -289,6 +287,7 @@ const struct omap_video_timings omap_dss_ntsc_timings = { | |||
289 | EXPORT_SYMBOL(omap_dss_ntsc_timings); | 287 | EXPORT_SYMBOL(omap_dss_ntsc_timings); |
290 | 288 | ||
291 | static struct { | 289 | static struct { |
290 | struct platform_device *pdev; | ||
292 | void __iomem *base; | 291 | void __iomem *base; |
293 | struct mutex venc_lock; | 292 | struct mutex venc_lock; |
294 | u32 wss_data; | 293 | u32 wss_data; |
@@ -381,11 +380,11 @@ static void venc_reset(void) | |||
381 | static void venc_enable_clocks(int enable) | 380 | static void venc_enable_clocks(int enable) |
382 | { | 381 | { |
383 | if (enable) | 382 | if (enable) |
384 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 383 | dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
385 | DSS_CLK_96M); | 384 | DSS_CLK_VIDFCK); |
386 | else | 385 | else |
387 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_54M | | 386 | dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK | DSS_CLK_TVFCK | |
388 | DSS_CLK_96M); | 387 | DSS_CLK_VIDFCK); |
389 | } | 388 | } |
390 | 389 | ||
391 | static const struct venc_config *venc_timings_to_config( | 390 | static const struct venc_config *venc_timings_to_config( |
@@ -641,50 +640,23 @@ static struct omap_dss_driver venc_driver = { | |||
641 | }; | 640 | }; |
642 | /* driver end */ | 641 | /* driver end */ |
643 | 642 | ||
644 | 643 | int venc_init_display(struct omap_dss_device *dssdev) | |
645 | |||
646 | int venc_init(struct platform_device *pdev) | ||
647 | { | 644 | { |
648 | u8 rev_id; | 645 | DSSDBG("init_display\n"); |
649 | 646 | ||
650 | mutex_init(&venc.venc_lock); | 647 | if (venc.vdda_dac_reg == NULL) { |
648 | struct regulator *vdda_dac; | ||
651 | 649 | ||
652 | venc.wss_data = 0; | 650 | vdda_dac = regulator_get(&venc.pdev->dev, "vdda_dac"); |
653 | 651 | ||
654 | venc.base = ioremap(VENC_BASE, SZ_1K); | 652 | if (IS_ERR(vdda_dac)) { |
655 | if (!venc.base) { | 653 | DSSERR("can't get VDDA_DAC regulator\n"); |
656 | DSSERR("can't ioremap VENC\n"); | 654 | return PTR_ERR(vdda_dac); |
657 | return -ENOMEM; | 655 | } |
658 | } | ||
659 | 656 | ||
660 | venc.vdda_dac_reg = dss_get_vdda_dac(); | 657 | venc.vdda_dac_reg = vdda_dac; |
661 | if (IS_ERR(venc.vdda_dac_reg)) { | ||
662 | iounmap(venc.base); | ||
663 | DSSERR("can't get VDDA_DAC regulator\n"); | ||
664 | return PTR_ERR(venc.vdda_dac_reg); | ||
665 | } | 658 | } |
666 | 659 | ||
667 | venc_enable_clocks(1); | ||
668 | |||
669 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
670 | printk(KERN_INFO "OMAP VENC rev %d\n", rev_id); | ||
671 | |||
672 | venc_enable_clocks(0); | ||
673 | |||
674 | return omap_dss_register_driver(&venc_driver); | ||
675 | } | ||
676 | |||
677 | void venc_exit(void) | ||
678 | { | ||
679 | omap_dss_unregister_driver(&venc_driver); | ||
680 | |||
681 | iounmap(venc.base); | ||
682 | } | ||
683 | |||
684 | int venc_init_display(struct omap_dss_device *dssdev) | ||
685 | { | ||
686 | DSSDBG("init_display\n"); | ||
687 | |||
688 | return 0; | 660 | return 0; |
689 | } | 661 | } |
690 | 662 | ||
@@ -740,3 +712,73 @@ void venc_dump_regs(struct seq_file *s) | |||
740 | 712 | ||
741 | #undef DUMPREG | 713 | #undef DUMPREG |
742 | } | 714 | } |
715 | |||
716 | /* VENC HW IP initialisation */ | ||
717 | static int omap_venchw_probe(struct platform_device *pdev) | ||
718 | { | ||
719 | u8 rev_id; | ||
720 | struct resource *venc_mem; | ||
721 | |||
722 | venc.pdev = pdev; | ||
723 | |||
724 | mutex_init(&venc.venc_lock); | ||
725 | |||
726 | venc.wss_data = 0; | ||
727 | |||
728 | venc_mem = platform_get_resource(venc.pdev, IORESOURCE_MEM, 0); | ||
729 | if (!venc_mem) { | ||
730 | DSSERR("can't get IORESOURCE_MEM VENC\n"); | ||
731 | return -EINVAL; | ||
732 | } | ||
733 | venc.base = ioremap(venc_mem->start, resource_size(venc_mem)); | ||
734 | if (!venc.base) { | ||
735 | DSSERR("can't ioremap VENC\n"); | ||
736 | return -ENOMEM; | ||
737 | } | ||
738 | |||
739 | venc_enable_clocks(1); | ||
740 | |||
741 | rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff); | ||
742 | dev_dbg(&pdev->dev, "OMAP VENC rev %d\n", rev_id); | ||
743 | |||
744 | venc_enable_clocks(0); | ||
745 | |||
746 | return omap_dss_register_driver(&venc_driver); | ||
747 | } | ||
748 | |||
749 | static int omap_venchw_remove(struct platform_device *pdev) | ||
750 | { | ||
751 | if (venc.vdda_dac_reg != NULL) { | ||
752 | regulator_put(venc.vdda_dac_reg); | ||
753 | venc.vdda_dac_reg = NULL; | ||
754 | } | ||
755 | omap_dss_unregister_driver(&venc_driver); | ||
756 | |||
757 | iounmap(venc.base); | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static struct platform_driver omap_venchw_driver = { | ||
762 | .probe = omap_venchw_probe, | ||
763 | .remove = omap_venchw_remove, | ||
764 | .driver = { | ||
765 | .name = "omapdss_venc", | ||
766 | .owner = THIS_MODULE, | ||
767 | }, | ||
768 | }; | ||
769 | |||
770 | int venc_init_platform_driver(void) | ||
771 | { | ||
772 | if (cpu_is_omap44xx()) | ||
773 | return 0; | ||
774 | |||
775 | return platform_driver_register(&omap_venchw_driver); | ||
776 | } | ||
777 | |||
778 | void venc_uninit_platform_driver(void) | ||
779 | { | ||
780 | if (cpu_is_omap44xx()) | ||
781 | return; | ||
782 | |||
783 | return platform_driver_unregister(&omap_venchw_driver); | ||
784 | } | ||
diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/omap2/omapfb/Kconfig index 65149b22cf37..aa33386c81ff 100644 --- a/drivers/video/omap2/omapfb/Kconfig +++ b/drivers/video/omap2/omapfb/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | menuconfig FB_OMAP2 | 1 | menuconfig FB_OMAP2 |
2 | tristate "OMAP2/3 frame buffer support (EXPERIMENTAL)" | 2 | tristate "OMAP2+ frame buffer support (EXPERIMENTAL)" |
3 | depends on FB && OMAP2_DSS | 3 | depends on FB && OMAP2_DSS |
4 | 4 | ||
5 | select OMAP2_VRAM | 5 | select OMAP2_VRAM |
@@ -8,10 +8,10 @@ menuconfig FB_OMAP2 | |||
8 | select FB_CFB_COPYAREA | 8 | select FB_CFB_COPYAREA |
9 | select FB_CFB_IMAGEBLIT | 9 | select FB_CFB_IMAGEBLIT |
10 | help | 10 | help |
11 | Frame buffer driver for OMAP2/3 based boards. | 11 | Frame buffer driver for OMAP2+ based boards. |
12 | 12 | ||
13 | config FB_OMAP2_DEBUG_SUPPORT | 13 | config FB_OMAP2_DEBUG_SUPPORT |
14 | bool "Debug support for OMAP2/3 FB" | 14 | bool "Debug support for OMAP2+ FB" |
15 | default y | 15 | default y |
16 | depends on FB_OMAP2 | 16 | depends on FB_OMAP2 |
17 | help | 17 | help |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 4fdab8e9c496..505ec6672049 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2090,7 +2090,7 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | |||
2090 | { | 2090 | { |
2091 | int r; | 2091 | int r; |
2092 | u8 bpp; | 2092 | u8 bpp; |
2093 | struct omap_video_timings timings; | 2093 | struct omap_video_timings timings, temp_timings; |
2094 | 2094 | ||
2095 | r = omapfb_mode_to_timings(mode_str, &timings, &bpp); | 2095 | r = omapfb_mode_to_timings(mode_str, &timings, &bpp); |
2096 | if (r) | 2096 | if (r) |
@@ -2100,14 +2100,23 @@ static int omapfb_set_def_mode(struct omapfb2_device *fbdev, | |||
2100 | fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; | 2100 | fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp; |
2101 | ++fbdev->num_bpp_overrides; | 2101 | ++fbdev->num_bpp_overrides; |
2102 | 2102 | ||
2103 | if (!display->driver->check_timings || !display->driver->set_timings) | 2103 | if (display->driver->check_timings) { |
2104 | return -EINVAL; | 2104 | r = display->driver->check_timings(display, &timings); |
2105 | if (r) | ||
2106 | return r; | ||
2107 | } else { | ||
2108 | /* If check_timings is not present compare xres and yres */ | ||
2109 | if (display->driver->get_timings) { | ||
2110 | display->driver->get_timings(display, &temp_timings); | ||
2105 | 2111 | ||
2106 | r = display->driver->check_timings(display, &timings); | 2112 | if (temp_timings.x_res != timings.x_res || |
2107 | if (r) | 2113 | temp_timings.y_res != timings.y_res) |
2108 | return r; | 2114 | return -EINVAL; |
2115 | } | ||
2116 | } | ||
2109 | 2117 | ||
2110 | display->driver->set_timings(display, &timings); | 2118 | if (display->driver->set_timings) |
2119 | display->driver->set_timings(display, &timings); | ||
2111 | 2120 | ||
2112 | return 0; | 2121 | return 0; |
2113 | } | 2122 | } |