Commit 8a105aaa25f4504d26ca828f12d709d2213a230e

Authored by Dave Airlie

Merge branch 'drm-armada-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into drm-next

Merge armada changes, I've confirmed the componenet changes are same as in Greg's tree.
* 'drm-armada-devel' of git://ftp.arm.linux.org.uk/~rmk/linux-arm:
  drm/armada: register crtc with port
  drm/armada: permit CRTCs to be registered as separate devices
  dt-bindings: add Marvell Dove LCD controller documentation
  drm/armada: update Armada 510 (Dove) to use "ext_ref_clk1" as the clock
  drm/armada: convert to componentized support
  drm: add of_graph endpoint helper to find possible CRTCs
  component: fix bug with legacy API
  drm/armada: make variant a CRTC thing
  drm/armada: move variant initialisation to CRTC init
  drm/armada: use number of CRTCs registered
  drm/armada: move IRQ handling into CRTC
  component: add support for component match array
  component: ignore multiple additions of the same component
  component: fix missed cleanup in case of devres failure

Showing 12 changed files Side-by-side Diff

Documentation/devicetree/bindings/drm/armada/marvell,dove-lcd.txt
  1 +Device Tree bindings for Armada DRM CRTC driver
  2 +
  3 +Required properties:
  4 + - compatible: value should be "marvell,dove-lcd".
  5 + - reg: base address and size of the LCD controller
  6 + - interrupts: single interrupt number for the LCD controller
  7 + - port: video output port with endpoints, as described by graph.txt
  8 +
  9 +Optional properties:
  10 +
  11 + - clocks: as described by clock-bindings.txt
  12 + - clock-names: as described by clock-bindings.txt
  13 + "axiclk" - axi bus clock for pixel clock
  14 + "plldivider" - pll divider clock for pixel clock
  15 + "ext_ref_clk0" - external clock 0 for pixel clock
  16 + "ext_ref_clk1" - external clock 1 for pixel clock
  17 +
  18 +Note: all clocks are optional but at least one must be specified.
  19 +Further clocks may be added in the future according to requirements of
  20 +different SoCs.
  21 +
  22 +Example:
  23 +
  24 + lcd0: lcd-controller@820000 {
  25 + compatible = "marvell,dove-lcd";
  26 + reg = <0x820000 0x1000>;
  27 + interrupts = <47>;
  28 + clocks = <&si5351 0>;
  29 + clock-names = "ext_ref_clk_1";
  30 + };
drivers/base/component.c
... ... @@ -18,6 +18,15 @@
18 18 #include <linux/mutex.h>
19 19 #include <linux/slab.h>
20 20  
  21 +struct component_match {
  22 + size_t alloc;
  23 + size_t num;
  24 + struct {
  25 + void *data;
  26 + int (*fn)(struct device *, void *);
  27 + } compare[0];
  28 +};
  29 +
21 30 struct master {
22 31 struct list_head node;
23 32 struct list_head components;
... ... @@ -25,6 +34,7 @@
25 34  
26 35 const struct component_master_ops *ops;
27 36 struct device *dev;
  37 + struct component_match *match;
28 38 };
29 39  
30 40 struct component {
... ... @@ -69,6 +79,11 @@
69 79 c->master = NULL;
70 80 }
71 81  
  82 +/*
  83 + * Add a component to a master, finding the component via the compare
  84 + * function and compare data. This is safe to call for duplicate matches
  85 + * and will not result in the same component being added multiple times.
  86 + */
