aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt33
-rw-r--r--Documentation/devicetree/bindings/video/simple-framebuffer.txt68
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/video/console/fbcon.c2
-rw-r--r--drivers/video/fbdev/omap2/displays-new/connector-hdmi.c99
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c1
-rw-r--r--drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c57
-rw-r--r--drivers/video/fbdev/omap2/dss/Kconfig7
-rw-r--r--drivers/video/fbdev/omap2/dss/Makefile2
-rw-r--r--drivers/video/fbdev/omap2/dss/dispc.c20
-rw-r--r--drivers/video/fbdev/omap2/dss/dpi.c327
-rw-r--r--drivers/video/fbdev/omap2/dss/dsi.c659
-rw-r--r--drivers/video/fbdev/omap2/dss/dss-of.c58
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c123
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.h225
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.c42
-rw-r--r--drivers/video/fbdev/omap2/dss/dss_features.h12
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi.h71
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4.c338
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.c14
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi4_core.h4
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5.c338
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5_core.c11
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi5_core.h2
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_common.c2
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_phy.c31
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_pll.c313
-rw-r--r--drivers/video/fbdev/omap2/dss/hdmi_wp.c16
-rw-r--r--drivers/video/fbdev/omap2/dss/output.c19
-rw-r--r--drivers/video/fbdev/omap2/dss/pll.c378
-rw-r--r--drivers/video/fbdev/omap2/dss/sdi.c2
-rw-r--r--drivers/video/fbdev/simplefb.c162
-rw-r--r--include/linux/of.h3
-rw-r--r--include/sound/omap-hdmi-audio.h43
-rw-r--r--include/video/omapdss.h45
-rw-r--r--sound/soc/omap/Kconfig26
-rw-r--r--sound/soc/omap/Makefile6
-rw-r--r--sound/soc/omap/omap-hdmi-audio.c407
-rw-r--r--sound/soc/omap/omap-hdmi-card.c87
-rw-r--r--sound/soc/omap/omap-hdmi.c364
-rw-r--r--sound/soc/omap/omap-hdmi.h38
41 files changed, 2352 insertions, 2111 deletions
diff --git a/Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt b/Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt
new file mode 100644
index 000000000000..c46ba641a1df
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/simple-framebuffer-sunxi.txt
@@ -0,0 +1,33 @@
1Sunxi specific Simple Framebuffer bindings
2
3This binding documents sunxi specific extensions to the simple-framebuffer
4bindings. The sunxi simplefb u-boot code relies on the devicetree containing
5pre-populated simplefb nodes.
6
7These extensions are intended so that u-boot can select the right node based
8on which pipeline is being used. As such they are solely intended for
9firmware / bootloader use, and the OS should ignore them.
10
11Required properties:
12- compatible: "allwinner,simple-framebuffer"
13- allwinner,pipeline, one of:
14 "de_be0-lcd0"
15 "de_be1-lcd1"
16 "de_be0-lcd0-hdmi"
17 "de_be1-lcd1-hdmi"
18
19Example:
20
21chosen {
22 #address-cells = <1>;
23 #size-cells = <1>;
24 ranges;
25
26 framebuffer@0 {
27 compatible = "allwinner,simple-framebuffer", "simple-framebuffer";
28 allwinner,pipeline = "de_be0-lcd0-hdmi";
29 clocks = <&pll5 1>, <&ahb_gates 36>, <&ahb_gates 43>,
30 <&ahb_gates 44>;
31 status = "disabled";
32 };
33};
diff --git a/Documentation/devicetree/bindings/video/simple-framebuffer.txt b/Documentation/devicetree/bindings/video/simple-framebuffer.txt
index 70c26f3a5b9a..4474ef6e0b95 100644
--- a/Documentation/devicetree/bindings/video/simple-framebuffer.txt
+++ b/Documentation/devicetree/bindings/video/simple-framebuffer.txt
@@ -1,8 +1,40 @@
1Simple Framebuffer 1Simple Framebuffer
2 2
3A simple frame-buffer describes a raw memory region that may be rendered to, 3A simple frame-buffer describes a frame-buffer setup by firmware or
4with the assumption that the display hardware has already been set up to scan 4the bootloader, with the assumption that the display hardware has already
5out from that buffer. 5been set up to scan out from the memory pointed to by the reg property.
6
7Since simplefb nodes represent runtime information they must be sub-nodes of
8the chosen node (*). Simplefb nodes must be named "framebuffer@<address>".
9
10If the devicetree contains nodes for the display hardware used by a simplefb,
11then the simplefb node must contain a property called "display", which
12contains a phandle pointing to the primary display hw node, so that the OS
13knows which simplefb to disable when handing over control to a driver for the
14real hardware. The bindings for the hw nodes must specify which node is
15considered the primary node.
16
17It is advised to add display# aliases to help the OS determine how to number
18things. If display# aliases are used, then if the simplefb node contains a
19"display" property then the /aliases/display# path must point to the display
20hw node the "display" property points to, otherwise it must point directly
21to the simplefb node.
22
23If a simplefb node represents the preferred console for user interaction,
24then the chosen node's stdout-path property should point to it, or to the
25primary display hw node, as with display# aliases. If display aliases are
26used then it should be set to the alias instead.
27
28It is advised that devicetree files contain pre-filled, disabled framebuffer
29nodes, so that the firmware only needs to update the mode information and
30enable them. This way if e.g. later on support for more display clocks get
31added, the simplefb nodes will already contain this info and the firmware
32does not need to be updated.
33
34If pre-filled framebuffer nodes are used, the firmware may need extra
35information to find the right node. In that case an extra platform specific
36compatible and platform specific properties should be used and documented,
37see e.g. simple-framebuffer-sunxi.txt .
6 38
7Required properties: 39Required properties:
8- compatible: "simple-framebuffer" 40- compatible: "simple-framebuffer"
@@ -14,13 +46,41 @@ Required properties:
14 - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b). 46 - r5g6b5 (16-bit pixels, d[15:11]=r, d[10:5]=g, d[4:0]=b).
15 - a8b8g8r8 (32-bit pixels, d[31:24]=a, d[23:16]=b, d[15:8]=g, d[7:0]=r). 47 - a8b8g8r8 (32-bit pixels, d[31:24]=a, d[23:16]=b, d[15:8]=g, d[7:0]=r).
16 48
49Optional properties:
50- clocks : List of clocks used by the framebuffer. Clocks listed here
51 are expected to already be configured correctly. The OS must
52 ensure these clocks are not modified or disabled while the
53 simple framebuffer remains active.
54- display : phandle pointing to the primary display hardware node
55
17Example: 56Example:
18 57
19 framebuffer { 58aliases {
59 display0 = &lcdc0;
60}
61
62chosen {
63 framebuffer0: framebuffer@1d385000 {
20 compatible = "simple-framebuffer"; 64 compatible = "simple-framebuffer";
21 reg = <0x1d385000 (1600 * 1200 * 2)>; 65 reg = <0x1d385000 (1600 * 1200 * 2)>;
22 width = <1600>; 66 width = <1600>;
23 height = <1200>; 67 height = <1200>;
24 stride = <(1600 * 2)>; 68 stride = <(1600 * 2)>;
25 format = "r5g6b5"; 69 format = "r5g6b5";
70 clocks = <&ahb_gates 36>, <&ahb_gates 43>, <&ahb_gates 44>;
71 display = <&lcdc0>;
72 };
73 stdout-path = "display0";
74};
75
76soc@01c00000 {
77 lcdc0: lcdc@1c0c000 {
78 compatible = "allwinner,sun4i-a10-lcdc";
79 ...
26 }; 80 };
81};
82
83
84*) Older devicetree files may have a compatible = "simple-framebuffer" node
85in a different place, operating systems must first enumerate any compatible
86nodes found under chosen and then check for other compatible nodes.
diff --git a/MAINTAINERS b/MAINTAINERS
index 3c6427190be2..d348ccc162fb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8442,6 +8442,14 @@ F: drivers/media/usb/siano/
8442F: drivers/media/usb/siano/ 8442F: drivers/media/usb/siano/
8443F: drivers/media/mmc/siano/ 8443F: drivers/media/mmc/siano/
8444 8444
8445SIMPLEFB FB DRIVER
8446M: Hans de Goede <hdegoede@redhat.com>
8447L: linux-fbdev@vger.kernel.org
8448S: Maintained
8449F: Documentation/devicetree/bindings/video/simple-framebuffer.txt
8450F: drivers/video/fbdev/simplefb.c
8451F: include/linux/platform_data/simplefb.h
8452
8445SH_VEU V4L2 MEM2MEM DRIVER 8453SH_VEU V4L2 MEM2MEM DRIVER
8446L: linux-media@vger.kernel.org 8454L: linux-media@vger.kernel.org
8447S: Orphan 8455S: Orphan
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index eb976ee3a02f..ea437245562e 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3624,7 +3624,7 @@ static int __init fb_console_init(void)
3624 return 0; 3624 return 0;
3625} 3625}
3626 3626
3627module_init(fb_console_init); 3627fs_initcall(fb_console_init);
3628 3628
3629#ifdef MODULE 3629#ifdef MODULE
3630 3630
diff --git a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
index 7b25967a91eb..219f14f59672 100644
--- a/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
+++ b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c
@@ -170,98 +170,6 @@ static bool hdmic_detect(struct omap_dss_device *dssdev)
170 return in->ops.hdmi->detect(in); 170 return in->ops.hdmi->detect(in);
171} 171}
172 172
173static int hdmic_audio_enable(struct omap_dss_device *dssdev)
174{
175 struct panel_drv_data *ddata = to_panel_data(dssdev);
176 struct omap_dss_device *in = ddata->in;
177 int r;
178
179 /* enable audio only if the display is active */
180 if (!omapdss_device_is_enabled(dssdev))
181 return -EPERM;
182
183 r = in->ops.hdmi->audio_enable(in);
184 if (r)
185 return r;
186
187 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
188
189 return 0;
190}
191
192static void hdmic_audio_disable(struct omap_dss_device *dssdev)
193{
194 struct panel_drv_data *ddata = to_panel_data(dssdev);
195 struct omap_dss_device *in = ddata->in;
196
197 in->ops.hdmi->audio_disable(in);
198
199 dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
200}
201
202static int hdmic_audio_start(struct omap_dss_device *dssdev)
203{
204 struct panel_drv_data *ddata = to_panel_data(dssdev);
205 struct omap_dss_device *in = ddata->in;
206 int r;
207
208 /*
209 * No need to check the panel state. It was checked when trasitioning
210 * to AUDIO_ENABLED.
211 */
212 if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED)
213 return -EPERM;
214
215 r = in->ops.hdmi->audio_start(in);
216 if (r)
217 return r;
218
219 dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
220
221 return 0;
222}
223
224static void hdmic_audio_stop(struct omap_dss_device *dssdev)
225{
226 struct panel_drv_data *ddata = to_panel_data(dssdev);
227 struct omap_dss_device *in = ddata->in;
228
229 in->ops.hdmi->audio_stop(in);
230
231 dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
232}
233
234static bool hdmic_audio_supported(struct omap_dss_device *dssdev)
235{
236 struct panel_drv_data *ddata = to_panel_data(dssdev);
237 struct omap_dss_device *in = ddata->in;
238
239 if (!omapdss_device_is_enabled(dssdev))
240 return false;
241
242 return in->ops.hdmi->audio_supported(in);
243}
244
245static int hdmic_audio_config(struct omap_dss_device *dssdev,
246 struct omap_dss_audio *audio)
247{
248 struct panel_drv_data *ddata = to_panel_data(dssdev);
249 struct omap_dss_device *in = ddata->in;
250 int r;
251
252 /* config audio only if the display is active */
253 if (!omapdss_device_is_enabled(dssdev))
254 return -EPERM;
255
256 r = in->ops.hdmi->audio_config(in, audio);
257 if (r)
258 return r;
259
260 dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
261
262 return 0;
263}
264
265static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode) 173static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
266{ 174{
267 struct panel_drv_data *ddata = to_panel_data(dssdev); 175 struct panel_drv_data *ddata = to_panel_data(dssdev);
@@ -296,13 +204,6 @@ static struct omap_dss_driver hdmic_driver = {
296 .detect = hdmic_detect, 204 .detect = hdmic_detect,
297 .set_hdmi_mode = hdmic_set_hdmi_mode, 205 .set_hdmi_mode = hdmic_set_hdmi_mode,
298 .set_hdmi_infoframe = hdmic_set_infoframe, 206 .set_hdmi_infoframe = hdmic_set_infoframe,
299
300 .audio_enable = hdmic_audio_enable,
301 .audio_disable = hdmic_audio_disable,
302 .audio_start = hdmic_audio_start,
303 .audio_stop = hdmic_audio_stop,
304 .audio_supported = hdmic_audio_supported,
305 .audio_config = hdmic_audio_config,
306}; 207};
307 208
308static int hdmic_probe_pdata(struct platform_device *pdev) 209static int hdmic_probe_pdata(struct platform_device *pdev)
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
index 47ee7cdee1c5..e349064ed615 100644
--- a/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c
@@ -249,6 +249,7 @@ static int tfp410_probe(struct platform_device *pdev)
249 dssdev->output_type = OMAP_DISPLAY_TYPE_DVI; 249 dssdev->output_type = OMAP_DISPLAY_TYPE_DVI;
250 dssdev->owner = THIS_MODULE; 250 dssdev->owner = THIS_MODULE;
251 dssdev->phy.dpi.data_lines = ddata->data_lines; 251 dssdev->phy.dpi.data_lines = ddata->data_lines;
252 dssdev->port_num = 1;
252 253
253 r = omapdss_register_output(dssdev); 254 r = omapdss_register_output(dssdev);
254 if (r) { 255 if (r) {
diff --git a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
index c4abd56dd846..c7a3ce2c5120 100644
--- a/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
+++ b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c
@@ -193,55 +193,6 @@ static bool tpd_detect(struct omap_dss_device *dssdev)
193 return gpio_get_value_cansleep(ddata->hpd_gpio); 193 return gpio_get_value_cansleep(ddata->hpd_gpio);
194} 194}
195 195
196static int tpd_audio_enable(struct omap_dss_device *dssdev)
197{
198 struct panel_drv_data *ddata = to_panel_data(dssdev);
199 struct omap_dss_device *in = ddata->in;
200
201 return in->ops.hdmi->audio_enable(in);
202}
203
204static void tpd_audio_disable(struct omap_dss_device *dssdev)
205{
206 struct panel_drv_data *ddata = to_panel_data(dssdev);
207 struct omap_dss_device *in = ddata->in;
208
209 in->ops.hdmi->audio_disable(in);
210}
211
212static int tpd_audio_start(struct omap_dss_device *dssdev)
213{
214 struct panel_drv_data *ddata = to_panel_data(dssdev);
215 struct omap_dss_device *in = ddata->in;
216
217 return in->ops.hdmi->audio_start(in);
218}
219
220static void tpd_audio_stop(struct omap_dss_device *dssdev)
221{
222 struct panel_drv_data *ddata = to_panel_data(dssdev);
223 struct omap_dss_device *in = ddata->in;
224
225 in->ops.hdmi->audio_stop(in);
226}
227
228static bool tpd_audio_supported(struct omap_dss_device *dssdev)
229{
230 struct panel_drv_data *ddata = to_panel_data(dssdev);
231 struct omap_dss_device *in = ddata->in;
232
233 return in->ops.hdmi->audio_supported(in);
234}
235
236static int tpd_audio_config(struct omap_dss_device *dssdev,
237 struct omap_dss_audio *audio)
238{
239 struct panel_drv_data *ddata = to_panel_data(dssdev);
240 struct omap_dss_device *in = ddata->in;
241
242 return in->ops.hdmi->audio_config(in, audio);
243}
244
245static int tpd_set_infoframe(struct omap_dss_device *dssdev, 196static int tpd_set_infoframe(struct omap_dss_device *dssdev,
246 const struct hdmi_avi_infoframe *avi) 197 const struct hdmi_avi_infoframe *avi)
247{ 198{
@@ -275,13 +226,6 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
275 .detect = tpd_detect, 226 .detect = tpd_detect,
276 .set_infoframe = tpd_set_infoframe, 227 .set_infoframe = tpd_set_infoframe,
277 .set_hdmi_mode = tpd_set_hdmi_mode, 228 .set_hdmi_mode = tpd_set_hdmi_mode,
278
279 .audio_enable = tpd_audio_enable,
280 .audio_disable = tpd_audio_disable,
281 .audio_start = tpd_audio_start,
282 .audio_stop = tpd_audio_stop,
283 .audio_supported = tpd_audio_supported,
284 .audio_config = tpd_audio_config,
285}; 229};
286 230
287static int tpd_probe_pdata(struct platform_device *pdev) 231static int tpd_probe_pdata(struct platform_device *pdev)
@@ -409,6 +353,7 @@ static int tpd_probe(struct platform_device *pdev)
409 dssdev->type = OMAP_DISPLAY_TYPE_HDMI; 353 dssdev->type = OMAP_DISPLAY_TYPE_HDMI;
410 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI; 354 dssdev->output_type = OMAP_DISPLAY_TYPE_HDMI;
411 dssdev->owner = THIS_MODULE; 355 dssdev->owner = THIS_MODULE;
356 dssdev->port_num = 1;
412 357
413 in = ddata->in; 358 in = ddata->in;
414 359
diff --git a/drivers/video/fbdev/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig
index 3d5eb6c36c22..d1fa730c7d54 100644
--- a/drivers/video/fbdev/omap2/dss/Kconfig
+++ b/drivers/video/fbdev/omap2/dss/Kconfig
@@ -74,9 +74,6 @@ config OMAP4_DSS_HDMI
74 help 74 help
75 HDMI support for OMAP4 based SoCs. 75 HDMI support for OMAP4 based SoCs.
76 76
77config OMAP4_DSS_HDMI_AUDIO
78 bool
79
80config OMAP5_DSS_HDMI 77config OMAP5_DSS_HDMI
81 bool "HDMI support for OMAP5" 78 bool "HDMI support for OMAP5"
82 default n 79 default n
@@ -86,10 +83,6 @@ config OMAP5_DSS_HDMI
86 Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI 83 Definition Multimedia Interface. See http://www.hdmi.org/ for HDMI
87 specification. 84 specification.
88 85
89config OMAP5_DSS_HDMI_AUDIO
90 depends on OMAP5_DSS_HDMI
91 bool
92
93config OMAP2_DSS_SDI 86config OMAP2_DSS_SDI
94 bool "SDI support" 87 bool "SDI support"
95 default n 88 default n
diff --git a/drivers/video/fbdev/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile
index 245f933060ee..2ea9d382354c 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 5 output.o dss-of.o 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 0e9a74bb9fc2..0729c08ac75a 100644
--- a/drivers/video/fbdev/omap2/dss/dispc.c
+++ b/drivers/video/fbdev/omap2/dss/dispc.c
@@ -3028,7 +3028,7 @@ static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div,
3028 3028
3029unsigned long dispc_fclk_rate(void) 3029unsigned long dispc_fclk_rate(void)
3030{ 3030{
3031 struct platform_device *dsidev; 3031 struct dss_pll *pll;
3032 unsigned long r = 0; 3032 unsigned long r = 0;
3033 3033
3034 switch (dss_get_dispc_clk_source()) { 3034 switch (dss_get_dispc_clk_source()) {
@@ -3036,12 +3036,12 @@ unsigned long dispc_fclk_rate(void)
3036 r = dss_get_dispc_clk_rate(); 3036 r = dss_get_dispc_clk_rate();
3037 break; 3037 break;
3038 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 3038 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3039 dsidev = dsi_get_dsidev_from_id(0); 3039 pll = dss_pll_find("dsi0");
3040 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3040 r = pll->cinfo.clkout[0];
3041 break; 3041 break;
3042 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 3042 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3043 dsidev = dsi_get_dsidev_from_id(1); 3043 pll = dss_pll_find("dsi1");
3044 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3044 r = pll->cinfo.clkout[0];
3045 break; 3045 break;
3046 default: 3046 default:
3047 BUG(); 3047 BUG();
@@ -3053,7 +3053,7 @@ unsigned long dispc_fclk_rate(void)
3053 3053
3054unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) 3054unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
3055{ 3055{
3056 struct platform_device *dsidev; 3056 struct dss_pll *pll;
3057 int lcd; 3057 int lcd;
3058 unsigned long r; 3058 unsigned long r;
3059 u32 l; 3059 u32 l;
@@ -3068,12 +3068,12 @@ unsigned long dispc_mgr_lclk_rate(enum omap_channel channel)
3068 r = dss_get_dispc_clk_rate(); 3068 r = dss_get_dispc_clk_rate();
3069 break; 3069 break;
3070 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 3070 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
3071 dsidev = dsi_get_dsidev_from_id(0); 3071 pll = dss_pll_find("dsi0");
3072 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3072 r = pll->cinfo.clkout[0];
3073 break; 3073 break;
3074 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 3074 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
3075 dsidev = dsi_get_dsidev_from_id(1); 3075 pll = dss_pll_find("dsi1");
3076 r = dsi_get_pll_hsdiv_dispc_rate(dsidev); 3076 r = pll->cinfo.clkout[0];
3077 break; 3077 break;
3078 default: 3078 default:
3079 BUG(); 3079 BUG();
diff --git a/drivers/video/fbdev/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c
index 4a3363dae74a..2edf5caa002f 100644
--- a/drivers/video/fbdev/omap2/dss/dpi.c
+++ b/drivers/video/fbdev/omap2/dss/dpi.c
@@ -31,17 +31,20 @@
31#include <linux/regulator/consumer.h> 31#include <linux/regulator/consumer.h>
32#include <linux/string.h> 32#include <linux/string.h>
33#include <linux/of.h> 33#include <linux/of.h>
34#include <linux/clk.h>
34 35
35#include <video/omapdss.h> 36#include <video/omapdss.h>
36 37
37#include "dss.h" 38#include "dss.h"
38#include "dss_features.h" 39#include "dss_features.h"
39 40
40static struct { 41#define HSDIV_DISPC 0
42
43struct dpi_data {
41 struct platform_device *pdev; 44 struct platform_device *pdev;
42 45
43 struct regulator *vdds_dsi_reg; 46 struct regulator *vdds_dsi_reg;
44 struct platform_device *dsidev; 47 struct dss_pll *pll;
45 48
46 struct mutex lock; 49 struct mutex lock;
47 50
@@ -52,9 +55,20 @@ static struct {
52 struct omap_dss_device output; 55 struct omap_dss_device output;
53 56
54 bool port_initialized; 57 bool port_initialized;
55} dpi; 58};
59
60static struct dpi_data *dpi_get_data_from_dssdev(struct omap_dss_device *dssdev)
61{
62 return container_of(dssdev, struct dpi_data, output);
63}
64
65/* only used in non-DT mode */
66static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev)
67{
68 return dev_get_drvdata(&pdev->dev);
69}
56 70
57static struct platform_device *dpi_get_dsidev(enum omap_channel channel) 71static struct dss_pll *dpi_get_pll(enum omap_channel channel)
58{ 72{
59 /* 73 /*
60 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL 74 * XXX we can't currently use DSI PLL for DPI with OMAP3, as the DSI PLL
@@ -75,9 +89,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
75 case OMAPDSS_VER_OMAP4: 89 case OMAPDSS_VER_OMAP4:
76 switch (channel) { 90 switch (channel) {
77 case OMAP_DSS_CHANNEL_LCD: 91 case OMAP_DSS_CHANNEL_LCD:
78 return dsi_get_dsidev_from_id(0); 92 return dss_pll_find("dsi0");
79 case OMAP_DSS_CHANNEL_LCD2: 93 case OMAP_DSS_CHANNEL_LCD2:
80 return dsi_get_dsidev_from_id(1); 94 return dss_pll_find("dsi1");
81 default: 95 default:
82 return NULL; 96 return NULL;
83 } 97 }
@@ -85,9 +99,9 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel)
85 case OMAPDSS_VER_OMAP5: 99 case OMAPDSS_VER_OMAP5:
86 switch (channel) { 100 switch (channel) {
87 case OMAP_DSS_CHANNEL_LCD: 101 case OMAP_DSS_CHANNEL_LCD:
88 return dsi_get_dsidev_from_id(0); 102 return dss_pll_find("dsi0");
89 case OMAP_DSS_CHANNEL_LCD3: 103 case OMAP_DSS_CHANNEL_LCD3:
90 return dsi_get_dsidev_from_id(1); 104 return dss_pll_find("dsi1");
91 default: 105 default:
92 return NULL; 106 return NULL;
93 } 107 }
@@ -114,7 +128,7 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel)
114} 128}
115 129
116struct dpi_clk_calc_ctx { 130struct dpi_clk_calc_ctx {
117 struct platform_device *dsidev; 131 struct dss_pll *pll;
118 132
119 /* inputs */ 133 /* inputs */
120 134
@@ -122,7 +136,7 @@ struct dpi_clk_calc_ctx {
122 136
123 /* outputs */ 137 /* outputs */
124 138
125 struct dsi_clock_info dsi_cinfo; 139 struct dss_pll_clock_info dsi_cinfo;
126 unsigned long fck; 140 unsigned long fck;
127 struct dispc_clock_info dispc_cinfo; 141 struct dispc_clock_info dispc_cinfo;
128}; 142};
@@ -154,7 +168,7 @@ static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
154} 168}
155 169
156 170
157static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, 171static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
158 void *data) 172 void *data)
159{ 173{
160 struct dpi_clk_calc_ctx *ctx = data; 174 struct dpi_clk_calc_ctx *ctx = data;
@@ -164,30 +178,31 @@ static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
164 * shifted. So skip all odd dividers when the pixel clock is on the 178 * shifted. So skip all odd dividers when the pixel clock is on the
165 * higher side. 179 * higher side.
166 */ 180 */
167 if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 100000000) 181 if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000)
168 return false; 182 return false;
169 183
170 ctx->dsi_cinfo.regm_dispc = regm_dispc; 184 ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
171 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; 185 ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
172 186
173 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, 187 return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max,
174 dpi_calc_dispc_cb, ctx); 188 dpi_calc_dispc_cb, ctx);
175} 189}
176 190
177 191
178static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, 192static bool dpi_calc_pll_cb(int n, int m, unsigned long fint,
179 unsigned long pll, 193 unsigned long clkdco,
180 void *data) 194 void *data)
181{ 195{
182 struct dpi_clk_calc_ctx *ctx = data; 196 struct dpi_clk_calc_ctx *ctx = data;
183 197
184 ctx->dsi_cinfo.regn = regn; 198 ctx->dsi_cinfo.n = n;
185 ctx->dsi_cinfo.regm = regm; 199 ctx->dsi_cinfo.m = m;
186 ctx->dsi_cinfo.fint = fint; 200 ctx->dsi_cinfo.fint = fint;
187 ctx->dsi_cinfo.clkin4ddr = pll; 201 ctx->dsi_cinfo.clkdco = clkdco;
188 202
189 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min, 203 return dss_pll_hsdiv_calc(ctx->pll, clkdco,
190 dpi_calc_hsdiv_cb, ctx); 204 ctx->pck_min, dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
205 dpi_calc_hsdiv_cb, ctx);
191} 206}
192 207
193static bool dpi_calc_dss_cb(unsigned long fck, void *data) 208static bool dpi_calc_dss_cb(unsigned long fck, void *data)
@@ -200,23 +215,23 @@ static bool dpi_calc_dss_cb(unsigned long fck, void *data)
200 dpi_calc_dispc_cb, ctx); 215 dpi_calc_dispc_cb, ctx);
201} 216}
202 217
203static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) 218static bool dpi_dsi_clk_calc(struct dpi_data *dpi, unsigned long pck,
219 struct dpi_clk_calc_ctx *ctx)
204{ 220{
205 unsigned long clkin; 221 unsigned long clkin;
206 unsigned long pll_min, pll_max; 222 unsigned long pll_min, pll_max;
207 223
208 clkin = dsi_get_pll_clkin(dpi.dsidev);
209
210 memset(ctx, 0, sizeof(*ctx)); 224 memset(ctx, 0, sizeof(*ctx));
211 ctx->dsidev = dpi.dsidev; 225 ctx->pll = dpi->pll;
212 ctx->pck_min = pck - 1000; 226 ctx->pck_min = pck - 1000;
213 ctx->pck_max = pck + 1000; 227 ctx->pck_max = pck + 1000;
214 ctx->dsi_cinfo.clkin = clkin;
215 228
216 pll_min = 0; 229 pll_min = 0;
217 pll_max = 0; 230 pll_max = 0;
218 231
219 return dsi_pll_calc(dpi.dsidev, clkin, 232 clkin = clk_get_rate(ctx->pll->clkin);
233
234 return dss_pll_calc(ctx->pll, clkin,
220 pll_min, pll_max, 235 pll_min, pll_max,
221 dpi_calc_pll_cb, ctx); 236 dpi_calc_pll_cb, ctx);
222} 237}
@@ -252,7 +267,7 @@ static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx)
252 267
253 268
254 269
255static int dpi_set_dsi_clk(enum omap_channel channel, 270static int dpi_set_dsi_clk(struct dpi_data *dpi, enum omap_channel channel,
256 unsigned long pck_req, unsigned long *fck, int *lck_div, 271 unsigned long pck_req, unsigned long *fck, int *lck_div,
257 int *pck_div) 272 int *pck_div)
258{ 273{
@@ -260,28 +275,28 @@ static int dpi_set_dsi_clk(enum omap_channel channel,
260 int r; 275 int r;
261 bool ok; 276 bool ok;
262 277
263 ok = dpi_dsi_clk_calc(pck_req, &ctx); 278 ok = dpi_dsi_clk_calc(dpi, pck_req, &ctx);
264 if (!ok) 279 if (!ok)
265 return -EINVAL; 280 return -EINVAL;
266 281
267 r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo); 282 r = dss_pll_set_config(dpi->pll, &ctx.dsi_cinfo);
268 if (r) 283 if (r)
269 return r; 284 return r;
270 285
271 dss_select_lcd_clk_source(channel, 286 dss_select_lcd_clk_source(channel,
272 dpi_get_alt_clk_src(channel)); 287 dpi_get_alt_clk_src(channel));
273 288
274 dpi.mgr_config.clock_info = ctx.dispc_cinfo; 289 dpi->mgr_config.clock_info = ctx.dispc_cinfo;
275 290
276 *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 291 *fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
277 *lck_div = ctx.dispc_cinfo.lck_div; 292 *lck_div = ctx.dispc_cinfo.lck_div;
278 *pck_div = ctx.dispc_cinfo.pck_div; 293 *pck_div = ctx.dispc_cinfo.pck_div;
279 294
280 return 0; 295 return 0;
281} 296}
282 297
283static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, 298static int dpi_set_dispc_clk(struct dpi_data *dpi, unsigned long pck_req,
284 int *lck_div, int *pck_div) 299 unsigned long *fck, int *lck_div, int *pck_div)
285{ 300{
286 struct dpi_clk_calc_ctx ctx; 301 struct dpi_clk_calc_ctx ctx;
287 int r; 302 int r;
@@ -295,7 +310,7 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
295 if (r) 310 if (r)
296 return r; 311 return r;
297 312
298 dpi.mgr_config.clock_info = ctx.dispc_cinfo; 313 dpi->mgr_config.clock_info = ctx.dispc_cinfo;
299 314
300 *fck = ctx.fck; 315 *fck = ctx.fck;
301 *lck_div = ctx.dispc_cinfo.lck_div; 316 *lck_div = ctx.dispc_cinfo.lck_div;
@@ -304,19 +319,21 @@ static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck,
304 return 0; 319 return 0;
305} 320}
306 321
307static int dpi_set_mode(struct omap_overlay_manager *mgr) 322static int dpi_set_mode(struct dpi_data *dpi)
308{ 323{
309 struct omap_video_timings *t = &dpi.timings; 324 struct omap_dss_device *out = &dpi->output;
325 struct omap_overlay_manager *mgr = out->manager;
326 struct omap_video_timings *t = &dpi->timings;
310 int lck_div = 0, pck_div = 0; 327 int lck_div = 0, pck_div = 0;
311 unsigned long fck = 0; 328 unsigned long fck = 0;
312 unsigned long pck; 329 unsigned long pck;
313 int r = 0; 330 int r = 0;
314 331
315 if (dpi.dsidev) 332 if (dpi->pll)
316 r = dpi_set_dsi_clk(mgr->id, t->pixelclock, &fck, 333 r = dpi_set_dsi_clk(dpi, mgr->id, t->pixelclock, &fck,
317 &lck_div, &pck_div); 334 &lck_div, &pck_div);
318 else 335 else
319 r = dpi_set_dispc_clk(t->pixelclock, &fck, 336 r = dpi_set_dispc_clk(dpi, t->pixelclock, &fck,
320 &lck_div, &pck_div); 337 &lck_div, &pck_div);
321 if (r) 338 if (r)
322 return r; 339 return r;
@@ -335,28 +352,32 @@ static int dpi_set_mode(struct omap_overlay_manager *mgr)
335 return 0; 352 return 0;
336} 353}
337 354
338static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr) 355static void dpi_config_lcd_manager(struct dpi_data *dpi)
339{ 356{
340 dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; 357 struct omap_dss_device *out = &dpi->output;
358 struct omap_overlay_manager *mgr = out->manager;
359
360 dpi->mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS;
341 361
342 dpi.mgr_config.stallmode = false; 362 dpi->mgr_config.stallmode = false;
343 dpi.mgr_config.fifohandcheck = false; 363 dpi->mgr_config.fifohandcheck = false;
344 364
345 dpi.mgr_config.video_port_width = dpi.data_lines; 365 dpi->mgr_config.video_port_width = dpi->data_lines;
346 366
347 dpi.mgr_config.lcden_sig_polarity = 0; 367 dpi->mgr_config.lcden_sig_polarity = 0;
348 368
349 dss_mgr_set_lcd_config(mgr, &dpi.mgr_config); 369 dss_mgr_set_lcd_config(mgr, &dpi->mgr_config);
350} 370}
351 371
352static int dpi_display_enable(struct omap_dss_device *dssdev) 372static int dpi_display_enable(struct omap_dss_device *dssdev)
353{ 373{
354 struct omap_dss_device *out = &dpi.output; 374 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
375 struct omap_dss_device *out = &dpi->output;
355 int r; 376 int r;
356 377
357 mutex_lock(&dpi.lock); 378 mutex_lock(&dpi->lock);
358 379
359 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi.vdds_dsi_reg) { 380 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI) && !dpi->vdds_dsi_reg) {
360 DSSERR("no VDSS_DSI regulator\n"); 381 DSSERR("no VDSS_DSI regulator\n");
361 r = -ENODEV; 382 r = -ENODEV;
362 goto err_no_reg; 383 goto err_no_reg;
@@ -369,7 +390,7 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
369 } 390 }
370 391
371 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) { 392 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) {
372 r = regulator_enable(dpi.vdds_dsi_reg); 393 r = regulator_enable(dpi->vdds_dsi_reg);
373 if (r) 394 if (r)
374 goto err_reg_enable; 395 goto err_reg_enable;
375 } 396 }
@@ -378,25 +399,21 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
378 if (r) 399 if (r)
379 goto err_get_dispc; 400 goto err_get_dispc;
380 401
381 r = dss_dpi_select_source(out->manager->id); 402 r = dss_dpi_select_source(out->port_num, out->manager->id);
382 if (r) 403 if (r)
383 goto err_src_sel; 404 goto err_src_sel;
384 405
385 if (dpi.dsidev) { 406 if (dpi->pll) {
386 r = dsi_runtime_get(dpi.dsidev); 407 r = dss_pll_enable(dpi->pll);
387 if (r)
388 goto err_get_dsi;
389
390 r = dsi_pll_init(dpi.dsidev, 0, 1);
391 if (r) 408 if (r)
392 goto err_dsi_pll_init; 409 goto err_dsi_pll_init;
393 } 410 }
394 411
395 r = dpi_set_mode(out->manager); 412 r = dpi_set_mode(dpi);
396 if (r) 413 if (r)
397 goto err_set_mode; 414 goto err_set_mode;
398 415
399 dpi_config_lcd_manager(out->manager); 416 dpi_config_lcd_manager(dpi);
400 417
401 mdelay(2); 418 mdelay(2);
402 419
@@ -404,78 +421,80 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
404 if (r) 421 if (r)
405 goto err_mgr_enable; 422 goto err_mgr_enable;
406 423
407 mutex_unlock(&dpi.lock); 424 mutex_unlock(&dpi->lock);
408 425
409 return 0; 426 return 0;
410 427
411err_mgr_enable: 428err_mgr_enable:
412err_set_mode: 429err_set_mode:
413 if (dpi.dsidev) 430 if (dpi->pll)
414 dsi_pll_uninit(dpi.dsidev, true); 431 dss_pll_disable(dpi->pll);
415err_dsi_pll_init: 432err_dsi_pll_init:
416 if (dpi.dsidev)
417 dsi_runtime_put(dpi.dsidev);
418err_get_dsi:
419err_src_sel: 433err_src_sel:
420 dispc_runtime_put(); 434 dispc_runtime_put();
421err_get_dispc: 435err_get_dispc:
422 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 436 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
423 regulator_disable(dpi.vdds_dsi_reg); 437 regulator_disable(dpi->vdds_dsi_reg);
424err_reg_enable: 438err_reg_enable:
425err_no_out_mgr: 439err_no_out_mgr:
426err_no_reg: 440err_no_reg:
427 mutex_unlock(&dpi.lock); 441 mutex_unlock(&dpi->lock);
428 return r; 442 return r;
429} 443}
430 444
431static void dpi_display_disable(struct omap_dss_device *dssdev) 445static void dpi_display_disable(struct omap_dss_device *dssdev)
432{ 446{
433 struct omap_overlay_manager *mgr = dpi.output.manager; 447 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
448 struct omap_overlay_manager *mgr = dpi->output.manager;
434 449
435 mutex_lock(&dpi.lock); 450 mutex_lock(&dpi->lock);
436 451
437 dss_mgr_disable(mgr); 452 dss_mgr_disable(mgr);
438 453
439 if (dpi.dsidev) { 454 if (dpi->pll) {
440 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); 455 dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK);
441 dsi_pll_uninit(dpi.dsidev, true); 456 dss_pll_disable(dpi->pll);
442 dsi_runtime_put(dpi.dsidev);
443 } 457 }
444 458
445 dispc_runtime_put(); 459 dispc_runtime_put();
446 460
447 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 461 if (dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
448 regulator_disable(dpi.vdds_dsi_reg); 462 regulator_disable(dpi->vdds_dsi_reg);
449 463
450 mutex_unlock(&dpi.lock); 464 mutex_unlock(&dpi->lock);
451} 465}
452 466
453static void dpi_set_timings(struct omap_dss_device *dssdev, 467static void dpi_set_timings(struct omap_dss_device *dssdev,
454 struct omap_video_timings *timings) 468 struct omap_video_timings *timings)
455{ 469{
470 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
471
456 DSSDBG("dpi_set_timings\n"); 472 DSSDBG("dpi_set_timings\n");
457 473
458 mutex_lock(&dpi.lock); 474 mutex_lock(&dpi->lock);
459 475
460 dpi.timings = *timings; 476 dpi->timings = *timings;
461 477
462 mutex_unlock(&dpi.lock); 478 mutex_unlock(&dpi->lock);
463} 479}
464 480
465static void dpi_get_timings(struct omap_dss_device *dssdev, 481static void dpi_get_timings(struct omap_dss_device *dssdev,
466 struct omap_video_timings *timings) 482 struct omap_video_timings *timings)
467{ 483{
468 mutex_lock(&dpi.lock); 484 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
485
486 mutex_lock(&dpi->lock);
469 487
470 *timings = dpi.timings; 488 *timings = dpi->timings;
471 489
472 mutex_unlock(&dpi.lock); 490 mutex_unlock(&dpi->lock);
473} 491}
474 492
475static int dpi_check_timings(struct omap_dss_device *dssdev, 493static int dpi_check_timings(struct omap_dss_device *dssdev,
476 struct omap_video_timings *timings) 494 struct omap_video_timings *timings)
477{ 495{
478 struct omap_overlay_manager *mgr = dpi.output.manager; 496 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
497 struct omap_overlay_manager *mgr = dpi->output.manager;
479 int lck_div, pck_div; 498 int lck_div, pck_div;
480 unsigned long fck; 499 unsigned long fck;
481 unsigned long pck; 500 unsigned long pck;
@@ -488,12 +507,12 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
488 if (timings->pixelclock == 0) 507 if (timings->pixelclock == 0)
489 return -EINVAL; 508 return -EINVAL;
490 509
491 if (dpi.dsidev) { 510 if (dpi->pll) {
492 ok = dpi_dsi_clk_calc(timings->pixelclock, &ctx); 511 ok = dpi_dsi_clk_calc(dpi, timings->pixelclock, &ctx);
493 if (!ok) 512 if (!ok)
494 return -EINVAL; 513 return -EINVAL;
495 514
496 fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; 515 fck = ctx.dsi_cinfo.clkout[HSDIV_DISPC];
497 } else { 516 } else {
498 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx); 517 ok = dpi_dss_clk_calc(timings->pixelclock, &ctx);
499 if (!ok) 518 if (!ok)
@@ -514,74 +533,69 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
514 533
515static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) 534static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines)
516{ 535{
517 mutex_lock(&dpi.lock); 536 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
518 537
519 dpi.data_lines = data_lines; 538 mutex_lock(&dpi->lock);
520 539
521 mutex_unlock(&dpi.lock); 540 dpi->data_lines = data_lines;
541
542 mutex_unlock(&dpi->lock);
522} 543}
523 544
524static int dpi_verify_dsi_pll(struct platform_device *dsidev) 545static int dpi_verify_dsi_pll(struct dss_pll *pll)
525{ 546{
526 int r; 547 int r;
527 548
528 /* do initial setup with the PLL to see if it is operational */ 549 /* do initial setup with the PLL to see if it is operational */
529 550
530 r = dsi_runtime_get(dsidev); 551 r = dss_pll_enable(pll);
531 if (r) 552 if (r)
532 return r; 553 return r;
533 554
534 r = dsi_pll_init(dsidev, 0, 1); 555 dss_pll_disable(pll);
535 if (r) {
536 dsi_runtime_put(dsidev);
537 return r;
538 }
539
540 dsi_pll_uninit(dsidev, true);
541 dsi_runtime_put(dsidev);
542 556
543 return 0; 557 return 0;
544} 558}
545 559
546static int dpi_init_regulator(void) 560static int dpi_init_regulator(struct dpi_data *dpi)
547{ 561{
548 struct regulator *vdds_dsi; 562 struct regulator *vdds_dsi;
549 563
550 if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI)) 564 if (!dss_has_feature(FEAT_DPI_USES_VDDS_DSI))
551 return 0; 565 return 0;
552 566
553 if (dpi.vdds_dsi_reg) 567 if (dpi->vdds_dsi_reg)
554 return 0; 568 return 0;
555 569
556 vdds_dsi = devm_regulator_get(&dpi.pdev->dev, "vdds_dsi"); 570 vdds_dsi = devm_regulator_get(&dpi->pdev->dev, "vdds_dsi");
557 if (IS_ERR(vdds_dsi)) { 571 if (IS_ERR(vdds_dsi)) {
558 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER) 572 if (PTR_ERR(vdds_dsi) != -EPROBE_DEFER)
559 DSSERR("can't get VDDS_DSI regulator\n"); 573 DSSERR("can't get VDDS_DSI regulator\n");
560 return PTR_ERR(vdds_dsi); 574 return PTR_ERR(vdds_dsi);
561 } 575 }
562 576
563 dpi.vdds_dsi_reg = vdds_dsi; 577 dpi->vdds_dsi_reg = vdds_dsi;
564 578
565 return 0; 579 return 0;
566} 580}
567 581
568static void dpi_init_pll(void) 582static void dpi_init_pll(struct dpi_data *dpi)
569{ 583{
570 struct platform_device *dsidev; 584 struct dss_pll *pll;
571 585
572 if (dpi.dsidev) 586 if (dpi->pll)
573 return; 587 return;
574 588
575 dsidev = dpi_get_dsidev(dpi.output.dispc_channel); 589 pll = dpi_get_pll(dpi->output.dispc_channel);
576 if (!dsidev) 590 if (!pll)
577 return; 591 return;
578 592
579 if (dpi_verify_dsi_pll(dsidev)) { 593 if (dpi_verify_dsi_pll(pll)) {
580 DSSWARN("DSI PLL not operational\n"); 594 DSSWARN("DSI PLL not operational\n");
581 return; 595 return;
582 } 596 }
583 597
584 dpi.dsidev = dsidev; 598 dpi->pll = pll;
585} 599}
586 600
587/* 601/*
@@ -590,7 +604,7 @@ static void dpi_init_pll(void)
590 * the channel in some more dynamic manner, or get the channel as a user 604 * the channel in some more dynamic manner, or get the channel as a user
591 * parameter. 605 * parameter.
592 */ 606 */
593static enum omap_channel dpi_get_channel(void) 607static enum omap_channel dpi_get_channel(int port_num)
594{ 608{
595 switch (omapdss_get_version()) { 609 switch (omapdss_get_version()) {
596 case OMAPDSS_VER_OMAP24xx: 610 case OMAPDSS_VER_OMAP24xx:
@@ -618,14 +632,15 @@ static enum omap_channel dpi_get_channel(void)
618static int dpi_connect(struct omap_dss_device *dssdev, 632static int dpi_connect(struct omap_dss_device *dssdev,
619 struct omap_dss_device *dst) 633 struct omap_dss_device *dst)
620{ 634{
635 struct dpi_data *dpi = dpi_get_data_from_dssdev(dssdev);
621 struct omap_overlay_manager *mgr; 636 struct omap_overlay_manager *mgr;
622 int r; 637 int r;
623 638
624 r = dpi_init_regulator(); 639 r = dpi_init_regulator(dpi);
625 if (r) 640 if (r)
626 return r; 641 return r;
627 642
628 dpi_init_pll(); 643 dpi_init_pll(dpi);
629 644
630 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel); 645 mgr = omap_dss_get_overlay_manager(dssdev->dispc_channel);
631 if (!mgr) 646 if (!mgr)
@@ -676,13 +691,14 @@ static const struct omapdss_dpi_ops dpi_ops = {
676 691
677static void dpi_init_output(struct platform_device *pdev) 692static void dpi_init_output(struct platform_device *pdev)
678{ 693{
679 struct omap_dss_device *out = &dpi.output; 694 struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
695 struct omap_dss_device *out = &dpi->output;
680 696
681 out->dev = &pdev->dev; 697 out->dev = &pdev->dev;
682 out->id = OMAP_DSS_OUTPUT_DPI; 698 out->id = OMAP_DSS_OUTPUT_DPI;
683 out->output_type = OMAP_DISPLAY_TYPE_DPI; 699 out->output_type = OMAP_DISPLAY_TYPE_DPI;
684 out->name = "dpi.0"; 700 out->name = "dpi.0";
685 out->dispc_channel = dpi_get_channel(); 701 out->dispc_channel = dpi_get_channel(0);
686 out->ops.dpi = &dpi_ops; 702 out->ops.dpi = &dpi_ops;
687 out->owner = THIS_MODULE; 703 out->owner = THIS_MODULE;
688 704
@@ -691,16 +707,69 @@ static void dpi_init_output(struct platform_device *pdev)
691 707
692static void __exit dpi_uninit_output(struct platform_device *pdev) 708static void __exit dpi_uninit_output(struct platform_device *pdev)
693{ 709{
694 struct omap_dss_device *out = &dpi.output; 710 struct dpi_data *dpi = dpi_get_data_from_pdev(pdev);
711 struct omap_dss_device *out = &dpi->output;
712
713 omapdss_unregister_output(out);
714}
715
716static void dpi_init_output_port(struct platform_device *pdev,
717 struct device_node *port)
718{
719 struct dpi_data *dpi = port->data;
720 struct omap_dss_device *out = &dpi->output;
721 int r;
722 u32 port_num;
723
724 r = of_property_read_u32(port, "reg", &port_num);
725 if (r)
726 port_num = 0;
727
728 switch (port_num) {
729 case 2:
730 out->name = "dpi.2";
731 break;
732 case 1:
733 out->name = "dpi.1";
734 break;
735 case 0:
736 default:
737 out->name = "dpi.0";
738 break;
739 }
740
741 out->dev = &pdev->dev;
742 out->id = OMAP_DSS_OUTPUT_DPI;
743 out->output_type = OMAP_DISPLAY_TYPE_DPI;
744 out->dispc_channel = dpi_get_channel(port_num);
745 out->port_num = port_num;
746 out->ops.dpi = &dpi_ops;
747 out->owner = THIS_MODULE;
748
749 omapdss_register_output(out);
750}
751
752static void __exit dpi_uninit_output_port(struct device_node *port)
753{
754 struct dpi_data *dpi = port->data;
755 struct omap_dss_device *out = &dpi->output;
695 756
696 omapdss_unregister_output(out); 757 omapdss_unregister_output(out);
697} 758}
698 759
699static int omap_dpi_probe(struct platform_device *pdev) 760static int omap_dpi_probe(struct platform_device *pdev)
700{ 761{
701 dpi.pdev = pdev; 762 struct dpi_data *dpi;
763
764 dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
765 if (!dpi)
766 return -ENOMEM;
702 767
703 mutex_init(&dpi.lock); 768 dpi->pdev = pdev;
769
770 dev_set_drvdata(&pdev->dev, dpi);
771
772 mutex_init(&dpi->lock);
704 773
705 dpi_init_output(pdev); 774 dpi_init_output(pdev);
706 775
@@ -736,10 +805,15 @@ void __exit dpi_uninit_platform_driver(void)
736 805
737int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) 806int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
738{ 807{
808 struct dpi_data *dpi;
739 struct device_node *ep; 809 struct device_node *ep;
740 u32 datalines; 810 u32 datalines;
741 int r; 811 int r;
742 812
813 dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL);
814 if (!dpi)
815 return -ENOMEM;
816
743 ep = omapdss_of_get_next_endpoint(port, NULL); 817 ep = omapdss_of_get_next_endpoint(port, NULL);
744 if (!ep) 818 if (!ep)
745 return 0; 819 return 0;
@@ -750,17 +824,18 @@ int __init dpi_init_port(struct platform_device *pdev, struct device_node *port)
750 goto err_datalines; 824 goto err_datalines;
751 } 825 }
752 826
753 dpi.data_lines = datalines; 827 dpi->data_lines = datalines;
754 828
755 of_node_put(ep); 829 of_node_put(ep);
756 830
757 dpi.pdev = pdev; 831 dpi->pdev = pdev;
832 port->data = dpi;
758 833
759 mutex_init(&dpi.lock); 834 mutex_init(&dpi->lock);
760 835
761 dpi_init_output(pdev); 836 dpi_init_output_port(pdev, port);
762 837
763 dpi.port_initialized = true; 838 dpi->port_initialized = true;
764 839
765 return 0; 840 return 0;
766 841
@@ -770,10 +845,12 @@ err_datalines:
770 return r; 845 return r;
771} 846}
772 847
773void __exit dpi_uninit_port(void) 848void __exit dpi_uninit_port(struct device_node *port)
774{ 849{
775 if (!dpi.port_initialized) 850 struct dpi_data *dpi = port->data;
851
852 if (!dpi->port_initialized)
776 return; 853 return;
777 854
778 dpi_uninit_output(dpi.pdev); 855 dpi_uninit_output_port(port);
779} 856}
diff --git a/drivers/video/fbdev/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c
index 0793bc67a275..73af35159468 100644
--- a/drivers/video/fbdev/omap2/dss/dsi.c
+++ b/drivers/video/fbdev/omap2/dss/dsi.c
@@ -219,6 +219,10 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
219 219
220static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); 220static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
221 221
222/* DSI PLL HSDIV indices */
223#define HSDIV_DISPC 0
224#define HSDIV_DSI 1
225
222#define DSI_MAX_NR_ISRS 2 226#define DSI_MAX_NR_ISRS 2
223#define DSI_MAX_NR_LANES 5 227#define DSI_MAX_NR_LANES 5
224 228
@@ -271,6 +275,7 @@ struct dsi_isr_tables {
271 275
272struct dsi_clk_calc_ctx { 276struct dsi_clk_calc_ctx {
273 struct platform_device *dsidev; 277 struct platform_device *dsidev;
278 struct dss_pll *pll;
274 279
275 /* inputs */ 280 /* inputs */
276 281
@@ -280,13 +285,18 @@ struct dsi_clk_calc_ctx {
280 285
281 /* outputs */ 286 /* outputs */
282 287
283 struct dsi_clock_info dsi_cinfo; 288 struct dss_pll_clock_info dsi_cinfo;
284 struct dispc_clock_info dispc_cinfo; 289 struct dispc_clock_info dispc_cinfo;
285 290
286 struct omap_video_timings dispc_vm; 291 struct omap_video_timings dispc_vm;
287 struct omap_dss_dsi_videomode_timings dsi_vm; 292 struct omap_dss_dsi_videomode_timings dsi_vm;
288}; 293};
289 294
295struct dsi_lp_clock_info {
296 unsigned long lp_clk;
297 u16 lp_clk_div;
298};
299
290struct dsi_data { 300struct dsi_data {
291 struct platform_device *pdev; 301 struct platform_device *pdev;
292 void __iomem *proto_base; 302 void __iomem *proto_base;
@@ -300,12 +310,14 @@ struct dsi_data {
300 bool is_enabled; 310 bool is_enabled;
301 311
302 struct clk *dss_clk; 312 struct clk *dss_clk;
303 struct clk *sys_clk;
304 313
305 struct dispc_clock_info user_dispc_cinfo; 314 struct dispc_clock_info user_dispc_cinfo;
306 struct dsi_clock_info user_dsi_cinfo; 315 struct dss_pll_clock_info user_dsi_cinfo;
316
317 struct dsi_lp_clock_info user_lp_cinfo;
318 struct dsi_lp_clock_info current_lp_cinfo;
307 319
308 struct dsi_clock_info current_cinfo; 320 struct dss_pll pll;
309 321
310 bool vdds_dsi_enabled; 322 bool vdds_dsi_enabled;
311 struct regulator *vdds_dsi_reg; 323 struct regulator *vdds_dsi_reg;
@@ -321,8 +333,6 @@ struct dsi_data {
321 struct mutex lock; 333 struct mutex lock;
322 struct semaphore bus_lock; 334 struct semaphore bus_lock;
323 335
324 unsigned pll_locked;
325
326 spinlock_t irq_lock; 336 spinlock_t irq_lock;
327 struct dsi_isr_tables isr_tables; 337 struct dsi_isr_tables isr_tables;
328 /* space for a copy used by the interrupt handler */ 338 /* space for a copy used by the interrupt handler */
@@ -347,7 +357,7 @@ struct dsi_data {
347 357
348 unsigned long cache_req_pck; 358 unsigned long cache_req_pck;
349 unsigned long cache_clk_freq; 359 unsigned long cache_clk_freq;
350 struct dsi_clock_info cache_cinfo; 360 struct dss_pll_clock_info cache_cinfo;
351 361
352 u32 errors; 362 u32 errors;
353 spinlock_t errors_lock; 363 spinlock_t errors_lock;
@@ -362,11 +372,6 @@ struct dsi_data {
362 spinlock_t irq_stats_lock; 372 spinlock_t irq_stats_lock;
363 struct dsi_irq_stats irq_stats; 373 struct dsi_irq_stats irq_stats;
364#endif 374#endif
365 /* DSI PLL Parameter Ranges */
366 unsigned long regm_max, regn_max;
367 unsigned long regm_dispc_max, regm_dsi_max;
368 unsigned long fint_min, fint_max;
369 unsigned long lpdiv_max;
370 375
371 unsigned num_lanes_supported; 376 unsigned num_lanes_supported;
372 unsigned line_buffer_size; 377 unsigned line_buffer_size;
@@ -412,7 +417,7 @@ static inline struct platform_device *dsi_get_dsidev_from_dssdev(struct omap_dss
412 return to_platform_device(dssdev->dev); 417 return to_platform_device(dssdev->dev);
413} 418}
414 419
415struct platform_device *dsi_get_dsidev_from_id(int module) 420static struct platform_device *dsi_get_dsidev_from_id(int module)
416{ 421{
417 struct omap_dss_device *out; 422 struct omap_dss_device *out;
418 enum omap_dss_output_id id; 423 enum omap_dss_output_id id;
@@ -1134,7 +1139,7 @@ static u32 dsi_get_errors(struct platform_device *dsidev)
1134 return e; 1139 return e;
1135} 1140}
1136 1141
1137int dsi_runtime_get(struct platform_device *dsidev) 1142static int dsi_runtime_get(struct platform_device *dsidev)
1138{ 1143{
1139 int r; 1144 int r;
1140 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1145 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -1146,7 +1151,7 @@ int dsi_runtime_get(struct platform_device *dsidev)
1146 return r < 0 ? r : 0; 1151 return r < 0 ? r : 0;
1147} 1152}
1148 1153
1149void dsi_runtime_put(struct platform_device *dsidev) 1154static void dsi_runtime_put(struct platform_device *dsidev)
1150{ 1155{
1151 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1156 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1152 int r; 1157 int r;
@@ -1188,23 +1193,6 @@ static int dsi_regulator_init(struct platform_device *dsidev)
1188 return 0; 1193 return 0;
1189} 1194}
1190 1195
1191/* source clock for DSI PLL. this could also be PCLKFREE */
1192static inline void dsi_enable_pll_clock(struct platform_device *dsidev,
1193 bool enable)
1194{
1195 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1196
1197 if (enable)
1198 clk_prepare_enable(dsi->sys_clk);
1199 else
1200 clk_disable_unprepare(dsi->sys_clk);
1201
1202 if (enable && dsi->pll_locked) {
1203 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1)
1204 DSSERR("cannot lock PLL when enabling clocks\n");
1205 }
1206}
1207
1208static void _dsi_print_reset_status(struct platform_device *dsidev) 1196static void _dsi_print_reset_status(struct platform_device *dsidev)
1209{ 1197{
1210 u32 l; 1198 u32 l;
@@ -1256,25 +1244,25 @@ static inline int dsi_if_enable(struct platform_device *dsidev, bool enable)
1256 return 0; 1244 return 0;
1257} 1245}
1258 1246
1259unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) 1247static unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
1260{ 1248{
1261 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1249 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1262 1250
1263 return dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk; 1251 return dsi->pll.cinfo.clkout[HSDIV_DISPC];
1264} 1252}
1265 1253
1266static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev) 1254static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev)
1267{ 1255{
1268 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1256 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1269 1257
1270 return dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk; 1258 return dsi->pll.cinfo.clkout[HSDIV_DSI];
1271} 1259}
1272 1260
1273static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) 1261static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
1274{ 1262{
1275 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1263 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1276 1264
1277 return dsi->current_cinfo.clkin4ddr / 16; 1265 return dsi->pll.cinfo.clkdco / 16;
1278} 1266}
1279 1267
1280static unsigned long dsi_fclk_rate(struct platform_device *dsidev) 1268static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
@@ -1293,10 +1281,10 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
1293 return r; 1281 return r;
1294} 1282}
1295 1283
1296static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo, 1284static int dsi_lp_clock_calc(unsigned long dsi_fclk,
1297 unsigned long lp_clk_min, unsigned long lp_clk_max) 1285 unsigned long lp_clk_min, unsigned long lp_clk_max,
1286 struct dsi_lp_clock_info *lp_cinfo)
1298{ 1287{
1299 unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk;
1300 unsigned lp_clk_div; 1288 unsigned lp_clk_div;
1301 unsigned long lp_clk; 1289 unsigned long lp_clk;
1302 1290
@@ -1306,8 +1294,8 @@ static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo,
1306 if (lp_clk < lp_clk_min || lp_clk > lp_clk_max) 1294 if (lp_clk < lp_clk_min || lp_clk > lp_clk_max)
1307 return -EINVAL; 1295 return -EINVAL;
1308 1296
1309 cinfo->lp_clk_div = lp_clk_div; 1297 lp_cinfo->lp_clk_div = lp_clk_div;
1310 cinfo->lp_clk = lp_clk; 1298 lp_cinfo->lp_clk = lp_clk;
1311 1299
1312 return 0; 1300 return 0;
1313} 1301}
@@ -1318,10 +1306,12 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
1318 unsigned long dsi_fclk; 1306 unsigned long dsi_fclk;
1319 unsigned lp_clk_div; 1307 unsigned lp_clk_div;
1320 unsigned long lp_clk; 1308 unsigned long lp_clk;
1309 unsigned lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
1310
1321 1311
1322 lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div; 1312 lp_clk_div = dsi->user_lp_cinfo.lp_clk_div;
1323 1313
1324 if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) 1314 if (lp_clk_div == 0 || lp_clk_div > lpdiv_max)
1325 return -EINVAL; 1315 return -EINVAL;
1326 1316
1327 dsi_fclk = dsi_fclk_rate(dsidev); 1317 dsi_fclk = dsi_fclk_rate(dsidev);
@@ -1329,8 +1319,8 @@ static int dsi_set_lp_clk_divisor(struct platform_device *dsidev)
1329 lp_clk = dsi_fclk / 2 / lp_clk_div; 1319 lp_clk = dsi_fclk / 2 / lp_clk_div;
1330 1320
1331 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk); 1321 DSSDBG("LP_CLK_DIV %u, LP_CLK %lu\n", lp_clk_div, lp_clk);
1332 dsi->current_cinfo.lp_clk = lp_clk; 1322 dsi->current_lp_cinfo.lp_clk = lp_clk;
1333 dsi->current_cinfo.lp_clk_div = lp_clk_div; 1323 dsi->current_lp_cinfo.lp_clk_div = lp_clk_div;
1334 1324
1335 /* LP_CLK_DIVISOR */ 1325 /* LP_CLK_DIVISOR */
1336 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0); 1326 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, lp_clk_div, 12, 0);
@@ -1391,286 +1381,33 @@ static int dsi_pll_power(struct platform_device *dsidev,
1391 return 0; 1381 return 0;
1392} 1382}
1393 1383
1394unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
1395{
1396 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1397 return clk_get_rate(dsi->sys_clk);
1398}
1399
1400bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
1401 unsigned long out_min, dsi_hsdiv_calc_func func, void *data)
1402{
1403 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1404 int regm, regm_start, regm_stop;
1405 unsigned long out_max;
1406 unsigned long out;
1407
1408 out_min = out_min ? out_min : 1;
1409 out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK);
1410
1411 regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul);
1412 regm_stop = min(pll / out_min, dsi->regm_dispc_max);
1413
1414 for (regm = regm_start; regm <= regm_stop; ++regm) {
1415 out = pll / regm;
1416
1417 if (func(regm, out, data))
1418 return true;
1419 }
1420
1421 return false;
1422}
1423
1424bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
1425 unsigned long pll_min, unsigned long pll_max,
1426 dsi_pll_calc_func func, void *data)
1427{
1428 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1429 int regn, regn_start, regn_stop;
1430 int regm, regm_start, regm_stop;
1431 unsigned long fint, pll;
1432 const unsigned long pll_hw_max = 1800000000;
1433 unsigned long fint_hw_min, fint_hw_max;
1434
1435 fint_hw_min = dsi->fint_min;
1436 fint_hw_max = dsi->fint_max;
1437 1384
1438 regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); 1385static void dsi_pll_calc_dsi_fck(struct dss_pll_clock_info *cinfo)
1439 regn_stop = min(clkin / fint_hw_min, dsi->regn_max);
1440
1441 pll_max = pll_max ? pll_max : ULONG_MAX;
1442
1443 for (regn = regn_start; regn <= regn_stop; ++regn) {
1444 fint = clkin / regn;
1445
1446 regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
1447 1ul);
1448 regm_stop = min3(pll_max / fint / 2,
1449 pll_hw_max / fint / 2,
1450 dsi->regm_max);
1451
1452 for (regm = regm_start; regm <= regm_stop; ++regm) {
1453 pll = 2 * regm * fint;
1454
1455 if (func(regn, regm, fint, pll, data))
1456 return true;
1457 }
1458 }
1459
1460 return false;
1461}
1462
1463/* calculate clock rates using dividers in cinfo */
1464static int dsi_calc_clock_rates(struct platform_device *dsidev,
1465 struct dsi_clock_info *cinfo)
1466{
1467 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1468
1469 if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
1470 return -EINVAL;
1471
1472 if (cinfo->regm == 0 || cinfo->regm > dsi->regm_max)
1473 return -EINVAL;
1474
1475 if (cinfo->regm_dispc > dsi->regm_dispc_max)
1476 return -EINVAL;
1477
1478 if (cinfo->regm_dsi > dsi->regm_dsi_max)
1479 return -EINVAL;
1480
1481 cinfo->clkin = clk_get_rate(dsi->sys_clk);
1482 cinfo->fint = cinfo->clkin / cinfo->regn;
1483
1484 if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
1485 return -EINVAL;
1486
1487 cinfo->clkin4ddr = 2 * cinfo->regm * cinfo->fint;
1488
1489 if (cinfo->clkin4ddr > 1800 * 1000 * 1000)
1490 return -EINVAL;
1491
1492 if (cinfo->regm_dispc > 0)
1493 cinfo->dsi_pll_hsdiv_dispc_clk =
1494 cinfo->clkin4ddr / cinfo->regm_dispc;
1495 else
1496 cinfo->dsi_pll_hsdiv_dispc_clk = 0;
1497
1498 if (cinfo->regm_dsi > 0)
1499 cinfo->dsi_pll_hsdiv_dsi_clk =
1500 cinfo->clkin4ddr / cinfo->regm_dsi;
1501 else
1502 cinfo->dsi_pll_hsdiv_dsi_clk = 0;
1503
1504 return 0;
1505}
1506
1507static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo)
1508{ 1386{
1509 unsigned long max_dsi_fck; 1387 unsigned long max_dsi_fck;
1510 1388
1511 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK); 1389 max_dsi_fck = dss_feat_get_param_max(FEAT_PARAM_DSI_FCK);
1512 1390
1513 cinfo->regm_dsi = DIV_ROUND_UP(cinfo->clkin4ddr, max_dsi_fck); 1391 cinfo->mX[HSDIV_DSI] = DIV_ROUND_UP(cinfo->clkdco, max_dsi_fck);
1514 cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; 1392 cinfo->clkout[HSDIV_DSI] = cinfo->clkdco / cinfo->mX[HSDIV_DSI];
1515} 1393}
1516 1394
1517int dsi_pll_set_clock_div(struct platform_device *dsidev, 1395static int dsi_pll_enable(struct dss_pll *pll)
1518 struct dsi_clock_info *cinfo)
1519{ 1396{
1520 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1397 struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
1398 struct platform_device *dsidev = dsi->pdev;
1521 int r = 0; 1399 int r = 0;
1522 u32 l;
1523 int f = 0;
1524 u8 regn_start, regn_end, regm_start, regm_end;
1525 u8 regm_dispc_start, regm_dispc_end, regm_dsi_start, regm_dsi_end;
1526
1527 DSSDBG("DSI PLL clock config starts");
1528
1529 dsi->current_cinfo.clkin = cinfo->clkin;
1530 dsi->current_cinfo.fint = cinfo->fint;
1531 dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
1532 dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
1533 cinfo->dsi_pll_hsdiv_dispc_clk;
1534 dsi->current_cinfo.dsi_pll_hsdiv_dsi_clk =
1535 cinfo->dsi_pll_hsdiv_dsi_clk;
1536
1537 dsi->current_cinfo.regn = cinfo->regn;
1538 dsi->current_cinfo.regm = cinfo->regm;
1539 dsi->current_cinfo.regm_dispc = cinfo->regm_dispc;
1540 dsi->current_cinfo.regm_dsi = cinfo->regm_dsi;
1541
1542 DSSDBG("DSI Fint %ld\n", cinfo->fint);
1543
1544 DSSDBG("clkin rate %ld\n", cinfo->clkin);
1545
1546 /* DSIPHY == CLKIN4DDR */
1547 DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
1548 cinfo->regm,
1549 cinfo->regn,
1550 cinfo->clkin,
1551 cinfo->clkin4ddr);
1552
1553 DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
1554 cinfo->clkin4ddr / 1000 / 1000 / 2);
1555
1556 DSSDBG("Clock lane freq %ld Hz\n", cinfo->clkin4ddr / 4);
1557
1558 DSSDBG("regm_dispc = %d, %s (%s) = %lu\n", cinfo->regm_dispc,
1559 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1560 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
1561 cinfo->dsi_pll_hsdiv_dispc_clk);
1562 DSSDBG("regm_dsi = %d, %s (%s) = %lu\n", cinfo->regm_dsi,
1563 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1564 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
1565 cinfo->dsi_pll_hsdiv_dsi_clk);
1566
1567 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGN, &regn_start, &regn_end);
1568 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, &regm_start, &regm_end);
1569 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, &regm_dispc_start,
1570 &regm_dispc_end);
1571 dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, &regm_dsi_start,
1572 &regm_dsi_end);
1573
1574 /* DSI_PLL_AUTOMODE = manual */
1575 REG_FLD_MOD(dsidev, DSI_PLL_CONTROL, 0, 0, 0);
1576
1577 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION1);
1578 l = FLD_MOD(l, 1, 0, 0); /* DSI_PLL_STOPMODE */
1579 /* DSI_PLL_REGN */
1580 l = FLD_MOD(l, cinfo->regn - 1, regn_start, regn_end);
1581 /* DSI_PLL_REGM */
1582 l = FLD_MOD(l, cinfo->regm, regm_start, regm_end);
1583 /* DSI_CLOCK_DIV */
1584 l = FLD_MOD(l, cinfo->regm_dispc > 0 ? cinfo->regm_dispc - 1 : 0,
1585 regm_dispc_start, regm_dispc_end);
1586 /* DSIPROTO_CLOCK_DIV */
1587 l = FLD_MOD(l, cinfo->regm_dsi > 0 ? cinfo->regm_dsi - 1 : 0,
1588 regm_dsi_start, regm_dsi_end);
1589 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION1, l);
1590
1591 BUG_ON(cinfo->fint < dsi->fint_min || cinfo->fint > dsi->fint_max);
1592
1593 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1594
1595 if (dss_has_feature(FEAT_DSI_PLL_FREQSEL)) {
1596 f = cinfo->fint < 1000000 ? 0x3 :
1597 cinfo->fint < 1250000 ? 0x4 :
1598 cinfo->fint < 1500000 ? 0x5 :
1599 cinfo->fint < 1750000 ? 0x6 :
1600 0x7;
1601
1602 l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
1603 } else if (dss_has_feature(FEAT_DSI_PLL_SELFREQDCO)) {
1604 f = cinfo->clkin4ddr < 1000000000 ? 0x2 : 0x4;
1605
1606 l = FLD_MOD(l, f, 3, 1); /* PLL_SELFREQDCO */
1607 }
1608
1609 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1610 l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
1611 l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
1612 if (dss_has_feature(FEAT_DSI_PLL_REFSEL))
1613 l = FLD_MOD(l, 3, 22, 21); /* REF_SYSCLK = sysclk */
1614 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1615
1616 REG_FLD_MOD(dsidev, DSI_PLL_GO, 1, 0, 0); /* DSI_PLL_GO */
1617
1618 if (wait_for_bit_change(dsidev, DSI_PLL_GO, 0, 0) != 0) {
1619 DSSERR("dsi pll go bit not going down.\n");
1620 r = -EIO;
1621 goto err;
1622 }
1623
1624 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 1, 1) != 1) {
1625 DSSERR("cannot lock PLL\n");
1626 r = -EIO;
1627 goto err;
1628 }
1629
1630 dsi->pll_locked = 1;
1631
1632 l = dsi_read_reg(dsidev, DSI_PLL_CONFIGURATION2);
1633 l = FLD_MOD(l, 0, 0, 0); /* DSI_PLL_IDLE */
1634 l = FLD_MOD(l, 0, 5, 5); /* DSI_PLL_PLLLPMODE */
1635 l = FLD_MOD(l, 0, 6, 6); /* DSI_PLL_LOWCURRSTBY */
1636 l = FLD_MOD(l, 0, 7, 7); /* DSI_PLL_TIGHTPHASELOCK */
1637 l = FLD_MOD(l, 0, 8, 8); /* DSI_PLL_DRIFTGUARDEN */
1638 l = FLD_MOD(l, 0, 10, 9); /* DSI_PLL_LOCKSEL */
1639 l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
1640 l = FLD_MOD(l, 1, 14, 14); /* DSIPHY_CLKINEN */
1641 l = FLD_MOD(l, 0, 15, 15); /* DSI_BYPASSEN */
1642 l = FLD_MOD(l, 1, 16, 16); /* DSS_CLOCK_EN */
1643 l = FLD_MOD(l, 0, 17, 17); /* DSS_CLOCK_PWDN */
1644 l = FLD_MOD(l, 1, 18, 18); /* DSI_PROTO_CLOCK_EN */
1645 l = FLD_MOD(l, 0, 19, 19); /* DSI_PROTO_CLOCK_PWDN */
1646 l = FLD_MOD(l, 0, 20, 20); /* DSI_HSDIVBYPASS */
1647 dsi_write_reg(dsidev, DSI_PLL_CONFIGURATION2, l);
1648
1649 DSSDBG("PLL config done\n");
1650err:
1651 return r;
1652}
1653
1654int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1655 bool enable_hsdiv)
1656{
1657 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1658 int r = 0;
1659 enum dsi_pll_power_state pwstate;
1660 1400
1661 DSSDBG("PLL init\n"); 1401 DSSDBG("PLL init\n");
1662 1402
1663 /*
1664 * It seems that on many OMAPs we need to enable both to have a
1665 * functional HSDivider.
1666 */
1667 enable_hsclk = enable_hsdiv = true;
1668
1669 r = dsi_regulator_init(dsidev); 1403 r = dsi_regulator_init(dsidev);
1670 if (r) 1404 if (r)
1671 return r; 1405 return r;
1672 1406
1673 dsi_enable_pll_clock(dsidev, 1); 1407 r = dsi_runtime_get(dsidev);
1408 if (r)
1409 return r;
1410
1674 /* 1411 /*
1675 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4. 1412 * Note: SCP CLK is not required on OMAP3, but it is required on OMAP4.
1676 */ 1413 */
@@ -1697,16 +1434,7 @@ int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
1697 * fill the whole display. No idea about this */ 1434 * fill the whole display. No idea about this */
1698 dispc_pck_free_enable(0); 1435 dispc_pck_free_enable(0);
1699 1436
1700 if (enable_hsclk && enable_hsdiv) 1437 r = dsi_pll_power(dsidev, DSI_PLL_POWER_ON_ALL);
1701 pwstate = DSI_PLL_POWER_ON_ALL;
1702 else if (enable_hsclk)
1703 pwstate = DSI_PLL_POWER_ON_HSCLK;
1704 else if (enable_hsdiv)
1705 pwstate = DSI_PLL_POWER_ON_DIV;
1706 else
1707 pwstate = DSI_PLL_POWER_OFF;
1708
1709 r = dsi_pll_power(dsidev, pwstate);
1710 1438
1711 if (r) 1439 if (r)
1712 goto err1; 1440 goto err1;
@@ -1721,15 +1449,14 @@ err1:
1721 } 1449 }
1722err0: 1450err0:
1723 dsi_disable_scp_clk(dsidev); 1451 dsi_disable_scp_clk(dsidev);
1724 dsi_enable_pll_clock(dsidev, 0); 1452 dsi_runtime_put(dsidev);
1725 return r; 1453 return r;
1726} 1454}
1727 1455
1728void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) 1456static void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
1729{ 1457{
1730 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1458 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1731 1459
1732 dsi->pll_locked = 0;
1733 dsi_pll_power(dsidev, DSI_PLL_POWER_OFF); 1460 dsi_pll_power(dsidev, DSI_PLL_POWER_OFF);
1734 if (disconnect_lanes) { 1461 if (disconnect_lanes) {
1735 WARN_ON(!dsi->vdds_dsi_enabled); 1462 WARN_ON(!dsi->vdds_dsi_enabled);
@@ -1738,18 +1465,27 @@ void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes)
1738 } 1465 }
1739 1466
1740 dsi_disable_scp_clk(dsidev); 1467 dsi_disable_scp_clk(dsidev);
1741 dsi_enable_pll_clock(dsidev, 0); 1468 dsi_runtime_put(dsidev);
1742 1469
1743 DSSDBG("PLL uninit done\n"); 1470 DSSDBG("PLL uninit done\n");
1744} 1471}
1745 1472
1473static void dsi_pll_disable(struct dss_pll *pll)
1474{
1475 struct dsi_data *dsi = container_of(pll, struct dsi_data, pll);
1476 struct platform_device *dsidev = dsi->pdev;
1477
1478 dsi_pll_uninit(dsidev, true);
1479}
1480
1746static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, 1481static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1747 struct seq_file *s) 1482 struct seq_file *s)
1748{ 1483{
1749 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1484 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
1750 struct dsi_clock_info *cinfo = &dsi->current_cinfo; 1485 struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
1751 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src; 1486 enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
1752 int dsi_module = dsi->module_id; 1487 int dsi_module = dsi->module_id;
1488 struct dss_pll *pll = &dsi->pll;
1753 1489
1754 dispc_clk_src = dss_get_dispc_clk_source(); 1490 dispc_clk_src = dss_get_dispc_clk_source();
1755 dsi_clk_src = dss_get_dsi_clk_source(dsi_module); 1491 dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
@@ -1759,28 +1495,28 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1759 1495
1760 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1); 1496 seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
1761 1497
1762 seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin); 1498 seq_printf(s, "dsi pll clkin\t%lu\n", clk_get_rate(pll->clkin));
1763 1499
1764 seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn); 1500 seq_printf(s, "Fint\t\t%-16lun %u\n", cinfo->fint, cinfo->n);
1765 1501
1766 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", 1502 seq_printf(s, "CLKIN4DDR\t%-16lum %u\n",
1767 cinfo->clkin4ddr, cinfo->regm); 1503 cinfo->clkdco, cinfo->m);
1768 1504
1769 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n", 1505 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16lum_dispc %u\t(%s)\n",
1770 dss_feat_get_clk_source_name(dsi_module == 0 ? 1506 dss_feat_get_clk_source_name(dsi_module == 0 ?
1771 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : 1507 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
1772 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC), 1508 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
1773 cinfo->dsi_pll_hsdiv_dispc_clk, 1509 cinfo->clkout[HSDIV_DISPC],
1774 cinfo->regm_dispc, 1510 cinfo->mX[HSDIV_DISPC],
1775 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1511 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1776 "off" : "on"); 1512 "off" : "on");
1777 1513
1778 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n", 1514 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16lum_dsi %u\t(%s)\n",
1779 dss_feat_get_clk_source_name(dsi_module == 0 ? 1515 dss_feat_get_clk_source_name(dsi_module == 0 ?
1780 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : 1516 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
1781 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI), 1517 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
1782 cinfo->dsi_pll_hsdiv_dsi_clk, 1518 cinfo->clkout[HSDIV_DSI],
1783 cinfo->regm_dsi, 1519 cinfo->mX[HSDIV_DSI],
1784 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1520 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1785 "off" : "on"); 1521 "off" : "on");
1786 1522
@@ -1793,11 +1529,11 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1793 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev)); 1529 seq_printf(s, "DSI_FCLK\t%lu\n", dsi_fclk_rate(dsidev));
1794 1530
1795 seq_printf(s, "DDR_CLK\t\t%lu\n", 1531 seq_printf(s, "DDR_CLK\t\t%lu\n",
1796 cinfo->clkin4ddr / 4); 1532 cinfo->clkdco / 4);
1797 1533
1798 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev)); 1534 seq_printf(s, "TxByteClkHS\t%lu\n", dsi_get_txbyteclkhs(dsidev));
1799 1535
1800 seq_printf(s, "LP_CLK\t\t%lu\n", cinfo->lp_clk); 1536 seq_printf(s, "LP_CLK\t\t%lu\n", dsi->current_lp_cinfo.lp_clk);
1801 1537
1802 dsi_runtime_put(dsidev); 1538 dsi_runtime_put(dsidev);
1803} 1539}
@@ -2132,7 +1868,7 @@ static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
2132 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1868 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2133 1869
2134 /* convert time in ns to ddr ticks, rounding up */ 1870 /* convert time in ns to ddr ticks, rounding up */
2135 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; 1871 unsigned long ddr_clk = dsi->pll.cinfo.clkdco / 4;
2136 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000; 1872 return (ns * (ddr_clk / 1000 / 1000) + 999) / 1000;
2137} 1873}
2138 1874
@@ -2140,7 +1876,7 @@ static inline unsigned ddr2ns(struct platform_device *dsidev, unsigned ddr)
2140{ 1876{
2141 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 1877 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2142 1878
2143 unsigned long ddr_clk = dsi->current_cinfo.clkin4ddr / 4; 1879 unsigned long ddr_clk = dsi->pll.cinfo.clkdco / 4;
2144 return ddr * 1000 * 1000 / (ddr_clk / 1000); 1880 return ddr * 1000 * 1000 / (ddr_clk / 1000);
2145} 1881}
2146 1882
@@ -3730,7 +3466,7 @@ static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev)
3730 struct omap_video_timings *timings = &dsi->timings; 3466 struct omap_video_timings *timings = &dsi->timings;
3731 int bpp = dsi_get_pixel_size(dsi->pix_fmt); 3467 int bpp = dsi_get_pixel_size(dsi->pix_fmt);
3732 int ndl = dsi->num_lanes_used - 1; 3468 int ndl = dsi->num_lanes_used - 1;
3733 int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1; 3469 int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.mX[HSDIV_DSI] + 1;
3734 int hsa_interleave_hs = 0, hsa_interleave_lp = 0; 3470 int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
3735 int hfp_interleave_hs = 0, hfp_interleave_lp = 0; 3471 int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
3736 int hbp_interleave_hs = 0, hbp_interleave_lp = 0; 3472 int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
@@ -4441,18 +4177,12 @@ static void dsi_display_uninit_dispc(struct platform_device *dsidev,
4441static int dsi_configure_dsi_clocks(struct platform_device *dsidev) 4177static int dsi_configure_dsi_clocks(struct platform_device *dsidev)
4442{ 4178{
4443 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4179 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4444 struct dsi_clock_info cinfo; 4180 struct dss_pll_clock_info cinfo;
4445 int r; 4181 int r;
4446 4182
4447 cinfo = dsi->user_dsi_cinfo; 4183 cinfo = dsi->user_dsi_cinfo;
4448 4184
4449 r = dsi_calc_clock_rates(dsidev, &cinfo); 4185 r = dss_pll_set_config(&dsi->pll, &cinfo);
4450 if (r) {
4451 DSSERR("Failed to calc dsi clocks\n");
4452 return r;
4453 }
4454
4455 r = dsi_pll_set_clock_div(dsidev, &cinfo);
4456 if (r) { 4186 if (r) {
4457 DSSERR("Failed to set dsi clocks\n"); 4187 DSSERR("Failed to set dsi clocks\n");
4458 return r; 4188 return r;
@@ -4466,7 +4196,7 @@ static int dsi_display_init_dsi(struct platform_device *dsidev)
4466 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4196 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4467 int r; 4197 int r;
4468 4198
4469 r = dsi_pll_init(dsidev, true, true); 4199 r = dss_pll_enable(&dsi->pll);
4470 if (r) 4200 if (r)
4471 goto err0; 4201 goto err0;
4472 4202
@@ -4510,7 +4240,7 @@ err3:
4510err2: 4240err2:
4511 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); 4241 dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
4512err1: 4242err1:
4513 dsi_pll_uninit(dsidev, true); 4243 dss_pll_disable(&dsi->pll);
4514err0: 4244err0:
4515 return r; 4245 return r;
4516} 4246}
@@ -4551,8 +4281,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
4551 if (r) 4281 if (r)
4552 goto err_get_dsi; 4282 goto err_get_dsi;
4553 4283
4554 dsi_enable_pll_clock(dsidev, 1);
4555
4556 _dsi_initialize_irq(dsidev); 4284 _dsi_initialize_irq(dsidev);
4557 4285
4558 r = dsi_display_init_dsi(dsidev); 4286 r = dsi_display_init_dsi(dsidev);
@@ -4564,7 +4292,6 @@ static int dsi_display_enable(struct omap_dss_device *dssdev)
4564 return 0; 4292 return 0;
4565 4293
4566err_init_dsi: 4294err_init_dsi:
4567 dsi_enable_pll_clock(dsidev, 0);
4568 dsi_runtime_put(dsidev); 4295 dsi_runtime_put(dsidev);
4569err_get_dsi: 4296err_get_dsi:
4570 mutex_unlock(&dsi->lock); 4297 mutex_unlock(&dsi->lock);
@@ -4592,7 +4319,6 @@ static void dsi_display_disable(struct omap_dss_device *dssdev,
4592 dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps); 4319 dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps);
4593 4320
4594 dsi_runtime_put(dsidev); 4321 dsi_runtime_put(dsidev);
4595 dsi_enable_pll_clock(dsidev, 0);
4596 4322
4597 mutex_unlock(&dsi->lock); 4323 mutex_unlock(&dsi->lock);
4598} 4324}
@@ -4713,29 +4439,30 @@ static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
4713 return true; 4439 return true;
4714} 4440}
4715 4441
4716static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, 4442static bool dsi_cm_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
4717 void *data) 4443 void *data)
4718{ 4444{
4719 struct dsi_clk_calc_ctx *ctx = data; 4445 struct dsi_clk_calc_ctx *ctx = data;
4720 4446
4721 ctx->dsi_cinfo.regm_dispc = regm_dispc; 4447 ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
4722 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; 4448 ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
4723 4449
4724 return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max, 4450 return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
4725 dsi_cm_calc_dispc_cb, ctx); 4451 dsi_cm_calc_dispc_cb, ctx);
4726} 4452}
4727 4453
4728static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint, 4454static bool dsi_cm_calc_pll_cb(int n, int m, unsigned long fint,
4729 unsigned long pll, void *data) 4455 unsigned long clkdco, void *data)
4730{ 4456{
4731 struct dsi_clk_calc_ctx *ctx = data; 4457 struct dsi_clk_calc_ctx *ctx = data;
4732 4458
4733 ctx->dsi_cinfo.regn = regn; 4459 ctx->dsi_cinfo.n = n;
4734 ctx->dsi_cinfo.regm = regm; 4460 ctx->dsi_cinfo.m = m;
4735 ctx->dsi_cinfo.fint = fint; 4461 ctx->dsi_cinfo.fint = fint;
4736 ctx->dsi_cinfo.clkin4ddr = pll; 4462 ctx->dsi_cinfo.clkdco = clkdco;
4737 4463
4738 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, 4464 return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
4465 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
4739 dsi_cm_calc_hsdiv_cb, ctx); 4466 dsi_cm_calc_hsdiv_cb, ctx);
4740} 4467}
4741 4468
@@ -4748,7 +4475,7 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
4748 unsigned long pll_min, pll_max; 4475 unsigned long pll_min, pll_max;
4749 unsigned long pck, txbyteclk; 4476 unsigned long pck, txbyteclk;
4750 4477
4751 clkin = clk_get_rate(dsi->sys_clk); 4478 clkin = clk_get_rate(dsi->pll.clkin);
4752 bitspp = dsi_get_pixel_size(cfg->pixel_format); 4479 bitspp = dsi_get_pixel_size(cfg->pixel_format);
4753 ndl = dsi->num_lanes_used - 1; 4480 ndl = dsi->num_lanes_used - 1;
4754 4481
@@ -4764,16 +4491,16 @@ static bool dsi_cm_calc(struct dsi_data *dsi,
4764 4491
4765 memset(ctx, 0, sizeof(*ctx)); 4492 memset(ctx, 0, sizeof(*ctx));
4766 ctx->dsidev = dsi->pdev; 4493 ctx->dsidev = dsi->pdev;
4494 ctx->pll = &dsi->pll;
4767 ctx->config = cfg; 4495 ctx->config = cfg;
4768 ctx->req_pck_min = pck; 4496 ctx->req_pck_min = pck;
4769 ctx->req_pck_nom = pck; 4497 ctx->req_pck_nom = pck;
4770 ctx->req_pck_max = pck * 3 / 2; 4498 ctx->req_pck_max = pck * 3 / 2;
4771 ctx->dsi_cinfo.clkin = clkin;
4772 4499
4773 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4); 4500 pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
4774 pll_max = cfg->hs_clk_max * 4; 4501 pll_max = cfg->hs_clk_max * 4;
4775 4502
4776 return dsi_pll_calc(dsi->pdev, clkin, 4503 return dss_pll_calc(ctx->pll, clkin,
4777 pll_min, pll_max, 4504 pll_min, pll_max,
4778 dsi_cm_calc_pll_cb, ctx); 4505 dsi_cm_calc_pll_cb, ctx);
4779} 4506}
@@ -4784,7 +4511,7 @@ static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
4784 const struct omap_dss_dsi_config *cfg = ctx->config; 4511 const struct omap_dss_dsi_config *cfg = ctx->config;
4785 int bitspp = dsi_get_pixel_size(cfg->pixel_format); 4512 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
4786 int ndl = dsi->num_lanes_used - 1; 4513 int ndl = dsi->num_lanes_used - 1;
4787 unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4; 4514 unsigned long hsclk = ctx->dsi_cinfo.clkdco / 4;
4788 unsigned long byteclk = hsclk / 4; 4515 unsigned long byteclk = hsclk / 4;
4789 4516
4790 unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max; 4517 unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
@@ -4999,14 +4726,14 @@ static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
4999 return true; 4726 return true;
5000} 4727}
5001 4728
5002static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, 4729static bool dsi_vm_calc_hsdiv_cb(int m_dispc, unsigned long dispc,
5003 void *data) 4730 void *data)
5004{ 4731{
5005 struct dsi_clk_calc_ctx *ctx = data; 4732 struct dsi_clk_calc_ctx *ctx = data;
5006 unsigned long pck_max; 4733 unsigned long pck_max;
5007 4734
5008 ctx->dsi_cinfo.regm_dispc = regm_dispc; 4735 ctx->dsi_cinfo.mX[HSDIV_DISPC] = m_dispc;
5009 ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; 4736 ctx->dsi_cinfo.clkout[HSDIV_DISPC] = dispc;
5010 4737
5011 /* 4738 /*
5012 * In burst mode we can let the dispc pck be arbitrarily high, but it 4739 * In burst mode we can let the dispc pck be arbitrarily high, but it
@@ -5022,17 +4749,18 @@ static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
5022 dsi_vm_calc_dispc_cb, ctx); 4749 dsi_vm_calc_dispc_cb, ctx);
5023} 4750}
5024 4751
5025static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint, 4752static bool dsi_vm_calc_pll_cb(int n, int m, unsigned long fint,
5026 unsigned long pll, void *data) 4753 unsigned long clkdco, void *data)
5027{ 4754{
5028 struct dsi_clk_calc_ctx *ctx = data; 4755 struct dsi_clk_calc_ctx *ctx = data;
5029 4756
5030 ctx->dsi_cinfo.regn = regn; 4757 ctx->dsi_cinfo.n = n;
5031 ctx->dsi_cinfo.regm = regm; 4758 ctx->dsi_cinfo.m = m;
5032 ctx->dsi_cinfo.fint = fint; 4759 ctx->dsi_cinfo.fint = fint;
5033 ctx->dsi_cinfo.clkin4ddr = pll; 4760 ctx->dsi_cinfo.clkdco = clkdco;
5034 4761
5035 return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, 4762 return dss_pll_hsdiv_calc(ctx->pll, clkdco, ctx->req_pck_min,
4763 dss_feat_get_param_max(FEAT_PARAM_DSS_FCK),
5036 dsi_vm_calc_hsdiv_cb, ctx); 4764 dsi_vm_calc_hsdiv_cb, ctx);
5037} 4765}
5038 4766
@@ -5048,14 +4776,13 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
5048 int bitspp = dsi_get_pixel_size(cfg->pixel_format); 4776 int bitspp = dsi_get_pixel_size(cfg->pixel_format);
5049 unsigned long byteclk_min; 4777 unsigned long byteclk_min;
5050 4778
5051 clkin = clk_get_rate(dsi->sys_clk); 4779 clkin = clk_get_rate(dsi->pll.clkin);
5052 4780
5053 memset(ctx, 0, sizeof(*ctx)); 4781 memset(ctx, 0, sizeof(*ctx));
5054 ctx->dsidev = dsi->pdev; 4782 ctx->dsidev = dsi->pdev;
4783 ctx->pll = &dsi->pll;
5055 ctx->config = cfg; 4784 ctx->config = cfg;
5056 4785
5057 ctx->dsi_cinfo.clkin = clkin;
5058
5059 /* these limits should come from the panel driver */ 4786 /* these limits should come from the panel driver */
5060 ctx->req_pck_min = t->pixelclock - 1000; 4787 ctx->req_pck_min = t->pixelclock - 1000;
5061 ctx->req_pck_nom = t->pixelclock; 4788 ctx->req_pck_nom = t->pixelclock;
@@ -5074,7 +4801,7 @@ static bool dsi_vm_calc(struct dsi_data *dsi,
5074 pll_max = byteclk_max * 4 * 4; 4801 pll_max = byteclk_max * 4 * 4;
5075 } 4802 }
5076 4803
5077 return dsi_pll_calc(dsi->pdev, clkin, 4804 return dss_pll_calc(ctx->pll, clkin,
5078 pll_min, pll_max, 4805 pll_min, pll_max,
5079 dsi_vm_calc_pll_cb, ctx); 4806 dsi_vm_calc_pll_cb, ctx);
5080} 4807}
@@ -5106,8 +4833,8 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
5106 4833
5107 dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo); 4834 dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo);
5108 4835
5109 r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min, 4836 r = dsi_lp_clock_calc(ctx.dsi_cinfo.clkout[HSDIV_DSI],
5110 config->lp_clk_max); 4837 config->lp_clk_min, config->lp_clk_max, &dsi->user_lp_cinfo);
5111 if (r) { 4838 if (r) {
5112 DSSERR("failed to find suitable DSI LP clock settings\n"); 4839 DSSERR("failed to find suitable DSI LP clock settings\n");
5113 goto err; 4840 goto err;
@@ -5234,35 +4961,6 @@ static void dsi_release_vc(struct omap_dss_device *dssdev, int channel)
5234 } 4961 }
5235} 4962}
5236 4963
5237void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
5238{
5239 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 7, 1) != 1)
5240 DSSERR("%s (%s) not active\n",
5241 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC),
5242 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC));
5243}
5244
5245void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
5246{
5247 if (wait_for_bit_change(dsidev, DSI_PLL_STATUS, 8, 1) != 1)
5248 DSSERR("%s (%s) not active\n",
5249 dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI),
5250 dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI));
5251}
5252
5253static void dsi_calc_clock_param_ranges(struct platform_device *dsidev)
5254{
5255 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5256
5257 dsi->regn_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGN);
5258 dsi->regm_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM);
5259 dsi->regm_dispc_max =
5260 dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DISPC);
5261 dsi->regm_dsi_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_REGM_DSI);
5262 dsi->fint_min = dss_feat_get_param_min(FEAT_PARAM_DSIPLL_FINT);
5263 dsi->fint_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_FINT);
5264 dsi->lpdiv_max = dss_feat_get_param_max(FEAT_PARAM_DSIPLL_LPDIV);
5265}
5266 4964
5267static int dsi_get_clocks(struct platform_device *dsidev) 4965static int dsi_get_clocks(struct platform_device *dsidev)
5268{ 4966{
@@ -5277,14 +4975,6 @@ static int dsi_get_clocks(struct platform_device *dsidev)
5277 4975
5278 dsi->dss_clk = clk; 4976 dsi->dss_clk = clk;
5279 4977
5280 clk = devm_clk_get(&dsidev->dev, "sys_clk");
5281 if (IS_ERR(clk)) {
5282 DSSERR("can't get sys_clk\n");
5283 return PTR_ERR(clk);
5284 }
5285
5286 dsi->sys_clk = clk;
5287
5288 return 0; 4978 return 0;
5289} 4979}
5290 4980
@@ -5453,6 +5143,135 @@ err:
5453 return r; 5143 return r;
5454} 5144}
5455 5145
5146static const struct dss_pll_ops dsi_pll_ops = {
5147 .enable = dsi_pll_enable,
5148 .disable = dsi_pll_disable,
5149 .set_config = dss_pll_write_config_type_a,
5150};
5151
5152static const struct dss_pll_hw dss_omap3_dsi_pll_hw = {
5153 .n_max = (1 << 7) - 1,
5154 .m_max = (1 << 11) - 1,
5155 .mX_max = (1 << 4) - 1,
5156 .fint_min = 750000,
5157 .fint_max = 2100000,
5158 .clkdco_low = 1000000000,
5159 .clkdco_max = 1800000000,
5160
5161 .n_msb = 7,
5162 .n_lsb = 1,
5163 .m_msb = 18,
5164 .m_lsb = 8,
5165
5166 .mX_msb[0] = 22,
5167 .mX_lsb[0] = 19,
5168 .mX_msb[1] = 26,
5169 .mX_lsb[1] = 23,
5170
5171 .has_stopmode = true,
5172 .has_freqsel = true,
5173 .has_selfreqdco = false,
5174 .has_refsel = false,
5175};
5176
5177static const struct dss_pll_hw dss_omap4_dsi_pll_hw = {
5178 .n_max = (1 << 8) - 1,
5179 .m_max = (1 << 12) - 1,
5180 .mX_max = (1 << 5) - 1,
5181 .fint_min = 500000,
5182 .fint_max = 2500000,
5183 .clkdco_low = 1000000000,
5184 .clkdco_max = 1800000000,
5185
5186 .n_msb = 8,
5187 .n_lsb = 1,
5188 .m_msb = 20,
5189 .m_lsb = 9,
5190
5191 .mX_msb[0] = 25,
5192 .mX_lsb[0] = 21,
5193 .mX_msb[1] = 30,
5194 .mX_lsb[1] = 26,
5195
5196 .has_stopmode = true,
5197 .has_freqsel = false,
5198 .has_selfreqdco = false,
5199 .has_refsel = false,
5200};
5201
5202static const struct dss_pll_hw dss_omap5_dsi_pll_hw = {
5203 .n_max = (1 << 8) - 1,
5204 .m_max = (1 << 12) - 1,
5205 .mX_max = (1 << 5) - 1,
5206 .fint_min = 150000,
5207 .fint_max = 52000000,
5208 .clkdco_low = 1000000000,
5209 .clkdco_max = 1800000000,
5210
5211 .n_msb = 8,
5212 .n_lsb = 1,
5213 .m_msb = 20,
5214 .m_lsb = 9,
5215
5216 .mX_msb[0] = 25,
5217 .mX_lsb[0] = 21,
5218 .mX_msb[1] = 30,
5219 .mX_lsb[1] = 26,
5220
5221 .has_stopmode = true,
5222 .has_freqsel = false,
5223 .has_selfreqdco = true,
5224 .has_refsel = true,
5225};
5226
5227static int dsi_init_pll_data(struct platform_device *dsidev)
5228{
5229 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
5230 struct dss_pll *pll = &dsi->pll;
5231 struct clk *clk;
5232 int r;
5233
5234 clk = devm_clk_get(&dsidev->dev, "sys_clk");
5235 if (IS_ERR(clk)) {
5236 DSSERR("can't get sys_clk\n");
5237 return PTR_ERR(clk);
5238 }
5239
5240 pll->name = dsi->module_id == 0 ? "dsi0" : "dsi1";
5241 pll->clkin = clk;
5242 pll->base = dsi->pll_base;
5243
5244 switch (omapdss_get_version()) {
5245 case OMAPDSS_VER_OMAP34xx_ES1:
5246 case OMAPDSS_VER_OMAP34xx_ES3:
5247 case OMAPDSS_VER_OMAP3630:
5248 case OMAPDSS_VER_AM35xx:
5249 pll->hw = &dss_omap3_dsi_pll_hw;
5250 break;
5251
5252 case OMAPDSS_VER_OMAP4430_ES1:
5253 case OMAPDSS_VER_OMAP4430_ES2:
5254 case OMAPDSS_VER_OMAP4:
5255 pll->hw = &dss_omap4_dsi_pll_hw;
5256 break;
5257
5258 case OMAPDSS_VER_OMAP5:
5259 pll->hw = &dss_omap5_dsi_pll_hw;
5260 break;
5261
5262 default:
5263 return -ENODEV;
5264 }
5265
5266 pll->ops = &dsi_pll_ops;
5267
5268 r = dss_pll_register(pll);
5269 if (r)
5270 return r;
5271
5272 return 0;
5273}
5274
5456/* DSI1 HW IP initialisation */ 5275/* DSI1 HW IP initialisation */
5457static int omap_dsihw_probe(struct platform_device *dsidev) 5276static int omap_dsihw_probe(struct platform_device *dsidev)
5458{ 5277{
@@ -5598,12 +5417,12 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
5598 dsi->vc[i].vc_id = 0; 5417 dsi->vc[i].vc_id = 0;
5599 } 5418 }
5600 5419
5601 dsi_calc_clock_param_ranges(dsidev);
5602
5603 r = dsi_get_clocks(dsidev); 5420 r = dsi_get_clocks(dsidev);
5604 if (r) 5421 if (r)
5605 return r; 5422 return r;
5606 5423
5424 dsi_init_pll_data(dsidev);
5425
5607 pm_runtime_enable(&dsidev->dev); 5426 pm_runtime_enable(&dsidev->dev);
5608 5427
5609 r = dsi_runtime_get(dsidev); 5428 r = dsi_runtime_get(dsidev);
@@ -5672,6 +5491,8 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev)
5672 5491
5673 WARN_ON(dsi->scp_clk_refcount > 0); 5492 WARN_ON(dsi->scp_clk_refcount > 0);
5674 5493
5494 dss_pll_unregister(&dsi->pll);
5495
5675 dsi_uninit_output(dsidev); 5496 dsi_uninit_output(dsidev);
5676 5497
5677 pm_runtime_disable(&dsidev->dev); 5498 pm_runtime_disable(&dsidev->dev);
diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c
index a4b20aaf6142..928ee639c0c1 100644
--- a/drivers/video/fbdev/omap2/dss/dss-of.c
+++ b/drivers/video/fbdev/omap2/dss/dss-of.c
@@ -20,6 +20,8 @@
20 20
21#include <video/omapdss.h> 21#include <video/omapdss.h>
22 22
23#include "dss.h"
24
23struct device_node * 25struct device_node *
24omapdss_of_get_next_port(const struct device_node *parent, 26omapdss_of_get_next_port(const struct device_node *parent,
25 struct device_node *prev) 27 struct device_node *prev)
@@ -84,20 +86,17 @@ omapdss_of_get_next_endpoint(const struct device_node *parent,
84} 86}
85EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); 87EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint);
86 88
87static struct device_node * 89struct device_node *dss_of_port_get_parent_device(struct device_node *port)
88omapdss_of_get_remote_device_node(const struct device_node *node)
89{ 90{
90 struct device_node *np; 91 struct device_node *np;
91 int i; 92 int i;
92 93
93 np = of_parse_phandle(node, "remote-endpoint", 0); 94 if (!port)
94
95 if (!np)
96 return NULL; 95 return NULL;
97 96
98 np = of_get_next_parent(np); 97 np = of_get_next_parent(port);
99 98
100 for (i = 0; i < 3 && np; ++i) { 99 for (i = 0; i < 2 && np; ++i) {
101 struct property *prop; 100 struct property *prop;
102 101
103 prop = of_find_property(np, "compatible", NULL); 102 prop = of_find_property(np, "compatible", NULL);
@@ -111,6 +110,31 @@ omapdss_of_get_remote_device_node(const struct device_node *node)
111 return NULL; 110 return NULL;
112} 111}
113 112
113u32 dss_of_port_get_port_number(struct device_node *port)
114{
115 int r;
116 u32 reg;
117
118 r = of_property_read_u32(port, "reg", &reg);
119 if (r)
120 reg = 0;
121
122 return reg;
123}
124
125static struct device_node *omapdss_of_get_remote_port(const struct device_node *node)
126{
127 struct device_node *np;
128
129 np = of_parse_phandle(node, "remote-endpoint", 0);
130 if (!np)
131 return NULL;
132
133 np = of_get_next_parent(np);
134
135 return np;
136}
137
114struct device_node * 138struct device_node *
115omapdss_of_get_first_endpoint(const struct device_node *parent) 139omapdss_of_get_first_endpoint(const struct device_node *parent)
116{ 140{
@@ -133,27 +157,25 @@ struct omap_dss_device *
133omapdss_of_find_source_for_first_ep(struct device_node *node) 157omapdss_of_find_source_for_first_ep(struct device_node *node)
134{ 158{
135 struct device_node *ep; 159 struct device_node *ep;
136 struct device_node *src_node; 160 struct device_node *src_port;
137 struct omap_dss_device *src; 161 struct omap_dss_device *src;
138 162
139 ep = omapdss_of_get_first_endpoint(node); 163 ep = omapdss_of_get_first_endpoint(node);
140 if (!ep) 164 if (!ep)
141 return ERR_PTR(-EINVAL); 165 return ERR_PTR(-EINVAL);
142 166
143 src_node = omapdss_of_get_remote_device_node(ep); 167 src_port = omapdss_of_get_remote_port(ep);
144 168 if (!src_port) {
145 of_node_put(ep); 169 of_node_put(ep);
146
147 if (!src_node)
148 return ERR_PTR(-EINVAL); 170 return ERR_PTR(-EINVAL);
171 }
149 172
150 src = omap_dss_find_output_by_node(src_node); 173 of_node_put(ep);
151 174
152 of_node_put(src_node); 175 src = omap_dss_find_output_by_port_node(src_port);
153 176
154 if (!src) 177 of_node_put(src_port);
155 return ERR_PTR(-EPROBE_DEFER);
156 178
157 return src; 179 return src ? src : ERR_PTR(-EPROBE_DEFER);
158} 180}
159EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep); 181EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep);
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index 14bcd6c43f72..702c495083ed 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -70,7 +70,9 @@ 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 int (*dpi_select_source)(enum omap_channel channel); 73 enum omap_display_type *ports;
74 int num_ports;
75 int (*dpi_select_source)(int port, enum omap_channel channel);
74}; 76};
75 77
76static struct { 78static struct {
@@ -294,7 +296,6 @@ static void dss_dump_regs(struct seq_file *s)
294 296
295static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 297static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
296{ 298{
297 struct platform_device *dsidev;
298 int b; 299 int b;
299 u8 start, end; 300 u8 start, end;
300 301
@@ -304,13 +305,9 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
304 break; 305 break;
305 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 306 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
306 b = 1; 307 b = 1;
307 dsidev = dsi_get_dsidev_from_id(0);
308 dsi_wait_pll_hsdiv_dispc_active(dsidev);
309 break; 308 break;
310 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 309 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
311 b = 2; 310 b = 2;
312 dsidev = dsi_get_dsidev_from_id(1);
313 dsi_wait_pll_hsdiv_dispc_active(dsidev);
314 break; 311 break;
315 default: 312 default:
316 BUG(); 313 BUG();
@@ -327,7 +324,6 @@ static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
327void dss_select_dsi_clk_source(int dsi_module, 324void dss_select_dsi_clk_source(int dsi_module,
328 enum omap_dss_clk_source clk_src) 325 enum omap_dss_clk_source clk_src)
329{ 326{
330 struct platform_device *dsidev;
331 int b, pos; 327 int b, pos;
332 328
333 switch (clk_src) { 329 switch (clk_src) {
@@ -337,14 +333,10 @@ void dss_select_dsi_clk_source(int dsi_module,
337 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: 333 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
338 BUG_ON(dsi_module != 0); 334 BUG_ON(dsi_module != 0);
339 b = 1; 335 b = 1;
340 dsidev = dsi_get_dsidev_from_id(0);
341 dsi_wait_pll_hsdiv_dsi_active(dsidev);
342 break; 336 break;
343 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: 337 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
344 BUG_ON(dsi_module != 1); 338 BUG_ON(dsi_module != 1);
345 b = 1; 339 b = 1;
346 dsidev = dsi_get_dsidev_from_id(1);
347 dsi_wait_pll_hsdiv_dsi_active(dsidev);
348 break; 340 break;
349 default: 341 default:
350 BUG(); 342 BUG();
@@ -360,7 +352,6 @@ void dss_select_dsi_clk_source(int dsi_module,
360void dss_select_lcd_clk_source(enum omap_channel channel, 352void dss_select_lcd_clk_source(enum omap_channel channel,
361 enum omap_dss_clk_source clk_src) 353 enum omap_dss_clk_source clk_src)
362{ 354{
363 struct platform_device *dsidev;
364 int b, ix, pos; 355 int b, ix, pos;
365 356
366 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { 357 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) {
@@ -375,15 +366,11 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
375 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 366 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
376 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); 367 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
377 b = 1; 368 b = 1;
378 dsidev = dsi_get_dsidev_from_id(0);
379 dsi_wait_pll_hsdiv_dispc_active(dsidev);
380 break; 369 break;
381 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 370 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
382 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 && 371 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 &&
383 channel != OMAP_DSS_CHANNEL_LCD3); 372 channel != OMAP_DSS_CHANNEL_LCD3);
384 b = 1; 373 b = 1;
385 dsidev = dsi_get_dsidev_from_id(1);
386 dsi_wait_pll_hsdiv_dispc_active(dsidev);
387 break; 374 break;
388 default: 375 default:
389 BUG(); 376 BUG();
@@ -564,7 +551,7 @@ enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void)
564 return REG_GET(DSS_CONTROL, 15, 15); 551 return REG_GET(DSS_CONTROL, 15, 15);
565} 552}
566 553
567static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) 554static int dss_dpi_select_source_omap2_omap3(int port, enum omap_channel channel)
568{ 555{
569 if (channel != OMAP_DSS_CHANNEL_LCD) 556 if (channel != OMAP_DSS_CHANNEL_LCD)
570 return -EINVAL; 557 return -EINVAL;
@@ -572,7 +559,7 @@ static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel)
572 return 0; 559 return 0;
573} 560}
574 561
575static int dss_dpi_select_source_omap4(enum omap_channel channel) 562static int dss_dpi_select_source_omap4(int port, enum omap_channel channel)
576{ 563{
577 int val; 564 int val;
578 565
@@ -592,7 +579,7 @@ static int dss_dpi_select_source_omap4(enum omap_channel channel)
592 return 0; 579 return 0;
593} 580}
594 581
595static int dss_dpi_select_source_omap5(enum omap_channel channel) 582static int dss_dpi_select_source_omap5(int port, enum omap_channel channel)
596{ 583{
597 int val; 584 int val;
598 585
@@ -618,9 +605,9 @@ static int dss_dpi_select_source_omap5(enum omap_channel channel)
618 return 0; 605 return 0;
619} 606}
620 607
621int dss_dpi_select_source(enum omap_channel channel) 608int dss_dpi_select_source(int port, enum omap_channel channel)
622{ 609{
623 return dss.feat->dpi_select_source(channel); 610 return dss.feat->dpi_select_source(port, channel);
624} 611}
625 612
626static int dss_get_clocks(void) 613static int dss_get_clocks(void)
@@ -689,6 +676,16 @@ void dss_debug_dump_clocks(struct seq_file *s)
689} 676}
690#endif 677#endif
691 678
679
680static enum omap_display_type omap2plus_ports[] = {
681 OMAP_DISPLAY_TYPE_DPI,
682};
683
684static enum omap_display_type omap34xx_ports[] = {
685 OMAP_DISPLAY_TYPE_DPI,
686 OMAP_DISPLAY_TYPE_SDI,
687};
688
692static const struct dss_features omap24xx_dss_feats __initconst = { 689static const struct dss_features omap24xx_dss_feats __initconst = {
693 /* 690 /*
694 * fck div max is really 16, but the divider range has gaps. The range 691 * fck div max is really 16, but the divider range has gaps. The range
@@ -698,6 +695,8 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
698 .dss_fck_multiplier = 2, 695 .dss_fck_multiplier = 2,
699 .parent_clk_name = "core_ck", 696 .parent_clk_name = "core_ck",
700 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 697 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
698 .ports = omap2plus_ports,
699 .num_ports = ARRAY_SIZE(omap2plus_ports),
701}; 700};
702 701
703static const struct dss_features omap34xx_dss_feats __initconst = { 702static const struct dss_features omap34xx_dss_feats __initconst = {
@@ -705,6 +704,8 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
705 .dss_fck_multiplier = 2, 704 .dss_fck_multiplier = 2,
706 .parent_clk_name = "dpll4_ck", 705 .parent_clk_name = "dpll4_ck",
707 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 706 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
707 .ports = omap34xx_ports,
708 .num_ports = ARRAY_SIZE(omap34xx_ports),
708}; 709};
709 710
710static const struct dss_features omap3630_dss_feats __initconst = { 711static const struct dss_features omap3630_dss_feats __initconst = {
@@ -712,6 +713,8 @@ static const struct dss_features omap3630_dss_feats __initconst = {
712 .dss_fck_multiplier = 1, 713 .dss_fck_multiplier = 1,
713 .parent_clk_name = "dpll4_ck", 714 .parent_clk_name = "dpll4_ck",
714 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 715 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
716 .ports = omap2plus_ports,
717 .num_ports = ARRAY_SIZE(omap2plus_ports),
715}; 718};
716 719
717static const struct dss_features omap44xx_dss_feats __initconst = { 720static const struct dss_features omap44xx_dss_feats __initconst = {
@@ -719,6 +722,8 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
719 .dss_fck_multiplier = 1, 722 .dss_fck_multiplier = 1,
720 .parent_clk_name = "dpll_per_x2_ck", 723 .parent_clk_name = "dpll_per_x2_ck",
721 .dpi_select_source = &dss_dpi_select_source_omap4, 724 .dpi_select_source = &dss_dpi_select_source_omap4,
725 .ports = omap2plus_ports,
726 .num_ports = ARRAY_SIZE(omap2plus_ports),
722}; 727};
723 728
724static const struct dss_features omap54xx_dss_feats __initconst = { 729static const struct dss_features omap54xx_dss_feats __initconst = {
@@ -726,6 +731,8 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
726 .dss_fck_multiplier = 1, 731 .dss_fck_multiplier = 1,
727 .parent_clk_name = "dpll_per_x2_ck", 732 .parent_clk_name = "dpll_per_x2_ck",
728 .dpi_select_source = &dss_dpi_select_source_omap5, 733 .dpi_select_source = &dss_dpi_select_source_omap5,
734 .ports = omap2plus_ports,
735 .num_ports = ARRAY_SIZE(omap2plus_ports),
729}; 736};
730 737
731static const struct dss_features am43xx_dss_feats __initconst = { 738static const struct dss_features am43xx_dss_feats __initconst = {
@@ -733,6 +740,8 @@ static const struct dss_features am43xx_dss_feats __initconst = {
733 .dss_fck_multiplier = 0, 740 .dss_fck_multiplier = 0,
734 .parent_clk_name = NULL, 741 .parent_clk_name = NULL,
735 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 742 .dpi_select_source = &dss_dpi_select_source_omap2_omap3,
743 .ports = omap2plus_ports,
744 .num_ports = ARRAY_SIZE(omap2plus_ports),
736}; 745};
737 746
738static int __init dss_init_features(struct platform_device *pdev) 747static int __init dss_init_features(struct platform_device *pdev)
@@ -798,37 +807,77 @@ static int __init dss_init_ports(struct platform_device *pdev)
798 if (!port) 807 if (!port)
799 return 0; 808 return 0;
800 809
810 if (dss.feat->num_ports == 0)
811 return 0;
812
801 do { 813 do {
814 enum omap_display_type port_type;
802 u32 reg; 815 u32 reg;
803 816
804 r = of_property_read_u32(port, "reg", &reg); 817 r = of_property_read_u32(port, "reg", &reg);
805 if (r) 818 if (r)
806 reg = 0; 819 reg = 0;
807 820
808#ifdef CONFIG_OMAP2_DSS_DPI 821 if (reg >= dss.feat->num_ports)
809 if (reg == 0) 822 continue;
810 dpi_init_port(pdev, port);
811#endif
812 823
813#ifdef CONFIG_OMAP2_DSS_SDI 824 port_type = dss.feat->ports[reg];
814 if (reg == 1)
815 sdi_init_port(pdev, port);
816#endif
817 825
826 switch (port_type) {
827 case OMAP_DISPLAY_TYPE_DPI:
828 dpi_init_port(pdev, port);
829 break;
830 case OMAP_DISPLAY_TYPE_SDI:
831 sdi_init_port(pdev, port);
832 break;
833 default:
834 break;
835 }
818 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); 836 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
819 837
820 return 0; 838 return 0;
821} 839}
822 840
823static void __exit dss_uninit_ports(void) 841static void __exit dss_uninit_ports(struct platform_device *pdev)
824{ 842{
825#ifdef CONFIG_OMAP2_DSS_DPI 843 struct device_node *parent = pdev->dev.of_node;
826 dpi_uninit_port(); 844 struct device_node *port;
827#endif
828 845
829#ifdef CONFIG_OMAP2_DSS_SDI 846 if (parent == NULL)
830 sdi_uninit_port(); 847 return;
831#endif 848
849 port = omapdss_of_get_next_port(parent, NULL);
850 if (!port)
851 return;
852
853 if (dss.feat->num_ports == 0)
854 return;
855
856 do {
857 enum omap_display_type port_type;
858 u32 reg;
859 int r;
860
861 r = of_property_read_u32(port, "reg", &reg);
862 if (r)
863 reg = 0;
864
865 if (reg >= dss.feat->num_ports)
866 continue;
867
868 port_type = dss.feat->ports[reg];
869
870 switch (port_type) {
871 case OMAP_DISPLAY_TYPE_DPI:
872 dpi_uninit_port(port);
873 break;
874 case OMAP_DISPLAY_TYPE_SDI:
875 sdi_uninit_port(port);
876 break;
877 default:
878 break;
879 }
880 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
832} 881}
833 882
834/* DSS HW IP initialisation */ 883/* DSS HW IP initialisation */
@@ -910,7 +959,7 @@ err_setup_clocks:
910 959
911static int __exit omap_dsshw_remove(struct platform_device *pdev) 960static int __exit omap_dsshw_remove(struct platform_device *pdev)
912{ 961{
913 dss_uninit_ports(); 962 dss_uninit_ports(pdev);
914 963
915 pm_runtime_disable(&pdev->dev); 964 pm_runtime_disable(&pdev->dev);
916 965
diff --git a/drivers/video/fbdev/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h
index 8ff22c134c62..14fb0c23f4a2 100644
--- a/drivers/video/fbdev/omap2/dss/dss.h
+++ b/drivers/video/fbdev/omap2/dss/dss.h
@@ -100,35 +100,77 @@ enum dss_writeback_channel {
100 DSS_WB_LCD3_MGR = 7, 100 DSS_WB_LCD3_MGR = 7,
101}; 101};
102 102
103struct dispc_clock_info { 103struct dss_pll;
104
105#define DSS_PLL_MAX_HSDIVS 4
106
107/*
108 * Type-A PLLs: clkout[]/mX[] refer to hsdiv outputs m4, m5, m6, m7.
109 * Type-B PLLs: clkout[0] refers to m2.
110 */
111struct dss_pll_clock_info {
104 /* rates that we get with dividers below */ 112 /* rates that we get with dividers below */
105 unsigned long lck; 113 unsigned long fint;
106 unsigned long pck; 114 unsigned long clkdco;
115 unsigned long clkout[DSS_PLL_MAX_HSDIVS];
107 116
108 /* dividers */ 117 /* dividers */
109 u16 lck_div; 118 u16 n;
110 u16 pck_div; 119 u16 m;
120 u32 mf;
121 u16 mX[DSS_PLL_MAX_HSDIVS];
122 u16 sd;
123};
124
125struct dss_pll_ops {
126 int (*enable)(struct dss_pll *pll);
127 void (*disable)(struct dss_pll *pll);
128 int (*set_config)(struct dss_pll *pll,
129 const struct dss_pll_clock_info *cinfo);
130};
131
132struct dss_pll_hw {
133 unsigned n_max;
134 unsigned m_min;
135 unsigned m_max;
136 unsigned mX_max;
137
138 unsigned long fint_min, fint_max;
139 unsigned long clkdco_min, clkdco_low, clkdco_max;
140
141 u8 n_msb, n_lsb;
142 u8 m_msb, m_lsb;
143 u8 mX_msb[DSS_PLL_MAX_HSDIVS], mX_lsb[DSS_PLL_MAX_HSDIVS];
144
145 bool has_stopmode;
146 bool has_freqsel;
147 bool has_selfreqdco;
148 bool has_refsel;
111}; 149};
112 150
113struct dsi_clock_info { 151struct dss_pll {
152 const char *name;
153
154 struct clk *clkin;
155 struct regulator *regulator;
156
157 void __iomem *base;
158
159 const struct dss_pll_hw *hw;
160
161 const struct dss_pll_ops *ops;
162
163 struct dss_pll_clock_info cinfo;
164};
165
166struct dispc_clock_info {
114 /* rates that we get with dividers below */ 167 /* rates that we get with dividers below */
115 unsigned long fint; 168 unsigned long lck;
116 unsigned long clkin4ddr; 169 unsigned long pck;
117 unsigned long clkin;
118 unsigned long dsi_pll_hsdiv_dispc_clk; /* OMAP3: DSI1_PLL_CLK
119 * OMAP4: PLLx_CLK1 */
120 unsigned long dsi_pll_hsdiv_dsi_clk; /* OMAP3: DSI2_PLL_CLK
121 * OMAP4: PLLx_CLK2 */
122 unsigned long lp_clk;
123 170
124 /* dividers */ 171 /* dividers */
125 u16 regn; 172 u16 lck_div;
126 u16 regm; 173 u16 pck_div;
127 u16 regm_dispc; /* OMAP3: REGM3
128 * OMAP4: REGM4 */
129 u16 regm_dsi; /* OMAP3: REGM4
130 * OMAP4: REGM5 */
131 u16 lp_clk_div;
132}; 174};
133 175
134struct dss_lcd_mgr_config { 176struct dss_lcd_mgr_config {
@@ -209,12 +251,16 @@ int dss_init_platform_driver(void) __init;
209void dss_uninit_platform_driver(void); 251void dss_uninit_platform_driver(void);
210 252
211unsigned long dss_get_dispc_clk_rate(void); 253unsigned long dss_get_dispc_clk_rate(void);
212int dss_dpi_select_source(enum omap_channel channel); 254int dss_dpi_select_source(int port, enum omap_channel channel);
213void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); 255void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
214enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); 256enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
215const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); 257const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
216void dss_dump_clocks(struct seq_file *s); 258void dss_dump_clocks(struct seq_file *s);
217 259
260/* dss-of */
261struct device_node *dss_of_port_get_parent_device(struct device_node *port);
262u32 dss_of_port_get_port_number(struct device_node *port);
263
218#if defined(CONFIG_OMAP2_DSS_DEBUGFS) 264#if defined(CONFIG_OMAP2_DSS_DEBUGFS)
219void dss_debug_dump_clocks(struct seq_file *s); 265void dss_debug_dump_clocks(struct seq_file *s);
220#endif 266#endif
@@ -244,16 +290,22 @@ bool dss_div_calc(unsigned long pck, unsigned long fck_min,
244int sdi_init_platform_driver(void) __init; 290int sdi_init_platform_driver(void) __init;
245void sdi_uninit_platform_driver(void) __exit; 291void sdi_uninit_platform_driver(void) __exit;
246 292
293#ifdef CONFIG_OMAP2_DSS_SDI
247int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; 294int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init;
248void sdi_uninit_port(void) __exit; 295void sdi_uninit_port(struct device_node *port) __exit;
296#else
297static inline int __init sdi_init_port(struct platform_device *pdev,
298 struct device_node *port)
299{
300 return 0;
301}
302static inline void __exit sdi_uninit_port(struct device_node *port)
303{
304}
305#endif
249 306
250/* DSI */ 307/* DSI */
251 308
252typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint,
253 unsigned long pll, void *data);
254typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc,
255 void *data);
256
257#ifdef CONFIG_OMAP2_DSS_DSI 309#ifdef CONFIG_OMAP2_DSS_DSI
258 310
259struct dentry; 311struct dentry;
@@ -262,104 +314,36 @@ struct file_operations;
262int dsi_init_platform_driver(void) __init; 314int dsi_init_platform_driver(void) __init;
263void dsi_uninit_platform_driver(void) __exit; 315void dsi_uninit_platform_driver(void) __exit;
264 316
265int dsi_runtime_get(struct platform_device *dsidev);
266void dsi_runtime_put(struct platform_device *dsidev);
267
268void dsi_dump_clocks(struct seq_file *s); 317void dsi_dump_clocks(struct seq_file *s);
269 318
270void dsi_irq_handler(void); 319void dsi_irq_handler(void);
271u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); 320u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
272 321
273unsigned long dsi_get_pll_clkin(struct platform_device *dsidev);
274
275bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll,
276 unsigned long out_min, dsi_hsdiv_calc_func func, void *data);
277bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin,
278 unsigned long pll_min, unsigned long pll_max,
279 dsi_pll_calc_func func, void *data);
280
281unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
282int dsi_pll_set_clock_div(struct platform_device *dsidev,
283 struct dsi_clock_info *cinfo);
284int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
285 bool enable_hsdiv);
286void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
287void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
288void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
289struct platform_device *dsi_get_dsidev_from_id(int module);
290#else 322#else
291static inline int dsi_runtime_get(struct platform_device *dsidev)
292{
293 return 0;
294}
295static inline void dsi_runtime_put(struct platform_device *dsidev)
296{
297}
298static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) 323static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
299{ 324{
300 WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__); 325 WARN("%s: DSI not compiled in, returning pixel_size as 0\n", __func__);
301 return 0; 326 return 0;
302} 327}
303static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
304{
305 WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
306 return 0;
307}
308static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
309 struct dsi_clock_info *cinfo)
310{
311 WARN("%s: DSI not compiled in\n", __func__);
312 return -ENODEV;
313}
314static inline int dsi_pll_init(struct platform_device *dsidev,
315 bool enable_hsclk, bool enable_hsdiv)
316{
317 WARN("%s: DSI not compiled in\n", __func__);
318 return -ENODEV;
319}
320static inline void dsi_pll_uninit(struct platform_device *dsidev,
321 bool disconnect_lanes)
322{
323}
324static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
325{
326}
327static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
328{
329}
330static inline struct platform_device *dsi_get_dsidev_from_id(int module)
331{
332 return NULL;
333}
334
335static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev)
336{
337 return 0;
338}
339
340static inline bool dsi_hsdiv_calc(struct platform_device *dsidev,
341 unsigned long pll, unsigned long out_min,
342 dsi_hsdiv_calc_func func, void *data)
343{
344 return false;
345}
346
347static inline bool dsi_pll_calc(struct platform_device *dsidev,
348 unsigned long clkin,
349 unsigned long pll_min, unsigned long pll_max,
350 dsi_pll_calc_func func, void *data)
351{
352 return false;
353}
354
355#endif 328#endif
356 329
357/* DPI */ 330/* DPI */
358int dpi_init_platform_driver(void) __init; 331int dpi_init_platform_driver(void) __init;
359void dpi_uninit_platform_driver(void) __exit; 332void dpi_uninit_platform_driver(void) __exit;
360 333
334#ifdef CONFIG_OMAP2_DSS_DPI
361int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; 335int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init;
362void dpi_uninit_port(void) __exit; 336void dpi_uninit_port(struct device_node *port) __exit;
337#else
338static inline int __init dpi_init_port(struct platform_device *pdev,
339 struct device_node *port)
340{
341 return 0;
342}
343static inline void __exit dpi_uninit_port(struct device_node *port)
344{
345}
346#endif
363 347
364/* DISPC */ 348/* DISPC */
365int dispc_init_platform_driver(void) __init; 349int dispc_init_platform_driver(void) __init;
@@ -438,4 +422,29 @@ static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
438} 422}
439#endif 423#endif
440 424
425/* PLL */
426typedef bool (*dss_pll_calc_func)(int n, int m, unsigned long fint,
427 unsigned long clkdco, void *data);
428typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc,
429 void *data);
430
431int dss_pll_register(struct dss_pll *pll);
432void dss_pll_unregister(struct dss_pll *pll);
433struct dss_pll *dss_pll_find(const char *name);
434int dss_pll_enable(struct dss_pll *pll);
435void dss_pll_disable(struct dss_pll *pll);
436int dss_pll_set_config(struct dss_pll *pll,
437 const struct dss_pll_clock_info *cinfo);
438
439bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
440 unsigned long out_min, unsigned long out_max,
441 dss_hsdiv_calc_func func, void *data);
442bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
443 unsigned long pll_min, unsigned long pll_max,
444 dss_pll_calc_func func, void *data);
445int dss_pll_write_config_type_a(struct dss_pll *pll,
446 const struct dss_pll_clock_info *cinfo);
447int dss_pll_write_config_type_b(struct dss_pll *pll,
448 const struct dss_pll_clock_info *cinfo);
449
441#endif 450#endif
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c
index 15088df7bd16..0e3da809473c 100644
--- a/drivers/video/fbdev/omap2/dss/dss_features.c
+++ b/drivers/video/fbdev/omap2/dss/dss_features.c
@@ -72,10 +72,6 @@ static const struct dss_reg_field omap2_dss_reg_fields[] = {
72 [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, 72 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
73 [FEAT_REG_VERTICALACCU] = { 25, 16 }, 73 [FEAT_REG_VERTICALACCU] = { 25, 16 },
74 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, 74 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
75 [FEAT_REG_DSIPLL_REGN] = { 0, 0 },
76 [FEAT_REG_DSIPLL_REGM] = { 0, 0 },
77 [FEAT_REG_DSIPLL_REGM_DISPC] = { 0, 0 },
78 [FEAT_REG_DSIPLL_REGM_DSI] = { 0, 0 },
79}; 75};
80 76
81static const struct dss_reg_field omap3_dss_reg_fields[] = { 77static const struct dss_reg_field omap3_dss_reg_fields[] = {
@@ -87,10 +83,6 @@ static const struct dss_reg_field omap3_dss_reg_fields[] = {
87 [FEAT_REG_HORIZONTALACCU] = { 9, 0 }, 83 [FEAT_REG_HORIZONTALACCU] = { 9, 0 },
88 [FEAT_REG_VERTICALACCU] = { 25, 16 }, 84 [FEAT_REG_VERTICALACCU] = { 25, 16 },
89 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 }, 85 [FEAT_REG_DISPC_CLK_SWITCH] = { 0, 0 },
90 [FEAT_REG_DSIPLL_REGN] = { 7, 1 },
91 [FEAT_REG_DSIPLL_REGM] = { 18, 8 },
92 [FEAT_REG_DSIPLL_REGM_DISPC] = { 22, 19 },
93 [FEAT_REG_DSIPLL_REGM_DSI] = { 26, 23 },
94}; 86};
95 87
96static const struct dss_reg_field am43xx_dss_reg_fields[] = { 88static const struct dss_reg_field am43xx_dss_reg_fields[] = {
@@ -113,10 +105,6 @@ static const struct dss_reg_field omap4_dss_reg_fields[] = {
113 [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, 105 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
114 [FEAT_REG_VERTICALACCU] = { 26, 16 }, 106 [FEAT_REG_VERTICALACCU] = { 26, 16 },
115 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 }, 107 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 8 },
116 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
117 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
118 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
119 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
120}; 108};
121 109
122static const struct dss_reg_field omap5_dss_reg_fields[] = { 110static const struct dss_reg_field omap5_dss_reg_fields[] = {
@@ -128,10 +116,6 @@ static const struct dss_reg_field omap5_dss_reg_fields[] = {
128 [FEAT_REG_HORIZONTALACCU] = { 10, 0 }, 116 [FEAT_REG_HORIZONTALACCU] = { 10, 0 },
129 [FEAT_REG_VERTICALACCU] = { 26, 16 }, 117 [FEAT_REG_VERTICALACCU] = { 26, 16 },
130 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 }, 118 [FEAT_REG_DISPC_CLK_SWITCH] = { 9, 7 },
131 [FEAT_REG_DSIPLL_REGN] = { 8, 1 },
132 [FEAT_REG_DSIPLL_REGM] = { 20, 9 },
133 [FEAT_REG_DSIPLL_REGM_DISPC] = { 25, 21 },
134 [FEAT_REG_DSIPLL_REGM_DSI] = { 30, 26 },
135}; 119};
136 120
137static const enum omap_display_type omap2_dss_supported_displays[] = { 121static const enum omap_display_type omap2_dss_supported_displays[] = {
@@ -437,12 +421,6 @@ static const char * const omap5_dss_clk_source_names[] = {
437static const struct dss_param_range omap2_dss_param_range[] = { 421static const struct dss_param_range omap2_dss_param_range[] = {
438 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, 422 [FEAT_PARAM_DSS_FCK] = { 0, 133000000 },
439 [FEAT_PARAM_DSS_PCD] = { 2, 255 }, 423 [FEAT_PARAM_DSS_PCD] = { 2, 255 },
440 [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 },
441 [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 },
442 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, 0 },
443 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, 0 },
444 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
445 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
446 [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, 424 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
447 /* 425 /*
448 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC 426 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
@@ -454,11 +432,6 @@ static const struct dss_param_range omap2_dss_param_range[] = {
454static const struct dss_param_range omap3_dss_param_range[] = { 432static const struct dss_param_range omap3_dss_param_range[] = {
455 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, 433 [FEAT_PARAM_DSS_FCK] = { 0, 173000000 },
456 [FEAT_PARAM_DSS_PCD] = { 1, 255 }, 434 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
457 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 7) - 1 },
458 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 11) - 1 },
459 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 4) - 1 },
460 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 4) - 1 },
461 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
462 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 435 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
463 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 }, 436 [FEAT_PARAM_DSI_FCK] = { 0, 173000000 },
464 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 437 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
@@ -475,11 +448,6 @@ static const struct dss_param_range am43xx_dss_param_range[] = {
475static const struct dss_param_range omap4_dss_param_range[] = { 448static const struct dss_param_range omap4_dss_param_range[] = {
476 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 }, 449 [FEAT_PARAM_DSS_FCK] = { 0, 186000000 },
477 [FEAT_PARAM_DSS_PCD] = { 1, 255 }, 450 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
478 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
479 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
480 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
481 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
482 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
483 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 451 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
484 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, 452 [FEAT_PARAM_DSI_FCK] = { 0, 170000000 },
485 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 453 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
@@ -489,11 +457,6 @@ static const struct dss_param_range omap4_dss_param_range[] = {
489static const struct dss_param_range omap5_dss_param_range[] = { 457static const struct dss_param_range omap5_dss_param_range[] = {
490 [FEAT_PARAM_DSS_FCK] = { 0, 209250000 }, 458 [FEAT_PARAM_DSS_FCK] = { 0, 209250000 },
491 [FEAT_PARAM_DSS_PCD] = { 1, 255 }, 459 [FEAT_PARAM_DSS_PCD] = { 1, 255 },
492 [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 },
493 [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 },
494 [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 },
495 [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 },
496 [FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 },
497 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 460 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
498 [FEAT_PARAM_DSI_FCK] = { 0, 209250000 }, 461 [FEAT_PARAM_DSI_FCK] = { 0, 209250000 },
499 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 462 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
@@ -517,7 +480,6 @@ static const enum dss_feat_id omap3430_dss_feat_list[] = {
517 FEAT_LINEBUFFERSPLIT, 480 FEAT_LINEBUFFERSPLIT,
518 FEAT_ROWREPEATENABLE, 481 FEAT_ROWREPEATENABLE,
519 FEAT_RESIZECONF, 482 FEAT_RESIZECONF,
520 FEAT_DSI_PLL_FREQSEL,
521 FEAT_DSI_REVERSE_TXCLKESC, 483 FEAT_DSI_REVERSE_TXCLKESC,
522 FEAT_VENC_REQUIRES_TV_DAC_CLK, 484 FEAT_VENC_REQUIRES_TV_DAC_CLK,
523 FEAT_CPR, 485 FEAT_CPR,
@@ -537,7 +499,6 @@ static const enum dss_feat_id am35xx_dss_feat_list[] = {
537 FEAT_LINEBUFFERSPLIT, 499 FEAT_LINEBUFFERSPLIT,
538 FEAT_ROWREPEATENABLE, 500 FEAT_ROWREPEATENABLE,
539 FEAT_RESIZECONF, 501 FEAT_RESIZECONF,
540 FEAT_DSI_PLL_FREQSEL,
541 FEAT_DSI_REVERSE_TXCLKESC, 502 FEAT_DSI_REVERSE_TXCLKESC,
542 FEAT_VENC_REQUIRES_TV_DAC_CLK, 503 FEAT_VENC_REQUIRES_TV_DAC_CLK,
543 FEAT_CPR, 504 FEAT_CPR,
@@ -572,7 +533,6 @@ static const enum dss_feat_id omap3630_dss_feat_list[] = {
572 FEAT_ROWREPEATENABLE, 533 FEAT_ROWREPEATENABLE,
573 FEAT_RESIZECONF, 534 FEAT_RESIZECONF,
574 FEAT_DSI_PLL_PWR_BUG, 535 FEAT_DSI_PLL_PWR_BUG,
575 FEAT_DSI_PLL_FREQSEL,
576 FEAT_CPR, 536 FEAT_CPR,
577 FEAT_PRELOAD, 537 FEAT_PRELOAD,
578 FEAT_FIR_COEF_V, 538 FEAT_FIR_COEF_V,
@@ -654,8 +614,6 @@ static const enum dss_feat_id omap5_dss_feat_list[] = {
654 FEAT_ALPHA_FREE_ZORDER, 614 FEAT_ALPHA_FREE_ZORDER,
655 FEAT_FIFO_MERGE, 615 FEAT_FIFO_MERGE,
656 FEAT_BURST_2D, 616 FEAT_BURST_2D,
657 FEAT_DSI_PLL_SELFREQDCO,
658 FEAT_DSI_PLL_REFSEL,
659 FEAT_DSI_PHY_DCC, 617 FEAT_DSI_PHY_DCC,
660 FEAT_MFLAG, 618 FEAT_MFLAG,
661}; 619};
diff --git a/drivers/video/fbdev/omap2/dss/dss_features.h b/drivers/video/fbdev/omap2/dss/dss_features.h
index e3ef3b714896..100f7a2d0638 100644
--- a/drivers/video/fbdev/omap2/dss/dss_features.h
+++ b/drivers/video/fbdev/omap2/dss/dss_features.h
@@ -41,7 +41,6 @@ enum dss_feat_id {
41 FEAT_LCD_CLK_SRC, 41 FEAT_LCD_CLK_SRC,
42 /* DSI-PLL power command 0x3 is not working */ 42 /* DSI-PLL power command 0x3 is not working */
43 FEAT_DSI_PLL_PWR_BUG, 43 FEAT_DSI_PLL_PWR_BUG,
44 FEAT_DSI_PLL_FREQSEL,
45 FEAT_DSI_DCS_CMD_CONFIG_VC, 44 FEAT_DSI_DCS_CMD_CONFIG_VC,
46 FEAT_DSI_VC_OCP_WIDTH, 45 FEAT_DSI_VC_OCP_WIDTH,
47 FEAT_DSI_REVERSE_TXCLKESC, 46 FEAT_DSI_REVERSE_TXCLKESC,
@@ -61,8 +60,6 @@ enum dss_feat_id {
61 /* An unknown HW bug causing the normal FIFO thresholds not to work */ 60 /* An unknown HW bug causing the normal FIFO thresholds not to work */
62 FEAT_OMAP3_DSI_FIFO_BUG, 61 FEAT_OMAP3_DSI_FIFO_BUG,
63 FEAT_BURST_2D, 62 FEAT_BURST_2D,
64 FEAT_DSI_PLL_SELFREQDCO,
65 FEAT_DSI_PLL_REFSEL,
66 FEAT_DSI_PHY_DCC, 63 FEAT_DSI_PHY_DCC,
67 FEAT_MFLAG, 64 FEAT_MFLAG,
68}; 65};
@@ -77,20 +74,11 @@ enum dss_feat_reg_field {
77 FEAT_REG_HORIZONTALACCU, 74 FEAT_REG_HORIZONTALACCU,
78 FEAT_REG_VERTICALACCU, 75 FEAT_REG_VERTICALACCU,
79 FEAT_REG_DISPC_CLK_SWITCH, 76 FEAT_REG_DISPC_CLK_SWITCH,
80 FEAT_REG_DSIPLL_REGN,
81 FEAT_REG_DSIPLL_REGM,
82 FEAT_REG_DSIPLL_REGM_DISPC,
83 FEAT_REG_DSIPLL_REGM_DSI,
84}; 77};
85 78
86enum dss_range_param { 79enum dss_range_param {
87 FEAT_PARAM_DSS_FCK, 80 FEAT_PARAM_DSS_FCK,
88 FEAT_PARAM_DSS_PCD, 81 FEAT_PARAM_DSS_PCD,
89 FEAT_PARAM_DSIPLL_REGN,
90 FEAT_PARAM_DSIPLL_REGM,
91 FEAT_PARAM_DSIPLL_REGM_DISPC,
92 FEAT_PARAM_DSIPLL_REGM_DSI,
93 FEAT_PARAM_DSIPLL_FINT,
94 FEAT_PARAM_DSIPLL_LPDIV, 82 FEAT_PARAM_DSIPLL_LPDIV,
95 FEAT_PARAM_DSI_FCK, 83 FEAT_PARAM_DSI_FCK,
96 FEAT_PARAM_DOWNSCALE, 84 FEAT_PARAM_DOWNSCALE,
diff --git a/drivers/video/fbdev/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h
index 262771b9b76b..e4a32fe77b02 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi.h
@@ -101,13 +101,6 @@ enum hdmi_core_hdmi_dvi {
101 HDMI_HDMI = 1 101 HDMI_HDMI = 1
102}; 102};
103 103
104enum hdmi_clk_refsel {
105 HDMI_REFSEL_PCLK = 0,
106 HDMI_REFSEL_REF1 = 1,
107 HDMI_REFSEL_REF2 = 2,
108 HDMI_REFSEL_SYSCLK = 3
109};
110
111enum hdmi_packing_mode { 104enum hdmi_packing_mode {
112 HDMI_PACK_10b_RGB_YUV444 = 0, 105 HDMI_PACK_10b_RGB_YUV444 = 0,
113 HDMI_PACK_24b_RGB_YUV444_YUV422 = 1, 106 HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
@@ -160,7 +153,8 @@ enum hdmi_audio_blk_strt_end_sig {
160 153
161enum hdmi_core_audio_layout { 154enum hdmi_core_audio_layout {
162 HDMI_AUDIO_LAYOUT_2CH = 0, 155 HDMI_AUDIO_LAYOUT_2CH = 0,
163 HDMI_AUDIO_LAYOUT_8CH = 1 156 HDMI_AUDIO_LAYOUT_8CH = 1,
157 HDMI_AUDIO_LAYOUT_6CH = 2
164}; 158};
165 159
166enum hdmi_core_cts_mode { 160enum hdmi_core_cts_mode {
@@ -191,17 +185,6 @@ struct hdmi_config {
191 enum hdmi_core_hdmi_dvi hdmi_dvi_mode; 185 enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
192}; 186};
193 187
194/* HDMI PLL structure */
195struct hdmi_pll_info {
196 u16 regn;
197 u16 regm;
198 u32 regmf;
199 u16 regm2;
200 u16 regsd;
201 u16 dcofreq;
202 enum hdmi_clk_refsel refsel;
203};
204
205struct hdmi_audio_format { 188struct hdmi_audio_format {
206 enum hdmi_stereo_channels stereo_channels; 189 enum hdmi_stereo_channels stereo_channels;
207 u8 active_chnnls_msk; 190 u8 active_chnnls_msk;
@@ -249,12 +232,15 @@ struct hdmi_core_audio_config {
249 232
250struct hdmi_wp_data { 233struct hdmi_wp_data {
251 void __iomem *base; 234 void __iomem *base;
235 phys_addr_t phys_base;
252}; 236};
253 237
254struct hdmi_pll_data { 238struct hdmi_pll_data {
239 struct dss_pll pll;
240
255 void __iomem *base; 241 void __iomem *base;
256 242
257 struct hdmi_pll_info info; 243 struct hdmi_wp_data *wp;
258}; 244};
259 245
260struct hdmi_phy_data { 246struct hdmi_phy_data {
@@ -316,16 +302,19 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp,
316void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, 302void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
317 struct omap_video_timings *timings, struct hdmi_config *param); 303 struct omap_video_timings *timings, struct hdmi_config *param);
318int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); 304int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp);
305phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp);
319 306
320/* HDMI PLL funcs */ 307/* HDMI PLL funcs */
321int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
322void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp);
323void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); 308void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s);
324void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy); 309void hdmi_pll_compute(struct hdmi_pll_data *pll,
325int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); 310 unsigned long target_tmds, struct dss_pll_clock_info *pi);
311int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
312 struct hdmi_wp_data *wp);
313void hdmi_pll_uninit(struct hdmi_pll_data *hpll);
326 314
327/* HDMI PHY funcs */ 315/* HDMI PHY funcs */
328int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg); 316int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
317 unsigned long lfbitclk);
329void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); 318void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s);
330int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); 319int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
331int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes); 320int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
@@ -334,7 +323,7 @@ int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
334int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep, 323int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
335 struct hdmi_phy_data *phy); 324 struct hdmi_phy_data *phy);
336 325
337#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) 326/* Audio funcs */
338int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); 327int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts);
339int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); 328int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable);
340int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); 329int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable);
@@ -342,9 +331,33 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
342 struct hdmi_audio_format *aud_fmt); 331 struct hdmi_audio_format *aud_fmt);
343void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, 332void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp,
344 struct hdmi_audio_dma *aud_dma); 333 struct hdmi_audio_dma *aud_dma);
345static inline bool hdmi_mode_has_audio(int mode) 334static inline bool hdmi_mode_has_audio(struct hdmi_config *cfg)
346{ 335{
347 return mode == HDMI_HDMI ? true : false; 336 return cfg->hdmi_dvi_mode == HDMI_HDMI ? true : false;
348} 337}
349#endif 338
339/* HDMI DRV data */
340struct omap_hdmi {
341 struct mutex lock;
342 struct platform_device *pdev;
343
344 struct hdmi_wp_data wp;
345 struct hdmi_pll_data pll;
346 struct hdmi_phy_data phy;
347 struct hdmi_core_data core;
348
349 struct hdmi_config cfg;
350
351 struct regulator *vdda_reg;
352
353 bool core_enabled;
354 bool display_enabled;
355
356 struct omap_dss_device output;
357
358 struct platform_device *audio_pdev;
359 void (*audio_abort_cb)(struct device *dev);
360 int wp_idlemode;
361};
362
350#endif 363#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c
index 9a8713ca090c..f1a02bf938ee 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4.c
@@ -33,29 +33,14 @@
33#include <linux/gpio.h> 33#include <linux/gpio.h>
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <video/omapdss.h> 35#include <video/omapdss.h>
36#include <sound/omap-hdmi-audio.h>
36 37
37#include "hdmi4_core.h" 38#include "hdmi4_core.h"
38#include "dss.h" 39#include "dss.h"
39#include "dss_features.h" 40#include "dss_features.h"
41#include "hdmi.h"
40 42
41static struct { 43static struct omap_hdmi hdmi;
42 struct mutex lock;
43 struct platform_device *pdev;
44
45 struct hdmi_wp_data wp;
46 struct hdmi_pll_data pll;
47 struct hdmi_phy_data phy;
48 struct hdmi_core_data core;
49
50 struct hdmi_config cfg;
51
52 struct clk *sys_clk;
53 struct regulator *vdda_hdmi_dac_reg;
54
55 bool core_enabled;
56
57 struct omap_dss_device output;
58} hdmi;
59 44
60static int hdmi_runtime_get(void) 45static int hdmi_runtime_get(void)
61{ 46{
@@ -117,7 +102,7 @@ static int hdmi_init_regulator(void)
117 int r; 102 int r;
118 struct regulator *reg; 103 struct regulator *reg;
119 104
120 if (hdmi.vdda_hdmi_dac_reg != NULL) 105 if (hdmi.vdda_reg != NULL)
121 return 0; 106 return 0;
122 107
123 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda"); 108 reg = devm_regulator_get(&hdmi.pdev->dev, "vdda");
@@ -137,7 +122,7 @@ static int hdmi_init_regulator(void)
137 } 122 }
138 } 123 }
139 124
140 hdmi.vdda_hdmi_dac_reg = reg; 125 hdmi.vdda_reg = reg;
141 126
142 return 0; 127 return 0;
143} 128}
@@ -146,7 +131,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
146{ 131{
147 int r; 132 int r;
148 133
149 r = regulator_enable(hdmi.vdda_hdmi_dac_reg); 134 r = regulator_enable(hdmi.vdda_reg);
150 if (r) 135 if (r)
151 return r; 136 return r;
152 137
@@ -162,7 +147,7 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev)
162 return 0; 147 return 0;
163 148
164err_runtime_get: 149err_runtime_get:
165 regulator_disable(hdmi.vdda_hdmi_dac_reg); 150 regulator_disable(hdmi.vdda_reg);
166 151
167 return r; 152 return r;
168} 153}
@@ -172,7 +157,7 @@ static void hdmi_power_off_core(struct omap_dss_device *dssdev)
172 hdmi.core_enabled = false; 157 hdmi.core_enabled = false;
173 158
174 hdmi_runtime_put(); 159 hdmi_runtime_put();
175 regulator_disable(hdmi.vdda_hdmi_dac_reg); 160 regulator_disable(hdmi.vdda_reg);
176} 161}
177 162
178static int hdmi_power_on_full(struct omap_dss_device *dssdev) 163static int hdmi_power_on_full(struct omap_dss_device *dssdev)
@@ -180,8 +165,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
180 int r; 165 int r;
181 struct omap_video_timings *p; 166 struct omap_video_timings *p;
182 struct omap_overlay_manager *mgr = hdmi.output.manager; 167 struct omap_overlay_manager *mgr = hdmi.output.manager;
183 unsigned long phy;
184 struct hdmi_wp_data *wp = &hdmi.wp; 168 struct hdmi_wp_data *wp = &hdmi.wp;
169 struct dss_pll_clock_info hdmi_cinfo = { 0 };
185 170
186 r = hdmi_power_on_core(dssdev); 171 r = hdmi_power_on_core(dssdev);
187 if (r) 172 if (r)
@@ -195,19 +180,22 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
195 180
196 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 181 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
197 182
198 /* the functions below use kHz pixel clock. TODO: change to Hz */ 183 hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
199 phy = p->pixelclock / 1000;
200
201 hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
202 184
203 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 185 r = dss_pll_enable(&hdmi.pll.pll);
204 r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
205 if (r) { 186 if (r) {
206 DSSDBG("Failed to lock PLL\n"); 187 DSSERR("Failed to enable PLL\n");
207 goto err_pll_enable; 188 goto err_pll_enable;
208 } 189 }
209 190
210 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg); 191 r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
192 if (r) {
193 DSSERR("Failed to configure PLL\n");
194 goto err_pll_cfg;
195 }
196
197 r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
198 hdmi_cinfo.clkout[0]);
211 if (r) { 199 if (r) {
212 DSSDBG("Failed to configure PHY\n"); 200 DSSDBG("Failed to configure PHY\n");
213 goto err_phy_cfg; 201 goto err_phy_cfg;
@@ -244,7 +232,8 @@ err_vid_enable:
244err_phy_cfg: 232err_phy_cfg:
245 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 233 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
246err_phy_pwr: 234err_phy_pwr:
247 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 235err_pll_cfg:
236 dss_pll_disable(&hdmi.pll.pll);
248err_pll_enable: 237err_pll_enable:
249 hdmi_power_off_core(dssdev); 238 hdmi_power_off_core(dssdev);
250 return -EIO; 239 return -EIO;
@@ -262,7 +251,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
262 251
263 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 252 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
264 253
265 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 254 dss_pll_disable(&hdmi.pll.pll);
266 255
267 hdmi_power_off_core(dssdev); 256 hdmi_power_off_core(dssdev);
268} 257}
@@ -352,6 +341,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
352 goto err0; 341 goto err0;
353 } 342 }
354 343
344 hdmi.display_enabled = true;
345
355 mutex_unlock(&hdmi.lock); 346 mutex_unlock(&hdmi.lock);
356 return 0; 347 return 0;
357 348
@@ -366,8 +357,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
366 357
367 mutex_lock(&hdmi.lock); 358 mutex_lock(&hdmi.lock);
368 359
360 if (hdmi.audio_pdev && hdmi.audio_abort_cb)
361 hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
362
369 hdmi_power_off_full(dssdev); 363 hdmi_power_off_full(dssdev);
370 364
365 hdmi.display_enabled = false;
366
371 mutex_unlock(&hdmi.lock); 367 mutex_unlock(&hdmi.lock);
372} 368}
373 369
@@ -404,21 +400,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
404 mutex_unlock(&hdmi.lock); 400 mutex_unlock(&hdmi.lock);
405} 401}
406 402
407static int hdmi_get_clocks(struct platform_device *pdev)
408{
409 struct clk *clk;
410
411 clk = devm_clk_get(&pdev->dev, "sys_clk");
412 if (IS_ERR(clk)) {
413 DSSERR("can't get sys_clk\n");
414 return PTR_ERR(clk);
415 }
416
417 hdmi.sys_clk = clk;
418
419 return 0;
420}
421
422static int hdmi_connect(struct omap_dss_device *dssdev, 403static int hdmi_connect(struct omap_dss_device *dssdev,
423 struct omap_dss_device *dst) 404 struct omap_dss_device *dst)
424{ 405{
@@ -484,112 +465,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
484 return r; 465 return r;
485} 466}
486 467
487#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
488static int hdmi_audio_enable(struct omap_dss_device *dssdev)
489{
490 int r;
491
492 mutex_lock(&hdmi.lock);
493
494 if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
495 r = -EPERM;
496 goto err;
497 }
498
499 r = hdmi_wp_audio_enable(&hdmi.wp, true);
500 if (r)
501 goto err;
502
503 mutex_unlock(&hdmi.lock);
504 return 0;
505
506err:
507 mutex_unlock(&hdmi.lock);
508 return r;
509}
510
511static void hdmi_audio_disable(struct omap_dss_device *dssdev)
512{
513 hdmi_wp_audio_enable(&hdmi.wp, false);
514}
515
516static int hdmi_audio_start(struct omap_dss_device *dssdev)
517{
518 return hdmi4_audio_start(&hdmi.core, &hdmi.wp);
519}
520
521static void hdmi_audio_stop(struct omap_dss_device *dssdev)
522{
523 hdmi4_audio_stop(&hdmi.core, &hdmi.wp);
524}
525
526static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
527{
528 bool r;
529
530 mutex_lock(&hdmi.lock);
531
532 r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
533
534 mutex_unlock(&hdmi.lock);
535 return r;
536}
537
538static int hdmi_audio_config(struct omap_dss_device *dssdev,
539 struct omap_dss_audio *audio)
540{
541 int r;
542 u32 pclk = hdmi.cfg.timings.pixelclock;
543
544 mutex_lock(&hdmi.lock);
545
546 if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
547 r = -EPERM;
548 goto err;
549 }
550
551 r = hdmi4_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
552 if (r)
553 goto err;
554
555 mutex_unlock(&hdmi.lock);
556 return 0;
557
558err:
559 mutex_unlock(&hdmi.lock);
560 return r;
561}
562#else
563static int hdmi_audio_enable(struct omap_dss_device *dssdev)
564{
565 return -EPERM;
566}
567
568static void hdmi_audio_disable(struct omap_dss_device *dssdev)
569{
570}
571
572static int hdmi_audio_start(struct omap_dss_device *dssdev)
573{
574 return -EPERM;
575}
576
577static void hdmi_audio_stop(struct omap_dss_device *dssdev)
578{
579}
580
581static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
582{
583 return false;
584}
585
586static int hdmi_audio_config(struct omap_dss_device *dssdev,
587 struct omap_dss_audio *audio)
588{
589 return -EPERM;
590}
591#endif
592
593static int hdmi_set_infoframe(struct omap_dss_device *dssdev, 468static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
594 const struct hdmi_avi_infoframe *avi) 469 const struct hdmi_avi_infoframe *avi)
595{ 470{
@@ -618,13 +493,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
618 .read_edid = hdmi_read_edid, 493 .read_edid = hdmi_read_edid,
619 .set_infoframe = hdmi_set_infoframe, 494 .set_infoframe = hdmi_set_infoframe,
620 .set_hdmi_mode = hdmi_set_hdmi_mode, 495 .set_hdmi_mode = hdmi_set_hdmi_mode,
621
622 .audio_enable = hdmi_audio_enable,
623 .audio_disable = hdmi_audio_disable,
624 .audio_start = hdmi_audio_start,
625 .audio_stop = hdmi_audio_stop,
626 .audio_supported = hdmi_audio_supported,
627 .audio_config = hdmi_audio_config,
628}; 496};
629 497
630static void hdmi_init_output(struct platform_device *pdev) 498static void hdmi_init_output(struct platform_device *pdev)
@@ -642,7 +510,7 @@ static void hdmi_init_output(struct platform_device *pdev)
642 omapdss_register_output(out); 510 omapdss_register_output(out);
643} 511}
644 512
645static void __exit hdmi_uninit_output(struct platform_device *pdev) 513static void hdmi_uninit_output(struct platform_device *pdev)
646{ 514{
647 struct omap_dss_device *out = &hdmi.output; 515 struct omap_dss_device *out = &hdmi.output;
648 516
@@ -671,6 +539,112 @@ err:
671 return r; 539 return r;
672} 540}
673 541
542/* Audio callbacks */
543static int hdmi_audio_startup(struct device *dev,
544 void (*abort_cb)(struct device *dev))
545{
546 struct omap_hdmi *hd = dev_get_drvdata(dev);
547 int ret = 0;
548
549 mutex_lock(&hd->lock);
550
551 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
552 ret = -EPERM;
553 goto out;
554 }
555
556 hd->audio_abort_cb = abort_cb;
557
558out:
559 mutex_unlock(&hd->lock);
560
561 return ret;
562}
563
564static int hdmi_audio_shutdown(struct device *dev)
565{
566 struct omap_hdmi *hd = dev_get_drvdata(dev);
567
568 mutex_lock(&hd->lock);
569 hd->audio_abort_cb = NULL;
570 mutex_unlock(&hd->lock);
571
572 return 0;
573}
574
575static int hdmi_audio_start(struct device *dev)
576{
577 struct omap_hdmi *hd = dev_get_drvdata(dev);
578
579 WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
580 WARN_ON(!hd->display_enabled);
581
582 hdmi_wp_audio_enable(&hd->wp, true);
583 hdmi4_audio_start(&hd->core, &hd->wp);
584
585 return 0;
586}
587
588static void hdmi_audio_stop(struct device *dev)
589{
590 struct omap_hdmi *hd = dev_get_drvdata(dev);
591
592 WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
593 WARN_ON(!hd->display_enabled);
594
595 hdmi4_audio_stop(&hd->core, &hd->wp);
596 hdmi_wp_audio_enable(&hd->wp, false);
597}
598
599static int hdmi_audio_config(struct device *dev,
600 struct omap_dss_audio *dss_audio)
601{
602 struct omap_hdmi *hd = dev_get_drvdata(dev);
603 int ret;
604
605 mutex_lock(&hd->lock);
606
607 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
608 ret = -EPERM;
609 goto out;
610 }
611
612 ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio,
613 hd->cfg.timings.pixelclock);
614
615out:
616 mutex_unlock(&hd->lock);
617
618 return ret;
619}
620
621static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
622 .audio_startup = hdmi_audio_startup,
623 .audio_shutdown = hdmi_audio_shutdown,
624 .audio_start = hdmi_audio_start,
625 .audio_stop = hdmi_audio_stop,
626 .audio_config = hdmi_audio_config,
627};
628
629static int hdmi_audio_register(struct device *dev)
630{
631 struct omap_hdmi_audio_pdata pdata = {
632 .dev = dev,
633 .dss_version = omapdss_get_version(),
634 .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
635 .ops = &hdmi_audio_ops,
636 };
637
638 hdmi.audio_pdev = platform_device_register_data(
639 dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
640 &pdata, sizeof(pdata));
641
642 if (IS_ERR(hdmi.audio_pdev))
643 return PTR_ERR(hdmi.audio_pdev);
644
645 return 0;
646}
647
674/* HDMI HW IP initialisation */ 648/* HDMI HW IP initialisation */
675static int omapdss_hdmihw_probe(struct platform_device *pdev) 649static int omapdss_hdmihw_probe(struct platform_device *pdev)
676{ 650{
@@ -678,6 +652,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
678 int irq; 652 int irq;
679 653
680 hdmi.pdev = pdev; 654 hdmi.pdev = pdev;
655 dev_set_drvdata(&pdev->dev, &hdmi);
681 656
682 mutex_init(&hdmi.lock); 657 mutex_init(&hdmi.lock);
683 658
@@ -691,28 +666,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
691 if (r) 666 if (r)
692 return r; 667 return r;
693 668
694 r = hdmi_pll_init(pdev, &hdmi.pll); 669 r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
695 if (r) 670 if (r)
696 return r; 671 return r;
697 672
698 r = hdmi_phy_init(pdev, &hdmi.phy); 673 r = hdmi_phy_init(pdev, &hdmi.phy);
699 if (r) 674 if (r)
700 return r; 675 goto err;
701 676
702 r = hdmi4_core_init(pdev, &hdmi.core); 677 r = hdmi4_core_init(pdev, &hdmi.core);
703 if (r) 678 if (r)
704 return r; 679 goto err;
705
706 r = hdmi_get_clocks(pdev);
707 if (r) {
708 DSSERR("can't get clocks\n");
709 return r;
710 }
711 680
712 irq = platform_get_irq(pdev, 0); 681 irq = platform_get_irq(pdev, 0);
713 if (irq < 0) { 682 if (irq < 0) {
714 DSSERR("platform_get_irq failed\n"); 683 DSSERR("platform_get_irq failed\n");
715 return -ENODEV; 684 r = -ENODEV;
685 goto err;
716 } 686 }
717 687
718 r = devm_request_threaded_irq(&pdev->dev, irq, 688 r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -720,22 +690,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
720 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); 690 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
721 if (r) { 691 if (r) {
722 DSSERR("HDMI IRQ request failed\n"); 692 DSSERR("HDMI IRQ request failed\n");
723 return r; 693 goto err;
724 } 694 }
725 695
726 pm_runtime_enable(&pdev->dev); 696 pm_runtime_enable(&pdev->dev);
727 697
728 hdmi_init_output(pdev); 698 hdmi_init_output(pdev);
729 699
700 r = hdmi_audio_register(&pdev->dev);
701 if (r) {
702 DSSERR("Registering HDMI audio failed\n");
703 hdmi_uninit_output(pdev);
704 pm_runtime_disable(&pdev->dev);
705 return r;
706 }
707
730 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 708 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
731 709
732 return 0; 710 return 0;
711err:
712 hdmi_pll_uninit(&hdmi.pll);
713 return r;
733} 714}
734 715
735static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 716static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
736{ 717{
718 if (hdmi.audio_pdev)
719 platform_device_unregister(hdmi.audio_pdev);
720
737 hdmi_uninit_output(pdev); 721 hdmi_uninit_output(pdev);
738 722
723 hdmi_pll_uninit(&hdmi.pll);
724
739 pm_runtime_disable(&pdev->dev); 725 pm_runtime_disable(&pdev->dev);
740 726
741 return 0; 727 return 0;
@@ -743,8 +729,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
743 729
744static int hdmi_runtime_suspend(struct device *dev) 730static int hdmi_runtime_suspend(struct device *dev)
745{ 731{
746 clk_disable_unprepare(hdmi.sys_clk);
747
748 dispc_runtime_put(); 732 dispc_runtime_put();
749 733
750 return 0; 734 return 0;
@@ -758,8 +742,6 @@ static int hdmi_runtime_resume(struct device *dev)
758 if (r < 0) 742 if (r < 0)
759 return r; 743 return r;
760 744
761 clk_prepare_enable(hdmi.sys_clk);
762
763 return 0; 745 return 0;
764} 746}
765 747
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
index 4ad39cfce254..7eafea5b8e19 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4_core.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.c
@@ -31,10 +31,8 @@
31#include <linux/platform_device.h> 31#include <linux/platform_device.h>
32#include <linux/string.h> 32#include <linux/string.h>
33#include <linux/seq_file.h> 33#include <linux/seq_file.h>
34#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
35#include <sound/asound.h> 34#include <sound/asound.h>
36#include <sound/asoundef.h> 35#include <sound/asoundef.h>
37#endif
38 36
39#include "hdmi4_core.h" 37#include "hdmi4_core.h"
40#include "dss_features.h" 38#include "dss_features.h"
@@ -530,7 +528,6 @@ void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s)
530 DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID); 528 DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
531} 529}
532 530
533#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
534static void hdmi_core_audio_config(struct hdmi_core_data *core, 531static void hdmi_core_audio_config(struct hdmi_core_data *core,
535 struct hdmi_core_audio_config *cfg) 532 struct hdmi_core_audio_config *cfg)
536{ 533{
@@ -877,17 +874,6 @@ void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp)
877 hdmi_wp_audio_core_req_enable(wp, false); 874 hdmi_wp_audio_core_req_enable(wp, false);
878} 875}
879 876
880int hdmi4_audio_get_dma_port(u32 *offset, u32 *size)
881{
882 if (!offset || !size)
883 return -EINVAL;
884 *offset = HDMI_WP_AUDIO_DATA;
885 *size = 4;
886 return 0;
887}
888
889#endif
890
891int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) 877int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
892{ 878{
893 struct resource *res; 879 struct resource *res;
diff --git a/drivers/video/fbdev/omap2/dss/hdmi4_core.h b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
index 827909eb6c50..a069f96ec6f6 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi4_core.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi4_core.h
@@ -266,12 +266,8 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
266void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); 266void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s);
267int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); 267int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
268 268
269#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
270int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); 269int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
271void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); 270void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp);
272int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, 271int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
273 struct omap_dss_audio *audio, u32 pclk); 272 struct omap_dss_audio *audio, u32 pclk);
274int hdmi4_audio_get_dma_port(u32 *offset, u32 *size);
275#endif
276
277#endif 273#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5.c b/drivers/video/fbdev/omap2/dss/hdmi5.c
index 169b764bb9d4..d9d0d781625a 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi5.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi5.c
@@ -38,29 +38,13 @@
38#include <linux/gpio.h> 38#include <linux/gpio.h>
39#include <linux/regulator/consumer.h> 39#include <linux/regulator/consumer.h>
40#include <video/omapdss.h> 40#include <video/omapdss.h>
41#include <sound/omap-hdmi-audio.h>
41 42
42#include "hdmi5_core.h" 43#include "hdmi5_core.h"
43#include "dss.h" 44#include "dss.h"
44#include "dss_features.h" 45#include "dss_features.h"
45 46
46static struct { 47static struct omap_hdmi hdmi;
47 struct mutex lock;
48 struct platform_device *pdev;
49
50 struct hdmi_wp_data wp;
51 struct hdmi_pll_data pll;
52 struct hdmi_phy_data phy;
53 struct hdmi_core_data core;
54
55 struct hdmi_config cfg;
56
57 struct clk *sys_clk;
58 struct regulator *vdda_reg;
59
60 bool core_enabled;
61
62 struct omap_dss_device output;
63} hdmi;
64 48
65static int hdmi_runtime_get(void) 49static int hdmi_runtime_get(void)
66{ 50{
@@ -198,7 +182,7 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
198 int r; 182 int r;
199 struct omap_video_timings *p; 183 struct omap_video_timings *p;
200 struct omap_overlay_manager *mgr = hdmi.output.manager; 184 struct omap_overlay_manager *mgr = hdmi.output.manager;
201 unsigned long phy; 185 struct dss_pll_clock_info hdmi_cinfo = { 0 };
202 186
203 r = hdmi_power_on_core(dssdev); 187 r = hdmi_power_on_core(dssdev);
204 if (r) 188 if (r)
@@ -208,24 +192,27 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev)
208 192
209 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res); 193 DSSDBG("hdmi_power_on x_res= %d y_res = %d\n", p->x_res, p->y_res);
210 194
211 /* the functions below use kHz pixel clock. TODO: change to Hz */ 195 hdmi_pll_compute(&hdmi.pll, p->pixelclock, &hdmi_cinfo);
212 phy = p->pixelclock / 1000;
213
214 hdmi_pll_compute(&hdmi.pll, clk_get_rate(hdmi.sys_clk), phy);
215 196
216 /* disable and clear irqs */ 197 /* disable and clear irqs */
217 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); 198 hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff);
218 hdmi_wp_set_irqstatus(&hdmi.wp, 199 hdmi_wp_set_irqstatus(&hdmi.wp,
219 hdmi_wp_get_irqstatus(&hdmi.wp)); 200 hdmi_wp_get_irqstatus(&hdmi.wp));
220 201
221 /* config the PLL and PHY hdmi_set_pll_pwrfirst */ 202 r = dss_pll_enable(&hdmi.pll.pll);
222 r = hdmi_pll_enable(&hdmi.pll, &hdmi.wp);
223 if (r) { 203 if (r) {
224 DSSDBG("Failed to lock PLL\n"); 204 DSSERR("Failed to enable PLL\n");
225 goto err_pll_enable; 205 goto err_pll_enable;
226 } 206 }
227 207
228 r = hdmi_phy_configure(&hdmi.phy, &hdmi.cfg); 208 r = dss_pll_set_config(&hdmi.pll.pll, &hdmi_cinfo);
209 if (r) {
210 DSSERR("Failed to configure PLL\n");
211 goto err_pll_cfg;
212 }
213
214 r = hdmi_phy_configure(&hdmi.phy, hdmi_cinfo.clkdco,
215 hdmi_cinfo.clkout[0]);
229 if (r) { 216 if (r) {
230 DSSDBG("Failed to start PHY\n"); 217 DSSDBG("Failed to start PHY\n");
231 goto err_phy_cfg; 218 goto err_phy_cfg;
@@ -262,7 +249,8 @@ err_vid_enable:
262 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 249 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
263err_phy_pwr: 250err_phy_pwr:
264err_phy_cfg: 251err_phy_cfg:
265 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 252err_pll_cfg:
253 dss_pll_disable(&hdmi.pll.pll);
266err_pll_enable: 254err_pll_enable:
267 hdmi_power_off_core(dssdev); 255 hdmi_power_off_core(dssdev);
268 return -EIO; 256 return -EIO;
@@ -280,7 +268,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev)
280 268
281 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); 269 hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF);
282 270
283 hdmi_pll_disable(&hdmi.pll, &hdmi.wp); 271 dss_pll_disable(&hdmi.pll.pll);
284 272
285 hdmi_power_off_core(dssdev); 273 hdmi_power_off_core(dssdev);
286} 274}
@@ -290,6 +278,10 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
290{ 278{
291 struct omap_dss_device *out = &hdmi.output; 279 struct omap_dss_device *out = &hdmi.output;
292 280
281 /* TODO: proper interlace support */
282 if (timings->interlace)
283 return -EINVAL;
284
293 if (!dispc_mgr_timings_ok(out->dispc_channel, timings)) 285 if (!dispc_mgr_timings_ok(out->dispc_channel, timings))
294 return -EINVAL; 286 return -EINVAL;
295 287
@@ -377,6 +369,8 @@ static int hdmi_display_enable(struct omap_dss_device *dssdev)
377 goto err0; 369 goto err0;
378 } 370 }
379 371
372 hdmi.display_enabled = true;
373
380 mutex_unlock(&hdmi.lock); 374 mutex_unlock(&hdmi.lock);
381 return 0; 375 return 0;
382 376
@@ -391,8 +385,13 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev)
391 385
392 mutex_lock(&hdmi.lock); 386 mutex_lock(&hdmi.lock);
393 387
388 if (hdmi.audio_pdev && hdmi.audio_abort_cb)
389 hdmi.audio_abort_cb(&hdmi.audio_pdev->dev);
390
394 hdmi_power_off_full(dssdev); 391 hdmi_power_off_full(dssdev);
395 392
393 hdmi.display_enabled = false;
394
396 mutex_unlock(&hdmi.lock); 395 mutex_unlock(&hdmi.lock);
397} 396}
398 397
@@ -429,21 +428,6 @@ static void hdmi_core_disable(struct omap_dss_device *dssdev)
429 mutex_unlock(&hdmi.lock); 428 mutex_unlock(&hdmi.lock);
430} 429}
431 430
432static int hdmi_get_clocks(struct platform_device *pdev)
433{
434 struct clk *clk;
435
436 clk = devm_clk_get(&pdev->dev, "sys_clk");
437 if (IS_ERR(clk)) {
438 DSSERR("can't get sys_clk\n");
439 return PTR_ERR(clk);
440 }
441
442 hdmi.sys_clk = clk;
443
444 return 0;
445}
446
447static int hdmi_connect(struct omap_dss_device *dssdev, 431static int hdmi_connect(struct omap_dss_device *dssdev,
448 struct omap_dss_device *dst) 432 struct omap_dss_device *dst)
449{ 433{
@@ -509,112 +493,6 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev,
509 return r; 493 return r;
510} 494}
511 495
512#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
513static int hdmi_audio_enable(struct omap_dss_device *dssdev)
514{
515 int r;
516
517 mutex_lock(&hdmi.lock);
518
519 if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
520 r = -EPERM;
521 goto err;
522 }
523
524 r = hdmi_wp_audio_enable(&hdmi.wp, true);
525 if (r)
526 goto err;
527
528 mutex_unlock(&hdmi.lock);
529 return 0;
530
531err:
532 mutex_unlock(&hdmi.lock);
533 return r;
534}
535
536static void hdmi_audio_disable(struct omap_dss_device *dssdev)
537{
538 hdmi_wp_audio_enable(&hdmi.wp, false);
539}
540
541static int hdmi_audio_start(struct omap_dss_device *dssdev)
542{
543 return hdmi_wp_audio_core_req_enable(&hdmi.wp, true);
544}
545
546static void hdmi_audio_stop(struct omap_dss_device *dssdev)
547{
548 hdmi_wp_audio_core_req_enable(&hdmi.wp, false);
549}
550
551static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
552{
553 bool r;
554
555 mutex_lock(&hdmi.lock);
556
557 r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
558
559 mutex_unlock(&hdmi.lock);
560 return r;
561}
562
563static int hdmi_audio_config(struct omap_dss_device *dssdev,
564 struct omap_dss_audio *audio)
565{
566 int r;
567 u32 pclk = hdmi.cfg.timings.pixelclock;
568
569 mutex_lock(&hdmi.lock);
570
571 if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
572 r = -EPERM;
573 goto err;
574 }
575
576 r = hdmi5_audio_config(&hdmi.core, &hdmi.wp, audio, pclk);
577 if (r)
578 goto err;
579
580 mutex_unlock(&hdmi.lock);
581 return 0;
582
583err:
584 mutex_unlock(&hdmi.lock);
585 return r;
586}
587#else
588static int hdmi_audio_enable(struct omap_dss_device *dssdev)
589{
590 return -EPERM;
591}
592
593static void hdmi_audio_disable(struct omap_dss_device *dssdev)
594{
595}
596
597static int hdmi_audio_start(struct omap_dss_device *dssdev)
598{
599 return -EPERM;
600}
601
602static void hdmi_audio_stop(struct omap_dss_device *dssdev)
603{
604}
605
606static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
607{
608 return false;
609}
610
611static int hdmi_audio_config(struct omap_dss_device *dssdev,
612 struct omap_dss_audio *audio)
613{
614 return -EPERM;
615}
616#endif
617
618static int hdmi_set_infoframe(struct omap_dss_device *dssdev, 496static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
619 const struct hdmi_avi_infoframe *avi) 497 const struct hdmi_avi_infoframe *avi)
620{ 498{
@@ -643,13 +521,6 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
643 .read_edid = hdmi_read_edid, 521 .read_edid = hdmi_read_edid,
644 .set_infoframe = hdmi_set_infoframe, 522 .set_infoframe = hdmi_set_infoframe,
645 .set_hdmi_mode = hdmi_set_hdmi_mode, 523 .set_hdmi_mode = hdmi_set_hdmi_mode,
646
647 .audio_enable = hdmi_audio_enable,
648 .audio_disable = hdmi_audio_disable,
649 .audio_start = hdmi_audio_start,
650 .audio_stop = hdmi_audio_stop,
651 .audio_supported = hdmi_audio_supported,
652 .audio_config = hdmi_audio_config,
653}; 524};
654 525
655static void hdmi_init_output(struct platform_device *pdev) 526static void hdmi_init_output(struct platform_device *pdev)
@@ -667,7 +538,7 @@ static void hdmi_init_output(struct platform_device *pdev)
667 omapdss_register_output(out); 538 omapdss_register_output(out);
668} 539}
669 540
670static void __exit hdmi_uninit_output(struct platform_device *pdev) 541static void hdmi_uninit_output(struct platform_device *pdev)
671{ 542{
672 struct omap_dss_device *out = &hdmi.output; 543 struct omap_dss_device *out = &hdmi.output;
673 544
@@ -696,6 +567,119 @@ err:
696 return r; 567 return r;
697} 568}
698 569
570/* Audio callbacks */
571static int hdmi_audio_startup(struct device *dev,
572 void (*abort_cb)(struct device *dev))
573{
574 struct omap_hdmi *hd = dev_get_drvdata(dev);
575 int ret = 0;
576
577 mutex_lock(&hd->lock);
578
579 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
580 ret = -EPERM;
581 goto out;
582 }
583
584 hd->audio_abort_cb = abort_cb;
585
586out:
587 mutex_unlock(&hd->lock);
588
589 return ret;
590}
591
592static int hdmi_audio_shutdown(struct device *dev)
593{
594 struct omap_hdmi *hd = dev_get_drvdata(dev);
595
596 mutex_lock(&hd->lock);
597 hd->audio_abort_cb = NULL;
598 mutex_unlock(&hd->lock);
599
600 return 0;
601}
602
603static int hdmi_audio_start(struct device *dev)
604{
605 struct omap_hdmi *hd = dev_get_drvdata(dev);
606
607 WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
608 WARN_ON(!hd->display_enabled);
609
610 /* No-idle while playing audio, store the old value */
611 hd->wp_idlemode = REG_GET(hdmi.wp.base, HDMI_WP_SYSCONFIG, 3, 2);
612 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, 1, 3, 2);
613
614 hdmi_wp_audio_enable(&hd->wp, true);
615 hdmi_wp_audio_core_req_enable(&hd->wp, true);
616
617 return 0;
618}
619
620static void hdmi_audio_stop(struct device *dev)
621{
622 struct omap_hdmi *hd = dev_get_drvdata(dev);
623
624 WARN_ON(!hdmi_mode_has_audio(&hd->cfg));
625 WARN_ON(!hd->display_enabled);
626
627 hdmi_wp_audio_core_req_enable(&hd->wp, false);
628 hdmi_wp_audio_enable(&hd->wp, false);
629
630 /* Playback stopped, restore original idlemode */
631 REG_FLD_MOD(hdmi.wp.base, HDMI_WP_SYSCONFIG, hd->wp_idlemode, 3, 2);
632}
633
634static int hdmi_audio_config(struct device *dev,
635 struct omap_dss_audio *dss_audio)
636{
637 struct omap_hdmi *hd = dev_get_drvdata(dev);
638 int ret;
639
640 mutex_lock(&hd->lock);
641
642 if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) {
643 ret = -EPERM;
644 goto out;
645 }
646
647 ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio,
648 hd->cfg.timings.pixelclock);
649
650out:
651 mutex_unlock(&hd->lock);
652
653 return ret;
654}
655
656static const struct omap_hdmi_audio_ops hdmi_audio_ops = {
657 .audio_startup = hdmi_audio_startup,
658 .audio_shutdown = hdmi_audio_shutdown,
659 .audio_start = hdmi_audio_start,
660 .audio_stop = hdmi_audio_stop,
661 .audio_config = hdmi_audio_config,
662};
663
664static int hdmi_audio_register(struct device *dev)
665{
666 struct omap_hdmi_audio_pdata pdata = {
667 .dev = dev,
668 .dss_version = omapdss_get_version(),
669 .audio_dma_addr = hdmi_wp_get_audio_dma_addr(&hdmi.wp),
670 .ops = &hdmi_audio_ops,
671 };
672
673 hdmi.audio_pdev = platform_device_register_data(
674 dev, "omap-hdmi-audio", PLATFORM_DEVID_AUTO,
675 &pdata, sizeof(pdata));
676
677 if (IS_ERR(hdmi.audio_pdev))
678 return PTR_ERR(hdmi.audio_pdev);
679
680 return 0;
681}
682
699/* HDMI HW IP initialisation */ 683/* HDMI HW IP initialisation */
700static int omapdss_hdmihw_probe(struct platform_device *pdev) 684static int omapdss_hdmihw_probe(struct platform_device *pdev)
701{ 685{
@@ -703,6 +687,7 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
703 int irq; 687 int irq;
704 688
705 hdmi.pdev = pdev; 689 hdmi.pdev = pdev;
690 dev_set_drvdata(&pdev->dev, &hdmi);
706 691
707 mutex_init(&hdmi.lock); 692 mutex_init(&hdmi.lock);
708 693
@@ -716,28 +701,23 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
716 if (r) 701 if (r)
717 return r; 702 return r;
718 703
719 r = hdmi_pll_init(pdev, &hdmi.pll); 704 r = hdmi_pll_init(pdev, &hdmi.pll, &hdmi.wp);
720 if (r) 705 if (r)
721 return r; 706 return r;
722 707
723 r = hdmi_phy_init(pdev, &hdmi.phy); 708 r = hdmi_phy_init(pdev, &hdmi.phy);
724 if (r) 709 if (r)
725 return r; 710 goto err;
726 711
727 r = hdmi5_core_init(pdev, &hdmi.core); 712 r = hdmi5_core_init(pdev, &hdmi.core);
728 if (r) 713 if (r)
729 return r; 714 goto err;
730
731 r = hdmi_get_clocks(pdev);
732 if (r) {
733 DSSERR("can't get clocks\n");
734 return r;
735 }
736 715
737 irq = platform_get_irq(pdev, 0); 716 irq = platform_get_irq(pdev, 0);
738 if (irq < 0) { 717 if (irq < 0) {
739 DSSERR("platform_get_irq failed\n"); 718 DSSERR("platform_get_irq failed\n");
740 return -ENODEV; 719 r = -ENODEV;
720 goto err;
741 } 721 }
742 722
743 r = devm_request_threaded_irq(&pdev->dev, irq, 723 r = devm_request_threaded_irq(&pdev->dev, irq,
@@ -745,22 +725,38 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
745 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); 725 IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp);
746 if (r) { 726 if (r) {
747 DSSERR("HDMI IRQ request failed\n"); 727 DSSERR("HDMI IRQ request failed\n");
748 return r; 728 goto err;
749 } 729 }
750 730
751 pm_runtime_enable(&pdev->dev); 731 pm_runtime_enable(&pdev->dev);
752 732
753 hdmi_init_output(pdev); 733 hdmi_init_output(pdev);
754 734
735 r = hdmi_audio_register(&pdev->dev);
736 if (r) {
737 DSSERR("Registering HDMI audio failed %d\n", r);
738 hdmi_uninit_output(pdev);
739 pm_runtime_disable(&pdev->dev);
740 return r;
741 }
742
755 dss_debugfs_create_file("hdmi", hdmi_dump_regs); 743 dss_debugfs_create_file("hdmi", hdmi_dump_regs);
756 744
757 return 0; 745 return 0;
746err:
747 hdmi_pll_uninit(&hdmi.pll);
748 return r;
758} 749}
759 750
760static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) 751static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
761{ 752{
753 if (hdmi.audio_pdev)
754 platform_device_unregister(hdmi.audio_pdev);
755
762 hdmi_uninit_output(pdev); 756 hdmi_uninit_output(pdev);
763 757
758 hdmi_pll_uninit(&hdmi.pll);
759
764 pm_runtime_disable(&pdev->dev); 760 pm_runtime_disable(&pdev->dev);
765 761
766 return 0; 762 return 0;
@@ -768,8 +764,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
768 764
769static int hdmi_runtime_suspend(struct device *dev) 765static int hdmi_runtime_suspend(struct device *dev)
770{ 766{
771 clk_disable_unprepare(hdmi.sys_clk);
772
773 dispc_runtime_put(); 767 dispc_runtime_put();
774 768
775 return 0; 769 return 0;
@@ -783,8 +777,6 @@ static int hdmi_runtime_resume(struct device *dev)
783 if (r < 0) 777 if (r < 0)
784 return r; 778 return r;
785 779
786 clk_prepare_enable(hdmi.sys_clk);
787
788 return 0; 780 return 0;
789} 781}
790 782
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.c b/drivers/video/fbdev/omap2/dss/hdmi5_core.c
index 83acbf7a8c89..a3cfe3d708f7 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi5_core.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.c
@@ -30,10 +30,8 @@
30#include <linux/string.h> 30#include <linux/string.h>
31#include <linux/seq_file.h> 31#include <linux/seq_file.h>
32#include <drm/drm_edid.h> 32#include <drm/drm_edid.h>
33#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
34#include <sound/asound.h> 33#include <sound/asound.h>
35#include <sound/asoundef.h> 34#include <sound/asoundef.h>
36#endif
37 35
38#include "hdmi5_core.h" 36#include "hdmi5_core.h"
39 37
@@ -644,9 +642,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
644 hdmi_core_enable_interrupts(core); 642 hdmi_core_enable_interrupts(core);
645} 643}
646 644
647
648#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
649
650static void hdmi5_core_audio_config(struct hdmi_core_data *core, 645static void hdmi5_core_audio_config(struct hdmi_core_data *core,
651 struct hdmi_core_audio_config *cfg) 646 struct hdmi_core_audio_config *cfg)
652{ 647{
@@ -721,7 +716,7 @@ static void hdmi5_core_audio_config(struct hdmi_core_data *core,
721 716
722 /* Source number */ 717 /* Source number */
723 val = cfg->iec60958_cfg->status[2] & IEC958_AES2_CON_SOURCE; 718 val = cfg->iec60958_cfg->status[2] & IEC958_AES2_CON_SOURCE;
724 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 4); 719 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(2), val, 3, 0);
725 720
726 /* Channel number right 0 */ 721 /* Channel number right 0 */
727 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 2, 3, 0); 722 REG_FLD_MOD(base, HDMI_CORE_FC_AUDSCHNLS(3), 2, 3, 0);
@@ -879,6 +874,9 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
879 /* only LPCM atm */ 874 /* only LPCM atm */
880 audio_format.type = HDMI_AUDIO_TYPE_LPCM; 875 audio_format.type = HDMI_AUDIO_TYPE_LPCM;
881 876
877 /* only allowed option */
878 audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
879
882 /* disable start/stop signals of IEC 60958 blocks */ 880 /* disable start/stop signals of IEC 60958 blocks */
883 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON; 881 audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_ON;
884 882
@@ -894,7 +892,6 @@ int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
894 892
895 return 0; 893 return 0;
896} 894}
897#endif
898 895
899int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core) 896int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core)
900{ 897{
diff --git a/drivers/video/fbdev/omap2/dss/hdmi5_core.h b/drivers/video/fbdev/omap2/dss/hdmi5_core.h
index ce7e9f376f04..f2f1022c5516 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi5_core.h
+++ b/drivers/video/fbdev/omap2/dss/hdmi5_core.h
@@ -299,8 +299,6 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
299 struct hdmi_config *cfg); 299 struct hdmi_config *cfg);
300int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); 300int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core);
301 301
302#if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
303int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, 302int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
304 struct omap_dss_audio *audio, u32 pclk); 303 struct omap_dss_audio *audio, u32 pclk);
305#endif 304#endif
306#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/dss/hdmi_common.c
index 7d5f1039de9f..1b8fcc6c4ba1 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_common.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_common.c
@@ -48,7 +48,6 @@ int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
48 return 0; 48 return 0;
49} 49}
50 50
51#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
52int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) 51int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
53{ 52{
54 u32 deep_color; 53 u32 deep_color;
@@ -147,4 +146,3 @@ int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts)
147 146
148 return 0; 147 return 0;
149} 148}
150#endif
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
index e007ac892d79..bc9e07d2afbe 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_phy.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_phy.c
@@ -20,9 +20,7 @@
20 20
21struct hdmi_phy_features { 21struct hdmi_phy_features {
22 bool bist_ctrl; 22 bool bist_ctrl;
23 bool calc_freqout;
24 bool ldo_voltage; 23 bool ldo_voltage;
25 unsigned long dcofreq_min;
26 unsigned long max_phy; 24 unsigned long max_phy;
27}; 25};
28 26
@@ -132,7 +130,8 @@ static void hdmi_phy_configure_lanes(struct hdmi_phy_data *phy)
132 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27); 130 REG_FLD_MOD(phy->base, HDMI_TXPHY_PAD_CFG_CTRL, pol_val, 30, 27);
133} 131}
134 132
135int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg) 133int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk,
134 unsigned long lfbitclk)
136{ 135{
137 u8 freqout; 136 u8 freqout;
138 137
@@ -149,20 +148,16 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
149 if (phy_feat->bist_ctrl) 148 if (phy_feat->bist_ctrl)
150 REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11); 149 REG_FLD_MOD(phy->base, HDMI_TXPHY_BIST_CONTROL, 1, 11, 11);
151 150
152 if (phy_feat->calc_freqout) { 151 /*
153 /* DCOCLK/10 is pixel clock, compare pclk with DCOCLK_MIN/10 */ 152 * If the hfbitclk != lfbitclk, it means the lfbitclk was configured
154 u32 dco_min = phy_feat->dcofreq_min / 10; 153 * to be used for TMDS.
155 u32 pclk = cfg->timings.pixelclock; 154 */
156 155 if (hfbitclk != lfbitclk)
157 if (pclk < dco_min) 156 freqout = 0;
158 freqout = 0; 157 else if (hfbitclk / 10 < phy_feat->max_phy)
159 else if ((pclk >= dco_min) && (pclk < phy_feat->max_phy))
160 freqout = 1;
161 else
162 freqout = 2;
163 } else {
164 freqout = 1; 158 freqout = 1;
165 } 159 else
160 freqout = 2;
166 161
167 /* 162 /*
168 * Write to phy address 0 to configure the clock 163 * Write to phy address 0 to configure the clock
@@ -184,17 +179,13 @@ int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg)
184 179
185static const struct hdmi_phy_features omap44xx_phy_feats = { 180static const struct hdmi_phy_features omap44xx_phy_feats = {
186 .bist_ctrl = false, 181 .bist_ctrl = false,
187 .calc_freqout = false,
188 .ldo_voltage = true, 182 .ldo_voltage = true,
189 .dcofreq_min = 500000000,
190 .max_phy = 185675000, 183 .max_phy = 185675000,
191}; 184};
192 185
193static const struct hdmi_phy_features omap54xx_phy_feats = { 186static const struct hdmi_phy_features omap54xx_phy_feats = {
194 .bist_ctrl = true, 187 .bist_ctrl = true,
195 .calc_freqout = true,
196 .ldo_voltage = false, 188 .ldo_voltage = false,
197 .dcofreq_min = 750000000,
198 .max_phy = 186000000, 189 .max_phy = 186000000,
199}; 190};
200 191
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
index 6d92bb32fe51..87accdb59c81 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_pll.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_pll.c
@@ -15,26 +15,13 @@
15#include <linux/err.h> 15#include <linux/err.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/clk.h>
19
18#include <video/omapdss.h> 20#include <video/omapdss.h>
19 21
20#include "dss.h" 22#include "dss.h"
21#include "hdmi.h" 23#include "hdmi.h"
22 24
23#define HDMI_DEFAULT_REGN 16
24#define HDMI_DEFAULT_REGM2 1
25
26struct hdmi_pll_features {
27 bool sys_reset;
28 /* this is a hack, need to replace it with a better computation of M2 */
29 bool bound_dcofreq;
30 unsigned long fint_min, fint_max;
31 u16 regm_max;
32 unsigned long dcofreq_low_min, dcofreq_low_max;
33 unsigned long dcofreq_high_min, dcofreq_high_max;
34};
35
36static const struct hdmi_pll_features *pll_feat;
37
38void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) 25void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
39{ 26{
40#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\ 27#define DUMPPLL(r) seq_printf(s, "%-35s %08x\n", #r,\
@@ -51,228 +38,189 @@ void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s)
51 DUMPPLL(PLLCTRL_CFG4); 38 DUMPPLL(PLLCTRL_CFG4);
52} 39}
53 40
54void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy) 41void hdmi_pll_compute(struct hdmi_pll_data *pll,
42 unsigned long target_tmds, struct dss_pll_clock_info *pi)
55{ 43{
56 struct hdmi_pll_info *pi = &pll->info; 44 unsigned long fint, clkdco, clkout;
57 unsigned long refclk; 45 unsigned long target_bitclk, target_clkdco;
58 u32 mf; 46 unsigned long min_dco;
47 unsigned n, m, mf, m2, sd;
48 unsigned long clkin;
49 const struct dss_pll_hw *hw = pll->pll.hw;
59 50
60 /* use our funky units */ 51 clkin = clk_get_rate(pll->pll.clkin);
61 clkin /= 10000;
62 52
63 /* 53 DSSDBG("clkin %lu, target tmds %lu\n", clkin, target_tmds);
64 * Input clock is predivided by N + 1
65 * out put of which is reference clk
66 */
67 54
68 pi->regn = HDMI_DEFAULT_REGN; 55 target_bitclk = target_tmds * 10;
69 56
70 refclk = clkin / pi->regn; 57 /* Fint */
58 n = DIV_ROUND_UP(clkin, hw->fint_max);
59 fint = clkin / n;
71 60
72 /* temorary hack to make sure DCO freq isn't calculated too low */ 61 /* adjust m2 so that the clkdco will be high enough */
73 if (pll_feat->bound_dcofreq && phy <= 65000) 62 min_dco = roundup(hw->clkdco_min, fint);
74 pi->regm2 = 3; 63 m2 = DIV_ROUND_UP(min_dco, target_bitclk);
75 else 64 if (m2 == 0)
76 pi->regm2 = HDMI_DEFAULT_REGM2; 65 m2 = 1;
77
78 /*
79 * multiplier is pixel_clk/ref_clk
80 * Multiplying by 100 to avoid fractional part removal
81 */
82 pi->regm = phy * pi->regm2 / refclk;
83
84 /*
85 * fractional multiplier is remainder of the difference between
86 * multiplier and actual phy(required pixel clock thus should be
87 * multiplied by 2^18(262144) divided by the reference clock
88 */
89 mf = (phy - pi->regm / pi->regm2 * refclk) * 262144;
90 pi->regmf = pi->regm2 * mf / refclk;
91
92 /*
93 * Dcofreq should be set to 1 if required pixel clock
94 * is greater than 1000MHz
95 */
96 pi->dcofreq = phy > 1000 * 100;
97 pi->regsd = ((pi->regm * clkin / 10) / (pi->regn * 250) + 5) / 10;
98
99 /* Set the reference clock to sysclk reference */
100 pi->refsel = HDMI_REFSEL_SYSCLK;
101
102 DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
103 DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
104}
105 66
67 target_clkdco = target_bitclk * m2;
68 m = target_clkdco / fint;
106 69
107static int hdmi_pll_config(struct hdmi_pll_data *pll) 70 clkdco = fint * m;
108{
109 u32 r;
110 struct hdmi_pll_info *fmt = &pll->info;
111 71
112 /* PLL start always use manual mode */ 72 /* adjust clkdco with fractional mf */
113 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, 0x0, 0, 0); 73 if (WARN_ON(target_clkdco - clkdco > fint))
114 74 mf = 0;
115 r = hdmi_read_reg(pll->base, PLLCTRL_CFG1);
116 r = FLD_MOD(r, fmt->regm, 20, 9); /* CFG1_PLL_REGM */
117 r = FLD_MOD(r, fmt->regn - 1, 8, 1); /* CFG1_PLL_REGN */
118 hdmi_write_reg(pll->base, PLLCTRL_CFG1, r);
119
120 r = hdmi_read_reg(pll->base, PLLCTRL_CFG2);
121
122 r = FLD_MOD(r, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
123 r = FLD_MOD(r, 0x1, 13, 13); /* PLL_REFEN */
124 r = FLD_MOD(r, 0x0, 14, 14); /* PHY_CLKINEN de-assert during locking */
125 r = FLD_MOD(r, fmt->refsel, 22, 21); /* REFSEL */
126
127 if (fmt->dcofreq)
128 r = FLD_MOD(r, 0x4, 3, 1); /* 1000MHz and 2000MHz */
129 else 75 else
130 r = FLD_MOD(r, 0x2, 3, 1); /* 500MHz and 1000MHz */ 76 mf = (u32)div_u64(262144ull * (target_clkdco - clkdco), fint);
131
132 hdmi_write_reg(pll->base, PLLCTRL_CFG2, r);
133
134 REG_FLD_MOD(pll->base, PLLCTRL_CFG3, fmt->regsd, 17, 10);
135 77
136 r = hdmi_read_reg(pll->base, PLLCTRL_CFG4); 78 if (mf > 0)
137 r = FLD_MOD(r, fmt->regm2, 24, 18); 79 clkdco += (u32)div_u64((u64)mf * fint, 262144);
138 r = FLD_MOD(r, fmt->regmf, 17, 0);
139 hdmi_write_reg(pll->base, PLLCTRL_CFG4, r);
140 80
141 /* go now */ 81 clkout = clkdco / m2;
142 REG_FLD_MOD(pll->base, PLLCTRL_PLL_GO, 0x1, 0, 0);
143 82
144 /* wait for bit change */ 83 /* sigma-delta */
145 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_GO, 84 sd = DIV_ROUND_UP(fint * m, 250000000);
146 0, 0, 0) != 0) {
147 DSSERR("PLL GO bit not clearing\n");
148 return -ETIMEDOUT;
149 }
150 85
151 /* Wait till the lock bit is set in PLL status */ 86 DSSDBG("N = %u, M = %u, M.f = %u, M2 = %u, SD = %u\n",
152 if (hdmi_wait_for_bit_change(pll->base, 87 n, m, mf, m2, sd);
153 PLLCTRL_PLL_STATUS, 1, 1, 1) != 1) { 88 DSSDBG("Fint %lu, clkdco %lu, clkout %lu\n", fint, clkdco, clkout);
154 DSSERR("cannot lock PLL\n");
155 DSSERR("CFG1 0x%x\n",
156 hdmi_read_reg(pll->base, PLLCTRL_CFG1));
157 DSSERR("CFG2 0x%x\n",
158 hdmi_read_reg(pll->base, PLLCTRL_CFG2));
159 DSSERR("CFG4 0x%x\n",
160 hdmi_read_reg(pll->base, PLLCTRL_CFG4));
161 return -ETIMEDOUT;
162 }
163 89
164 DSSDBG("PLL locked!\n"); 90 pi->n = n;
91 pi->m = m;
92 pi->mf = mf;
93 pi->mX[0] = m2;
94 pi->sd = sd;
165 95
166 return 0; 96 pi->fint = fint;
97 pi->clkdco = clkdco;
98 pi->clkout[0] = clkout;
167} 99}
168 100
169static int hdmi_pll_reset(struct hdmi_pll_data *pll) 101static int hdmi_pll_enable(struct dss_pll *dsspll)
170{
171 /* SYSRESET controlled by power FSM */
172 REG_FLD_MOD(pll->base, PLLCTRL_PLL_CONTROL, pll_feat->sys_reset, 3, 3);
173
174 /* READ 0x0 reset is in progress */
175 if (hdmi_wait_for_bit_change(pll->base, PLLCTRL_PLL_STATUS, 0, 0, 1)
176 != 1) {
177 DSSERR("Failed to sysreset PLL\n");
178 return -ETIMEDOUT;
179 }
180
181 return 0;
182}
183
184int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp)
185{ 102{
103 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
104 struct hdmi_wp_data *wp = pll->wp;
186 u16 r = 0; 105 u16 r = 0;
187 106
188 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
189 if (r)
190 return r;
191
192 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS); 107 r = hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_BOTHON_ALLCLKS);
193 if (r) 108 if (r)
194 return r; 109 return r;
195 110
196 r = hdmi_pll_reset(pll);
197 if (r)
198 return r;
199
200 r = hdmi_pll_config(pll);
201 if (r)
202 return r;
203
204 return 0; 111 return 0;
205} 112}
206 113
207void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) 114static void hdmi_pll_disable(struct dss_pll *dsspll)
208{ 115{
116 struct hdmi_pll_data *pll = container_of(dsspll, struct hdmi_pll_data, pll);
117 struct hdmi_wp_data *wp = pll->wp;
118
209 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF); 119 hdmi_wp_set_pll_pwr(wp, HDMI_PLLPWRCMD_ALLOFF);
210} 120}
211 121
212static const struct hdmi_pll_features omap44xx_pll_feats = { 122static const struct dss_pll_ops dsi_pll_ops = {
213 .sys_reset = false, 123 .enable = hdmi_pll_enable,
214 .bound_dcofreq = false, 124 .disable = hdmi_pll_disable,
215 .fint_min = 500000, 125 .set_config = dss_pll_write_config_type_b,
216 .fint_max = 2500000,
217 .regm_max = 4095,
218 .dcofreq_low_min = 500000000,
219 .dcofreq_low_max = 1000000000,
220 .dcofreq_high_min = 1000000000,
221 .dcofreq_high_max = 2000000000,
222}; 126};
223 127
224static const struct hdmi_pll_features omap54xx_pll_feats = { 128static const struct dss_pll_hw dss_omap4_hdmi_pll_hw = {
225 .sys_reset = true, 129 .n_max = 255,
226 .bound_dcofreq = true, 130 .m_min = 20,
227 .fint_min = 620000, 131 .m_max = 4095,
228 .fint_max = 2500000, 132 .mX_max = 127,
229 .regm_max = 2046, 133 .fint_min = 500000,
230 .dcofreq_low_min = 750000000, 134 .fint_max = 2500000,
231 .dcofreq_low_max = 1500000000, 135 .clkdco_max = 1800000000,
232 .dcofreq_high_min = 1250000000, 136
233 .dcofreq_high_max = 2500000000UL, 137 .clkdco_min = 500000000,
138 .clkdco_low = 1000000000,
139 .clkdco_max = 2000000000,
140
141 .n_msb = 8,
142 .n_lsb = 1,
143 .m_msb = 20,
144 .m_lsb = 9,
145
146 .mX_msb[0] = 24,
147 .mX_lsb[0] = 18,
148
149 .has_selfreqdco = true,
234}; 150};
235 151
236static int hdmi_pll_init_features(struct platform_device *pdev) 152static const struct dss_pll_hw dss_omap5_hdmi_pll_hw = {
153 .n_max = 255,
154 .m_min = 20,
155 .m_max = 2045,
156 .mX_max = 127,
157 .fint_min = 620000,
158 .fint_max = 2500000,
159 .clkdco_max = 1800000000,
160
161 .clkdco_min = 750000000,
162 .clkdco_low = 1500000000,
163 .clkdco_max = 2500000000UL,
164
165 .n_msb = 8,
166 .n_lsb = 1,
167 .m_msb = 20,
168 .m_lsb = 9,
169
170 .mX_msb[0] = 24,
171 .mX_lsb[0] = 18,
172
173 .has_selfreqdco = true,
174 .has_refsel = true,
175};
176
177static int dsi_init_pll_data(struct platform_device *pdev, struct hdmi_pll_data *hpll)
237{ 178{
238 struct hdmi_pll_features *dst; 179 struct dss_pll *pll = &hpll->pll;
239 const struct hdmi_pll_features *src; 180 struct clk *clk;
181 int r;
240 182
241 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); 183 clk = devm_clk_get(&pdev->dev, "sys_clk");
242 if (!dst) { 184 if (IS_ERR(clk)) {
243 dev_err(&pdev->dev, "Failed to allocate HDMI PHY Features\n"); 185 DSSERR("can't get sys_clk\n");
244 return -ENOMEM; 186 return PTR_ERR(clk);
245 } 187 }
246 188
189 pll->name = "hdmi";
190 pll->base = hpll->base;
191 pll->clkin = clk;
192
247 switch (omapdss_get_version()) { 193 switch (omapdss_get_version()) {
248 case OMAPDSS_VER_OMAP4430_ES1: 194 case OMAPDSS_VER_OMAP4430_ES1:
249 case OMAPDSS_VER_OMAP4430_ES2: 195 case OMAPDSS_VER_OMAP4430_ES2:
250 case OMAPDSS_VER_OMAP4: 196 case OMAPDSS_VER_OMAP4:
251 src = &omap44xx_pll_feats; 197 pll->hw = &dss_omap4_hdmi_pll_hw;
252 break; 198 break;
253 199
254 case OMAPDSS_VER_OMAP5: 200 case OMAPDSS_VER_OMAP5:
255 src = &omap54xx_pll_feats; 201 pll->hw = &dss_omap5_hdmi_pll_hw;
256 break; 202 break;
257 203
258 default: 204 default:
259 return -ENODEV; 205 return -ENODEV;
260 } 206 }
261 207
262 memcpy(dst, src, sizeof(*dst)); 208 pll->ops = &dsi_pll_ops;
263 pll_feat = dst; 209
210 r = dss_pll_register(pll);
211 if (r)
212 return r;
264 213
265 return 0; 214 return 0;
266} 215}
267 216
268int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) 217int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll,
218 struct hdmi_wp_data *wp)
269{ 219{
270 int r; 220 int r;
271 struct resource *res; 221 struct resource *res;
272 222
273 r = hdmi_pll_init_features(pdev); 223 pll->wp = wp;
274 if (r)
275 return r;
276 224
277 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll"); 225 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll");
278 if (!res) { 226 if (!res) {
@@ -286,5 +234,18 @@ int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll)
286 return PTR_ERR(pll->base); 234 return PTR_ERR(pll->base);
287 } 235 }
288 236
237 r = dsi_init_pll_data(pdev, pll);
238 if (r) {
239 DSSERR("failed to init HDMI PLL\n");
240 return r;
241 }
242
289 return 0; 243 return 0;
290} 244}
245
246void hdmi_pll_uninit(struct hdmi_pll_data *hpll)
247{
248 struct dss_pll *pll = &hpll->pll;
249
250 dss_pll_unregister(pll);
251}
diff --git a/drivers/video/fbdev/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
index 496327e2b21b..c15377e242cc 100644
--- a/drivers/video/fbdev/omap2/dss/hdmi_wp.c
+++ b/drivers/video/fbdev/omap2/dss/hdmi_wp.c
@@ -185,7 +185,6 @@ void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt,
185 timings->interlace = param->timings.interlace; 185 timings->interlace = param->timings.interlace;
186} 186}
187 187
188#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) || defined(CONFIG_OMAP5_DSS_HDMI_AUDIO)
189void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, 188void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
190 struct hdmi_audio_format *aud_fmt) 189 struct hdmi_audio_format *aud_fmt)
191{ 190{
@@ -194,8 +193,12 @@ void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp,
194 DSSDBG("Enter hdmi_wp_audio_config_format\n"); 193 DSSDBG("Enter hdmi_wp_audio_config_format\n");
195 194
196 r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG); 195 r = hdmi_read_reg(wp->base, HDMI_WP_AUDIO_CFG);
197 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24); 196 if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 ||
198 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16); 197 omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 ||
198 omapdss_get_version() == OMAPDSS_VER_OMAP4) {
199 r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
200 r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
201 }
199 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5); 202 r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
200 r = FLD_MOD(r, aud_fmt->type, 4, 4); 203 r = FLD_MOD(r, aud_fmt->type, 4, 4);
201 r = FLD_MOD(r, aud_fmt->justification, 3, 3); 204 r = FLD_MOD(r, aud_fmt->justification, 3, 3);
@@ -236,7 +239,6 @@ int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable)
236 239
237 return 0; 240 return 0;
238} 241}
239#endif
240 242
241int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) 243int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
242{ 244{
@@ -247,6 +249,7 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
247 DSSERR("can't get WP mem resource\n"); 249 DSSERR("can't get WP mem resource\n");
248 return -EINVAL; 250 return -EINVAL;
249 } 251 }
252 wp->phys_base = res->start;
250 253
251 wp->base = devm_ioremap_resource(&pdev->dev, res); 254 wp->base = devm_ioremap_resource(&pdev->dev, res);
252 if (IS_ERR(wp->base)) { 255 if (IS_ERR(wp->base)) {
@@ -256,3 +259,8 @@ int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp)
256 259
257 return 0; 260 return 0;
258} 261}
262
263phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp)
264{
265 return wp->phys_base + HDMI_WP_AUDIO_DATA;
266}
diff --git a/drivers/video/fbdev/omap2/dss/output.c b/drivers/video/fbdev/omap2/dss/output.c
index 2ab3afa615e8..16072159bd24 100644
--- a/drivers/video/fbdev/omap2/dss/output.c
+++ b/drivers/video/fbdev/omap2/dss/output.c
@@ -19,6 +19,7 @@
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22#include <linux/of.h>
22 23
23#include <video/omapdss.h> 24#include <video/omapdss.h>
24 25
@@ -131,18 +132,30 @@ struct omap_dss_device *omap_dss_find_output(const char *name)
131} 132}
132EXPORT_SYMBOL(omap_dss_find_output); 133EXPORT_SYMBOL(omap_dss_find_output);
133 134
134struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node) 135struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port)
135{ 136{
137 struct device_node *src_node;
136 struct omap_dss_device *out; 138 struct omap_dss_device *out;
139 u32 reg;
140
141 src_node = dss_of_port_get_parent_device(port);
142 if (!src_node)
143 return NULL;
144
145 reg = dss_of_port_get_port_number(port);
137 146
138 list_for_each_entry(out, &output_list, list) { 147 list_for_each_entry(out, &output_list, list) {
139 if (out->dev->of_node == node) 148 if (out->dev->of_node == src_node && out->port_num == reg) {
149 of_node_put(src_node);
140 return omap_dss_get_device(out); 150 return omap_dss_get_device(out);
151 }
141 } 152 }
142 153
154 of_node_put(src_node);
155
143 return NULL; 156 return NULL;
144} 157}
145EXPORT_SYMBOL(omap_dss_find_output_by_node); 158EXPORT_SYMBOL(omap_dss_find_output_by_port_node);
146 159
147struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev) 160struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev)
148{ 161{
diff --git a/drivers/video/fbdev/omap2/dss/pll.c b/drivers/video/fbdev/omap2/dss/pll.c
new file mode 100644
index 000000000000..50bc62c5d367
--- /dev/null
+++ b/drivers/video/fbdev/omap2/dss/pll.c
@@ -0,0 +1,378 @@
1/*
2 * Copyright (C) 2014 Texas Instruments Incorporated
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 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#define DSS_SUBSYS_NAME "PLL"
18
19#include <linux/clk.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/regulator/consumer.h>
23#include <linux/sched.h>
24
25#include <video/omapdss.h>
26
27#include "dss.h"
28
29#define PLL_CONTROL 0x0000
30#define PLL_STATUS 0x0004
31#define PLL_GO 0x0008
32#define PLL_CONFIGURATION1 0x000C
33#define PLL_CONFIGURATION2 0x0010
34#define PLL_CONFIGURATION3 0x0014
35#define PLL_SSC_CONFIGURATION1 0x0018
36#define PLL_SSC_CONFIGURATION2 0x001C
37#define PLL_CONFIGURATION4 0x0020
38
39static struct dss_pll *dss_plls[4];
40
41int dss_pll_register(struct dss_pll *pll)
42{
43 int i;
44
45 for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
46 if (!dss_plls[i]) {
47 dss_plls[i] = pll;
48 return 0;
49 }
50 }
51
52 return -EBUSY;
53}
54
55void dss_pll_unregister(struct dss_pll *pll)
56{
57 int i;
58
59 for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
60 if (dss_plls[i] == pll) {
61 dss_plls[i] = NULL;
62 return;
63 }
64 }
65}
66
67struct dss_pll *dss_pll_find(const char *name)
68{
69 int i;
70
71 for (i = 0; i < ARRAY_SIZE(dss_plls); ++i) {
72 if (dss_plls[i] && strcmp(dss_plls[i]->name, name) == 0)
73 return dss_plls[i];
74 }
75
76 return NULL;
77}
78
79int dss_pll_enable(struct dss_pll *pll)
80{
81 int r;
82
83 r = clk_prepare_enable(pll->clkin);
84 if (r)
85 return r;
86
87 if (pll->regulator) {
88 r = regulator_enable(pll->regulator);
89 if (r)
90 goto err_reg;
91 }
92
93 r = pll->ops->enable(pll);
94 if (r)
95 goto err_enable;
96
97 return 0;
98
99err_enable:
100 regulator_disable(pll->regulator);
101err_reg:
102 clk_disable_unprepare(pll->clkin);
103 return r;
104}
105
106void dss_pll_disable(struct dss_pll *pll)
107{
108 pll->ops->disable(pll);
109
110 if (pll->regulator)
111 regulator_disable(pll->regulator);
112
113 clk_disable_unprepare(pll->clkin);
114
115 memset(&pll->cinfo, 0, sizeof(pll->cinfo));
116}
117
118int dss_pll_set_config(struct dss_pll *pll, const struct dss_pll_clock_info *cinfo)
119{
120 int r;
121
122 r = pll->ops->set_config(pll, cinfo);
123 if (r)
124 return r;
125
126 pll->cinfo = *cinfo;
127
128 return 0;
129}
130
131bool dss_pll_hsdiv_calc(const struct dss_pll *pll, unsigned long clkdco,
132 unsigned long out_min, unsigned long out_max,
133 dss_hsdiv_calc_func func, void *data)
134{
135 const struct dss_pll_hw *hw = pll->hw;
136 int m, m_start, m_stop;
137 unsigned long out;
138
139 out_min = out_min ? out_min : 1;
140 out_max = out_max ? out_max : ULONG_MAX;
141
142 m_start = max(DIV_ROUND_UP(clkdco, out_max), 1ul);
143
144 m_stop = min((unsigned)(clkdco / out_min), hw->mX_max);
145
146 for (m = m_start; m <= m_stop; ++m) {
147 out = clkdco / m;
148
149 if (func(m, out, data))
150 return true;
151 }
152
153 return false;
154}
155
156bool dss_pll_calc(const struct dss_pll *pll, unsigned long clkin,
157 unsigned long pll_min, unsigned long pll_max,
158 dss_pll_calc_func func, void *data)
159{
160 const struct dss_pll_hw *hw = pll->hw;
161 int n, n_start, n_stop;
162 int m, m_start, m_stop;
163 unsigned long fint, clkdco;
164 unsigned long pll_hw_max;
165 unsigned long fint_hw_min, fint_hw_max;
166
167 pll_hw_max = hw->clkdco_max;
168
169 fint_hw_min = hw->fint_min;
170 fint_hw_max = hw->fint_max;
171
172 n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul);
173 n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max);
174
175 pll_max = pll_max ? pll_max : ULONG_MAX;
176
177 for (n = n_start; n <= n_stop; ++n) {
178 fint = clkin / n;
179
180 m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2),
181 1ul);
182 m_stop = min3((unsigned)(pll_max / fint / 2),
183 (unsigned)(pll_hw_max / fint / 2),
184 hw->m_max);
185
186 for (m = m_start; m <= m_stop; ++m) {
187 clkdco = 2 * m * fint;
188
189 if (func(n, m, fint, clkdco, data))
190 return true;
191 }
192 }
193
194 return false;
195}
196
197static int wait_for_bit_change(void __iomem *reg, int bitnum, int value)
198{
199 unsigned long timeout;
200 ktime_t wait;
201 int t;
202
203 /* first busyloop to see if the bit changes right away */
204 t = 100;
205 while (t-- > 0) {
206 if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
207 return value;
208 }
209
210 /* then loop for 500ms, sleeping for 1ms in between */
211 timeout = jiffies + msecs_to_jiffies(500);
212 while (time_before(jiffies, timeout)) {
213 if (FLD_GET(readl_relaxed(reg), bitnum, bitnum) == value)
214 return value;
215
216 wait = ns_to_ktime(1000 * 1000);
217 set_current_state(TASK_UNINTERRUPTIBLE);
218 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
219 }
220
221 return !value;
222}
223
224static int dss_wait_hsdiv_ack(struct dss_pll *pll, u32 hsdiv_ack_mask)
225{
226 int t = 100;
227
228 while (t-- > 0) {
229 u32 v = readl_relaxed(pll->base + PLL_STATUS);
230 v &= hsdiv_ack_mask;
231 if (v == hsdiv_ack_mask)
232 return 0;
233 }
234
235 return -ETIMEDOUT;
236}
237
238int dss_pll_write_config_type_a(struct dss_pll *pll,
239 const struct dss_pll_clock_info *cinfo)
240{
241 const struct dss_pll_hw *hw = pll->hw;
242 void __iomem *base = pll->base;
243 int r = 0;
244 u32 l;
245
246 l = 0;
247 if (hw->has_stopmode)
248 l = FLD_MOD(l, 1, 0, 0); /* PLL_STOPMODE */
249 l = FLD_MOD(l, cinfo->n - 1, hw->n_msb, hw->n_lsb); /* PLL_REGN */
250 l = FLD_MOD(l, cinfo->m, hw->m_msb, hw->m_lsb); /* PLL_REGM */
251 /* M4 */
252 l = FLD_MOD(l, cinfo->mX[0] ? cinfo->mX[0] - 1 : 0,
253 hw->mX_msb[0], hw->mX_lsb[0]);
254 /* M5 */
255 l = FLD_MOD(l, cinfo->mX[1] ? cinfo->mX[1] - 1 : 0,
256 hw->mX_msb[1], hw->mX_lsb[1]);
257 writel_relaxed(l, base + PLL_CONFIGURATION1);
258
259 l = 0;
260 /* M6 */
261 l = FLD_MOD(l, cinfo->mX[2] ? cinfo->mX[2] - 1 : 0,
262 hw->mX_msb[2], hw->mX_lsb[2]);
263 /* M7 */
264 l = FLD_MOD(l, cinfo->mX[3] ? cinfo->mX[3] - 1 : 0,
265 hw->mX_msb[3], hw->mX_lsb[3]);
266 writel_relaxed(l, base + PLL_CONFIGURATION3);
267
268 l = readl_relaxed(base + PLL_CONFIGURATION2);
269 if (hw->has_freqsel) {
270 u32 f = cinfo->fint < 1000000 ? 0x3 :
271 cinfo->fint < 1250000 ? 0x4 :
272 cinfo->fint < 1500000 ? 0x5 :
273 cinfo->fint < 1750000 ? 0x6 :
274 0x7;
275
276 l = FLD_MOD(l, f, 4, 1); /* PLL_FREQSEL */
277 } else if (hw->has_selfreqdco) {
278 u32 f = cinfo->clkdco < hw->clkdco_low ? 0x2 : 0x4;
279
280 l = FLD_MOD(l, f, 3, 1); /* PLL_SELFREQDCO */
281 }
282 l = FLD_MOD(l, 1, 13, 13); /* PLL_REFEN */
283 l = FLD_MOD(l, 0, 14, 14); /* PHY_CLKINEN */
284 l = FLD_MOD(l, 0, 16, 16); /* M4_CLOCK_EN */
285 l = FLD_MOD(l, 0, 18, 18); /* M5_CLOCK_EN */
286 l = FLD_MOD(l, 1, 20, 20); /* HSDIVBYPASS */
287 if (hw->has_refsel)
288 l = FLD_MOD(l, 3, 22, 21); /* REFSEL = sysclk */
289 l = FLD_MOD(l, 0, 23, 23); /* M6_CLOCK_EN */
290 l = FLD_MOD(l, 0, 25, 25); /* M7_CLOCK_EN */
291 writel_relaxed(l, base + PLL_CONFIGURATION2);
292
293 writel_relaxed(1, base + PLL_GO); /* PLL_GO */
294
295 if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
296 DSSERR("DSS DPLL GO bit not going down.\n");
297 r = -EIO;
298 goto err;
299 }
300
301 if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
302 DSSERR("cannot lock DSS DPLL\n");
303 r = -EIO;
304 goto err;
305 }
306
307 l = readl_relaxed(base + PLL_CONFIGURATION2);
308 l = FLD_MOD(l, 1, 14, 14); /* PHY_CLKINEN */
309 l = FLD_MOD(l, cinfo->mX[0] ? 1 : 0, 16, 16); /* M4_CLOCK_EN */
310 l = FLD_MOD(l, cinfo->mX[1] ? 1 : 0, 18, 18); /* M5_CLOCK_EN */
311 l = FLD_MOD(l, 0, 20, 20); /* HSDIVBYPASS */
312 l = FLD_MOD(l, cinfo->mX[2] ? 1 : 0, 23, 23); /* M6_CLOCK_EN */
313 l = FLD_MOD(l, cinfo->mX[3] ? 1 : 0, 25, 25); /* M7_CLOCK_EN */
314 writel_relaxed(l, base + PLL_CONFIGURATION2);
315
316 r = dss_wait_hsdiv_ack(pll,
317 (cinfo->mX[0] ? BIT(7) : 0) |
318 (cinfo->mX[1] ? BIT(8) : 0) |
319 (cinfo->mX[2] ? BIT(10) : 0) |
320 (cinfo->mX[3] ? BIT(11) : 0));
321 if (r) {
322 DSSERR("failed to enable HSDIV clocks\n");
323 goto err;
324 }
325
326err:
327 return r;
328}
329
330int dss_pll_write_config_type_b(struct dss_pll *pll,
331 const struct dss_pll_clock_info *cinfo)
332{
333 const struct dss_pll_hw *hw = pll->hw;
334 void __iomem *base = pll->base;
335 u32 l;
336
337 l = 0;
338 l = FLD_MOD(l, cinfo->m, 20, 9); /* PLL_REGM */
339 l = FLD_MOD(l, cinfo->n - 1, 8, 1); /* PLL_REGN */
340 writel_relaxed(l, base + PLL_CONFIGURATION1);
341
342 l = readl_relaxed(base + PLL_CONFIGURATION2);
343 l = FLD_MOD(l, 0x0, 12, 12); /* PLL_HIGHFREQ divide by 2 */
344 l = FLD_MOD(l, 0x1, 13, 13); /* PLL_REFEN */
345 l = FLD_MOD(l, 0x0, 14, 14); /* PHY_CLKINEN */
346 if (hw->has_refsel)
347 l = FLD_MOD(l, 0x3, 22, 21); /* REFSEL = SYSCLK */
348
349 /* PLL_SELFREQDCO */
350 if (cinfo->clkdco > hw->clkdco_low)
351 l = FLD_MOD(l, 0x4, 3, 1);
352 else
353 l = FLD_MOD(l, 0x2, 3, 1);
354 writel_relaxed(l, base + PLL_CONFIGURATION2);
355
356 l = readl_relaxed(base + PLL_CONFIGURATION3);
357 l = FLD_MOD(l, cinfo->sd, 17, 10); /* PLL_REGSD */
358 writel_relaxed(l, base + PLL_CONFIGURATION3);
359
360 l = readl_relaxed(base + PLL_CONFIGURATION4);
361 l = FLD_MOD(l, cinfo->mX[0], 24, 18); /* PLL_REGM2 */
362 l = FLD_MOD(l, cinfo->mf, 17, 0); /* PLL_REGM_F */
363 writel_relaxed(l, base + PLL_CONFIGURATION4);
364
365 writel_relaxed(1, base + PLL_GO); /* PLL_GO */
366
367 if (wait_for_bit_change(base + PLL_GO, 0, 0) != 0) {
368 DSSERR("DSS DPLL GO bit not going down.\n");
369 return -EIO;
370 }
371
372 if (wait_for_bit_change(base + PLL_STATUS, 1, 1) != 1) {
373 DSSERR("cannot lock DSS DPLL\n");
374 return -ETIMEDOUT;
375 }
376
377 return 0;
378}
diff --git a/drivers/video/fbdev/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c
index 4c9c46d4ea60..d9b10f27be20 100644
--- a/drivers/video/fbdev/omap2/dss/sdi.c
+++ b/drivers/video/fbdev/omap2/dss/sdi.c
@@ -425,7 +425,7 @@ err_datapairs:
425 return r; 425 return r;
426} 426}
427 427
428void __exit sdi_uninit_port(void) 428void __exit sdi_uninit_port(struct device_node *port)
429{ 429{
430 if (!sdi.port_initialized) 430 if (!sdi.port_initialized)
431 return; 431 return;
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index 210f3a02121a..b2ae9254fd75 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -26,6 +26,8 @@
26#include <linux/module.h> 26#include <linux/module.h>
27#include <linux/platform_data/simplefb.h> 27#include <linux/platform_data/simplefb.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/clk-provider.h>
30#include <linux/of_platform.h>
29 31
30static struct fb_fix_screeninfo simplefb_fix = { 32static struct fb_fix_screeninfo simplefb_fix = {
31 .id = "simple", 33 .id = "simple",
@@ -41,6 +43,8 @@ static struct fb_var_screeninfo simplefb_var = {
41 .vmode = FB_VMODE_NONINTERLACED, 43 .vmode = FB_VMODE_NONINTERLACED,
42}; 44};
43 45
46#define PSEUDO_PALETTE_SIZE 16
47
44static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 48static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
45 u_int transp, struct fb_info *info) 49 u_int transp, struct fb_info *info)
46{ 50{
@@ -50,7 +54,7 @@ static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
50 u32 cb = blue >> (16 - info->var.blue.length); 54 u32 cb = blue >> (16 - info->var.blue.length);
51 u32 value; 55 u32 value;
52 56
53 if (regno >= 16) 57 if (regno >= PSEUDO_PALETTE_SIZE)
54 return -EINVAL; 58 return -EINVAL;
55 59
56 value = (cr << info->var.red.offset) | 60 value = (cr << info->var.red.offset) |
@@ -163,11 +167,113 @@ static int simplefb_parse_pd(struct platform_device *pdev,
163 return 0; 167 return 0;
164} 168}
165 169
170struct simplefb_par {
171 u32 palette[PSEUDO_PALETTE_SIZE];
172#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
173 int clk_count;
174 struct clk **clks;
175#endif
176};
177
178#if defined CONFIG_OF && defined CONFIG_COMMON_CLK
179/*
180 * Clock handling code.
181 *
182 * Here we handle the clocks property of our "simple-framebuffer" dt node.
183 * This is necessary so that we can make sure that any clocks needed by
184 * the display engine that the bootloader set up for us (and for which it
185 * provided a simplefb dt node), stay up, for the life of the simplefb
186 * driver.
187 *
188 * When the driver unloads, we cleanly disable, and then release the clocks.
189 *
190 * We only complain about errors here, no action is taken as the most likely
191 * error can only happen due to a mismatch between the bootloader which set
192 * up simplefb, and the clock definitions in the device tree. Chances are
193 * that there are no adverse effects, and if there are, a clean teardown of
194 * the fb probe will not help us much either. So just complain and carry on,
195 * and hope that the user actually gets a working fb at the end of things.
196 */
197static int simplefb_clocks_init(struct simplefb_par *par,
198 struct platform_device *pdev)
199{
200 struct device_node *np = pdev->dev.of_node;
201 struct clk *clock;
202 int i, ret;
203
204 if (dev_get_platdata(&pdev->dev) || !np)
205 return 0;
206
207 par->clk_count = of_clk_get_parent_count(np);
208 if (par->clk_count <= 0)
209 return 0;
210
211 par->clks = kcalloc(par->clk_count, sizeof(struct clk *), GFP_KERNEL);
212 if (!par->clks)
213 return -ENOMEM;
214
215 for (i = 0; i < par->clk_count; i++) {
216 clock = of_clk_get(np, i);
217 if (IS_ERR(clock)) {
218 if (PTR_ERR(clock) == -EPROBE_DEFER) {
219 while (--i >= 0) {
220 if (par->clks[i])
221 clk_put(par->clks[i]);
222 }
223 kfree(par->clks);
224 return -EPROBE_DEFER;
225 }
226 dev_err(&pdev->dev, "%s: clock %d not found: %ld\n",
227 __func__, i, PTR_ERR(clock));
228 continue;
229 }
230 par->clks[i] = clock;
231 }
232
233 for (i = 0; i < par->clk_count; i++) {
234 if (par->clks[i]) {
235 ret = clk_prepare_enable(par->clks[i]);
236 if (ret) {
237 dev_err(&pdev->dev,
238 "%s: failed to enable clock %d: %d\n",
239 __func__, i, ret);
240 clk_put(par->clks[i]);
241 par->clks[i] = NULL;
242 }
243 }
244 }
245
246 return 0;
247}
248
249static void simplefb_clocks_destroy(struct simplefb_par *par)
250{
251 int i;
252
253 if (!par->clks)
254 return;
255
256 for (i = 0; i < par->clk_count; i++) {
257 if (par->clks[i]) {
258 clk_disable_unprepare(par->clks[i]);
259 clk_put(par->clks[i]);
260 }
261 }
262
263 kfree(par->clks);
264}
265#else
266static int simplefb_clocks_init(struct simplefb_par *par,
267 struct platform_device *pdev) { return 0; }
268static void simplefb_clocks_destroy(struct simplefb_par *par) { }
269#endif
270
166static int simplefb_probe(struct platform_device *pdev) 271static int simplefb_probe(struct platform_device *pdev)
167{ 272{
168 int ret; 273 int ret;
169 struct simplefb_params params; 274 struct simplefb_params params;
170 struct fb_info *info; 275 struct fb_info *info;
276 struct simplefb_par *par;
171 struct resource *mem; 277 struct resource *mem;
172 278
173 if (fb_get_options("simplefb", NULL)) 279 if (fb_get_options("simplefb", NULL))
@@ -188,11 +294,13 @@ static int simplefb_probe(struct platform_device *pdev)
188 return -EINVAL; 294 return -EINVAL;
189 } 295 }
190 296
191 info = framebuffer_alloc(sizeof(u32) * 16, &pdev->dev); 297 info = framebuffer_alloc(sizeof(struct simplefb_par), &pdev->dev);
192 if (!info) 298 if (!info)
193 return -ENOMEM; 299 return -ENOMEM;
194 platform_set_drvdata(pdev, info); 300 platform_set_drvdata(pdev, info);
195 301
302 par = info->par;
303
196 info->fix = simplefb_fix; 304 info->fix = simplefb_fix;
197 info->fix.smem_start = mem->start; 305 info->fix.smem_start = mem->start;
198 info->fix.smem_len = resource_size(mem); 306 info->fix.smem_len = resource_size(mem);
@@ -211,8 +319,8 @@ static int simplefb_probe(struct platform_device *pdev)
211 319
212 info->apertures = alloc_apertures(1); 320 info->apertures = alloc_apertures(1);
213 if (!info->apertures) { 321 if (!info->apertures) {
214 framebuffer_release(info); 322 ret = -ENOMEM;
215 return -ENOMEM; 323 goto error_fb_release;
216 } 324 }
217 info->apertures->ranges[0].base = info->fix.smem_start; 325 info->apertures->ranges[0].base = info->fix.smem_start;
218 info->apertures->ranges[0].size = info->fix.smem_len; 326 info->apertures->ranges[0].size = info->fix.smem_len;
@@ -222,10 +330,14 @@ static int simplefb_probe(struct platform_device *pdev)
222 info->screen_base = ioremap_wc(info->fix.smem_start, 330 info->screen_base = ioremap_wc(info->fix.smem_start,
223 info->fix.smem_len); 331 info->fix.smem_len);
224 if (!info->screen_base) { 332 if (!info->screen_base) {
225 framebuffer_release(info); 333 ret = -ENOMEM;
226 return -ENODEV; 334 goto error_fb_release;
227 } 335 }
228 info->pseudo_palette = (void *)(info + 1); 336 info->pseudo_palette = par->palette;
337
338 ret = simplefb_clocks_init(par, pdev);
339 if (ret < 0)
340 goto error_unmap;
229 341
230 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n", 342 dev_info(&pdev->dev, "framebuffer at 0x%lx, 0x%x bytes, mapped to 0x%p\n",
231 info->fix.smem_start, info->fix.smem_len, 343 info->fix.smem_start, info->fix.smem_len,
@@ -238,21 +350,29 @@ static int simplefb_probe(struct platform_device *pdev)
238 ret = register_framebuffer(info); 350 ret = register_framebuffer(info);
239 if (ret < 0) { 351 if (ret < 0) {
240 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret); 352 dev_err(&pdev->dev, "Unable to register simplefb: %d\n", ret);
241 iounmap(info->screen_base); 353 goto error_clocks;
242 framebuffer_release(info);
243 return ret;
244 } 354 }
245 355
246 dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node); 356 dev_info(&pdev->dev, "fb%d: simplefb registered!\n", info->node);
247 357
248 return 0; 358 return 0;
359
360error_clocks:
361 simplefb_clocks_destroy(par);
362error_unmap:
363 iounmap(info->screen_base);
364error_fb_release:
365 framebuffer_release(info);
366 return ret;
249} 367}
250 368
251static int simplefb_remove(struct platform_device *pdev) 369static int simplefb_remove(struct platform_device *pdev)
252{ 370{
253 struct fb_info *info = platform_get_drvdata(pdev); 371 struct fb_info *info = platform_get_drvdata(pdev);
372 struct simplefb_par *par = info->par;
254 373
255 unregister_framebuffer(info); 374 unregister_framebuffer(info);
375 simplefb_clocks_destroy(par);
256 framebuffer_release(info); 376 framebuffer_release(info);
257 377
258 return 0; 378 return 0;
@@ -273,7 +393,27 @@ static struct platform_driver simplefb_driver = {
273 .probe = simplefb_probe, 393 .probe = simplefb_probe,
274 .remove = simplefb_remove, 394 .remove = simplefb_remove,
275}; 395};
276module_platform_driver(simplefb_driver); 396
397static int __init simplefb_init(void)
398{
399 int ret;
400 struct device_node *np;
401
402 ret = platform_driver_register(&simplefb_driver);
403 if (ret)
404 return ret;
405
406 if (IS_ENABLED(CONFIG_OF) && of_chosen) {
407 for_each_child_of_node(of_chosen, np) {
408 if (of_device_is_compatible(np, "simple-framebuffer"))
409 of_platform_device_create(np, NULL, NULL);
410 }
411 }
412
413 return 0;
414}
415
416fs_initcall(simplefb_init);
277 417
278MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>"); 418MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>");
279MODULE_DESCRIPTION("Simple framebuffer driver"); 419MODULE_DESCRIPTION("Simple framebuffer driver");
diff --git a/include/linux/of.h b/include/linux/of.h
index 6545e7aec7bb..f83ca9dddcba 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -105,8 +105,6 @@ static inline struct device_node *of_node_get(struct device_node *node)
105static inline void of_node_put(struct device_node *node) { } 105static inline void of_node_put(struct device_node *node) { }
106#endif /* !CONFIG_OF_DYNAMIC */ 106#endif /* !CONFIG_OF_DYNAMIC */
107 107
108#ifdef CONFIG_OF
109
110/* Pointer for first entry in chain of all nodes. */ 108/* Pointer for first entry in chain of all nodes. */
111extern struct device_node *of_allnodes; 109extern struct device_node *of_allnodes;
112extern struct device_node *of_chosen; 110extern struct device_node *of_chosen;
@@ -114,6 +112,7 @@ extern struct device_node *of_aliases;
114extern struct device_node *of_stdout; 112extern struct device_node *of_stdout;
115extern raw_spinlock_t devtree_lock; 113extern raw_spinlock_t devtree_lock;
116 114
115#ifdef CONFIG_OF
117static inline bool of_have_populated_dt(void) 116static inline bool of_have_populated_dt(void)
118{ 117{
119 return of_allnodes != NULL; 118 return of_allnodes != NULL;
diff --git a/include/sound/omap-hdmi-audio.h b/include/sound/omap-hdmi-audio.h
new file mode 100644
index 000000000000..afdb416898e0
--- /dev/null
+++ b/include/sound/omap-hdmi-audio.h
@@ -0,0 +1,43 @@
1/*
2 * hdmi-audio.c -- OMAP4+ DSS HDMI audio support library
3 *
4 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Jyri Sarha <jsarha@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 */
18
19#include <video/omapdss.h>
20
21#ifndef __OMAP_HDMI_AUDIO_H__
22#define __OMAP_HDMI_AUDIO_H__
23
24struct omap_hdmi_audio_ops {
25 int (*audio_startup)(struct device *dev,
26 void (*abort_cb)(struct device *dev));
27 int (*audio_shutdown)(struct device *dev);
28 int (*audio_start)(struct device *dev);
29 void (*audio_stop)(struct device *dev);
30 int (*audio_config)(struct device *dev,
31 struct omap_dss_audio *dss_audio);
32};
33
34/* HDMI audio initalization data */
35struct omap_hdmi_audio_pdata {
36 struct device *dev;
37 enum omapdss_version dss_version;
38 phys_addr_t audio_dma_addr;
39
40 const struct omap_hdmi_audio_ops *ops;
41};
42
43#endif /* __OMAP_HDMI_AUDIO_H__ */
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 069dfca9549a..6a84498ea513 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -166,13 +166,6 @@ enum omap_dss_display_state {
166 OMAP_DSS_DISPLAY_ACTIVE, 166 OMAP_DSS_DISPLAY_ACTIVE,
167}; 167};
168 168
169enum omap_dss_audio_state {
170 OMAP_DSS_AUDIO_DISABLED = 0,
171 OMAP_DSS_AUDIO_ENABLED,
172 OMAP_DSS_AUDIO_CONFIGURED,
173 OMAP_DSS_AUDIO_PLAYING,
174};
175
176struct omap_dss_audio { 169struct omap_dss_audio {
177 struct snd_aes_iec958 *iec; 170 struct snd_aes_iec958 *iec;
178 struct snd_cea_861_aud_if *cea; 171 struct snd_cea_861_aud_if *cea;
@@ -635,19 +628,6 @@ struct omapdss_hdmi_ops {
635 int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); 628 int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
636 int (*set_infoframe)(struct omap_dss_device *dssdev, 629 int (*set_infoframe)(struct omap_dss_device *dssdev,
637 const struct hdmi_avi_infoframe *avi); 630 const struct hdmi_avi_infoframe *avi);
638
639 /*
640 * Note: These functions might sleep. Do not call while
641 * holding a spinlock/readlock.
642 */
643 int (*audio_enable)(struct omap_dss_device *dssdev);
644 void (*audio_disable)(struct omap_dss_device *dssdev);
645 bool (*audio_supported)(struct omap_dss_device *dssdev);
646 int (*audio_config)(struct omap_dss_device *dssdev,
647 struct omap_dss_audio *audio);
648 /* Note: These functions may not sleep */
649 int (*audio_start)(struct omap_dss_device *dssdev);
650 void (*audio_stop)(struct omap_dss_device *dssdev);
651}; 631};
652 632
653struct omapdss_dsi_ops { 633struct omapdss_dsi_ops {
@@ -783,8 +763,6 @@ struct omap_dss_device {
783 763
784 enum omap_dss_display_state state; 764 enum omap_dss_display_state state;
785 765
786 enum omap_dss_audio_state audio_state;
787
788 /* OMAP DSS output specific fields */ 766 /* OMAP DSS output specific fields */
789 767
790 struct list_head list; 768 struct list_head list;
@@ -795,6 +773,9 @@ struct omap_dss_device {
795 /* output instance */ 773 /* output instance */
796 enum omap_dss_output_id id; 774 enum omap_dss_output_id id;
797 775
776 /* the port number in the DT node */
777 int port_num;
778
798 /* dynamic fields */ 779 /* dynamic fields */
799 struct omap_overlay_manager *manager; 780 struct omap_overlay_manager *manager;
800 781
@@ -858,24 +839,6 @@ struct omap_dss_driver {
858 int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode); 839 int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
859 int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev, 840 int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
860 const struct hdmi_avi_infoframe *avi); 841 const struct hdmi_avi_infoframe *avi);
861
862 /*
863 * For display drivers that support audio. This encompasses
864 * HDMI and DisplayPort at the moment.
865 */
866 /*
867 * Note: These functions might sleep. Do not call while
868 * holding a spinlock/readlock.
869 */
870 int (*audio_enable)(struct omap_dss_device *dssdev);
871 void (*audio_disable)(struct omap_dss_device *dssdev);
872 bool (*audio_supported)(struct omap_dss_device *dssdev);
873 int (*audio_config)(struct omap_dss_device *dssdev,
874 struct omap_dss_audio *audio);
875 /* Note: These functions may not sleep */
876 int (*audio_start)(struct omap_dss_device *dssdev);
877 void (*audio_stop)(struct omap_dss_device *dssdev);
878
879}; 842};
880 843
881enum omapdss_version omapdss_get_version(void); 844enum omapdss_version omapdss_get_version(void);
@@ -918,7 +881,7 @@ int omapdss_register_output(struct omap_dss_device *output);
918void omapdss_unregister_output(struct omap_dss_device *output); 881void omapdss_unregister_output(struct omap_dss_device *output);
919struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id); 882struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id);
920struct omap_dss_device *omap_dss_find_output(const char *name); 883struct omap_dss_device *omap_dss_find_output(const char *name);
921struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node); 884struct omap_dss_device *omap_dss_find_output_by_port_node(struct device_node *port);
922int omapdss_output_set_device(struct omap_dss_device *out, 885int omapdss_output_set_device(struct omap_dss_device *out,
923 struct omap_dss_device *dssdev); 886 struct omap_dss_device *dssdev);
924int omapdss_output_unset_device(struct omap_dss_device *out); 887int omapdss_output_unset_device(struct omap_dss_device *out);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index d44463a7b0fa..3dfcadf00e55 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -12,8 +12,20 @@ config SND_OMAP_SOC_MCBSP
12config SND_OMAP_SOC_MCPDM 12config SND_OMAP_SOC_MCPDM
13 tristate 13 tristate
14 14
15config SND_OMAP_SOC_HDMI 15config SND_OMAP_SOC_HDMI_AUDIO
16 tristate 16 tristate "HDMI audio support for OMAP4+ based SoCs"
17 depends on SND_OMAP_SOC
18 help
19 For HDMI audio to work OMAPDSS HDMI support should be
20 enabled.
21 The hdmi audio driver implements cpu-dai component using the
22 callbacks provided by OMAPDSS and registers the component
23 under DSS HDMI device. Omap-pcm is registered for platform
24 component also under DSS HDMI device. Dummy codec is used as
25 as codec component. The hdmi audio driver implements also
26 the card and registers it under its own platform device.
27 The device for the dirver is registered by OMAPDSS hdmi
28 driver.
17 29
18config SND_OMAP_SOC_N810 30config SND_OMAP_SOC_N810
19 tristate "SoC Audio support for Nokia N810" 31 tristate "SoC Audio support for Nokia N810"
@@ -100,16 +112,6 @@ config SND_OMAP_SOC_OMAP_ABE_TWL6040
100 - PandaBoard (4430) 112 - PandaBoard (4430)
101 - PandaBoardES (4460) 113 - PandaBoardES (4460)
102 114
103config SND_OMAP_SOC_OMAP_HDMI
104 tristate "SoC Audio support for Texas Instruments OMAP HDMI"
105 depends on SND_OMAP_SOC && OMAP4_DSS_HDMI && OMAP2_DSS
106 select SND_OMAP_SOC_HDMI
107 select SND_SOC_HDMI_CODEC
108 select OMAP4_DSS_HDMI_AUDIO
109 help
110 Say Y if you want to add support for SoC HDMI audio on Texas Instruments
111 OMAP4 chips
112
113config SND_OMAP_SOC_OMAP3_PANDORA 115config SND_OMAP_SOC_OMAP3_PANDORA
114 tristate "SoC Audio support for OMAP3 Pandora" 116 tristate "SoC Audio support for OMAP3 Pandora"
115 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA 117 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index a725905b2c68..db36fbd5d1a0 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -3,13 +3,13 @@ snd-soc-omap-objs := omap-pcm.o
3snd-soc-omap-dmic-objs := omap-dmic.o 3snd-soc-omap-dmic-objs := omap-dmic.o
4snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o 4snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
5snd-soc-omap-mcpdm-objs := omap-mcpdm.o 5snd-soc-omap-mcpdm-objs := omap-mcpdm.o
6snd-soc-omap-hdmi-objs := omap-hdmi.o 6snd-soc-omap-hdmi-audio-objs := omap-hdmi-audio.o
7 7
8obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o 8obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
9obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o 9obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
10obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o 10obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
11obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o 11obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
12obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o 12obj-$(CONFIG_SND_OMAP_SOC_HDMI_AUDIO) += snd-soc-omap-hdmi-audio.o
13 13
14# OMAP Machine Support 14# OMAP Machine Support
15snd-soc-n810-objs := n810.o 15snd-soc-n810-objs := n810.o
@@ -20,7 +20,6 @@ snd-soc-am3517evm-objs := am3517evm.o
20snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o 20snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
21snd-soc-omap-twl4030-objs := omap-twl4030.o 21snd-soc-omap-twl4030-objs := omap-twl4030.o
22snd-soc-omap3pandora-objs := omap3pandora.o 22snd-soc-omap3pandora-objs := omap3pandora.o
23snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o
24 23
25obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 24obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
26obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o 25obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o
@@ -30,4 +29,3 @@ obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
30obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o 29obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
31obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o 30obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o
32obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 31obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
33obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c
new file mode 100644
index 000000000000..3f9ac7dbdc80
--- /dev/null
+++ b/sound/soc/omap/omap-hdmi-audio.c
@@ -0,0 +1,407 @@
1/*
2 * omap-hdmi-audio.c -- OMAP4+ DSS HDMI audio support library
3 *
4 * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
5 *
6 * Author: Jyri Sarha <jsarha@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/err.h>
22#include <linux/string.h>
23#include <linux/platform_device.h>
24#include <sound/soc.h>
25#include <sound/pcm_params.h>
26#include <sound/dmaengine_pcm.h>
27#include <uapi/sound/asound.h>
28#include <sound/asoundef.h>
29#include <sound/omap-pcm.h>
30#include <sound/omap-hdmi-audio.h>
31#include <video/omapdss.h>
32
33#define DRV_NAME "omap-hdmi-audio"
34
35struct hdmi_audio_data {
36 struct snd_soc_card *card;
37
38 const struct omap_hdmi_audio_ops *ops;
39 struct device *dssdev;
40 struct snd_dmaengine_dai_dma_data dma_data;
41 struct omap_dss_audio dss_audio;
42 struct snd_aes_iec958 iec;
43 struct snd_cea_861_aud_if cea;
44
45 struct mutex current_stream_lock;
46 struct snd_pcm_substream *current_stream;
47};
48
49static
50struct hdmi_audio_data *card_drvdata_substream(struct snd_pcm_substream *ss)
51{
52 struct snd_soc_pcm_runtime *rtd = ss->private_data;
53
54 return snd_soc_card_get_drvdata(rtd->card);
55}
56
57static void hdmi_dai_abort(struct device *dev)
58{
59 struct hdmi_audio_data *ad = dev_get_drvdata(dev);
60
61 mutex_lock(&ad->current_stream_lock);
62 if (ad->current_stream && ad->current_stream->runtime &&
63 snd_pcm_running(ad->current_stream)) {
64 dev_err(dev, "HDMI display disabled, aborting playback\n");
65 snd_pcm_stream_lock_irq(ad->current_stream);
66 snd_pcm_stop(ad->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
67 snd_pcm_stream_unlock_irq(ad->current_stream);
68 }
69 mutex_unlock(&ad->current_stream_lock);
70}
71
72static int hdmi_dai_startup(struct snd_pcm_substream *substream,
73 struct snd_soc_dai *dai)
74{
75 struct hdmi_audio_data *ad = card_drvdata_substream(substream);
76 int ret;
77 /*
78 * Make sure that the period bytes are multiple of the DMA packet size.
79 * Largest packet size we use is 32 32-bit words = 128 bytes
80 */
81 ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
82 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
83 if (ret < 0) {
84 dev_err(dai->dev, "could not apply constraint\n");
85 return ret;
86 }
87
88 snd_soc_dai_set_dma_data(dai, substream, &ad->dma_data);
89
90 mutex_lock(&ad->current_stream_lock);
91 ad->current_stream = substream;
92 mutex_unlock(&ad->current_stream_lock);
93
94 ret = ad->ops->audio_startup(ad->dssdev, hdmi_dai_abort);
95
96 if (ret) {
97 mutex_lock(&ad->current_stream_lock);
98 ad->current_stream = NULL;
99 mutex_unlock(&ad->current_stream_lock);
100 }
101
102 return ret;
103}
104
105static int hdmi_dai_hw_params(struct snd_pcm_substream *substream,
106 struct snd_pcm_hw_params *params,
107 struct snd_soc_dai *dai)
108{
109 struct hdmi_audio_data *ad = card_drvdata_substream(substream);
110 struct snd_aes_iec958 *iec = &ad->iec;
111 struct snd_cea_861_aud_if *cea = &ad->cea;
112
113 WARN_ON(ad->current_stream != substream);
114
115 switch (params_format(params)) {
116 case SNDRV_PCM_FORMAT_S16_LE:
117 ad->dma_data.maxburst = 16;
118 break;
119 case SNDRV_PCM_FORMAT_S24_LE:
120 ad->dma_data.maxburst = 32;
121 break;
122 default:
123 dev_err(dai->dev, "format not supported!\n");
124 return -EINVAL;
125 }
126
127 ad->dss_audio.iec = iec;
128 ad->dss_audio.cea = cea;
129 /*
130 * fill the IEC-60958 channel status word
131 */
132 /* initialize the word bytes */
133 memset(iec->status, 0, sizeof(iec->status));
134
135 /* specify IEC-60958-3 (commercial use) */
136 iec->status[0] &= ~IEC958_AES0_PROFESSIONAL;
137
138 /* specify that the audio is LPCM*/
139 iec->status[0] &= ~IEC958_AES0_NONAUDIO;
140
141 iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
142
143 iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE;
144
145 iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID;
146
147 iec->status[1] = IEC958_AES1_CON_GENERAL;
148
149 iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC;
150
151 iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC;
152
153 switch (params_rate(params)) {
154 case 32000:
155 iec->status[3] |= IEC958_AES3_CON_FS_32000;
156 break;
157 case 44100:
158 iec->status[3] |= IEC958_AES3_CON_FS_44100;
159 break;
160 case 48000:
161 iec->status[3] |= IEC958_AES3_CON_FS_48000;
162 break;
163 case 88200:
164 iec->status[3] |= IEC958_AES3_CON_FS_88200;
165 break;
166 case 96000:
167 iec->status[3] |= IEC958_AES3_CON_FS_96000;
168 break;
169 case 176400:
170 iec->status[3] |= IEC958_AES3_CON_FS_176400;
171 break;
172 case 192000:
173 iec->status[3] |= IEC958_AES3_CON_FS_192000;
174 break;
175 default:
176 dev_err(dai->dev, "rate not supported!\n");
177 return -EINVAL;
178 }
179
180 /* specify the clock accuracy */
181 iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM;
182
183 /*
184 * specify the word length. The same word length value can mean
185 * two different lengths. Hence, we need to specify the maximum
186 * word length as well.
187 */
188 switch (params_format(params)) {
189 case SNDRV_PCM_FORMAT_S16_LE:
190 iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16;
191 iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24;
192 break;
193 case SNDRV_PCM_FORMAT_S24_LE:
194 iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20;
195 iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24;
196 break;
197 default:
198 dev_err(dai->dev, "format not supported!\n");
199 return -EINVAL;
200 }
201
202 /*
203 * Fill the CEA-861 audio infoframe (see spec for details)
204 */
205
206 cea->db1_ct_cc = (params_channels(params) - 1)
207 & CEA861_AUDIO_INFOFRAME_DB1CC;
208 cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM;
209
210 cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM;
211 cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM;
212
213 cea->db3 = 0; /* not used, all zeros */
214
215 /*
216 * The OMAP HDMI IP requires to use the 8-channel channel code when
217 * transmitting more than two channels.
218 */
219 if (params_channels(params) == 2)
220 cea->db4_ca = 0x0;
221 else
222 cea->db4_ca = 0x13;
223
224 cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
225 /* the expression is trivial but makes clear what we are doing */
226 cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV);
227
228 return ad->ops->audio_config(ad->dssdev, &ad->dss_audio);
229}
230
231static int hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
232 struct snd_soc_dai *dai)
233{
234 struct hdmi_audio_data *ad = card_drvdata_substream(substream);
235 int err = 0;
236
237 WARN_ON(ad->current_stream != substream);
238
239 switch (cmd) {
240 case SNDRV_PCM_TRIGGER_START:
241 case SNDRV_PCM_TRIGGER_RESUME:
242 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
243 err = ad->ops->audio_start(ad->dssdev);
244 break;
245 case SNDRV_PCM_TRIGGER_STOP:
246 case SNDRV_PCM_TRIGGER_SUSPEND:
247 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
248 ad->ops->audio_stop(ad->dssdev);
249 break;
250 default:
251 err = -EINVAL;
252 }
253 return err;
254}
255
256static void hdmi_dai_shutdown(struct snd_pcm_substream *substream,
257 struct snd_soc_dai *dai)
258{
259 struct hdmi_audio_data *ad = card_drvdata_substream(substream);
260
261 WARN_ON(ad->current_stream != substream);
262
263 ad->ops->audio_shutdown(ad->dssdev);
264
265 mutex_lock(&ad->current_stream_lock);
266 ad->current_stream = NULL;
267 mutex_unlock(&ad->current_stream_lock);
268}
269
270static const struct snd_soc_dai_ops hdmi_dai_ops = {
271 .startup = hdmi_dai_startup,
272 .hw_params = hdmi_dai_hw_params,
273 .trigger = hdmi_dai_trigger,
274 .shutdown = hdmi_dai_shutdown,
275};
276
277static const struct snd_soc_component_driver omap_hdmi_component = {
278 .name = "omapdss_hdmi",
279};
280
281static struct snd_soc_dai_driver omap5_hdmi_dai = {
282 .name = "omap5-hdmi-dai",
283 .playback = {
284 .channels_min = 2,
285 .channels_max = 8,
286 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
287 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
288 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
289 SNDRV_PCM_RATE_192000),
290 .formats = SNDRV_PCM_FMTBIT_S16_LE,
291 },
292 .ops = &hdmi_dai_ops,
293};
294
295static struct snd_soc_dai_driver omap4_hdmi_dai = {
296 .name = "omap4-hdmi-dai",
297 .playback = {
298 .channels_min = 2,
299 .channels_max = 8,
300 .rates = (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
301 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
302 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
303 SNDRV_PCM_RATE_192000),
304 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
305 },
306 .ops = &hdmi_dai_ops,
307};
308
309static int omap_hdmi_audio_probe(struct platform_device *pdev)
310{
311 struct omap_hdmi_audio_pdata *ha = pdev->dev.platform_data;
312 struct device *dev = &pdev->dev;
313 struct hdmi_audio_data *ad;
314 struct snd_soc_dai_driver *dai_drv;
315 struct snd_soc_card *card;
316 int ret;
317
318 if (!ha) {
319 dev_err(dev, "No platform data\n");
320 return -EINVAL;
321 }
322
323 ad = devm_kzalloc(dev, sizeof(*ad), GFP_KERNEL);
324 if (!ad)
325 return -ENOMEM;
326 ad->dssdev = ha->dev;
327 ad->ops = ha->ops;
328 ad->dma_data.addr = ha->audio_dma_addr;
329 ad->dma_data.filter_data = "audio_tx";
330 ad->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
331 mutex_init(&ad->current_stream_lock);
332
333 switch (ha->dss_version) {
334 case OMAPDSS_VER_OMAP4430_ES1:
335 case OMAPDSS_VER_OMAP4430_ES2:
336 case OMAPDSS_VER_OMAP4:
337 dai_drv = &omap4_hdmi_dai;
338 break;
339 case OMAPDSS_VER_OMAP5:
340 dai_drv = &omap5_hdmi_dai;
341 break;
342 default:
343 return -EINVAL;
344 }
345 ret = snd_soc_register_component(ad->dssdev, &omap_hdmi_component,
346 dai_drv, 1);
347 if (ret)
348 return ret;
349
350 ret = omap_pcm_platform_register(ad->dssdev);
351 if (ret)
352 return ret;
353
354 card = devm_kzalloc(dev, sizeof(*card), GFP_KERNEL);
355 card->name = devm_kasprintf(dev, GFP_KERNEL,
356 "HDMI %s", dev_name(ad->dssdev));
357 card->owner = THIS_MODULE;
358 card->dai_link =
359 devm_kzalloc(dev, sizeof(*(card->dai_link)), GFP_KERNEL);
360 card->dai_link->name = card->name;
361 card->dai_link->stream_name = card->name;
362 card->dai_link->cpu_dai_name = dev_name(ad->dssdev);
363 card->dai_link->platform_name = dev_name(ad->dssdev);
364 card->dai_link->codec_name = "snd-soc-dummy";
365 card->dai_link->codec_dai_name = "snd-soc-dummy-dai";
366 card->num_links = 1;
367 card->dev = dev;
368
369 ret = snd_soc_register_card(card);
370 if (ret) {
371 dev_err(dev, "snd_soc_register_card failed (%d)\n", ret);
372 snd_soc_unregister_component(ad->dssdev);
373 return ret;
374 }
375
376 ad->card = card;
377 snd_soc_card_set_drvdata(card, ad);
378
379 dev_set_drvdata(dev, ad);
380
381 return 0;
382}
383
384static int omap_hdmi_audio_remove(struct platform_device *pdev)
385{
386 struct hdmi_audio_data *ad = platform_get_drvdata(pdev);
387
388 snd_soc_unregister_card(ad->card);
389 snd_soc_unregister_component(ad->dssdev);
390 return 0;
391}
392
393static struct platform_driver hdmi_audio_driver = {
394 .driver = {
395 .name = DRV_NAME,
396 .owner = THIS_MODULE,
397 },
398 .probe = omap_hdmi_audio_probe,
399 .remove = omap_hdmi_audio_remove,
400};
401
402module_platform_driver(hdmi_audio_driver);
403
404MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
405MODULE_DESCRIPTION("OMAP HDMI Audio Driver");
406MODULE_LICENSE("GPL");
407MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi-card.c b/sound/soc/omap/omap-hdmi-card.c
deleted file mode 100644
index f649fe84b629..000000000000
--- a/sound/soc/omap/omap-hdmi-card.c
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * omap-hdmi-card.c
3 *
4 * OMAP ALSA SoC machine driver for TI OMAP HDMI
5 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Author: Ricardo Neri <ricardo.neri@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <asm/mach-types.h>
28#include <video/omapdss.h>
29
30#define DRV_NAME "omap-hdmi-audio"
31
32static struct snd_soc_dai_link omap_hdmi_dai = {
33 .name = "HDMI",
34 .stream_name = "HDMI",
35 .cpu_dai_name = "omap-hdmi-audio-dai",
36 .platform_name = "omap-hdmi-audio-dai",
37 .codec_name = "hdmi-audio-codec",
38 .codec_dai_name = "hdmi-hifi",
39};
40
41static struct snd_soc_card snd_soc_omap_hdmi = {
42 .name = "OMAPHDMI",
43 .owner = THIS_MODULE,
44 .dai_link = &omap_hdmi_dai,
45 .num_links = 1,
46};
47
48static int omap_hdmi_probe(struct platform_device *pdev)
49{
50 struct snd_soc_card *card = &snd_soc_omap_hdmi;
51 int ret;
52
53 card->dev = &pdev->dev;
54
55 ret = snd_soc_register_card(card);
56 if (ret) {
57 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
58 card->dev = NULL;
59 return ret;
60 }
61 return 0;
62}
63
64static int omap_hdmi_remove(struct platform_device *pdev)
65{
66 struct snd_soc_card *card = platform_get_drvdata(pdev);
67
68 snd_soc_unregister_card(card);
69 card->dev = NULL;
70 return 0;
71}
72
73static struct platform_driver omap_hdmi_driver = {
74 .driver = {
75 .name = DRV_NAME,
76 .owner = THIS_MODULE,
77 },
78 .probe = omap_hdmi_probe,
79 .remove = omap_hdmi_remove,
80};
81
82module_platform_driver(omap_hdmi_driver);
83
84MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
85MODULE_DESCRIPTION("OMAP HDMI machine ASoC driver");
86MODULE_LICENSE("GPL");
87MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
deleted file mode 100644
index eb9c39299f81..000000000000
--- a/sound/soc/omap/omap-hdmi.c
+++ /dev/null
@@ -1,364 +0,0 @@
1/*
2 * omap-hdmi.c
3 *
4 * OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
7 * Ricardo Neri <ricardo.neri@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#include <linux/init.h>
26#include <linux/module.h>
27#include <linux/device.h>
28#include <sound/core.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/initval.h>
32#include <sound/soc.h>
33#include <sound/asound.h>
34#include <sound/asoundef.h>
35#include <sound/dmaengine_pcm.h>
36#include <video/omapdss.h>
37#include <sound/omap-pcm.h>
38
39#include "omap-hdmi.h"
40
41#define DRV_NAME "omap-hdmi-audio-dai"
42
43struct hdmi_priv {
44 struct snd_dmaengine_dai_dma_data dma_data;
45 unsigned int dma_req;
46 struct omap_dss_audio dss_audio;
47 struct snd_aes_iec958 iec;
48 struct snd_cea_861_aud_if cea;
49 struct omap_dss_device *dssdev;
50};
51
52static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
53 struct snd_soc_dai *dai)
54{
55 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
56 int err;
57 /*
58 * Make sure that the period bytes are multiple of the DMA packet size.
59 * Largest packet size we use is 32 32-bit words = 128 bytes
60 */
61 err = snd_pcm_hw_constraint_step(substream->runtime, 0,
62 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
63 if (err < 0) {
64 dev_err(dai->dev, "could not apply constraint\n");
65 return err;
66 }
67
68 if (!priv->dssdev->driver->audio_supported(priv->dssdev)) {
69 dev_err(dai->dev, "audio not supported\n");
70 return -ENODEV;
71 }
72
73 snd_soc_dai_set_dma_data(dai, substream, &priv->dma_data);
74
75 return 0;
76}
77
78static int omap_hdmi_dai_prepare(struct snd_pcm_substream *substream,
79 struct snd_soc_dai *dai)
80{
81 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
82
83 return priv->dssdev->driver->audio_enable(priv->dssdev);
84}
85
86static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
87 struct snd_pcm_hw_params *params,
88 struct snd_soc_dai *dai)
89{
90 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
91 struct snd_aes_iec958 *iec = &priv->iec;
92 struct snd_cea_861_aud_if *cea = &priv->cea;
93 int err = 0;
94
95 switch (params_format(params)) {
96 case SNDRV_PCM_FORMAT_S16_LE:
97 priv->dma_data.maxburst = 16;
98 break;
99 case SNDRV_PCM_FORMAT_S24_LE:
100 priv->dma_data.maxburst = 32;
101 break;
102 default:
103 dev_err(dai->dev, "format not supported!\n");
104 return -EINVAL;
105 }
106
107 /*
108 * fill the IEC-60958 channel status word
109 */
110 /* initialize the word bytes */
111 memset(iec->status, 0, sizeof(iec->status));
112
113 /* specify IEC-60958-3 (commercial use) */
114 iec->status[0] &= ~IEC958_AES0_PROFESSIONAL;
115
116 /* specify that the audio is LPCM*/
117 iec->status[0] &= ~IEC958_AES0_NONAUDIO;
118
119 iec->status[0] |= IEC958_AES0_CON_NOT_COPYRIGHT;
120
121 iec->status[0] |= IEC958_AES0_CON_EMPHASIS_NONE;
122
123 iec->status[0] |= IEC958_AES1_PRO_MODE_NOTID;
124
125 iec->status[1] = IEC958_AES1_CON_GENERAL;
126
127 iec->status[2] |= IEC958_AES2_CON_SOURCE_UNSPEC;
128
129 iec->status[2] |= IEC958_AES2_CON_CHANNEL_UNSPEC;
130
131 switch (params_rate(params)) {
132 case 32000:
133 iec->status[3] |= IEC958_AES3_CON_FS_32000;
134 break;
135 case 44100:
136 iec->status[3] |= IEC958_AES3_CON_FS_44100;
137 break;
138 case 48000:
139 iec->status[3] |= IEC958_AES3_CON_FS_48000;
140 break;
141 case 88200:
142 iec->status[3] |= IEC958_AES3_CON_FS_88200;
143 break;
144 case 96000:
145 iec->status[3] |= IEC958_AES3_CON_FS_96000;
146 break;
147 case 176400:
148 iec->status[3] |= IEC958_AES3_CON_FS_176400;
149 break;
150 case 192000:
151 iec->status[3] |= IEC958_AES3_CON_FS_192000;
152 break;
153 default:
154 dev_err(dai->dev, "rate not supported!\n");
155 return -EINVAL;
156 }
157
158 /* specify the clock accuracy */
159 iec->status[3] |= IEC958_AES3_CON_CLOCK_1000PPM;
160
161 /*
162 * specify the word length. The same word length value can mean
163 * two different lengths. Hence, we need to specify the maximum
164 * word length as well.
165 */
166 switch (params_format(params)) {
167 case SNDRV_PCM_FORMAT_S16_LE:
168 iec->status[4] |= IEC958_AES4_CON_WORDLEN_20_16;
169 iec->status[4] &= ~IEC958_AES4_CON_MAX_WORDLEN_24;
170 break;
171 case SNDRV_PCM_FORMAT_S24_LE:
172 iec->status[4] |= IEC958_AES4_CON_WORDLEN_24_20;
173 iec->status[4] |= IEC958_AES4_CON_MAX_WORDLEN_24;
174 break;
175 default:
176 dev_err(dai->dev, "format not supported!\n");
177 return -EINVAL;
178 }
179
180 /*
181 * Fill the CEA-861 audio infoframe (see spec for details)
182 */
183
184 cea->db1_ct_cc = (params_channels(params) - 1)
185 & CEA861_AUDIO_INFOFRAME_DB1CC;
186 cea->db1_ct_cc |= CEA861_AUDIO_INFOFRAME_DB1CT_FROM_STREAM;
187
188 cea->db2_sf_ss = CEA861_AUDIO_INFOFRAME_DB2SF_FROM_STREAM;
189 cea->db2_sf_ss |= CEA861_AUDIO_INFOFRAME_DB2SS_FROM_STREAM;
190
191 cea->db3 = 0; /* not used, all zeros */
192
193 /*
194 * The OMAP HDMI IP requires to use the 8-channel channel code when
195 * transmitting more than two channels.
196 */
197 if (params_channels(params) == 2)
198 cea->db4_ca = 0x0;
199 else
200 cea->db4_ca = 0x13;
201
202 cea->db5_dminh_lsv = CEA861_AUDIO_INFOFRAME_DB5_DM_INH_PROHIBITED;
203 /* the expression is trivial but makes clear what we are doing */
204 cea->db5_dminh_lsv |= (0 & CEA861_AUDIO_INFOFRAME_DB5_LSV);
205
206 priv->dss_audio.iec = iec;
207 priv->dss_audio.cea = cea;
208
209 err = priv->dssdev->driver->audio_config(priv->dssdev,
210 &priv->dss_audio);
211
212 return err;
213}
214
215static int omap_hdmi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
216 struct snd_soc_dai *dai)
217{
218 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
219 int err = 0;
220
221 switch (cmd) {
222 case SNDRV_PCM_TRIGGER_START:
223 case SNDRV_PCM_TRIGGER_RESUME:
224 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
225 err = priv->dssdev->driver->audio_start(priv->dssdev);
226 break;
227 case SNDRV_PCM_TRIGGER_STOP:
228 case SNDRV_PCM_TRIGGER_SUSPEND:
229 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
230 priv->dssdev->driver->audio_stop(priv->dssdev);
231 break;
232 default:
233 err = -EINVAL;
234 }
235 return err;
236}
237
238static void omap_hdmi_dai_shutdown(struct snd_pcm_substream *substream,
239 struct snd_soc_dai *dai)
240{
241 struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai);
242
243 priv->dssdev->driver->audio_disable(priv->dssdev);
244}
245
246static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
247 .startup = omap_hdmi_dai_startup,
248 .hw_params = omap_hdmi_dai_hw_params,
249 .prepare = omap_hdmi_dai_prepare,
250 .trigger = omap_hdmi_dai_trigger,
251 .shutdown = omap_hdmi_dai_shutdown,
252};
253
254static struct snd_soc_dai_driver omap_hdmi_dai = {
255 .playback = {
256 .channels_min = 2,
257 .channels_max = 8,
258 .rates = OMAP_HDMI_RATES,
259 .formats = OMAP_HDMI_FORMATS,
260 },
261 .ops = &omap_hdmi_dai_ops,
262};
263
264static const struct snd_soc_component_driver omap_hdmi_component = {
265 .name = DRV_NAME,
266};
267
268static int omap_hdmi_probe(struct platform_device *pdev)
269{
270 int ret;
271 struct resource *hdmi_rsrc;
272 struct hdmi_priv *hdmi_data;
273 bool hdmi_dev_found = false;
274
275 hdmi_data = devm_kzalloc(&pdev->dev, sizeof(*hdmi_data), GFP_KERNEL);
276 if (hdmi_data == NULL) {
277 dev_err(&pdev->dev, "Cannot allocate memory for HDMI data\n");
278 return -ENOMEM;
279 }
280
281 hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
282 if (!hdmi_rsrc) {
283 dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n");
284 return -ENODEV;
285 }
286
287 hdmi_data->dma_data.addr = hdmi_rsrc->start + OMAP_HDMI_AUDIO_DMA_PORT;
288
289 hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_DMA, 0);
290 if (!hdmi_rsrc) {
291 dev_err(&pdev->dev, "Cannot obtain IORESOURCE_DMA HDMI\n");
292 return -ENODEV;
293 }
294
295 hdmi_data->dma_req = hdmi_rsrc->start;
296 hdmi_data->dma_data.filter_data = &hdmi_data->dma_req;
297 hdmi_data->dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
298
299 /*
300 * TODO: We assume that there is only one DSS HDMI device. Future
301 * OMAP implementations may support more than one HDMI devices and
302 * we should provided separate audio support for all of them.
303 */
304 /* Find an HDMI device. */
305 for_each_dss_dev(hdmi_data->dssdev) {
306 omap_dss_get_device(hdmi_data->dssdev);
307
308 if (!hdmi_data->dssdev->driver) {
309 omap_dss_put_device(hdmi_data->dssdev);
310 continue;
311 }
312
313 if (hdmi_data->dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
314 hdmi_dev_found = true;
315 break;
316 }
317 }
318
319 if (!hdmi_dev_found) {
320 dev_err(&pdev->dev, "no driver for HDMI display found\n");
321 return -ENODEV;
322 }
323
324 dev_set_drvdata(&pdev->dev, hdmi_data);
325 ret = snd_soc_register_component(&pdev->dev, &omap_hdmi_component,
326 &omap_hdmi_dai, 1);
327
328 if (ret)
329 return ret;
330
331 return omap_pcm_platform_register(&pdev->dev);
332}
333
334static int omap_hdmi_remove(struct platform_device *pdev)
335{
336 struct hdmi_priv *hdmi_data = dev_get_drvdata(&pdev->dev);
337
338 snd_soc_unregister_component(&pdev->dev);
339
340 if (hdmi_data == NULL) {
341 dev_err(&pdev->dev, "cannot obtain HDMi data\n");
342 return -ENODEV;
343 }
344
345 omap_dss_put_device(hdmi_data->dssdev);
346 return 0;
347}
348
349static struct platform_driver hdmi_dai_driver = {
350 .driver = {
351 .name = DRV_NAME,
352 .owner = THIS_MODULE,
353 },
354 .probe = omap_hdmi_probe,
355 .remove = omap_hdmi_remove,
356};
357
358module_platform_driver(hdmi_dai_driver);
359
360MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
361MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
362MODULE_DESCRIPTION("OMAP HDMI SoC Interface");
363MODULE_LICENSE("GPL");
364MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/omap/omap-hdmi.h b/sound/soc/omap/omap-hdmi.h
deleted file mode 100644
index 6ad2bf4f2697..000000000000
--- a/sound/soc/omap/omap-hdmi.h
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * omap-hdmi.h
3 *
4 * Definitions for OMAP ALSA SoC DAI driver for HDMI audio on OMAP4 processors.
5 * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
6 * Authors: Jorge Candelaria <jorge.candelaria@ti.com>
7 * Ricardo Neri <ricardo.neri@ti.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __OMAP_HDMI_H__
26#define __OMAP_HDMI_H__
27
28#define OMAP_HDMI_AUDIO_DMA_PORT 0x8c
29
30#define OMAP_HDMI_RATES (SNDRV_PCM_RATE_32000 | \
31 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
32 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
33 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
34
35#define OMAP_HDMI_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
36 SNDRV_PCM_FMTBIT_S24_LE)
37
38#endif