aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/omap2/dss/dss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/omap2/dss/dss.c')
-rw-r--r--drivers/video/fbdev/omap2/dss/dss.c232
1 files changed, 160 insertions, 72 deletions
diff --git a/drivers/video/fbdev/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c
index 7f978b6a34e8..9200a8668b49 100644
--- a/drivers/video/fbdev/omap2/dss/dss.c
+++ b/drivers/video/fbdev/omap2/dss/dss.c
@@ -39,6 +39,7 @@
39#include <linux/of.h> 39#include <linux/of.h>
40#include <linux/regulator/consumer.h> 40#include <linux/regulator/consumer.h>
41#include <linux/suspend.h> 41#include <linux/suspend.h>
42#include <linux/component.h>
42 43
43#include <video/omapdss.h> 44#include <video/omapdss.h>
44 45
@@ -111,6 +112,14 @@ static const char * const dss_generic_clk_source_names[] = {
111 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", 112 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI",
112}; 113};
113 114
115static bool dss_initialized;
116
117bool omapdss_is_initialized(void)
118{
119 return dss_initialized;
120}
121EXPORT_SYMBOL(omapdss_is_initialized);
122
114static inline void dss_write_reg(const struct dss_reg idx, u32 val) 123static inline void dss_write_reg(const struct dss_reg idx, u32 val)
115{ 124{
116 __raw_writel(val, dss.base + idx.idx); 125 __raw_writel(val, dss.base + idx.idx);
@@ -811,7 +820,7 @@ static const enum omap_display_type dra7xx_ports[] = {
811 OMAP_DISPLAY_TYPE_DPI, 820 OMAP_DISPLAY_TYPE_DPI,
812}; 821};
813 822
814static const struct dss_features omap24xx_dss_feats __initconst = { 823static const struct dss_features omap24xx_dss_feats = {
815 /* 824 /*
816 * fck div max is really 16, but the divider range has gaps. The range 825 * fck div max is really 16, but the divider range has gaps. The range
817 * from 1 to 6 has no gaps, so let's use that as a max. 826 * from 1 to 6 has no gaps, so let's use that as a max.
@@ -824,7 +833,7 @@ static const struct dss_features omap24xx_dss_feats __initconst = {
824 .num_ports = ARRAY_SIZE(omap2plus_ports), 833 .num_ports = ARRAY_SIZE(omap2plus_ports),
825}; 834};
826 835
827static const struct dss_features omap34xx_dss_feats __initconst = { 836static const struct dss_features omap34xx_dss_feats = {
828 .fck_div_max = 16, 837 .fck_div_max = 16,
829 .dss_fck_multiplier = 2, 838 .dss_fck_multiplier = 2,
830 .parent_clk_name = "dpll4_ck", 839 .parent_clk_name = "dpll4_ck",
@@ -833,7 +842,7 @@ static const struct dss_features omap34xx_dss_feats __initconst = {
833 .num_ports = ARRAY_SIZE(omap34xx_ports), 842 .num_ports = ARRAY_SIZE(omap34xx_ports),
834}; 843};
835 844
836static const struct dss_features omap3630_dss_feats __initconst = { 845static const struct dss_features omap3630_dss_feats = {
837 .fck_div_max = 32, 846 .fck_div_max = 32,
838 .dss_fck_multiplier = 1, 847 .dss_fck_multiplier = 1,
839 .parent_clk_name = "dpll4_ck", 848 .parent_clk_name = "dpll4_ck",
@@ -842,7 +851,7 @@ static const struct dss_features omap3630_dss_feats __initconst = {
842 .num_ports = ARRAY_SIZE(omap2plus_ports), 851 .num_ports = ARRAY_SIZE(omap2plus_ports),
843}; 852};
844 853
845static const struct dss_features omap44xx_dss_feats __initconst = { 854static const struct dss_features omap44xx_dss_feats = {
846 .fck_div_max = 32, 855 .fck_div_max = 32,
847 .dss_fck_multiplier = 1, 856 .dss_fck_multiplier = 1,
848 .parent_clk_name = "dpll_per_x2_ck", 857 .parent_clk_name = "dpll_per_x2_ck",
@@ -851,7 +860,7 @@ static const struct dss_features omap44xx_dss_feats __initconst = {
851 .num_ports = ARRAY_SIZE(omap2plus_ports), 860 .num_ports = ARRAY_SIZE(omap2plus_ports),
852}; 861};
853 862
854static const struct dss_features omap54xx_dss_feats __initconst = { 863static const struct dss_features omap54xx_dss_feats = {
855 .fck_div_max = 64, 864 .fck_div_max = 64,
856 .dss_fck_multiplier = 1, 865 .dss_fck_multiplier = 1,
857 .parent_clk_name = "dpll_per_x2_ck", 866 .parent_clk_name = "dpll_per_x2_ck",
@@ -860,7 +869,7 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
860 .num_ports = ARRAY_SIZE(omap2plus_ports), 869 .num_ports = ARRAY_SIZE(omap2plus_ports),
861}; 870};
862 871
863static const struct dss_features am43xx_dss_feats __initconst = { 872static const struct dss_features am43xx_dss_feats = {
864 .fck_div_max = 0, 873 .fck_div_max = 0,
865 .dss_fck_multiplier = 0, 874 .dss_fck_multiplier = 0,
866 .parent_clk_name = NULL, 875 .parent_clk_name = NULL,
@@ -869,7 +878,7 @@ static const struct dss_features am43xx_dss_feats __initconst = {
869 .num_ports = ARRAY_SIZE(omap2plus_ports), 878 .num_ports = ARRAY_SIZE(omap2plus_ports),
870}; 879};
871 880
872static const struct dss_features dra7xx_dss_feats __initconst = { 881static const struct dss_features dra7xx_dss_feats = {
873 .fck_div_max = 64, 882 .fck_div_max = 64,
874 .dss_fck_multiplier = 1, 883 .dss_fck_multiplier = 1,
875 .parent_clk_name = "dpll_per_x2_ck", 884 .parent_clk_name = "dpll_per_x2_ck",
@@ -878,7 +887,7 @@ static const struct dss_features dra7xx_dss_feats __initconst = {
878 .num_ports = ARRAY_SIZE(dra7xx_ports), 887 .num_ports = ARRAY_SIZE(dra7xx_ports),
879}; 888};
880 889
881static int __init dss_init_features(struct platform_device *pdev) 890static int dss_init_features(struct platform_device *pdev)
882{ 891{
883 const struct dss_features *src; 892 const struct dss_features *src;
884 struct dss_features *dst; 893 struct dss_features *dst;
@@ -932,7 +941,7 @@ static int __init dss_init_features(struct platform_device *pdev)
932 return 0; 941 return 0;
933} 942}
934 943
935static int __init dss_init_ports(struct platform_device *pdev) 944static int dss_init_ports(struct platform_device *pdev)
936{ 945{
937 struct device_node *parent = pdev->dev.of_node; 946 struct device_node *parent = pdev->dev.of_node;
938 struct device_node *port; 947 struct device_node *port;
@@ -976,7 +985,7 @@ static int __init dss_init_ports(struct platform_device *pdev)
976 return 0; 985 return 0;
977} 986}
978 987
979static void __exit dss_uninit_ports(struct platform_device *pdev) 988static void dss_uninit_ports(struct platform_device *pdev)
980{ 989{
981 struct device_node *parent = pdev->dev.of_node; 990 struct device_node *parent = pdev->dev.of_node;
982 struct device_node *port; 991 struct device_node *port;
@@ -1018,14 +1027,74 @@ static void __exit dss_uninit_ports(struct platform_device *pdev)
1018 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); 1027 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
1019} 1028}
1020 1029
1030static int dss_video_pll_probe(struct platform_device *pdev)
1031{
1032 struct device_node *np = pdev->dev.of_node;
1033 struct regulator *pll_regulator;
1034 int r;
1035
1036 if (!np)
1037 return 0;
1038
1039 if (of_property_read_bool(np, "syscon-pll-ctrl")) {
1040 dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
1041 "syscon-pll-ctrl");
1042 if (IS_ERR(dss.syscon_pll_ctrl)) {
1043 dev_err(&pdev->dev,
1044 "failed to get syscon-pll-ctrl regmap\n");
1045 return PTR_ERR(dss.syscon_pll_ctrl);
1046 }
1047
1048 if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
1049 &dss.syscon_pll_ctrl_offset)) {
1050 dev_err(&pdev->dev,
1051 "failed to get syscon-pll-ctrl offset\n");
1052 return -EINVAL;
1053 }
1054 }
1055
1056 pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
1057 if (IS_ERR(pll_regulator)) {
1058 r = PTR_ERR(pll_regulator);
1059
1060 switch (r) {
1061 case -ENOENT:
1062 pll_regulator = NULL;
1063 break;
1064
1065 case -EPROBE_DEFER:
1066 return -EPROBE_DEFER;
1067
1068 default:
1069 DSSERR("can't get DPLL VDDA regulator\n");
1070 return r;
1071 }
1072 }
1073
1074 if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
1075 dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
1076 if (IS_ERR(dss.video1_pll))
1077 return PTR_ERR(dss.video1_pll);
1078 }
1079
1080 if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
1081 dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
1082 if (IS_ERR(dss.video2_pll)) {
1083 dss_video_pll_uninit(dss.video1_pll);
1084 return PTR_ERR(dss.video2_pll);
1085 }
1086 }
1087
1088 return 0;
1089}
1090
1021/* DSS HW IP initialisation */ 1091/* DSS HW IP initialisation */
1022static int __init omap_dsshw_probe(struct platform_device *pdev) 1092static int dss_bind(struct device *dev)
1023{ 1093{
1094 struct platform_device *pdev = to_platform_device(dev);
1024 struct resource *dss_mem; 1095 struct resource *dss_mem;
1025 struct device_node *np = pdev->dev.of_node;
1026 u32 rev; 1096 u32 rev;
1027 int r; 1097 int r;
1028 struct regulator *pll_regulator;
1029 1098
1030 dss.pdev = pdev; 1099 dss.pdev = pdev;
1031 1100
@@ -1054,6 +1123,14 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
1054 if (r) 1123 if (r)
1055 goto err_setup_clocks; 1124 goto err_setup_clocks;
1056 1125
1126 r = dss_video_pll_probe(pdev);
1127 if (r)
1128 goto err_pll_init;
1129
1130 r = dss_init_ports(pdev);
1131 if (r)
1132 goto err_init_ports;
1133
1057 pm_runtime_enable(&pdev->dev); 1134 pm_runtime_enable(&pdev->dev);
1058 1135
1059 r = dss_runtime_get(); 1136 r = dss_runtime_get();
@@ -1078,86 +1155,48 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
1078 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 1155 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
1079 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 1156 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
1080 1157
1081 dss_init_ports(pdev);
1082
1083 if (np && of_property_read_bool(np, "syscon-pll-ctrl")) {
1084 dss.syscon_pll_ctrl = syscon_regmap_lookup_by_phandle(np,
1085 "syscon-pll-ctrl");
1086 if (IS_ERR(dss.syscon_pll_ctrl)) {
1087 dev_err(&pdev->dev,
1088 "failed to get syscon-pll-ctrl regmap\n");
1089 return PTR_ERR(dss.syscon_pll_ctrl);
1090 }
1091
1092 if (of_property_read_u32_index(np, "syscon-pll-ctrl", 1,
1093 &dss.syscon_pll_ctrl_offset)) {
1094 dev_err(&pdev->dev,
1095 "failed to get syscon-pll-ctrl offset\n");
1096 return -EINVAL;
1097 }
1098 }
1099
1100 pll_regulator = devm_regulator_get(&pdev->dev, "vdda_video");
1101 if (IS_ERR(pll_regulator)) {
1102 r = PTR_ERR(pll_regulator);
1103
1104 switch (r) {
1105 case -ENOENT:
1106 pll_regulator = NULL;
1107 break;
1108
1109 case -EPROBE_DEFER:
1110 return -EPROBE_DEFER;
1111
1112 default:
1113 DSSERR("can't get DPLL VDDA regulator\n");
1114 return r;
1115 }
1116 }
1117
1118 if (of_property_match_string(np, "reg-names", "pll1") >= 0) {
1119 dss.video1_pll = dss_video_pll_init(pdev, 0, pll_regulator);
1120 if (IS_ERR(dss.video1_pll)) {
1121 r = PTR_ERR(dss.video1_pll);
1122 goto err_pll_init;
1123 }
1124 }
1125
1126 if (of_property_match_string(np, "reg-names", "pll2") >= 0) {
1127 dss.video2_pll = dss_video_pll_init(pdev, 1, pll_regulator);
1128 if (IS_ERR(dss.video2_pll)) {
1129 r = PTR_ERR(dss.video2_pll);
1130 goto err_pll_init;
1131 }
1132 }
1133
1134 rev = dss_read_reg(DSS_REVISION); 1158 rev = dss_read_reg(DSS_REVISION);
1135 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 1159 printk(KERN_INFO "OMAP DSS rev %d.%d\n",
1136 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 1160 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
1137 1161
1138 dss_runtime_put(); 1162 dss_runtime_put();
1139 1163
1164 r = component_bind_all(&pdev->dev, NULL);
1165 if (r)
1166 goto err_component;
1167
1140 dss_debugfs_create_file("dss", dss_dump_regs); 1168 dss_debugfs_create_file("dss", dss_dump_regs);
1141 1169
1142 pm_set_vt_switch(0); 1170 pm_set_vt_switch(0);
1143 1171
1172 dss_initialized = true;
1173
1144 return 0; 1174 return 0;
1145 1175
1146err_pll_init: 1176err_component:
1177err_runtime_get:
1178 pm_runtime_disable(&pdev->dev);
1179 dss_uninit_ports(pdev);
1180err_init_ports:
1147 if (dss.video1_pll) 1181 if (dss.video1_pll)
1148 dss_video_pll_uninit(dss.video1_pll); 1182 dss_video_pll_uninit(dss.video1_pll);
1149 1183
1150 if (dss.video2_pll) 1184 if (dss.video2_pll)
1151 dss_video_pll_uninit(dss.video2_pll); 1185 dss_video_pll_uninit(dss.video2_pll);
1152err_runtime_get: 1186err_pll_init:
1153 pm_runtime_disable(&pdev->dev);
1154err_setup_clocks: 1187err_setup_clocks:
1155 dss_put_clocks(); 1188 dss_put_clocks();
1156 return r; 1189 return r;
1157} 1190}
1158 1191
1159static int __exit omap_dsshw_remove(struct platform_device *pdev) 1192static void dss_unbind(struct device *dev)
1160{ 1193{
1194 struct platform_device *pdev = to_platform_device(dev);
1195
1196 dss_initialized = false;
1197
1198 component_unbind_all(&pdev->dev, NULL);
1199
1161 if (dss.video1_pll) 1200 if (dss.video1_pll)
1162 dss_video_pll_uninit(dss.video1_pll); 1201 dss_video_pll_uninit(dss.video1_pll);
1163 1202
@@ -1169,7 +1208,55 @@ static int __exit omap_dsshw_remove(struct platform_device *pdev)
1169 pm_runtime_disable(&pdev->dev); 1208 pm_runtime_disable(&pdev->dev);
1170 1209
1171 dss_put_clocks(); 1210 dss_put_clocks();
1211}
1212
1213static const struct component_master_ops dss_component_ops = {
1214 .bind = dss_bind,
1215 .unbind = dss_unbind,
1216};
1172 1217
1218static int dss_component_compare(struct device *dev, void *data)
1219{
1220 struct device *child = data;
1221 return dev == child;
1222}
1223
1224static int dss_add_child_component(struct device *dev, void *data)
1225{
1226 struct component_match **match = data;
1227
1228 /*
1229 * HACK
1230 * We don't have a working driver for rfbi, so skip it here always.
1231 * Otherwise dss will never get probed successfully, as it will wait
1232 * for rfbi to get probed.
1233 */
1234 if (strstr(dev_name(dev), "rfbi"))
1235 return 0;
1236
1237 component_match_add(dev->parent, match, dss_component_compare, dev);
1238
1239 return 0;
1240}
1241
1242static int dss_probe(struct platform_device *pdev)
1243{
1244 struct component_match *match = NULL;
1245 int r;
1246
1247 /* add all the child devices as components */
1248 device_for_each_child(&pdev->dev, &match, dss_add_child_component);
1249
1250 r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
1251 if (r)
1252 return r;
1253
1254 return 0;
1255}
1256
1257static int dss_remove(struct platform_device *pdev)
1258{
1259 component_master_del(&pdev->dev, &dss_component_ops);
1173 return 0; 1260 return 0;
1174} 1261}
1175 1262
@@ -1215,7 +1302,8 @@ static const struct of_device_id dss_of_match[] = {
1215MODULE_DEVICE_TABLE(of, dss_of_match); 1302MODULE_DEVICE_TABLE(of, dss_of_match);
1216 1303
1217static struct platform_driver omap_dsshw_driver = { 1304static struct platform_driver omap_dsshw_driver = {
1218 .remove = __exit_p(omap_dsshw_remove), 1305 .probe = dss_probe,
1306 .remove = dss_remove,
1219 .driver = { 1307 .driver = {
1220 .name = "omapdss_dss", 1308 .name = "omapdss_dss",
1221 .pm = &dss_pm_ops, 1309 .pm = &dss_pm_ops,
@@ -1226,7 +1314,7 @@ static struct platform_driver omap_dsshw_driver = {
1226 1314
1227int __init dss_init_platform_driver(void) 1315int __init dss_init_platform_driver(void)
1228{ 1316{
1229 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); 1317 return platform_driver_register(&omap_dsshw_driver);
1230} 1318}
1231 1319
1232void dss_uninit_platform_driver(void) 1320void dss_uninit_platform_driver(void)