72 87 int component_master_add_child(struct master *master,
73 88 int (*compare)(struct device *, void *), void *compare_data)
74 89 {
75 90  
... ... @@ -76,11 +91,12 @@
76 91 int ret = -ENXIO;
77 92  
78 93 list_for_each_entry(c, &component_list, node) {
79   - if (c->master)
  94 + if (c->master && c->master != master)
80 95 continue;
81 96  
82 97 if (compare(c->dev, compare_data)) {
83   - component_attach_master(master, c);
  98 + if (!c->master)
  99 + component_attach_master(master, c);
84 100 ret = 0;
85 101 break;
86 102 }
... ... @@ -90,6 +106,34 @@
90 106 }
91 107 EXPORT_SYMBOL_GPL(component_master_add_child);
92 108  
  109 +static int find_components(struct master *master)
  110 +{
  111 + struct component_match *match = master->match;
  112 + size_t i;
  113 + int ret = 0;
  114 +
  115 + if (!match) {
  116 + /*
  117 + * Search the list of components, looking for components that
  118 + * belong to this master, and attach them to the master.
  119 + */
  120 + return master->ops->add_components(master->dev, master);
  121 + }
  122 +
  123 + /*
  124 + * Scan the array of match functions and attach
  125 + * any components which are found to this master.
  126 + */
  127 + for (i = 0; i < match->num; i++) {
  128 + ret = component_master_add_child(master,
  129 + match->compare[i].fn,
  130 + match->compare[i].data);
  131 + if (ret)
  132 + break;
  133 + }
  134 + return ret;
  135 +}
  136 +
93 137 /* Detach all attached components from this master */
94 138 static void master_remove_components(struct master *master)
95 139 {
96 140  
97 141  
98 142  
99 143  
100 144  
101 145  
102 146  
... ... @@ -113,44 +157,44 @@
113 157 static int try_to_bring_up_master(struct master *master,
114 158 struct component *component)
115 159 {
116   - int ret = 0;
  160 + int ret;
117 161  
118   - if (!master->bound) {
119   - /*
120   - * Search the list of components, looking for components that
121   - * belong to this master, and attach them to the master.
122   - */
123   - if (master->ops->add_components(master->dev, master)) {
124   - /* Failed to find all components */
125   - master_remove_components(master);
126   - ret = 0;
127   - goto out;
128   - }
  162 + if (master->bound)
  163 + return 0;
129 164  
130   - if (component && component->master != master) {
131   - master_remove_components(master);
132   - ret = 0;
133   - goto out;
134   - }
  165 + /*
  166 + * Search the list of components, looking for components that
  167 + * belong to this master, and attach them to the master.
  168 + */
  169 + if (find_components(master)) {
  170 + /* Failed to find all components */
  171 + ret = 0;
  172 + goto out;
  173 + }
135 174  
136   - if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
137   - ret = -ENOMEM;
138   - goto out;
139   - }
  175 + if (component && component->master != master) {
  176 + ret = 0;
  177 + goto out;
  178 + }
140 179  
141   - /* Found all components */
142   - ret = master->ops->bind(master->dev);
143   - if (ret < 0) {
144   - devres_release_group(master->dev, NULL);
145   - dev_info(master->dev, "master bind failed: %d\n", ret);
146   - master_remove_components(master);
147   - goto out;
148   - }
  180 + if (!devres_open_group(master->dev, NULL, GFP_KERNEL)) {
  181 + ret = -ENOMEM;
  182 + goto out;
  183 + }
149 184  
150   - master->bound = true;
151   - ret = 1;
  185 + /* Found all components */
  186 + ret = master->ops->bind(master->dev);
  187 + if (ret < 0) {
  188 + devres_release_group(master->dev, NULL);
  189 + dev_info(master->dev, "master bind failed: %d\n", ret);
  190 + goto out;
152 191 }
  192 +
  193 + master->bound = true;
  194 + return 1;
  195 +
153 196 out:
  197 + master_remove_components(master);
154 198  
155 199 return ret;
156 200 }
157 201  
158 202  
159 203  
... ... @@ -180,18 +224,89 @@
180 224 master_remove_components(master);
181 225 }
182 226  
183   -int component_master_add(struct device *dev,
184   - const struct component_master_ops *ops)
  227 +static size_t component_match_size(size_t num)
185 228 {
  229 + return offsetof(struct component_match, compare[num]);
  230 +}
  231 +
  232 +static struct component_match *component_match_realloc(struct device *dev,
  233 + struct component_match *match, size_t num)
  234 +{
  235 + struct component_match *new;
  236 +
  237 + if (match && match->alloc == num)
  238 + return match;
  239 +
  240 + new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);
  241 + if (!new)
  242 + return ERR_PTR(-ENOMEM);
  243 +
  244 + if (match) {
  245 + memcpy(new, match, component_match_size(min(match->num, num)));
  246 + devm_kfree(dev, match);
  247 + } else {
  248 + new->num = 0;
  249 + }
  250 +
  251 + new->alloc = num;
  252 +
  253 + return new;
  254 +}
  255 +
  256 +/*
  257 + * Add a component to be matched.
  258 + *
  259 + * The match array is first created or extended if necessary.
  260 + */
  261 +void component_match_add(struct device *dev, struct component_match **matchptr,
  262 + int (*compare)(struct device *, void *), void *compare_data)
  263 +{
  264 + struct component_match *match = *matchptr;
  265 +
  266 + if (IS_ERR(match))
  267 + return;
  268 +
  269 + if (!match || match->num == match->alloc) {
  270 + size_t new_size = match ? match->alloc + 16 : 15;
  271 +
  272 + match = component_match_realloc(dev, match, new_size);
  273 +
  274 + *matchptr = match;
  275 +
  276 + if (IS_ERR(match))
  277 + return;
  278 + }
  279 +
  280 + match->compare[match->num].fn = compare;
  281 + match->compare[match->num].data = compare_data;
  282 + match->num++;
  283 +}
  284 +EXPORT_SYMBOL(component_match_add);
  285 +
  286 +int component_master_add_with_match(struct device *dev,
  287 + const struct component_master_ops *ops,
  288 + struct component_match *match)
  289 +{
186 290 struct master *master;
187 291 int ret;
188 292  
  293 + if (ops->add_components && match)
  294 + return -EINVAL;
  295 +
  296 + if (match) {
  297 + /* Reallocate the match array for its true size */
  298 + match = component_match_realloc(dev, match, match->num);
  299 + if (IS_ERR(match))
  300 + return PTR_ERR(match);
  301 + }
  302 +
189 303 master = kzalloc(sizeof(*master), GFP_KERNEL);
190 304 if (!master)
191 305 return -ENOMEM;
192 306  
193 307 master->dev = dev;
194 308 master->ops = ops;
  309 + master->match = match;
195 310 INIT_LIST_HEAD(&master->components);
196 311  
197 312 /* Add to the list of available masters. */
... ... @@ -208,6 +323,13 @@
208 323 mutex_unlock(&component_mutex);
209 324  
210 325 return ret < 0 ? ret : 0;
  326 +}
  327 +EXPORT_SYMBOL_GPL(component_master_add_with_match);
  328 +
  329 +int component_master_add(struct device *dev,
  330 + const struct component_master_ops *ops)
  331 +{
  332 + return component_master_add_with_match(dev, ops, NULL);
211 333 }
212 334 EXPORT_SYMBOL_GPL(component_master_add);
213 335  
drivers/gpu/drm/Makefile
... ... @@ -20,6 +20,7 @@
20 20 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
21 21 drm-$(CONFIG_PCI) += ati_pcigart.o
22 22 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
  23 +drm-$(CONFIG_OF) += drm_of.o
23 24  
24 25 drm-usb-y := drm_usb.o
25 26  
drivers/gpu/drm/armada/armada_510.c
... ... @@ -15,20 +15,19 @@
15 15 #include "armada_drm.h"
16 16 #include "armada_hw.h"
17 17  
18   -static int armada510_init(struct armada_private *priv, struct device *dev)
  18 +static int armada510_crtc_init(struct armada_crtc *dcrtc, struct device *dev)
19 19 {
20   - priv->extclk[0] = devm_clk_get(dev, "ext_ref_clk_1");
  20 + struct clk *clk;
21 21  
22   - if (IS_ERR(priv->extclk[0]) && PTR_ERR(priv->extclk[0]) == -ENOENT)
23   - priv->extclk[0] = ERR_PTR(-EPROBE_DEFER);
  22 + clk = devm_clk_get(dev, "ext_ref_clk1");
  23 + if (IS_ERR(clk))
  24 + return PTR_ERR(clk) == -ENOENT ? -EPROBE_DEFER : PTR_ERR(clk);
24 25  
25   - return PTR_RET(priv->extclk[0]);
26   -}
  26 + dcrtc->extclk[0] = clk;
