| @@ -9,12 +9,16 @@ · 8 unmodified lines |
| 9 | | 9 | |
| 10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
| 11 | #include <linux/media-bus-format.h> | 11 | #include <linux/media-bus-format.h> |
| | 12 | #include <linux/of.h> |
| | 13 | #include <linux/of_graph.h> |
| 12 | #include <linux/pm_runtime.h> | 14 | #include <linux/pm_runtime.h> |
| 13 | | 15 | |
| 14 | #include <drm/drm_atomic.h> | 16 | #include <drm/drm_atomic.h> |
| 15 | #include <drm/drm_atomic_helper.h> | 17 | #include <drm/drm_atomic_helper.h> |
| 16 | #include <drm/drm_atomic_state_helper.h> | 18 | #include <drm/drm_atomic_state_helper.h> |
| 17 | #include <drm/drm_atomic_uapi.h> | 19 | #include <drm/drm_atomic_uapi.h> |
| | 20 | #include <drm/drm_bridge.h> |
| | 21 | #include <drm/drm_bridge_connector.h> |
| 18 | #include <drm/drm_crtc.h> | 22 | #include <drm/drm_crtc.h> |
| 19 | #include <drm/drm_crtc_helper.h> | 23 | #include <drm/drm_crtc_helper.h> |
| 20 | #include <drm/drm_fb_dma_helper.h> | 24 | #include <drm/drm_fb_dma_helper.h> |
| @@ -23,6 +27,7 @@ · 2 unmodified lines |
| 23 | #include <drm/drm_gem_dma_helper.h> | 27 | #include <drm/drm_gem_dma_helper.h> |
| 24 | #include <drm/drm_modeset_helper.h> | 28 | #include <drm/drm_modeset_helper.h> |
| 25 | #include <drm/drm_modeset_helper_vtables.h> | 29 | #include <drm/drm_modeset_helper_vtables.h> |
| | 30 | #include <drm/drm_panel.h> |
| 26 | #include <drm/drm_probe_helper.h> | 31 | #include <drm/drm_probe_helper.h> |
| 27 | #include <drm/drm_simple_kms_helper.h> | 32 | #include <drm/drm_simple_kms_helper.h> |
| 28 | #include <drm/drm_vblank.h> | 33 | #include <drm/drm_vblank.h> |
| @@ -35,10 +40,6 @@ · 6 unmodified lines |
| 35 | #include "shmob_drm_plane.h" | 40 | #include "shmob_drm_plane.h" |
| 36 | #include "shmob_drm_regs.h" | 41 | #include "shmob_drm_regs.h" |
| 37 | | 42 | |
| 38 | /* | | |
| 39 | * TODO: panel support | | |
| 40 | */ | | |
| 41 | | | |
| 42 | /* ----------------------------------------------------------------------------- | 43 | /* ----------------------------------------------------------------------------- |
| 43 | * Page Flip | 44 | * Page Flip |
| 44 | */ | 45 | */ |
| @@ -201,7 +202,7 @@ static void shmob_drm_crtc_atomic_enable(struct drm_crtc *crtc, · 156 unmodified lines |
| 201 | { | 202 | { |
| 202 | struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc); | 203 | struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc); |
| 203 | struct shmob_drm_device *sdev = to_shmob_device(crtc->dev); | 204 | struct shmob_drm_device *sdev = to_shmob_device(crtc->dev); |
| 204 | const struct shmob_drm_interface_data *idata = &sdev->pdata->iface; | 205 | unsigned int clk_div = sdev->config.clk_div; |
| 205 | struct device *dev = sdev->dev; | 206 | struct device *dev = sdev->dev; |
| 206 | u32 value; | 207 | u32 value; |
| 207 | int ret; | 208 | int ret; |
| @@ -223,17 +224,17 @@ static void shmob_drm_crtc_atomic_enable(struct drm_crtc *crtc, · 15 unmodified lines |
| 223 | lcdc_write(sdev, LDPMR, 0); | 224 | lcdc_write(sdev, LDPMR, 0); |
| 224 | | 225 | |
| 225 | value = sdev->lddckr; | 226 | value = sdev->lddckr; |
| 226 | if (idata->clk_div) { | 227 | if (clk_div) { |
| 227 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider | 228 | /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider |
| 228 | * denominator. | 229 | * denominator. |
| 229 | */ | 230 | */ |
| 230 | lcdc_write(sdev, LDDCKPAT1R, 0); | 231 | lcdc_write(sdev, LDDCKPAT1R, 0); |
| 231 | lcdc_write(sdev, LDDCKPAT2R, (1 << (idata->clk_div / 2)) - 1); | 232 | lcdc_write(sdev, LDDCKPAT2R, (1 << (clk_div / 2)) - 1); |
| 232 | | 233 | |
| 233 | if (idata->clk_div == 1) | 234 | if (clk_div == 1) |
| 234 | value |= LDDCKR_MOSEL; | 235 | value |= LDDCKR_MOSEL; |
| 235 | else | 236 | else |
| 236 | value |= idata->clk_div; | 237 | value |= clk_div; |
| 237 | } | 238 | } |
| 238 | | 239 | |
| 239 | lcdc_write(sdev, LDDCKR, value); | 240 | lcdc_write(sdev, LDDCKR, value); |
| @@ -406,7 +407,7 @@ int shmob_drm_crtc_create(struct shmob_drm_device *sdev) · 166 unmodified lines |
| 406 | } | 407 | } |
| 407 | | 408 | |
| 408 | /* ----------------------------------------------------------------------------- | 409 | /* ----------------------------------------------------------------------------- |
| 409 | * Encoder | 410 | * Legacy Encoder |
| 410 | */ | 411 | */ |
| 411 | | 412 | |
| 412 | static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder, | 413 | static bool shmob_drm_encoder_mode_fixup(struct drm_encoder *encoder, |
| @@ -435,9 +436,14 @@ static const struct drm_encoder_helper_funcs encoder_helper_funcs = { · 22 unmodified lines |
| 435 | .mode_fixup = shmob_drm_encoder_mode_fixup, | 436 | .mode_fixup = shmob_drm_encoder_mode_fixup, |
| 436 | }; | 437 | }; |
| 437 | | 438 | |
| | 439 | /* ----------------------------------------------------------------------------- |
| | 440 | * Encoder |
| | 441 | */ |
| | 442 | |
| 438 | int shmob_drm_encoder_create(struct shmob_drm_device *sdev) | 443 | int shmob_drm_encoder_create(struct shmob_drm_device *sdev) |
| 439 | { | 444 | { |
| 440 | struct drm_encoder *encoder = &sdev->encoder; | 445 | struct drm_encoder *encoder = &sdev->encoder; |
| | 446 | struct drm_bridge *bridge; |
| 441 | int ret; | 447 | int ret; |
| 442 | | 448 | |
| 443 | encoder->possible_crtcs = 1; | 449 | encoder->possible_crtcs = 1; |
| @@ -447,13 +453,30 @@ int shmob_drm_encoder_create(struct shmob_drm_device *sdev) · 3 unmodified lines |
| 447 | if (ret < 0) | 453 | if (ret < 0) |
| 448 | return ret; | 454 | return ret; |
| 449 | | 455 | |
| 450 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); | 456 | if (sdev->pdata) { |
| | 457 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); |
| | 458 | return 0; |
| | 459 | } |
| | 460 | |
| | 461 | /* Create a panel bridge */ |
| | 462 | bridge = devm_drm_of_get_bridge(sdev->dev, sdev->dev->of_node, 0, 0); |
| | 463 | if (IS_ERR(bridge)) |
| | 464 | return PTR_ERR(bridge); |
| | 465 | |
| | 466 | /* Attach the bridge to the encoder */ |
| | 467 | ret = drm_bridge_attach(encoder, bridge, NULL, |
| | 468 | DRM_BRIDGE_ATTACH_NO_CONNECTOR); |
| | 469 | if (ret) { |
| | 470 | dev_err(sdev->dev, "failed to attach bridge: %pe\n", |
| | 471 | ERR_PTR(ret)); |
| | 472 | return ret; |
| | 473 | } |
| 451 | | 474 | |
| 452 | return 0; | 475 | return 0; |
| 453 | } | 476 | } |
| 454 | | 477 | |
| 455 | /* ----------------------------------------------------------------------------- | 478 | /* ----------------------------------------------------------------------------- |
| 456 | * Connector | 479 | * Legacy Connector |
| 457 | */ | 480 | */ |
| 458 | | 481 | |
| 459 | static inline struct shmob_drm_connector *to_shmob_connector(struct drm_connector *connector) | 482 | static inline struct shmob_drm_connector *to_shmob_connector(struct drm_connector *connector) |
| @@ -563,13 +586,20 @@ shmob_drm_connector_init(struct shmob_drm_device *sdev, · 103 unmodified lines |
| 563 | return connector; | 586 | return connector; |
| 564 | } | 587 | } |
| 565 | | 588 | |
| | 589 | /* ----------------------------------------------------------------------------- |
| | 590 | * Connector |
| | 591 | */ |
| | 592 | |
| 566 | int shmob_drm_connector_create(struct shmob_drm_device *sdev, | 593 | int shmob_drm_connector_create(struct shmob_drm_device *sdev, |
| 567 | struct drm_encoder *encoder) | 594 | struct drm_encoder *encoder) |
| 568 | { | 595 | { |
| 569 | struct drm_connector *connector; | 596 | struct drm_connector *connector; |
| 570 | int ret; | 597 | int ret; |
| 571 | | 598 | |
| 572 | connector = shmob_drm_connector_init(sdev, encoder); | 599 | if (sdev->pdata) |
| | 600 | connector = shmob_drm_connector_init(sdev, encoder); |
| | 601 | else |
| | 602 | connector = drm_bridge_connector_init(&sdev->ddev, encoder); |
| 573 | if (IS_ERR(connector)) { | 603 | if (IS_ERR(connector)) { |
| 574 | dev_err(sdev->dev, "failed to created connector: %pe\n", | 604 | dev_err(sdev->dev, "failed to created connector: %pe\n", |
| 575 | connector); | 605 | connector); |