diff options
Diffstat (limited to 'drivers/video')
29 files changed, 1776 insertions, 1559 deletions
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 | ||
3627 | module_init(fb_console_init); | 3627 | fs_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 | ||
173 | static 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 | |||
192 | static 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 | |||
202 | static 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 | |||
224 | static 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 | |||
234 | static 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 | |||
245 | static 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 | |||
265 | static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode) | 173 | static 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 | ||
308 | static int hdmic_probe_pdata(struct platform_device *pdev) | 209 | static 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 | ||
196 | static 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 | |||
204 | static 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 | |||
212 | static 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 | |||
220 | static 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 | |||
228 | static 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 | |||
236 | static 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 | |||
245 | static int tpd_set_infoframe(struct omap_dss_device *dssdev, | 196 | static 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 | ||
287 | static int tpd_probe_pdata(struct platform_device *pdev) | 231 | static 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 | ||
77 | config OMAP4_DSS_HDMI_AUDIO | ||
78 | bool | ||
79 | |||
80 | config OMAP5_DSS_HDMI | 77 | config 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 | ||
89 | config OMAP5_DSS_HDMI_AUDIO | ||
90 | depends on OMAP5_DSS_HDMI | ||
91 | bool | ||
92 | |||
93 | config OMAP2_DSS_SDI | 86 | config 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 | |||
2 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o | 2 | obj-$(CONFIG_OMAP2_DSS) += omapdss.o |
3 | # Core DSS files | 3 | # Core DSS files |
4 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ | 4 | omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ |
5 | output.o dss-of.o | 5 | output.o dss-of.o pll.o |
6 | # DSS compat layer files | 6 | # DSS compat layer files |
7 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ | 7 | omapdss-y += manager.o manager-sysfs.o overlay.o overlay-sysfs.o apply.o \ |
8 | dispc-compat.o display-sysfs.o | 8 | dispc-compat.o display-sysfs.o |
diff --git a/drivers/video/fbdev/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c index 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 | ||
3029 | unsigned long dispc_fclk_rate(void) | 3029 | unsigned 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 | ||
3054 | unsigned long dispc_mgr_lclk_rate(enum omap_channel channel) | 3054 | unsigned 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 | ||
40 | static struct { | 41 | #define HSDIV_DISPC 0 |
42 | |||
43 | struct 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 | |||
60 | static 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 */ | ||
66 | static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev) | ||
67 | { | ||
68 | return dev_get_drvdata(&pdev->dev); | ||
69 | } | ||
56 | 70 | ||
57 | static struct platform_device *dpi_get_dsidev(enum omap_channel channel) | 71 | static 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 | ||
116 | struct dpi_clk_calc_ctx { | 130 | struct 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 | ||
157 | static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, | 171 | static 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 | ||
178 | static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, | 192 | static 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 | ||
193 | static bool dpi_calc_dss_cb(unsigned long fck, void *data) | 208 | static 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 | ||
203 | static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) | 218 | static 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 | ||
255 | static int dpi_set_dsi_clk(enum omap_channel channel, | 270 | static 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 | ||
283 | static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, | 298 | static 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 | ||
307 | static int dpi_set_mode(struct omap_overlay_manager *mgr) | 322 | static 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 | ||
338 | static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr) | 355 | static 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 | ||
352 | static int dpi_display_enable(struct omap_dss_device *dssdev) | 372 | static 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 | ||
411 | err_mgr_enable: | 428 | err_mgr_enable: |
412 | err_set_mode: | 429 | err_set_mode: |
413 | if (dpi.dsidev) | 430 | if (dpi->pll) |
414 | dsi_pll_uninit(dpi.dsidev, true); | 431 | dss_pll_disable(dpi->pll); |
415 | err_dsi_pll_init: | 432 | err_dsi_pll_init: |
416 | if (dpi.dsidev) | ||
417 | dsi_runtime_put(dpi.dsidev); | ||
418 | err_get_dsi: | ||
419 | err_src_sel: | 433 | err_src_sel: |
420 | dispc_runtime_put(); | 434 | dispc_runtime_put(); |
421 | err_get_dispc: | 435 | err_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); |
424 | err_reg_enable: | 438 | err_reg_enable: |
425 | err_no_out_mgr: | 439 | err_no_out_mgr: |
426 | err_no_reg: | 440 | err_no_reg: |
427 | mutex_unlock(&dpi.lock); | 441 | mutex_unlock(&dpi->lock); |
428 | return r; | 442 | return r; |
429 | } | 443 | } |
430 | 444 | ||
431 | static void dpi_display_disable(struct omap_dss_device *dssdev) | 445 | static 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 | ||
453 | static void dpi_set_timings(struct omap_dss_device *dssdev, | 467 | static 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 | ||
465 | static void dpi_get_timings(struct omap_dss_device *dssdev, | 481 | static 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 | ||
475 | static int dpi_check_timings(struct omap_dss_device *dssdev, | 493 | static 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 | ||
515 | static void dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) | 534 | static 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 | ||
524 | static int dpi_verify_dsi_pll(struct platform_device *dsidev) | 545 | static 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 | ||
546 | static int dpi_init_regulator(void) | 560 | static 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 | ||
568 | static void dpi_init_pll(void) | 582 | static 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 | */ |
593 | static enum omap_channel dpi_get_channel(void) | 607 | static 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) | |||
618 | static int dpi_connect(struct omap_dss_device *dssdev, | 632 | static 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 | ||
677 | static void dpi_init_output(struct platform_device *pdev) | 692 | static 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 | ||
692 | static void __exit dpi_uninit_output(struct platform_device *pdev) | 708 | static 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 | |||
716 | static 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 | |||
752 | static 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 | ||
699 | static int omap_dpi_probe(struct platform_device *pdev) | 760 | static 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 | ||
737 | int __init dpi_init_port(struct platform_device *pdev, struct device_node *port) | 806 | int __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 | ||
773 | void __exit dpi_uninit_port(void) | 848 | void __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 | ||
220 | static int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); | 220 | static 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 | ||
272 | struct dsi_clk_calc_ctx { | 276 | struct 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 | ||
295 | struct dsi_lp_clock_info { | ||
296 | unsigned long lp_clk; | ||
297 | u16 lp_clk_div; | ||
298 | }; | ||
299 | |||
290 | struct dsi_data { | 300 | struct 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 | ||
415 | struct platform_device *dsi_get_dsidev_from_id(int module) | 420 | static 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 | ||
1137 | int dsi_runtime_get(struct platform_device *dsidev) | 1142 | static 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 | ||
1149 | void dsi_runtime_put(struct platform_device *dsidev) | 1154 | static 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 */ | ||
1192 | static 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 | |||
1208 | static void _dsi_print_reset_status(struct platform_device *dsidev) | 1196 | static 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 | ||
1259 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev) | 1247 | static 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 | ||
1266 | static unsigned long dsi_get_pll_hsdiv_dsi_rate(struct platform_device *dsidev) | 1254 | static 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 | ||
1273 | static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev) | 1261 | static 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 | ||
1280 | static unsigned long dsi_fclk_rate(struct platform_device *dsidev) | 1268 | static 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 | ||
1296 | static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo, | 1284 | static 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 | ||
1394 | unsigned 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 | |||
1400 | bool 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 | |||
1424 | bool 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); | 1385 | static 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 */ | ||
1464 | static 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 | |||
1507 | static 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 | ||
1517 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 1395 | static 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, ®n_start, ®n_end); | ||
1568 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM, ®m_start, ®m_end); | ||
1569 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DISPC, ®m_dispc_start, | ||
1570 | ®m_dispc_end); | ||
1571 | dss_feat_get_reg_field(FEAT_REG_DSIPLL_REGM_DSI, ®m_dsi_start, | ||
1572 | ®m_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"); | ||
1650 | err: | ||
1651 | return r; | ||
1652 | } | ||
1653 | |||
1654 | int 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 | } |
1722 | err0: | 1450 | err0: |
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 | ||
1728 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes) | 1456 | static 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 | ||
1473 | static 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 | |||
1746 | static void dsi_dump_dsidev_clocks(struct platform_device *dsidev, | 1481 | static 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, | |||
4441 | static int dsi_configure_dsi_clocks(struct platform_device *dsidev) | 4177 | static 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: | |||
4510 | err2: | 4240 | err2: |
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); |
4512 | err1: | 4242 | err1: |
4513 | dsi_pll_uninit(dsidev, true); | 4243 | dss_pll_disable(&dsi->pll); |
4514 | err0: | 4244 | err0: |
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 | ||
4566 | err_init_dsi: | 4294 | err_init_dsi: |
4567 | dsi_enable_pll_clock(dsidev, 0); | ||
4568 | dsi_runtime_put(dsidev); | 4295 | dsi_runtime_put(dsidev); |
4569 | err_get_dsi: | 4296 | err_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 | ||
4716 | static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, | 4442 | static 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 | ||
4728 | static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint, | 4454 | static 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 | ||
5002 | static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, | 4729 | static 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 | ||
5025 | static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint, | 4752 | static 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 | ||
5237 | void 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 | |||
5245 | void 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 | |||
5253 | static 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 | ||
5267 | static int dsi_get_clocks(struct platform_device *dsidev) | 4965 | static 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 | ||
5146 | static 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 | |||
5152 | static 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 | |||
5177 | static 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 | |||
5202 | static 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 | |||
5227 | static 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 */ |
5457 | static int omap_dsihw_probe(struct platform_device *dsidev) | 5276 | static 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 | |||
23 | struct device_node * | 25 | struct device_node * |
24 | omapdss_of_get_next_port(const struct device_node *parent, | 26 | omapdss_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 | } |
85 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); | 87 | EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); |
86 | 88 | ||
87 | static struct device_node * | 89 | struct device_node *dss_of_port_get_parent_device(struct device_node *port) |
88 | omapdss_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 | ||
113 | u32 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", ®); | ||
119 | if (r) | ||
120 | reg = 0; | ||
121 | |||
122 | return reg; | ||
123 | } | ||
124 | |||
125 | static 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 | |||
114 | struct device_node * | 138 | struct device_node * |
115 | omapdss_of_get_first_endpoint(const struct device_node *parent) | 139 | omapdss_of_get_first_endpoint(const struct device_node *parent) |
116 | { | 140 | { |
@@ -133,27 +157,25 @@ struct omap_dss_device * | |||
133 | omapdss_of_find_source_for_first_ep(struct device_node *node) | 157 | omapdss_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 | } |
159 | EXPORT_SYMBOL_GPL(omapdss_of_find_source_for_first_ep); | 181 | EXPORT_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 | ||
76 | static struct { | 78 | static struct { |
@@ -294,7 +296,6 @@ static void dss_dump_regs(struct seq_file *s) | |||
294 | 296 | ||
295 | static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) | 297 | static 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) | |||
327 | void dss_select_dsi_clk_source(int dsi_module, | 324 | void 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, | |||
360 | void dss_select_lcd_clk_source(enum omap_channel channel, | 352 | void 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 | ||
567 | static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) | 554 | static 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 | ||
575 | static int dss_dpi_select_source_omap4(enum omap_channel channel) | 562 | static 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 | ||
595 | static int dss_dpi_select_source_omap5(enum omap_channel channel) | 582 | static 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 | ||
621 | int dss_dpi_select_source(enum omap_channel channel) | 608 | int 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 | ||
626 | static int dss_get_clocks(void) | 613 | static 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 | |||
680 | static enum omap_display_type omap2plus_ports[] = { | ||
681 | OMAP_DISPLAY_TYPE_DPI, | ||
682 | }; | ||
683 | |||
684 | static enum omap_display_type omap34xx_ports[] = { | ||
685 | OMAP_DISPLAY_TYPE_DPI, | ||
686 | OMAP_DISPLAY_TYPE_SDI, | ||
687 | }; | ||
688 | |||
692 | static const struct dss_features omap24xx_dss_feats __initconst = { | 689 | static 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 | ||
703 | static const struct dss_features omap34xx_dss_feats __initconst = { | 702 | static 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 | ||
710 | static const struct dss_features omap3630_dss_feats __initconst = { | 711 | static 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 | ||
717 | static const struct dss_features omap44xx_dss_feats __initconst = { | 720 | static 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 | ||
724 | static const struct dss_features omap54xx_dss_feats __initconst = { | 729 | static 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 | ||
731 | static const struct dss_features am43xx_dss_feats __initconst = { | 738 | static 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 | ||
738 | static int __init dss_init_features(struct platform_device *pdev) | 747 | static 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", ®); | 817 | r = of_property_read_u32(port, "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 | ||
823 | static void __exit dss_uninit_ports(void) | 841 | static 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", ®); | ||
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 | ||
911 | static int __exit omap_dsshw_remove(struct platform_device *pdev) | 960 | static 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 | ||
103 | struct dispc_clock_info { | 103 | struct 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 | */ | ||
111 | struct 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 | |||
125 | struct 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 | |||
132 | struct 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 | ||
113 | struct dsi_clock_info { | 151 | struct 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 | |||
166 | struct 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 | ||
134 | struct dss_lcd_mgr_config { | 176 | struct dss_lcd_mgr_config { |
@@ -209,12 +251,16 @@ int dss_init_platform_driver(void) __init; | |||
209 | void dss_uninit_platform_driver(void); | 251 | void dss_uninit_platform_driver(void); |
210 | 252 | ||
211 | unsigned long dss_get_dispc_clk_rate(void); | 253 | unsigned long dss_get_dispc_clk_rate(void); |
212 | int dss_dpi_select_source(enum omap_channel channel); | 254 | int dss_dpi_select_source(int port, enum omap_channel channel); |
213 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); | 255 | void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select); |
214 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); | 256 | enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void); |
215 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); | 257 | const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src); |
216 | void dss_dump_clocks(struct seq_file *s); | 258 | void dss_dump_clocks(struct seq_file *s); |
217 | 259 | ||
260 | /* dss-of */ | ||
261 | struct device_node *dss_of_port_get_parent_device(struct device_node *port); | ||
262 | u32 dss_of_port_get_port_number(struct device_node *port); | ||
263 | |||
218 | #if defined(CONFIG_OMAP2_DSS_DEBUGFS) | 264 | #if defined(CONFIG_OMAP2_DSS_DEBUGFS) |
219 | void dss_debug_dump_clocks(struct seq_file *s); | 265 | void 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, | |||
244 | int sdi_init_platform_driver(void) __init; | 290 | int sdi_init_platform_driver(void) __init; |
245 | void sdi_uninit_platform_driver(void) __exit; | 291 | void sdi_uninit_platform_driver(void) __exit; |
246 | 292 | ||
293 | #ifdef CONFIG_OMAP2_DSS_SDI | ||
247 | int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; | 294 | int sdi_init_port(struct platform_device *pdev, struct device_node *port) __init; |
248 | void sdi_uninit_port(void) __exit; | 295 | void sdi_uninit_port(struct device_node *port) __exit; |
296 | #else | ||
297 | static inline int __init sdi_init_port(struct platform_device *pdev, | ||
298 | struct device_node *port) | ||
299 | { | ||
300 | return 0; | ||
301 | } | ||
302 | static inline void __exit sdi_uninit_port(struct device_node *port) | ||
303 | { | ||
304 | } | ||
305 | #endif | ||
249 | 306 | ||
250 | /* DSI */ | 307 | /* DSI */ |
251 | 308 | ||
252 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, | ||
253 | unsigned long pll, void *data); | ||
254 | typedef 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 | ||
259 | struct dentry; | 311 | struct dentry; |
@@ -262,104 +314,36 @@ struct file_operations; | |||
262 | int dsi_init_platform_driver(void) __init; | 314 | int dsi_init_platform_driver(void) __init; |
263 | void dsi_uninit_platform_driver(void) __exit; | 315 | void dsi_uninit_platform_driver(void) __exit; |
264 | 316 | ||
265 | int dsi_runtime_get(struct platform_device *dsidev); | ||
266 | void dsi_runtime_put(struct platform_device *dsidev); | ||
267 | |||
268 | void dsi_dump_clocks(struct seq_file *s); | 317 | void dsi_dump_clocks(struct seq_file *s); |
269 | 318 | ||
270 | void dsi_irq_handler(void); | 319 | void dsi_irq_handler(void); |
271 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | 320 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); |
272 | 321 | ||
273 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev); | ||
274 | |||
275 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
276 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data); | ||
277 | bool 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 | |||
281 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | ||
282 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | ||
283 | struct dsi_clock_info *cinfo); | ||
284 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, | ||
285 | bool enable_hsdiv); | ||
286 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); | ||
287 | void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev); | ||
288 | void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev); | ||
289 | struct platform_device *dsi_get_dsidev_from_id(int module); | ||
290 | #else | 322 | #else |
291 | static inline int dsi_runtime_get(struct platform_device *dsidev) | ||
292 | { | ||
293 | return 0; | ||
294 | } | ||
295 | static inline void dsi_runtime_put(struct platform_device *dsidev) | ||
296 | { | ||
297 | } | ||
298 | static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) | 323 | static 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 | } |
303 | static 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 | } | ||
308 | static 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 | } | ||
314 | static 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 | } | ||
320 | static inline void dsi_pll_uninit(struct platform_device *dsidev, | ||
321 | bool disconnect_lanes) | ||
322 | { | ||
323 | } | ||
324 | static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev) | ||
325 | { | ||
326 | } | ||
327 | static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev) | ||
328 | { | ||
329 | } | ||
330 | static inline struct platform_device *dsi_get_dsidev_from_id(int module) | ||
331 | { | ||
332 | return NULL; | ||
333 | } | ||
334 | |||
335 | static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) | ||
336 | { | ||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static 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 | |||
347 | static 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 */ |
358 | int dpi_init_platform_driver(void) __init; | 331 | int dpi_init_platform_driver(void) __init; |
359 | void dpi_uninit_platform_driver(void) __exit; | 332 | void dpi_uninit_platform_driver(void) __exit; |
360 | 333 | ||
334 | #ifdef CONFIG_OMAP2_DSS_DPI | ||
361 | int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; | 335 | int dpi_init_port(struct platform_device *pdev, struct device_node *port) __init; |
362 | void dpi_uninit_port(void) __exit; | 336 | void dpi_uninit_port(struct device_node *port) __exit; |
337 | #else | ||
338 | static inline int __init dpi_init_port(struct platform_device *pdev, | ||
339 | struct device_node *port) | ||
340 | { | ||
341 | return 0; | ||
342 | } | ||
343 | static inline void __exit dpi_uninit_port(struct device_node *port) | ||
344 | { | ||
345 | } | ||
346 | #endif | ||
363 | 347 | ||
364 | /* DISPC */ | 348 | /* DISPC */ |
365 | int dispc_init_platform_driver(void) __init; | 349 | int 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 */ | ||
426 | typedef bool (*dss_pll_calc_func)(int n, int m, unsigned long fint, | ||
427 | unsigned long clkdco, void *data); | ||
428 | typedef bool (*dss_hsdiv_calc_func)(int m_dispc, unsigned long dispc, | ||
429 | void *data); | ||
430 | |||
431 | int dss_pll_register(struct dss_pll *pll); | ||
432 | void dss_pll_unregister(struct dss_pll *pll); | ||
433 | struct dss_pll *dss_pll_find(const char *name); | ||
434 | int dss_pll_enable(struct dss_pll *pll); | ||
435 | void dss_pll_disable(struct dss_pll *pll); | ||
436 | int dss_pll_set_config(struct dss_pll *pll, | ||
437 | const struct dss_pll_clock_info *cinfo); | ||
438 | |||
439 | bool 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); | ||
442 | bool 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); | ||
445 | int dss_pll_write_config_type_a(struct dss_pll *pll, | ||
446 | const struct dss_pll_clock_info *cinfo); | ||
447 | int 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 | ||
81 | static const struct dss_reg_field omap3_dss_reg_fields[] = { | 77 | static 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 | ||
96 | static const struct dss_reg_field am43xx_dss_reg_fields[] = { | 88 | static 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 | ||
122 | static const struct dss_reg_field omap5_dss_reg_fields[] = { | 110 | static 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 | ||
137 | static const enum omap_display_type omap2_dss_supported_displays[] = { | 121 | static const enum omap_display_type omap2_dss_supported_displays[] = { |
@@ -437,12 +421,6 @@ static const char * const omap5_dss_clk_source_names[] = { | |||
437 | static const struct dss_param_range omap2_dss_param_range[] = { | 421 | static 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[] = { | |||
454 | static const struct dss_param_range omap3_dss_param_range[] = { | 432 | static 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[] = { | |||
475 | static const struct dss_param_range omap4_dss_param_range[] = { | 448 | static 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[] = { | |||
489 | static const struct dss_param_range omap5_dss_param_range[] = { | 457 | static 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 | ||
86 | enum dss_range_param { | 79 | enum 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 | ||
104 | enum 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 | |||
111 | enum hdmi_packing_mode { | 104 | enum 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 | ||
161 | enum hdmi_core_audio_layout { | 154 | enum 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 | ||
166 | enum hdmi_core_cts_mode { | 160 | enum 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 */ | ||
195 | struct 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 | |||
205 | struct hdmi_audio_format { | 188 | struct 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 | ||
250 | struct hdmi_wp_data { | 233 | struct hdmi_wp_data { |
251 | void __iomem *base; | 234 | void __iomem *base; |
235 | phys_addr_t phys_base; | ||
252 | }; | 236 | }; |
253 | 237 | ||
254 | struct hdmi_pll_data { | 238 | struct 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 | ||
260 | struct hdmi_phy_data { | 246 | struct hdmi_phy_data { |
@@ -316,16 +302,19 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data *wp, | |||
316 | void hdmi_wp_init_vid_fmt_timings(struct hdmi_video_format *video_fmt, | 302 | void 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); |
318 | int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); | 304 | int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp); |
305 | phys_addr_t hdmi_wp_get_audio_dma_addr(struct hdmi_wp_data *wp); | ||
319 | 306 | ||
320 | /* HDMI PLL funcs */ | 307 | /* HDMI PLL funcs */ |
321 | int hdmi_pll_enable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); | ||
322 | void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp); | ||
323 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); | 308 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s); |
324 | void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy); | 309 | void hdmi_pll_compute(struct hdmi_pll_data *pll, |
325 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll); | 310 | unsigned long target_tmds, struct dss_pll_clock_info *pi); |
311 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll, | ||
312 | struct hdmi_wp_data *wp); | ||
313 | void hdmi_pll_uninit(struct hdmi_pll_data *hpll); | ||
326 | 314 | ||
327 | /* HDMI PHY funcs */ | 315 | /* HDMI PHY funcs */ |
328 | int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg); | 316 | int hdmi_phy_configure(struct hdmi_phy_data *phy, unsigned long hfbitclk, |
317 | unsigned long lfbitclk); | ||
329 | void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); | 318 | void hdmi_phy_dump(struct hdmi_phy_data *phy, struct seq_file *s); |
330 | int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); | 319 | int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy); |
331 | int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes); | 320 | int 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); | |||
334 | int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep, | 323 | int 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 */ |
338 | int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); | 327 | int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts); |
339 | int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); | 328 | int hdmi_wp_audio_enable(struct hdmi_wp_data *wp, bool enable); |
340 | int hdmi_wp_audio_core_req_enable(struct hdmi_wp_data *wp, bool enable); | 329 | int 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); |
343 | void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, | 332 | void hdmi_wp_audio_config_dma(struct hdmi_wp_data *wp, |
344 | struct hdmi_audio_dma *aud_dma); | 333 | struct hdmi_audio_dma *aud_dma); |
345 | static inline bool hdmi_mode_has_audio(int mode) | 334 | static 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 */ | ||
340 | struct 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 | ||
41 | static struct { | 43 | static 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 | ||
60 | static int hdmi_runtime_get(void) | 45 | static 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 | ||
164 | err_runtime_get: | 149 | err_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 | ||
178 | static int hdmi_power_on_full(struct omap_dss_device *dssdev) | 163 | static 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: | |||
244 | err_phy_cfg: | 232 | err_phy_cfg: |
245 | hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); | 233 | hdmi_wp_set_phy_pwr(&hdmi.wp, HDMI_PHYPWRCMD_OFF); |
246 | err_phy_pwr: | 234 | err_phy_pwr: |
247 | hdmi_pll_disable(&hdmi.pll, &hdmi.wp); | 235 | err_pll_cfg: |
236 | dss_pll_disable(&hdmi.pll.pll); | ||
248 | err_pll_enable: | 237 | err_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 | ||
407 | static 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 | |||
422 | static int hdmi_connect(struct omap_dss_device *dssdev, | 403 | static 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) | ||
488 | static 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 | |||
506 | err: | ||
507 | mutex_unlock(&hdmi.lock); | ||
508 | return r; | ||
509 | } | ||
510 | |||
511 | static void hdmi_audio_disable(struct omap_dss_device *dssdev) | ||
512 | { | ||
513 | hdmi_wp_audio_enable(&hdmi.wp, false); | ||
514 | } | ||
515 | |||
516 | static int hdmi_audio_start(struct omap_dss_device *dssdev) | ||
517 | { | ||
518 | return hdmi4_audio_start(&hdmi.core, &hdmi.wp); | ||
519 | } | ||
520 | |||
521 | static void hdmi_audio_stop(struct omap_dss_device *dssdev) | ||
522 | { | ||
523 | hdmi4_audio_stop(&hdmi.core, &hdmi.wp); | ||
524 | } | ||
525 | |||
526 | static 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 | |||
538 | static 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 | |||
558 | err: | ||
559 | mutex_unlock(&hdmi.lock); | ||
560 | return r; | ||
561 | } | ||
562 | #else | ||
563 | static int hdmi_audio_enable(struct omap_dss_device *dssdev) | ||
564 | { | ||
565 | return -EPERM; | ||
566 | } | ||
567 | |||
568 | static void hdmi_audio_disable(struct omap_dss_device *dssdev) | ||
569 | { | ||
570 | } | ||
571 | |||
572 | static int hdmi_audio_start(struct omap_dss_device *dssdev) | ||
573 | { | ||
574 | return -EPERM; | ||
575 | } | ||
576 | |||
577 | static void hdmi_audio_stop(struct omap_dss_device *dssdev) | ||
578 | { | ||
579 | } | ||
580 | |||
581 | static bool hdmi_audio_supported(struct omap_dss_device *dssdev) | ||
582 | { | ||
583 | return false; | ||
584 | } | ||
585 | |||
586 | static int hdmi_audio_config(struct omap_dss_device *dssdev, | ||
587 | struct omap_dss_audio *audio) | ||
588 | { | ||
589 | return -EPERM; | ||
590 | } | ||
591 | #endif | ||
592 | |||
593 | static int hdmi_set_infoframe(struct omap_dss_device *dssdev, | 468 | static 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 | ||
630 | static void hdmi_init_output(struct platform_device *pdev) | 498 | static 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 | ||
645 | static void __exit hdmi_uninit_output(struct platform_device *pdev) | 513 | static 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 */ | ||
543 | static 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 | |||
558 | out: | ||
559 | mutex_unlock(&hd->lock); | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static 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 | |||
575 | static 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 | |||
588 | static 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 | |||
599 | static 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 | |||
615 | out: | ||
616 | mutex_unlock(&hd->lock); | ||
617 | |||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static 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 | |||
629 | static 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 */ |
675 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 649 | static 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; |
711 | err: | ||
712 | hdmi_pll_uninit(&hdmi.pll); | ||
713 | return r; | ||
733 | } | 714 | } |
734 | 715 | ||
735 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 716 | static 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 | ||
744 | static int hdmi_runtime_suspend(struct device *dev) | 730 | static 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) | ||
534 | static void hdmi_core_audio_config(struct hdmi_core_data *core, | 531 | static 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 | ||
880 | int 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 | |||
891 | int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core) | 877 | int 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, | |||
266 | void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); | 266 | void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); |
267 | int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); | 267 | int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); |
268 | 268 | ||
269 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | ||
270 | int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); | 269 | int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); |
271 | void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); | 270 | void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); |
272 | int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | 271 | int 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); |
274 | int 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 | ||
46 | static struct { | 47 | static 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 | ||
65 | static int hdmi_runtime_get(void) | 49 | static 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); |
263 | err_phy_pwr: | 250 | err_phy_pwr: |
264 | err_phy_cfg: | 251 | err_phy_cfg: |
265 | hdmi_pll_disable(&hdmi.pll, &hdmi.wp); | 252 | err_pll_cfg: |
253 | dss_pll_disable(&hdmi.pll.pll); | ||
266 | err_pll_enable: | 254 | err_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 | ||
432 | static 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 | |||
447 | static int hdmi_connect(struct omap_dss_device *dssdev, | 431 | static 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) | ||
513 | static 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 | |||
531 | err: | ||
532 | mutex_unlock(&hdmi.lock); | ||
533 | return r; | ||
534 | } | ||
535 | |||
536 | static void hdmi_audio_disable(struct omap_dss_device *dssdev) | ||
537 | { | ||
538 | hdmi_wp_audio_enable(&hdmi.wp, false); | ||
539 | } | ||
540 | |||
541 | static int hdmi_audio_start(struct omap_dss_device *dssdev) | ||
542 | { | ||
543 | return hdmi_wp_audio_core_req_enable(&hdmi.wp, true); | ||
544 | } | ||
545 | |||
546 | static void hdmi_audio_stop(struct omap_dss_device *dssdev) | ||
547 | { | ||
548 | hdmi_wp_audio_core_req_enable(&hdmi.wp, false); | ||
549 | } | ||
550 | |||
551 | static 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 | |||
563 | static 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 | |||
583 | err: | ||
584 | mutex_unlock(&hdmi.lock); | ||
585 | return r; | ||
586 | } | ||
587 | #else | ||
588 | static int hdmi_audio_enable(struct omap_dss_device *dssdev) | ||
589 | { | ||
590 | return -EPERM; | ||
591 | } | ||
592 | |||
593 | static void hdmi_audio_disable(struct omap_dss_device *dssdev) | ||
594 | { | ||
595 | } | ||
596 | |||
597 | static int hdmi_audio_start(struct omap_dss_device *dssdev) | ||
598 | { | ||
599 | return -EPERM; | ||
600 | } | ||
601 | |||
602 | static void hdmi_audio_stop(struct omap_dss_device *dssdev) | ||
603 | { | ||
604 | } | ||
605 | |||
606 | static bool hdmi_audio_supported(struct omap_dss_device *dssdev) | ||
607 | { | ||
608 | return false; | ||
609 | } | ||
610 | |||
611 | static int hdmi_audio_config(struct omap_dss_device *dssdev, | ||
612 | struct omap_dss_audio *audio) | ||
613 | { | ||
614 | return -EPERM; | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | static int hdmi_set_infoframe(struct omap_dss_device *dssdev, | 496 | static 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 | ||
655 | static void hdmi_init_output(struct platform_device *pdev) | 526 | static 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 | ||
670 | static void __exit hdmi_uninit_output(struct platform_device *pdev) | 541 | static 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 */ | ||
571 | static 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 | |||
586 | out: | ||
587 | mutex_unlock(&hd->lock); | ||
588 | |||
589 | return ret; | ||
590 | } | ||
591 | |||
592 | static 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 | |||
603 | static 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 | |||
620 | static 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 | |||
634 | static 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 | |||
650 | out: | ||
651 | mutex_unlock(&hd->lock); | ||
652 | |||
653 | return ret; | ||
654 | } | ||
655 | |||
656 | static 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 | |||
664 | static 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 */ |
700 | static int omapdss_hdmihw_probe(struct platform_device *pdev) | 684 | static 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; |
746 | err: | ||
747 | hdmi_pll_uninit(&hdmi.pll); | ||
748 | return r; | ||
758 | } | 749 | } |
759 | 750 | ||
760 | static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | 751 | static 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 | ||
769 | static int hdmi_runtime_suspend(struct device *dev) | 765 | static 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 | |||
650 | static void hdmi5_core_audio_config(struct hdmi_core_data *core, | 645 | static 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 | ||
899 | int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core) | 896 | int 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); |
300 | int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); | 300 | int hdmi5_core_init(struct platform_device *pdev, struct hdmi_core_data *core); |
301 | 301 | ||
302 | #if defined(CONFIG_OMAP5_DSS_HDMI_AUDIO) | ||
303 | int hdmi5_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, | 302 | int 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) | ||
52 | int hdmi_compute_acr(u32 pclk, u32 sample_freq, u32 *n, u32 *cts) | 51 | int 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 | ||
21 | struct hdmi_phy_features { | 21 | struct 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 | ||
135 | int hdmi_phy_configure(struct hdmi_phy_data *phy, struct hdmi_config *cfg) | 133 | int 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 | ||
185 | static const struct hdmi_phy_features omap44xx_phy_feats = { | 180 | static 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 | ||
193 | static const struct hdmi_phy_features omap54xx_phy_feats = { | 186 | static 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 | |||
26 | struct 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 | |||
36 | static const struct hdmi_pll_features *pll_feat; | ||
37 | |||
38 | void hdmi_pll_dump(struct hdmi_pll_data *pll, struct seq_file *s) | 25 | void 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 | ||
54 | void hdmi_pll_compute(struct hdmi_pll_data *pll, unsigned long clkin, int phy) | 41 | void 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 | ||
107 | static 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 | ||
169 | static int hdmi_pll_reset(struct hdmi_pll_data *pll) | 101 | static 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 | |||
184 | int 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 | ||
207 | void hdmi_pll_disable(struct hdmi_pll_data *pll, struct hdmi_wp_data *wp) | 114 | static 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 | ||
212 | static const struct hdmi_pll_features omap44xx_pll_feats = { | 122 | static 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 | ||
224 | static const struct hdmi_pll_features omap54xx_pll_feats = { | 128 | static 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 | ||
236 | static int hdmi_pll_init_features(struct platform_device *pdev) | 152 | static 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 | |||
177 | static 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 | ||
268 | int hdmi_pll_init(struct platform_device *pdev, struct hdmi_pll_data *pll) | 217 | int 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 | |||
246 | void 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) | ||
189 | void hdmi_wp_audio_config_format(struct hdmi_wp_data *wp, | 188 | void 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 | ||
241 | int hdmi_wp_init(struct platform_device *pdev, struct hdmi_wp_data *wp) | 243 | int 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 | |||
263 | phys_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 | } |
132 | EXPORT_SYMBOL(omap_dss_find_output); | 133 | EXPORT_SYMBOL(omap_dss_find_output); |
133 | 134 | ||
134 | struct omap_dss_device *omap_dss_find_output_by_node(struct device_node *node) | 135 | struct 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 | } |
145 | EXPORT_SYMBOL(omap_dss_find_output_by_node); | 158 | EXPORT_SYMBOL(omap_dss_find_output_by_port_node); |
146 | 159 | ||
147 | struct omap_dss_device *omapdss_find_output_from_display(struct omap_dss_device *dssdev) | 160 | struct 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 | |||
39 | static struct dss_pll *dss_plls[4]; | ||
40 | |||
41 | int 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 | |||
55 | void 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 | |||
67 | struct 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 | |||
79 | int 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 | |||
99 | err_enable: | ||
100 | regulator_disable(pll->regulator); | ||
101 | err_reg: | ||
102 | clk_disable_unprepare(pll->clkin); | ||
103 | return r; | ||
104 | } | ||
105 | |||
106 | void 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 | |||
118 | int 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 | |||
131 | bool 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 | |||
156 | bool 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 | |||
197 | static 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 | |||
224 | static 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 | |||
238 | int 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 | |||
326 | err: | ||
327 | return r; | ||
328 | } | ||
329 | |||
330 | int 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 | ||
428 | void __exit sdi_uninit_port(void) | 428 | void __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 | ||
30 | static struct fb_fix_screeninfo simplefb_fix = { | 32 | static 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 | |||
44 | static int simplefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, | 48 | static 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 | ||
170 | struct 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 | */ | ||
197 | static 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 | |||
249 | static 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 | ||
266 | static int simplefb_clocks_init(struct simplefb_par *par, | ||
267 | struct platform_device *pdev) { return 0; } | ||
268 | static void simplefb_clocks_destroy(struct simplefb_par *par) { } | ||
269 | #endif | ||
270 | |||
166 | static int simplefb_probe(struct platform_device *pdev) | 271 | static 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 | |||
360 | error_clocks: | ||
361 | simplefb_clocks_destroy(par); | ||
362 | error_unmap: | ||
363 | iounmap(info->screen_base); | ||
364 | error_fb_release: | ||
365 | framebuffer_release(info); | ||
366 | return ret; | ||
249 | } | 367 | } |
250 | 368 | ||
251 | static int simplefb_remove(struct platform_device *pdev) | 369 | static 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 | }; |
276 | module_platform_driver(simplefb_driver); | 396 | |
397 | static 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 | |||
416 | fs_initcall(simplefb_init); | ||
277 | 417 | ||
278 | MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>"); | 418 | MODULE_AUTHOR("Stephen Warren <swarren@wwwdotorg.org>"); |
279 | MODULE_DESCRIPTION("Simple framebuffer driver"); | 419 | MODULE_DESCRIPTION("Simple framebuffer driver"); |