27 27  
28   -static int armada510_crtc_init(struct armada_crtc *dcrtc)
29   -{
30 28 /* Lower the watermark so to eliminate jitter at higher bandwidths */
31 29 armada_updatel(0x20, (1 << 11) | 0xff, dcrtc->base + LCD_CFG_RDREG4F);
  30 +
32 31 return 0;
33 32 }
34 33  
... ... @@ -45,8 +44,7 @@
45 44 static int armada510_crtc_compute_clock(struct armada_crtc *dcrtc,
46 45 const struct drm_display_mode *mode, uint32_t *sclk)
47 46 {
48   - struct armada_private *priv = dcrtc->crtc.dev->dev_private;
49   - struct clk *clk = priv->extclk[0];
  47 + struct clk *clk = dcrtc->extclk[0];
50 48 int ret;
51 49  
52 50 if (dcrtc->num == 1)
... ... @@ -81,8 +79,7 @@
81 79 const struct armada_variant armada510_ops = {
82 80 .has_spu_adv_reg = true,
83 81 .spu_adv_reg = ADV_HWC32ENABLE | ADV_HWC32ARGB | ADV_HWC32BLEND,
84   - .init = armada510_init,
85   - .crtc_init = armada510_crtc_init,
86   - .crtc_compute_clock = armada510_crtc_compute_clock,
  82 + .init = armada510_crtc_init,
  83 + .compute_clock = armada510_crtc_compute_clock,
87 84 };
drivers/gpu/drm/armada/armada_crtc.c
... ... @@ -7,6 +7,9 @@
7 7 * published by the Free Software Foundation.
8 8 */
9 9 #include <linux/clk.h>
  10 +#include <linux/component.h>
  11 +#include <linux/of_device.h>
  12 +#include <linux/platform_device.h>
10 13 #include <drm/drmP.h>
11 14 #include <drm/drm_crtc_helper.h>
12 15 #include "armada_crtc.h"
13 16  
14 17  
15 18  
... ... @@ -332,24 +335,23 @@
332 335 static bool armada_drm_crtc_mode_fixup(struct drm_crtc *crtc,
333 336 const struct drm_display_mode *mode, struct drm_display_mode *adj)
334 337 {
335   - struct armada_private *priv = crtc->dev->dev_private;
336 338 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
337 339 int ret;
338 340  
339 341 /* We can't do interlaced modes if we don't have the SPU_ADV_REG */
340   - if (!priv->variant->has_spu_adv_reg &&
  342 + if (!dcrtc->variant->has_spu_adv_reg &&
341 343 adj->flags & DRM_MODE_FLAG_INTERLACE)
342 344 return false;
343 345  
344 346 /* Check whether the display mode is possible */
345   - ret = priv->variant->crtc_compute_clock(dcrtc, adj, NULL);
  347 + ret = dcrtc->variant->compute_clock(dcrtc, adj, NULL);
346 348 if (ret)
347 349 return false;
348 350  
349 351 return true;
350 352 }
351 353  
352   -void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
  354 +static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
353 355 {
354 356 struct armada_vbl_event *e, *n;
355 357 void __iomem *base = dcrtc->base;
... ... @@ -410,6 +412,27 @@
410 412 }
411 413 }
412 414  
  415 +static irqreturn_t armada_drm_irq(int irq, void *arg)
  416 +{
  417 + struct armada_crtc *dcrtc = arg;
  418 + u32 v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
  419 +
  420 + /*
  421 + * This is rediculous - rather than writing bits to clear, we
  422 + * have to set the actual status register value. This is racy.
  423 + */
  424 + writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
  425 +
  426 + /* Mask out those interrupts we haven't enabled */
  427 + v = stat & dcrtc->irq_ena;
  428 +
  429 + if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
  430 + armada_drm_crtc_irq(dcrtc, stat);
  431 + return IRQ_HANDLED;
  432 + }
  433 + return IRQ_NONE;
  434 +}
  435 +
413 436 /* These are locked by dev->vbl_lock */
414 437 void armada_drm_crtc_disable_irq(struct armada_crtc *dcrtc, u32 mask)
415 438 {
... ... @@ -470,7 +493,6 @@
470 493 struct drm_display_mode *mode, struct drm_display_mode *adj,
471 494 int x, int y, struct drm_framebuffer *old_fb)
472 495 {
473   - struct armada_private *priv = crtc->dev->dev_private;
474 496 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
475 497 struct armada_regs regs[17];
476 498 uint32_t lm, rm, tm, bm, val, sclk;
... ... @@ -515,7 +537,7 @@
515 537 }
516 538  
517 539 /* Now compute the divider for real */
518   - priv->variant->crtc_compute_clock(dcrtc, adj, &sclk);
  540 + dcrtc->variant->compute_clock(dcrtc, adj, &sclk);
519 541  
520 542 /* Ensure graphic fifo is enabled */
521 543 armada_reg_queue_mod(regs, i, 0, CFG_PDWN64x66, LCD_SPU_SRAM_PARA1);
... ... @@ -537,7 +559,7 @@
537 559 dcrtc->v[1].spu_v_porch = tm << 16 | bm;
538 560 val = adj->crtc_hsync_start;
539 561 dcrtc->v[1].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
540   - priv->variant->spu_adv_reg;
  562 + dcrtc->variant->spu_adv_reg;
