diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-04-22 06:10:15 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2014-07-11 15:34:45 -0400 |
commit | d8c96083cf5e4a910c20836414e8a06ebcf07317 (patch) | |
tree | 9d8e951f1b75c5d9023f30feea50f3a750da1c42 | |
parent | ad49579adfd4b8097b391f838b62b5a6fa346a4a (diff) |
drm/armada: permit CRTCs to be registered as separate devices
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.c | 113 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_crtc.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/armada/armada_drv.c | 17 |
3 files changed, 122 insertions, 14 deletions
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index afa497489000..0642b5cfa563 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
@@ -7,6 +7,9 @@ | |||
7 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
8 | */ | 8 | */ |
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
10 | #include <linux/component.h> | ||
11 | #include <linux/of_device.h> | ||
12 | #include <linux/platform_device.h> | ||
10 | #include <drm/drmP.h> | 13 | #include <drm/drmP.h> |
11 | #include <drm/drm_crtc_helper.h> | 14 | #include <drm/drm_crtc_helper.h> |
12 | #include "armada_crtc.h" | 15 | #include "armada_crtc.h" |
@@ -1046,19 +1049,19 @@ static int armada_drm_crtc_create_properties(struct drm_device *dev) | |||
1046 | return 0; | 1049 | return 0; |
1047 | } | 1050 | } |
1048 | 1051 | ||
1049 | int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, | 1052 | int armada_drm_crtc_create(struct drm_device *drm, struct device *dev, |
1050 | int irq, const struct armada_variant *variant) | 1053 | struct resource *res, int irq, const struct armada_variant *variant) |
1051 | { | 1054 | { |
1052 | struct armada_private *priv = dev->dev_private; | 1055 | struct armada_private *priv = drm->dev_private; |
1053 | struct armada_crtc *dcrtc; | 1056 | struct armada_crtc *dcrtc; |
1054 | void __iomem *base; | 1057 | void __iomem *base; |
1055 | int ret; | 1058 | int ret; |
1056 | 1059 | ||
1057 | ret = armada_drm_crtc_create_properties(dev); | 1060 | ret = armada_drm_crtc_create_properties(drm); |
1058 | if (ret) | 1061 | if (ret) |
1059 | return ret; | 1062 | return ret; |
1060 | 1063 | ||
1061 | base = devm_request_and_ioremap(dev->dev, res); | 1064 | base = devm_request_and_ioremap(dev, res); |
1062 | if (!base) { | 1065 | if (!base) { |
1063 | DRM_ERROR("failed to ioremap register\n"); | 1066 | DRM_ERROR("failed to ioremap register\n"); |
1064 | return -ENOMEM; | 1067 | return -ENOMEM; |
@@ -1070,9 +1073,12 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, | |||
1070 | return -ENOMEM; | 1073 | return -ENOMEM; |
1071 | } | 1074 | } |
1072 | 1075 | ||
1076 | if (dev != drm->dev) | ||
1077 | dev_set_drvdata(dev, dcrtc); | ||
1078 | |||
1073 | dcrtc->variant = variant; | 1079 | dcrtc->variant = variant; |
1074 | dcrtc->base = base; | 1080 | dcrtc->base = base; |
1075 | dcrtc->num = dev->mode_config.num_crtc; | 1081 | dcrtc->num = drm->mode_config.num_crtc; |
1076 | dcrtc->clk = ERR_PTR(-EINVAL); | 1082 | dcrtc->clk = ERR_PTR(-EINVAL); |
1077 | dcrtc->csc_yuv_mode = CSC_AUTO; | 1083 | dcrtc->csc_yuv_mode = CSC_AUTO; |
1078 | dcrtc->csc_rgb_mode = CSC_AUTO; | 1084 | dcrtc->csc_rgb_mode = CSC_AUTO; |
@@ -1105,7 +1111,7 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, | |||
1105 | } | 1111 | } |
1106 | 1112 | ||
1107 | if (dcrtc->variant->init) { | 1113 | if (dcrtc->variant->init) { |
1108 | ret = dcrtc->variant->init(dcrtc, dev->dev); | 1114 | ret = dcrtc->variant->init(dcrtc, dev); |
1109 | if (ret) { | 1115 | if (ret) { |
1110 | kfree(dcrtc); | 1116 | kfree(dcrtc); |
1111 | return ret; | 1117 | return ret; |
@@ -1117,7 +1123,7 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, | |||
1117 | 1123 | ||
1118 | priv->dcrtc[dcrtc->num] = dcrtc; | 1124 | priv->dcrtc[dcrtc->num] = dcrtc; |
1119 | 1125 | ||
1120 | drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs); | 1126 | drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs); |
1121 | drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); | 1127 | drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs); |
1122 | 1128 | ||
1123 | drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, | 1129 | drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop, |
@@ -1125,5 +1131,94 @@ int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, | |||
1125 | drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop, | 1131 | drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop, |
1126 | dcrtc->csc_rgb_mode); | 1132 | dcrtc->csc_rgb_mode); |
1127 | 1133 | ||
1128 | return armada_overlay_plane_create(dev, 1 << dcrtc->num); | 1134 | return armada_overlay_plane_create(drm, 1 << dcrtc->num); |
1135 | } | ||
1136 | |||
1137 | static int | ||
1138 | armada_lcd_bind(struct device *dev, struct device *master, void *data) | ||
1139 | { | ||
1140 | struct platform_device *pdev = to_platform_device(dev); | ||
1141 | struct drm_device *drm = data; | ||
1142 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1143 | int irq = platform_get_irq(pdev, 0); | ||
1144 | const struct armada_variant *variant; | ||
1145 | |||
1146 | if (irq < 0) | ||
1147 | return irq; | ||
1148 | |||
1149 | if (!dev->of_node) { | ||
1150 | const struct platform_device_id *id; | ||
1151 | |||
1152 | id = platform_get_device_id(pdev); | ||
1153 | if (!id) | ||
1154 | return -ENXIO; | ||
1155 | |||
1156 | variant = (const struct armada_variant *)id->driver_data; | ||
1157 | } else { | ||
1158 | const struct of_device_id *match; | ||
1159 | |||
1160 | match = of_match_device(dev->driver->of_match_table, dev); | ||
1161 | if (!match) | ||
1162 | return -ENXIO; | ||
1163 | |||
1164 | variant = match->data; | ||
1165 | } | ||
1166 | |||
1167 | return armada_drm_crtc_create(drm, dev, res, irq, variant); | ||
1168 | } | ||
1169 | |||
1170 | static void | ||
1171 | armada_lcd_unbind(struct device *dev, struct device *master, void *data) | ||
1172 | { | ||
1173 | struct armada_crtc *dcrtc = dev_get_drvdata(dev); | ||
1174 | |||
1175 | armada_drm_crtc_destroy(&dcrtc->crtc); | ||
1176 | } | ||
1177 | |||
1178 | static const struct component_ops armada_lcd_ops = { | ||
1179 | .bind = armada_lcd_bind, | ||
1180 | .unbind = armada_lcd_unbind, | ||
1181 | }; | ||
1182 | |||
1183 | static int armada_lcd_probe(struct platform_device *pdev) | ||
1184 | { | ||
1185 | return component_add(&pdev->dev, &armada_lcd_ops); | ||
1186 | } | ||
1187 | |||
1188 | static int armada_lcd_remove(struct platform_device *pdev) | ||
1189 | { | ||
1190 | component_del(&pdev->dev, &armada_lcd_ops); | ||
1191 | return 0; | ||
1129 | } | 1192 | } |
1193 | |||
1194 | static struct of_device_id armada_lcd_of_match[] = { | ||
1195 | { | ||
1196 | .compatible = "marvell,dove-lcd", | ||
1197 | .data = &armada510_ops, | ||
1198 | }, | ||
1199 | {} | ||
1200 | }; | ||
1201 | MODULE_DEVICE_TABLE(of, armada_lcd_of_match); | ||
1202 | |||
1203 | static const struct platform_device_id armada_lcd_platform_ids[] = { | ||
1204 | { | ||
1205 | .name = "armada-lcd", | ||
1206 | .driver_data = (unsigned long)&armada510_ops, | ||
1207 | }, { | ||
1208 | .name = "armada-510-lcd", | ||
1209 | .driver_data = (unsigned long)&armada510_ops, | ||
1210 | }, | ||
1211 | { }, | ||
1212 | }; | ||
1213 | MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids); | ||
1214 | |||
1215 | struct platform_driver armada_lcd_platform_driver = { | ||
1216 | .probe = armada_lcd_probe, | ||
1217 | .remove = armada_lcd_remove, | ||
1218 | .driver = { | ||
1219 | .name = "armada-lcd", | ||
1220 | .owner = THIS_MODULE, | ||
1221 | .of_match_table = armada_lcd_of_match, | ||
1222 | }, | ||
1223 | .id_table = armada_lcd_platform_ids, | ||
1224 | }; | ||
diff --git a/drivers/gpu/drm/armada/armada_crtc.h b/drivers/gpu/drm/armada/armada_crtc.h index 73efcfcdf814..0d9a80392b1e 100644 --- a/drivers/gpu/drm/armada/armada_crtc.h +++ b/drivers/gpu/drm/armada/armada_crtc.h | |||
@@ -75,12 +75,14 @@ struct armada_crtc { | |||
75 | }; | 75 | }; |
76 | #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) | 76 | #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc) |
77 | 77 | ||
78 | int armada_drm_crtc_create(struct drm_device *, struct resource *, int, | 78 | int armada_drm_crtc_create(struct drm_device *, struct device *, |
79 | const struct armada_variant *); | 79 | struct resource *, int, const struct armada_variant *); |
80 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); | 80 | void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); |
81 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); | 81 | void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); |
82 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); | 82 | void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); |
83 | void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); | 83 | void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); |
84 | void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); | 84 | void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); |
85 | 85 | ||
86 | extern struct platform_driver armada_lcd_platform_driver; | ||
87 | |||
86 | #endif | 88 | #endif |
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 2b6fc6cf62f2..f237f44d8b6d 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c | |||
@@ -115,7 +115,7 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) | |||
115 | return -EINVAL; | 115 | return -EINVAL; |
116 | } | 116 | } |
117 | 117 | ||
118 | if (!res[0] || !mem) | 118 | if (!mem) |
119 | return -ENXIO; | 119 | return -ENXIO; |
120 | 120 | ||
121 | if (!devm_request_mem_region(dev->dev, mem->start, | 121 | if (!devm_request_mem_region(dev->dev, mem->start, |
@@ -168,7 +168,8 @@ static int armada_drm_load(struct drm_device *dev, unsigned long flags) | |||
168 | if (irq < 0) | 168 | if (irq < 0) |
169 | goto err_kms; | 169 | goto err_kms; |
170 | 170 | ||
171 | ret = armada_drm_crtc_create(dev, res[n], irq, variant); | 171 | ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq, |
172 | variant); | ||
172 | if (ret) | 173 | if (ret) |
173 | goto err_kms; | 174 | goto err_kms; |
174 | } | 175 | } |
@@ -490,14 +491,24 @@ static struct platform_driver armada_drm_platform_driver = { | |||
490 | 491 | ||
491 | static int __init armada_drm_init(void) | 492 | static int __init armada_drm_init(void) |
492 | { | 493 | { |
494 | int ret; | ||
495 | |||
493 | armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls); | 496 | armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls); |
494 | return platform_driver_register(&armada_drm_platform_driver); | 497 | |
498 | ret = platform_driver_register(&armada_lcd_platform_driver); | ||
499 | if (ret) | ||
500 | return ret; | ||
501 | ret = platform_driver_register(&armada_drm_platform_driver); | ||
502 | if (ret) | ||
503 | platform_driver_unregister(&armada_lcd_platform_driver); | ||
504 | return ret; | ||
495 | } | 505 | } |
496 | module_init(armada_drm_init); | 506 | module_init(armada_drm_init); |
497 | 507 | ||
498 | static void __exit armada_drm_exit(void) | 508 | static void __exit armada_drm_exit(void) |
499 | { | 509 | { |
500 | platform_driver_unregister(&armada_drm_platform_driver); | 510 | platform_driver_unregister(&armada_drm_platform_driver); |
511 | platform_driver_unregister(&armada_lcd_platform_driver); | ||
501 | } | 512 | } |
502 | module_exit(armada_drm_exit); | 513 | module_exit(armada_drm_exit); |
503 | 514 | ||