mirror of https://gitee.com/openkylin/linux.git
drm/tegra: Changes for v4.1-rc1
Perhaps the most noteworthy change in this set is the implementation of a hardware VBLANK counter using host1x syncpoints. The SOR registers can now be dumped via debugfs, which can be useful while debugging. The IOVA address space maintained by the driver can also be dumped via debugfs. Other than than, these changes are mostly cleanup work, such as making register names more consistent or removing unused code (that was left over after the atomic mode-setting conversion). There's also a fix for eDP that makes the driver cope with firmware that already initialized the display (such as the firmware on the Tegra-based Chromebooks). -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCAAGBQJVHXUKAAoJEN0jrNd/PrOhjSUQAL9QJZBZmQmit1mroVWmWAx8 1m4/lj0bP3s1uOLzkQUwXJes0/niVie6lGmdZ9WCa3lThPErfvgYqKNpVJOYknMR iFg3HbEHgqz9T5zGNxp43g2hQrxssGEPAJXg4vE06nyS9YTOe0PZi27z9ynwapNZ Z+Gl2787mmnQE+PyQUQjT96OJv2ahnTgHtcDNMU0SWh5Dr6tI/vo5l/mHnqFOKnQ Kt/CCf+eNZ1jWCKqN5WYjxUT8kCMsMPPcnKzwhvrCXf6RqMDhr/rc47PGeak/qKR 0poIA47XlN6lPwul1P2gtyJaMiE7790aPKcgUDdpHJItPxbC9D/A8o8M+TcUqryw NHdKKEDxoo/yg+2x6ZgFk202UbVevp6cBtP+3nrfUAefPCrrkDX31ej6rWAUs7Zm POzugFON7q+85kF/yO1IEg1lov3zLIl4tCXNtprXUPFHbaBJJpMYK8joNyg2YZVh pYrV6AaKEwiVpi2h/kfhk/B32fx/KsufBR7fEPFOcJFQ6Gmi/l6GB+li00+LbrI4 8mDN6ngw7KASj03/RWXKSwGXdHqoMx2vtQPgjlNuGhHSgGzk3hZqapC7X+5WhoAw bOelbtzFABv8EA+vQN5IXd8SKdMPt4AFVGhk4B9HbZUyQLHln187p1tE1q9jSe/V D9bxrB3Wlf4Ks6Kl8OqU =HZO1 -----END PGP SIGNATURE----- Merge tag 'drm/tegra/for-4.1-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next drm/tegra: Changes for v4.1-rc1 Perhaps the most noteworthy change in this set is the implementation of a hardware VBLANK counter using host1x syncpoints. The SOR registers can now be dumped via debugfs, which can be useful while debugging. The IOVA address space maintained by the driver can also be dumped via debugfs. Other than than, these changes are mostly cleanup work, such as making register names more consistent or removing unused code (that was left over after the atomic mode-setting conversion). There's also a fix for eDP that makes the driver cope with firmware that already initialized the display (such as the firmware on the Tegra-based Chromebooks). * tag 'drm/tegra/for-4.1-rc1' of git://anongit.freedesktop.org/tegra/linux: drm/tegra: sor: Reset during initialization drm/tegra: gem: Return 64-bit offset for mmap(2) drm/tegra: hdmi: Name register fields consistently drm/tegra: hdmi: Resets are synchronous drm/tegra: dc: Document tegra_dc_state_setup_clock() drm/tegra: dc: Remove unused callbacks drm/tegra: dc: Remove unused function drm/tegra: dc: Use base atomic state helpers drm/atomic: Add helpers for state-subclassing drivers drm/tegra: dc: Implement hardware VBLANK counter gpu: host1x: Export host1x_syncpt_read() drm/tegra: sor: Dump registers via debugfs drm/tegra: sor: Registers are 32-bit drm/tegra: Provide debugfs file for the IOVA space drm/tegra: dc: Check for valid parent clock
This commit is contained in:
commit
1ddd36eda1
|
@ -2068,6 +2068,26 @@ void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
|
EXPORT_SYMBOL(drm_atomic_helper_crtc_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_crtc_duplicate_state - copy atomic CRTC state
|
||||||
|
* @crtc: CRTC object
|
||||||
|
* @state: atomic CRTC state
|
||||||
|
*
|
||||||
|
* Copies atomic state from a CRTC's current state and resets inferred values.
|
||||||
|
* This is useful for drivers that subclass the CRTC state.
|
||||||
|
*/
|
||||||
|
void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *state)
|
||||||
|
{
|
||||||
|
memcpy(state, crtc->state, sizeof(*state));
|
||||||
|
|
||||||
|
state->mode_changed = false;
|
||||||
|
state->active_changed = false;
|
||||||
|
state->planes_changed = false;
|
||||||
|
state->event = NULL;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
|
* drm_atomic_helper_crtc_duplicate_state - default state duplicate hook
|
||||||
* @crtc: drm CRTC
|
* @crtc: drm CRTC
|
||||||
|
@ -2083,19 +2103,34 @@ drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc)
|
||||||
if (WARN_ON(!crtc->state))
|
if (WARN_ON(!crtc->state))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
state = kmemdup(crtc->state, sizeof(*crtc->state), GFP_KERNEL);
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||||
|
if (state)
|
||||||
if (state) {
|
__drm_atomic_helper_crtc_duplicate_state(crtc, state);
|
||||||
state->mode_changed = false;
|
|
||||||
state->active_changed = false;
|
|
||||||
state->planes_changed = false;
|
|
||||||
state->event = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
|
EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_crtc_destroy_state - release CRTC state
|
||||||
|
* @crtc: CRTC object
|
||||||
|
* @state: CRTC state object to release
|
||||||
|
*
|
||||||
|
* Releases all resources stored in the CRTC state without actually freeing
|
||||||
|
* the memory of the CRTC state. This is useful for drivers that subclass the
|
||||||
|
* CRTC state.
|
||||||
|
*/
|
||||||
|
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *state)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is currently a placeholder so that drivers that subclass the
|
||||||
|
* state will automatically do the right thing if code is ever added
|
||||||
|
* to this function.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_crtc_destroy_state - default state destroy hook
|
* drm_atomic_helper_crtc_destroy_state - default state destroy hook
|
||||||
* @crtc: drm CRTC
|
* @crtc: drm CRTC
|
||||||
|
@ -2107,6 +2142,7 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state);
|
||||||
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||||
struct drm_crtc_state *state)
|
struct drm_crtc_state *state)
|
||||||
{
|
{
|
||||||
|
__drm_atomic_helper_crtc_destroy_state(crtc, state);
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
|
EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state);
|
||||||
|
@ -2131,6 +2167,24 @@ void drm_atomic_helper_plane_reset(struct drm_plane *plane)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
|
EXPORT_SYMBOL(drm_atomic_helper_plane_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_plane_duplicate_state - copy atomic plane state
|
||||||
|
* @plane: plane object
|
||||||
|
* @state: atomic plane state
|
||||||
|
*
|
||||||
|
* Copies atomic state from a plane's current state. This is useful for
|
||||||
|
* drivers that subclass the plane state.
|
||||||
|
*/
|
||||||
|
void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *state)
|
||||||
|
{
|
||||||
|
memcpy(state, plane->state, sizeof(*state));
|
||||||
|
|
||||||
|
if (state->fb)
|
||||||
|
drm_framebuffer_reference(state->fb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_plane_duplicate_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_plane_duplicate_state - default state duplicate hook
|
* drm_atomic_helper_plane_duplicate_state - default state duplicate hook
|
||||||
* @plane: drm plane
|
* @plane: drm plane
|
||||||
|
@ -2146,15 +2200,31 @@ drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane)
|
||||||
if (WARN_ON(!plane->state))
|
if (WARN_ON(!plane->state))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
state = kmemdup(plane->state, sizeof(*plane->state), GFP_KERNEL);
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||||
|
if (state)
|
||||||
if (state && state->fb)
|
__drm_atomic_helper_plane_duplicate_state(plane, state);
|
||||||
drm_framebuffer_reference(state->fb);
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
|
EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_plane_destroy_state - release plane state
|
||||||
|
* @plane: plane object
|
||||||
|
* @state: plane state object to release
|
||||||
|
*
|
||||||
|
* Releases all resources stored in the plane state without actually freeing
|
||||||
|
* the memory of the plane state. This is useful for drivers that subclass the
|
||||||
|
* plane state.
|
||||||
|
*/
|
||||||
|
void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *state)
|
||||||
|
{
|
||||||
|
if (state->fb)
|
||||||
|
drm_framebuffer_unreference(state->fb);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_plane_destroy_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_plane_destroy_state - default state destroy hook
|
* drm_atomic_helper_plane_destroy_state - default state destroy hook
|
||||||
* @plane: drm plane
|
* @plane: drm plane
|
||||||
|
@ -2166,9 +2236,7 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_duplicate_state);
|
||||||
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||||
struct drm_plane_state *state)
|
struct drm_plane_state *state)
|
||||||
{
|
{
|
||||||
if (state->fb)
|
__drm_atomic_helper_plane_destroy_state(plane, state);
|
||||||
drm_framebuffer_unreference(state->fb);
|
|
||||||
|
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
|
EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state);
|
||||||
|
@ -2191,6 +2259,22 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
|
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
|
||||||
|
* @connector: connector object
|
||||||
|
* @state: atomic connector state
|
||||||
|
*
|
||||||
|
* Copies atomic state from a connector's current state. This is useful for
|
||||||
|
* drivers that subclass the connector state.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
|
||||||
|
struct drm_connector_state *state)
|
||||||
|
{
|
||||||
|
memcpy(state, connector->state, sizeof(*state));
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_connector_duplicate_state - default state duplicate hook
|
* drm_atomic_helper_connector_duplicate_state - default state duplicate hook
|
||||||
* @connector: drm connector
|
* @connector: drm connector
|
||||||
|
@ -2201,13 +2285,40 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
|
||||||
struct drm_connector_state *
|
struct drm_connector_state *
|
||||||
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
|
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
|
struct drm_connector_state *state;
|
||||||
|
|
||||||
if (WARN_ON(!connector->state))
|
if (WARN_ON(!connector->state))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return kmemdup(connector->state, sizeof(*connector->state), GFP_KERNEL);
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
||||||
|
if (state)
|
||||||
|
__drm_atomic_helper_connector_duplicate_state(connector, state);
|
||||||
|
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
|
EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __drm_atomic_helper_connector_destroy_state - release connector state
|
||||||
|
* @connector: connector object
|
||||||
|
* @state: connector state object to release
|
||||||
|
*
|
||||||
|
* Releases all resources stored in the connector state without actually
|
||||||
|
* freeing the memory of the connector state. This is useful for drivers that
|
||||||
|
* subclass the connector state.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||||
|
struct drm_connector_state *state)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is currently a placeholder so that drivers that subclass the
|
||||||
|
* state will automatically do the right thing if code is ever added
|
||||||
|
* to this function.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__drm_atomic_helper_connector_destroy_state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_atomic_helper_connector_destroy_state - default state destroy hook
|
* drm_atomic_helper_connector_destroy_state - default state destroy hook
|
||||||
* @connector: drm connector
|
* @connector: drm connector
|
||||||
|
@ -2219,6 +2330,7 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_duplicate_state);
|
||||||
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||||
struct drm_connector_state *state)
|
struct drm_connector_state *state)
|
||||||
{
|
{
|
||||||
|
__drm_atomic_helper_connector_destroy_state(connector, state);
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
|
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
|
||||||
|
|
|
@ -425,8 +425,8 @@ static void tegra_plane_reset(struct drm_plane *plane)
|
||||||
{
|
{
|
||||||
struct tegra_plane_state *state;
|
struct tegra_plane_state *state;
|
||||||
|
|
||||||
if (plane->state && plane->state->fb)
|
if (plane->state)
|
||||||
drm_framebuffer_unreference(plane->state->fb);
|
__drm_atomic_helper_plane_destroy_state(plane, plane->state);
|
||||||
|
|
||||||
kfree(plane->state);
|
kfree(plane->state);
|
||||||
plane->state = NULL;
|
plane->state = NULL;
|
||||||
|
@ -443,12 +443,14 @@ static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_pla
|
||||||
struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
|
struct tegra_plane_state *state = to_tegra_plane_state(plane->state);
|
||||||
struct tegra_plane_state *copy;
|
struct tegra_plane_state *copy;
|
||||||
|
|
||||||
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
|
copy = kmalloc(sizeof(*copy), GFP_KERNEL);
|
||||||
if (!copy)
|
if (!copy)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (copy->base.fb)
|
__drm_atomic_helper_plane_duplicate_state(plane, ©->base);
|
||||||
drm_framebuffer_reference(copy->base.fb);
|
copy->tiling = state->tiling;
|
||||||
|
copy->format = state->format;
|
||||||
|
copy->swap = state->swap;
|
||||||
|
|
||||||
return ©->base;
|
return ©->base;
|
||||||
}
|
}
|
||||||
|
@ -456,9 +458,7 @@ static struct drm_plane_state *tegra_plane_atomic_duplicate_state(struct drm_pla
|
||||||
static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
|
static void tegra_plane_atomic_destroy_state(struct drm_plane *plane,
|
||||||
struct drm_plane_state *state)
|
struct drm_plane_state *state)
|
||||||
{
|
{
|
||||||
if (state->fb)
|
__drm_atomic_helper_plane_destroy_state(plane, state);
|
||||||
drm_framebuffer_unreference(state->fb);
|
|
||||||
|
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,6 +908,15 @@ static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc)
|
||||||
|
{
|
||||||
|
if (dc->syncpt)
|
||||||
|
return host1x_syncpt_read(dc->syncpt);
|
||||||
|
|
||||||
|
/* fallback to software emulated VBLANK counter */
|
||||||
|
return drm_crtc_vblank_count(&dc->base);
|
||||||
|
}
|
||||||
|
|
||||||
void tegra_dc_enable_vblank(struct tegra_dc *dc)
|
void tegra_dc_enable_vblank(struct tegra_dc *dc)
|
||||||
{
|
{
|
||||||
unsigned long value, flags;
|
unsigned long value, flags;
|
||||||
|
@ -995,6 +1004,9 @@ static void tegra_crtc_reset(struct drm_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct tegra_dc_state *state;
|
struct tegra_dc_state *state;
|
||||||
|
|
||||||
|
if (crtc->state)
|
||||||
|
__drm_atomic_helper_crtc_destroy_state(crtc, crtc->state);
|
||||||
|
|
||||||
kfree(crtc->state);
|
kfree(crtc->state);
|
||||||
crtc->state = NULL;
|
crtc->state = NULL;
|
||||||
|
|
||||||
|
@ -1011,14 +1023,15 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
|
||||||
struct tegra_dc_state *state = to_dc_state(crtc->state);
|
struct tegra_dc_state *state = to_dc_state(crtc->state);
|
||||||
struct tegra_dc_state *copy;
|
struct tegra_dc_state *copy;
|
||||||
|
|
||||||
copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
|
copy = kmalloc(sizeof(*copy), GFP_KERNEL);
|
||||||
if (!copy)
|
if (!copy)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
copy->base.mode_changed = false;
|
__drm_atomic_helper_crtc_duplicate_state(crtc, ©->base);
|
||||||
copy->base.active_changed = false;
|
copy->clk = state->clk;
|
||||||
copy->base.planes_changed = false;
|
copy->pclk = state->pclk;
|
||||||
copy->base.event = NULL;
|
copy->div = state->div;
|
||||||
|
copy->planes = state->planes;
|
||||||
|
|
||||||
return ©->base;
|
return ©->base;
|
||||||
}
|
}
|
||||||
|
@ -1026,6 +1039,7 @@ tegra_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
|
||||||
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc,
|
||||||
struct drm_crtc_state *state)
|
struct drm_crtc_state *state)
|
||||||
{
|
{
|
||||||
|
__drm_atomic_helper_crtc_destroy_state(crtc, state);
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1152,26 +1166,18 @@ static int tegra_dc_set_timings(struct tegra_dc *dc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tegra_dc_setup_clock(struct tegra_dc *dc, struct clk *parent,
|
/**
|
||||||
unsigned long pclk, unsigned int div)
|
* tegra_dc_state_setup_clock - check clock settings and store them in atomic
|
||||||
{
|
* state
|
||||||
u32 value;
|
* @dc: display controller
|
||||||
int err;
|
* @crtc_state: CRTC atomic state
|
||||||
|
* @clk: parent clock for display controller
|
||||||
err = clk_set_parent(dc->clk, parent);
|
* @pclk: pixel clock
|
||||||
if (err < 0) {
|
* @div: shift clock divider
|
||||||
dev_err(dc->dev, "failed to set parent clock: %d\n", err);
|
*
|
||||||
return err;
|
* Returns:
|
||||||
}
|
* 0 on success or a negative error-code on failure.
|
||||||
|
*/
|
||||||
DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk), div);
|
|
||||||
|
|
||||||
value = SHIFT_CLK_DIVIDER(div) | PIXEL_CLK_DIVIDER_PCD1;
|
|
||||||
tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
|
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
|
||||||
struct drm_crtc_state *crtc_state,
|
struct drm_crtc_state *crtc_state,
|
||||||
struct clk *clk, unsigned long pclk,
|
struct clk *clk, unsigned long pclk,
|
||||||
|
@ -1179,6 +1185,9 @@ int tegra_dc_state_setup_clock(struct tegra_dc *dc,
|
||||||
{
|
{
|
||||||
struct tegra_dc_state *state = to_dc_state(crtc_state);
|
struct tegra_dc_state *state = to_dc_state(crtc_state);
|
||||||
|
|
||||||
|
if (!clk_has_parent(dc->clk, clk))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
state->clk = clk;
|
state->clk = clk;
|
||||||
state->pclk = pclk;
|
state->pclk = pclk;
|
||||||
state->div = div;
|
state->div = div;
|
||||||
|
@ -1294,9 +1303,7 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc)
|
||||||
static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
|
static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
|
||||||
.disable = tegra_crtc_disable,
|
.disable = tegra_crtc_disable,
|
||||||
.mode_fixup = tegra_crtc_mode_fixup,
|
.mode_fixup = tegra_crtc_mode_fixup,
|
||||||
.mode_set = drm_helper_crtc_mode_set,
|
|
||||||
.mode_set_nofb = tegra_crtc_mode_set_nofb,
|
.mode_set_nofb = tegra_crtc_mode_set_nofb,
|
||||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
|
||||||
.prepare = tegra_crtc_prepare,
|
.prepare = tegra_crtc_prepare,
|
||||||
.commit = tegra_crtc_commit,
|
.commit = tegra_crtc_commit,
|
||||||
.atomic_check = tegra_crtc_atomic_check,
|
.atomic_check = tegra_crtc_atomic_check,
|
||||||
|
@ -1631,7 +1638,6 @@ static int tegra_dc_init(struct host1x_client *client)
|
||||||
struct tegra_drm *tegra = drm->dev_private;
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
struct drm_plane *primary = NULL;
|
struct drm_plane *primary = NULL;
|
||||||
struct drm_plane *cursor = NULL;
|
struct drm_plane *cursor = NULL;
|
||||||
unsigned int syncpt;
|
|
||||||
u32 value;
|
u32 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
@ -1700,13 +1706,15 @@ static int tegra_dc_init(struct host1x_client *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize display controller */
|
/* initialize display controller */
|
||||||
if (dc->pipe)
|
if (dc->syncpt) {
|
||||||
syncpt = SYNCPT_VBLANK1;
|
u32 syncpt = host1x_syncpt_id(dc->syncpt);
|
||||||
else
|
|
||||||
syncpt = SYNCPT_VBLANK0;
|
|
||||||
|
|
||||||
tegra_dc_writel(dc, 0x00000100, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
|
value = SYNCPT_CNTRL_NO_STALL;
|
||||||
tegra_dc_writel(dc, 0x100 | syncpt, DC_CMD_CONT_SYNCPT_VSYNC);
|
tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
|
||||||
|
|
||||||
|
value = SYNCPT_VSYNC_ENABLE | syncpt;
|
||||||
|
tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
|
||||||
|
}
|
||||||
|
|
||||||
value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
|
value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
|
||||||
tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
|
tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
|
||||||
|
@ -1874,6 +1882,7 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
|
||||||
|
|
||||||
static int tegra_dc_probe(struct platform_device *pdev)
|
static int tegra_dc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED;
|
||||||
const struct of_device_id *id;
|
const struct of_device_id *id;
|
||||||
struct resource *regs;
|
struct resource *regs;
|
||||||
struct tegra_dc *dc;
|
struct tegra_dc *dc;
|
||||||
|
@ -1965,6 +1974,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc->syncpt = host1x_syncpt_request(&pdev->dev, flags);
|
||||||
|
if (!dc->syncpt)
|
||||||
|
dev_warn(&pdev->dev, "failed to allocate syncpoint\n");
|
||||||
|
|
||||||
platform_set_drvdata(pdev, dc);
|
platform_set_drvdata(pdev, dc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1975,6 +1988,8 @@ static int tegra_dc_remove(struct platform_device *pdev)
|
||||||
struct tegra_dc *dc = platform_get_drvdata(pdev);
|
struct tegra_dc *dc = platform_get_drvdata(pdev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
host1x_syncpt_free(dc->syncpt);
|
||||||
|
|
||||||
err = host1x_client_unregister(&dc->client);
|
err = host1x_client_unregister(&dc->client);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
|
dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
|
#define DC_CMD_GENERAL_INCR_SYNCPT 0x000
|
||||||
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
|
#define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001
|
||||||
|
#define SYNCPT_CNTRL_NO_STALL (1 << 8)
|
||||||
|
#define SYNCPT_CNTRL_SOFT_RESET (1 << 0)
|
||||||
#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002
|
#define DC_CMD_GENERAL_INCR_SYNCPT_ERROR 0x002
|
||||||
#define DC_CMD_WIN_A_INCR_SYNCPT 0x008
|
#define DC_CMD_WIN_A_INCR_SYNCPT 0x008
|
||||||
#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009
|
#define DC_CMD_WIN_A_INCR_SYNCPT_CNTRL 0x009
|
||||||
|
@ -23,6 +25,7 @@
|
||||||
#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019
|
#define DC_CMD_WIN_C_INCR_SYNCPT_CNTRL 0x019
|
||||||
#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
|
#define DC_CMD_WIN_C_INCR_SYNCPT_ERROR 0x01a
|
||||||
#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
|
#define DC_CMD_CONT_SYNCPT_VSYNC 0x028
|
||||||
|
#define SYNCPT_VSYNC_ENABLE (1 << 8)
|
||||||
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
|
#define DC_CMD_DISPLAY_COMMAND_OPTION0 0x031
|
||||||
#define DC_CMD_DISPLAY_COMMAND 0x032
|
#define DC_CMD_DISPLAY_COMMAND 0x032
|
||||||
#define DISP_CTRL_MODE_STOP (0 << 5)
|
#define DISP_CTRL_MODE_STOP (0 << 5)
|
||||||
|
@ -438,8 +441,4 @@
|
||||||
#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
|
#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
|
||||||
#define DC_WINBUF_CD_UFLOW_STATUS 0xfca
|
#define DC_WINBUF_CD_UFLOW_STATUS 0xfca
|
||||||
|
|
||||||
/* synchronization points */
|
|
||||||
#define SYNCPT_VBLANK0 26
|
|
||||||
#define SYNCPT_VBLANK1 27
|
|
||||||
|
|
||||||
#endif /* TEGRA_DC_H */
|
#endif /* TEGRA_DC_H */
|
||||||
|
|
|
@ -172,6 +172,10 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
|
||||||
*/
|
*/
|
||||||
drm->irq_enabled = true;
|
drm->irq_enabled = true;
|
||||||
|
|
||||||
|
/* syncpoints are used for full 32-bit hardware VBLANK counters */
|
||||||
|
drm->vblank_disable_immediate = true;
|
||||||
|
drm->max_vblank_count = 0xffffffff;
|
||||||
|
|
||||||
err = drm_vblank_init(drm, drm->mode_config.num_crtc);
|
err = drm_vblank_init(drm, drm->mode_config.num_crtc);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto device;
|
goto device;
|
||||||
|
@ -813,12 +817,12 @@ static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm,
|
||||||
static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe)
|
static u32 tegra_drm_get_vblank_counter(struct drm_device *drm, int pipe)
|
||||||
{
|
{
|
||||||
struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
|
struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe);
|
||||||
|
struct tegra_dc *dc = to_tegra_dc(crtc);
|
||||||
|
|
||||||
if (!crtc)
|
if (!crtc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* TODO: implement real hardware counter using syncpoints */
|
return tegra_dc_get_vblank_counter(dc);
|
||||||
return drm_crtc_vblank_count(crtc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
|
static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe)
|
||||||
|
@ -879,8 +883,18 @@ static int tegra_debugfs_framebuffers(struct seq_file *s, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tegra_debugfs_iova(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct drm_info_node *node = (struct drm_info_node *)s->private;
|
||||||
|
struct drm_device *drm = node->minor->dev;
|
||||||
|
struct tegra_drm *tegra = drm->dev_private;
|
||||||
|
|
||||||
|
return drm_mm_dump_table(s, &tegra->mm);
|
||||||
|
}
|
||||||
|
|
||||||
static struct drm_info_list tegra_debugfs_list[] = {
|
static struct drm_info_list tegra_debugfs_list[] = {
|
||||||
{ "framebuffers", tegra_debugfs_framebuffers, 0 },
|
{ "framebuffers", tegra_debugfs_framebuffers, 0 },
|
||||||
|
{ "iova", tegra_debugfs_iova, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int tegra_debugfs_init(struct drm_minor *minor)
|
static int tegra_debugfs_init(struct drm_minor *minor)
|
||||||
|
|
|
@ -106,6 +106,7 @@ struct tegra_output;
|
||||||
|
|
||||||
struct tegra_dc {
|
struct tegra_dc {
|
||||||
struct host1x_client client;
|
struct host1x_client client;
|
||||||
|
struct host1x_syncpt *syncpt;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
|
@ -180,12 +181,11 @@ struct tegra_dc_window {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* from dc.c */
|
/* from dc.c */
|
||||||
|
u32 tegra_dc_get_vblank_counter(struct tegra_dc *dc);
|
||||||
void tegra_dc_enable_vblank(struct tegra_dc *dc);
|
void tegra_dc_enable_vblank(struct tegra_dc *dc);
|
||||||
void tegra_dc_disable_vblank(struct tegra_dc *dc);
|
void tegra_dc_disable_vblank(struct tegra_dc *dc);
|
||||||
void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
|
void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file);
|
||||||
void tegra_dc_commit(struct tegra_dc *dc);
|
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,
|
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
|
||||||
struct drm_crtc_state *crtc_state,
|
struct drm_crtc_state *crtc_state,
|
||||||
struct clk *clk, unsigned long pclk,
|
struct clk *clk, unsigned long pclk,
|
||||||
|
|
|
@ -952,7 +952,7 @@ static void tegra_hdmi_encoder_mode_set(struct drm_encoder *encoder,
|
||||||
}
|
}
|
||||||
|
|
||||||
tegra_hdmi_writel(hdmi,
|
tegra_hdmi_writel(hdmi,
|
||||||
SOR_SEQ_CTL_PU_PC(0) |
|
SOR_SEQ_PU_PC(0) |
|
||||||
SOR_SEQ_PU_PC_ALT(0) |
|
SOR_SEQ_PU_PC_ALT(0) |
|
||||||
SOR_SEQ_PD_PC(8) |
|
SOR_SEQ_PD_PC(8) |
|
||||||
SOR_SEQ_PD_PC_ALT(8),
|
SOR_SEQ_PD_PC_ALT(8),
|
||||||
|
@ -1394,8 +1394,8 @@ static int tegra_hdmi_exit(struct host1x_client *client)
|
||||||
|
|
||||||
tegra_output_exit(&hdmi->output);
|
tegra_output_exit(&hdmi->output);
|
||||||
|
|
||||||
clk_disable_unprepare(hdmi->clk);
|
|
||||||
reset_control_assert(hdmi->rst);
|
reset_control_assert(hdmi->rst);
|
||||||
|
clk_disable_unprepare(hdmi->clk);
|
||||||
|
|
||||||
regulator_disable(hdmi->vdd);
|
regulator_disable(hdmi->vdd);
|
||||||
regulator_disable(hdmi->pll);
|
regulator_disable(hdmi->pll);
|
||||||
|
|
|
@ -201,7 +201,7 @@
|
||||||
#define HDMI_NV_PDISP_SOR_CRCB 0x5d
|
#define HDMI_NV_PDISP_SOR_CRCB 0x5d
|
||||||
#define HDMI_NV_PDISP_SOR_BLANK 0x5e
|
#define HDMI_NV_PDISP_SOR_BLANK 0x5e
|
||||||
#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f
|
#define HDMI_NV_PDISP_SOR_SEQ_CTL 0x5f
|
||||||
#define SOR_SEQ_CTL_PU_PC(x) (((x) & 0xf) << 0)
|
#define SOR_SEQ_PU_PC(x) (((x) & 0xf) << 0)
|
||||||
#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
|
#define SOR_SEQ_PU_PC_ALT(x) (((x) & 0xf) << 4)
|
||||||
#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
|
#define SOR_SEQ_PD_PC(x) (((x) & 0xf) << 8)
|
||||||
#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
|
#define SOR_SEQ_PD_PC_ALT(x) (((x) & 0xf) << 12)
|
||||||
|
|
|
@ -41,6 +41,8 @@ struct tegra_sor {
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
|
struct drm_info_list *debugfs_files;
|
||||||
|
struct drm_minor *minor;
|
||||||
struct dentry *debugfs;
|
struct dentry *debugfs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,13 +70,12 @@ static inline struct tegra_sor *to_sor(struct tegra_output *output)
|
||||||
return container_of(output, struct tegra_sor, output);
|
return container_of(output, struct tegra_sor, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long tegra_sor_readl(struct tegra_sor *sor,
|
static inline u32 tegra_sor_readl(struct tegra_sor *sor, unsigned long offset)
|
||||||
unsigned long offset)
|
|
||||||
{
|
{
|
||||||
return readl(sor->regs + (offset << 2));
|
return readl(sor->regs + (offset << 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value,
|
static inline void tegra_sor_writel(struct tegra_sor *sor, u32 value,
|
||||||
unsigned long offset)
|
unsigned long offset)
|
||||||
{
|
{
|
||||||
writel(value, sor->regs + (offset << 2));
|
writel(value, sor->regs + (offset << 2));
|
||||||
|
@ -83,9 +84,9 @@ static inline void tegra_sor_writel(struct tegra_sor *sor, unsigned long value,
|
||||||
static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
|
static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
|
||||||
struct drm_dp_link *link)
|
struct drm_dp_link *link)
|
||||||
{
|
{
|
||||||
unsigned long value;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
u8 pattern;
|
u8 pattern;
|
||||||
|
u32 value;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* setup lane parameters */
|
/* setup lane parameters */
|
||||||
|
@ -202,7 +203,7 @@ static void tegra_sor_update(struct tegra_sor *sor)
|
||||||
|
|
||||||
static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
|
static int tegra_sor_setup_pwm(struct tegra_sor *sor, unsigned long timeout)
|
||||||
{
|
{
|
||||||
unsigned long value;
|
u32 value;
|
||||||
|
|
||||||
value = tegra_sor_readl(sor, SOR_PWM_DIV);
|
value = tegra_sor_readl(sor, SOR_PWM_DIV);
|
||||||
value &= ~SOR_PWM_DIV_MASK;
|
value &= ~SOR_PWM_DIV_MASK;
|
||||||
|
@ -281,7 +282,7 @@ static int tegra_sor_wakeup(struct tegra_sor *sor)
|
||||||
|
|
||||||
static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
|
static int tegra_sor_power_up(struct tegra_sor *sor, unsigned long timeout)
|
||||||
{
|
{
|
||||||
unsigned long value;
|
u32 value;
|
||||||
|
|
||||||
value = tegra_sor_readl(sor, SOR_PWR);
|
value = tegra_sor_readl(sor, SOR_PWR);
|
||||||
value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
|
value |= SOR_PWR_TRIGGER | SOR_PWR_NORMAL_STATE_PU;
|
||||||
|
@ -674,38 +675,195 @@ static const struct file_operations tegra_sor_crc_fops = {
|
||||||
.release = tegra_sor_crc_release,
|
.release = tegra_sor_crc_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int tegra_sor_show_regs(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
struct drm_info_node *node = s->private;
|
||||||
|
struct tegra_sor *sor = node->info_ent->data;
|
||||||
|
|
||||||
|
#define DUMP_REG(name) \
|
||||||
|
seq_printf(s, "%-38s %#05x %08x\n", #name, name, \
|
||||||
|
tegra_sor_readl(sor, name))
|
||||||
|
|
||||||
|
DUMP_REG(SOR_CTXSW);
|
||||||
|
DUMP_REG(SOR_SUPER_STATE_0);
|
||||||
|
DUMP_REG(SOR_SUPER_STATE_1);
|
||||||
|
DUMP_REG(SOR_STATE_0);
|
||||||
|
DUMP_REG(SOR_STATE_1);
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_0(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_0(1));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_1(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_1(1));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_2(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_2(1));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_3(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_3(1));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_4(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_4(1));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_5(0));
|
||||||
|
DUMP_REG(SOR_HEAD_STATE_5(1));
|
||||||
|
DUMP_REG(SOR_CRC_CNTRL);
|
||||||
|
DUMP_REG(SOR_DP_DEBUG_MVID);
|
||||||
|
DUMP_REG(SOR_CLK_CNTRL);
|
||||||
|
DUMP_REG(SOR_CAP);
|
||||||
|
DUMP_REG(SOR_PWR);
|
||||||
|
DUMP_REG(SOR_TEST);
|
||||||
|
DUMP_REG(SOR_PLL_0);
|
||||||
|
DUMP_REG(SOR_PLL_1);
|
||||||
|
DUMP_REG(SOR_PLL_2);
|
||||||
|
DUMP_REG(SOR_PLL_3);
|
||||||
|
DUMP_REG(SOR_CSTM);
|
||||||
|
DUMP_REG(SOR_LVDS);
|
||||||
|
DUMP_REG(SOR_CRC_A);
|
||||||
|
DUMP_REG(SOR_CRC_B);
|
||||||
|
DUMP_REG(SOR_BLANK);
|
||||||
|
DUMP_REG(SOR_SEQ_CTL);
|
||||||
|
DUMP_REG(SOR_LANE_SEQ_CTL);
|
||||||
|
DUMP_REG(SOR_SEQ_INST(0));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(1));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(2));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(3));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(4));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(5));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(6));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(7));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(8));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(9));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(10));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(11));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(12));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(13));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(14));
|
||||||
|
DUMP_REG(SOR_SEQ_INST(15));
|
||||||
|
DUMP_REG(SOR_PWM_DIV);
|
||||||
|
DUMP_REG(SOR_PWM_CTL);
|
||||||
|
DUMP_REG(SOR_VCRC_A_0);
|
||||||
|
DUMP_REG(SOR_VCRC_A_1);
|
||||||
|
DUMP_REG(SOR_VCRC_B_0);
|
||||||
|
DUMP_REG(SOR_VCRC_B_1);
|
||||||
|
DUMP_REG(SOR_CCRC_A_0);
|
||||||
|
DUMP_REG(SOR_CCRC_A_1);
|
||||||
|
DUMP_REG(SOR_CCRC_B_0);
|
||||||
|
DUMP_REG(SOR_CCRC_B_1);
|
||||||
|
DUMP_REG(SOR_EDATA_A_0);
|
||||||
|
DUMP_REG(SOR_EDATA_A_1);
|
||||||
|
DUMP_REG(SOR_EDATA_B_0);
|
||||||
|
DUMP_REG(SOR_EDATA_B_1);
|
||||||
|
DUMP_REG(SOR_COUNT_A_0);
|
||||||
|
DUMP_REG(SOR_COUNT_A_1);
|
||||||
|
DUMP_REG(SOR_COUNT_B_0);
|
||||||
|
DUMP_REG(SOR_COUNT_B_1);
|
||||||
|
DUMP_REG(SOR_DEBUG_A_0);
|
||||||
|
DUMP_REG(SOR_DEBUG_A_1);
|
||||||
|
DUMP_REG(SOR_DEBUG_B_0);
|
||||||
|
DUMP_REG(SOR_DEBUG_B_1);
|
||||||
|
DUMP_REG(SOR_TRIG);
|
||||||
|
DUMP_REG(SOR_MSCHECK);
|
||||||
|
DUMP_REG(SOR_XBAR_CTRL);
|
||||||
|
DUMP_REG(SOR_XBAR_POL);
|
||||||
|
DUMP_REG(SOR_DP_LINKCTL_0);
|
||||||
|
DUMP_REG(SOR_DP_LINKCTL_1);
|
||||||
|
DUMP_REG(SOR_LANE_DRIVE_CURRENT_0);
|
||||||
|
DUMP_REG(SOR_LANE_DRIVE_CURRENT_1);
|
||||||
|
DUMP_REG(SOR_LANE4_DRIVE_CURRENT_0);
|
||||||
|
DUMP_REG(SOR_LANE4_DRIVE_CURRENT_1);
|
||||||
|
DUMP_REG(SOR_LANE_PREEMPHASIS_0);
|
||||||
|
DUMP_REG(SOR_LANE_PREEMPHASIS_1);
|
||||||
|
DUMP_REG(SOR_LANE4_PREEMPHASIS_0);
|
||||||
|
DUMP_REG(SOR_LANE4_PREEMPHASIS_1);
|
||||||
|
DUMP_REG(SOR_LANE_POST_CURSOR_0);
|
||||||
|
DUMP_REG(SOR_LANE_POST_CURSOR_1);
|
||||||
|
DUMP_REG(SOR_DP_CONFIG_0);
|
||||||
|
DUMP_REG(SOR_DP_CONFIG_1);
|
||||||
|
DUMP_REG(SOR_DP_MN_0);
|
||||||
|
DUMP_REG(SOR_DP_MN_1);
|
||||||
|
DUMP_REG(SOR_DP_PADCTL_0);
|
||||||
|
DUMP_REG(SOR_DP_PADCTL_1);
|
||||||
|
DUMP_REG(SOR_DP_DEBUG_0);
|
||||||
|
DUMP_REG(SOR_DP_DEBUG_1);
|
||||||
|
DUMP_REG(SOR_DP_SPARE_0);
|
||||||
|
DUMP_REG(SOR_DP_SPARE_1);
|
||||||
|
DUMP_REG(SOR_DP_AUDIO_CTRL);
|
||||||
|
DUMP_REG(SOR_DP_AUDIO_HBLANK_SYMBOLS);
|
||||||
|
DUMP_REG(SOR_DP_AUDIO_VBLANK_SYMBOLS);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_HEADER);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_0);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_1);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_2);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_3);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_4);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_5);
|
||||||
|
DUMP_REG(SOR_DP_GENERIC_INFOFRAME_SUBPACK_6);
|
||||||
|
DUMP_REG(SOR_DP_TPG);
|
||||||
|
DUMP_REG(SOR_DP_TPG_CONFIG);
|
||||||
|
DUMP_REG(SOR_DP_LQ_CSTM_0);
|
||||||
|
DUMP_REG(SOR_DP_LQ_CSTM_1);
|
||||||
|
DUMP_REG(SOR_DP_LQ_CSTM_2);
|
||||||
|
|
||||||
|
#undef DUMP_REG
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_info_list debugfs_files[] = {
|
||||||
|
{ "regs", tegra_sor_show_regs, 0, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
static int tegra_sor_debugfs_init(struct tegra_sor *sor,
|
static int tegra_sor_debugfs_init(struct tegra_sor *sor,
|
||||||
struct drm_minor *minor)
|
struct drm_minor *minor)
|
||||||
{
|
{
|
||||||
struct dentry *entry;
|
struct dentry *entry;
|
||||||
|
unsigned int i;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root);
|
sor->debugfs = debugfs_create_dir("sor", minor->debugfs_root);
|
||||||
if (!sor->debugfs)
|
if (!sor->debugfs)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
entry = debugfs_create_file("crc", 0644, sor->debugfs, sor,
|
sor->debugfs_files = kmemdup(debugfs_files, sizeof(debugfs_files),
|
||||||
&tegra_sor_crc_fops);
|
GFP_KERNEL);
|
||||||
if (!entry) {
|
if (!sor->debugfs_files) {
|
||||||
dev_err(sor->dev,
|
|
||||||
"cannot create /sys/kernel/debug/dri/%s/sor/crc\n",
|
|
||||||
minor->debugfs_root->d_name.name);
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto remove;
|
goto remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(debugfs_files); i++)
|
||||||
|
sor->debugfs_files[i].data = sor;
|
||||||
|
|
||||||
|
err = drm_debugfs_create_files(sor->debugfs_files,
|
||||||
|
ARRAY_SIZE(debugfs_files),
|
||||||
|
sor->debugfs, minor);
|
||||||
|
if (err < 0)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
entry = debugfs_create_file("crc", 0644, sor->debugfs, sor,
|
||||||
|
&tegra_sor_crc_fops);
|
||||||
|
if (!entry) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
free:
|
||||||
|
kfree(sor->debugfs_files);
|
||||||
|
sor->debugfs_files = NULL;
|
||||||
remove:
|
remove:
|
||||||
debugfs_remove(sor->debugfs);
|
debugfs_remove_recursive(sor->debugfs);
|
||||||
sor->debugfs = NULL;
|
sor->debugfs = NULL;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
|
static void tegra_sor_debugfs_exit(struct tegra_sor *sor)
|
||||||
{
|
{
|
||||||
debugfs_remove_recursive(sor->debugfs);
|
drm_debugfs_remove_files(sor->debugfs_files, ARRAY_SIZE(debugfs_files),
|
||||||
|
sor->minor);
|
||||||
|
sor->minor = NULL;
|
||||||
|
|
||||||
|
kfree(sor->debugfs_files);
|
||||||
sor->debugfs = NULL;
|
sor->debugfs = NULL;
|
||||||
|
|
||||||
|
debugfs_remove_recursive(sor->debugfs);
|
||||||
|
sor->debugfs_files = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
|
static void tegra_sor_connector_dpms(struct drm_connector *connector, int mode)
|
||||||
|
@ -791,8 +949,8 @@ static void tegra_sor_encoder_mode_set(struct drm_encoder *encoder,
|
||||||
struct tegra_sor_config config;
|
struct tegra_sor_config config;
|
||||||
struct drm_dp_link link;
|
struct drm_dp_link link;
|
||||||
struct drm_dp_aux *aux;
|
struct drm_dp_aux *aux;
|
||||||
unsigned long value;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
u32 value;
|
||||||
|
|
||||||
mutex_lock(&sor->lock);
|
mutex_lock(&sor->lock);
|
||||||
|
|
||||||
|
@ -1354,12 +1512,30 @@ static int tegra_sor_init(struct host1x_client *client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: Remove this reset once proper hand-over from firmware to
|
||||||
|
* kernel is possible.
|
||||||
|
*/
|
||||||
|
err = reset_control_assert(sor->rst);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(sor->dev, "failed to assert SOR reset: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(sor->clk);
|
err = clk_prepare_enable(sor->clk);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(sor->dev, "failed to enable clock: %d\n", err);
|
dev_err(sor->dev, "failed to enable clock: %d\n", err);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
usleep_range(1000, 3000);
|
||||||
|
|
||||||
|
err = reset_control_deassert(sor->rst);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(sor->dev, "failed to deassert SOR reset: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(sor->clk_safe);
|
err = clk_prepare_enable(sor->clk_safe);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -425,6 +425,12 @@ u32 host1x_syncpt_read_min(struct host1x_syncpt *sp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(host1x_syncpt_read_min);
|
EXPORT_SYMBOL(host1x_syncpt_read_min);
|
||||||
|
|
||||||
|
u32 host1x_syncpt_read(struct host1x_syncpt *sp)
|
||||||
|
{
|
||||||
|
return host1x_syncpt_load(sp);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_syncpt_read);
|
||||||
|
|
||||||
int host1x_syncpt_nb_pts(struct host1x *host)
|
int host1x_syncpt_nb_pts(struct host1x *host)
|
||||||
{
|
{
|
||||||
return host->info->nb_pts;
|
return host->info->nb_pts;
|
||||||
|
|
|
@ -87,20 +87,34 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,
|
||||||
|
|
||||||
/* default implementations for state handling */
|
/* default implementations for state handling */
|
||||||
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
|
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc);
|
||||||
|
void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *state);
|
||||||
struct drm_crtc_state *
|
struct drm_crtc_state *
|
||||||
drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
|
drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc);
|
||||||
|
void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||||
|
struct drm_crtc_state *state);
|
||||||
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
||||||
struct drm_crtc_state *state);
|
struct drm_crtc_state *state);
|
||||||
|
|
||||||
void drm_atomic_helper_plane_reset(struct drm_plane *plane);
|
void drm_atomic_helper_plane_reset(struct drm_plane *plane);
|
||||||
|
void __drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *state);
|
||||||
struct drm_plane_state *
|
struct drm_plane_state *
|
||||||
drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
|
drm_atomic_helper_plane_duplicate_state(struct drm_plane *plane);
|
||||||
|
void __drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||||
|
struct drm_plane_state *state);
|
||||||
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane,
|
||||||
struct drm_plane_state *state);
|
struct drm_plane_state *state);
|
||||||
|
|
||||||
void drm_atomic_helper_connector_reset(struct drm_connector *connector);
|
void drm_atomic_helper_connector_reset(struct drm_connector *connector);
|
||||||
|
void
|
||||||
|
__drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector,
|
||||||
|
struct drm_connector_state *state);
|
||||||
struct drm_connector_state *
|
struct drm_connector_state *
|
||||||
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
|
drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector);
|
||||||
|
void
|
||||||
|
__drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||||
|
struct drm_connector_state *state);
|
||||||
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||||
struct drm_connector_state *state);
|
struct drm_connector_state *state);
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,7 @@ struct host1x_syncpt *host1x_syncpt_get(struct host1x *host, u32 id);
|
||||||
u32 host1x_syncpt_id(struct host1x_syncpt *sp);
|
u32 host1x_syncpt_id(struct host1x_syncpt *sp);
|
||||||
u32 host1x_syncpt_read_min(struct host1x_syncpt *sp);
|
u32 host1x_syncpt_read_min(struct host1x_syncpt *sp);
|
||||||
u32 host1x_syncpt_read_max(struct host1x_syncpt *sp);
|
u32 host1x_syncpt_read_max(struct host1x_syncpt *sp);
|
||||||
|
u32 host1x_syncpt_read(struct host1x_syncpt *sp);
|
||||||
int host1x_syncpt_incr(struct host1x_syncpt *sp);
|
int host1x_syncpt_incr(struct host1x_syncpt *sp);
|
||||||
u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
|
u32 host1x_syncpt_incr_max(struct host1x_syncpt *sp, u32 incrs);
|
||||||
int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
|
int host1x_syncpt_wait(struct host1x_syncpt *sp, u32 thresh, long timeout,
|
||||||
|
|
|
@ -36,7 +36,8 @@ struct drm_tegra_gem_create {
|
||||||
|
|
||||||
struct drm_tegra_gem_mmap {
|
struct drm_tegra_gem_mmap {
|
||||||
__u32 handle;
|
__u32 handle;
|
||||||
__u32 offset;
|
__u32 pad;
|
||||||
|
__u64 offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drm_tegra_syncpt_read {
|
struct drm_tegra_syncpt_read {
|
||||||
|
|
Loading…
Reference in New Issue