77 * Copyright (C) 2014 Endless Mobile
88 */
99
10- #include <linux/module .h>
10+ #include <linux/component .h>
1111#include <linux/dma-mapping.h>
12+ #include <linux/module.h>
1213#include <linux/of_address.h>
1314#include <linux/of_device.h>
1415
@@ -390,46 +391,55 @@ static int apple_get_fb_resource(struct device *dev, const char *name,
390391 return ret ;
391392}
392393
394+ static const struct of_device_id apple_dcp_id_tbl [] = {
395+ { .compatible = "apple,dcp" },
396+ {},
397+ };
393398
394- static int apple_platform_probe (struct platform_device * pdev )
399+ static int apple_drm_init_dcp (struct device * dev )
395400{
396- struct device * dev = & pdev -> dev ;
397- struct apple_drm_private * apple ;
398- struct resource fb_r ;
399- resource_size_t fb_size ;
401+ struct apple_drm_private * apple = dev_get_drvdata (dev );
400402 struct platform_device * dcp [MAX_COPROCESSORS ];
401- int ret , nr_dcp , i ;
402-
403- for (nr_dcp = 0 ; nr_dcp < MAX_COPROCESSORS ; ++ nr_dcp ) {
404- struct device_node * np ;
405- struct device_link * dcp_link ;
403+ struct device_node * np ;
404+ int ret , num_dcp = 0 ;
406405
407- np = of_parse_phandle ( dev -> of_node , "apple,coprocessors" ,
408- nr_dcp );
409-
410- if (! np )
411- break ;
406+ for_each_matching_node ( np , apple_dcp_id_tbl ) {
407+ if (! of_device_is_available ( np )) {
408+ of_node_put ( np );
409+ continue ;
410+ }
412411
413- dcp [nr_dcp ] = of_find_device_by_node (np );
412+ dcp [num_dcp ] = of_find_device_by_node (np );
413+ of_node_put (np );
414+ if (!dcp [num_dcp ])
415+ continue ;
414416
415- if (!dcp [nr_dcp ])
416- return - ENODEV ;
417+ ret = apple_probe_per_dcp (dev , & apple -> drm , dcp [num_dcp ],
418+ num_dcp );
419+ if (ret )
420+ continue ;
417421
418- dcp_link = device_link_add (dev , & dcp [nr_dcp ]-> dev ,
419- DL_FLAG_AUTOREMOVE_CONSUMER );
420- if (!dcp_link ) {
421- dev_err (dev , "Failed to link to DCP %d device" , nr_dcp );
422- return - EINVAL ;
423- }
422+ ret = dcp_start (dcp [num_dcp ]);
423+ if (ret )
424+ continue ;
424425
425- if (dcp_link -> supplier -> links .status != DL_DEV_DRIVER_BOUND )
426- return - EPROBE_DEFER ;
426+ num_dcp ++ ;
427427 }
428428
429- /* Need at least 1 DCP for a display subsystem */
430- if (nr_dcp < 1 )
429+ if (num_dcp < 1 )
431430 return - ENODEV ;
432431
432+
433+ return 0 ;
434+ }
435+
436+ static int apple_drm_init (struct device * dev )
437+ {
438+ struct apple_drm_private * apple ;
439+ struct resource fb_r ;
440+ resource_size_t fb_size ;
441+ int ret ;
442+
433443 ret = dma_set_mask_and_coherent (dev , DMA_BIT_MASK (36 ));
434444 if (ret )
435445 return ret ;
@@ -438,21 +448,25 @@ static int apple_platform_probe(struct platform_device *pdev)
438448 if (ret )
439449 return ret ;
440450
441- fb_size = fb_r .end - fb_r .start + 1 ;
442- ret = drm_aperture_remove_conflicting_framebuffers (fb_r .start , fb_size ,
443- false, & apple_drm_driver );
444- if (ret ) {
445- dev_err (dev , "Failed remove fb: %d\n" , ret );
446- return ret ;
447- }
448-
449451 apple = devm_drm_dev_alloc (dev , & apple_drm_driver ,
450452 struct apple_drm_private , drm );
451453 if (IS_ERR (apple ))
452454 return PTR_ERR (apple );
453455
454456 dev_set_drvdata (dev , apple );
455457
458+ ret = component_bind_all (dev , apple );
459+ if (ret )
460+ return ret ;
461+
462+ fb_size = fb_r .end - fb_r .start + 1 ;
463+ ret = drm_aperture_remove_conflicting_framebuffers (fb_r .start , fb_size ,
464+ false, & apple_drm_driver );
465+ if (ret ) {
466+ dev_err (dev , "Failed remove fb: %d\n" , ret );
467+ goto err_unbind ;
468+ }
469+
456470 ret = drmm_mode_config_init (& apple -> drm );
457471 if (ret )
458472 goto err_unload ;
@@ -477,17 +491,9 @@ static int apple_platform_probe(struct platform_device *pdev)
477491 apple -> drm .mode_config .funcs = & apple_mode_config_funcs ;
478492 apple -> drm .mode_config .helper_private = & apple_mode_config_helpers ;
479493
480- for (i = 0 ; i < nr_dcp ; ++ i ) {
481- ret = apple_probe_per_dcp (dev , & apple -> drm , dcp [i ], i );
482-
483- if (ret )
484- goto err_unload ;
485-
486- ret = dcp_start (dcp [i ]);
487-
488- if (ret )
489- goto err_unload ;
490- }
494+ ret = apple_drm_init_dcp (dev );
495+ if (ret )
496+ goto err_unload ;
491497
492498 drm_mode_config_reset (& apple -> drm );
493499
@@ -501,14 +507,96 @@ static int apple_platform_probe(struct platform_device *pdev)
501507
502508err_unload :
503509 drm_dev_put (& apple -> drm );
510+ err_unbind :
511+ component_unbind_all (dev , NULL );
504512 return ret ;
505513}
506514
507- static int apple_platform_remove (struct platform_device * pdev )
515+ static void apple_drm_uninit (struct device * dev )
508516{
509- struct apple_drm_private * apple = platform_get_drvdata ( pdev );
517+ struct apple_drm_private * apple = dev_get_drvdata ( dev );
510518
511519 drm_dev_unregister (& apple -> drm );
520+ drm_atomic_helper_shutdown (& apple -> drm );
521+
522+ component_unbind_all (dev , NULL );
523+
524+ dev_set_drvdata (dev , NULL );
525+ }
526+
527+ static int apple_drm_bind (struct device * dev )
528+ {
529+ return apple_drm_init (dev );
530+ }
531+
532+ static void apple_drm_unbind (struct device * dev )
533+ {
534+ apple_drm_uninit (dev );
535+ }
536+
537+ const struct component_master_ops apple_drm_ops = {
538+ .bind = apple_drm_bind ,
539+ .unbind = apple_drm_unbind ,
540+ };
541+
542+ static const struct of_device_id apple_component_id_tbl [] = {
543+ { .compatible = "apple,dcp-piodma" },
544+ {},
545+ };
546+
547+ static int add_display_components (struct device * dev ,
548+ struct component_match * * matchptr )
549+ {
550+ struct device_node * np ;
551+
552+ for_each_matching_node (np , apple_component_id_tbl ) {
553+ if (of_device_is_available (np ))
554+ drm_of_component_match_add (dev , matchptr ,
555+ component_compare_of , np );
556+ of_node_put (np );
557+ }
558+
559+ return 0 ;
560+ }
561+
562+ static int add_dcp_components (struct device * dev ,
563+ struct component_match * * matchptr )
564+ {
565+ struct device_node * np ;
566+ int num = 0 ;
567+
568+ for_each_matching_node (np , apple_dcp_id_tbl ) {
569+ if (of_device_is_available (np )) {
570+ drm_of_component_match_add (dev , matchptr ,
571+ component_compare_of , np );
572+ num ++ ;
573+ }
574+ of_node_put (np );
575+ }
576+
577+ return num ;
578+ }
579+
580+ static int apple_platform_probe (struct platform_device * pdev )
581+ {
582+ struct device * mdev = & pdev -> dev ;
583+ struct component_match * match = NULL ;
584+ int num_dcp ;
585+
586+ /* add PIODMA mapper components */
587+ add_display_components (mdev , & match );
588+
589+ /* add DCP components, handle less than 1 as probe error */
590+ num_dcp = add_dcp_components (mdev , & match );
591+ if (num_dcp < 1 )
592+ return - ENODEV ;
593+
594+ return component_master_add_with_match (mdev , & apple_drm_ops , match );
595+ }
596+
597+ static int apple_platform_remove (struct platform_device * pdev )
598+ {
599+ component_master_del (& pdev -> dev , & apple_drm_ops );
512600
513601 return 0 ;
514602}
@@ -524,14 +612,19 @@ static int apple_platform_suspend(struct device *dev)
524612{
525613 struct apple_drm_private * apple = dev_get_drvdata (dev );
526614
527- return drm_mode_config_helper_suspend (& apple -> drm );
615+ if (apple )
616+ return drm_mode_config_helper_suspend (& apple -> drm );
617+
618+ return 0 ;
528619}
529620
530621static int apple_platform_resume (struct device * dev )
531622{
532623 struct apple_drm_private * apple = dev_get_drvdata (dev );
533624
534- drm_mode_config_helper_resume (& apple -> drm );
625+ if (apple )
626+ drm_mode_config_helper_resume (& apple -> drm );
627+
535628 return 0 ;
536629}
537630
0 commit comments