diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-02-04 05:44:11 -0500 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2015-02-04 05:44:11 -0500 |
commit | d6c2152b3efd73be265f426b5a1bb50ec436d999 (patch) | |
tree | f35b2a9b40c82028a4a2ecd4593d592431db8fc2 /drivers/video | |
parent | ee06bd155b081a1895f995ec2777094c7e746152 (diff) | |
parent | 811fbb1f580ca024a0af603dfaef08a4d1dcb5ef (diff) |
Merge branches '3.20/fbdev' and '3.20/omapdss' into for-next
Merge fbdev topic branches
Diffstat (limited to 'drivers/video')
19 files changed, 855 insertions, 60 deletions
diff --git a/drivers/video/fbdev/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/displays-new/Kconfig index e6cfc38160d3..574710141a61 100644 --- a/drivers/video/fbdev/omap2/displays-new/Kconfig +++ b/drivers/video/fbdev/omap2/displays-new/Kconfig | |||
@@ -1,6 +1,12 @@ | |||
1 | menu "OMAP Display Device Drivers (new device model)" | 1 | menu "OMAP Display Device Drivers (new device model)" |
2 | depends on OMAP2_DSS | 2 | depends on OMAP2_DSS |
3 | 3 | ||
4 | config DISPLAY_ENCODER_OPA362 | ||
5 | tristate "OPA362 external analog amplifier" | ||
6 | help | ||
7 | Driver for OPA362 external analog TV amplifier controlled | ||
8 | through a GPIO. | ||
9 | |||
4 | config DISPLAY_ENCODER_TFP410 | 10 | config DISPLAY_ENCODER_TFP410 |
5 | tristate "TFP410 DPI to DVI Encoder" | 11 | tristate "TFP410 DPI to DVI Encoder" |
6 | help | 12 | help |
diff --git a/drivers/video/fbdev/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile index 0323a8a1c682..9aa176bfbf2e 100644 --- a/drivers/video/fbdev/omap2/displays-new/Makefile +++ b/drivers/video/fbdev/omap2/displays-new/Makefile | |||
@@ -1,3 +1,4 @@ | |||
1 | obj-$(CONFIG_DISPLAY_ENCODER_OPA362) += encoder-opa362.o | ||
1 | obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o | 2 | obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o |
2 | obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o | 3 | obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o |
3 | obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o | 4 | obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o |
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c index 9a2b5ce58545..8511c648a15c 100644 --- a/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c +++ b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c | |||
@@ -208,7 +208,7 @@ static int tvc_probe_pdata(struct platform_device *pdev) | |||
208 | ddata->in = in; | 208 | ddata->in = in; |
209 | 209 | ||
210 | ddata->connector_type = pdata->connector_type; | 210 | ddata->connector_type = pdata->connector_type; |
211 | ddata->invert_polarity = ddata->invert_polarity; | 211 | ddata->invert_polarity = pdata->invert_polarity; |
212 | 212 | ||
213 | dssdev = &ddata->dssdev; | 213 | dssdev = &ddata->dssdev; |
214 | dssdev->name = pdata->name; | 214 | dssdev->name = pdata->name; |
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c b/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c new file mode 100644 index 000000000000..84a6b3367124 --- /dev/null +++ b/drivers/video/fbdev/omap2/displays-new/encoder-opa362.c | |||
@@ -0,0 +1,285 @@ | |||
1 | /* | ||
2 | * OPA362 analog video amplifier with output/power control | ||
3 | * | ||
4 | * Copyright (C) 2014 Golden Delicious Computers | ||
5 | * Author: H. Nikolaus Schaller <hns@goldelico.com> | ||
6 | * | ||
7 | * based on encoder-tfp410 | ||
8 | * | ||
9 | * Copyright (C) 2013 Texas Instruments | ||
10 | * Author: Tomi Valkeinen <tomi.valkeinen@ti.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License version 2 as published by | ||
14 | * the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/of_gpio.h> | ||
22 | |||
23 | #include <video/omapdss.h> | ||
24 | |||
25 | struct panel_drv_data { | ||
26 | struct omap_dss_device dssdev; | ||
27 | struct omap_dss_device *in; | ||
28 | |||
29 | struct gpio_desc *enable_gpio; | ||
30 | |||
31 | struct omap_video_timings timings; | ||
32 | }; | ||
33 | |||
34 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) | ||
35 | |||
36 | static int opa362_connect(struct omap_dss_device *dssdev, | ||
37 | struct omap_dss_device *dst) | ||
38 | { | ||
39 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
40 | struct omap_dss_device *in = ddata->in; | ||
41 | int r; | ||
42 | |||
43 | dev_dbg(dssdev->dev, "connect\n"); | ||
44 | |||
45 | if (omapdss_device_is_connected(dssdev)) | ||
46 | return -EBUSY; | ||
47 | |||
48 | r = in->ops.atv->connect(in, dssdev); | ||
49 | if (r) | ||
50 | return r; | ||
51 | |||
52 | dst->src = dssdev; | ||
53 | dssdev->dst = dst; | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static void opa362_disconnect(struct omap_dss_device *dssdev, | ||
59 | struct omap_dss_device *dst) | ||
60 | { | ||
61 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
62 | struct omap_dss_device *in = ddata->in; | ||
63 | |||
64 | dev_dbg(dssdev->dev, "disconnect\n"); | ||
65 | |||
66 | WARN_ON(!omapdss_device_is_connected(dssdev)); | ||
67 | if (!omapdss_device_is_connected(dssdev)) | ||
68 | return; | ||
69 | |||
70 | WARN_ON(dst != dssdev->dst); | ||
71 | if (dst != dssdev->dst) | ||
72 | return; | ||
73 | |||
74 | dst->src = NULL; | ||
75 | dssdev->dst = NULL; | ||
76 | |||
77 | in->ops.atv->disconnect(in, &ddata->dssdev); | ||
78 | } | ||
79 | |||
80 | static int opa362_enable(struct omap_dss_device *dssdev) | ||
81 | { | ||
82 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
83 | struct omap_dss_device *in = ddata->in; | ||
84 | int r; | ||
85 | |||
86 | dev_dbg(dssdev->dev, "enable\n"); | ||
87 | |||
88 | if (!omapdss_device_is_connected(dssdev)) | ||
89 | return -ENODEV; | ||
90 | |||
91 | if (omapdss_device_is_enabled(dssdev)) | ||
92 | return 0; | ||
93 | |||
94 | in->ops.atv->set_timings(in, &ddata->timings); | ||
95 | |||
96 | r = in->ops.atv->enable(in); | ||
97 | if (r) | ||
98 | return r; | ||
99 | |||
100 | if (ddata->enable_gpio) | ||
101 | gpiod_set_value_cansleep(ddata->enable_gpio, 1); | ||
102 | |||
103 | dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; | ||
104 | |||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void opa362_disable(struct omap_dss_device *dssdev) | ||
109 | { | ||
110 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
111 | struct omap_dss_device *in = ddata->in; | ||
112 | |||
113 | dev_dbg(dssdev->dev, "disable\n"); | ||
114 | |||
115 | if (!omapdss_device_is_enabled(dssdev)) | ||
116 | return; | ||
117 | |||
118 | if (ddata->enable_gpio) | ||
119 | gpiod_set_value_cansleep(ddata->enable_gpio, 0); | ||
120 | |||
121 | in->ops.atv->disable(in); | ||
122 | |||
123 | dssdev->state = OMAP_DSS_DISPLAY_DISABLED; | ||
124 | } | ||
125 | |||
126 | static void opa362_set_timings(struct omap_dss_device *dssdev, | ||
127 | struct omap_video_timings *timings) | ||
128 | { | ||
129 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
130 | struct omap_dss_device *in = ddata->in; | ||
131 | |||
132 | dev_dbg(dssdev->dev, "set_timings\n"); | ||
133 | |||
134 | ddata->timings = *timings; | ||
135 | dssdev->panel.timings = *timings; | ||
136 | |||
137 | in->ops.atv->set_timings(in, timings); | ||
138 | } | ||
139 | |||
140 | static void opa362_get_timings(struct omap_dss_device *dssdev, | ||
141 | struct omap_video_timings *timings) | ||
142 | { | ||
143 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
144 | |||
145 | dev_dbg(dssdev->dev, "get_timings\n"); | ||
146 | |||
147 | *timings = ddata->timings; | ||
148 | } | ||
149 | |||
150 | static int opa362_check_timings(struct omap_dss_device *dssdev, | ||
151 | struct omap_video_timings *timings) | ||
152 | { | ||
153 | struct panel_drv_data *ddata = to_panel_data(dssdev); | ||
154 | struct omap_dss_device *in = ddata->in; | ||
155 | |||
156 | dev_dbg(dssdev->dev, "check_timings\n"); | ||
157 | |||
158 | return in->ops.atv->check_timings(in, timings); | ||
159 | } | ||
160 | |||
161 | static void opa362_set_type(struct omap_dss_device *dssdev, | ||
162 | enum omap_dss_venc_type type) | ||
163 | { | ||
164 | /* we can only drive a COMPOSITE output */ | ||
165 | WARN_ON(type != OMAP_DSS_VENC_TYPE_COMPOSITE); | ||
166 | |||
167 | } | ||
168 | |||
169 | static const struct omapdss_atv_ops opa362_atv_ops = { | ||
170 | .connect = opa362_connect, | ||
171 | .disconnect = opa362_disconnect, | ||
172 | |||
173 | .enable = opa362_enable, | ||
174 | .disable = opa362_disable, | ||
175 | |||
176 | .check_timings = opa362_check_timings, | ||
177 | .set_timings = opa362_set_timings, | ||
178 | .get_timings = opa362_get_timings, | ||
179 | |||
180 | .set_type = opa362_set_type, | ||
181 | }; | ||
182 | |||
183 | static int opa362_probe(struct platform_device *pdev) | ||
184 | { | ||
185 | struct device_node *node = pdev->dev.of_node; | ||
186 | struct panel_drv_data *ddata; | ||
187 | struct omap_dss_device *dssdev, *in; | ||
188 | struct gpio_desc *gpio; | ||
189 | int r; | ||
190 | |||
191 | dev_dbg(&pdev->dev, "probe\n"); | ||
192 | |||
193 | if (node == NULL) { | ||
194 | dev_err(&pdev->dev, "Unable to find device tree\n"); | ||
195 | return -EINVAL; | ||
196 | } | ||
197 | |||
198 | ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL); | ||
199 | if (!ddata) | ||
200 | return -ENOMEM; | ||
201 | |||
202 | platform_set_drvdata(pdev, ddata); | ||
203 | |||
204 | gpio = devm_gpiod_get(&pdev->dev, "enable"); | ||
205 | if (IS_ERR(gpio)) { | ||
206 | if (PTR_ERR(gpio) != -ENOENT) | ||
207 | return PTR_ERR(gpio); | ||
208 | |||
209 | gpio = NULL; | ||
210 | } else { | ||
211 | gpiod_direction_output(gpio, 0); | ||
212 | } | ||
213 | |||
214 | ddata->enable_gpio = gpio; | ||
215 | |||
216 | in = omapdss_of_find_source_for_first_ep(node); | ||
217 | if (IS_ERR(in)) { | ||
218 | dev_err(&pdev->dev, "failed to find video source\n"); | ||
219 | return PTR_ERR(in); | ||
220 | } | ||
221 | |||
222 | ddata->in = in; | ||
223 | |||
224 | dssdev = &ddata->dssdev; | ||
225 | dssdev->ops.atv = &opa362_atv_ops; | ||
226 | dssdev->dev = &pdev->dev; | ||
227 | dssdev->type = OMAP_DISPLAY_TYPE_VENC; | ||
228 | dssdev->output_type = OMAP_DISPLAY_TYPE_VENC; | ||
229 | dssdev->owner = THIS_MODULE; | ||
230 | |||
231 | r = omapdss_register_output(dssdev); | ||
232 | if (r) { | ||
233 | dev_err(&pdev->dev, "Failed to register output\n"); | ||
234 | goto err_reg; | ||
235 | } | ||
236 | |||
237 | return 0; | ||
238 | err_reg: | ||
239 | omap_dss_put_device(ddata->in); | ||
240 | return r; | ||
241 | } | ||
242 | |||
243 | static int __exit opa362_remove(struct platform_device *pdev) | ||
244 | { | ||
245 | struct panel_drv_data *ddata = platform_get_drvdata(pdev); | ||
246 | struct omap_dss_device *dssdev = &ddata->dssdev; | ||
247 | struct omap_dss_device *in = ddata->in; | ||
248 | |||
249 | omapdss_unregister_output(&ddata->dssdev); | ||
250 | |||
251 | WARN_ON(omapdss_device_is_enabled(dssdev)); | ||
252 | if (omapdss_device_is_enabled(dssdev)) | ||
253 | opa362_disable(dssdev); | ||
254 | |||
255 | WARN_ON(omapdss_device_is_connected(dssdev)); | ||
256 | if (omapdss_device_is_connected(dssdev)) | ||
257 | opa362_disconnect(dssdev, dssdev->dst); | ||
258 | |||
259 | omap_dss_put_device(in); | ||
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static const struct of_device_id opa362_of_match[] = { | ||
265 | { .compatible = "omapdss,ti,opa362", }, | ||
266 | {}, | ||
267 | }; | ||
268 | MODULE_DEVICE_TABLE(of, opa362_of_match); | ||
269 | |||
270 | static struct platform_driver opa362_driver = { | ||
271 | .probe = opa362_probe, | ||
272 | .remove = __exit_p(opa362_remove), | ||
273 | .driver = { | ||
274 | .name = "amplifier-opa362", | ||
275 | .owner = THIS_MODULE, | ||
276 | .of_match_table = opa362_of_match, | ||
277 | .suppress_bind_attrs = true, | ||
278 | }, | ||
279 | }; | ||
280 | |||
281 | module_platform_driver(opa362_driver); | ||
282 | |||
283 | MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>"); | ||
284 | MODULE_DESCRIPTION("OPA362 analog video amplifier with output/power control"); | ||
285 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c index 7f3e11b16c86..990af6baeb0f 100644 --- a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c +++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c | |||
@@ -29,33 +29,10 @@ struct panel_drv_data { | |||
29 | int hpd_gpio; | 29 | int hpd_gpio; |
30 | 30 | ||
31 | struct omap_video_timings timings; | 31 | struct omap_video_timings timings; |
32 | |||
33 | struct completion hpd_completion; | ||
34 | }; | 32 | }; |
35 | 33 | ||
36 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) | 34 | #define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) |
37 | 35 | ||
38 | static irqreturn_t tpd_hpd_irq_handler(int irq, void *data) | ||
39 | { | ||
40 | struct panel_drv_data *ddata = data; | ||
41 | bool hpd; | ||
42 | |||
43 | hpd = gpio_get_value_cansleep(ddata->hpd_gpio); | ||
44 | |||
45 | dev_dbg(ddata->dssdev.dev, "hpd %d\n", hpd); | ||
46 | |||
47 | if (gpio_is_valid(ddata->ls_oe_gpio)) { | ||
48 | if (hpd) | ||
49 | gpio_set_value_cansleep(ddata->ls_oe_gpio, 1); | ||
50 | else | ||
51 | gpio_set_value_cansleep(ddata->ls_oe_gpio, 0); | ||
52 | } | ||
53 | |||
54 | complete_all(&ddata->hpd_completion); | ||
55 | |||
56 | return IRQ_HANDLED; | ||
57 | } | ||
58 | |||
59 | static int tpd_connect(struct omap_dss_device *dssdev, | 36 | static int tpd_connect(struct omap_dss_device *dssdev, |
60 | struct omap_dss_device *dst) | 37 | struct omap_dss_device *dst) |
61 | { | 38 | { |
@@ -70,23 +47,10 @@ static int tpd_connect(struct omap_dss_device *dssdev, | |||
70 | dst->src = dssdev; | 47 | dst->src = dssdev; |
71 | dssdev->dst = dst; | 48 | dssdev->dst = dst; |
72 | 49 | ||
73 | reinit_completion(&ddata->hpd_completion); | ||
74 | |||
75 | gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); | 50 | gpio_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); |
76 | /* DC-DC converter needs at max 300us to get to 90% of 5V */ | 51 | /* DC-DC converter needs at max 300us to get to 90% of 5V */ |
77 | udelay(300); | 52 | udelay(300); |
78 | 53 | ||
79 | /* | ||
80 | * If there's a cable connected, wait for the hpd irq to trigger, | ||
81 | * which turns on the level shifters. | ||
82 | */ | ||
83 | if (gpio_get_value_cansleep(ddata->hpd_gpio)) { | ||
84 | unsigned long to; | ||
85 | to = wait_for_completion_timeout(&ddata->hpd_completion, | ||
86 | msecs_to_jiffies(250)); | ||
87 | WARN_ON_ONCE(to == 0); | ||
88 | } | ||
89 | |||
90 | return 0; | 54 | return 0; |
91 | } | 55 | } |
92 | 56 | ||
@@ -179,11 +143,20 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, | |||
179 | { | 143 | { |
180 | struct panel_drv_data *ddata = to_panel_data(dssdev); | 144 | struct panel_drv_data *ddata = to_panel_data(dssdev); |
181 | struct omap_dss_device *in = ddata->in; | 145 | struct omap_dss_device *in = ddata->in; |
146 | int r; | ||
182 | 147 | ||
183 | if (!gpio_get_value_cansleep(ddata->hpd_gpio)) | 148 | if (!gpio_get_value_cansleep(ddata->hpd_gpio)) |
184 | return -ENODEV; | 149 | return -ENODEV; |
185 | 150 | ||
186 | return in->ops.hdmi->read_edid(in, edid, len); | 151 | if (gpio_is_valid(ddata->ls_oe_gpio)) |
152 | gpio_set_value_cansleep(ddata->ls_oe_gpio, 1); | ||
153 | |||
154 | r = in->ops.hdmi->read_edid(in, edid, len); | ||
155 | |||
156 | if (gpio_is_valid(ddata->ls_oe_gpio)) | ||
157 | gpio_set_value_cansleep(ddata->ls_oe_gpio, 0); | ||
158 | |||
159 | return r; | ||
187 | } | 160 | } |
188 | 161 | ||
189 | static bool tpd_detect(struct omap_dss_device *dssdev) | 162 | static bool tpd_detect(struct omap_dss_device *dssdev) |
@@ -309,8 +282,6 @@ static int tpd_probe(struct platform_device *pdev) | |||
309 | 282 | ||
310 | platform_set_drvdata(pdev, ddata); | 283 | platform_set_drvdata(pdev, ddata); |
311 | 284 | ||
312 | init_completion(&ddata->hpd_completion); | ||
313 | |||
314 | if (dev_get_platdata(&pdev->dev)) { | 285 | if (dev_get_platdata(&pdev->dev)) { |
315 | r = tpd_probe_pdata(pdev); | 286 | r = tpd_probe_pdata(pdev); |
316 | if (r) | 287 | if (r) |
@@ -340,13 +311,6 @@ static int tpd_probe(struct platform_device *pdev) | |||
340 | if (r) | 311 | if (r) |
341 | goto err_gpio; | 312 | goto err_gpio; |
342 | 313 | ||
343 | r = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(ddata->hpd_gpio), | ||
344 | NULL, tpd_hpd_irq_handler, | ||
345 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | | ||
346 | IRQF_ONESHOT, "hpd", ddata); | ||
347 | if (r) | ||
348 | goto err_irq; | ||
349 | |||
350 | dssdev = &ddata->dssdev; | 314 | dssdev = &ddata->dssdev; |
351 | dssdev->ops.hdmi = &tpd_hdmi_ops; | 315 | dssdev->ops.hdmi = &tpd_hdmi_ops; |
352 | dssdev->dev = &pdev->dev; | 316 | dssdev->dev = &pdev->dev; |
@@ -365,7 +329,6 @@ static int tpd_probe(struct platform_device *pdev) | |||
365 | 329 | ||
366 | return 0; | 330 | return 0; |
367 | err_reg: | 331 | err_reg: |
368 | err_irq: | ||
369 | err_gpio: | 332 | err_gpio: |
370 | omap_dss_put_device(ddata->in); | 333 | omap_dss_put_device(ddata->in); |
371 | return r; | 334 | return r; |
diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile index 2ea9d382354c..b5136d3d4b77 100644 --- a/drivers/video/fbdev/omap2/dss/Makefile +++ b/drivers/video/fbdev/omap2/dss/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o | |||
2 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 2 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
3 | # Core DSS files | 3 | # Core DSS files |
4 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ | 4 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ |
5 | output.o dss-of.o pll.o | 5 | output.o dss-of.o pll.o video-pll.o |
6 | # DSS compat layer files | 6 | # DSS compat layer files |
7 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ | 7 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ |
8 | dispc-compat.o display-sysfs.o | 8 | dispc-compat.o display-sysfs.o |
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 9850d9ef9a9d..31b743c70272 100644 --- a/drivers/video/fbdev/omap2/dss/dispc.c +++ b/drivers/video/fbdev/omap2/dss/dispc.c | |||
@@ -36,6 +36,9 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/pm_runtime.h> | 37 | #include <linux/pm_runtime.h> |
38 | #include <linux/sizes.h> | 38 | #include <linux/sizes.h> |
39 | #include <linux/mfd/syscon.h> | ||
40 | #include <linux/regmap.h> | ||
41 | #include <linux/of.h> | ||
39 | 42 | ||
40 | #include <video/omapdss.h> | 43 | #include <video/omapdss.h> |
41 | 44 | ||
@@ -117,6 +120,9 @@ static struct { | |||
117 | const struct dispc_features *feat; | 120 | const struct dispc_features *feat; |
118 | 121 | ||
119 | bool is_enabled; | 122 | bool is_enabled; |
123 | |||
124 | struct regmap *syscon_pol; | ||
125 | u32 syscon_pol_offset; | ||
120 | } dispc; | 126 | } dispc; |
121 | 127 | ||
122 | enum omap_color_component { | 128 | enum omap_color_component { |
@@ -2958,6 +2964,25 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw, | |||
2958 | FLD_VAL(vsync_level, 12, 12); | 2964 | FLD_VAL(vsync_level, 12, 12); |
2959 | 2965 | ||
2960 | dispc_write_reg(DISPC_POL_FREQ(channel), l); | 2966 | dispc_write_reg(DISPC_POL_FREQ(channel), l); |
2967 | |||
2968 | if (dispc.syscon_pol) { | ||
2969 | const int shifts[] = { | ||
2970 | [OMAP_DSS_CHANNEL_LCD] = 0, | ||
2971 | [OMAP_DSS_CHANNEL_LCD2] = 1, | ||
2972 | [OMAP_DSS_CHANNEL_LCD3] = 2, | ||
2973 | }; | ||
2974 | |||
2975 | u32 mask, val; | ||
2976 | |||
2977 | mask = (1 << 0) | (1 << 3) | (1 << 6); | ||
2978 | val = (rf << 0) | (ipc << 3) | (onoff << 6); | ||
2979 | |||
2980 | mask <<= 16 + shifts[channel]; | ||
2981 | val <<= 16 + shifts[channel]; | ||
2982 | |||
2983 | regmap_update_bits(dispc.syscon_pol, dispc.syscon_pol_offset, | ||
2984 | mask, val); | ||
2985 | } | ||
2961 | } | 2986 | } |
2962 | 2987 | ||
2963 | /* change name to mode? */ | 2988 | /* change name to mode? */ |
@@ -3037,10 +3062,16 @@ unsigned long dispc_fclk_rate(void) | |||
3037 | break; | 3062 | break; |
3038 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 3063 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
3039 | pll = dss_pll_find("dsi0"); | 3064 | pll = dss_pll_find("dsi0"); |
3065 | if (!pll) | ||
3066 | pll = dss_pll_find("video0"); | ||
3067 | |||
3040 | r = pll->cinfo.clkout[0]; | 3068 | r = pll->cinfo.clkout[0]; |
3041 | break; | 3069 | break; |
3042 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | 3070 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: |
3043 | pll = dss_pll_find("dsi1"); | 3071 | pll = dss_pll_find("dsi1"); |
3072 | if (!pll) | ||
3073 | pll = dss_pll_find("video1"); | ||
3074 | |||
3044 | r = pll->cinfo.clkout[0]; | 3075 | r = pll->cinfo.clkout[0]; |
3045 | break; | 3076 | break; |
3046 | default: | 3077 | default: |
@@ -3069,10 +3100,16 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) | |||
3069 | break; | 3100 | break; |
3070 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: | 3101 | case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: |
3071 | pll = dss_pll_find("dsi0"); | 3102 | pll = dss_pll_find("dsi0"); |
3103 | if (!pll) | ||
3104 | pll = dss_pll_find("video0"); | ||
3105 | |||
3072 | r = pll->cinfo.clkout[0]; | 3106 | r = pll->cinfo.clkout[0]; |
3073 | break; | 3107 | break; |
3074 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: | 3108 | case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: |
3075 | pll = dss_pll_find("dsi1"); | 3109 | pll = dss_pll_find("dsi1"); |
3110 | if (!pll) | ||
3111 | pll = dss_pll_find("video1"); | ||
3112 | |||
3076 | r = pll->cinfo.clkout[0]; | 3113 | r = pll->cinfo.clkout[0]; |
3077 | break; | 3114 | break; |
3078 | default: | 3115 | default: |
@@ -3668,6 +3705,7 @@ static int __init dispc_init_features(struct platform_device *pdev) | |||
3668 | break; | 3705 | break; |
3669 | 3706 | ||
3670 | case OMAPDSS_VER_OMAP5: | 3707 | case OMAPDSS_VER_OMAP5: |
3708 | case OMAPDSS_VER_DRA7xx: | ||
3671 | src = &omap54xx_dispc_feats; | 3709 | src = &omap54xx_dispc_feats; |
3672 | break; | 3710 | break; |
3673 | 3711 | ||
@@ -3728,6 +3766,7 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
3728 | u32 rev; | 3766 | u32 rev; |
3729 | int r = 0; | 3767 | int r = 0; |
3730 | struct resource *dispc_mem; | 3768 | struct resource *dispc_mem; |
3769 | struct device_node *np = pdev->dev.of_node; | ||
3731 | 3770 | ||
3732 | dispc.pdev = pdev; | 3771 | dispc.pdev = pdev; |
3733 | 3772 | ||
@@ -3754,6 +3793,20 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) | |||
3754 | return -ENODEV; | 3793 | return -ENODEV; |
3755 | } | 3794 | } |
3756 | 3795 | ||
3796 | if (np && of_property_read_bool(np, "syscon-pol")) { | ||
3797 | dispc.syscon_pol = syscon_regmap_lookup_by_phandle(np, "syscon-pol"); | ||
3798 | if (IS_ERR(dispc.syscon_pol)) { | ||
3799 | dev_err(&pdev->dev, "failed to get syscon-pol regmap\n"); | ||
3800 | return PTR_ERR(dispc.syscon_pol); | ||
3801 | } | ||
3802 | |||
3803 | if (of_property_read_u32_index(np, "syscon-pol", 1, | ||
3804 | &dispc.syscon_pol_offset)) { | ||
3805 | dev_err(&pdev->dev, "failed to get syscon-pol offset\n"); | ||
3806 | return -EINVAL; | ||
3807 | } | ||
3808 | } | ||
3809 | |||
3757 | pm_runtime_enable(&pdev->dev); | 3810 | pm_runtime_enable(&pdev->dev); |
3758 | 3811 | ||
3759 | r = dispc_runtime_get(); | 3812 | r = dispc_runtime_get(); |
@@ -3832,6 +3885,7 @@ static const struct of_device_id dispc_of_match[] = { | |||
3832 | { .compatible = "ti,omap3-dispc", }, | 3885 | { .compatible = "ti,omap3-dispc", }, |
3833 | { .compatible = "ti,omap4-dispc", }, | 3886 | { .compatible = "ti,omap4-dispc", }, |
3834 | { .compatible = "ti,omap5-dispc", }, | 3887 | { .compatible = "ti,omap5-dispc", }, |
3888 | { .compatible = "ti,dra7-dispc", }, | ||
3835 | {}, | 3889 | {}, |
3836 | }; | 3890 | }; |
3837 | 3891 | ||
diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c index 9a2f8c3b102d..f83e7b030249 100644 --- a/drivers/video/fbdev/omap2/dss/dpi.c +++ b/drivers/video/fbdev/omap2/dss/dpi.c | |||
@@ -106,6 +106,17 @@ static struct dss_pll *dpi_get_pll(enum omap_channel channel) | |||
106 | return NULL; | 106 | return NULL; |
107 | } | 107 | } |
108 | 108 | ||
109 | case OMAPDSS_VER_DRA7xx: | ||
110 | switch (channel) { | ||
111 | case OMAP_DSS_CHANNEL_LCD: | ||
112 | case OMAP_DSS_CHANNEL_LCD2: | ||
113 | return dss_pll_find("video0"); | ||
114 | case OMAP_DSS_CHANNEL_LCD3: | ||
115 | return dss_pll_find("video1"); | ||
116 | default: | ||
117 | return NULL; | ||
118 | } | ||
119 | |||
109 | default: | 120 | default: |
110 | return NULL; | 121 | return NULL; |
111 | } | 122 | } |
@@ -590,6 +601,10 @@ static void dpi_init_pll(struct dpi_data *dpi) | |||
590 | if (!pll) | 601 | if (!pll) |
591 | return; | 602 | return; |
592 | 603 | ||
604 | /* On DRA7 we need to set a mux to use the PLL */ | ||
605 | if (omapdss_get_version() == OMAPDSS_VER_DRA7xx) | ||
606 | dss_ctrl_pll_set_control_mux(pll->id, dpi->output.dispc_channel); | ||
607 | |||
593 | if (dpi_verify_dsi_pll(pll)) { | 608 | if (dpi_verify_dsi_pll(pll)) { |
594 | DSSWARN("DSI PLL not operational\n"); | 609 | DSSWARN("DSI PLL not operational\n"); |
595 | return; | 610 | return; |
@@ -615,6 +630,17 @@ static enum omap_channel dpi_get_channel(int port_num) | |||
615 | case OMAPDSS_VER_AM43xx: | 630 | case OMAPDSS_VER_AM43xx: |
616 | return OMAP_DSS_CHANNEL_LCD; | 631 | return OMAP_DSS_CHANNEL_LCD; |
617 | 632 | ||
633 | case OMAPDSS_VER_DRA7xx: | ||
634 | switch (port_num) { | ||
635 | case 2: | ||
636 | return OMAP_DSS_CHANNEL_LCD3; | ||
637 | case 1: | ||
638 | return OMAP_DSS_CHANNEL_LCD2; | ||
639 | case 0: | ||
640 | default: | ||
641 | return OMAP_DSS_CHANNEL_LCD; | ||
642 | } | ||
643 | |||
618 | case OMAPDSS_VER_OMAP4430_ES1: | 644 | case OMAPDSS_VER_OMAP4430_ES1: |
619 | case OMAPDSS_VER_OMAP4430_ES2: | 645 | case OMAPDSS_VER_OMAP4430_ES2: |
620 | case OMAPDSS_VER_OMAP4: | 646 | case OMAPDSS_VER_OMAP4: |
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c index 3e44c580b1f8..5081f6fb1737 100644 --- a/drivers/video/fbdev/omap2/dss/dsi.c +++ b/drivers/video/fbdev/omap2/dss/dsi.c | |||
@@ -5238,6 +5238,7 @@ static int dsi_init_pll_data(struct platform_device *dsidev) | |||
5238 | } | 5238 | } |
5239 | 5239 | ||
5240 | pll->name = dsi->module_id == 0 ? "dsi0" : "dsi1"; | 5240 | pll->name = dsi->module_id == 0 ? "dsi0" : "dsi1"; |
5241 | pll->id = dsi->module_id == 0 ? DSS_PLL_DSI1 : DSS_PLL_DSI2; | ||
5241 | pll->clkin = clk; | 5242 | pll->clkin = clk; |
5242 | pll->base = dsi->pll_base; | 5243 | pll->base = dsi->pll_base; |
5243 | 5244 | ||
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c index 9987154d50b4..a6d10d4279f3 100644 --- a/drivers/video/fbdev/omap2/dss/dss.c +++ b/drivers/video/fbdev/omap2/dss/dss.c | |||
@@ -34,7 +34,10 @@ | |||
34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
35 | #include <linux/gfp.h> | 35 | #include <linux/gfp.h> |
36 | #include <linux/sizes.h> | 36 | #include <linux/sizes.h> |
37 | #include <linux/mfd/syscon.h> | ||
38 | #include <linux/regmap.h> | ||
37 | #include <linux/of.h> | 39 | #include <linux/of.h> |
40 | #include <linux/regulator/consumer.h> | ||
38 | 41 | ||
39 | #include <video/omapdss.h> | 42 | #include <video/omapdss.h> |
40 | 43 | ||
@@ -63,14 +66,11 @@ struct dss_reg { | |||
63 | #define REG_FLD_MOD(idx, val, start, end) \ | 66 | #define REG_FLD_MOD(idx, val, start, end) \ |
64 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) | 67 | dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) |
65 | 68 | ||
66 | static int dss_runtime_get(void); | ||
67 | static void dss_runtime_put(void); | ||
68 | |||
69 | struct dss_features { | 69 | struct dss_features { |
70 | u8 fck_div_max; | 70 | u8 fck_div_max; |
71 | u8 dss_fck_multiplier; | 71 | u8 dss_fck_multiplier; |
72 | const char *parent_clk_name; | 72 | const char *parent_clk_name; |
73 | enum omap_display_type *ports; | 73 | const enum omap_display_type *ports; |
74 | int num_ports; | 74 | int num_ports; |
75 | int (*dpi_select_source)(int port, enum omap_channel channel); | 75 | int (*dpi_select_source)(int port, enum omap_channel channel); |
76 | }; | 76 | }; |
@@ -78,6 +78,8 @@ struct dss_features { | |||
78 | static struct { | 78 | static struct { |
79 | struct platform_device *pdev; | 79 | struct platform_device *pdev; |
80 | void __iomem *base; | 80 | void __iomem *base; |
81 | struct regmap *syscon_pll_ctrl; | ||
82 | u32 syscon_pll_ctrl_offset; | ||
81 | 83 | ||
82 | struct clk *parent_clk; | 84 | struct clk *parent_clk; |
83 | struct clk *dss_clk; | 85 | struct clk *dss_clk; |
@@ -95,6 +97,9 @@ static struct { | |||
95 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; | 97 | u32 ctx[DSS_SZ_REGS / sizeof(u32)]; |
96 | 98 | ||
97 | const struct dss_features *feat; | 99 | const struct dss_features *feat; |
100 | |||
101 | struct dss_pll *video1_pll; | ||
102 | struct dss_pll *video2_pll; | ||
98 | } dss; | 103 | } dss; |
99 | 104 | ||
100 | static const char * const dss_generic_clk_source_names[] = { | 105 | static const char * const dss_generic_clk_source_names[] = { |
@@ -158,6 +163,99 @@ static void dss_restore_context(void) | |||
158 | #undef SR | 163 | #undef SR |
159 | #undef RR | 164 | #undef RR |
160 | 165 | ||
166 | void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable) | ||
167 | { | ||
168 | unsigned shift; | ||
169 | unsigned val; | ||
170 | |||
171 | if (!dss.syscon_pll_ctrl) | ||
172 | return; | ||
173 | |||
174 | val = !enable; | ||
175 | |||
176 | switch (pll_id) { | ||
177 | case DSS_PLL_VIDEO1: | ||
178 | shift = 0; | ||
179 | break; | ||
180 | case DSS_PLL_VIDEO2: | ||
181 | shift = 1; | ||
182 | break; | ||
183 | case DSS_PLL_HDMI: | ||
184 | shift = 2; | ||
185 | break; | ||
186 | default: | ||
187 | DSSERR("illegal DSS PLL ID %d\n", pll_id); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, | ||
192 | 1 << shift, val << shift); | ||
193 | } | ||
194 | |||
195 | void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, | ||
196 | enum omap_channel channel) | ||
197 | { | ||
198 | unsigned shift, val; | ||
199 | |||
200 | if (!dss.syscon_pll_ctrl) | ||
201 | return; | ||
202 | |||
203 | switch (channel) { | ||
204 | case OMAP_DSS_CHANNEL_LCD: | ||
205 | shift = 3; | ||
206 | |||
207 | switch (pll_id) { | ||
208 | case DSS_PLL_VIDEO1: | ||
209 | val = 0; break; | ||
210 | case DSS_PLL_HDMI: | ||
211 | val = 1; break; | ||
212 | default: | ||
213 | DSSERR("error in PLL mux config for LCD\n"); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | break; | ||
218 | case OMAP_DSS_CHANNEL_LCD2: | ||
219 | shift = 5; | ||
220 | |||
221 | switch (pll_id) { | ||
222 | case DSS_PLL_VIDEO1: | ||
223 | val = 0; break; | ||
224 | case DSS_PLL_VIDEO2: | ||
225 | val = 1; break; | ||
226 | case DSS_PLL_HDMI: | ||
227 | val = 2; break; | ||
228 | default: | ||
229 | DSSERR("error in PLL mux config for LCD2\n"); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | break; | ||
234 | case OMAP_DSS_CHANNEL_LCD3: | ||
235 | shift = 7; | ||
236 | |||
237 | switch (pll_id) { | ||
238 | case DSS_PLL_VIDEO1: | ||
239 | val = 1; break; | ||
240 | case DSS_PLL_VIDEO2: | ||
241 | val = 0; break; | ||
242 | case DSS_PLL_HDMI: | ||
243 | val = 2; break; | ||
244 | default: | ||
245 | DSSERR("error in PLL mux config for LCD3\n"); | ||
246 | return; | ||
247 | } | ||
248 | |||
249 | break; | ||
250 | default: | ||
251 | DSSERR("error in PLL mux config\n"); | ||
252 | return; | ||
253 | } | ||
254 | |||
255 | regmap_update_bits(dss.syscon_pll_ctrl, dss.syscon_pll_ctrl_offset, | ||
256 | 0x3 << shift, val << shift); | ||
257 | } | ||
258 | |||
161 | void dss_sdi_init(int datapairs) | 259 | void dss_sdi_init(int datapairs) |
162 | { | 260 | { |
163 | u32 l; | 261 | u32 l; |
@@ -605,6 +703,26 @@ static int dss_dpi_select_source_omap5(int port, enum omap_channel channel) | |||
605 | return 0; | 703 | return 0; |
606 | } | 704 | } |
607 | 705 | ||
706 | static int dss_dpi_select_source_dra7xx(int port, enum omap_channel channel) | ||
707 | { | ||
708 | switch (port) { | ||
709 | case 0: | ||
710 | return dss_dpi_select_source_omap5(port, channel); | ||
711 | case 1: | ||
712 | if (channel != OMAP_DSS_CHANNEL_LCD2) | ||
713 | return -EINVAL; | ||
714 | break; | ||
715 | case 2: | ||
716 | if (channel != OMAP_DSS_CHANNEL_LCD3) | ||
717 | return -EINVAL; | ||
718 | break; | ||
719 | default: | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
608 | int dss_dpi_select_source(int port, enum omap_channel channel) | 726 | int dss_dpi_select_source(int port, enum omap_channel channel) |
609 | { | 727 | { |
610 | return dss.feat->dpi_select_source(port, channel); | 728 | return dss.feat->dpi_select_source(port, channel); |
@@ -643,7 +761,7 @@ static void dss_put_clocks(void) | |||
643 | clk_put(dss.parent_clk); | 761 | clk_put(dss.parent_clk); |
644 | } | 762 | } |
645 | 763 | ||
646 | static int dss_runtime_get(void) | 764 | int dss_runtime_get(void) |
647 | { | 765 | { |
648 | int r; | 766 | int r; |
649 | 767 | ||
@@ -654,7 +772,7 @@ static int dss_runtime_get(void) | |||
654 | return r < 0 ? r : 0; | 772 | return r < 0 ? r : 0; |
655 | } | 773 | } |
656 | 774 | ||
657 | static void dss_runtime_put(void) | 775 | void dss_runtime_put(void) |
658 | { | 776 | { |
659 | int r; | 777 | int r; |
660 | 778 | ||
@@ -677,15 +795,21 @@ void dss_debug_dump_clocks(struct seq_file *s) | |||
677 | #endif | 795 | #endif |
678 | 796 | ||
679 | 797 | ||
680 | static enum omap_display_type omap2plus_ports[] = { | 798 | static const enum omap_display_type omap2plus_ports[] = { |
681 | OMAP_DISPLAY_TYPE_DPI, | 799 | OMAP_DISPLAY_TYPE_DPI, |
682 | }; | 800 | }; |
683 | 801 | ||
684 | static enum omap_display_type omap34xx_ports[] = { | 802 | static const enum omap_display_type omap34xx_ports[] = { |
685 | OMAP_DISPLAY_TYPE_DPI, | 803 | OMAP_DISPLAY_TYPE_DPI, |
686 | OMAP_DISPLAY_TYPE_SDI, | 804 | OMAP_DISPLAY_TYPE_SDI, |
687 | }; | 805 | }; |
688 | 806 | ||
807 | static const enum omap_display_type dra7xx_ports[] = { | ||
808 | OMAP_DISPLAY_TYPE_DPI, | ||
809 | OMAP_DISPLAY_TYPE_DPI, | ||
810 | OMAP_DISPLAY_TYPE_DPI, | ||
811 | }; | ||
812 | |||
689 | static const struct dss_features omap24xx_dss_feats __initconst = { | 813 | static const struct dss_features omap24xx_dss_feats __initconst = { |
690 | /* | 814 | /* |
691 | * fck div max is really 16, but the divider range has gaps. The range | 815 | * fck div max is really 16, but the divider range has gaps. The range |
@@ -744,6 +868,15 @@ static const struct dss_features am43xx_dss_feats __initconst = { | |||
744 | .num_ports = ARRAY_SIZE(omap2plus_ports), | 868 | .num_ports = ARRAY_SIZE(omap2plus_ports), |
745 | }; | 869 | }; |
746 | 870 | ||
871 | static const struct dss_features dra7xx_dss_feats __initconst = { | ||
872 | .fck_div_max = 64, | ||
873 | .dss_fck_multiplier = 1, | ||
874 | .parent_clk_name = "dpll_per_x2_ck", | ||
875 | .dpi_select_source = &dss_dpi_select_source_dra7xx, | ||
876 | .ports = dra7xx_ports, | ||
877 | .num_ports = ARRAY_SIZE(dra7xx_ports), | ||
878 | }; | ||
879 | |||
747 | static int __init dss_init_features(struct platform_device *pdev) | 880 | static int __init dss_init_features(struct platform_device *pdev) |
748 | { | 881 | { |
749 | const struct dss_features *src; | 882 | const struct dss_features *src; |
@@ -784,6 +917,10 @@ static int __init dss_init_features(struct platform_device *pdev) | |||
784 | src = &am43xx_dss_feats; | 917 | src = &am43xx_dss_feats; |
785 | break; | 918 | break; |
786 | 919 | ||
920 | case OMAPDSS_VER_DRA7xx: | ||
921 | src = &dra7xx_dss_feats; | ||
922 | break; | ||
923 | |||
787 | default: | 924 | default: |
788 | return -ENODEV; | 925 | return -ENODEV; |
789 | } | 926 | } |
@@ -884,8 +1021,10 @@ static void __exit dss_uninit_ports(struct platform_device *pdev) | |||
884 | static int __init omap_dsshw_probe(struct platform_device *pdev) | 1021 | static int __init omap_dsshw_probe(struct platform_device *pdev) |
885 | { | 1022 | { |
886 | struct resource *dss_mem; | 1023 | struct resource *dss_mem; |
1024 | struct device_node *np = pdev->dev.of_node; | ||
887 | u32 rev; | 1025 | u32 rev; |
888 | int r; | 1026 | int r; |
1027 | struct regulator *pll_regulator; | ||
889 | 1028 | ||
890 | dss.pdev = pdev; | 1029 | dss.pdev = pdev; |
891 | 1030 | ||
@@ -940,6 +1079,57 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
940 | 1079 | ||
941 | dss_init_ports(pdev); | 1080 | dss_init_ports(pdev); |
942 | 1081 | ||
1082 | if (np && of_property_read_bool(np, "syscon-pll-ctrl")) { | ||
1083 | dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np, | ||
1084 | "syscon-pll-ctrl"); | ||
1085 | if (IS_ERR(dss.syscon_pll_ctrl)) { | ||
1086 | dev_err(&pdev->dev, | ||
1087 | "failed to get syscon-pll-ctrl regmap\n"); | ||
1088 | return PTR_ERR(dss.syscon_pll_ctrl); | ||
1089 | } | ||
1090 | |||
1091 | if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1, | ||
1092 | &dss.syscon_pll_ctrl_offset)) { | ||
1093 | dev_err(&pdev->dev, | ||
1094 | "failed to get syscon-pll-ctrl offset\n"); | ||
1095 | return -EINVAL; | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video"); | ||
1100 | if (IS_ERR(pll_regulator)) { | ||
1101 | r = PTR_ERR(pll_regulator); | ||
1102 | |||
1103 | switch (r) { | ||
1104 | case -ENOENT: | ||
1105 | pll_regulator = NULL; | ||
1106 | break; | ||
1107 | |||
1108 | case -EPROBE_DEFER: | ||
1109 | return -EPROBE_DEFER; | ||
1110 | |||
1111 | default: | ||
1112 | DSSERR("can't get DPLL VDDA regulator\n"); | ||
1113 | return r; | ||
1114 | } | ||
1115 | } | ||
1116 | |||
1117 | if (of_property_match_string(np, "reg-names", "pll1") >= 0) { | ||
1118 | dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator); | ||
1119 | if (IS_ERR(dss.video1_pll)) { | ||
1120 | r = PTR_ERR(dss.video1_pll); | ||
1121 | goto err_pll_init; | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | if (of_property_match_string(np, "reg-names", "pll2") >= 0) { | ||
1126 | dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator); | ||
1127 | if (IS_ERR(dss.video2_pll)) { | ||
1128 | r = PTR_ERR(dss.video2_pll); | ||
1129 | goto err_pll_init; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
943 | rev = dss_read_reg(DSS_REVISION); | 1133 | rev = dss_read_reg(DSS_REVISION); |
944 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", | 1134 | printk(KERN_INFO "OMAP DSS rev %d.%d\n", |
945 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); | 1135 | FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); |
@@ -950,6 +1140,12 @@ static int __init omap_dsshw_probe(struct platform_device *pdev) | |||
950 | 1140 | ||
951 | return 0; | 1141 | return 0; |
952 | 1142 | ||
1143 | err_pll_init: | ||
1144 | if (dss.video1_pll) | ||
1145 | dss_video_pll_uninit(dss.video1_pll); | ||
1146 | |||
1147 | if (dss.video2_pll) | ||
1148 | dss_video_pll_uninit(dss.video2_pll); | ||
953 | err_runtime_get: | 1149 | err_runtime_get: |
954 | pm_runtime_disable(&pdev->dev); | 1150 | pm_runtime_disable(&pdev->dev); |
955 | err_setup_clocks: | 1151 | err_setup_clocks: |
@@ -959,6 +1155,12 @@ err_setup_clocks: | |||
959 | 1155 | ||
960 | static int __exit omap_dsshw_remove(struct platform_device *pdev) | 1156 | static int __exit omap_dsshw_remove(struct platform_device *pdev) |
961 | { | 1157 | { |
1158 | if (dss.video1_pll) | ||
1159 | dss_video_pll_uninit(dss.video1_pll); | ||
1160 | |||
1161 | if (dss.video2_pll) | ||
1162 | dss_video_pll_uninit(dss.video2_pll); | ||
1163 | |||
962 | dss_uninit_ports(pdev); | 1164 | dss_uninit_ports(pdev); |
963 | 1165 | ||
964 | pm_runtime_disable(&pdev->dev); | 1166 | pm_runtime_disable(&pdev->dev); |
@@ -1003,6 +1205,7 @@ static const struct of_device_id dss_of_match[] = { | |||
1003 | { .compatible = "ti,omap3-dss", }, | 1205 | { .compatible = "ti,omap3-dss", }, |
1004 | { .compatible = "ti,omap4-dss", }, | 1206 | { .compatible = "ti,omap4-dss", }, |
1005 | { .compatible = "ti,omap5-dss", }, | 1207 | { .compatible = "ti,omap5-dss", }, |
1208 | { .compatible = "ti,dra7-dss", }, | ||
1006 | {}, | 1209 | {}, |
1007 | }; | 1210 | }; |
1008 | 1211 | ||
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h index 14fb0c23f4a2..4812eee2622a 100644 --- a/drivers/video/fbdev/omap2/dss/dss.h +++ b/drivers/video/fbdev/omap2/dss/dss.h | |||
@@ -100,6 +100,14 @@ enum dss_writeback_channel { | |||
100 | DSS_WB_LCD3_MGR = 7, | 100 | DSS_WB_LCD3_MGR = 7, |
101 | }; | 101 | }; |
102 | 102 | ||
103 | enum dss_pll_id { | ||
104 | DSS_PLL_DSI1, | ||
105 | DSS_PLL_DSI2, | ||
106 | DSS_PLL_HDMI, | ||
107 | DSS_PLL_VIDEO1, | ||
108 | DSS_PLL_VIDEO2, | ||
109 | }; | ||
110 | |||
103 | struct dss_pll; | 111 | struct dss_pll; |
104 | 112 | ||
105 | #define DSS_PLL_MAX_HSDIVS 4 | 113 | #define DSS_PLL_MAX_HSDIVS 4 |
@@ -150,6 +158,7 @@ struct dss_pll_hw { | |||
150 | 158 | ||
151 | struct dss_pll { | 159 | struct dss_pll { |
152 | const char *name; | 160 | const char *name; |
161 | enum dss_pll_id id; | ||
153 | 162 | ||
154 | struct clk *clkin; | 163 | struct clk *clkin; |
155 | struct regulator *regulator; | 164 | struct regulator *regulator; |
@@ -250,6 +259,9 @@ void dss_overlay_kobj_uninit(struct omap_overlay *ovl); | |||
250 | int dss_init_platform_driver(void) __init; | 259 | int dss_init_platform_driver(void) __init; |
251 | void dss_uninit_platform_driver(void); | 260 | void dss_uninit_platform_driver(void); |
252 | 261 | ||
262 | int dss_runtime_get(void); | ||
263 | void dss_runtime_put(void); | ||
264 | |||
253 | unsigned long dss_get_dispc_clk_rate(void); | 265 | unsigned long dss_get_dispc_clk_rate(void); |
254 | int dss_dpi_select_source(int port, enum omap_channel channel); | 266 | int dss_dpi_select_source(int port, enum omap_channel channel); |
255 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 267 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
@@ -257,6 +269,11 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | |||
257 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 269 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
258 | void dss_dump_clocks(struct seq_file *s); | 270 | void dss_dump_clocks(struct seq_file *s); |
259 | 271 | ||
272 | /* DSS VIDEO PLL */ | ||
273 | struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, | ||
274 | struct regulator *regulator); | ||
275 | void dss_video_pll_uninit(struct dss_pll *pll); | ||
276 | |||
260 | /* dss-of */ | 277 | /* dss-of */ |
261 | struct device_node *dss_of_port_get_parent_device(struct device_node *port); | 278 | struct device_node *dss_of_port_get_parent_device(struct device_node *port); |
262 | u32 dss_of_port_get_port_number(struct device_node *port); | 279 | u32 dss_of_port_get_port_number(struct device_node *port); |
@@ -265,6 +282,10 @@ u32 dss_of_port_get_port_number(struct device_node *port); | |||
265 | void dss_debug_dump_clocks(struct seq_file *s); | 282 | void dss_debug_dump_clocks(struct seq_file *s); |
266 | #endif | 283 | #endif |
267 | 284 | ||
285 | void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable); | ||
286 | void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id, | ||
287 | enum omap_channel channel); | ||
288 | |||
268 | void dss_sdi_init(int datapairs); | 289 | void dss_sdi_init(int datapairs); |
269 | int dss_sdi_enable(void); | 290 | int dss_sdi_enable(void); |
270 | void dss_sdi_disable(void); | 291 | void dss_sdi_disable(void); |
@@ -446,5 +467,6 @@ int dss_pll_write_config_type_a(struct dss_pll *pll, | |||
446 | const struct dss_pll_clock_info *cinfo); | 467 | const struct dss_pll_clock_info *cinfo); |
447 | int dss_pll_write_config_type_b(struct dss_pll *pll, | 468 | int dss_pll_write_config_type_b(struct dss_pll *pll, |
448 | const struct dss_pll_clock_info *cinfo); | 469 | const struct dss_pll_clock_info *cinfo); |
470 | int dss_pll_wait_reset_done(struct dss_pll *pll); | ||
449 | 471 | ||
450 | #endif | 472 | #endif |
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c index 0e3da809473c..376270b777f8 100644 --- a/drivers/video/fbdev/omap2/dss/dss_features.c +++ b/drivers/video/fbdev/omap2/dss/dss_features.c | |||
@@ -223,7 +223,7 @@ static const enum omap_dss_output_id omap5_dss_supported_outputs[] = { | |||
223 | OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, | 223 | OMAP_DSS_OUTPUT_DSI1 | OMAP_DSS_OUTPUT_DSI2, |
224 | 224 | ||
225 | /* OMAP_DSS_CHANNEL_DIGIT */ | 225 | /* OMAP_DSS_CHANNEL_DIGIT */ |
226 | OMAP_DSS_OUTPUT_HDMI | OMAP_DSS_OUTPUT_DPI, | 226 | OMAP_DSS_OUTPUT_HDMI, |
227 | 227 | ||
228 | /* OMAP_DSS_CHANNEL_LCD2 */ | 228 | /* OMAP_DSS_CHANNEL_LCD2 */ |
229 | OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | | 229 | OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | |
@@ -943,6 +943,7 @@ void dss_features_init(enum omapdss_version version) | |||
943 | break; | 943 | break; |
944 | 944 | ||
945 | case OMAPDSS_VER_OMAP5: | 945 | case OMAPDSS_VER_OMAP5: |
946 | case OMAPDSS_VER_DRA7xx: | ||
946 | omap_current_dss_features = &omap5_dss_features; | 947 | omap_current_dss_features = &omap5_dss_features; |
947 | break; | 948 | break; |
948 | 949 | ||
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c index 39aae3aa7136..3f0b34a7031a 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi5.c +++ b/drivers/video/fbdev/omap2/dss/hdmi5.c | |||
@@ -787,6 +787,7 @@ static const struct dev_pm_ops hdmi_pm_ops = { | |||
787 | 787 | ||
788 | static const struct of_device_id hdmi_of_match[] = { | 788 | static const struct of_device_id hdmi_of_match[] = { |
789 | { .compatible = "ti,omap5-hdmi", }, | 789 | { .compatible = "ti,omap5-hdmi", }, |
790 | { .compatible = "ti,dra7-hdmi", }, | ||
790 | {}, | 791 | {}, |
791 | }; | 792 | }; |
792 | 793 | ||
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c index bc9e07d2afbe..1f5d19c119ce 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_phy.c +++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c | |||
@@ -208,6 +208,7 @@ static int hdmi_phy_init_features(struct platform_device *pdev) | |||
208 | break; | 208 | break; |
209 | 209 | ||
210 | case OMAPDSS_VER_OMAP5: | 210 | case OMAPDSS_VER_OMAP5: |
211 | case OMAPDSS_VER_DRA7xx: | ||
211 | src = &omap54xx_phy_feats; | 212 | src = &omap54xx_phy_feats; |
212 | break; | 213 | break; |
213 | 214 | ||
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c index ac83ef5cfd7d..06e23a7c432c 100644 --- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c +++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c | |||
@@ -104,6 +104,8 @@ static int hdmi_pll_enable(struct dss_pll *dsspll) | |||
104 | struct hdmi_wp_data *wp = pll->wp; | 104 | struct hdmi_wp_data *wp = pll->wp; |
105 | u16 r = 0; | 105 | u16 r = 0; |
106 | 106 | ||
107 | dss_ctrl_pll_enable(DSS_PLL_HDMI, true); | ||
108 | |||
107 | r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); | 109 | r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); |
108 | if (r) | 110 | if (r) |
109 | return r; | 111 | return r; |
@@ -117,6 +119,8 @@ static void hdmi_pll_disable(struct dss_pll *dsspll) | |||
117 | struct hdmi_wp_data *wp = pll->wp; | 119 | struct hdmi_wp_data *wp = pll->wp; |
118 | 120 | ||
119 | hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); | 121 | hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); |
122 | |||
123 | dss_ctrl_pll_enable(DSS_PLL_HDMI, false); | ||
120 | } | 124 | } |
121 | 125 | ||
122 | static const struct dss_pll_ops dsi_pll_ops = { | 126 | static const struct dss_pll_ops dsi_pll_ops = { |
@@ -185,6 +189,7 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data | |||
185 | } | 189 | } |
186 | 190 | ||
187 | pll->name = "hdmi"; | 191 | pll->name = "hdmi"; |
192 | pll->id = DSS_PLL_HDMI; | ||
188 | pll->base = hpll->base; | 193 | pll->base = hpll->base; |
189 | pll->clkin = clk; | 194 | pll->clkin = clk; |
190 | 195 | ||
@@ -196,6 +201,7 @@ static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data | |||
196 | break; | 201 | break; |
197 | 202 | ||
198 | case OMAPDSS_VER_OMAP5: | 203 | case OMAPDSS_VER_OMAP5: |
204 | case OMAPDSS_VER_DRA7xx: | ||
199 | pll->hw = &dss_omap5_hdmi_pll_hw; | 205 | pll->hw = &dss_omap5_hdmi_pll_hw; |
200 | break; | 206 | break; |
201 | 207 | ||
diff --git a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c index 2f0822ee3ff9..42b87f95267c 100644 --- a/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c +++ b/drivers/video/fbdev/omap2/dss/omapdss-boot-init.c | |||
@@ -186,6 +186,7 @@ static const struct of_device_id omapdss_of_match[] __initconst = { | |||
186 | { .compatible = "ti,omap3-dss", }, | 186 | { .compatible = "ti,omap3-dss", }, |
187 | { .compatible = "ti,omap4-dss", }, | 187 | { .compatible = "ti,omap4-dss", }, |
188 | { .compatible = "ti,omap5-dss", }, | 188 | { .compatible = "ti,omap5-dss", }, |
189 | { .compatible = "ti,dra7-dss", }, | ||
189 | {}, | 190 | {}, |
190 | }; | 191 | }; |
191 | 192 | ||
diff --git a/drivers/video/fbdev/omap2/dss/pll.c b/drivers/video/fbdev/omap2/dss/pll.c index 335ffac224b9..f974ddcd3b6e 100644 --- a/drivers/video/fbdev/omap2/dss/pll.c +++ b/drivers/video/fbdev/omap2/dss/pll.c | |||
@@ -222,6 +222,16 @@ static int wait_for_bit_change(void __iomem *reg, int bitnum, int value) | |||
222 | return !value; | 222 | return !value; |
223 | } | 223 | } |
224 | 224 | ||
225 | int dss_pll_wait_reset_done(struct dss_pll *pll) | ||
226 | { | ||
227 | void __iomem *base = pll->base; | ||
228 | |||
229 | if (wait_for_bit_change(base + PLL_STATUS, 0, 1) != 1) | ||
230 | return -ETIMEDOUT; | ||
231 | else | ||
232 | return 0; | ||
233 | } | ||
234 | |||
225 | static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask) | 235 | static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask) |
226 | { | 236 | { |
227 | int t = 100; | 237 | int t = 100; |
diff --git a/drivers/video/fbdev/omap2/dss/video-pll.c b/drivers/video/fbdev/omap2/dss/video-pll.c new file mode 100644 index 000000000000..b1ec59e42940 --- /dev/null +++ b/drivers/video/fbdev/omap2/dss/video-pll.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Texas Instruments Ltd | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License version 2 as published by | ||
6 | * the Free Software Foundation. | ||
7 | * | ||
8 | * You should have received a copy of the GNU General Public License along with | ||
9 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/sched.h> | ||
19 | |||
20 | #include <video/omapdss.h> | ||
21 | |||
22 | #include "dss.h" | ||
23 | #include "dss_features.h" | ||
24 | |||
25 | struct dss_video_pll { | ||
26 | struct dss_pll pll; | ||
27 | |||
28 | struct device *dev; | ||
29 | |||
30 | void __iomem *clkctrl_base; | ||
31 | }; | ||
32 | |||
33 | #define REG_MOD(reg, val, start, end) \ | ||
34 | writel_relaxed(FLD_MOD(readl_relaxed(reg), val, start, end), reg) | ||
35 | |||
36 | static void dss_dpll_enable_scp_clk(struct dss_video_pll *vpll) | ||
37 | { | ||
38 | REG_MOD(vpll->clkctrl_base, 1, 14, 14); /* CIO_CLK_ICG */ | ||
39 | } | ||
40 | |||
41 | static void dss_dpll_disable_scp_clk(struct dss_video_pll *vpll) | ||
42 | { | ||
43 | REG_MOD(vpll->clkctrl_base, 0, 14, 14); /* CIO_CLK_ICG */ | ||
44 | } | ||
45 | |||
46 | static void dss_dpll_power_enable(struct dss_video_pll *vpll) | ||
47 | { | ||
48 | REG_MOD(vpll->clkctrl_base, 2, 31, 30); /* PLL_POWER_ON_ALL */ | ||
49 | |||
50 | /* | ||
51 | * DRA7x PLL CTRL's PLL_PWR_STATUS seems to always return 0, | ||
52 | * so we have to use fixed delay here. | ||
53 | */ | ||
54 | msleep(1); | ||
55 | } | ||
56 | |||
57 | static void dss_dpll_power_disable(struct dss_video_pll *vpll) | ||
58 | { | ||
59 | REG_MOD(vpll->clkctrl_base, 0, 31, 30); /* PLL_POWER_OFF */ | ||
60 | } | ||
61 | |||
62 | static int dss_video_pll_enable(struct dss_pll *pll) | ||
63 | { | ||
64 | struct dss_video_pll *vpll = container_of(pll, struct dss_video_pll, pll); | ||
65 | int r; | ||
66 | |||
67 | r = dss_runtime_get(); | ||
68 | if (r) | ||
69 | return r; | ||
70 | |||
71 | dss_ctrl_pll_enable(pll->id, true); | ||
72 | |||
73 | dss_dpll_enable_scp_clk(vpll); | ||
74 | |||
75 | r = dss_pll_wait_reset_done(pll); | ||
76 | if (r) | ||
77 | goto err_reset; | ||
78 | |||
79 | dss_dpll_power_enable(vpll); | ||
80 | |||
81 | return 0; | ||
82 | |||
83 | err_reset: | ||
84 | dss_dpll_disable_scp_clk(vpll); | ||
85 | dss_ctrl_pll_enable(pll->id, false); | ||
86 | dss_runtime_put(); | ||
87 | |||
88 | return r; | ||
89 | } | ||
90 | |||
91 | static void dss_video_pll_disable(struct dss_pll *pll) | ||
92 | { | ||
93 | struct dss_video_pll *vpll = container_of(pll, struct dss_video_pll, pll); | ||
94 | |||
95 | dss_dpll_power_disable(vpll); | ||
96 | |||
97 | dss_dpll_disable_scp_clk(vpll); | ||
98 | |||
99 | dss_ctrl_pll_enable(pll->id, false); | ||
100 | |||
101 | dss_runtime_put(); | ||
102 | } | ||
103 | |||
104 | static const struct dss_pll_ops dss_pll_ops = { | ||
105 | .enable = dss_video_pll_enable, | ||
106 | .disable = dss_video_pll_disable, | ||
107 | .set_config = dss_pll_write_config_type_a, | ||
108 | }; | ||
109 | |||
110 | static const struct dss_pll_hw dss_dra7_video_pll_hw = { | ||
111 | .n_max = (1 << 8) - 1, | ||
112 | .m_max = (1 << 12) - 1, | ||
113 | .mX_max = (1 << 5) - 1, | ||
114 | .fint_min = 500000, | ||
115 | .fint_max = 2500000, | ||
116 | .clkdco_max = 1800000000, | ||
117 | |||
118 | .n_msb = 8, | ||
119 | .n_lsb = 1, | ||
120 | .m_msb = 20, | ||
121 | .m_lsb = 9, | ||
122 | |||
123 | .mX_msb[0] = 25, | ||
124 | .mX_lsb[0] = 21, | ||
125 | .mX_msb[1] = 30, | ||
126 | .mX_lsb[1] = 26, | ||
127 | |||
128 | .has_refsel = true, | ||
129 | }; | ||
130 | |||
131 | struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, | ||
132 | struct regulator *regulator) | ||
133 | { | ||
134 | const char * const reg_name[] = { "pll1", "pll2" }; | ||
135 | const char * const clkctrl_name[] = { "pll1_clkctrl", "pll2_clkctrl" }; | ||
136 | const char * const clkin_name[] = { "video1_clk", "video2_clk" }; | ||
137 | |||
138 | struct resource *res; | ||
139 | struct dss_video_pll *vpll; | ||
140 | void __iomem *pll_base, *clkctrl_base; | ||
141 | struct clk *clk; | ||
142 | struct dss_pll *pll; | ||
143 | int r; | ||
144 | |||
145 | /* PLL CONTROL */ | ||
146 | |||
147 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, reg_name[id]); | ||
148 | if (!res) { | ||
149 | dev_err(&pdev->dev, | ||
150 | "missing platform resource data for pll%d\n", id); | ||
151 | return ERR_PTR(-ENODEV); | ||
152 | } | ||
153 | |||
154 | pll_base = devm_ioremap_resource(&pdev->dev, res); | ||
155 | if (IS_ERR(pll_base)) { | ||
156 | dev_err(&pdev->dev, "failed to ioremap pll%d reg_name\n", id); | ||
157 | return ERR_CAST(pll_base); | ||
158 | } | ||
159 | |||
160 | /* CLOCK CONTROL */ | ||
161 | |||
162 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
163 | clkctrl_name[id]); | ||
164 | if (!res) { | ||
165 | dev_err(&pdev->dev, | ||
166 | "missing platform resource data for pll%d\n", id); | ||
167 | return ERR_PTR(-ENODEV); | ||
168 | } | ||
169 | |||
170 | clkctrl_base = devm_ioremap_resource(&pdev->dev, res); | ||
171 | if (IS_ERR(clkctrl_base)) { | ||
172 | dev_err(&pdev->dev, "failed to ioremap pll%d clkctrl\n", id); | ||
173 | return ERR_CAST(clkctrl_base); | ||
174 | } | ||
175 | |||
176 | /* CLKIN */ | ||
177 | |||
178 | clk = devm_clk_get(&pdev->dev, clkin_name[id]); | ||
179 | if (IS_ERR(clk)) { | ||
180 | DSSERR("can't get video pll clkin\n"); | ||
181 | return ERR_CAST(clk); | ||
182 | } | ||
183 | |||
184 | vpll = devm_kzalloc(&pdev->dev, sizeof(*vpll), GFP_KERNEL); | ||
185 | if (!vpll) | ||
186 | return ERR_PTR(-ENOMEM); | ||
187 | |||
188 | vpll->dev = &pdev->dev; | ||
189 | vpll->clkctrl_base = clkctrl_base; | ||
190 | |||
191 | pll = &vpll->pll; | ||
192 | |||
193 | pll->name = id == 0 ? "video0" : "video1"; | ||
194 | pll->id = id == 0 ? DSS_PLL_VIDEO1 : DSS_PLL_VIDEO2; | ||
195 | pll->clkin = clk; | ||
196 | pll->regulator = regulator; | ||
197 | pll->base = pll_base; | ||
198 | pll->hw = &dss_dra7_video_pll_hw; | ||
199 | pll->ops = &dss_pll_ops; | ||
200 | |||
201 | r = dss_pll_register(pll); | ||
202 | if (r) | ||
203 | return ERR_PTR(r); | ||
204 | |||
205 | return pll; | ||
206 | } | ||
207 | |||
208 | void dss_video_pll_uninit(struct dss_pll *pll) | ||
209 | { | ||
210 | dss_pll_unregister(pll); | ||
211 | } | ||
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c index 146b6f5428db..9ddfdd63b84c 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c | |||
@@ -137,8 +137,11 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi) | |||
137 | goto undo; | 137 | goto undo; |
138 | } | 138 | } |
139 | 139 | ||
140 | if (ovl->manager) | 140 | if (ovl->manager) { |
141 | ovl->manager->apply(ovl->manager); | 141 | r = ovl->manager->apply(ovl->manager); |
142 | if (r) | ||
143 | goto undo; | ||
144 | } | ||
142 | 145 | ||
143 | if (pi->enabled) { | 146 | if (pi->enabled) { |
144 | r = ovl->enable(ovl); | 147 | r = ovl->enable(ovl); |