541 563  
542 564 if (interlaced) {
543 565 /* Odd interlaced frame */
... ... @@ -546,7 +568,7 @@
546 568 dcrtc->v[0].spu_v_porch = dcrtc->v[1].spu_v_porch + 1;
547 569 val = adj->crtc_hsync_start - adj->crtc_htotal / 2;
548 570 dcrtc->v[0].spu_adv_reg = val << 20 | val | ADV_VSYNCOFFEN |
549   - priv->variant->spu_adv_reg;
  571 + dcrtc->variant->spu_adv_reg;
550 572 } else {
551 573 dcrtc->v[0] = dcrtc->v[1];
552 574 }
... ... @@ -561,7 +583,7 @@
561 583 armada_reg_queue_set(regs, i, dcrtc->v[0].spu_v_h_total,
562 584 LCD_SPUT_V_H_TOTAL);
563 585  
564   - if (priv->variant->has_spu_adv_reg) {
  586 + if (dcrtc->variant->has_spu_adv_reg) {
565 587 armada_reg_queue_mod(regs, i, dcrtc->v[0].spu_adv_reg,
566 588 ADV_VSYNC_L_OFF | ADV_VSYNC_H_OFF |
567 589 ADV_VSYNCOFFEN, LCD_SPU_ADV_REG);
568 590  
... ... @@ -805,12 +827,11 @@
805 827 {
806 828 struct drm_device *dev = crtc->dev;
807 829 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
808   - struct armada_private *priv = crtc->dev->dev_private;
809 830 struct armada_gem_object *obj = NULL;
810 831 int ret;
811 832  
812 833 /* If no cursor support, replicate drm's return value */
813   - if (!priv->variant->has_spu_adv_reg)
  834 + if (!dcrtc->variant->has_spu_adv_reg)
814 835 return -ENXIO;
815 836  
816 837 if (handle && w > 0 && h > 0) {
817 838  
... ... @@ -858,11 +879,10 @@
858 879 {
859 880 struct drm_device *dev = crtc->dev;
860 881 struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc);
861   - struct armada_private *priv = crtc->dev->dev_private;
862 882 int ret;
863 883  
864 884 /* If no cursor support, replicate drm's return value */
865   - if (!priv->variant->has_spu_adv_reg)
  885 + if (!dcrtc->variant->has_spu_adv_reg)
866 886 return -EFAULT;
867 887  
868 888 mutex_lock(&dev->struct_mutex);
... ... @@ -888,6 +908,10 @@
888 908 if (!IS_ERR(dcrtc->clk))
889 909 clk_disable_unprepare(dcrtc->clk);
890 910  
  911 + writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ENA);
  912 +
  913 + of_node_put(dcrtc->crtc.port);
  914 +
891 915 kfree(dcrtc);
892 916 }
893 917  
894 918  
895 919  
896 920  
... ... @@ -1027,19 +1051,20 @@
1027 1051 return 0;
1028 1052 }
1029 1053  
1030   -int armada_drm_crtc_create(struct drm_device *dev, unsigned num,
1031   - struct resource *res)
  1054 +int armada_drm_crtc_create(struct drm_device *drm, struct device *dev,
  1055 + struct resource *res, int irq, const struct armada_variant *variant,
  1056 + struct device_node *port)
1032 1057 {
1033   - struct armada_private *priv = dev->dev_private;
  1058 + struct armada_private *priv = drm->dev_private;
1034 1059 struct armada_crtc *dcrtc;
1035 1060 void __iomem *base;
1036 1061 int ret;
1037 1062  
1038   - ret = armada_drm_crtc_create_properties(dev);
  1063 + ret = armada_drm_crtc_create_properties(drm);
1039 1064 if (ret)
1040 1065 return ret;
1041 1066  
1042   - base = devm_request_and_ioremap(dev->dev, res);
  1067 + base = devm_request_and_ioremap(dev, res);
1043 1068 if (!base) {
1044 1069 DRM_ERROR("failed to ioremap register\n");
1045 1070 return -ENOMEM;
1046 1071  
... ... @@ -1051,8 +1076,12 @@
1051 1076 return -ENOMEM;
1052 1077 }
1053 1078  
  1079 + if (dev != drm->dev)
  1080 + dev_set_drvdata(dev, dcrtc);
  1081 +
  1082 + dcrtc->variant = variant;
1054 1083 dcrtc->base = base;
1055   - dcrtc->num = num;
  1084 + dcrtc->num = drm->mode_config.num_crtc;
1056 1085 dcrtc->clk = ERR_PTR(-EINVAL);
1057 1086 dcrtc->csc_yuv_mode = CSC_AUTO;
1058 1087 dcrtc->csc_rgb_mode = CSC_AUTO;
1059 1088  
... ... @@ -1074,9 +1103,18 @@
1074 1103 CFG_PDWN64x66, dcrtc->base + LCD_SPU_SRAM_PARA1);
1075 1104 writel_relaxed(0x2032ff81, dcrtc->base + LCD_SPU_DMA_CTRL1);
1076 1105 writel_relaxed(0x00000000, dcrtc->base + LCD_SPU_GRA_OVSA_HPXL_VLN);
  1106 + writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
  1107 + writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
1077 1108  
1078   - if (priv->variant->crtc_init) {
1079   - ret = priv->variant->crtc_init(dcrtc);
  1109 + ret = devm_request_irq(dev, irq, armada_drm_irq, 0, "armada_drm_crtc",
  1110 + dcrtc);
  1111 + if (ret < 0) {
  1112 + kfree(dcrtc);
  1113 + return ret;
  1114 + }
  1115 +
  1116 + if (dcrtc->variant->init) {
  1117 + ret = dcrtc->variant->init(dcrtc, dev);
1080 1118 if (ret) {
1081 1119 kfree(dcrtc);
1082 1120 return ret;
... ... @@ -1088,7 +1126,8 @@
1088 1126  
1089 1127 priv->dcrtc[dcrtc->num] = dcrtc;
1090 1128  
1091   - drm_crtc_init(dev, &dcrtc->crtc, &armada_crtc_funcs);
  1129 + dcrtc->crtc.port = port;
  1130 + drm_crtc_init(drm, &dcrtc->crtc, &armada_crtc_funcs);
1092 1131 drm_crtc_helper_add(&dcrtc->crtc, &armada_crtc_helper_funcs);
1093 1132  
1094 1133 drm_object_attach_property(&dcrtc->crtc.base, priv->csc_yuv_prop,
1095 1134  
... ... @@ -1096,6 +1135,108 @@
1096 1135 drm_object_attach_property(&dcrtc->crtc.base, priv->csc_rgb_prop,
1097 1136 dcrtc->csc_rgb_mode);
1098 1137  
1099   - return armada_overlay_plane_create(dev, 1 << dcrtc->num);
  1138 + return armada_overlay_plane_create(drm, 1 << dcrtc->num);
1100 1139 }
  1140 +
  1141 +static int
  1142 +armada_lcd_bind(struct device *dev, struct device *master, void *data)
  1143 +{
  1144 + struct platform_device *pdev = to_platform_device(dev);
  1145 + struct drm_device *drm = data;
  1146 + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  1147 + int irq = platform_get_irq(pdev, 0);
  1148 + const struct armada_variant *variant;
  1149 + struct device_node *port = NULL;
  1150 +
  1151 + if (irq < 0)
  1152 + return irq;
  1153 +
  1154 + if (!dev->of_node) {
  1155 + const struct platform_device_id *id;
  1156 +
  1157 + id = platform_get_device_id(pdev);
  1158 + if (!id)
  1159 + return -ENXIO;
  1160 +
  1161 + variant = (const struct armada_variant *)id->driver_data;
  1162 + } else {
  1163 + const struct of_device_id *match;
  1164 + struct device_node *np, *parent = dev->of_node;
  1165 +
  1166 + match = of_match_device(dev->driver->of_match_table, dev);
  1167 + if (!match)
  1168 + return -ENXIO;
  1169 +
  1170 + np = of_get_child_by_name(parent, "ports");
  1171 + if (np)
  1172 + parent = np;
  1173 + port = of_get_child_by_name(parent, "port");
  1174 + of_node_put(np);
  1175 + if (!port) {
  1176 + dev_err(dev, "no port node found in %s\n",
  1177 + parent->full_name);
  1178 + return -ENXIO;
  1179 + }
  1180 +
  1181 + variant = match->data;
  1182 + }
  1183 +
  1184 + return armada_drm_crtc_create(drm, dev, res, irq, variant, port);
  1185 +}
  1186 +
  1187 +static void
  1188 +armada_lcd_unbind(struct device *dev, struct device *master, void *data)
  1189 +{
  1190 + struct armada_crtc *dcrtc = dev_get_drvdata(dev);
  1191 +
  1192 + armada_drm_crtc_destroy(&dcrtc->crtc);
  1193 +}
  1194 +
  1195 +static const struct component_ops armada_lcd_ops = {
  1196 + .bind = armada_lcd_bind,
  1197 + .unbind = armada_lcd_unbind,
  1198 +};
  1199 +
  1200 +static int armada_lcd_probe(struct platform_device *pdev)
  1201 +{
  1202 + return component_add(&pdev->dev, &armada_lcd_ops);
  1203 +}
  1204 +
  1205 +static int armada_lcd_remove(struct platform_device *pdev)
  1206 +{
  1207 + component_del(&pdev->dev, &armada_lcd_ops);
  1208 + return 0;
  1209 +}
  1210 +
  1211 +static struct of_device_id armada_lcd_of_match[] = {
  1212 + {
  1213 + .compatible = "marvell,dove-lcd",
  1214 + .data = &armada510_ops,
  1215 + },
  1216 + {}
  1217 +};
  1218 +MODULE_DEVICE_TABLE(of, armada_lcd_of_match);
  1219 +
  1220 +static const struct platform_device_id armada_lcd_platform_ids[] = {
  1221 + {
  1222 + .name = "armada-lcd",
  1223 + .driver_data = (unsigned long)&armada510_ops,
  1224 + }, {
  1225 + .name = "armada-510-lcd",
  1226 + .driver_data = (unsigned long)&armada510_ops,
  1227 + },
  1228 + { },
  1229 +};
  1230 +MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
  1231 +
  1232 +struct platform_driver armada_lcd_platform_driver = {
  1233 + .probe = armada_lcd_probe,
  1234 + .remove = armada_lcd_remove,
  1235 + .driver = {
  1236 + .name = "armada-lcd",
  1237 + .owner = THIS_MODULE,
  1238 + .of_match_table = armada_lcd_of_match,
  1239 + },
  1240 + .id_table = armada_lcd_platform_ids,
  1241 +};
drivers/gpu/drm/armada/armada_crtc.h
... ... @@ -32,12 +32,15 @@
32 32 armada_reg_queue_mod(_r, _i, 0, 0, ~0)
33 33  
34 34 struct armada_frame_work;
  35 +struct armada_variant;
35 36  
36 37 struct armada_crtc {
37 38 struct drm_crtc crtc;
  39 + const struct armada_variant *variant;
38 40 unsigned num;
39 41 void __iomem *base;
40 42 struct clk *clk;
  43 + struct clk *extclk[2];
41 44 struct {
42 45 uint32_t spu_v_h_total;
43 46 uint32_t spu_v_porch;
44 47  
45 48  
... ... @@ -72,13 +75,17 @@
72 75 };
73 76 #define drm_to_armada_crtc(c) container_of(c, struct armada_crtc, crtc)
74 77  
75   -int armada_drm_crtc_create(struct drm_device *, unsigned, struct resource *);
  78 +struct device_node;
  79 +int armada_drm_crtc_create(struct drm_device *, struct device *,
  80 + struct resource *, int, const struct armada_variant *,
  81 + struct device_node *);
76 82 void armada_drm_crtc_gamma_set(struct drm_crtc *, u16, u16, u16, int);
77 83 void armada_drm_crtc_gamma_get(struct drm_crtc *, u16 *, u16 *, u16 *, int);
78   -void armada_drm_crtc_irq(struct armada_crtc *, u32);
79 84 void armada_drm_crtc_disable_irq(struct armada_crtc *, u32);
80 85 void armada_drm_crtc_enable_irq(struct armada_crtc *, u32);
81 86 void armada_drm_crtc_update_regs(struct armada_crtc *, struct armada_regs *);
  87 +
  88 +extern struct platform_driver armada_lcd_platform_driver;
82 89  
83 90 #endif
drivers/gpu/drm/armada/armada_drm.h
... ... @@ -59,26 +59,23 @@
59 59 struct armada_private;
60 60  
61 61 struct armada_variant {
62   - bool has_spu_adv_reg;
  62 + bool has_spu_adv_reg;
63 63 uint32_t spu_adv_reg;
64   - int (*init)(struct armada_private *, struct device *);
65   - int (*crtc_init)(struct armada_crtc *);
66   - int (*crtc_compute_clock)(struct armada_crtc *,
67   - const struct drm_display_mode *,
68   - uint32_t *);
  64 + int (*init)(struct armada_crtc *, struct device *);
  65 + int (*compute_clock)(struct armada_crtc *,
  66 + const struct drm_display_mode *,
  67 + uint32_t *);
69 68 };
70 69  
71 70 /* Variant ops */
72 71 extern const struct armada_variant armada510_ops;
73 72  
74 73 struct armada_private {
75   - const struct armada_variant *variant;
76 74 struct work_struct fb_unref_work;
77 75 DECLARE_KFIFO(fb_unref, struct drm_framebuffer *, 8);
78 76 struct drm_fb_helper *fbdev;
79 77 struct armada_crtc *dcrtc[2];
80 78 struct drm_mm linear;
81   - struct clk *extclk[2];
82 79 struct drm_property *csc_yuv_prop;
83 80 struct drm_property *csc_rgb_prop;
84 81 struct drm_property *colorkey_prop;
drivers/gpu/drm/armada/armada_drv.c
... ... @@ -6,7 +6,9 @@
6 6 * published by the Free Software Foundation.
7 7 */
8 8 #include <linux/clk.h>
  9 +#include <linux/component.h>
9 10 #include <linux/module.h>
  11 +#include <linux/of_graph.h>
10 12 #include <drm/drmP.h>
11 13 #include <drm/drm_crtc_helper.h>
12 14 #include "armada_crtc.h"
... ... @@ -52,6 +54,11 @@
52 54 };
53 55 #endif
54 56  
  57 +static bool is_componentized(struct device *dev)
  58 +{
  59 + return dev->of_node || dev->platform_data;
  60 +}
  61 +
55 62 static void armada_drm_unref_work(struct work_struct *work)
56 63 {
57 64 struct armada_private *priv =
... ... @@ -85,6 +92,7 @@
85 92 static int armada_drm_load(struct drm_device *dev, unsigned long flags)
86 93 {
87 94 const struct platform_device_id *id;
  95 + const struct armada_variant *variant;
88 96 struct armada_private *priv;
89 97 struct resource *res[ARRAY_SIZE(priv->dcrtc)];
90 98 struct resource *mem = NULL;
... ... @@ -107,7 +115,7 @@
107 115 return -EINVAL;
108 116 }
109 117  
110   - if (!res[0] || !mem)
  118 + if (!mem)
111 119 return -ENXIO;
112 120  
113 121 if (!devm_request_mem_region(dev->dev, mem->start,
114 122  
... ... @@ -128,12 +136,8 @@
128 136 if (!id)
129 137 return -ENXIO;
130 138  
131   - priv->variant = (struct armada_variant *)id->driver_data;
  139 + variant = (const struct armada_variant *)id->driver_data;
132 140  
133   - ret = priv->variant->init(priv, dev->dev);
134   - if (ret)
135   - return ret;
136   -
137 141 INIT_WORK(&priv->fb_unref_work, armada_drm_unref_work);
138 142 INIT_KFIFO(priv->fb_unref);
139 143  
140 144  
141 145  
142 146  
143 147  
144 148  
145 149  
146 150  
147 151  
148 152  
... ... @@ -155,40 +159,50 @@
155 159  
156 160 /* Create all LCD controllers */
157 161 for (n = 0; n < ARRAY_SIZE(priv->dcrtc); n++) {
  162 + int irq;
  163 +
158 164 if (!res[n])
159 165 break;
160 166  
161   - ret = armada_drm_crtc_create(dev, n, res[n]);
  167 + irq = platform_get_irq(dev->platformdev, n);
  168 + if (irq < 0)
  169 + goto err_kms;
  170 +
  171 + ret = armada_drm_crtc_create(dev, dev->dev, res[n], irq,
  172 + variant, NULL);
162 173 if (ret)
163 174 goto err_kms;
164 175 }
165 176  
  177 + if (is_componentized(dev->dev)) {
  178 + ret = component_bind_all(dev->dev, dev);
  179 + if (ret)
  180 + goto err_kms;
  181 + } else {
166 182 #ifdef CONFIG_DRM_ARMADA_TDA1998X
167   - ret = armada_drm_connector_slave_create(dev, &tda19988_config);
168   - if (ret)
169   - goto err_kms;
  183 + ret = armada_drm_connector_slave_create(dev, &tda19988_config);
  184 + if (ret)
  185 + goto err_kms;
170 186 #endif
  187 + }
171 188  
172   - ret = drm_vblank_init(dev, n);
  189 + ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
173 190 if (ret)
174   - goto err_kms;
  191 + goto err_comp;
175 192  
176   - ret = drm_irq_install(dev, platform_get_irq(dev->platformdev, 0));
177   - if (ret)
178   - goto err_kms;
179   -
180 193 dev->vblank_disable_allowed = 1;
181 194  
182 195 ret = armada_fbdev_init(dev);
183 196 if (ret)
184   - goto err_irq;
  197 + goto err_comp;
185 198  
186 199 drm_kms_helper_poll_init(dev);
187 200  
188 201 return 0;
189 202  
190   - err_irq:
191   - drm_irq_uninstall(dev);
  203 + err_comp:
  204 + if (is_componentized(dev->dev))
  205 + component_unbind_all(dev->dev, dev);
192 206 err_kms:
193 207 drm_mode_config_cleanup(dev);
194 208 drm_mm_takedown(&priv->linear);
... ... @@ -203,7 +217,10 @@
203 217  
204 218 drm_kms_helper_poll_fini(dev);
205 219 armada_fbdev_fini(dev);
206   - drm_irq_uninstall(dev);
  220 +
  221 + if (is_componentized(dev->dev))
  222 + component_unbind_all(dev->dev, dev);
  223 +
207 224 drm_mode_config_cleanup(dev);
208 225 drm_mm_takedown(&priv->linear);
209 226 flush_work(&priv->fb_unref_work);
... ... @@ -259,52 +276,6 @@
259 276 armada_drm_crtc_disable_irq(priv->dcrtc[crtc], VSYNC_IRQ_ENA);
260 277 }
261 278  
262   -static irqreturn_t armada_drm_irq_handler(int irq, void *arg)
263   -{
264   - struct drm_device *dev = arg;
265   - struct armada_private *priv = dev->dev_private;
266   - struct armada_crtc *dcrtc = priv->dcrtc[0];
267   - uint32_t v, stat = readl_relaxed(dcrtc->base + LCD_SPU_IRQ_ISR);
268   - irqreturn_t handled = IRQ_NONE;
269   -
270   - /*
271   - * This is rediculous - rather than writing bits to clear, we
272   - * have to set the actual status register value. This is racy.
273   - */
274   - writel_relaxed(0, dcrtc->base + LCD_SPU_IRQ_ISR);
275   -
276   - /* Mask out those interrupts we haven't enabled */
277   - v = stat & dcrtc->irq_ena;
278   -
279   - if (v & (VSYNC_IRQ|GRA_FRAME_IRQ|DUMB_FRAMEDONE)) {
280   - armada_drm_crtc_irq(dcrtc, stat);
281   - handled = IRQ_HANDLED;
282   - }
283   -
284   - return handled;
285   -}
286   -
287   -static int armada_drm_irq_postinstall(struct drm_device *dev)
288   -{
289   - struct armada_private *priv = dev->dev_private;
290   - struct armada_crtc *dcrtc = priv->dcrtc[0];
291   -
292   - spin_lock_irq(&dev->vbl_lock);
293   - writel_relaxed(dcrtc->irq_ena, dcrtc->base + LCD_SPU_IRQ_ENA);
294   - writel(0, dcrtc->base + LCD_SPU_IRQ_ISR);
295   - spin_unlock_irq(&dev->vbl_lock);
296   -
297   - return 0;
298   -}
299   -
300   -static void armada_drm_irq_uninstall(struct drm_device *dev)
301   -{
302   - struct armada_private *priv = dev->dev_private;
303   - struct armada_crtc *dcrtc = priv->dcrtc[0];
304   -
305   - writel(0, dcrtc->base + LCD_SPU_IRQ_ENA);
306   -}
307   -
308 279 static struct drm_ioctl_desc armada_ioctls[] = {
309 280 DRM_IOCTL_DEF_DRV(ARMADA_GEM_CREATE, armada_gem_create_ioctl,
310 281 DRM_UNLOCKED),
... ... @@ -340,9 +311,6 @@
340 311 .get_vblank_counter = drm_vblank_count,
341 312 .enable_vblank = armada_drm_enable_vblank,
342 313 .disable_vblank = armada_drm_disable_vblank,
343   - .irq_handler = armada_drm_irq_handler,
344   - .irq_postinstall = armada_drm_irq_postinstall,
345   - .irq_uninstall = armada_drm_irq_uninstall,
346 314 #ifdef CONFIG_DEBUG_FS
347 315 .debugfs_init = armada_drm_debugfs_init,
348 316 .debugfs_cleanup = armada_drm_debugfs_cleanup,
349 317  
350 318  
351 319  
... ... @@ -362,19 +330,140 @@
362 330 .desc = "Armada SoC DRM",
363 331 .date = "20120730",
364 332 .driver_features = DRIVER_GEM | DRIVER_MODESET |
365   - DRIVER_HAVE_IRQ | DRIVER_PRIME,
  333 + DRIVER_PRIME,
366 334 .ioctls = armada_ioctls,
367 335 .fops = &armada_drm_fops,
368 336 };
369 337  
  338 +static int armada_drm_bind(struct device *dev)
  339 +{
  340 + return drm_platform_init(&armada_drm_driver, to_platform_device(dev));
  341 +}
  342 +
  343 +static void armada_drm_unbind(struct device *dev)
  344 +{
  345 + drm_put_dev(dev_get_drvdata(dev));
  346 +}
  347 +
  348 +static int compare_of(struct device *dev, void *data)
  349 +{
  350 + return dev->of_node == data;
  351 +}
  352 +
  353 +static int compare_dev_name(struct device *dev, void *data)
  354 +{
  355 + const char *name = data;
  356 + return !strcmp(dev_name(dev), name);
  357 +}
  358 +
  359 +static void armada_add_endpoints(struct device *dev,
  360 + struct component_match **match, struct device_node *port)
  361 +{
  362 + struct device_node *ep, *remote;
  363 +
  364 + for_each_child_of_node(port, ep) {
  365 + remote = of_graph_get_remote_port_parent(ep);
  366 + if (!remote || !of_device_is_available(remote)) {
  367 + of_node_put(remote);
  368 + continue;
  369 + } else if (!of_device_is_available(remote->parent)) {
  370 + dev_warn(dev, "parent device of %s is not available\n",
  371 + remote->full_name);
  372 + of_node_put(remote);
  373 + continue;
  374 + }
  375 +
  376 + component_match_add(dev, match, compare_of, remote);
  377 + of_node_put(remote);
  378 + }
  379 +}
  380 +
  381 +static int armada_drm_find_components(struct device *dev,
  382 + struct component_match **match)
  383 +{
  384 + struct device_node *port;
  385 + int i;
  386 +
  387 + if (dev->of_node) {
  388 + struct device_node *np = dev->of_node;
  389 +
  390 + for (i = 0; ; i++) {
  391 + port = of_parse_phandle(np, "ports", i);
  392 + if (!port)
  393 + break;
  394 +
  395 + component_match_add(dev, match, compare_of, port);
  396 + of_node_put(port);
  397 + }
  398 +
  399 + if (i == 0) {
  400 + dev_err(dev, "missing 'ports' property\n");
  401 + return -ENODEV;
  402 + }
  403 +
  404 + for (i = 0; ; i++) {
  405 + port = of_parse_phandle(np, "ports", i);
  406 + if (!port)
  407 + break;
  408 +
  409 + armada_add_endpoints(dev, match, port);
  410 + of_node_put(port);
  411 + }
  412 + } else if (dev->platform_data) {
  413 + char **devices = dev->platform_data;
  414 + struct device *d;
  415 +
  416 + for (i = 0; devices[i]; i++)
  417 + component_match_add(dev, match, compare_dev_name,
  418 + devices[i]);
  419 +
  420 + if (i == 0) {
  421 + dev_err(dev, "missing 'ports' property\n");
  422 + return -ENODEV;
  423 + }
  424 +
  425 + for (i = 0; devices[i]; i++) {
  426 + d = bus_find_device_by_name(&platform_bus_type, NULL,
  427 + devices[i]);
  428 + if (d && d->of_node) {
  429 + for_each_child_of_node(d->of_node, port)
  430 + armada_add_endpoints(dev, match, port);
  431 + }
  432 + put_device(d);
  433 + }
  434 + }
  435 +
  436 + return 0;
  437 +}
  438 +
  439 +static const struct component_master_ops armada_master_ops = {
  440 + .bind = armada_drm_bind,
  441 + .unbind = armada_drm_unbind,
  442 +};
  443 +
370 444 static int armada_drm_probe(struct platform_device *pdev)
371 445 {
372   - return drm_platform_init(&armada_drm_driver, pdev);
  446 + if (is_componentized(&pdev->dev)) {
  447 + struct component_match *match = NULL;
  448 + int ret;
  449 +
  450 + ret = armada_drm_find_components(&pdev->dev, &match);
  451 + if (ret < 0)
  452 + return ret;
  453 +
  454 + return component_master_add_with_match(&pdev->dev,
  455 + &armada_master_ops, match);
  456 + } else {
  457 + return drm_platform_init(&armada_drm_driver, pdev);
  458 + }
373 459 }
374 460  
375 461 static int armada_drm_remove(struct platform_device *pdev)
376 462 {
377   - drm_put_dev(platform_get_drvdata(pdev));
  463 + if (is_componentized(&pdev->dev))
  464 + component_master_del(&pdev->dev, &armada_master_ops);
  465 + else
  466 + drm_put_dev(platform_get_drvdata(pdev));
378 467 return 0;
379 468 }
380 469  
381 470  
382 471  
... ... @@ -402,14 +491,24 @@
402 491  
403 492 static int __init armada_drm_init(void)
404 493 {
  494 + int ret;
  495 +
405 496 armada_drm_driver.num_ioctls = ARRAY_SIZE(armada_ioctls);
406   - 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;
407 505 }
408 506 module_init(armada_drm_init);
409 507  
410 508 static void __exit armada_drm_exit(void)
411 509 {
412 510 platform_driver_unregister(&armada_drm_platform_driver);
  511 + platform_driver_unregister(&armada_lcd_platform_driver);
413 512 }
414 513 module_exit(armada_drm_exit);
415 514  
drivers/gpu/drm/drm_of.c
  1 +#include <linux/export.h>
  2 +#include <linux/list.h>
  3 +#include <linux/of_graph.h>
  4 +#include <drm/drmP.h>
  5 +#include <drm/drm_crtc.h>
  6 +#include <drm/drm_of.h>
  7 +
  8 +/**
  9 + * drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
  10 + * @dev: DRM device
  11 + * @port: port OF node
  12 + *
  13 + * Given a port OF node, return the possible mask of the corresponding
  14 + * CRTC within a device's list of CRTCs. Returns zero if not found.
  15 + */
  16 +static uint32_t drm_crtc_port_mask(struct drm_device *dev,
  17 + struct device_node *port)
  18 +{
  19 + unsigned int index = 0;
  20 + struct drm_crtc *tmp;
  21 +
  22 + list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
  23 + if (tmp->port == port)
  24 + return 1 << index;
  25 +
  26 + index++;
  27 + }
  28 +
  29 + return 0;
  30 +}
  31 +
  32 +/**
  33 + * drm_of_find_possible_crtcs - find the possible CRTCs for an encoder port
  34 + * @dev: DRM device
  35 + * @port: encoder port to scan for endpoints
  36 + *
  37 + * Scan all endpoints attached to a port, locate their attached CRTCs,
  38 + * and generate the DRM mask of CRTCs which may be attached to this
  39 + * encoder.
  40 + *
  41 + * See Documentation/devicetree/bindings/graph.txt for the bindings.
  42 + */
  43 +uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
  44 + struct device_node *port)
  45 +{
  46 + struct device_node *remote_port, *ep = NULL;
  47 + uint32_t possible_crtcs = 0;
  48 +
  49 + do {
  50 + ep = of_graph_get_next_endpoint(port, ep);
  51 + if (!ep)
  52 + break;
  53 +
  54 + remote_port = of_graph_get_remote_port(ep);
  55 + if (!remote_port) {
  56 + of_node_put(ep);
  57 + return 0;
  58 + }
  59 +
  60 + possible_crtcs |= drm_crtc_port_mask(dev, remote_port);
  61 +
  62 + of_node_put(remote_port);
  63 + } while (1);
  64 +
  65 + return possible_crtcs;
  66 +}
  67 +EXPORT_SYMBOL(drm_of_find_possible_crtcs);
include/drm/drm_crtc.h
... ... @@ -41,6 +41,7 @@
41 41 struct drm_object_properties;
42 42 struct drm_file;
43 43 struct drm_clip_rect;
  44 +struct device_node;
44 45  
45 46 #define DRM_MODE_OBJECT_CRTC 0xcccccccc
46 47 #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
... ... @@ -314,6 +315,7 @@
314 315 */
315 316 struct drm_crtc {
316 317 struct drm_device *dev;
  318 + struct device_node *port;
317 319 struct list_head head;
318 320  
319 321 /**
include/drm/drm_of.h
  1 +#ifndef __DRM_OF_H__
  2 +#define __DRM_OF_H__
  3 +
  4 +struct drm_device;
  5 +struct device_node;
  6 +
  7 +#ifdef CONFIG_OF
  8 +extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
  9 + struct device_node *port);
  10 +#else
  11 +static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
  12 + struct device_node *port)
  13 +{
  14 + return 0;
  15 +}
  16 +#endif
  17 +
  18 +#endif /* __DRM_OF_H__ */
include/linux/component.h
... ... @@ -29,5 +29,12 @@
29 29 int component_master_add_child(struct master *master,
30 30 int (*compare)(struct device *, void *), void *compare_data);
31 31  
  32 +struct component_match;
  33 +
  34 +int component_master_add_with_match(struct device *,
  35 + const struct component_master_ops *, struct component_match *);
  36 +void component_match_add(struct device *, struct component_match **,
  37 + int (*compare)(struct device *, void *), void *compare_data);
  38 +
32 39 #endif