1 // SPDX-License-Identifier: GPL-2.0
6 #include <drm/drm_atomic.h>
7 #include <drm/drm_atomic_helper.h>
8 #include <drm/drm_bridge_connector.h>
9 #include <drm/drm_drv.h>
10 #include <drm/drm_fb_helper.h>
11 #include <drm/drm_gem_cma_helper.h>
12 #include <drm/drm_gem_framebuffer_helper.h>
13 #include <drm/drm_of.h>
14 #include <drm/drm_probe_helper.h>
15 #include <drm/drm_vblank.h>
20 DEFINE_DRM_GEM_CMA_FOPS(dcss_cma_fops
);
22 static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs
= {
23 .fb_create
= drm_gem_fb_create
,
24 .output_poll_changed
= drm_fb_helper_output_poll_changed
,
25 .atomic_check
= drm_atomic_helper_check
,
26 .atomic_commit
= drm_atomic_helper_commit
,
29 static struct drm_driver dcss_kms_driver
= {
30 .driver_features
= DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
31 .gem_free_object_unlocked
= drm_gem_cma_free_object
,
32 .gem_vm_ops
= &drm_gem_cma_vm_ops
,
33 .dumb_create
= drm_gem_cma_dumb_create
,
35 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
36 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
37 .gem_prime_import
= drm_gem_prime_import
,
38 .gem_prime_export
= drm_gem_prime_export
,
39 .gem_prime_get_sg_table
= drm_gem_cma_prime_get_sg_table
,
40 .gem_prime_import_sg_table
= drm_gem_cma_prime_import_sg_table
,
41 .gem_prime_vmap
= drm_gem_cma_prime_vmap
,
42 .gem_prime_vunmap
= drm_gem_cma_prime_vunmap
,
43 .gem_prime_mmap
= drm_gem_cma_prime_mmap
,
44 .fops
= &dcss_cma_fops
,
46 .desc
= "i.MX8MQ Display Subsystem",
53 static const struct drm_mode_config_helper_funcs dcss_mode_config_helpers
= {
54 .atomic_commit_tail
= drm_atomic_helper_commit_tail_rpm
,
57 static void dcss_kms_mode_config_init(struct dcss_kms_dev
*kms
)
59 struct drm_mode_config
*config
= &kms
->base
.mode_config
;
61 drm_mode_config_init(&kms
->base
);
63 config
->min_width
= 1;
64 config
->min_height
= 1;
65 config
->max_width
= 4096;
66 config
->max_height
= 4096;
67 config
->allow_fb_modifiers
= true;
68 config
->normalize_zpos
= true;
70 config
->funcs
= &dcss_drm_mode_config_funcs
;
71 config
->helper_private
= &dcss_mode_config_helpers
;
74 static const struct drm_encoder_funcs dcss_kms_simple_encoder_funcs
= {
75 .destroy
= drm_encoder_cleanup
,
78 static int dcss_kms_bridge_connector_init(struct dcss_kms_dev
*kms
)
80 struct drm_device
*ddev
= &kms
->base
;
81 struct drm_encoder
*encoder
= &kms
->encoder
;
82 struct drm_crtc
*crtc
= (struct drm_crtc
*)&kms
->crtc
;
83 struct drm_panel
*panel
;
84 struct drm_bridge
*bridge
;
87 ret
= drm_of_find_panel_or_bridge(ddev
->dev
->of_node
, 0, 0,
93 dev_err(ddev
->dev
, "No bridge found %d.\n", ret
);
97 encoder
->possible_crtcs
= drm_crtc_mask(crtc
);
99 ret
= drm_encoder_init(&kms
->base
, encoder
,
100 &dcss_kms_simple_encoder_funcs
,
101 DRM_MODE_ENCODER_NONE
, NULL
);
103 dev_err(ddev
->dev
, "Failed initializing encoder %d.\n", ret
);
107 ret
= drm_bridge_attach(encoder
, bridge
, NULL
,
108 DRM_BRIDGE_ATTACH_NO_CONNECTOR
);
110 dev_err(ddev
->dev
, "Unable to attach bridge %pOF\n",
115 kms
->connector
= drm_bridge_connector_init(ddev
, encoder
);
116 if (IS_ERR(kms
->connector
)) {
117 dev_err(ddev
->dev
, "Unable to create bridge connector.\n");
118 return PTR_ERR(kms
->connector
);
121 drm_connector_attach_encoder(kms
->connector
, encoder
);
126 struct dcss_kms_dev
*dcss_kms_attach(struct dcss_dev
*dcss
)
128 struct dcss_kms_dev
*kms
;
129 struct drm_device
*drm
;
130 struct dcss_crtc
*crtc
;
133 kms
= devm_drm_dev_alloc(dcss
->dev
, &dcss_kms_driver
,
134 struct dcss_kms_dev
, base
);
141 drm
->dev_private
= dcss
;
143 dcss_kms_mode_config_init(kms
);
145 ret
= drm_vblank_init(drm
, 1);
147 goto cleanup_mode_config
;
149 drm
->irq_enabled
= true;
151 ret
= dcss_kms_bridge_connector_init(kms
);
153 goto cleanup_mode_config
;
155 ret
= dcss_crtc_init(crtc
, drm
);
157 goto cleanup_mode_config
;
159 drm_mode_config_reset(drm
);
161 drm_kms_helper_poll_init(drm
);
163 drm_bridge_connector_enable_hpd(kms
->connector
);
165 ret
= drm_dev_register(drm
, 0);
169 drm_fbdev_generic_setup(drm
, 32);
174 drm_bridge_connector_disable_hpd(kms
->connector
);
175 drm_kms_helper_poll_fini(drm
);
176 dcss_crtc_deinit(crtc
, drm
);
179 drm_mode_config_cleanup(drm
);
180 drm
->dev_private
= NULL
;
185 void dcss_kms_detach(struct dcss_kms_dev
*kms
)
187 struct drm_device
*drm
= &kms
->base
;
189 drm_dev_unregister(drm
);
190 drm_bridge_connector_disable_hpd(kms
->connector
);
191 drm_kms_helper_poll_fini(drm
);
192 drm_atomic_helper_shutdown(drm
);
193 drm_crtc_vblank_off(&kms
->crtc
.base
);
194 drm
->irq_enabled
= false;
195 drm_mode_config_cleanup(drm
);
196 dcss_crtc_deinit(&kms
->crtc
, drm
);
197 drm
->dev_private
= NULL
;