diff options
Diffstat (limited to 'drivers/video/omap2/dss/sdi.c')
-rw-r--r-- | drivers/video/omap2/dss/sdi.c | 126 |
1 files changed, 103 insertions, 23 deletions
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index f43bfe17b3b6..7760851f6e5d 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/string.h> | ||
28 | 29 | ||
29 | #include <video/omapdss.h> | 30 | #include <video/omapdss.h> |
30 | #include "dss.h" | 31 | #include "dss.h" |
@@ -34,10 +35,16 @@ static struct { | |||
34 | struct regulator *vdds_sdi_reg; | 35 | struct regulator *vdds_sdi_reg; |
35 | 36 | ||
36 | struct dss_lcd_mgr_config mgr_config; | 37 | struct dss_lcd_mgr_config mgr_config; |
38 | struct omap_video_timings timings; | ||
39 | int datapairs; | ||
40 | |||
41 | struct omap_dss_output output; | ||
37 | } sdi; | 42 | } sdi; |
38 | 43 | ||
39 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) | 44 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) |
40 | { | 45 | { |
46 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
47 | |||
41 | sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; | 48 | sdi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; |
42 | 49 | ||
43 | sdi.mgr_config.stallmode = false; | 50 | sdi.mgr_config.stallmode = false; |
@@ -46,19 +53,20 @@ static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) | |||
46 | sdi.mgr_config.video_port_width = 24; | 53 | sdi.mgr_config.video_port_width = 24; |
47 | sdi.mgr_config.lcden_sig_polarity = 1; | 54 | sdi.mgr_config.lcden_sig_polarity = 1; |
48 | 55 | ||
49 | dss_mgr_set_lcd_config(dssdev->manager, &sdi.mgr_config); | 56 | dss_mgr_set_lcd_config(mgr, &sdi.mgr_config); |
50 | } | 57 | } |
51 | 58 | ||
52 | int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | 59 | int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) |
53 | { | 60 | { |
54 | struct omap_video_timings *t = &dssdev->panel.timings; | 61 | struct omap_dss_output *out = dssdev->output; |
62 | struct omap_video_timings *t = &sdi.timings; | ||
55 | struct dss_clock_info dss_cinfo; | 63 | struct dss_clock_info dss_cinfo; |
56 | struct dispc_clock_info dispc_cinfo; | 64 | struct dispc_clock_info dispc_cinfo; |
57 | unsigned long pck; | 65 | unsigned long pck; |
58 | int r; | 66 | int r; |
59 | 67 | ||
60 | if (dssdev->manager == NULL) { | 68 | if (out == NULL || out->manager == NULL) { |
61 | DSSERR("failed to enable display: no manager\n"); | 69 | DSSERR("failed to enable display: no output/manager\n"); |
62 | return -ENODEV; | 70 | return -ENODEV; |
63 | } | 71 | } |
64 | 72 | ||
@@ -77,8 +85,8 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
77 | goto err_get_dispc; | 85 | goto err_get_dispc; |
78 | 86 | ||
79 | /* 15.5.9.1.2 */ | 87 | /* 15.5.9.1.2 */ |
80 | dssdev->panel.timings.data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; | 88 | t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; |
81 | dssdev->panel.timings.sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; | 89 | t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; |
82 | 90 | ||
83 | r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); | 91 | r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); |
84 | if (r) | 92 | if (r) |
@@ -97,7 +105,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
97 | } | 105 | } |
98 | 106 | ||
99 | 107 | ||
100 | dss_mgr_set_timings(dssdev->manager, t); | 108 | dss_mgr_set_timings(out->manager, t); |
101 | 109 | ||
102 | r = dss_set_clock_div(&dss_cinfo); | 110 | r = dss_set_clock_div(&dss_cinfo); |
103 | if (r) | 111 | if (r) |
@@ -116,16 +124,15 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
116 | * need to care about the shadow register mechanism for pck-free. The | 124 | * need to care about the shadow register mechanism for pck-free. The |
117 | * exact reason for this is unknown. | 125 | * exact reason for this is unknown. |
118 | */ | 126 | */ |
119 | dispc_mgr_set_clock_div(dssdev->manager->id, | 127 | dispc_mgr_set_clock_div(out->manager->id, &sdi.mgr_config.clock_info); |
120 | &sdi.mgr_config.clock_info); | ||
121 | 128 | ||
122 | dss_sdi_init(dssdev->phy.sdi.datapairs); | 129 | dss_sdi_init(sdi.datapairs); |
123 | r = dss_sdi_enable(); | 130 | r = dss_sdi_enable(); |
124 | if (r) | 131 | if (r) |
125 | goto err_sdi_enable; | 132 | goto err_sdi_enable; |
126 | mdelay(2); | 133 | mdelay(2); |
127 | 134 | ||
128 | r = dss_mgr_enable(dssdev->manager); | 135 | r = dss_mgr_enable(out->manager); |
129 | if (r) | 136 | if (r) |
130 | goto err_mgr_enable; | 137 | goto err_mgr_enable; |
131 | 138 | ||
@@ -148,7 +155,9 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable); | |||
148 | 155 | ||
149 | void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | 156 | void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) |
150 | { | 157 | { |
151 | dss_mgr_disable(dssdev->manager); | 158 | struct omap_overlay_manager *mgr = dssdev->output->manager; |
159 | |||
160 | dss_mgr_disable(mgr); | ||
152 | 161 | ||
153 | dss_sdi_disable(); | 162 | dss_sdi_disable(); |
154 | 163 | ||
@@ -160,6 +169,19 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) | |||
160 | } | 169 | } |
161 | EXPORT_SYMBOL(omapdss_sdi_display_disable); | 170 | EXPORT_SYMBOL(omapdss_sdi_display_disable); |
162 | 171 | ||
172 | void omapdss_sdi_set_timings(struct omap_dss_device *dssdev, | ||
173 | struct omap_video_timings *timings) | ||
174 | { | ||
175 | sdi.timings = *timings; | ||
176 | } | ||
177 | EXPORT_SYMBOL(omapdss_sdi_set_timings); | ||
178 | |||
179 | void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs) | ||
180 | { | ||
181 | sdi.datapairs = datapairs; | ||
182 | } | ||
183 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); | ||
184 | |||
163 | static int __init sdi_init_display(struct omap_dss_device *dssdev) | 185 | static int __init sdi_init_display(struct omap_dss_device *dssdev) |
164 | { | 186 | { |
165 | DSSDBG("SDI init\n"); | 187 | DSSDBG("SDI init\n"); |
@@ -180,10 +202,14 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev) | |||
180 | return 0; | 202 | return 0; |
181 | } | 203 | } |
182 | 204 | ||
183 | static void __init sdi_probe_pdata(struct platform_device *pdev) | 205 | static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) |
184 | { | 206 | { |
185 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 207 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
186 | int i, r; | 208 | const char *def_disp_name = dss_get_default_display_name(); |
209 | struct omap_dss_device *def_dssdev; | ||
210 | int i; | ||
211 | |||
212 | def_dssdev = NULL; | ||
187 | 213 | ||
188 | for (i = 0; i < pdata->num_devices; ++i) { | 214 | for (i = 0; i < pdata->num_devices; ++i) { |
189 | struct omap_dss_device *dssdev = pdata->devices[i]; | 215 | struct omap_dss_device *dssdev = pdata->devices[i]; |
@@ -191,21 +217,73 @@ static void __init sdi_probe_pdata(struct platform_device *pdev) | |||
191 | if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) | 217 | if (dssdev->type != OMAP_DISPLAY_TYPE_SDI) |
192 | continue; | 218 | continue; |
193 | 219 | ||
194 | r = sdi_init_display(dssdev); | 220 | if (def_dssdev == NULL) |
195 | if (r) { | 221 | def_dssdev = dssdev; |
196 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 222 | |
197 | continue; | 223 | if (def_disp_name != NULL && |
224 | strcmp(dssdev->name, def_disp_name) == 0) { | ||
225 | def_dssdev = dssdev; | ||
226 | break; | ||
198 | } | 227 | } |
228 | } | ||
229 | |||
230 | return def_dssdev; | ||
231 | } | ||
232 | |||
233 | static void __init sdi_probe_pdata(struct platform_device *sdidev) | ||
234 | { | ||
235 | struct omap_dss_device *plat_dssdev; | ||
236 | struct omap_dss_device *dssdev; | ||
237 | int r; | ||
238 | |||
239 | plat_dssdev = sdi_find_dssdev(sdidev); | ||
199 | 240 | ||
200 | r = omap_dss_register_device(dssdev, &pdev->dev, i); | 241 | if (!plat_dssdev) |
201 | if (r) | 242 | return; |
202 | DSSERR("device %s register failed: %d\n", | 243 | |
203 | dssdev->name, r); | 244 | dssdev = dss_alloc_and_init_device(&sdidev->dev); |
245 | if (!dssdev) | ||
246 | return; | ||
247 | |||
248 | dss_copy_device_pdata(dssdev, plat_dssdev); | ||
249 | |||
250 | r = sdi_init_display(dssdev); | ||
251 | if (r) { | ||
252 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | ||
253 | dss_put_device(dssdev); | ||
254 | return; | ||
204 | } | 255 | } |
256 | |||
257 | r = dss_add_device(dssdev); | ||
258 | if (r) { | ||
259 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | ||
260 | dss_put_device(dssdev); | ||
261 | return; | ||
262 | } | ||
263 | } | ||
264 | |||
265 | static void __init sdi_init_output(struct platform_device *pdev) | ||
266 | { | ||
267 | struct omap_dss_output *out = &sdi.output; | ||
268 | |||
269 | out->pdev = pdev; | ||
270 | out->id = OMAP_DSS_OUTPUT_SDI; | ||
271 | out->type = OMAP_DISPLAY_TYPE_SDI; | ||
272 | |||
273 | dss_register_output(out); | ||
274 | } | ||
275 | |||
276 | static void __exit sdi_uninit_output(struct platform_device *pdev) | ||
277 | { | ||
278 | struct omap_dss_output *out = &sdi.output; | ||
279 | |||
280 | dss_unregister_output(out); | ||
205 | } | 281 | } |
206 | 282 | ||
207 | static int __init omap_sdi_probe(struct platform_device *pdev) | 283 | static int __init omap_sdi_probe(struct platform_device *pdev) |
208 | { | 284 | { |
285 | sdi_init_output(pdev); | ||
286 | |||
209 | sdi_probe_pdata(pdev); | 287 | sdi_probe_pdata(pdev); |
210 | 288 | ||
211 | return 0; | 289 | return 0; |
@@ -213,7 +291,9 @@ static int __init omap_sdi_probe(struct platform_device *pdev) | |||
213 | 291 | ||
214 | static int __exit omap_sdi_remove(struct platform_device *pdev) | 292 | static int __exit omap_sdi_remove(struct platform_device *pdev) |
215 | { | 293 | { |
216 | omap_dss_unregister_child_devices(&pdev->dev); | 294 | dss_unregister_child_devices(&pdev->dev); |
295 | |||
296 | sdi_uninit_output(pdev); | ||
217 | 297 | ||
218 | return 0; | 298 | return 0; |
219 | } | 299 | } |