forked from Minki/linux
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:
parent
07866963b6
commit
ca915b108a
@ -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 ©->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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user