aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2014-04-22 06:10:15 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2014-07-11 15:34:45 -0400
commitd8c96083cf5e4a910c20836414e8a06ebcf07317 (patch)
tree9d8e951f1b75c5d9023f30feea50f3a750da1c42
parentad49579adfd4b8097b391f838b62b5a6fa346a4a (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.c113
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.h6
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c17
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
1049int armada_drm_crtc_create(struct drm_device *dev, struct resource *res, 1052int 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
1137static int
1138armada_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
1170static void
1171armada_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
1178static const struct component_ops armada_lcd_ops = {
1179 .bind = armada_lcd_bind,
1180 .unbind = armada_lcd_unbind,
1181};
1182
1183static int armada_lcd_probe(struct platform_device *pdev)
1184{
1185 return component_add(&pdev->dev, &armada_lcd_ops);
1186}
1187
1188static int armada_lcd_remove(struct platform_device *pdev)
1189{
1190 component_del(&pdev->dev, &armada_lcd_ops);
1191 return 0;
1129} 1192}
1193
1194static struct of_device_id armada_lcd_of_match[] = {
1195 {
1196 .compatible = "marvell,dove-lcd",
1197 .data = &armada510_ops,
1198 },
1199 {}
1200};
1201MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
1202
1203static 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};
1213MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
1214
1215struct 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
78int armada_drm_crtc_create(struct drm_device *, struct resource *, int, 78int armada_drm_crtc_create(struct drm_device *, struct device *,
79 const struct armada_variant *); 79 struct resource *, int, const struct armada_variant *);
80void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int); 80void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
81void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int); 81void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
82void armada_drm_crtc_disable_irq(struct armada_crtc *, u32); 82void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
83void armada_drm_crtc_enable_irq(struct armada_crtc *, u32); 83void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
84void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *); 84void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
85 85
86extern 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
491static int __init armada_drm_init(void) 492static 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}
496module_init(armada_drm_init); 506module_init(armada_drm_init);
497 507
498static void __exit armada_drm_exit(void) 508static 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}
502module_exit(armada_drm_exit); 513module_exit(armada_drm_exit);
503 514