Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

OMAPDSS: componentize omapdss

omapdss kernel module contains drivers for multiple devices, one for
each DSS submodule. The probing we have at the moment is a mess, and
doesn't give us proper deferred probing nor ensure that all the devices
are probed before omapfb/omapdrm start using omapdss.

This patch solves the mess by using the component system for DSS
submodules.

The changes to all DSS submodules (dispc, dpi, dsi, hdmi4/5, rfbi, sdi,
venc) are the same: probe & remove functions are changed to bind &
unbind, and new probe & remove functions are added which call
component_add/del.

The dss_core driver (dss.c) acts as a component master. Adding and
matching the components is simple: all dss device's child devices are
added as components.

However, we do have some dependencies between the drivers. The order in
which they should be probed is reflected by the list in core.c
(dss_output_drv_reg_funcs). The drivers are registered in that order,
which causes the components to be added in that order, which makes the
components to be bound in that order. This feels a bit fragile, and we
probably should improve the code to manage binds in random order.
However, for now, this works fine.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

+236 -40
+23 -5
drivers/video/fbdev/omap2/dss/dispc.c
··· 39 39 #include <linux/mfd/syscon.h> 40 40 #include <linux/regmap.h> 41 41 #include <linux/of.h> 42 + #include <linux/component.h> 42 43 43 44 #include <video/omapdss.h> 44 45 ··· 3883 3882 EXPORT_SYMBOL(dispc_free_irq); 3884 3883 3885 3884 /* DISPC HW IP initialisation */ 3886 - static int omap_dispchw_probe(struct platform_device *pdev) 3885 + static int dispc_bind(struct device *dev, struct device *master, void *data) 3887 3886 { 3887 + struct platform_device *pdev = to_platform_device(dev); 3888 3888 u32 rev; 3889 3889 int r = 0; 3890 3890 struct resource *dispc_mem; ··· 3957 3955 return r; 3958 3956 } 3959 3957 3960 - static int omap_dispchw_remove(struct platform_device *pdev) 3958 + static void dispc_unbind(struct device *dev, struct device *master, 3959 + void *data) 3961 3960 { 3962 - pm_runtime_disable(&pdev->dev); 3961 + pm_runtime_disable(dev); 3963 3962 3964 3963 dss_uninit_overlay_managers(); 3964 + } 3965 3965 3966 + static const struct component_ops dispc_component_ops = { 3967 + .bind = dispc_bind, 3968 + .unbind = dispc_unbind, 3969 + }; 3970 + 3971 + static int dispc_probe(struct platform_device *pdev) 3972 + { 3973 + return component_add(&pdev->dev, &dispc_component_ops); 3974 + } 3975 + 3976 + static int dispc_remove(struct platform_device *pdev) 3977 + { 3978 + component_del(&pdev->dev, &dispc_component_ops); 3966 3979 return 0; 3967 3980 } 3968 3981 ··· 4030 4013 }; 4031 4014 4032 4015 static struct platform_driver omap_dispchw_driver = { 4033 - .remove = omap_dispchw_remove, 4016 + .probe = dispc_probe, 4017 + .remove = dispc_remove, 4034 4018 .driver = { 4035 4019 .name = "omapdss_dispc", 4036 4020 .pm = &dispc_pm_ops, ··· 4042 4024 4043 4025 int __init dispc_init_platform_driver(void) 4044 4026 { 4045 - return platform_driver_probe(&omap_dispchw_driver, omap_dispchw_probe); 4027 + return platform_driver_register(&omap_dispchw_driver); 4046 4028 } 4047 4029 4048 4030 void dispc_uninit_platform_driver(void)
+23 -5
drivers/video/fbdev/omap2/dss/dpi.c
··· 32 32 #include <linux/string.h> 33 33 #include <linux/of.h> 34 34 #include <linux/clk.h> 35 + #include <linux/component.h> 35 36 36 37 #include <video/omapdss.h> 37 38 ··· 784 783 omapdss_unregister_output(out); 785 784 } 786 785 787 - static int omap_dpi_probe(struct platform_device *pdev) 786 + static int dpi_bind(struct device *dev, struct device *master, void *data) 788 787 { 788 + struct platform_device *pdev = to_platform_device(dev); 789 789 struct dpi_data *dpi; 790 790 791 791 dpi = devm_kzalloc(&pdev->dev, sizeof(*dpi), GFP_KERNEL); ··· 804 802 return 0; 805 803 } 806 804 807 - static int omap_dpi_remove(struct platform_device *pdev) 805 + static void dpi_unbind(struct device *dev, struct device *master, void *data) 808 806 { 809 - dpi_uninit_output(pdev); 807 + struct platform_device *pdev = to_platform_device(dev); 810 808 809 + dpi_uninit_output(pdev); 810 + } 811 + 812 + static const struct component_ops dpi_component_ops = { 813 + .bind = dpi_bind, 814 + .unbind = dpi_unbind, 815 + }; 816 + 817 + static int dpi_probe(struct platform_device *pdev) 818 + { 819 + return component_add(&pdev->dev, &dpi_component_ops); 820 + } 821 + 822 + static int dpi_remove(struct platform_device *pdev) 823 + { 824 + component_del(&pdev->dev, &dpi_component_ops); 811 825 return 0; 812 826 } 813 827 814 828 static struct platform_driver omap_dpi_driver = { 815 - .probe = omap_dpi_probe, 816 - .remove = omap_dpi_remove, 829 + .probe = dpi_probe, 830 + .remove = dpi_remove, 817 831 .driver = { 818 832 .name = "omapdss_dpi", 819 833 .suppress_bind_attrs = true,
+21 -4
drivers/video/fbdev/omap2/dss/dsi.c
··· 40 40 #include <linux/pm_runtime.h> 41 41 #include <linux/of.h> 42 42 #include <linux/of_platform.h> 43 + #include <linux/component.h> 43 44 44 45 #include <video/omapdss.h> 45 46 #include <video/mipi_display.h> ··· 5275 5274 } 5276 5275 5277 5276 /* DSI1 HW IP initialisation */ 5278 - static int omap_dsihw_probe(struct platform_device *dsidev) 5277 + static int dsi_bind(struct device *dev, struct device *master, void *data) 5279 5278 { 5279 + struct platform_device *dsidev = to_platform_device(dev); 5280 5280 u32 rev; 5281 5281 int r, i; 5282 5282 struct dsi_data *dsi; ··· 5486 5484 return r; 5487 5485 } 5488 5486 5489 - static int omap_dsihw_remove(struct platform_device *dsidev) 5487 + static void dsi_unbind(struct device *dev, struct device *master, void *data) 5490 5488 { 5489 + struct platform_device *dsidev = to_platform_device(dev); 5491 5490 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 5492 5491 5493 5492 of_platform_depopulate(&dsidev->dev); ··· 5505 5502 regulator_disable(dsi->vdds_dsi_reg); 5506 5503 dsi->vdds_dsi_enabled = false; 5507 5504 } 5505 + } 5508 5506 5507 + static const struct component_ops dsi_component_ops = { 5508 + .bind = dsi_bind, 5509 + .unbind = dsi_unbind, 5510 + }; 5511 + 5512 + static int dsi_probe(struct platform_device *pdev) 5513 + { 5514 + return component_add(&pdev->dev, &dsi_component_ops); 5515 + } 5516 + 5517 + static int dsi_remove(struct platform_device *pdev) 5518 + { 5519 + component_del(&pdev->dev, &dsi_component_ops); 5509 5520 return 0; 5510 5521 } 5511 5522 ··· 5586 5569 }; 5587 5570 5588 5571 static struct platform_driver omap_dsihw_driver = { 5589 - .probe = omap_dsihw_probe, 5590 - .remove = omap_dsihw_remove, 5572 + .probe = dsi_probe, 5573 + .remove = dsi_remove, 5591 5574 .driver = { 5592 5575 .name = "omapdss_dsi", 5593 5576 .pm = &dsi_pm_ops,
+55 -4
drivers/video/fbdev/omap2/dss/dss.c
··· 39 39 #include <linux/of.h> 40 40 #include <linux/regulator/consumer.h> 41 41 #include <linux/suspend.h> 42 + #include <linux/component.h> 42 43 43 44 #include <video/omapdss.h> 44 45 ··· 1089 1088 } 1090 1089 1091 1090 /* DSS HW IP initialisation */ 1092 - static int omap_dsshw_probe(struct platform_device *pdev) 1091 + static int dss_bind(struct device *dev) 1093 1092 { 1093 + struct platform_device *pdev = to_platform_device(dev); 1094 1094 struct resource *dss_mem; 1095 1095 u32 rev; 1096 1096 int r; ··· 1161 1159 1162 1160 dss_runtime_put(); 1163 1161 1162 + r = component_bind_all(&pdev->dev, NULL); 1163 + if (r) 1164 + goto err_component; 1165 + 1164 1166 dss_debugfs_create_file("dss", dss_dump_regs); 1165 1167 1166 1168 pm_set_vt_switch(0); ··· 1173 1167 1174 1168 return 0; 1175 1169 1170 + err_component: 1176 1171 err_runtime_get: 1177 1172 pm_runtime_disable(&pdev->dev); 1178 1173 dss_uninit_ports(pdev); ··· 1189 1182 return r; 1190 1183 } 1191 1184 1192 - static int omap_dsshw_remove(struct platform_device *pdev) 1185 + static void dss_unbind(struct device *dev) 1193 1186 { 1187 + struct platform_device *pdev = to_platform_device(dev); 1188 + 1194 1189 dss_initialized = false; 1190 + 1191 + component_unbind_all(&pdev->dev, NULL); 1195 1192 1196 1193 if (dss.video1_pll) 1197 1194 dss_video_pll_uninit(dss.video1_pll); ··· 1208 1197 pm_runtime_disable(&pdev->dev); 1209 1198 1210 1199 dss_put_clocks(); 1200 + } 1211 1201 1202 + static const struct component_master_ops dss_component_ops = { 1203 + .bind = dss_bind, 1204 + .unbind = dss_unbind, 1205 + }; 1206 + 1207 + static int dss_component_compare(struct device *dev, void *data) 1208 + { 1209 + struct device *child = data; 1210 + return dev == child; 1211 + } 1212 + 1213 + static int dss_add_child_component(struct device *dev, void *data) 1214 + { 1215 + struct component_match **match = data; 1216 + 1217 + component_match_add(dev->parent, match, dss_component_compare, dev); 1218 + 1219 + return 0; 1220 + } 1221 + 1222 + static int dss_probe(struct platform_device *pdev) 1223 + { 1224 + struct component_match *match = NULL; 1225 + int r; 1226 + 1227 + /* add all the child devices as components */ 1228 + device_for_each_child(&pdev->dev, &match, dss_add_child_component); 1229 + 1230 + r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match); 1231 + if (r) 1232 + return r; 1233 + 1234 + return 0; 1235 + } 1236 + 1237 + static int dss_remove(struct platform_device *pdev) 1238 + { 1239 + component_master_del(&pdev->dev, &dss_component_ops); 1212 1240 return 0; 1213 1241 } 1214 1242 ··· 1293 1243 MODULE_DEVICE_TABLE(of, dss_of_match); 1294 1244 1295 1245 static struct platform_driver omap_dsshw_driver = { 1296 - .remove = omap_dsshw_remove, 1246 + .probe = dss_probe, 1247 + .remove = dss_remove, 1297 1248 .driver = { 1298 1249 .name = "omapdss_dss", 1299 1250 .pm = &dss_pm_ops, ··· 1305 1254 1306 1255 int __init dss_init_platform_driver(void) 1307 1256 { 1308 - return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); 1257 + return platform_driver_register(&omap_dsshw_driver); 1309 1258 } 1310 1259 1311 1260 void dss_uninit_platform_driver(void)
+22 -4
drivers/video/fbdev/omap2/dss/hdmi4.c
··· 32 32 #include <linux/clk.h> 33 33 #include <linux/gpio.h> 34 34 #include <linux/regulator/consumer.h> 35 + #include <linux/component.h> 35 36 #include <video/omapdss.h> 36 37 #include <sound/omap-hdmi-audio.h> 37 38 ··· 647 646 } 648 647 649 648 /* HDMI HW IP initialisation */ 650 - static int omapdss_hdmihw_probe(struct platform_device *pdev) 649 + static int hdmi4_bind(struct device *dev, struct device *master, void *data) 651 650 { 651 + struct platform_device *pdev = to_platform_device(dev); 652 652 int r; 653 653 int irq; 654 654 ··· 715 713 return r; 716 714 } 717 715 718 - static int omapdss_hdmihw_remove(struct platform_device *pdev) 716 + static void hdmi4_unbind(struct device *dev, struct device *master, void *data) 719 717 { 718 + struct platform_device *pdev = to_platform_device(dev); 719 + 720 720 if (hdmi.audio_pdev) 721 721 platform_device_unregister(hdmi.audio_pdev); 722 722 ··· 727 723 hdmi_pll_uninit(&hdmi.pll); 728 724 729 725 pm_runtime_disable(&pdev->dev); 726 + } 730 727 728 + static const struct component_ops hdmi4_component_ops = { 729 + .bind = hdmi4_bind, 730 + .unbind = hdmi4_unbind, 731 + }; 732 + 733 + static int hdmi4_probe(struct platform_device *pdev) 734 + { 735 + return component_add(&pdev->dev, &hdmi4_component_ops); 736 + } 737 + 738 + static int hdmi4_remove(struct platform_device *pdev) 739 + { 740 + component_del(&pdev->dev, &hdmi4_component_ops); 731 741 return 0; 732 742 } 733 743 ··· 774 756 }; 775 757 776 758 static struct platform_driver omapdss_hdmihw_driver = { 777 - .probe = omapdss_hdmihw_probe, 778 - .remove = omapdss_hdmihw_remove, 759 + .probe = hdmi4_probe, 760 + .remove = hdmi4_remove, 779 761 .driver = { 780 762 .name = "omapdss_hdmi", 781 763 .pm = &hdmi_pm_ops,
+22 -4
drivers/video/fbdev/omap2/dss/hdmi5.c
··· 37 37 #include <linux/clk.h> 38 38 #include <linux/gpio.h> 39 39 #include <linux/regulator/consumer.h> 40 + #include <linux/component.h> 40 41 #include <video/omapdss.h> 41 42 #include <sound/omap-hdmi-audio.h> 42 43 ··· 682 681 } 683 682 684 683 /* HDMI HW IP initialisation */ 685 - static int omapdss_hdmihw_probe(struct platform_device *pdev) 684 + static int hdmi5_bind(struct device *dev, struct device *master, void *data) 686 685 { 686 + struct platform_device *pdev = to_platform_device(dev); 687 687 int r; 688 688 int irq; 689 689 ··· 750 748 return r; 751 749 } 752 750 753 - static int omapdss_hdmihw_remove(struct platform_device *pdev) 751 + static void hdmi5_unbind(struct device *dev, struct device *master, void *data) 754 752 { 753 + struct platform_device *pdev = to_platform_device(dev); 754 + 755 755 if (hdmi.audio_pdev) 756 756 platform_device_unregister(hdmi.audio_pdev); 757 757 ··· 762 758 hdmi_pll_uninit(&hdmi.pll); 763 759 764 760 pm_runtime_disable(&pdev->dev); 761 + } 765 762 763 + static const struct component_ops hdmi5_component_ops = { 764 + .bind = hdmi5_bind, 765 + .unbind = hdmi5_unbind, 766 + }; 767 + 768 + static int hdmi5_probe(struct platform_device *pdev) 769 + { 770 + return component_add(&pdev->dev, &hdmi5_component_ops); 771 + } 772 + 773 + static int hdmi5_remove(struct platform_device *pdev) 774 + { 775 + component_del(&pdev->dev, &hdmi5_component_ops); 766 776 return 0; 767 777 } 768 778 ··· 810 792 }; 811 793 812 794 static struct platform_driver omapdss_hdmihw_driver = { 813 - .probe = omapdss_hdmihw_probe, 814 - .remove = omapdss_hdmihw_remove, 795 + .probe = hdmi5_probe, 796 + .remove = hdmi5_remove, 815 797 .driver = { 816 798 .name = "omapdss_hdmi5", 817 799 .pm = &hdmi_pm_ops,
+24 -4
drivers/video/fbdev/omap2/dss/rfbi.c
··· 36 36 #include <linux/semaphore.h> 37 37 #include <linux/platform_device.h> 38 38 #include <linux/pm_runtime.h> 39 + #include <linux/component.h> 39 40 40 41 #include <video/omapdss.h> 41 42 #include "dss.h" ··· 947 946 } 948 947 949 948 /* RFBI HW IP initialisation */ 950 - static int omap_rfbihw_probe(struct platform_device *pdev) 949 + static int rfbi_bind(struct device *dev, struct device *master, void *data) 951 950 { 951 + struct platform_device *pdev = to_platform_device(dev); 952 952 u32 rev; 953 953 struct resource *rfbi_mem; 954 954 struct clk *clk; ··· 1007 1005 return r; 1008 1006 } 1009 1007 1010 - static int omap_rfbihw_remove(struct platform_device *pdev) 1008 + static void rfbi_unbind(struct device *dev, struct device *master, void *data) 1011 1009 { 1010 + struct platform_device *pdev = to_platform_device(dev); 1011 + 1012 1012 rfbi_uninit_output(pdev); 1013 1013 1014 1014 pm_runtime_disable(&pdev->dev); 1015 1015 1016 + return 0; 1017 + } 1018 + 1019 + static const struct component_ops rfbi_component_ops = { 1020 + .bind = rfbi_bind, 1021 + .unbind = rfbi_unbind, 1022 + }; 1023 + 1024 + static int rfbi_probe(struct platform_device *pdev) 1025 + { 1026 + return component_add(&pdev->dev, &rfbi_component_ops); 1027 + } 1028 + 1029 + static int rfbi_remove(struct platform_device *pdev) 1030 + { 1031 + component_del(&pdev->dev, &rfbi_component_ops); 1016 1032 return 0; 1017 1033 } 1018 1034 ··· 1058 1038 }; 1059 1039 1060 1040 static struct platform_driver omap_rfbihw_driver = { 1061 - .probe = omap_rfbihw_probe, 1062 - .remove = omap_rfbihw_remove, 1041 + .probe = rfbi_probe, 1042 + .remove = rfbi_remove, 1063 1043 .driver = { 1064 1044 .name = "omapdss_rfbi", 1065 1045 .pm = &rfbi_pm_ops,
+24 -5
drivers/video/fbdev/omap2/dss/sdi.c
··· 27 27 #include <linux/platform_device.h> 28 28 #include <linux/string.h> 29 29 #include <linux/of.h> 30 + #include <linux/component.h> 30 31 31 32 #include <video/omapdss.h> 32 33 #include "dss.h" ··· 358 357 omapdss_unregister_output(out); 359 358 } 360 359 361 - static int omap_sdi_probe(struct platform_device *pdev) 360 + static int sdi_bind(struct device *dev, struct device *master, void *data) 362 361 { 362 + struct platform_device *pdev = to_platform_device(dev); 363 + 363 364 sdi.pdev = pdev; 364 365 365 366 sdi_init_output(pdev); ··· 369 366 return 0; 370 367 } 371 368 372 - static int omap_sdi_remove(struct platform_device *pdev) 369 + static void sdi_unbind(struct device *dev, struct device *master, void *data) 373 370 { 374 - sdi_uninit_output(pdev); 371 + struct platform_device *pdev = to_platform_device(dev); 375 372 373 + sdi_uninit_output(pdev); 374 + } 375 + 376 + static const struct component_ops sdi_component_ops = { 377 + .bind = sdi_bind, 378 + .unbind = sdi_unbind, 379 + }; 380 + 381 + static int sdi_probe(struct platform_device *pdev) 382 + { 383 + return component_add(&pdev->dev, &sdi_component_ops); 384 + } 385 + 386 + static int sdi_remove(struct platform_device *pdev) 387 + { 388 + component_del(&pdev->dev, &sdi_component_ops); 376 389 return 0; 377 390 } 378 391 379 392 static struct platform_driver omap_sdi_driver = { 380 - .probe = omap_sdi_probe, 381 - .remove = omap_sdi_remove, 393 + .probe = sdi_probe, 394 + .remove = sdi_remove, 382 395 .driver = { 383 396 .name = "omapdss_sdi", 384 397 .suppress_bind_attrs = true,
+22 -5
drivers/video/fbdev/omap2/dss/venc.c
··· 35 35 #include <linux/regulator/consumer.h> 36 36 #include <linux/pm_runtime.h> 37 37 #include <linux/of.h> 38 + #include <linux/component.h> 38 39 39 40 #include <video/omapdss.h> 40 41 ··· 853 852 } 854 853 855 854 /* VENC HW IP initialisation */ 856 - static int omap_venchw_probe(struct platform_device *pdev) 855 + static int venc_bind(struct device *dev, struct device *master, void *data) 857 856 { 857 + struct platform_device *pdev = to_platform_device(dev); 858 858 u8 rev_id; 859 859 struct resource *venc_mem; 860 860 int r; ··· 914 912 return r; 915 913 } 916 914 917 - static int omap_venchw_remove(struct platform_device *pdev) 915 + static void venc_unbind(struct device *dev, struct device *master, void *data) 918 916 { 917 + struct platform_device *pdev = to_platform_device(dev); 918 + 919 919 venc_uninit_output(pdev); 920 920 921 921 pm_runtime_disable(&pdev->dev); 922 + } 922 923 924 + static const struct component_ops venc_component_ops = { 925 + .bind = venc_bind, 926 + .unbind = venc_unbind, 927 + }; 928 + 929 + static int venc_probe(struct platform_device *pdev) 930 + { 931 + return component_add(&pdev->dev, &venc_component_ops); 932 + } 933 + 934 + static int venc_remove(struct platform_device *pdev) 935 + { 936 + component_del(&pdev->dev, &venc_component_ops); 923 937 return 0; 924 938 } 925 939 ··· 968 950 .runtime_resume = venc_runtime_resume, 969 951 }; 970 952 971 - 972 953 static const struct of_device_id venc_of_match[] = { 973 954 { .compatible = "ti,omap2-venc", }, 974 955 { .compatible = "ti,omap3-venc", }, ··· 976 959 }; 977 960 978 961 static struct platform_driver omap_venchw_driver = { 979 - .probe = omap_venchw_probe, 980 - .remove = omap_venchw_remove, 962 + .probe = venc_probe, 963 + .remove = venc_remove, 981 964 .driver = { 982 965 .name = "omapdss_venc", 983 966 .pm = &venc_pm_ops,