Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
1
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
965e32b
Breadcrumbs
linux
/
drivers
/
video
/
omap2
/
dss
/
core.c
Copy path
Blame
Blame
Latest commit
History
History
584 lines (468 loc) · 12.7 KB
Breadcrumbs
linux
/
drivers
/
video
/
omap2
/
dss
/
core.c
Top
File metadata and controls
Code
Blame
584 lines (468 loc) · 12.7 KB
Raw
/* * linux/drivers/video/omap2/dss/core.c * * Copyright (C) 2009 Nokia Corporation * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> * * Some code and ideas taken from drivers/video/omap/ driver * by Imre Deak. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see <http://www.gnu.org/licenses/>. */ #define DSS_SUBSYS_NAME "CORE" #include <linux/kernel.h> #include <linux/module.h> #include <linux/clk.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/debugfs.h> #include <linux/io.h> #include <linux/device.h> #include <linux/regulator/consumer.h> #include <video/omapdss.h> #include "dss.h" #include "dss_features.h" static struct { struct platform_device *pdev; struct regulator *vdds_dsi_reg; struct regulator *vdds_sdi_reg; } core; static char *def_disp_name; module_param_named(def_disp, def_disp_name, charp, 0); MODULE_PARM_DESC(def_disp, "default display name"); #ifdef DEBUG unsigned int dss_debug; module_param_named(debug, dss_debug, bool, 0644); #endif static int omap_dss_register_device(struct omap_dss_device *); static void omap_dss_unregister_device(struct omap_dss_device *); /* REGULATORS */ struct regulator *dss_get_vdds_dsi(void) { struct regulator *reg; if (core.vdds_dsi_reg != NULL) return core.vdds_dsi_reg; reg = regulator_get(&core.pdev->dev, "vdds_dsi"); if (!IS_ERR(reg)) core.vdds_dsi_reg = reg; return reg; } struct regulator *dss_get_vdds_sdi(void) { struct regulator *reg; if (core.vdds_sdi_reg != NULL) return core.vdds_sdi_reg; reg = regulator_get(&core.pdev->dev, "vdds_sdi"); if (!IS_ERR(reg)) core.vdds_sdi_reg = reg; return reg; } #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT) static int dss_debug_show(struct seq_file *s, void *unused) { void (*func)(struct seq_file *) = s->private; func(s); return 0; } static int dss_debug_open(struct inode *inode, struct file *file) { return single_open(file, dss_debug_show, inode->i_private); } static const struct file_operations dss_debug_fops = { .open = dss_debug_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static struct dentry *dss_debugfs_dir; static int dss_initialize_debugfs(void) { dss_debugfs_dir = debugfs_create_dir("omapdss", NULL); if (IS_ERR(dss_debugfs_dir)) { int err = PTR_ERR(dss_debugfs_dir); dss_debugfs_dir = NULL; return err; } debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, &dss_debug_dump_clocks, &dss_debug_fops); #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir, &dispc_dump_irqs, &dss_debug_fops); #endif #if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS) dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops); #endif debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, &dss_dump_regs, &dss_debug_fops); debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, &dispc_dump_regs, &dss_debug_fops); #ifdef CONFIG_OMAP2_DSS_RFBI debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir, &rfbi_dump_regs, &dss_debug_fops); #endif #ifdef CONFIG_OMAP2_DSS_DSI dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops); #endif #ifdef CONFIG_OMAP2_DSS_VENC debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir, &venc_dump_regs, &dss_debug_fops); #endif return 0; } static void dss_uninitialize_debugfs(void) { if (dss_debugfs_dir) debugfs_remove_recursive(dss_debugfs_dir); } #else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ static inline int dss_initialize_debugfs(void) { return 0; } static inline void dss_uninitialize_debugfs(void) { } #endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */ /* PLATFORM DEVICE */ static int omap_dss_probe(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int r; int i; core.pdev = pdev; dss_features_init(); dss_init_overlay_managers(pdev); dss_init_overlays(pdev); r = dss_init_platform_driver(); if (r) { DSSERR("Failed to initialize DSS platform driver\n"); goto err_dss; } r = dispc_init_platform_driver(); if (r) { DSSERR("Failed to initialize dispc platform driver\n"); goto err_dispc; } r = rfbi_init_platform_driver(); if (r) { DSSERR("Failed to initialize rfbi platform driver\n"); goto err_rfbi; } r = venc_init_platform_driver(); if (r) { DSSERR("Failed to initialize venc platform driver\n"); goto err_venc; } r = dsi_init_platform_driver(); if (r) { DSSERR("Failed to initialize DSI platform driver\n"); goto err_dsi; } r = hdmi_init_platform_driver(); if (r) { DSSERR("Failed to initialize hdmi\n"); goto err_hdmi; } r = dss_initialize_debugfs(); if (r) goto err_debugfs; for (i = 0; i < pdata->num_devices; ++i) { struct omap_dss_device *dssdev = pdata->devices[i]; r = omap_dss_register_device(dssdev); if (r) { DSSERR("device %d %s register failed %d\n", i, dssdev->name ?: "unnamed", r); while (--i >= 0) omap_dss_unregister_device(pdata->devices[i]); goto err_register; } if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0) pdata->default_device = dssdev; } return 0; err_register: dss_uninitialize_debugfs(); err_debugfs: hdmi_uninit_platform_driver(); err_hdmi: dsi_uninit_platform_driver(); err_dsi: venc_uninit_platform_driver(); err_venc: dispc_uninit_platform_driver(); err_dispc: rfbi_uninit_platform_driver(); err_rfbi: dss_uninit_platform_driver(); err_dss: return r; } static int omap_dss_remove(struct platform_device *pdev) { struct omap_dss_board_info *pdata = pdev->dev.platform_data; int i; dss_uninitialize_debugfs(); hdmi_uninit_platform_driver(); dsi_uninit_platform_driver(); venc_uninit_platform_driver(); rfbi_uninit_platform_driver(); dispc_uninit_platform_driver(); dss_uninit_platform_driver(); dss_uninit_overlays(pdev); dss_uninit_overlay_managers(pdev); for (i = 0; i < pdata->num_devices; ++i) omap_dss_unregister_device(pdata->devices[i]); return 0; } static void omap_dss_shutdown(struct platform_device *pdev) { DSSDBG("shutdown\n"); dss_disable_all_devices(); } static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state) { DSSDBG("suspend %d\n", state.event); return dss_suspend_all_devices(); } static int omap_dss_resume(struct platform_device *pdev) { DSSDBG("resume\n"); return dss_resume_all_devices(); } static struct platform_driver omap_dss_driver = { .probe = omap_dss_probe, .remove = omap_dss_remove, .shutdown = omap_dss_shutdown, .suspend = omap_dss_suspend, .resume = omap_dss_resume, .driver = { .name = "omapdss", .owner = THIS_MODULE, }, }; /* BUS */ static int dss_bus_match(struct device *dev, struct device_driver *driver) { struct omap_dss_device *dssdev = to_dss_device(dev); DSSDBG("bus_match. dev %s/%s, drv %s\n", dev_name(dev), dssdev->driver_name, driver->name); return strcmp(dssdev->driver_name, driver->name) == 0; } static ssize_t device_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct omap_dss_device *dssdev = to_dss_device(dev); return snprintf(buf, PAGE_SIZE, "%s\n", dssdev->name ? dssdev->name : ""); } static struct device_attribute default_dev_attrs[] = { __ATTR(name, S_IRUGO, device_name_show, NULL), __ATTR_NULL, }; static ssize_t driver_name_show(struct device_driver *drv, char *buf) { struct omap_dss_driver *dssdrv = to_dss_driver(drv); return snprintf(buf, PAGE_SIZE, "%s\n", dssdrv->driver.name ? dssdrv->driver.name : ""); } static struct driver_attribute default_drv_attrs[] = { __ATTR(name, S_IRUGO, driver_name_show, NULL), __ATTR_NULL, }; static struct bus_type dss_bus_type = { .name = "omapdss", .match = dss_bus_match, .dev_attrs = default_dev_attrs, .drv_attrs = default_drv_attrs, }; static void dss_bus_release(struct device *dev) { DSSDBG("bus_release\n"); } static struct device dss_bus = { .release = dss_bus_release, }; struct bus_type *dss_get_bus(void) { return &dss_bus_type; } /* DRIVER */ static int dss_driver_probe(struct device *dev) { int r; struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); struct omap_dss_device *dssdev = to_dss_device(dev); struct omap_dss_board_info *pdata = core.pdev->dev.platform_data; bool force; DSSDBG("driver_probe: dev %s/%s, drv %s\n", dev_name(dev), dssdev->driver_name, dssdrv->driver.name); dss_init_device(core.pdev, dssdev); force = pdata->default_device == dssdev; dss_recheck_connections(dssdev, force); r = dssdrv->probe(dssdev); if (r) { DSSERR("driver probe failed: %d\n", r); dss_uninit_device(core.pdev, dssdev); return r; } DSSDBG("probe done for device %s\n", dev_name(dev)); dssdev->driver = dssdrv; return 0; } static int dss_driver_remove(struct device *dev) { struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver); struct omap_dss_device *dssdev = to_dss_device(dev); DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev), dssdev->driver_name); dssdrv->remove(dssdev); dss_uninit_device(core.pdev, dssdev); dssdev->driver = NULL; return 0; } int omap_dss_register_driver(struct omap_dss_driver *dssdriver) { dssdriver->driver.bus = &dss_bus_type; dssdriver->driver.probe = dss_driver_probe; dssdriver->driver.remove = dss_driver_remove; if (dssdriver->get_resolution == NULL) dssdriver->get_resolution = omapdss_default_get_resolution; if (dssdriver->get_recommended_bpp == NULL) dssdriver->get_recommended_bpp = omapdss_default_get_recommended_bpp; return driver_register(&dssdriver->driver); } EXPORT_SYMBOL(omap_dss_register_driver); void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver) { driver_unregister(&dssdriver->driver); } EXPORT_SYMBOL(omap_dss_unregister_driver); /* DEVICE */ static void reset_device(struct device *dev, int check) { u8 *dev_p = (u8 *)dev; u8 *dev_end = dev_p + sizeof(*dev); void *saved_pdata; saved_pdata = dev->platform_data; if (check) { /* * Check if there is any other setting than platform_data * in struct device; warn that these will be reset by our * init. */ dev->platform_data = NULL; while (dev_p < dev_end) { if (*dev_p) { WARN("%s: struct device fields will be " "discarded\n", __func__); break; } dev_p++; } } memset(dev, 0, sizeof(*dev)); dev->platform_data = saved_pdata; } static void omap_dss_dev_release(struct device *dev) { reset_device(dev, 0); } static int omap_dss_register_device(struct omap_dss_device *dssdev) { static int dev_num; WARN_ON(!dssdev->driver_name); reset_device(&dssdev->dev, 1); dssdev->dev.bus = &dss_bus_type; dssdev->dev.parent = &dss_bus; dssdev->dev.release = omap_dss_dev_release; dev_set_name(&dssdev->dev, "display%d", dev_num++); return device_register(&dssdev->dev); } static void omap_dss_unregister_device(struct omap_dss_device *dssdev) { device_unregister(&dssdev->dev); } /* BUS */ static int omap_dss_bus_register(void) { int r; r = bus_register(&dss_bus_type); if (r) { DSSERR("bus register failed\n"); return r; } dev_set_name(&dss_bus, "omapdss"); r = device_register(&dss_bus); if (r) { DSSERR("bus driver register failed\n"); bus_unregister(&dss_bus_type); return r; } return 0; } /* INIT */ #ifdef CONFIG_OMAP2_DSS_MODULE static void omap_dss_bus_unregister(void) { device_unregister(&dss_bus); bus_unregister(&dss_bus_type); } static int __init omap_dss_init(void) { int r; r = omap_dss_bus_register(); if (r) return r; r = platform_driver_register(&omap_dss_driver); if (r) { omap_dss_bus_unregister(); return r; } return 0; } static void __exit omap_dss_exit(void) { if (core.vdds_dsi_reg != NULL) { regulator_put(core.vdds_dsi_reg); core.vdds_dsi_reg = NULL; } if (core.vdds_sdi_reg != NULL) { regulator_put(core.vdds_sdi_reg); core.vdds_sdi_reg = NULL; } platform_driver_unregister(&omap_dss_driver); omap_dss_bus_unregister(); } module_init(omap_dss_init); module_exit(omap_dss_exit); #else static int __init omap_dss_init(void) { return omap_dss_bus_register(); } static int __init omap_dss_init2(void) { return platform_driver_register(&omap_dss_driver); } core_initcall(omap_dss_init); device_initcall(omap_dss_init2); #endif MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); MODULE_DESCRIPTION("OMAP2/3 Display Subsystem"); MODULE_LICENSE("GPL v2");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
You can’t perform that action at this time.