aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2017-11-28 05:20:40 -0500
committerThierry Reding <treding@nvidia.com>2018-03-16 19:03:36 -0400
commit0281c4149021376123b4ccdb1548692a3f6e70bd (patch)
treee2d1031c16f495b117a96f2f6035736561455b8e
parent4ae4b5c0dbaa499f2fd9215caac6e474c8dd477f (diff)
drm/tegra: hub: Use private object for global state
Rather than subclass the global atomic state to store the hub display clock and rate, create a private object and store this data in its state. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/dc.c26
-rw-r--r--drivers/gpu/drm/tegra/drm.c36
-rw-r--r--drivers/gpu/drm/tegra/drm.h14
-rw-r--r--drivers/gpu/drm/tegra/hub.c110
-rw-r--r--drivers/gpu/drm/tegra/hub.h17
5 files changed, 123 insertions, 80 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index dfa787e383cc..464495b46db2 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -1736,31 +1736,6 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
1736 drm_crtc_vblank_on(crtc); 1736 drm_crtc_vblank_on(crtc);
1737} 1737}
1738 1738
1739static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
1740 struct drm_crtc_state *state)
1741{
1742 struct tegra_atomic_state *s = to_tegra_atomic_state(state->state);
1743 struct tegra_dc_state *tegra = to_dc_state(state);
1744
1745 /*
1746 * The display hub display clock needs to be fed by the display clock
1747 * with the highest frequency to ensure proper functioning of all the
1748 * displays.
1749 *
1750 * Note that this isn't used before Tegra186, but it doesn't hurt and
1751 * conditionalizing it would make the code less clean.
1752 */
1753 if (state->active) {
1754 if (!s->clk_disp || tegra->pclk > s->rate) {
1755 s->dc = to_tegra_dc(crtc);
1756 s->clk_disp = s->dc->clk;
1757 s->rate = tegra->pclk;
1758 }
1759 }
1760
1761 return 0;
1762}
1763
1764static void tegra_crtc_atomic_begin(struct drm_crtc *crtc, 1739static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
1765 struct drm_crtc_state *old_crtc_state) 1740 struct drm_crtc_state *old_crtc_state)
1766{ 1741{
@@ -1797,7 +1772,6 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
1797} 1772}
1798 1773
1799static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { 1774static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
1800 .atomic_check = tegra_crtc_atomic_check,
1801 .atomic_begin = tegra_crtc_atomic_begin, 1775 .atomic_begin = tegra_crtc_atomic_begin,
1802 .atomic_flush = tegra_crtc_atomic_flush, 1776 .atomic_flush = tegra_crtc_atomic_flush,
1803 .atomic_enable = tegra_crtc_atomic_enable, 1777 .atomic_enable = tegra_crtc_atomic_enable,
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index d50bddb2e447..e20e013151f0 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -42,6 +42,10 @@ static int tegra_atomic_check(struct drm_device *drm,
42 if (err < 0) 42 if (err < 0)
43 return err; 43 return err;
44 44
45 err = tegra_display_hub_atomic_check(drm, state);
46 if (err < 0)
47 return err;
48
45 err = drm_atomic_normalize_zpos(drm, state); 49 err = drm_atomic_normalize_zpos(drm, state);
46 if (err < 0) 50 if (err < 0)
47 return err; 51 return err;
@@ -56,35 +60,6 @@ static int tegra_atomic_check(struct drm_device *drm,
56 return 0; 60 return 0;
57} 61}
58 62
59static struct drm_atomic_state *
60tegra_atomic_state_alloc(struct drm_device *drm)
61{
62 struct tegra_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
63
64 if (!state || drm_atomic_state_init(drm, &state->base) < 0) {
65 kfree(state);
66 return NULL;
67 }
68
69 return &state->base;
70}
71
72static void tegra_atomic_state_clear(struct drm_atomic_state *state)
73{
74 struct tegra_atomic_state *tegra = to_tegra_atomic_state(state);
75
76 drm_atomic_state_default_clear(state);
77 tegra->clk_disp = NULL;
78 tegra->dc = NULL;
79 tegra->rate = 0;
80}
81
82static void tegra_atomic_state_free(struct drm_atomic_state *state)
83{
84 drm_atomic_state_default_release(state);
85 kfree(state);
86}
87
88static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = { 63static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
89 .fb_create = tegra_fb_create, 64 .fb_create = tegra_fb_create,
90#ifdef CONFIG_DRM_FBDEV_EMULATION 65#ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -92,9 +67,6 @@ static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
92#endif 67#endif
93 .atomic_check = tegra_atomic_check, 68 .atomic_check = tegra_atomic_check,
94 .atomic_commit = drm_atomic_helper_commit, 69 .atomic_commit = drm_atomic_helper_commit,
95 .atomic_state_alloc = tegra_atomic_state_alloc,
96 .atomic_state_clear = tegra_atomic_state_clear,
97 .atomic_state_free = tegra_atomic_state_free,
98}; 70};
99 71
100static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state) 72static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 73b661ce7086..4f41aaec8530 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -42,20 +42,6 @@ struct tegra_fbdev {
42}; 42};
43#endif 43#endif
44 44
45struct tegra_atomic_state {
46 struct drm_atomic_state base;
47
48 struct clk *clk_disp;
49 struct tegra_dc *dc;
50 unsigned long rate;
51};
52
53static inline struct tegra_atomic_state *
54to_tegra_atomic_state(struct drm_atomic_state *state)
55{
56 return container_of(state, struct tegra_atomic_state, base);
57}
58
59struct tegra_drm { 45struct tegra_drm {
60 struct drm_device *drm; 46 struct drm_device *drm;
61 47
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index 094324daa917..9a3f23d4780f 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -573,6 +573,89 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,
573 return p; 573 return p;
574} 574}
575 575
576static struct drm_private_state *
577tegra_display_hub_duplicate_state(struct drm_private_obj *obj)
578{
579 struct tegra_display_hub_state *state;
580
581 state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
582 if (!state)
583 return NULL;
584
585 __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
586
587 return &state->base;
588}
589
590static void tegra_display_hub_destroy_state(struct drm_private_obj *obj,
591 struct drm_private_state *state)
592{
593 struct tegra_display_hub_state *hub_state =
594 to_tegra_display_hub_state(state);
595
596 kfree(hub_state);
597}
598
599static const struct drm_private_state_funcs tegra_display_hub_state_funcs = {
600 .atomic_duplicate_state = tegra_display_hub_duplicate_state,
601 .atomic_destroy_state = tegra_display_hub_destroy_state,
602};
603
604static struct tegra_display_hub_state *
605tegra_display_hub_get_state(struct tegra_display_hub *hub,
606 struct drm_atomic_state *state)
607{
608 struct drm_device *drm = dev_get_drvdata(hub->client.parent);
609 struct drm_private_state *priv;
610
611 WARN_ON(!drm_modeset_is_locked(&drm->mode_config.connection_mutex));
612
613 priv = drm_atomic_get_private_obj_state(state, &hub->base);
614 if (IS_ERR(priv))
615 return ERR_CAST(priv);
616
617 return to_tegra_display_hub_state(priv);
618}
619
620int tegra_display_hub_atomic_check(struct drm_device *drm,
621 struct drm_atomic_state *state)
622{
623 struct tegra_drm *tegra = drm->dev_private;
624 struct tegra_display_hub_state *hub_state;
625 struct drm_crtc_state *old, *new;
626 struct drm_crtc *crtc;
627 unsigned int i;
628
629 if (!tegra->hub)
630 return 0;
631
632 hub_state = tegra_display_hub_get_state(tegra->hub, state);
633 if (IS_ERR(hub_state))
634 return PTR_ERR(hub_state);
635
636 /*
637 * The display hub display clock needs to be fed by the display clock
638 * with the highest frequency to ensure proper functioning of all the
639 * displays.
640 *
641 * Note that this isn't used before Tegra186, but it doesn't hurt and
642 * conditionalizing it would make the code less clean.
643 */
644 for_each_oldnew_crtc_in_state(state, crtc, old, new, i) {
645 struct tegra_dc_state *dc = to_dc_state(new);
646
647 if (new->active) {
648 if (!hub_state->clk || dc->pclk > hub_state->rate) {
649 hub_state->dc = to_tegra_dc(dc->base.crtc);
650 hub_state->clk = hub_state->dc->clk;
651 hub_state->rate = dc->pclk;
652 }
653 }
654 }
655
656 return 0;
657}
658
576static void tegra_display_hub_update(struct tegra_dc *dc) 659static void tegra_display_hub_update(struct tegra_dc *dc)
577{ 660{
578 u32 value; 661 u32 value;
@@ -598,26 +681,28 @@ static void tegra_display_hub_update(struct tegra_dc *dc)
598void tegra_display_hub_atomic_commit(struct drm_device *drm, 681void tegra_display_hub_atomic_commit(struct drm_device *drm,
599 struct drm_atomic_state *state) 682 struct drm_atomic_state *state)
600{ 683{
601 struct tegra_atomic_state *s = to_tegra_atomic_state(state);
602 struct tegra_drm *tegra = drm->dev_private; 684 struct tegra_drm *tegra = drm->dev_private;
603 struct tegra_display_hub *hub = tegra->hub; 685 struct tegra_display_hub *hub = tegra->hub;
686 struct tegra_display_hub_state *hub_state;
604 struct device *dev = hub->client.dev; 687 struct device *dev = hub->client.dev;
605 int err; 688 int err;
606 689
607 if (s->clk_disp) { 690 hub_state = tegra_display_hub_get_state(hub, state);
608 err = clk_set_rate(s->clk_disp, s->rate); 691
692 if (hub_state->clk) {
693 err = clk_set_rate(hub_state->clk, hub_state->rate);
609 if (err < 0) 694 if (err < 0)
610 dev_err(dev, "failed to set rate of %pC to %lu Hz\n", 695 dev_err(dev, "failed to set rate of %pC to %lu Hz\n",
611 s->clk_disp, s->rate); 696 hub_state->clk, hub_state->rate);
612 697
613 err = clk_set_parent(hub->clk_disp, s->clk_disp); 698 err = clk_set_parent(hub->clk_disp, hub_state->clk);
614 if (err < 0) 699 if (err < 0)
615 dev_err(dev, "failed to set parent of %pC to %pC: %d\n", 700 dev_err(dev, "failed to set parent of %pC to %pC: %d\n",
616 hub->clk_disp, s->clk_disp, err); 701 hub->clk_disp, hub_state->clk, err);
617 } 702 }
618 703
619 if (s->dc) 704 if (hub_state->dc)
620 tegra_display_hub_update(s->dc); 705 tegra_display_hub_update(hub_state->dc);
621} 706}
622 707
623static int tegra_display_hub_init(struct host1x_client *client) 708static int tegra_display_hub_init(struct host1x_client *client)
@@ -625,6 +710,14 @@ static int tegra_display_hub_init(struct host1x_client *client)
625 struct tegra_display_hub *hub = to_tegra_display_hub(client); 710 struct tegra_display_hub *hub = to_tegra_display_hub(client);
626 struct drm_device *drm = dev_get_drvdata(client->parent); 711 struct drm_device *drm = dev_get_drvdata(client->parent);
627 struct tegra_drm *tegra = drm->dev_private; 712 struct tegra_drm *tegra = drm->dev_private;
713 struct tegra_display_hub_state *state;
714
715 state = kzalloc(sizeof(*state), GFP_KERNEL);
716 if (!state)
717 return -ENOMEM;
718
719 drm_atomic_private_obj_init(&hub->base, &state->base,
720 &tegra_display_hub_state_funcs);
628 721
629 tegra->hub = hub; 722 tegra->hub = hub;
630 723
@@ -636,6 +729,7 @@ static int tegra_display_hub_exit(struct host1x_client *client)
636 struct drm_device *drm = dev_get_drvdata(client->parent); 729 struct drm_device *drm = dev_get_drvdata(client->parent);
637 struct tegra_drm *tegra = drm->dev_private; 730 struct tegra_drm *tegra = drm->dev_private;
638 731
732 drm_atomic_private_obj_fini(&tegra->hub->base);
639 tegra->hub = NULL; 733 tegra->hub = NULL;
640 734
641 return 0; 735 return 0;
diff --git a/drivers/gpu/drm/tegra/hub.h b/drivers/gpu/drm/tegra/hub.h
index 890a47cd05c3..85b8bf41a395 100644
--- a/drivers/gpu/drm/tegra/hub.h
+++ b/drivers/gpu/drm/tegra/hub.h
@@ -41,6 +41,7 @@ struct tegra_display_hub_soc {
41}; 41};
42 42
43struct tegra_display_hub { 43struct tegra_display_hub {
44 struct drm_private_obj base;
44 struct host1x_client client; 45 struct host1x_client client;
45 struct clk *clk_disp; 46 struct clk *clk_disp;
46 struct clk *clk_dsc; 47 struct clk *clk_dsc;
@@ -57,6 +58,20 @@ to_tegra_display_hub(struct host1x_client *client)
57 return container_of(client, struct tegra_display_hub, client); 58 return container_of(client, struct tegra_display_hub, client);
58} 59}
59 60
61struct tegra_display_hub_state {
62 struct drm_private_state base;
63
64 struct tegra_dc *dc;
65 unsigned long rate;
66 struct clk *clk;
67};
68
69static inline struct tegra_display_hub_state *
70to_tegra_display_hub_state(struct drm_private_state *priv)
71{
72 return container_of(priv, struct tegra_display_hub_state, base);
73}
74
60struct tegra_dc; 75struct tegra_dc;
61struct tegra_plane; 76struct tegra_plane;
62 77
@@ -68,6 +83,8 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm,
68 unsigned int wgrp, 83 unsigned int wgrp,
69 unsigned int index); 84 unsigned int index);
70 85
86int tegra_display_hub_atomic_check(struct drm_device *drm,
87 struct drm_atomic_state *state);
71void tegra_display_hub_atomic_commit(struct drm_device *drm, 88void tegra_display_hub_atomic_commit(struct drm_device *drm,
72 struct drm_atomic_state *state); 89 struct drm_atomic_state *state);
73 90