8
8
*/
9
9
10
10
#include <linux/clk.h>
11
+ #include <linux/media-bus-format.h>
11
12
#include <linux/pm_runtime.h>
12
13
13
14
#include <drm/drm_crtc.h>
39
40
* CRTC
40
41
*/
41
42
43
+ static const struct {
44
+ u32 fmt ;
45
+ u32 ldmt1r ;
46
+ } shmob_drm_bus_fmts [] = {
47
+ { MEDIA_BUS_FMT_RGB888_3X8 , LDMT1R_MIFTYP_RGB8 },
48
+ { MEDIA_BUS_FMT_RGB666_2X9_BE , LDMT1R_MIFTYP_RGB9 },
49
+ { MEDIA_BUS_FMT_RGB888_2X12_BE , LDMT1R_MIFTYP_RGB12A },
50
+ { MEDIA_BUS_FMT_RGB444_1X12 , LDMT1R_MIFTYP_RGB12B },
51
+ { MEDIA_BUS_FMT_RGB565_1X16 , LDMT1R_MIFTYP_RGB16 },
52
+ { MEDIA_BUS_FMT_RGB666_1X18 , LDMT1R_MIFTYP_RGB18 },
53
+ { MEDIA_BUS_FMT_RGB888_1X24 , LDMT1R_MIFTYP_RGB24 },
54
+ { MEDIA_BUS_FMT_UYVY8_1X16 , LDMT1R_MIFTYP_YCBCR },
55
+ };
56
+
42
57
static void shmob_drm_crtc_setup_geometry (struct shmob_drm_crtc * scrtc )
43
58
{
44
59
struct drm_crtc * crtc = & scrtc -> crtc ;
45
60
struct shmob_drm_device * sdev = to_shmob_device (crtc -> dev );
46
- enum display_flags dpy_flags = sdev -> connector . mode -> flags ;
61
+ const struct drm_display_info * info = & sdev -> connector -> display_info ;
47
62
const struct drm_display_mode * mode = & crtc -> mode ;
63
+ unsigned int i ;
48
64
u32 value ;
49
65
50
- value = sdev -> ldmt1r
51
- | ((mode -> flags & DRM_MODE_FLAG_PVSYNC ) ? 0 : LDMT1R_VPOL )
52
- | ((mode -> flags & DRM_MODE_FLAG_PHSYNC ) ? 0 : LDMT1R_HPOL )
53
- | ((dpy_flags & DISPLAY_FLAGS_PIXDATA_POSEDGE ) ? LDMT1R_DWPOL : 0 )
54
- | ((dpy_flags & DISPLAY_FLAGS_DE_LOW ) ? LDMT1R_DIPOL : 0 );
66
+ if (!info -> num_bus_formats || !info -> bus_formats ) {
67
+ dev_warn (sdev -> dev , "No bus format reported, using RGB888\n" );
68
+ value = LDMT1R_MIFTYP_RGB24 ;
69
+ } else {
70
+ for (i = 0 ; i < ARRAY_SIZE (shmob_drm_bus_fmts ); i ++ ) {
71
+ if (shmob_drm_bus_fmts [i ].fmt == info -> bus_formats [0 ])
72
+ break ;
73
+ }
74
+ if (i < ARRAY_SIZE (shmob_drm_bus_fmts )) {
75
+ value = shmob_drm_bus_fmts [i ].ldmt1r ;
76
+ } else {
77
+ dev_warn (sdev -> dev ,
78
+ "unsupported bus format 0x%x, using RGB888\n" ,
79
+ info -> bus_formats [0 ]);
80
+ value = LDMT1R_MIFTYP_RGB24 ;
81
+ }
82
+ }
55
83
84
+ if (info -> bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE )
85
+ value |= LDMT1R_DWPOL ;
86
+ if (info -> bus_flags & DRM_BUS_FLAG_DE_LOW )
87
+ value |= LDMT1R_DIPOL ;
88
+ if (mode -> flags & DRM_MODE_FLAG_NVSYNC )
89
+ value |= LDMT1R_VPOL ;
90
+ if (mode -> flags & DRM_MODE_FLAG_NHSYNC )
91
+ value |= LDMT1R_HPOL ;
56
92
lcdc_write (sdev , LDMT1R , value );
57
93
58
94
value = ((mode -> hdisplay / 8 ) << 16 ) /* HDCN */
@@ -479,7 +515,7 @@ static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder,
479
515
{
480
516
struct drm_device * dev = encoder -> dev ;
481
517
struct shmob_drm_device * sdev = to_shmob_device (dev );
482
- struct drm_connector * connector = & sdev -> connector . connector ;
518
+ struct drm_connector * connector = sdev -> connector ;
483
519
const struct drm_display_mode * panel_mode ;
484
520
485
521
if (list_empty (& connector -> modes )) {
@@ -581,6 +617,8 @@ static void shmob_drm_connector_destroy(struct drm_connector *connector)
581
617
{
582
618
drm_connector_unregister (connector );
583
619
drm_connector_cleanup (connector );
620
+
621
+ kfree (connector );
584
622
}
585
623
586
624
static const struct drm_connector_funcs connector_funcs = {
@@ -589,26 +627,74 @@ static const struct drm_connector_funcs connector_funcs = {
589
627
.destroy = shmob_drm_connector_destroy ,
590
628
};
591
629
592
- int shmob_drm_connector_create (struct shmob_drm_device * sdev ,
593
- struct drm_encoder * encoder )
630
+ static struct drm_connector *
631
+ shmob_drm_connector_init (struct shmob_drm_device * sdev ,
632
+ struct drm_encoder * encoder )
594
633
{
595
- struct shmob_drm_connector * scon = & sdev -> connector ;
596
- struct drm_connector * connector = & scon -> connector ;
634
+ u32 bus_fmt = sdev -> pdata -> iface .bus_fmt ;
635
+ struct shmob_drm_connector * scon ;
636
+ struct drm_connector * connector ;
637
+ struct drm_display_info * info ;
638
+ unsigned int i ;
597
639
int ret ;
598
640
641
+ for (i = 0 ; i < ARRAY_SIZE (shmob_drm_bus_fmts ); i ++ ) {
642
+ if (shmob_drm_bus_fmts [i ].fmt == bus_fmt )
643
+ break ;
644
+ }
645
+ if (i == ARRAY_SIZE (shmob_drm_bus_fmts )) {
646
+ dev_err (sdev -> dev , "unsupported bus format 0x%x\n" , bus_fmt );
647
+ return ERR_PTR (- EINVAL );
648
+ }
649
+
650
+ scon = kzalloc (sizeof (* scon ), GFP_KERNEL );
651
+ if (!scon )
652
+ return ERR_PTR (- ENOMEM );
653
+
654
+ connector = & scon -> connector ;
599
655
scon -> encoder = encoder ;
600
656
scon -> mode = & sdev -> pdata -> panel .mode ;
601
657
602
- connector -> display_info .width_mm = sdev -> pdata -> panel .width_mm ;
603
- connector -> display_info .height_mm = sdev -> pdata -> panel .height_mm ;
658
+ info = & connector -> display_info ;
659
+ info -> width_mm = sdev -> pdata -> panel .width_mm ;
660
+ info -> height_mm = sdev -> pdata -> panel .height_mm ;
661
+
662
+ if (scon -> mode -> flags & DISPLAY_FLAGS_PIXDATA_POSEDGE )
663
+ info -> bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE ;
664
+ if (scon -> mode -> flags & DISPLAY_FLAGS_DE_LOW )
665
+ info -> bus_flags |= DRM_BUS_FLAG_DE_LOW ;
666
+
667
+ ret = drm_display_info_set_bus_formats (info , & bus_fmt , 1 );
668
+ if (ret < 0 ) {
669
+ kfree (scon );
670
+ return ERR_PTR (ret );
671
+ }
604
672
605
673
ret = drm_connector_init (& sdev -> ddev , connector , & connector_funcs ,
606
674
DRM_MODE_CONNECTOR_DPI );
607
- if (ret < 0 )
608
- return ret ;
675
+ if (ret < 0 ) {
676
+ kfree (scon );
677
+ return ERR_PTR (ret );
678
+ }
609
679
610
680
drm_connector_helper_add (connector , & connector_helper_funcs );
611
681
682
+ return connector ;
683
+ }
684
+
685
+ int shmob_drm_connector_create (struct shmob_drm_device * sdev ,
686
+ struct drm_encoder * encoder )
687
+ {
688
+ struct drm_connector * connector ;
689
+ int ret ;
690
+
691
+ connector = shmob_drm_connector_init (sdev , encoder );
692
+ if (IS_ERR (connector )) {
693
+ dev_err (sdev -> dev , "failed to created connector: %pe\n" ,
694
+ connector );
695
+ return PTR_ERR (connector );
696
+ }
697
+
612
698
ret = drm_connector_attach_encoder (connector , encoder );
613
699
if (ret < 0 )
614
700
goto error ;
@@ -617,6 +703,8 @@ int shmob_drm_connector_create(struct shmob_drm_device *sdev,
617
703
drm_object_property_set_value (& connector -> base ,
618
704
sdev -> ddev .mode_config .dpms_property , DRM_MODE_DPMS_OFF );
619
705
706
+ sdev -> connector = connector ;
707
+
620
708
return 0 ;
621
709
622
710
error :
0 commit comments