1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2f76ee892STomi Valkeinen /*
3f76ee892STomi Valkeinen  * linux/drivers/video/omap2/dss/core.c
4f76ee892STomi Valkeinen  *
5f76ee892STomi Valkeinen  * Copyright (C) 2009 Nokia Corporation
6f76ee892STomi Valkeinen  * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
7f76ee892STomi Valkeinen  *
8f76ee892STomi Valkeinen  * Some code and ideas taken from drivers/video/omap/ driver
9f76ee892STomi Valkeinen  * by Imre Deak.
10f76ee892STomi Valkeinen  */
11f76ee892STomi Valkeinen 
12f76ee892STomi Valkeinen #define DSS_SUBSYS_NAME "CORE"
13f76ee892STomi Valkeinen 
14f76ee892STomi Valkeinen #include <linux/kernel.h>
15f76ee892STomi Valkeinen #include <linux/module.h>
16f76ee892STomi Valkeinen #include <linux/clk.h>
17f76ee892STomi Valkeinen #include <linux/err.h>
18f76ee892STomi Valkeinen #include <linux/platform_device.h>
19f76ee892STomi Valkeinen #include <linux/seq_file.h>
20f76ee892STomi Valkeinen #include <linux/debugfs.h>
21f76ee892STomi Valkeinen #include <linux/io.h>
22f76ee892STomi Valkeinen #include <linux/device.h>
23f76ee892STomi Valkeinen #include <linux/regulator/consumer.h>
24f76ee892STomi Valkeinen #include <linux/suspend.h>
25f76ee892STomi Valkeinen #include <linux/slab.h>
26f76ee892STomi Valkeinen 
2762d9e44eSPeter Ujfalusi #include <video/omapfb_dss.h>
28f76ee892STomi Valkeinen 
29f76ee892STomi Valkeinen #include "dss.h"
30f76ee892STomi Valkeinen #include "dss_features.h"
31f76ee892STomi Valkeinen 
32f76ee892STomi Valkeinen static struct {
33f76ee892STomi Valkeinen 	struct platform_device *pdev;
34f76ee892STomi Valkeinen 
35f76ee892STomi Valkeinen 	const char *default_display_name;
36f76ee892STomi Valkeinen } core;
37f76ee892STomi Valkeinen 
38f76ee892STomi Valkeinen static char *def_disp_name;
39f76ee892STomi Valkeinen module_param_named(def_disp, def_disp_name, charp, 0);
40f76ee892STomi Valkeinen MODULE_PARM_DESC(def_disp, "default display name");
41f76ee892STomi Valkeinen 
omapdss_get_default_display_name(void)42f76ee892STomi Valkeinen const char *omapdss_get_default_display_name(void)
43f76ee892STomi Valkeinen {
44f76ee892STomi Valkeinen 	return core.default_display_name;
45f76ee892STomi Valkeinen }
46f76ee892STomi Valkeinen EXPORT_SYMBOL(omapdss_get_default_display_name);
47f76ee892STomi Valkeinen 
omapdss_get_version(void)48f76ee892STomi Valkeinen enum omapdss_version omapdss_get_version(void)
49f76ee892STomi Valkeinen {
50f76ee892STomi Valkeinen 	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
51f76ee892STomi Valkeinen 	return pdata->version;
52f76ee892STomi Valkeinen }
53f76ee892STomi Valkeinen EXPORT_SYMBOL(omapdss_get_version);
54f76ee892STomi Valkeinen 
dss_get_core_pdev(void)55f76ee892STomi Valkeinen struct platform_device *dss_get_core_pdev(void)
56f76ee892STomi Valkeinen {
57f76ee892STomi Valkeinen 	return core.pdev;
58f76ee892STomi Valkeinen }
59f76ee892STomi Valkeinen 
dss_dsi_enable_pads(int dsi_id,unsigned lane_mask)60f76ee892STomi Valkeinen int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
61f76ee892STomi Valkeinen {
62f76ee892STomi Valkeinen 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
63f76ee892STomi Valkeinen 
64f76ee892STomi Valkeinen 	if (!board_data->dsi_enable_pads)
65f76ee892STomi Valkeinen 		return -ENOENT;
66f76ee892STomi Valkeinen 
67f76ee892STomi Valkeinen 	return board_data->dsi_enable_pads(dsi_id, lane_mask);
68f76ee892STomi Valkeinen }
69f76ee892STomi Valkeinen 
dss_dsi_disable_pads(int dsi_id,unsigned lane_mask)70f76ee892STomi Valkeinen void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
71f76ee892STomi Valkeinen {
72f76ee892STomi Valkeinen 	struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
73f76ee892STomi Valkeinen 
74f76ee892STomi Valkeinen 	if (!board_data->dsi_disable_pads)
75f76ee892STomi Valkeinen 		return;
76f76ee892STomi Valkeinen 
77f76ee892STomi Valkeinen 	return board_data->dsi_disable_pads(dsi_id, lane_mask);
78f76ee892STomi Valkeinen }
79f76ee892STomi Valkeinen 
dss_set_min_bus_tput(struct device * dev,unsigned long tput)80f76ee892STomi Valkeinen int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
81f76ee892STomi Valkeinen {
82f76ee892STomi Valkeinen 	struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
83f76ee892STomi Valkeinen 
84f76ee892STomi Valkeinen 	if (pdata->set_min_bus_tput)
85f76ee892STomi Valkeinen 		return pdata->set_min_bus_tput(dev, tput);
86f76ee892STomi Valkeinen 	else
87f76ee892STomi Valkeinen 		return 0;
88f76ee892STomi Valkeinen }
89f76ee892STomi Valkeinen 
9035b522cfSTomi Valkeinen #if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS)
dss_show(struct seq_file * s,void * unused)91452f2d49SYangtao Li static int dss_show(struct seq_file *s, void *unused)
92f76ee892STomi Valkeinen {
93f76ee892STomi Valkeinen 	void (*func)(struct seq_file *) = s->private;
94f76ee892STomi Valkeinen 	func(s);
95f76ee892STomi Valkeinen 	return 0;
96f76ee892STomi Valkeinen }
97f76ee892STomi Valkeinen 
98452f2d49SYangtao Li DEFINE_SHOW_ATTRIBUTE(dss);
99f76ee892STomi Valkeinen 
100f76ee892STomi Valkeinen static struct dentry *dss_debugfs_dir;
101f76ee892STomi Valkeinen 
dss_initialize_debugfs(void)10260d2fa0dSGreg Kroah-Hartman static void dss_initialize_debugfs(void)
103f76ee892STomi Valkeinen {
104f76ee892STomi Valkeinen 	dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
105f76ee892STomi Valkeinen 
106f76ee892STomi Valkeinen 	debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
107452f2d49SYangtao Li 			&dss_debug_dump_clocks, &dss_fops);
108f76ee892STomi Valkeinen }
109f76ee892STomi Valkeinen 
dss_uninitialize_debugfs(void)110f76ee892STomi Valkeinen static void dss_uninitialize_debugfs(void)
111f76ee892STomi Valkeinen {
112f76ee892STomi Valkeinen 	debugfs_remove_recursive(dss_debugfs_dir);
113f76ee892STomi Valkeinen }
114f76ee892STomi Valkeinen 
dss_debugfs_create_file(const char * name,void (* write)(struct seq_file *))11560d2fa0dSGreg Kroah-Hartman void dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
116f76ee892STomi Valkeinen {
11760d2fa0dSGreg Kroah-Hartman 	debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, write, &dss_fops);
118f76ee892STomi Valkeinen }
11935b522cfSTomi Valkeinen #else /* CONFIG_FB_OMAP2_DSS_DEBUGFS */
dss_initialize_debugfs(void)12060d2fa0dSGreg Kroah-Hartman static inline void dss_initialize_debugfs(void)
121f76ee892STomi Valkeinen {
122f76ee892STomi Valkeinen }
dss_uninitialize_debugfs(void)123f76ee892STomi Valkeinen static inline void dss_uninitialize_debugfs(void)
124f76ee892STomi Valkeinen {
125f76ee892STomi Valkeinen }
dss_debugfs_create_file(const char * name,void (* write)(struct seq_file *))12660d2fa0dSGreg Kroah-Hartman void dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
127f76ee892STomi Valkeinen {
128f76ee892STomi Valkeinen }
12935b522cfSTomi Valkeinen #endif /* CONFIG_FB_OMAP2_DSS_DEBUGFS */
130f76ee892STomi Valkeinen 
131f76ee892STomi Valkeinen /* PLATFORM DEVICE */
omap_dss_pm_notif(struct notifier_block * b,unsigned long v,void * d)132f76ee892STomi Valkeinen static int omap_dss_pm_notif(struct notifier_block *b, unsigned long v, void *d)
133f76ee892STomi Valkeinen {
134f76ee892STomi Valkeinen 	DSSDBG("pm notif %lu\n", v);
135f76ee892STomi Valkeinen 
136f76ee892STomi Valkeinen 	switch (v) {
137f76ee892STomi Valkeinen 	case PM_SUSPEND_PREPARE:
138f76ee892STomi Valkeinen 	case PM_HIBERNATION_PREPARE:
139f76ee892STomi Valkeinen 	case PM_RESTORE_PREPARE:
140f76ee892STomi Valkeinen 		DSSDBG("suspending displays\n");
141f76ee892STomi Valkeinen 		return dss_suspend_all_devices();
142f76ee892STomi Valkeinen 
143f76ee892STomi Valkeinen 	case PM_POST_SUSPEND:
144f76ee892STomi Valkeinen 	case PM_POST_HIBERNATION:
145f76ee892STomi Valkeinen 	case PM_POST_RESTORE:
146f76ee892STomi Valkeinen 		DSSDBG("resuming displays\n");
147f76ee892STomi Valkeinen 		return dss_resume_all_devices();
148f76ee892STomi Valkeinen 
149f76ee892STomi Valkeinen 	default:
150f76ee892STomi Valkeinen 		return 0;
151f76ee892STomi Valkeinen 	}
152f76ee892STomi Valkeinen }
153f76ee892STomi Valkeinen 
154f76ee892STomi Valkeinen static struct notifier_block omap_dss_pm_notif_block = {
155f76ee892STomi Valkeinen 	.notifier_call = omap_dss_pm_notif,
156f76ee892STomi Valkeinen };
157f76ee892STomi Valkeinen 
omap_dss_probe(struct platform_device * pdev)158f76ee892STomi Valkeinen static int __init omap_dss_probe(struct platform_device *pdev)
159f76ee892STomi Valkeinen {
160f76ee892STomi Valkeinen 	core.pdev = pdev;
161f76ee892STomi Valkeinen 
162f76ee892STomi Valkeinen 	dss_features_init(omapdss_get_version());
163f76ee892STomi Valkeinen 
16460d2fa0dSGreg Kroah-Hartman 	dss_initialize_debugfs();
165f76ee892STomi Valkeinen 
166f76ee892STomi Valkeinen 	if (def_disp_name)
167f76ee892STomi Valkeinen 		core.default_display_name = def_disp_name;
168f76ee892STomi Valkeinen 
169f76ee892STomi Valkeinen 	register_pm_notifier(&omap_dss_pm_notif_block);
170f76ee892STomi Valkeinen 
171f76ee892STomi Valkeinen 	return 0;
172f76ee892STomi Valkeinen }
173f76ee892STomi Valkeinen 
omap_dss_remove(struct platform_device * pdev)174*dc6b77baSUwe Kleine-König static void omap_dss_remove(struct platform_device *pdev)
175f76ee892STomi Valkeinen {
176f76ee892STomi Valkeinen 	unregister_pm_notifier(&omap_dss_pm_notif_block);
177f76ee892STomi Valkeinen 
178f76ee892STomi Valkeinen 	dss_uninitialize_debugfs();
179f76ee892STomi Valkeinen }
180f76ee892STomi Valkeinen 
omap_dss_shutdown(struct platform_device * pdev)181f76ee892STomi Valkeinen static void omap_dss_shutdown(struct platform_device *pdev)
182f76ee892STomi Valkeinen {
183f76ee892STomi Valkeinen 	DSSDBG("shutdown\n");
184f76ee892STomi Valkeinen 	dss_disable_all_devices();
185f76ee892STomi Valkeinen }
186f76ee892STomi Valkeinen 
187f76ee892STomi Valkeinen static struct platform_driver omap_dss_driver = {
188*dc6b77baSUwe Kleine-König 	.remove_new     = omap_dss_remove,
189f76ee892STomi Valkeinen 	.shutdown	= omap_dss_shutdown,
190f76ee892STomi Valkeinen 	.driver         = {
191f76ee892STomi Valkeinen 		.name   = "omapdss",
192f76ee892STomi Valkeinen 	},
193f76ee892STomi Valkeinen };
194f76ee892STomi Valkeinen 
195f76ee892STomi Valkeinen /* INIT */
196f76ee892STomi Valkeinen static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
197f76ee892STomi Valkeinen 	dss_init_platform_driver,
198f76ee892STomi Valkeinen 	dispc_init_platform_driver,
19935b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_DSI
200f76ee892STomi Valkeinen 	dsi_init_platform_driver,
201f76ee892STomi Valkeinen #endif
20235b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_DPI
203f76ee892STomi Valkeinen 	dpi_init_platform_driver,
204f76ee892STomi Valkeinen #endif
20535b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_SDI
206f76ee892STomi Valkeinen 	sdi_init_platform_driver,
207f76ee892STomi Valkeinen #endif
20835b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_VENC
209f76ee892STomi Valkeinen 	venc_init_platform_driver,
210f76ee892STomi Valkeinen #endif
21135b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP4_DSS_HDMI
212f76ee892STomi Valkeinen 	hdmi4_init_platform_driver,
213f76ee892STomi Valkeinen #endif
21435b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP5_DSS_HDMI
215f76ee892STomi Valkeinen 	hdmi5_init_platform_driver,
216f76ee892STomi Valkeinen #endif
217f76ee892STomi Valkeinen };
218f76ee892STomi Valkeinen 
219f76ee892STomi Valkeinen static void (*dss_output_drv_unreg_funcs[])(void) = {
22035b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP5_DSS_HDMI
221f76ee892STomi Valkeinen 	hdmi5_uninit_platform_driver,
222f76ee892STomi Valkeinen #endif
22335b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP4_DSS_HDMI
224f76ee892STomi Valkeinen 	hdmi4_uninit_platform_driver,
225f76ee892STomi Valkeinen #endif
22635b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_VENC
227f76ee892STomi Valkeinen 	venc_uninit_platform_driver,
228f76ee892STomi Valkeinen #endif
22935b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_SDI
230f76ee892STomi Valkeinen 	sdi_uninit_platform_driver,
231f76ee892STomi Valkeinen #endif
23235b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_DPI
233f76ee892STomi Valkeinen 	dpi_uninit_platform_driver,
234f76ee892STomi Valkeinen #endif
23535b522cfSTomi Valkeinen #ifdef CONFIG_FB_OMAP2_DSS_DSI
236f76ee892STomi Valkeinen 	dsi_uninit_platform_driver,
237f76ee892STomi Valkeinen #endif
238f76ee892STomi Valkeinen 	dispc_uninit_platform_driver,
239f76ee892STomi Valkeinen 	dss_uninit_platform_driver,
240f76ee892STomi Valkeinen };
241f76ee892STomi Valkeinen 
omap_dss_init(void)242f76ee892STomi Valkeinen static int __init omap_dss_init(void)
243f76ee892STomi Valkeinen {
244f76ee892STomi Valkeinen 	int r;
245f76ee892STomi Valkeinen 	int i;
246f76ee892STomi Valkeinen 
247f76ee892STomi Valkeinen 	r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
248f76ee892STomi Valkeinen 	if (r)
249f76ee892STomi Valkeinen 		return r;
250f76ee892STomi Valkeinen 
251f76ee892STomi Valkeinen 	for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
252f76ee892STomi Valkeinen 		r = dss_output_drv_reg_funcs[i]();
253f76ee892STomi Valkeinen 		if (r)
254f76ee892STomi Valkeinen 			goto err_reg;
255f76ee892STomi Valkeinen 	}
256f76ee892STomi Valkeinen 
257f76ee892STomi Valkeinen 	return 0;
258f76ee892STomi Valkeinen 
259f76ee892STomi Valkeinen err_reg:
260f76ee892STomi Valkeinen 	for (i = ARRAY_SIZE(dss_output_drv_reg_funcs) - i;
261f76ee892STomi Valkeinen 			i < ARRAY_SIZE(dss_output_drv_reg_funcs);
262f76ee892STomi Valkeinen 			++i)
263f76ee892STomi Valkeinen 		dss_output_drv_unreg_funcs[i]();
264f76ee892STomi Valkeinen 
265f76ee892STomi Valkeinen 	platform_driver_unregister(&omap_dss_driver);
266f76ee892STomi Valkeinen 
267f76ee892STomi Valkeinen 	return r;
268f76ee892STomi Valkeinen }
269f76ee892STomi Valkeinen 
omap_dss_exit(void)270f76ee892STomi Valkeinen static void __exit omap_dss_exit(void)
271f76ee892STomi Valkeinen {
272f76ee892STomi Valkeinen 	int i;
273f76ee892STomi Valkeinen 
274f76ee892STomi Valkeinen 	for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i)
275f76ee892STomi Valkeinen 		dss_output_drv_unreg_funcs[i]();
276f76ee892STomi Valkeinen 
277f76ee892STomi Valkeinen 	platform_driver_unregister(&omap_dss_driver);
278f76ee892STomi Valkeinen }
279f76ee892STomi Valkeinen 
280f76ee892STomi Valkeinen module_init(omap_dss_init);
281f76ee892STomi Valkeinen module_exit(omap_dss_exit);
282f76ee892STomi Valkeinen 
283f76ee892STomi Valkeinen MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
284f76ee892STomi Valkeinen MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
285f76ee892STomi Valkeinen MODULE_LICENSE("GPL v2");
286f76ee892STomi Valkeinen 
287