Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/exynos: Split manager/display/subdrv

This patch splits display and manager from subdrv. The result is that
crtc functions can directly call into manager callbacks and encoder
functions can directly call into display callbacks. This will allow
us to remove the exynos_drm_hdmi shim and support mixer/hdmi & fimd/dp
with common code.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>

authored by

Sean Paul and committed by
Inki Dae
080be03d 3f283d93

+644 -712
+20 -30
drivers/gpu/drm/exynos/exynos_drm_connector.c
··· 23 23 drm_connector) 24 24 25 25 struct exynos_drm_connector { 26 - struct drm_connector drm_connector; 27 - uint32_t encoder_id; 28 - struct exynos_drm_manager *manager; 26 + struct drm_connector drm_connector; 27 + uint32_t encoder_id; 28 + struct exynos_drm_display *display; 29 29 }; 30 30 31 31 static int exynos_drm_connector_get_modes(struct drm_connector *connector) 32 32 { 33 33 struct exynos_drm_connector *exynos_connector = 34 34 to_exynos_connector(connector); 35 - struct exynos_drm_manager *manager = exynos_connector->manager; 36 - struct exynos_drm_display_ops *display_ops = manager->display_ops; 35 + struct exynos_drm_display *display = exynos_connector->display; 37 36 struct edid *edid = NULL; 38 37 unsigned int count = 0; 39 38 int ret; 40 - 41 - if (!display_ops) { 42 - DRM_DEBUG_KMS("display_ops is null.\n"); 43 - return 0; 44 - } 45 39 46 40 /* 47 41 * if get_edid() exists then get_edid() callback of hdmi side ··· 45 51 * P.S. in case of lcd panel, count is always 1 if success 46 52 * because lcd panel has only one mode. 47 53 */ 48 - if (display_ops->get_edid) { 49 - edid = display_ops->get_edid(manager->dev, connector); 54 + if (display->ops->get_edid) { 55 + edid = display->ops->get_edid(display, connector); 50 56 if (IS_ERR_OR_NULL(edid)) { 51 57 ret = PTR_ERR(edid); 52 58 edid = NULL; ··· 69 75 return 0; 70 76 } 71 77 72 - if (display_ops->get_panel) 73 - panel = display_ops->get_panel(manager->dev); 78 + if (display->ops->get_panel) 79 + panel = display->ops->get_panel(display); 74 80 else { 75 81 drm_mode_destroy(connector->dev, mode); 76 82 return 0; ··· 99 105 { 100 106 struct exynos_drm_connector *exynos_connector = 101 107 to_exynos_connector(connector); 102 - struct exynos_drm_manager *manager = exynos_connector->manager; 103 - struct exynos_drm_display_ops *display_ops = manager->display_ops; 108 + struct exynos_drm_display *display = exynos_connector->display; 104 109 int ret = MODE_BAD; 105 110 106 111 DRM_DEBUG_KMS("%s\n", __FILE__); 107 112 108 - if (display_ops && display_ops->check_mode) 109 - if (!display_ops->check_mode(manager->dev, mode)) 113 + if (display->ops->check_mode) 114 + if (!display->ops->check_mode(display, mode)) 110 115 ret = MODE_OK; 111 116 112 117 return ret; ··· 144 151 { 145 152 struct exynos_drm_connector *exynos_connector = 146 153 to_exynos_connector(connector); 147 - struct exynos_drm_manager *manager = exynos_connector->manager; 148 - struct exynos_drm_manager_ops *ops = manager->ops; 154 + struct exynos_drm_display *display = exynos_connector->display; 149 155 unsigned int width, height; 150 156 151 157 width = max_width; ··· 154 162 * if specific driver want to find desired_mode using maxmum 155 163 * resolution then get max width and height from that driver. 156 164 */ 157 - if (ops && ops->get_max_resol) 158 - ops->get_max_resol(manager, &width, &height); 165 + if (display->ops->get_max_resol) 166 + display->ops->get_max_resol(display, &width, &height); 159 167 160 168 return drm_helper_probe_single_connector_modes(connector, width, 161 169 height); ··· 167 175 { 168 176 struct exynos_drm_connector *exynos_connector = 169 177 to_exynos_connector(connector); 170 - struct exynos_drm_manager *manager = exynos_connector->manager; 171 - struct exynos_drm_display_ops *display_ops = 172 - manager->display_ops; 178 + struct exynos_drm_display *display = exynos_connector->display; 173 179 enum drm_connector_status status = connector_status_disconnected; 174 180 175 - if (display_ops && display_ops->is_connected) { 176 - if (display_ops->is_connected(manager->dev)) 181 + if (display->ops->is_connected) { 182 + if (display->ops->is_connected(display)) 177 183 status = connector_status_connected; 178 184 else 179 185 status = connector_status_disconnected; ··· 201 211 struct drm_encoder *encoder) 202 212 { 203 213 struct exynos_drm_connector *exynos_connector; 204 - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); 214 + struct exynos_drm_display *display = exynos_drm_get_display(encoder); 205 215 struct drm_connector *connector; 206 216 int type; 207 217 int err; ··· 212 222 213 223 connector = &exynos_connector->drm_connector; 214 224 215 - switch (manager->display_ops->type) { 225 + switch (display->type) { 216 226 case EXYNOS_DISPLAY_TYPE_HDMI: 217 227 type = DRM_MODE_CONNECTOR_HDMIA; 218 228 connector->interlace_allowed = true; ··· 235 245 goto err_connector; 236 246 237 247 exynos_connector->encoder_id = encoder->base.id; 238 - exynos_connector->manager = manager; 248 + exynos_connector->display = display; 239 249 connector->dpms = DRM_MODE_DPMS_OFF; 240 250 connector->encoder = encoder; 241 251
+134 -45
drivers/gpu/drm/exynos/exynos_drm_core.c
··· 14 14 15 15 #include <drm/drmP.h> 16 16 #include "exynos_drm_drv.h" 17 + #include "exynos_drm_crtc.h" 17 18 #include "exynos_drm_encoder.h" 18 19 #include "exynos_drm_connector.h" 19 20 #include "exynos_drm_fbdev.h" 20 21 21 22 static LIST_HEAD(exynos_drm_subdrv_list); 23 + static LIST_HEAD(exynos_drm_manager_list); 24 + static LIST_HEAD(exynos_drm_display_list); 22 25 23 26 static int exynos_drm_create_enc_conn(struct drm_device *dev, 24 - struct exynos_drm_subdrv *subdrv) 27 + struct exynos_drm_display *display) 25 28 { 26 29 struct drm_encoder *encoder; 27 30 struct drm_connector *connector; 31 + struct exynos_drm_manager *manager; 28 32 int ret; 33 + unsigned long possible_crtcs = 0; 29 34 30 - subdrv->manager->dev = subdrv->dev; 35 + /* Find possible crtcs for this display */ 36 + list_for_each_entry(manager, &exynos_drm_manager_list, list) 37 + if (manager->type == display->type) 38 + possible_crtcs |= 1 << manager->pipe; 31 39 32 40 /* create and initialize a encoder for this sub driver. */ 33 - encoder = exynos_drm_encoder_create(dev, subdrv->manager, 34 - (1 << MAX_CRTC) - 1); 41 + encoder = exynos_drm_encoder_create(dev, display, possible_crtcs); 35 42 if (!encoder) { 36 43 DRM_ERROR("failed to create encoder\n"); 37 44 return -EFAULT; ··· 55 48 goto err_destroy_encoder; 56 49 } 57 50 58 - subdrv->encoder = encoder; 59 - subdrv->connector = connector; 51 + display->encoder = encoder; 52 + display->connector = connector; 60 53 61 54 return 0; 62 55 63 56 err_destroy_encoder: 64 57 encoder->funcs->destroy(encoder); 65 58 return ret; 66 - } 67 - 68 - static void exynos_drm_destroy_enc_conn(struct exynos_drm_subdrv *subdrv) 69 - { 70 - if (subdrv->encoder) { 71 - struct drm_encoder *encoder = subdrv->encoder; 72 - encoder->funcs->destroy(encoder); 73 - subdrv->encoder = NULL; 74 - } 75 - 76 - if (subdrv->connector) { 77 - struct drm_connector *connector = subdrv->connector; 78 - connector->funcs->destroy(connector); 79 - subdrv->connector = NULL; 80 - } 81 59 } 82 60 83 61 static int exynos_drm_subdrv_probe(struct drm_device *dev, ··· 96 104 subdrv->remove(dev, subdrv->dev); 97 105 } 98 106 107 + int exynos_drm_initialize_managers(struct drm_device *dev) 108 + { 109 + struct exynos_drm_manager *manager, *n; 110 + int ret, pipe = 0; 111 + 112 + list_for_each_entry(manager, &exynos_drm_manager_list, list) { 113 + if (manager->ops->initialize) { 114 + ret = manager->ops->initialize(manager, dev, pipe); 115 + if (ret) { 116 + DRM_ERROR("Mgr init [%d] failed with %d\n", 117 + manager->type, ret); 118 + goto err; 119 + } 120 + } 121 + 122 + manager->drm_dev = dev; 123 + manager->pipe = pipe++; 124 + 125 + ret = exynos_drm_crtc_create(manager); 126 + if (ret) { 127 + DRM_ERROR("CRTC create [%d] failed with %d\n", 128 + manager->type, ret); 129 + goto err; 130 + } 131 + } 132 + return 0; 133 + 134 + err: 135 + list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) { 136 + if (pipe-- > 0) 137 + exynos_drm_manager_unregister(manager); 138 + else 139 + list_del(&manager->list); 140 + } 141 + return ret; 142 + } 143 + 144 + void exynos_drm_remove_managers(struct drm_device *dev) 145 + { 146 + struct exynos_drm_manager *manager, *n; 147 + 148 + list_for_each_entry_safe(manager, n, &exynos_drm_manager_list, list) 149 + exynos_drm_manager_unregister(manager); 150 + } 151 + 152 + int exynos_drm_initialize_displays(struct drm_device *dev) 153 + { 154 + struct exynos_drm_display *display, *n; 155 + int ret, initialized = 0; 156 + 157 + list_for_each_entry(display, &exynos_drm_display_list, list) { 158 + if (display->ops->initialize) { 159 + ret = display->ops->initialize(display, dev); 160 + if (ret) { 161 + DRM_ERROR("Display init [%d] failed with %d\n", 162 + display->type, ret); 163 + goto err; 164 + } 165 + } 166 + 167 + initialized++; 168 + 169 + ret = exynos_drm_create_enc_conn(dev, display); 170 + if (ret) { 171 + DRM_ERROR("Encoder create [%d] failed with %d\n", 172 + display->type, ret); 173 + goto err; 174 + } 175 + } 176 + return 0; 177 + 178 + err: 179 + list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) { 180 + if (initialized-- > 0) 181 + exynos_drm_display_unregister(display); 182 + else 183 + list_del(&display->list); 184 + } 185 + return ret; 186 + } 187 + 188 + void exynos_drm_remove_displays(struct drm_device *dev) 189 + { 190 + struct exynos_drm_display *display, *n; 191 + 192 + list_for_each_entry_safe(display, n, &exynos_drm_display_list, list) 193 + exynos_drm_display_unregister(display); 194 + } 195 + 99 196 int exynos_drm_device_register(struct drm_device *dev) 100 197 { 101 198 struct exynos_drm_subdrv *subdrv, *n; 102 - unsigned int fine_cnt = 0; 103 199 int err; 104 200 105 201 if (!dev) ··· 200 120 list_del(&subdrv->list); 201 121 continue; 202 122 } 203 - 204 - /* 205 - * if manager is null then it means that this sub driver 206 - * doesn't need encoder and connector. 207 - */ 208 - if (!subdrv->manager) { 209 - fine_cnt++; 210 - continue; 211 - } 212 - 213 - err = exynos_drm_create_enc_conn(dev, subdrv); 214 - if (err) { 215 - DRM_DEBUG("failed to create encoder and connector.\n"); 216 - exynos_drm_subdrv_remove(dev, subdrv); 217 - list_del(&subdrv->list); 218 - continue; 219 - } 220 - 221 - fine_cnt++; 222 123 } 223 - 224 - if (!fine_cnt) 225 - return -EINVAL; 226 124 227 125 return 0; 228 126 } ··· 217 159 218 160 list_for_each_entry(subdrv, &exynos_drm_subdrv_list, list) { 219 161 exynos_drm_subdrv_remove(dev, subdrv); 220 - exynos_drm_destroy_enc_conn(subdrv); 221 162 } 222 163 223 164 return 0; 224 165 } 225 166 EXPORT_SYMBOL_GPL(exynos_drm_device_unregister); 167 + 168 + int exynos_drm_manager_register(struct exynos_drm_manager *manager) 169 + { 170 + BUG_ON(!manager->ops); 171 + list_add_tail(&manager->list, &exynos_drm_manager_list); 172 + return 0; 173 + } 174 + 175 + int exynos_drm_manager_unregister(struct exynos_drm_manager *manager) 176 + { 177 + if (manager->ops->remove) 178 + manager->ops->remove(manager); 179 + 180 + list_del(&manager->list); 181 + return 0; 182 + } 183 + 184 + int exynos_drm_display_register(struct exynos_drm_display *display) 185 + { 186 + BUG_ON(!display->ops); 187 + list_add_tail(&display->list, &exynos_drm_display_list); 188 + return 0; 189 + } 190 + 191 + int exynos_drm_display_unregister(struct exynos_drm_display *display) 192 + { 193 + if (display->ops->remove) 194 + display->ops->remove(display); 195 + 196 + list_del(&display->list); 197 + return 0; 198 + } 226 199 227 200 int exynos_drm_subdrv_register(struct exynos_drm_subdrv *subdrv) 228 201 {
+92 -23
drivers/gpu/drm/exynos/exynos_drm_crtc.c
··· 33 33 * 34 34 * @drm_crtc: crtc object. 35 35 * @drm_plane: pointer of private plane object for this crtc 36 + * @manager: the manager associated with this crtc 36 37 * @pipe: a crtc index created at load() with a new crtc object creation 37 38 * and the crtc object would be set to private->crtc array 38 39 * to get a crtc object corresponding to this pipe from private->crtc ··· 47 46 struct exynos_drm_crtc { 48 47 struct drm_crtc drm_crtc; 49 48 struct drm_plane *plane; 49 + struct exynos_drm_manager *manager; 50 50 unsigned int pipe; 51 51 unsigned int dpms; 52 52 enum exynos_crtc_mode mode; ··· 58 56 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode) 59 57 { 60 58 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 59 + struct exynos_drm_manager *manager = exynos_crtc->manager; 61 60 62 61 DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode); 63 62 ··· 74 71 drm_vblank_off(crtc->dev, exynos_crtc->pipe); 75 72 } 76 73 77 - exynos_drm_fn_encoder(crtc, &mode, exynos_drm_encoder_crtc_dpms); 74 + if (manager->ops->dpms) 75 + manager->ops->dpms(manager, mode); 76 + 78 77 exynos_crtc->dpms = mode; 79 78 } 80 79 ··· 88 83 static void exynos_drm_crtc_commit(struct drm_crtc *crtc) 89 84 { 90 85 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); 86 + struct exynos_drm_manager *manager = exynos_crtc->manager; 91 87 92 88 exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON); 89 + 93 90 exynos_plane_commit(exynos_crtc->plane); 91 + 92 + if (manager->ops->commit) 93 + manager->ops->commit(manager); 94 + 94 95 exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON); 95 96 } 96 97 ··· 118 107 struct drm_plane *plane = exynos_crtc->plane; 119 108 unsigned int crtc_w; 120 109 unsigned int crtc_h; 121 - int pipe = exynos_crtc->pipe; 122 110 int ret; 123 111 124 112 /* ··· 136 126 137 127 plane->crtc = crtc; 138 128 plane->fb = crtc->fb; 139 - 140 - exynos_drm_fn_encoder(crtc, &pipe, exynos_drm_encoder_crtc_pipe); 141 129 142 130 return 0; 143 131 } ··· 326 318 drm_object_attach_property(&crtc->base, prop, 0); 327 319 } 328 320 329 - int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr) 321 + int exynos_drm_crtc_create(struct exynos_drm_manager *manager) 330 322 { 331 323 struct exynos_drm_crtc *exynos_crtc; 332 - struct exynos_drm_private *private = dev->dev_private; 324 + struct exynos_drm_private *private = manager->drm_dev->dev_private; 333 325 struct drm_crtc *crtc; 334 326 335 327 exynos_crtc = kzalloc(sizeof(*exynos_crtc), GFP_KERNEL); 336 328 if (!exynos_crtc) 337 329 return -ENOMEM; 338 330 339 - exynos_crtc->pipe = nr; 340 - exynos_crtc->dpms = DRM_MODE_DPMS_OFF; 341 331 init_waitqueue_head(&exynos_crtc->pending_flip_queue); 342 332 atomic_set(&exynos_crtc->pending_flip, 0); 343 - exynos_crtc->plane = exynos_plane_init(dev, 1 << nr, true); 333 + 334 + exynos_crtc->dpms = DRM_MODE_DPMS_OFF; 335 + exynos_crtc->manager = manager; 336 + exynos_crtc->pipe = manager->pipe; 337 + exynos_crtc->plane = exynos_plane_init(manager->drm_dev, 338 + 1 << manager->pipe, true); 344 339 if (!exynos_crtc->plane) { 345 340 kfree(exynos_crtc); 346 341 return -ENOMEM; ··· 351 340 352 341 crtc = &exynos_crtc->drm_crtc; 353 342 354 - private->crtc[nr] = crtc; 343 + private->crtc[manager->pipe] = crtc; 355 344 356 - drm_crtc_init(dev, crtc, &exynos_crtc_funcs); 345 + drm_crtc_init(manager->drm_dev, crtc, &exynos_crtc_funcs); 357 346 drm_crtc_helper_add(crtc, &exynos_crtc_helper_funcs); 358 347 359 348 exynos_drm_crtc_attach_mode_property(crtc); ··· 361 350 return 0; 362 351 } 363 352 364 - int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc) 353 + int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe) 365 354 { 366 355 struct exynos_drm_private *private = dev->dev_private; 367 356 struct exynos_drm_crtc *exynos_crtc = 368 - to_exynos_crtc(private->crtc[crtc]); 357 + to_exynos_crtc(private->crtc[pipe]); 358 + struct exynos_drm_manager *manager = exynos_crtc->manager; 369 359 370 360 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 371 361 return -EPERM; 372 362 373 - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 374 - exynos_drm_enable_vblank); 363 + if (manager->ops->enable_vblank) 364 + manager->ops->enable_vblank(manager); 375 365 376 366 return 0; 377 367 } 378 368 379 - void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc) 369 + void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe) 380 370 { 381 371 struct exynos_drm_private *private = dev->dev_private; 382 372 struct exynos_drm_crtc *exynos_crtc = 383 - to_exynos_crtc(private->crtc[crtc]); 373 + to_exynos_crtc(private->crtc[pipe]); 374 + struct exynos_drm_manager *manager = exynos_crtc->manager; 384 375 385 376 if (exynos_crtc->dpms != DRM_MODE_DPMS_ON) 386 377 return; 387 378 388 - exynos_drm_fn_encoder(private->crtc[crtc], &crtc, 389 - exynos_drm_disable_vblank); 379 + if (manager->ops->disable_vblank) 380 + manager->ops->disable_vblank(manager); 390 381 } 391 382 392 - void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc) 383 + void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe) 393 384 { 394 385 struct exynos_drm_private *dev_priv = dev->dev_private; 395 386 struct drm_pending_vblank_event *e, *t; 396 - struct drm_crtc *drm_crtc = dev_priv->crtc[crtc]; 387 + struct drm_crtc *drm_crtc = dev_priv->crtc[pipe]; 397 388 struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(drm_crtc); 398 389 unsigned long flags; 399 390 ··· 404 391 list_for_each_entry_safe(e, t, &dev_priv->pageflip_event_list, 405 392 base.link) { 406 393 /* if event's pipe isn't same as crtc then ignore it. */ 407 - if (crtc != e->pipe) 394 + if (pipe != e->pipe) 408 395 continue; 409 396 410 397 list_del(&e->base.link); 411 398 drm_send_vblank_event(dev, -1, e); 412 - drm_vblank_put(dev, crtc); 399 + drm_vblank_put(dev, pipe); 413 400 atomic_set(&exynos_crtc->pending_flip, 0); 414 401 wake_up(&exynos_crtc->pending_flip_queue); 415 402 } 416 403 417 404 spin_unlock_irqrestore(&dev->event_lock, flags); 405 + } 406 + 407 + void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, 408 + struct exynos_drm_overlay *overlay) 409 + { 410 + struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 411 + 412 + if (manager->ops->win_mode_set) 413 + manager->ops->win_mode_set(manager, overlay); 414 + } 415 + 416 + void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos) 417 + { 418 + struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 419 + 420 + if (manager->ops->win_commit) 421 + manager->ops->win_commit(manager, zpos); 422 + } 423 + 424 + void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos) 425 + { 426 + struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 427 + 428 + if (manager->ops->win_enable) 429 + manager->ops->win_enable(manager, zpos); 430 + } 431 + 432 + void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos) 433 + { 434 + struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager; 435 + 436 + if (manager->ops->win_disable) 437 + manager->ops->win_disable(manager, zpos); 438 + } 439 + 440 + void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb) 441 + { 442 + struct exynos_drm_manager *manager; 443 + struct drm_device *dev = fb->dev; 444 + struct drm_crtc *crtc; 445 + 446 + /* 447 + * make sure that overlay data are updated to real hardware 448 + * for all encoders. 449 + */ 450 + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 451 + manager = to_exynos_crtc(crtc)->manager; 452 + 453 + /* 454 + * wait for vblank interrupt 455 + * - this makes sure that overlay data are updated to 456 + * real hardware. 457 + */ 458 + if (manager->ops->wait_for_vblank) 459 + manager->ops->wait_for_vblank(manager); 460 + } 418 461 }
+16 -4
drivers/gpu/drm/exynos/exynos_drm_crtc.h
··· 15 15 #ifndef _EXYNOS_DRM_CRTC_H_ 16 16 #define _EXYNOS_DRM_CRTC_H_ 17 17 18 - int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr); 19 - int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc); 20 - void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc); 21 - void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int crtc); 18 + struct drm_device; 19 + struct drm_crtc; 20 + struct exynos_drm_manager; 21 + struct exynos_drm_overlay; 22 + 23 + int exynos_drm_crtc_create(struct exynos_drm_manager *manager); 24 + int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int pipe); 25 + void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int pipe); 26 + void exynos_drm_crtc_finish_pageflip(struct drm_device *dev, int pipe); 27 + void exynos_drm_crtc_complete_scanout(struct drm_framebuffer *fb); 28 + 29 + void exynos_drm_crtc_plane_mode_set(struct drm_crtc *crtc, 30 + struct exynos_drm_overlay *overlay); 31 + void exynos_drm_crtc_plane_commit(struct drm_crtc *crtc, int zpos); 32 + void exynos_drm_crtc_plane_enable(struct drm_crtc *crtc, int zpos); 33 + void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos); 22 34 23 35 #endif
+17 -12
drivers/gpu/drm/exynos/exynos_drm_drv.c
··· 74 74 75 75 exynos_drm_mode_config_init(dev); 76 76 77 - /* 78 - * EXYNOS4 is enough to have two CRTCs and each crtc would be used 79 - * without dependency of hardware. 80 - */ 81 - for (nr = 0; nr < MAX_CRTC; nr++) { 82 - ret = exynos_drm_crtc_create(dev, nr); 83 - if (ret) 84 - goto err_release_iommu_mapping; 85 - } 77 + ret = exynos_drm_initialize_managers(dev); 78 + if (ret) 79 + goto err_mode_config_cleanup; 86 80 87 81 for (nr = 0; nr < MAX_PLANE; nr++) { 88 82 struct drm_plane *plane; ··· 84 90 85 91 plane = exynos_plane_init(dev, possible_crtcs, false); 86 92 if (!plane) 87 - goto err_release_iommu_mapping; 93 + goto err_manager_cleanup; 88 94 } 95 + 96 + ret = exynos_drm_initialize_displays(dev); 97 + if (ret) 98 + goto err_manager_cleanup; 89 99 90 100 ret = drm_vblank_init(dev, MAX_CRTC); 91 101 if (ret) 92 - goto err_release_iommu_mapping; 102 + goto err_display_cleanup; 93 103 94 104 /* 95 105 * probe sub drivers such as display controller and hdmi driver, ··· 127 129 exynos_drm_device_unregister(dev); 128 130 err_vblank: 129 131 drm_vblank_cleanup(dev); 130 - err_release_iommu_mapping: 132 + err_display_cleanup: 133 + exynos_drm_remove_displays(dev); 134 + err_manager_cleanup: 135 + exynos_drm_remove_managers(dev); 136 + err_mode_config_cleanup: 137 + drm_mode_config_cleanup(dev); 131 138 drm_release_iommu_mapping(dev); 132 139 err_crtc: 133 140 drm_mode_config_cleanup(dev); ··· 147 144 exynos_drm_device_unregister(dev); 148 145 drm_vblank_cleanup(dev); 149 146 drm_kms_helper_poll_fini(dev); 147 + exynos_drm_remove_displays(dev); 148 + exynos_drm_remove_managers(dev); 150 149 drm_mode_config_cleanup(dev); 151 150 152 151 drm_release_iommu_mapping(dev);
+67 -39
drivers/gpu/drm/exynos/exynos_drm_drv.h
··· 122 122 * Exynos DRM Display Structure. 123 123 * - this structure is common to analog tv, digital tv and lcd panel. 124 124 * 125 - * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. 126 125 * @initialize: initializes the display with drm_dev 126 + * @remove: cleans up the display for removal 127 127 * @is_connected: check for that display is connected or not. 128 + * @get_max_resol: get maximum resolution to specific hardware. 128 129 * @get_edid: get edid modes from display driver. 129 130 * @get_panel: get panel object from display driver. 131 + * @mode_fixup: fix mode data comparing to hw specific display mode. 132 + * @mode_set: convert drm_display_mode to hw specific display mode and 133 + * would be called by encoder->mode_set(). 130 134 * @check_mode: check if mode is valid or not. 131 135 * @dpms: display device on or off. 136 + * @commit: apply changes to hw 132 137 */ 138 + struct exynos_drm_display; 133 139 struct exynos_drm_display_ops { 140 + int (*initialize)(struct exynos_drm_display *display, 141 + struct drm_device *drm_dev); 142 + void (*remove)(struct exynos_drm_display *display); 143 + bool (*is_connected)(struct exynos_drm_display *display); 144 + void (*get_max_resol)(struct exynos_drm_display *display, 145 + unsigned int *width, 146 + unsigned int *height); 147 + struct edid *(*get_edid)(struct exynos_drm_display *display, 148 + struct drm_connector *connector); 149 + void *(*get_panel)(struct exynos_drm_display *display); 150 + void (*mode_fixup)(struct exynos_drm_display *display, 151 + struct drm_connector *connector, 152 + const struct drm_display_mode *mode, 153 + struct drm_display_mode *adjusted_mode); 154 + void (*mode_set)(struct exynos_drm_display *display, 155 + struct drm_display_mode *mode); 156 + int (*check_mode)(struct exynos_drm_display *display, 157 + struct drm_display_mode *mode); 158 + void (*dpms)(struct exynos_drm_display *display, int mode); 159 + void (*commit)(struct exynos_drm_display *display); 160 + }; 161 + 162 + /* 163 + * Exynos drm display structure, maps 1:1 with an encoder/connector 164 + * 165 + * @list: the list entry for this manager 166 + * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. 167 + * @encoder: encoder object this display maps to 168 + * @connector: connector object this display maps to 169 + * @ops: pointer to callbacks for exynos drm specific functionality 170 + * @ctx: A pointer to the display's implementation specific context 171 + */ 172 + struct exynos_drm_display { 173 + struct list_head list; 134 174 enum exynos_drm_output_type type; 135 - int (*initialize)(struct device *dev, struct drm_device *drm_dev); 136 - bool (*is_connected)(struct device *dev); 137 - struct edid *(*get_edid)(struct device *dev, 138 - struct drm_connector *connector); 139 - void *(*get_panel)(struct device *dev); 140 - int (*check_mode)(struct device *dev, struct drm_display_mode *mode); 141 - int (*dpms)(struct device *dev, int mode); 175 + struct drm_encoder *encoder; 176 + struct drm_connector *connector; 177 + struct exynos_drm_display_ops *ops; 178 + void *ctx; 142 179 }; 143 180 144 181 /* 145 182 * Exynos drm manager ops 146 183 * 147 184 * @initialize: initializes the manager with drm_dev 185 + * @remove: cleans up the manager for removal 148 186 * @dpms: control device power. 149 - * @mode_fixup: fix mode data comparing to hw specific display mode. 150 - * @mode_set: convert drm_display_mode to hw specific display mode and 151 - * would be called by encoder->mode_set(). 152 - * @get_max_resol: get maximum resolution to specific hardware. 153 187 * @commit: set current hw specific display mode to hw. 154 188 * @enable_vblank: specific driver callback for enabling vblank interrupt. 155 189 * @disable_vblank: specific driver callback for disabling vblank interrupt. ··· 197 163 struct exynos_drm_manager; 198 164 struct exynos_drm_manager_ops { 199 165 int (*initialize)(struct exynos_drm_manager *mgr, 200 - struct drm_device *drm_dev); 166 + struct drm_device *drm_dev, int pipe); 167 + void (*remove)(struct exynos_drm_manager *mgr); 201 168 void (*dpms)(struct exynos_drm_manager *mgr, int mode); 202 - void (*mode_fixup)(struct exynos_drm_manager *mgr, 203 - struct drm_connector *connector, 204 - const struct drm_display_mode *mode, 205 - struct drm_display_mode *adjusted_mode); 206 - void (*mode_set)(struct exynos_drm_manager *mgr, void *mode); 207 - void (*get_max_resol)(struct exynos_drm_manager *mgr, 208 - unsigned int *width, unsigned int *height); 209 169 void (*commit)(struct exynos_drm_manager *mgr); 210 170 int (*enable_vblank)(struct exynos_drm_manager *mgr); 211 171 void (*disable_vblank)(struct exynos_drm_manager *mgr); ··· 212 184 }; 213 185 214 186 /* 215 - * Exynos drm common manager structure. 187 + * Exynos drm common manager structure, maps 1:1 with a crtc 216 188 * 217 - * @dev: pointer to device object for subdrv device driver. 218 - * sub drivers such as display controller or hdmi driver, 219 - * have their own device object. 220 - * @ops: pointer to callbacks for exynos drm specific framebuffer. 221 - * these callbacks should be set by specific drivers such fimd 222 - * or hdmi driver and are used to control hardware global registers. 223 - * @display: pointer to callbacks for exynos drm specific framebuffer. 224 - * these callbacks should be set by specific drivers such fimd 225 - * or hdmi driver and are used to control display devices such as 226 - * analog tv, digital tv and lcd panel and also get timing data for them. 189 + * @list: the list entry for this manager 190 + * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. 191 + * @drm_dev: pointer to the drm device 192 + * @pipe: the pipe number for this crtc/manager 193 + * @ops: pointer to callbacks for exynos drm specific functionality 227 194 * @ctx: A pointer to the manager's implementation specific context 228 195 */ 229 196 struct exynos_drm_manager { 230 - struct device *dev; 197 + struct list_head list; 198 + enum exynos_drm_output_type type; 199 + struct drm_device *drm_dev; 231 200 int pipe; 232 201 struct exynos_drm_manager_ops *ops; 233 - struct exynos_drm_display_ops *display_ops; 234 202 void *ctx; 235 203 }; 236 204 ··· 292 268 * by probe callback. 293 269 * @open: this would be called with drm device file open. 294 270 * @close: this would be called with drm device file close. 295 - * @encoder: encoder object owned by this sub driver. 296 - * @connector: connector object owned by this sub driver. 297 271 */ 298 272 struct exynos_drm_subdrv { 299 273 struct list_head list; 300 274 struct device *dev; 301 275 struct drm_device *drm_dev; 302 - struct exynos_drm_manager *manager; 303 276 304 277 int (*probe)(struct drm_device *drm_dev, struct device *dev); 305 278 void (*remove)(struct drm_device *drm_dev, struct device *dev); ··· 304 283 struct drm_file *file); 305 284 void (*close)(struct drm_device *drm_dev, struct device *dev, 306 285 struct drm_file *file); 307 - 308 - struct drm_encoder *encoder; 309 - struct drm_connector *connector; 310 286 }; 311 287 312 288 /* ··· 317 299 * destroy its own encoder and connetor. 318 300 */ 319 301 int exynos_drm_device_unregister(struct drm_device *dev); 302 + 303 + int exynos_drm_initialize_managers(struct drm_device *dev); 304 + void exynos_drm_remove_managers(struct drm_device *dev); 305 + int exynos_drm_initialize_displays(struct drm_device *dev); 306 + void exynos_drm_remove_displays(struct drm_device *dev); 307 + 308 + int exynos_drm_manager_register(struct exynos_drm_manager *manager); 309 + int exynos_drm_manager_unregister(struct exynos_drm_manager *manager); 310 + int exynos_drm_display_register(struct exynos_drm_display *display); 311 + int exynos_drm_display_unregister(struct exynos_drm_display *display); 320 312 321 313 /* 322 314 * this function would be called by sub drivers such as display controller
+33 -227
drivers/gpu/drm/exynos/exynos_drm_encoder.c
··· 26 26 * exynos specific encoder structure. 27 27 * 28 28 * @drm_encoder: encoder object. 29 - * @manager: specific encoder has its own manager to control a hardware 30 - * appropriately and we can access a hardware drawing on this manager. 29 + * @display: the display structure that maps to this encoder 31 30 */ 32 31 struct exynos_drm_encoder { 33 32 struct drm_crtc *old_crtc; 34 33 struct drm_encoder drm_encoder; 35 - struct exynos_drm_manager *manager; 34 + struct exynos_drm_display *display; 36 35 }; 37 36 38 37 static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode) 39 38 { 40 - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); 41 - struct exynos_drm_display_ops *display_ops = manager->display_ops; 39 + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 40 + struct exynos_drm_display *display = exynos_encoder->display; 42 41 43 42 DRM_DEBUG_KMS("encoder dpms: %d\n", mode); 44 43 45 - if (display_ops && display_ops->dpms) 46 - display_ops->dpms(manager->ctx, mode); 44 + if (display->ops->dpms) 45 + display->ops->dpms(display, mode); 47 46 } 48 47 49 48 static bool ··· 51 52 struct drm_display_mode *adjusted_mode) 52 53 { 53 54 struct drm_device *dev = encoder->dev; 55 + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 56 + struct exynos_drm_display *display = exynos_encoder->display; 54 57 struct drm_connector *connector; 55 - struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); 56 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 57 58 58 59 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 59 - if (connector->encoder == encoder) 60 - if (manager_ops && manager_ops->mode_fixup) 61 - manager_ops->mode_fixup(manager, connector, 62 - mode, adjusted_mode); 60 + if (connector->encoder != encoder) 61 + continue; 62 + 63 + if (display->ops->mode_fixup) 64 + display->ops->mode_fixup(display, connector, mode, 65 + adjusted_mode); 63 66 } 64 67 65 68 return true; ··· 103 102 { 104 103 struct drm_device *dev = encoder->dev; 105 104 struct drm_connector *connector; 106 - struct exynos_drm_manager *manager; 107 - struct exynos_drm_manager_ops *manager_ops; 105 + struct exynos_drm_display *display; 108 106 109 107 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 110 108 if (connector->encoder == encoder) { ··· 123 123 encoder->crtc); 124 124 } 125 125 126 - manager = exynos_drm_get_manager(encoder); 127 - manager_ops = manager->ops; 126 + display = exynos_encoder->display; 128 127 129 - if (manager_ops && manager_ops->mode_set) 130 - manager_ops->mode_set(manager, adjusted_mode); 128 + if (display->ops->mode_set) 129 + display->ops->mode_set(display, 130 + adjusted_mode); 131 131 132 132 exynos_encoder->old_crtc = encoder->crtc; 133 133 } ··· 142 142 static void exynos_drm_encoder_commit(struct drm_encoder *encoder) 143 143 { 144 144 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 145 - struct exynos_drm_manager *manager = exynos_encoder->manager; 146 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 145 + struct exynos_drm_display *display = exynos_encoder->display; 147 146 148 - if (manager_ops && manager_ops->commit) 149 - manager_ops->commit(manager); 147 + if (display->ops->dpms) 148 + display->ops->dpms(display, DRM_MODE_DPMS_ON); 149 + 150 + if (display->ops->commit) 151 + display->ops->commit(display); 150 152 } 151 - 152 - void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb) 153 - { 154 - struct exynos_drm_encoder *exynos_encoder; 155 - struct exynos_drm_manager_ops *ops; 156 - struct drm_device *dev = fb->dev; 157 - struct drm_encoder *encoder; 158 - 159 - /* 160 - * make sure that overlay data are updated to real hardware 161 - * for all encoders. 162 - */ 163 - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 164 - exynos_encoder = to_exynos_encoder(encoder); 165 - ops = exynos_encoder->manager->ops; 166 - 167 - /* 168 - * wait for vblank interrupt 169 - * - this makes sure that overlay data are updated to 170 - * real hardware. 171 - */ 172 - if (ops->wait_for_vblank) 173 - ops->wait_for_vblank(exynos_encoder->manager); 174 - } 175 - } 176 - 177 153 178 154 static void exynos_drm_encoder_disable(struct drm_encoder *encoder) 179 155 { ··· 176 200 177 201 static void exynos_drm_encoder_destroy(struct drm_encoder *encoder) 178 202 { 179 - struct exynos_drm_encoder *exynos_encoder = 180 - to_exynos_encoder(encoder); 181 - 182 - exynos_encoder->manager->pipe = -1; 203 + struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 183 204 184 205 drm_encoder_cleanup(encoder); 185 206 kfree(exynos_encoder); ··· 191 218 struct drm_encoder *clone; 192 219 struct drm_device *dev = encoder->dev; 193 220 struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 194 - struct exynos_drm_display_ops *display_ops = 195 - exynos_encoder->manager->display_ops; 221 + struct exynos_drm_display *display = exynos_encoder->display; 196 222 unsigned int clone_mask = 0; 197 223 int cnt = 0; 198 224 199 225 list_for_each_entry(clone, &dev->mode_config.encoder_list, head) { 200 - switch (display_ops->type) { 226 + switch (display->type) { 201 227 case EXYNOS_DISPLAY_TYPE_LCD: 202 228 case EXYNOS_DISPLAY_TYPE_HDMI: 203 229 case EXYNOS_DISPLAY_TYPE_VIDI: ··· 220 248 221 249 struct drm_encoder * 222 250 exynos_drm_encoder_create(struct drm_device *dev, 223 - struct exynos_drm_manager *manager, 251 + struct exynos_drm_display *display, 224 252 unsigned long possible_crtcs) 225 253 { 226 254 struct drm_encoder *encoder; 227 255 struct exynos_drm_encoder *exynos_encoder; 228 - int ret; 229 256 230 - if (!manager || !possible_crtcs) 231 - return NULL; 232 - 233 - if (!manager->dev) 257 + if (!possible_crtcs) 234 258 return NULL; 235 259 236 260 exynos_encoder = kzalloc(sizeof(*exynos_encoder), GFP_KERNEL); 237 261 if (!exynos_encoder) 238 262 return NULL; 239 263 240 - exynos_encoder->manager = manager; 264 + exynos_encoder->display = display; 241 265 encoder = &exynos_encoder->drm_encoder; 242 266 encoder->possible_crtcs = possible_crtcs; 243 267 ··· 244 276 245 277 drm_encoder_helper_add(encoder, &exynos_encoder_helper_funcs); 246 278 247 - if (manager->ops && manager->ops->initialize) { 248 - ret = manager->ops->initialize(manager, dev); 249 - if (ret) { 250 - DRM_ERROR("Manager initialize failed %d\n", ret); 251 - goto error; 252 - } 253 - } 254 - 255 - if (manager->display_ops && manager->display_ops->initialize) { 256 - ret = manager->display_ops->initialize(manager->dev, dev); 257 - if (ret) { 258 - DRM_ERROR("Display initialize failed %d\n", ret); 259 - goto error; 260 - } 261 - } 262 - 263 279 DRM_DEBUG_KMS("encoder has been created\n"); 264 280 265 281 return encoder; 266 - 267 - error: 268 - exynos_drm_encoder_destroy(&exynos_encoder->drm_encoder); 269 - return NULL; 270 282 } 271 283 272 - struct exynos_drm_manager *exynos_drm_get_manager(struct drm_encoder *encoder) 284 + struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder) 273 285 { 274 - return to_exynos_encoder(encoder)->manager; 275 - } 276 - 277 - void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, 278 - void (*fn)(struct drm_encoder *, void *)) 279 - { 280 - struct drm_device *dev = crtc->dev; 281 - struct drm_encoder *encoder; 282 - struct exynos_drm_private *private = dev->dev_private; 283 - struct exynos_drm_manager *manager; 284 - 285 - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 286 - /* 287 - * if crtc is detached from encoder, check pipe, 288 - * otherwise check crtc attached to encoder 289 - */ 290 - if (!encoder->crtc) { 291 - manager = to_exynos_encoder(encoder)->manager; 292 - if (manager->pipe < 0 || 293 - private->crtc[manager->pipe] != crtc) 294 - continue; 295 - } else { 296 - if (encoder->crtc != crtc) 297 - continue; 298 - } 299 - 300 - fn(encoder, data); 301 - } 302 - } 303 - 304 - void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data) 305 - { 306 - struct exynos_drm_manager *manager = 307 - to_exynos_encoder(encoder)->manager; 308 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 309 - int crtc = *(int *)data; 310 - 311 - if (manager->pipe != crtc) 312 - return; 313 - 314 - if (manager_ops->enable_vblank) 315 - manager_ops->enable_vblank(manager); 316 - } 317 - 318 - void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data) 319 - { 320 - struct exynos_drm_manager *manager = 321 - to_exynos_encoder(encoder)->manager; 322 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 323 - int crtc = *(int *)data; 324 - 325 - if (manager->pipe != crtc) 326 - return; 327 - 328 - if (manager_ops->disable_vblank) 329 - manager_ops->disable_vblank(manager); 330 - } 331 - 332 - void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data) 333 - { 334 - struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); 335 - struct exynos_drm_manager *manager = exynos_encoder->manager; 336 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 337 - int mode = *(int *)data; 338 - 339 - if (manager_ops && manager_ops->dpms) 340 - manager_ops->dpms(manager, mode); 341 - 342 - /* 343 - * if this condition is ok then it means that the crtc is already 344 - * detached from encoder and last function for detaching is properly 345 - * done, so clear pipe from manager to prevent repeated call. 346 - */ 347 - if (mode > DRM_MODE_DPMS_ON) { 348 - if (!encoder->crtc) 349 - manager->pipe = -1; 350 - } 351 - } 352 - 353 - void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data) 354 - { 355 - struct exynos_drm_manager *manager = 356 - to_exynos_encoder(encoder)->manager; 357 - int pipe = *(int *)data; 358 - 359 - /* 360 - * when crtc is detached from encoder, this pipe is used 361 - * to select manager operation 362 - */ 363 - manager->pipe = pipe; 364 - } 365 - 366 - void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data) 367 - { 368 - struct exynos_drm_manager *manager = 369 - to_exynos_encoder(encoder)->manager; 370 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 371 - struct exynos_drm_overlay *overlay = data; 372 - 373 - if (manager_ops && manager_ops->win_mode_set) 374 - manager_ops->win_mode_set(manager, overlay); 375 - } 376 - 377 - void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data) 378 - { 379 - struct exynos_drm_manager *manager = 380 - to_exynos_encoder(encoder)->manager; 381 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 382 - int zpos = DEFAULT_ZPOS; 383 - 384 - if (data) 385 - zpos = *(int *)data; 386 - 387 - if (manager_ops && manager_ops->win_commit) 388 - manager_ops->win_commit(manager, zpos); 389 - } 390 - 391 - void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data) 392 - { 393 - struct exynos_drm_manager *manager = 394 - to_exynos_encoder(encoder)->manager; 395 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 396 - int zpos = DEFAULT_ZPOS; 397 - 398 - if (data) 399 - zpos = *(int *)data; 400 - 401 - if (manager_ops && manager_ops->win_enable) 402 - manager_ops->win_enable(manager, zpos); 403 - } 404 - 405 - void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data) 406 - { 407 - struct exynos_drm_manager *manager = 408 - to_exynos_encoder(encoder)->manager; 409 - struct exynos_drm_manager_ops *manager_ops = manager->ops; 410 - int zpos = DEFAULT_ZPOS; 411 - 412 - if (data) 413 - zpos = *(int *)data; 414 - 415 - if (manager_ops && manager_ops->win_disable) 416 - manager_ops->win_disable(manager, zpos); 286 + return to_exynos_encoder(encoder)->display; 417 287 }
+3 -15
drivers/gpu/drm/exynos/exynos_drm_encoder.h
··· 18 18 19 19 void exynos_drm_encoder_setup(struct drm_device *dev); 20 20 struct drm_encoder *exynos_drm_encoder_create(struct drm_device *dev, 21 - struct exynos_drm_manager *mgr, 22 - unsigned long possible_crtcs); 23 - struct exynos_drm_manager * 24 - exynos_drm_get_manager(struct drm_encoder *encoder); 25 - void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data, 26 - void (*fn)(struct drm_encoder *, void *)); 27 - void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data); 28 - void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data); 29 - void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data); 30 - void exynos_drm_encoder_crtc_pipe(struct drm_encoder *encoder, void *data); 31 - void exynos_drm_encoder_plane_mode_set(struct drm_encoder *encoder, void *data); 32 - void exynos_drm_encoder_plane_commit(struct drm_encoder *encoder, void *data); 33 - void exynos_drm_encoder_plane_enable(struct drm_encoder *encoder, void *data); 34 - void exynos_drm_encoder_plane_disable(struct drm_encoder *encoder, void *data); 35 - void exynos_drm_encoder_complete_scanout(struct drm_framebuffer *fb); 21 + struct exynos_drm_display *mgr, 22 + unsigned long possible_crtcs); 23 + struct exynos_drm_display *exynos_drm_get_display(struct drm_encoder *encoder); 36 24 37 25 #endif
+2 -2
drivers/gpu/drm/exynos/exynos_drm_fb.c
··· 22 22 #include "exynos_drm_fb.h" 23 23 #include "exynos_drm_gem.h" 24 24 #include "exynos_drm_iommu.h" 25 - #include "exynos_drm_encoder.h" 25 + #include "exynos_drm_crtc.h" 26 26 27 27 #define to_exynos_fb(x) container_of(x, struct exynos_drm_fb, fb) 28 28 ··· 71 71 unsigned int i; 72 72 73 73 /* make sure that overlay data are updated before relesing fb. */ 74 - exynos_drm_encoder_complete_scanout(fb); 74 + exynos_drm_crtc_complete_scanout(fb); 75 75 76 76 drm_framebuffer_cleanup(fb); 77 77
+104 -114
drivers/gpu/drm/exynos/exynos_drm_fimd.c
··· 105 105 }; 106 106 107 107 struct fimd_context { 108 - struct exynos_drm_subdrv subdrv; 109 108 struct device *dev; 110 109 struct drm_device *drm_dev; 111 110 int irq; ··· 119 120 u32 vidcon0; 120 121 u32 vidcon1; 121 122 bool suspended; 123 + int pipe; 122 124 struct mutex lock; 123 125 wait_queue_head_t wait_vsync_queue; 124 126 atomic_t wait_vsync_event; ··· 147 147 return (struct fimd_driver_data *)of_id->data; 148 148 } 149 149 150 - static bool fimd_display_is_connected(struct device *dev) 150 + static bool fimd_display_is_connected(struct exynos_drm_display *display) 151 151 { 152 152 /* TODO. */ 153 153 154 154 return true; 155 155 } 156 156 157 - static void *fimd_get_panel(struct device *dev) 157 + static void *fimd_get_panel(struct exynos_drm_display *display) 158 158 { 159 - struct exynos_drm_manager *mgr = get_fimd_manager(dev); 160 - struct fimd_context *ctx = mgr->ctx; 159 + struct fimd_context *ctx = display->ctx; 161 160 162 161 return &ctx->panel; 163 162 } 164 163 165 - static int fimd_check_mode(struct device *dev, struct drm_display_mode *mode) 164 + static int fimd_check_mode(struct exynos_drm_display *display, 165 + struct drm_display_mode *mode) 166 166 { 167 167 /* TODO. */ 168 168 ··· 170 170 } 171 171 172 172 static struct exynos_drm_display_ops fimd_display_ops = { 173 - .type = EXYNOS_DISPLAY_TYPE_LCD, 174 173 .is_connected = fimd_display_is_connected, 175 174 .get_panel = fimd_get_panel, 176 175 .check_mode = fimd_check_mode, 177 176 }; 178 177 178 + static struct exynos_drm_display fimd_display = { 179 + .type = EXYNOS_DISPLAY_TYPE_LCD, 180 + .ops = &fimd_display_ops, 181 + }; 182 + 179 183 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr, 180 - struct drm_device *drm_dev) 184 + struct drm_device *drm_dev, int pipe) 181 185 { 182 186 struct fimd_context *ctx = mgr->ctx; 183 187 184 188 ctx->drm_dev = drm_dev; 189 + ctx->pipe = pipe; 190 + 191 + /* 192 + * enable drm irq mode. 193 + * - with irq_enabled = true, we can use the vblank feature. 194 + * 195 + * P.S. note that we wouldn't use drm irq handler but 196 + * just specific driver own one instead because 197 + * drm framework supports only one irq handler. 198 + */ 199 + drm_dev->irq_enabled = true; 200 + 201 + /* 202 + * with vblank_disable_allowed = true, vblank interrupt will be disabled 203 + * by drm timer once a current process gives up ownership of 204 + * vblank event.(after drm_vblank_put function is called) 205 + */ 206 + drm_dev->vblank_disable_allowed = true; 207 + 208 + /* attach this sub driver to iommu mapping if supported. */ 209 + if (is_drm_iommu_supported(ctx->drm_dev)) 210 + drm_iommu_attach_device(ctx->drm_dev, ctx->dev); 185 211 186 212 return 0; 187 213 } 188 214 189 - static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 215 + static void fimd_mgr_remove(struct exynos_drm_manager *mgr) 190 216 { 191 217 struct fimd_context *ctx = mgr->ctx; 192 218 193 - DRM_DEBUG_KMS("%d\n", mode); 194 - 195 - mutex_lock(&ctx->lock); 196 - 197 - switch (mode) { 198 - case DRM_MODE_DPMS_ON: 199 - /* 200 - * enable fimd hardware only if suspended status. 201 - * 202 - * P.S. fimd_dpms function would be called at booting time so 203 - * clk_enable could be called double time. 204 - */ 205 - if (ctx->suspended) 206 - pm_runtime_get_sync(ctx->dev); 207 - break; 208 - case DRM_MODE_DPMS_STANDBY: 209 - case DRM_MODE_DPMS_SUSPEND: 210 - case DRM_MODE_DPMS_OFF: 211 - if (!ctx->suspended) 212 - pm_runtime_put_sync(ctx->dev); 213 - break; 214 - default: 215 - DRM_DEBUG_KMS("unspecified mode %d\n", mode); 216 - break; 217 - } 218 - 219 - mutex_unlock(&ctx->lock); 220 - } 221 - 222 - static void fimd_apply(struct exynos_drm_manager *mgr) 223 - { 224 - struct fimd_context *ctx = mgr->ctx; 225 - struct exynos_drm_manager_ops *mgr_ops = mgr->ops; 226 - struct fimd_win_data *win_data; 227 - int i; 228 - 229 - for (i = 0; i < WINDOWS_NR; i++) { 230 - win_data = &ctx->win_data[i]; 231 - if (win_data->enabled && (mgr_ops && mgr_ops->win_commit)) 232 - mgr_ops->win_commit(mgr, i); 233 - } 234 - 235 - if (mgr_ops && mgr_ops->commit) 236 - mgr_ops->commit(mgr); 219 + /* detach this sub driver from iommu mapping if supported. */ 220 + if (is_drm_iommu_supported(ctx->drm_dev)) 221 + drm_iommu_detach_device(ctx->drm_dev, ctx->dev); 237 222 } 238 223 239 224 static void fimd_commit(struct exynos_drm_manager *mgr) ··· 646 661 win_data->enabled = false; 647 662 } 648 663 664 + static void fimd_dpms(struct exynos_drm_manager *mgr, int mode) 665 + { 666 + struct fimd_context *ctx = mgr->ctx; 667 + 668 + DRM_DEBUG_KMS("%d\n", mode); 669 + 670 + mutex_lock(&ctx->lock); 671 + 672 + switch (mode) { 673 + case DRM_MODE_DPMS_ON: 674 + /* 675 + * enable fimd hardware only if suspended status. 676 + * 677 + * P.S. fimd_dpms function would be called at booting time so 678 + * clk_enable could be called double time. 679 + */ 680 + if (ctx->suspended) 681 + pm_runtime_get_sync(ctx->dev); 682 + break; 683 + case DRM_MODE_DPMS_STANDBY: 684 + case DRM_MODE_DPMS_SUSPEND: 685 + case DRM_MODE_DPMS_OFF: 686 + if (!ctx->suspended) 687 + pm_runtime_put_sync(ctx->dev); 688 + break; 689 + default: 690 + DRM_DEBUG_KMS("unspecified mode %d\n", mode); 691 + break; 692 + } 693 + 694 + mutex_unlock(&ctx->lock); 695 + } 696 + 649 697 static struct exynos_drm_manager_ops fimd_manager_ops = { 650 698 .initialize = fimd_mgr_initialize, 699 + .remove = fimd_mgr_remove, 651 700 .dpms = fimd_dpms, 652 701 .commit = fimd_commit, 653 702 .enable_vblank = fimd_enable_vblank, ··· 693 674 }; 694 675 695 676 static struct exynos_drm_manager fimd_manager = { 696 - .pipe = -1, 697 - .ops = &fimd_manager_ops, 698 - .display_ops = &fimd_display_ops, 677 + .type = EXYNOS_DISPLAY_TYPE_LCD, 678 + .ops = &fimd_manager_ops, 699 679 }; 700 680 701 681 static irqreturn_t fimd_irq_handler(int irq, void *dev_id) 702 682 { 703 683 struct fimd_context *ctx = (struct fimd_context *)dev_id; 704 - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 705 - struct exynos_drm_manager *manager = subdrv->manager; 706 684 u32 val; 707 685 708 686 val = readl(ctx->regs + VIDINTCON1); ··· 709 693 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); 710 694 711 695 /* check the crtc is detached already from encoder */ 712 - if (manager->pipe < 0 || !ctx->drm_dev) 696 + if (ctx->pipe < 0 || !ctx->drm_dev) 713 697 goto out; 714 698 715 - drm_handle_vblank(ctx->drm_dev, manager->pipe); 716 - exynos_drm_crtc_finish_pageflip(ctx->drm_dev, manager->pipe); 699 + drm_handle_vblank(ctx->drm_dev, ctx->pipe); 700 + exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); 717 701 718 702 /* set wait vsync event to zero and wake up queue. */ 719 703 if (atomic_read(&ctx->wait_vsync_event)) { ··· 722 706 } 723 707 out: 724 708 return IRQ_HANDLED; 725 - } 726 - 727 - static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev) 728 - { 729 - /* 730 - * enable drm irq mode. 731 - * - with irq_enabled = true, we can use the vblank feature. 732 - * 733 - * P.S. note that we wouldn't use drm irq handler but 734 - * just specific driver own one instead because 735 - * drm framework supports only one irq handler. 736 - */ 737 - drm_dev->irq_enabled = true; 738 - 739 - /* 740 - * with vblank_disable_allowed = true, vblank interrupt will be disabled 741 - * by drm timer once a current process gives up ownership of 742 - * vblank event.(after drm_vblank_put function is called) 743 - */ 744 - drm_dev->vblank_disable_allowed = true; 745 - 746 - /* attach this sub driver to iommu mapping if supported. */ 747 - if (is_drm_iommu_supported(drm_dev)) 748 - drm_iommu_attach_device(drm_dev, dev); 749 - 750 - return 0; 751 - } 752 - 753 - static void fimd_subdrv_remove(struct drm_device *drm_dev, struct device *dev) 754 - { 755 - /* detach this sub driver from iommu mapping if supported. */ 756 - if (is_drm_iommu_supported(drm_dev)) 757 - drm_iommu_detach_device(drm_dev, dev); 758 709 } 759 710 760 711 static int fimd_configure_clocks(struct fimd_context *ctx, struct device *dev) ··· 809 826 return 0; 810 827 } 811 828 812 - static void fimd_window_suspend(struct device *dev) 829 + static void fimd_window_suspend(struct exynos_drm_manager *mgr) 813 830 { 814 - struct exynos_drm_manager *mgr = get_fimd_manager(dev); 815 831 struct fimd_context *ctx = mgr->ctx; 816 832 struct fimd_win_data *win_data; 817 833 int i; ··· 823 841 fimd_wait_for_vblank(mgr); 824 842 } 825 843 826 - static void fimd_window_resume(struct device *dev) 844 + static void fimd_window_resume(struct exynos_drm_manager *mgr) 827 845 { 828 - struct exynos_drm_manager *mgr = get_fimd_manager(dev); 829 846 struct fimd_context *ctx = mgr->ctx; 830 847 struct fimd_win_data *win_data; 831 848 int i; ··· 836 855 } 837 856 } 838 857 858 + static void fimd_apply(struct exynos_drm_manager *mgr) 859 + { 860 + struct fimd_context *ctx = mgr->ctx; 861 + struct fimd_win_data *win_data; 862 + int i; 863 + 864 + for (i = 0; i < WINDOWS_NR; i++) { 865 + win_data = &ctx->win_data[i]; 866 + if (win_data->enabled) 867 + fimd_win_commit(mgr, i); 868 + } 869 + 870 + fimd_commit(mgr); 871 + } 872 + 839 873 static int fimd_activate(struct exynos_drm_manager *mgr, bool enable) 840 874 { 841 875 struct fimd_context *ctx = mgr->ctx; 842 - struct device *dev = ctx->subdrv.dev; 843 876 844 877 if (enable) { 845 878 int ret; ··· 868 873 if (test_and_clear_bit(0, &ctx->irq_flags)) 869 874 fimd_enable_vblank(mgr); 870 875 871 - fimd_window_resume(dev); 876 + fimd_window_resume(mgr); 872 877 873 878 fimd_apply(mgr); 874 879 } else { 875 - fimd_window_suspend(dev); 880 + fimd_window_suspend(mgr); 876 881 877 882 fimd_clock(ctx, false); 878 883 ctx->suspended = true; ··· 909 914 { 910 915 struct device *dev = &pdev->dev; 911 916 struct fimd_context *ctx; 912 - struct exynos_drm_subdrv *subdrv; 913 917 struct resource *res; 914 918 int win; 915 919 int ret = -EINVAL; ··· 955 961 init_waitqueue_head(&ctx->wait_vsync_queue); 956 962 atomic_set(&ctx->wait_vsync_event, 0); 957 963 958 - fimd_manager.ctx = ctx; 959 - 960 - subdrv = &ctx->subdrv; 961 - 962 - subdrv->dev = dev; 963 - subdrv->manager = &fimd_manager; 964 - subdrv->probe = fimd_subdrv_probe; 965 - subdrv->remove = fimd_subdrv_remove; 966 - 967 964 mutex_init(&ctx->lock); 968 965 969 966 platform_set_drvdata(pdev, &fimd_manager); 967 + 968 + fimd_manager.ctx = ctx; 969 + exynos_drm_manager_register(&fimd_manager); 970 + 971 + fimd_display.ctx = ctx; 972 + exynos_drm_display_register(&fimd_display); 970 973 971 974 pm_runtime_enable(dev); 972 975 pm_runtime_get_sync(dev); 973 976 974 977 for (win = 0; win < WINDOWS_NR; win++) 975 978 fimd_clear_win(ctx, win); 976 - 977 - exynos_drm_subdrv_register(subdrv); 978 979 979 980 return 0; 980 981 } ··· 980 991 struct exynos_drm_manager *mgr = platform_get_drvdata(pdev); 981 992 struct fimd_context *ctx = mgr->ctx; 982 993 983 - exynos_drm_subdrv_unregister(&ctx->subdrv); 994 + exynos_drm_display_unregister(&fimd_display); 995 + exynos_drm_manager_unregister(&fimd_manager); 984 996 985 997 if (ctx->suspended) 986 998 goto out;
+89 -122
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
··· 23 23 #include "exynos_drm_drv.h" 24 24 #include "exynos_drm_hdmi.h" 25 25 26 - #define to_context(dev) platform_get_drvdata(to_platform_device(dev)) 27 - #define to_subdrv(dev) to_context(dev) 28 - #define get_ctx_from_subdrv(subdrv) container_of(subdrv,\ 29 - struct drm_hdmi_context, subdrv); 30 - 31 26 /* platform device pointer for common drm hdmi device. */ 32 27 static struct platform_device *exynos_drm_hdmi_pdev; 33 28 ··· 36 41 static struct exynos_mixer_ops *mixer_ops; 37 42 38 43 struct drm_hdmi_context { 39 - struct exynos_drm_subdrv subdrv; 40 44 struct exynos_drm_hdmi_context *hdmi_ctx; 41 45 struct exynos_drm_hdmi_context *mixer_ctx; 42 46 ··· 91 97 mixer_ops = ops; 92 98 } 93 99 94 - static int drm_hdmi_display_initialize(struct device *dev, 100 + static int drm_hdmi_display_initialize(struct exynos_drm_display *display, 95 101 struct drm_device *drm_dev) 96 102 { 97 - struct drm_hdmi_context *ctx = to_context(dev); 103 + struct drm_hdmi_context *ctx = display->ctx; 98 104 99 105 if (hdmi_ops && hdmi_ops->initialize) 100 106 return hdmi_ops->initialize(ctx->hdmi_ctx->ctx, drm_dev); ··· 103 109 } 104 110 105 111 106 - static bool drm_hdmi_is_connected(struct device *dev) 112 + static bool drm_hdmi_is_connected(struct exynos_drm_display *display) 107 113 { 108 - struct drm_hdmi_context *ctx = to_context(dev); 114 + struct drm_hdmi_context *ctx = display->ctx; 109 115 110 116 if (hdmi_ops && hdmi_ops->is_connected) 111 117 return hdmi_ops->is_connected(ctx->hdmi_ctx->ctx); ··· 113 119 return false; 114 120 } 115 121 116 - static struct edid *drm_hdmi_get_edid(struct device *dev, 122 + static struct edid *drm_hdmi_get_edid(struct exynos_drm_display *display, 117 123 struct drm_connector *connector) 118 124 { 119 - struct drm_hdmi_context *ctx = to_context(dev); 125 + struct drm_hdmi_context *ctx = display->ctx; 120 126 121 127 if (hdmi_ops && hdmi_ops->get_edid) 122 128 return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector); ··· 145 151 return 0; 146 152 } 147 153 148 - static int drm_hdmi_check_mode(struct device *dev, 154 + static int drm_hdmi_check_mode(struct exynos_drm_display *display, 149 155 struct drm_display_mode *mode) 150 156 { 151 - struct drm_hdmi_context *ctx = to_context(dev); 157 + struct drm_hdmi_context *ctx = display->ctx; 152 158 153 159 return drm_hdmi_check_mode_ctx(ctx, mode); 154 160 } 155 161 156 - static int drm_hdmi_display_dpms(struct device *dev, int mode) 162 + static void drm_hdmi_display_dpms(struct exynos_drm_display *display, int mode) 157 163 { 158 - struct drm_hdmi_context *ctx = to_context(dev); 164 + struct drm_hdmi_context *ctx = display->ctx; 159 165 160 166 if (hdmi_ops && hdmi_ops->dpms) 161 167 hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode); 162 - 163 - return 0; 164 168 } 165 169 166 - static struct exynos_drm_display_ops drm_hdmi_display_ops = { 167 - .type = EXYNOS_DISPLAY_TYPE_HDMI, 168 - .initialize = drm_hdmi_display_initialize, 169 - .is_connected = drm_hdmi_is_connected, 170 - .get_edid = drm_hdmi_get_edid, 171 - .check_mode = drm_hdmi_check_mode, 172 - .dpms = drm_hdmi_display_dpms, 173 - }; 174 - 175 - static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr) 176 - { 177 - struct drm_hdmi_context *ctx = mgr->ctx; 178 - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 179 - struct exynos_drm_manager *manager = subdrv->manager; 180 - 181 - if (mixer_ops && mixer_ops->enable_vblank) 182 - return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, 183 - manager->pipe); 184 - 185 - return 0; 186 - } 187 - 188 - static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr) 189 - { 190 - struct drm_hdmi_context *ctx = mgr->ctx; 191 - 192 - if (mixer_ops && mixer_ops->disable_vblank) 193 - return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); 194 - } 195 - 196 - static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr) 197 - { 198 - struct drm_hdmi_context *ctx = mgr->ctx; 199 - 200 - if (mixer_ops && mixer_ops->wait_for_vblank) 201 - mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx); 202 - } 203 - 204 - static void drm_hdmi_mode_fixup(struct exynos_drm_manager *mgr, 170 + static void drm_hdmi_mode_fixup(struct exynos_drm_display *display, 205 171 struct drm_connector *connector, 206 172 const struct drm_display_mode *mode, 207 173 struct drm_display_mode *adjusted_mode) 208 174 { 209 - struct drm_hdmi_context *ctx = mgr->ctx; 175 + struct drm_hdmi_context *ctx = display->ctx; 210 176 struct drm_display_mode *m; 211 177 int mode_ok; 212 178 ··· 206 252 } 207 253 } 208 254 209 - static void drm_hdmi_mode_set(struct exynos_drm_manager *mgr, void *mode) 255 + static void drm_hdmi_mode_set(struct exynos_drm_display *display, 256 + struct drm_display_mode *mode) 210 257 { 211 - struct drm_hdmi_context *ctx = mgr->ctx; 258 + struct drm_hdmi_context *ctx = display->ctx; 212 259 213 260 if (hdmi_ops && hdmi_ops->mode_set) 214 261 hdmi_ops->mode_set(ctx->hdmi_ctx->ctx, mode); 215 262 } 216 263 217 - static void drm_hdmi_get_max_resol(struct exynos_drm_manager *mgr, 264 + static void drm_hdmi_get_max_resol(struct exynos_drm_display *display, 218 265 unsigned int *width, unsigned int *height) 219 266 { 220 - struct drm_hdmi_context *ctx = mgr->ctx; 267 + struct drm_hdmi_context *ctx = display->ctx; 221 268 222 269 if (hdmi_ops && hdmi_ops->get_max_resol) 223 270 hdmi_ops->get_max_resol(ctx->hdmi_ctx->ctx, width, height); 271 + } 272 + 273 + static struct exynos_drm_display_ops drm_hdmi_display_ops = { 274 + .initialize = drm_hdmi_display_initialize, 275 + .is_connected = drm_hdmi_is_connected, 276 + .get_edid = drm_hdmi_get_edid, 277 + .check_mode = drm_hdmi_check_mode, 278 + .dpms = drm_hdmi_display_dpms, 279 + .mode_fixup = drm_hdmi_mode_fixup, 280 + .mode_set = drm_hdmi_mode_set, 281 + .get_max_resol = drm_hdmi_get_max_resol, 282 + }; 283 + 284 + static struct exynos_drm_display hdmi_display = { 285 + .type = EXYNOS_DISPLAY_TYPE_HDMI, 286 + .ops = &drm_hdmi_display_ops, 287 + }; 288 + 289 + static int drm_hdmi_enable_vblank(struct exynos_drm_manager *mgr) 290 + { 291 + struct drm_hdmi_context *ctx = mgr->ctx; 292 + 293 + if (mixer_ops && mixer_ops->enable_vblank) 294 + return mixer_ops->enable_vblank(ctx->mixer_ctx->ctx, mgr->pipe); 295 + 296 + return 0; 297 + } 298 + 299 + static void drm_hdmi_disable_vblank(struct exynos_drm_manager *mgr) 300 + { 301 + struct drm_hdmi_context *ctx = mgr->ctx; 302 + 303 + if (mixer_ops && mixer_ops->disable_vblank) 304 + return mixer_ops->disable_vblank(ctx->mixer_ctx->ctx); 305 + } 306 + 307 + static void drm_hdmi_wait_for_vblank(struct exynos_drm_manager *mgr) 308 + { 309 + struct drm_hdmi_context *ctx = mgr->ctx; 310 + 311 + if (mixer_ops && mixer_ops->wait_for_vblank) 312 + mixer_ops->wait_for_vblank(ctx->mixer_ctx->ctx); 224 313 } 225 314 226 315 static void drm_hdmi_commit(struct exynos_drm_manager *mgr) ··· 274 277 hdmi_ops->commit(ctx->hdmi_ctx->ctx); 275 278 } 276 279 277 - static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr, struct drm_device *drm_dev) 280 + static int drm_hdmi_mgr_initialize(struct exynos_drm_manager *mgr, 281 + struct drm_device *drm_dev, int pipe) 278 282 { 279 283 struct drm_hdmi_context *ctx = mgr->ctx; 280 284 int ret = 0; 285 + 286 + if (!hdmi_ctx) { 287 + DRM_ERROR("hdmi context not initialized.\n"); 288 + return -EFAULT; 289 + } 290 + 291 + if (!mixer_ctx) { 292 + DRM_ERROR("mixer context not initialized.\n"); 293 + return -EFAULT; 294 + } 295 + 296 + ctx->hdmi_ctx = hdmi_ctx; 297 + ctx->mixer_ctx = mixer_ctx; 281 298 282 299 if (mixer_ops && mixer_ops->initialize) 283 300 ret = mixer_ops->initialize(ctx->mixer_ctx->ctx, drm_dev); ··· 300 289 mixer_ops->iommu_on(ctx->mixer_ctx->ctx, true); 301 290 302 291 return ret; 292 + } 293 + 294 + static void drm_hdmi_mgr_remove(struct exynos_drm_manager *mgr) 295 + { 296 + struct drm_hdmi_context *ctx = mgr->ctx; 297 + 298 + if (mixer_ops->iommu_on) 299 + mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false); 303 300 } 304 301 305 302 static void drm_hdmi_dpms(struct exynos_drm_manager *mgr, int mode) ··· 364 345 365 346 static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { 366 347 .initialize = drm_hdmi_mgr_initialize, 348 + .remove = drm_hdmi_mgr_remove, 367 349 .dpms = drm_hdmi_dpms, 368 350 .enable_vblank = drm_hdmi_enable_vblank, 369 351 .disable_vblank = drm_hdmi_disable_vblank, 370 352 .wait_for_vblank = drm_hdmi_wait_for_vblank, 371 - .mode_fixup = drm_hdmi_mode_fixup, 372 - .mode_set = drm_hdmi_mode_set, 373 - .get_max_resol = drm_hdmi_get_max_resol, 374 353 .commit = drm_hdmi_commit, 375 354 .win_mode_set = drm_mixer_win_mode_set, 376 355 .win_commit = drm_mixer_win_commit, ··· 376 359 }; 377 360 378 361 static struct exynos_drm_manager hdmi_manager = { 379 - .pipe = -1, 362 + .type = EXYNOS_DISPLAY_TYPE_HDMI, 380 363 .ops = &drm_hdmi_manager_ops, 381 - .display_ops = &drm_hdmi_display_ops, 382 364 }; 383 - 384 - static int hdmi_subdrv_probe(struct drm_device *drm_dev, 385 - struct device *dev) 386 - { 387 - struct exynos_drm_subdrv *subdrv = to_subdrv(dev); 388 - struct drm_hdmi_context *ctx; 389 - 390 - if (!hdmi_ctx) { 391 - DRM_ERROR("hdmi context not initialized.\n"); 392 - return -EFAULT; 393 - } 394 - 395 - if (!mixer_ctx) { 396 - DRM_ERROR("mixer context not initialized.\n"); 397 - return -EFAULT; 398 - } 399 - 400 - ctx = get_ctx_from_subdrv(subdrv); 401 - 402 - if (!ctx) { 403 - DRM_ERROR("no drm hdmi context.\n"); 404 - return -EFAULT; 405 - } 406 - 407 - ctx->hdmi_ctx = hdmi_ctx; 408 - ctx->mixer_ctx = mixer_ctx; 409 - 410 - return 0; 411 - } 412 - 413 - static void hdmi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) 414 - { 415 - struct drm_hdmi_context *ctx; 416 - struct exynos_drm_subdrv *subdrv = to_subdrv(dev); 417 - 418 - ctx = get_ctx_from_subdrv(subdrv); 419 - 420 - if (mixer_ops->iommu_on) 421 - mixer_ops->iommu_on(ctx->mixer_ctx->ctx, false); 422 - } 423 365 424 366 static int exynos_drm_hdmi_probe(struct platform_device *pdev) 425 367 { 426 368 struct device *dev = &pdev->dev; 427 - struct exynos_drm_subdrv *subdrv; 428 369 struct drm_hdmi_context *ctx; 429 370 430 371 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ··· 390 415 return -ENOMEM; 391 416 392 417 hdmi_manager.ctx = ctx; 418 + hdmi_display.ctx = ctx; 393 419 394 - subdrv = &ctx->subdrv; 395 - 396 - subdrv->dev = dev; 397 - subdrv->manager = &hdmi_manager; 398 - subdrv->probe = hdmi_subdrv_probe; 399 - subdrv->remove = hdmi_subdrv_remove; 400 - 401 - platform_set_drvdata(pdev, subdrv); 402 - 403 - exynos_drm_subdrv_register(subdrv); 420 + exynos_drm_manager_register(&hdmi_manager); 421 + exynos_drm_display_register(&hdmi_display); 404 422 405 423 return 0; 406 424 } 407 425 408 426 static int exynos_drm_hdmi_remove(struct platform_device *pdev) 409 427 { 410 - struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); 411 - 412 - exynos_drm_subdrv_unregister(&ctx->subdrv); 428 + exynos_drm_display_unregister(&hdmi_display); 429 + exynos_drm_manager_unregister(&hdmi_manager); 413 430 414 431 return 0; 415 432 }
+2
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
··· 19 19 * exynos hdmi common context structure. 20 20 * 21 21 * @drm_dev: pointer to drm_device. 22 + * @pipe: pipe for mixer 22 23 * @ctx: pointer to the context of specific device driver. 23 24 * this context should be hdmi_context or mixer_context. 24 25 */ 25 26 struct exynos_drm_hdmi_context { 27 + int pipe; 26 28 void *ctx; 27 29 }; 28 30
+5 -10
drivers/gpu/drm/exynos/exynos_drm_plane.c
··· 13 13 14 14 #include <drm/exynos_drm.h> 15 15 #include "exynos_drm_drv.h" 16 - #include "exynos_drm_encoder.h" 16 + #include "exynos_drm_crtc.h" 17 17 #include "exynos_drm_fb.h" 18 18 #include "exynos_drm_gem.h" 19 19 #include "exynos_drm_plane.h" ··· 139 139 overlay->crtc_x, overlay->crtc_y, 140 140 overlay->crtc_width, overlay->crtc_height); 141 141 142 - exynos_drm_fn_encoder(crtc, overlay, exynos_drm_encoder_plane_mode_set); 142 + exynos_drm_crtc_plane_mode_set(crtc, overlay); 143 143 144 144 return 0; 145 145 } ··· 149 149 struct exynos_plane *exynos_plane = to_exynos_plane(plane); 150 150 struct exynos_drm_overlay *overlay = &exynos_plane->overlay; 151 151 152 - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 153 - exynos_drm_encoder_plane_commit); 152 + exynos_drm_crtc_plane_commit(plane->crtc, overlay->zpos); 154 153 } 155 154 156 155 void exynos_plane_dpms(struct drm_plane *plane, int mode) ··· 161 162 if (exynos_plane->enabled) 162 163 return; 163 164 164 - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 165 - exynos_drm_encoder_plane_enable); 166 - 165 + exynos_drm_crtc_plane_enable(plane->crtc, overlay->zpos); 167 166 exynos_plane->enabled = true; 168 167 } else { 169 168 if (!exynos_plane->enabled) 170 169 return; 171 170 172 - exynos_drm_fn_encoder(plane->crtc, &overlay->zpos, 173 - exynos_drm_encoder_plane_disable); 174 - 171 + exynos_drm_crtc_plane_disable(plane->crtc, overlay->zpos); 175 172 exynos_plane->enabled = false; 176 173 } 177 174 }
+60 -69
drivers/gpu/drm/exynos/exynos_drm_vidi.c
··· 45 45 }; 46 46 47 47 struct vidi_context { 48 - struct exynos_drm_subdrv subdrv; 48 + struct drm_device *drm_dev; 49 49 struct drm_crtc *crtc; 50 50 struct vidi_win_data win_data[WINDOWS_NR]; 51 51 struct edid *raw_edid; ··· 58 58 bool direct_vblank; 59 59 struct work_struct work; 60 60 struct mutex lock; 61 + int pipe; 61 62 }; 62 63 63 64 static const char fake_edid_info[] = { ··· 86 85 0x00, 0x00, 0x00, 0x06 87 86 }; 88 87 89 - static bool vidi_display_is_connected(struct device *dev) 88 + static bool vidi_display_is_connected(struct exynos_drm_display *display) 90 89 { 91 - struct exynos_drm_manager *mgr = get_vidi_mgr(dev); 92 - struct vidi_context *ctx = mgr->ctx; 90 + struct vidi_context *ctx = display->ctx; 93 91 94 92 /* 95 93 * connection request would come from user side ··· 97 97 return ctx->connected ? true : false; 98 98 } 99 99 100 - static struct edid *vidi_get_edid(struct device *dev, 100 + static struct edid *vidi_get_edid(struct exynos_drm_display *display, 101 101 struct drm_connector *connector) 102 102 { 103 - struct exynos_drm_manager *mgr = get_vidi_mgr(dev); 104 - struct vidi_context *ctx = mgr->ctx; 103 + struct vidi_context *ctx = display->ctx; 105 104 struct edid *edid; 106 105 107 106 /* ··· 121 122 return edid; 122 123 } 123 124 124 - static void *vidi_get_panel(struct device *dev) 125 - { 126 - /* TODO. */ 127 - 128 - return NULL; 129 - } 130 - 131 - static int vidi_check_mode(struct device *dev, struct drm_display_mode *mode) 125 + static int vidi_check_mode(struct exynos_drm_display *display, 126 + struct drm_display_mode *mode) 132 127 { 133 128 /* TODO. */ 134 129 ··· 130 137 } 131 138 132 139 static struct exynos_drm_display_ops vidi_display_ops = { 133 - .type = EXYNOS_DISPLAY_TYPE_VIDI, 134 140 .is_connected = vidi_display_is_connected, 135 141 .get_edid = vidi_get_edid, 136 - .get_panel = vidi_get_panel, 137 142 .check_mode = vidi_check_mode, 143 + }; 144 + 145 + static struct exynos_drm_display vidi_display = { 146 + .type = EXYNOS_DISPLAY_TYPE_VIDI, 147 + .ops = &vidi_display_ops, 138 148 }; 139 149 140 150 static void vidi_dpms(struct exynos_drm_manager *mgr, int mode) ··· 319 323 /* TODO. */ 320 324 } 321 325 326 + static int vidi_mgr_initialize(struct exynos_drm_manager *mgr, 327 + struct drm_device *drm_dev, int pipe) 328 + { 329 + struct vidi_context *ctx = mgr->ctx; 330 + 331 + DRM_ERROR("vidi initialize ct=%p dev=%p pipe=%d\n", ctx, drm_dev, pipe); 332 + 333 + ctx->drm_dev = drm_dev; 334 + ctx->pipe = pipe; 335 + 336 + /* 337 + * enable drm irq mode. 338 + * - with irq_enabled = 1, we can use the vblank feature. 339 + * 340 + * P.S. note that we wouldn't use drm irq handler but 341 + * just specific driver own one instead because 342 + * drm framework supports only one irq handler. 343 + */ 344 + drm_dev->irq_enabled = 1; 345 + 346 + /* 347 + * with vblank_disable_allowed = 1, vblank interrupt will be disabled 348 + * by drm timer once a current process gives up ownership of 349 + * vblank event.(after drm_vblank_put function is called) 350 + */ 351 + drm_dev->vblank_disable_allowed = 1; 352 + 353 + return 0; 354 + } 355 + 322 356 static struct exynos_drm_manager_ops vidi_manager_ops = { 357 + .initialize = vidi_mgr_initialize, 323 358 .dpms = vidi_dpms, 324 359 .commit = vidi_commit, 325 360 .enable_vblank = vidi_enable_vblank, ··· 361 334 }; 362 335 363 336 static struct exynos_drm_manager vidi_manager = { 364 - .pipe = -1, 365 - .ops = &vidi_manager_ops, 366 - .display_ops = &vidi_display_ops, 337 + .type = EXYNOS_DISPLAY_TYPE_VIDI, 338 + .ops = &vidi_manager_ops, 367 339 }; 368 340 369 341 static void vidi_fake_vblank_handler(struct work_struct *work) 370 342 { 371 343 struct vidi_context *ctx = container_of(work, struct vidi_context, 372 344 work); 373 - struct exynos_drm_subdrv *subdrv = &ctx->subdrv; 374 - struct exynos_drm_manager *manager = subdrv->manager; 375 345 376 - if (manager->pipe < 0) 346 + if (ctx->pipe < 0) 377 347 return; 378 348 379 349 /* refresh rate is about 50Hz. */ ··· 379 355 mutex_lock(&ctx->lock); 380 356 381 357 if (ctx->direct_vblank) { 382 - drm_handle_vblank(subdrv->drm_dev, manager->pipe); 358 + drm_handle_vblank(ctx->drm_dev, ctx->pipe); 383 359 ctx->direct_vblank = false; 384 360 mutex_unlock(&ctx->lock); 385 361 return; ··· 387 363 388 364 mutex_unlock(&ctx->lock); 389 365 390 - exynos_drm_crtc_finish_pageflip(subdrv->drm_dev, manager->pipe); 391 - } 392 - 393 - static int vidi_subdrv_probe(struct drm_device *drm_dev, struct device *dev) 394 - { 395 - /* 396 - * enable drm irq mode. 397 - * - with irq_enabled = true, we can use the vblank feature. 398 - * 399 - * P.S. note that we wouldn't use drm irq handler but 400 - * just specific driver own one instead because 401 - * drm framework supports only one irq handler. 402 - */ 403 - drm_dev->irq_enabled = true; 404 - 405 - /* 406 - * with vblank_disable_allowed = true, vblank interrupt will be disabled 407 - * by drm timer once a current process gives up ownership of 408 - * vblank event.(after drm_vblank_put function is called) 409 - */ 410 - drm_dev->vblank_disable_allowed = true; 411 - 412 - return 0; 413 - } 414 - 415 - static void vidi_subdrv_remove(struct drm_device *drm_dev, struct device *dev) 416 - { 417 - /* TODO. */ 366 + exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); 418 367 } 419 368 420 369 static int vidi_power_on(struct exynos_drm_manager *mgr, bool enable) ··· 457 460 458 461 DRM_DEBUG_KMS("requested connection.\n"); 459 462 460 - drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); 463 + drm_helper_hpd_irq_event(ctx->drm_dev); 461 464 462 465 return len; 463 466 } ··· 470 473 { 471 474 struct vidi_context *ctx = NULL; 472 475 struct drm_encoder *encoder; 473 - struct exynos_drm_manager *manager; 474 - struct exynos_drm_display_ops *display_ops; 476 + struct exynos_drm_display *display; 475 477 struct drm_exynos_vidi_connection *vidi = data; 476 478 477 479 if (!vidi) { ··· 485 489 486 490 list_for_each_entry(encoder, &drm_dev->mode_config.encoder_list, 487 491 head) { 488 - manager = exynos_drm_get_manager(encoder); 489 - display_ops = manager->display_ops; 492 + display = exynos_drm_get_display(encoder); 490 493 491 - if (display_ops->type == EXYNOS_DISPLAY_TYPE_VIDI) { 492 - ctx = manager->ctx; 494 + if (display->type == EXYNOS_DISPLAY_TYPE_VIDI) { 495 + ctx = display->ctx; 493 496 break; 494 497 } 495 498 } ··· 527 532 } 528 533 529 534 ctx->connected = vidi->connection; 530 - drm_helper_hpd_irq_event(ctx->subdrv.drm_dev); 535 + drm_helper_hpd_irq_event(ctx->drm_dev); 531 536 532 537 return 0; 533 538 } ··· 536 541 { 537 542 struct device *dev = &pdev->dev; 538 543 struct vidi_context *ctx; 539 - struct exynos_drm_subdrv *subdrv; 540 544 int ret; 541 545 542 546 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ··· 547 553 INIT_WORK(&ctx->work, vidi_fake_vblank_handler); 548 554 549 555 vidi_manager.ctx = ctx; 550 - 551 - subdrv = &ctx->subdrv; 552 - subdrv->dev = dev; 553 - subdrv->manager = &vidi_manager; 554 - subdrv->probe = vidi_subdrv_probe; 555 - subdrv->remove = vidi_subdrv_remove; 556 + vidi_display.ctx = ctx; 556 557 557 558 mutex_init(&ctx->lock); 558 559 ··· 557 568 if (ret < 0) 558 569 DRM_INFO("failed to create connection sysfs.\n"); 559 570 560 - exynos_drm_subdrv_register(subdrv); 571 + exynos_drm_manager_register(&vidi_manager); 572 + exynos_drm_display_register(&vidi_display); 561 573 562 574 return 0; 563 575 } ··· 567 577 { 568 578 struct vidi_context *ctx = platform_get_drvdata(pdev); 569 579 570 - exynos_drm_subdrv_unregister(&ctx->subdrv); 580 + exynos_drm_display_unregister(&vidi_display); 581 + exynos_drm_manager_unregister(&vidi_manager); 571 582 572 583 if (ctx->raw_edid != (struct edid *)fake_edid_info) { 573 584 kfree(ctx->raw_edid);