aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2015-02-04 05:44:11 -0500
committerTomi Valkeinen <tomi.valkeinen@ti.com>2015-02-04 05:44:11 -0500
commitd6c2152b3efd73be265f426b5a1bb50ec436d999 (patch)
treef35b2a9b40c82028a4a2ecd4593d592431db8fc2 /drivers/video
parentee06bd155b081a1895f995ec2777094c7e746152 (diff)
parent811fbb1f580ca024a0af603dfaef08a4d1dcb5ef (diff)
Merge branches '3.20/fbdev' and '3.20/omapdss' into for-next
Merge fbdev topic branches
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbdev/omap2/displays-new/Kconfig6
-rw-r--r--drivers/video/fbdev/omap2/displays-new/Makefile1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c2
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-opa362.c285
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c57
-rw-r--r--drivers/video/fbdev/omap2/dss/Makefile2
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c54
-rw-r--r--drivers/video/fbdev/omap2/dss/dpi.c26
-rw-r--r--drivers/video/fbdev/omap2/dss/dsi.c1
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c219
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.h22
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.c3
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5.c1
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_phy.c1
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_pll.c6
-rw-r--r--drivers/video/fbdev/omap2/dss/omapdss-boot-init.c1
-rw-r--r--drivers/video/fbdev/omap2/dss/pll.c10
-rw-r--r--drivers/video/fbdev/omap2/dss/video-pll.c211
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c7
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 @@
1menu "OMAP Display Device Drivers (new device model)" 1menu "OMAP Display Device Drivers (new device model)"
2 depends on OMAP2_DSS 2 depends on OMAP2_DSS
3 3
4config 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
4config DISPLAY_ENCODER_TFP410 10config 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 @@
1obj-$(CONFIG_DISPLAY_ENCODER_OPA362) += encoder-opa362.o
1obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o 2obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
2obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o 3obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
3obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o 4obj-$(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
25struct 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
36static 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
58static 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
80static 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
108static 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
126static 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
140static 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
150static 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
161static 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
169static 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
183static 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;
238err_reg:
239 omap_dss_put_device(ddata->in);
240 return r;
241}
242
243static 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
264static const struct of_device_id opa362_of_match[] = {
265 { .compatible = "omapdss,ti,opa362", },
266 {},
267};
268MODULE_DEVICE_TABLE(of, opa362_of_match);
269
270static 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
281module_platform_driver(opa362_driver);
282
283MODULE_AUTHOR("H. Nikolaus Schaller <hns@goldelico.com>");
284MODULE_DESCRIPTION("OPA362 analog video amplifier with output/power control");
285MODULE_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
38static 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
59static int tpd_connect(struct omap_dss_device *dssdev, 36static 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
189static bool tpd_detect(struct omap_dss_device *dssdev) 162static 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;
367err_reg: 331err_reg:
368err_irq:
369err_gpio: 332err_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
2obj-$(CONFIG_OMAP2_DSS) += omapdss.o 2obj-$(CONFIG_OMAP2_DSS) += omapdss.o
3# Core DSS files 3# Core DSS files
4omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 4omapdss-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
7omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ 7omapdss-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
122enum omap_color_component { 128enum 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
66static int dss_runtime_get(void);
67static void dss_runtime_put(void);
68
69struct dss_features { 69struct 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 {
78static struct { 78static 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
100static const char * const dss_generic_clk_source_names[] = { 105static 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
166void 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
195void 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
161void dss_sdi_init(int datapairs) 259void 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
706static 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
608int dss_dpi_select_source(int port, enum omap_channel channel) 726int 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
646static int dss_runtime_get(void) 764int 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
657static void dss_runtime_put(void) 775void 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
680static enum omap_display_type omap2plus_ports[] = { 798static const enum omap_display_type omap2plus_ports[] = {
681 OMAP_DISPLAY_TYPE_DPI, 799 OMAP_DISPLAY_TYPE_DPI,
682}; 800};
683 801
684static enum omap_display_type omap34xx_ports[] = { 802static 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
807static const enum omap_display_type dra7xx_ports[] = {
808 OMAP_DISPLAY_TYPE_DPI,
809 OMAP_DISPLAY_TYPE_DPI,
810 OMAP_DISPLAY_TYPE_DPI,
811};
812
689static const struct dss_features omap24xx_dss_feats __initconst = { 813static 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
871static 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
747static int __init dss_init_features(struct platform_device *pdev) 880static 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)
884static int __init omap_dsshw_probe(struct platform_device *pdev) 1021static 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
1143err_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);
953err_runtime_get: 1149err_runtime_get:
954 pm_runtime_disable(&pdev->dev); 1150 pm_runtime_disable(&pdev->dev);
955err_setup_clocks: 1151err_setup_clocks:
@@ -959,6 +1155,12 @@ err_setup_clocks:
959 1155
960static int __exit omap_dsshw_remove(struct platform_device *pdev) 1156static 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
103enum 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
103struct dss_pll; 111struct 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
151struct dss_pll { 159struct 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);
250int dss_init_platform_driver(void) __init; 259int dss_init_platform_driver(void) __init;
251void dss_uninit_platform_driver(void); 260void dss_uninit_platform_driver(void);
252 261
262int dss_runtime_get(void);
263void dss_runtime_put(void);
264
253unsigned long dss_get_dispc_clk_rate(void); 265unsigned long dss_get_dispc_clk_rate(void);
254int dss_dpi_select_source(int port, enum omap_channel channel); 266int dss_dpi_select_source(int port, enum omap_channel channel);
255void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 267void 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);
257const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 269const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
258void dss_dump_clocks(struct seq_file *s); 270void dss_dump_clocks(struct seq_file *s);
259 271
272/* DSS VIDEO PLL */
273struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id,
274 struct regulator *regulator);
275void dss_video_pll_uninit(struct dss_pll *pll);
276
260/* dss-of */ 277/* dss-of */
261struct device_node *dss_of_port_get_parent_device(struct device_node *port); 278struct device_node *dss_of_port_get_parent_device(struct device_node *port);
262u32 dss_of_port_get_port_number(struct device_node *port); 279u32 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);
265void dss_debug_dump_clocks(struct seq_file *s); 282void dss_debug_dump_clocks(struct seq_file *s);
266#endif 283#endif
267 284
285void dss_ctrl_pll_enable(enum dss_pll_id pll_id, bool enable);
286void dss_ctrl_pll_set_control_mux(enum dss_pll_id pll_id,
287 enum omap_channel channel);
288
268void dss_sdi_init(int datapairs); 289void dss_sdi_init(int datapairs);
269int dss_sdi_enable(void); 290int dss_sdi_enable(void);
270void dss_sdi_disable(void); 291void 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);
447int dss_pll_write_config_type_b(struct dss_pll *pll, 468int 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);
470int 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
788static const struct of_device_id hdmi_of_match[] = { 788static 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
122static const struct dss_pll_ops dsi_pll_ops = { 126static 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
225int 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
225static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask) 235static 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
25struct 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
36static 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
41static 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
46static 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
57static 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
62static 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
83err_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
91static 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
104static 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
110static 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
131struct 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
208void 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);