drm/tegra: dc: Store clock setup in atomic state

This allows the clock setup to be separated from the clock programming
and better matches the expectations of the atomic modesetting where no
code paths must fail during modeset.

Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
Thierry Reding 2014-12-08 16:14:45 +01:00
parent 07866963b6
commit ca915b108a
2 changed files with 72 additions and 3 deletions

View File

@ -41,6 +41,22 @@ static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane)
return container_of(plane, struct tegra_plane, base);
}
struct tegra_dc_state {
struct drm_crtc_state base;
struct clk *clk;
unsigned long pclk;
unsigned int div;
};
static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
{
if (state)
return container_of(state, struct tegra_dc_state, base);
return NULL;
}
static void tegra_dc_window_commit(struct tegra_dc *dc, unsigned int index)
{
u32 value = WIN_A_ACT_REQ << index;
@ -1004,13 +1020,48 @@ static void tegra_dc_destroy(struct drm_crtc *crtc)
drm_crtc_cleanup(crtc);
}
static void tegra_crtc_reset(struct drm_crtc *crtc)
{
struct tegra_dc_state *state;
kfree(crtc->state);
crtc->state = NULL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state)
crtc->state = &state->base;
}
static struct drm_crtc_state *
tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
{
struct tegra_dc_state *state = to_dc_state(crtc->state);
struct tegra_dc_state *copy;
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
if (!copy)
return NULL;
copy->base.mode_changed = false;
copy->base.planes_changed = false;
copy->base.event = NULL;
return &copy->base;
}
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
kfree(state);
}
static const struct drm_crtc_funcs tegra_crtc_funcs = {
.page_flip = tegra_dc_page_flip,
.set_config = drm_crtc_helper_set_config,
.destroy = tegra_dc_destroy,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
.reset = tegra_crtc_reset,
.atomic_duplicate_state = tegra_crtc_atomic_duplicate_state,
.atomic_destroy_state = tegra_crtc_atomic_destroy_state,
};
static void tegra_dc_stop(struct tegra_dc *dc)
@ -1148,6 +1199,20 @@ int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent,
return 0;
}
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
struct drm_crtc_state *crtc_state,
struct clk *clk, unsigned long pclk,
unsigned int div)
{
struct tegra_dc_state *state = to_dc_state(crtc_state);
state->clk = clk;
state->pclk = pclk;
state->div = div;
return 0;
}
static void tegra_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
struct drm_display_mode *mode = &crtc->state->adjusted_mode;

View File

@ -180,6 +180,10 @@ void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
void tegra_dc_commit(struct tegra_dc *dc);
int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent,
unsigned long pclk, unsigned int div);
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
struct drm_crtc_state *crtc_state,
struct clk *clk, unsigned long pclk,
unsigned int div);
struct tegra_output {
struct device_node *of_node;