Commit 9a1123e8 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm/tegra/for-4.5-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next

drm/tegra: Changes for v4.5-rc1

This adds support for the version of host1x found on Tegra210 SoCs. It
also makes use of the new atomic suspend/resume functionality to bring
this feature to Tegra.

Other than that it's mostly small fixes and cleanups, with some prep-
work for things that will hopefully get merged for the next release.

* tag 'drm/tegra/for-4.5-rc1' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: Advertise DRIVER_ATOMIC
  drm/tegra: Use DRIVER level for IOMMU aperture message
  drm/tegra: checking for IS_ERR() instead of NULL
  drm/tegra: dc: Add missing of_node_put()
  drm/tegra: Implement subsystem-level suspend/resume
  drm/tegra: sor: Remove unnecessary conditional
  drm/tegra: sor: Operate on struct drm_dp_aux *
  drm/tegra: Use drm_gem_object_unreference_unlocked()
  drm/tegra: Don't take dev->struct_mutex in mmap offset ioctl
  drm/tegra: Use unlocked gem unreferencing
  drm/tegra: Use new multi-driver module helpers
  gpu: host1x: Add Tegra210 support
  gpu: host1x: Remove core driver on unregister
  gpu: host1x: Use platform_register/unregister_drivers()
parents 07ade844 ad906599
......@@ -1955,8 +1955,10 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc)
* cases where only a single display controller is used.
*/
for_each_matching_node(np, tegra_dc_of_match) {
if (np == dc->dev->of_node)
if (np == dc->dev->of_node) {
of_node_put(np);
break;
}
value++;
}
......
......@@ -436,7 +436,7 @@ struct platform_driver tegra_dpaux_driver = {
.remove = tegra_dpaux_remove,
};
struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)
{
struct tegra_dpaux *dpaux;
......@@ -445,7 +445,7 @@ struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
list_for_each_entry(dpaux, &dpaux_list, list)
if (np == dpaux->dev->of_node) {
mutex_unlock(&dpaux_lock);
return dpaux;
return &dpaux->aux;
}
mutex_unlock(&dpaux_lock);
......@@ -453,8 +453,9 @@ struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
return NULL;
}
int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output)
{
struct tegra_dpaux *dpaux = to_dpaux(aux);
unsigned long timeout;
int err;
......@@ -470,7 +471,7 @@ int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
while (time_before(jiffies, timeout)) {
enum drm_connector_status status;
status = tegra_dpaux_detect(dpaux);
status = drm_dp_aux_detect(aux);
if (status == connector_status_connected) {
enable_irq(dpaux->irq);
return 0;
......@@ -482,8 +483,9 @@ int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
return -ETIMEDOUT;
}
int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
int drm_dp_aux_detach(struct drm_dp_aux *aux)
{
struct tegra_dpaux *dpaux = to_dpaux(aux);
unsigned long timeout;
int err;
......@@ -498,7 +500,7 @@ int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
while (time_before(jiffies, timeout)) {
enum drm_connector_status status;
status = tegra_dpaux_detect(dpaux);
status = drm_dp_aux_detect(aux);
if (status == connector_status_disconnected) {
dpaux->output = NULL;
return 0;
......@@ -510,8 +512,9 @@ int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
return -ETIMEDOUT;
}
enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux)
{
struct tegra_dpaux *dpaux = to_dpaux(aux);
u32 value;
value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
......@@ -522,8 +525,9 @@ enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
return connector_status_disconnected;
}
int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
int drm_dp_aux_enable(struct drm_dp_aux *aux)
{
struct tegra_dpaux *dpaux = to_dpaux(aux);
u32 value;
value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
......@@ -540,8 +544,9 @@ int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
return 0;
}
int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
int drm_dp_aux_disable(struct drm_dp_aux *aux)
{
struct tegra_dpaux *dpaux = to_dpaux(aux);
u32 value;
value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
......@@ -551,11 +556,11 @@ int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
return 0;
}
int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding)
{
int err;
err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
err = drm_dp_dpcd_writeb(aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
encoding);
if (err < 0)
return err;
......@@ -563,15 +568,15 @@ int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
return 0;
}
int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
u8 pattern)
int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
u8 pattern)
{
u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
u8 status[DP_LINK_STATUS_SIZE], values[4];
unsigned int i;
int err;
err = drm_dp_dpcd_writeb(&dpaux->aux, DP_TRAINING_PATTERN_SET, pattern);
err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, pattern);
if (err < 0)
return err;
......@@ -584,14 +589,14 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
DP_TRAIN_MAX_SWING_REACHED |
DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
err = drm_dp_dpcd_write(&dpaux->aux, DP_TRAINING_LANE0_SET, values,
err = drm_dp_dpcd_write(aux, DP_TRAINING_LANE0_SET, values,
link->num_lanes);
if (err < 0)
return err;
usleep_range(500, 1000);
err = drm_dp_dpcd_read_link_status(&dpaux->aux, status);
err = drm_dp_dpcd_read_link_status(aux, status);
if (err < 0)
return err;
......@@ -609,11 +614,11 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
break;
default:
dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
dev_err(aux->dev, "unsupported training pattern %u\n", tp);
return -EINVAL;
}
err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
err = drm_dp_dpcd_writeb(aux, DP_EDP_CONFIGURATION_SET, 0);
if (err < 0)
return err;
......
......@@ -137,8 +137,8 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
start = geometry->aperture_start;
end = geometry->aperture_end;
DRM_DEBUG("IOMMU context initialized (aperture: %#llx-%#llx)\n",
start, end);
DRM_DEBUG_DRIVER("IOMMU aperture initialized (%#llx-%#llx)\n",
start, end);
drm_mm_init(&tegra->mm, start, end - start + 1);
}
......@@ -277,9 +277,7 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
if (!gem)
return NULL;
mutex_lock(&drm->struct_mutex);
drm_gem_object_unreference(gem);
mutex_unlock(&drm->struct_mutex);
drm_gem_object_unreference_unlocked(gem);
bo = to_tegra_bo(gem);
return &bo->base;
......@@ -473,7 +471,7 @@ static int tegra_gem_mmap(struct drm_device *drm, void *data,
args->offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
drm_gem_object_unreference(gem);
drm_gem_object_unreference_unlocked(gem);
return 0;
}
......@@ -683,7 +681,7 @@ static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
bo->tiling.mode = mode;
bo->tiling.value = value;
drm_gem_object_unreference(gem);
drm_gem_object_unreference_unlocked(gem);
return 0;
}
......@@ -723,7 +721,7 @@ static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
break;
}
drm_gem_object_unreference(gem);
drm_gem_object_unreference_unlocked(gem);
return err;
}
......@@ -748,7 +746,7 @@ static int tegra_gem_set_flags(struct drm_device *drm, void *data,
if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
bo->flags |= TEGRA_BO_BOTTOM_UP;
drm_gem_object_unreference(gem);
drm_gem_object_unreference_unlocked(gem);
return 0;
}
......@@ -770,7 +768,7 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data,
if (bo->flags & TEGRA_BO_BOTTOM_UP)
args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
drm_gem_object_unreference(gem);
drm_gem_object_unreference_unlocked(gem);
return 0;
}
......@@ -921,7 +919,8 @@ static void tegra_debugfs_cleanup(struct drm_minor *minor)
#endif
static struct drm_driver tegra_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
DRIVER_ATOMIC,
.load = tegra_drm_load,
.unload = tegra_drm_unload,
.open = tegra_drm_open,
......@@ -1023,8 +1022,17 @@ static int host1x_drm_remove(struct host1x_device *dev)
static int host1x_drm_suspend(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_kms_helper_poll_disable(drm);
tegra_drm_fb_suspend(drm);
tegra->state = drm_atomic_helper_suspend(drm);
if (IS_ERR(tegra->state)) {
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
return PTR_ERR(tegra->state);
}
return 0;
}
......@@ -1032,7 +1040,10 @@ static int host1x_drm_suspend(struct device *dev)
static int host1x_drm_resume(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
struct tegra_drm *tegra = drm->dev_private;
drm_atomic_helper_resume(drm, tegra->state);
tegra_drm_fb_resume(drm);
drm_kms_helper_poll_enable(drm);
return 0;
......@@ -1076,6 +1087,16 @@ static struct host1x_driver host1x_drm_driver = {
.subdevs = host1x_drm_subdevs,
};
static struct platform_driver * const drivers[] = {
&tegra_dc_driver,
&tegra_hdmi_driver,
&tegra_dsi_driver,
&tegra_dpaux_driver,
&tegra_sor_driver,
&tegra_gr2d_driver,
&tegra_gr3d_driver,
};
static int __init host1x_drm_init(void)
{
int err;
......@@ -1084,48 +1105,12 @@ static int __init host1x_drm_init(void)
if (err < 0)
return err;
err = platform_driver_register(&tegra_dc_driver);
err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
if (err < 0)
goto unregister_host1x;
err = platform_driver_register(&tegra_dsi_driver);
if (err < 0)
goto unregister_dc;
err = platform_driver_register(&tegra_sor_driver);
if (err < 0)
goto unregister_dsi;
err = platform_driver_register(&tegra_hdmi_driver);
if (err < 0)
goto unregister_sor;
err = platform_driver_register(&tegra_dpaux_driver);
if (err < 0)
goto unregister_hdmi;
err = platform_driver_register(&tegra_gr2d_driver);
if (err < 0)
goto unregister_dpaux;
err = platform_driver_register(&tegra_gr3d_driver);
if (err < 0)
goto unregister_gr2d;
return 0;
unregister_gr2d:
platform_driver_unregister(&tegra_gr2d_driver);
unregister_dpaux:
platform_driver_unregister(&tegra_dpaux_driver);
unregister_hdmi:
platform_driver_unregister(&tegra_hdmi_driver);
unregister_sor:
platform_driver_unregister(&tegra_sor_driver);
unregister_dsi:
platform_driver_unregister(&tegra_dsi_driver);
unregister_dc:
platform_driver_unregister(&tegra_dc_driver);
unregister_host1x:
host1x_driver_unregister(&host1x_drm_driver);
return err;
......@@ -1134,13 +1119,7 @@ module_init(host1x_drm_init);
static void __exit host1x_drm_exit(void)
{
platform_driver_unregister(&tegra_gr3d_driver);
platform_driver_unregister(&tegra_gr2d_driver);
platform_driver_unregister(&tegra_dpaux_driver);
platform_driver_unregister(&tegra_hdmi_driver);
platform_driver_unregister(&tegra_sor_driver);
platform_driver_unregister(&tegra_dsi_driver);
platform_driver_unregister(&tegra_dc_driver);
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
host1x_driver_unregister(&host1x_drm_driver);
}
module_exit(host1x_drm_exit);
......
......@@ -57,6 +57,8 @@ struct tegra_drm {
struct work_struct work;
struct mutex lock;
} commit;
struct drm_atomic_state *state;
};
struct tegra_drm_client;
......@@ -247,18 +249,17 @@ void tegra_output_connector_destroy(struct drm_connector *connector);
void tegra_output_encoder_destroy(struct drm_encoder *encoder);
/* from dpaux.c */
struct tegra_dpaux;
struct drm_dp_link;
struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np);
enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux);
int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output);
int tegra_dpaux_detach(struct tegra_dpaux *dpaux);
int tegra_dpaux_enable(struct tegra_dpaux *dpaux);
int tegra_dpaux_disable(struct tegra_dpaux *dpaux);
int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding);
int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
u8 pattern);
struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np);
enum drm_connector_status drm_dp_aux_detect(struct drm_dp_aux *aux);
int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output);
int drm_dp_aux_detach(struct drm_dp_aux *aux);
int drm_dp_aux_enable(struct drm_dp_aux *aux);
int drm_dp_aux_disable(struct drm_dp_aux *aux);
int drm_dp_aux_prepare(struct drm_dp_aux *aux, u8 encoding);
int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
u8 pattern);
/* from fb.c */
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
......@@ -273,16 +274,18 @@ int tegra_drm_fb_prepare(struct drm_device *drm);
void tegra_drm_fb_free(struct drm_device *drm);
int tegra_drm_fb_init(struct drm_device *drm);
void tegra_drm_fb_exit(struct drm_device *drm);
void tegra_drm_fb_suspend(struct drm_device *drm);
void tegra_drm_fb_resume(struct drm_device *drm);
#ifdef CONFIG_DRM_FBDEV_EMULATION
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev);
void tegra_fb_output_poll_changed(struct drm_device *drm);
#endif
extern struct platform_driver tegra_dc_driver;
extern struct platform_driver tegra_dsi_driver;
extern struct platform_driver tegra_sor_driver;
extern struct platform_driver tegra_hdmi_driver;
extern struct platform_driver tegra_dsi_driver;
extern struct platform_driver tegra_dpaux_driver;
extern struct platform_driver tegra_sor_driver;
extern struct platform_driver tegra_gr2d_driver;
extern struct platform_driver tegra_gr3d_driver;
......
......@@ -10,6 +10,8 @@
* published by the Free Software Foundation.
*/
#include <linux/console.h>
#include "drm.h"
#include "gem.h"
......@@ -413,3 +415,25 @@ void tegra_drm_fb_exit(struct drm_device *drm)
tegra_fbdev_exit(tegra->fbdev);
#endif
}
void tegra_drm_fb_suspend(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 1);
console_unlock();
#endif
}
void tegra_drm_fb_resume(struct drm_device *drm)
{
#ifdef CONFIG_DRM_FBDEV_EMULATION
struct tegra_drm *tegra = drm->dev_private;
console_lock();
drm_fb_helper_set_suspend(&tegra->fbdev->base, 0);
console_unlock();
#endif
}
......@@ -28,11 +28,8 @@ static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
static void tegra_bo_put(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
struct drm_device *drm = obj->gem.dev;
mutex_lock(&drm->struct_mutex);
drm_gem_object_unreference(&obj->gem);
mutex_unlock(&drm->struct_mutex);
drm_gem_object_unreference_unlocked(&obj->gem);
}
static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt)
......@@ -72,11 +69,8 @@ static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page,
static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
struct drm_device *drm = obj->gem.dev;
mutex_lock(&drm->struct_mutex);
drm_gem_object_reference(&obj->gem);
mutex_unlock(&drm->struct_mutex);
return bo;
}
......@@ -408,12 +402,9 @@ int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
struct drm_gem_object *gem;
struct tegra_bo *bo;
mutex_lock(&drm->struct_mutex);
gem = drm_gem_object_lookup(drm, file, handle);
if (!gem) {
dev_err(drm->dev, "failed to lookup GEM object\n");
mutex_unlock(&drm->struct_mutex);
return -EINVAL;
}
......@@ -421,9 +412,7 @@ int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm,
*offset = drm_vma_node_offset_addr(&bo->gem.vma_node);
drm_gem_object_unreference(gem);
mutex_unlock(&drm->struct_mutex);
drm_gem_object_unreference_unlocked(gem);
return 0;
}
......
......@@ -173,7 +173,7 @@ struct tegra_sor {
struct clk *clk_dp;
struct clk *clk;
struct tegra_dpaux *dpaux;
struct drm_dp_aux *aux;
struct drm_info_list *debugfs_files;
struct drm_minor *minor;
......@@ -273,7 +273,7 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
SOR_DP_PADCTL_CM_TXD_1 | SOR_DP_PADCTL_CM_TXD_0);
tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
err = tegra_dpaux_prepare(sor->dpaux, DP_SET_ANSI_8B10B);
err = drm_dp_aux_prepare(sor->aux, DP_SET_ANSI_8B10B);
if (err < 0)
return err;
......@@ -288,7 +288,7 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
pattern = DP_TRAINING_PATTERN_1;
err = tegra_dpaux_train(sor->dpaux, link, pattern);
err = drm_dp_aux_train(sor->aux, link, pattern);
if (err < 0)
return err;
......@@ -309,7 +309,7 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
pattern = DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2;
err = tegra_dpaux_train(sor->dpaux, link, pattern);
err = drm_dp_aux_train(sor->aux, link, pattern);
if (err < 0)
return err;
......@@ -324,7 +324,7 @@ static int tegra_sor_dp_train_fast(struct tegra_sor *sor,
pattern = DP_TRAINING_PATTERN_DISABLE;
err = tegra_dpaux_train(sor->dpaux, link, pattern);
err = drm_dp_aux_train(sor->aux, link, pattern);
if (err < 0)
return err;
......@@ -1044,8 +1044,8 @@ tegra_sor_connector_detect(struct drm_connector *connector, bool force)
struct tegra_output *output = connector_to_output(connector);
struct tegra_sor *sor = to_sor(output);
if (sor->dpaux)
return tegra_dpaux_detect(sor->dpaux);
if (sor->aux)
return drm_dp_aux_detect(sor->aux);
return tegra_output_connector_detect(connector, force);
}
......@@ -1066,13 +1066,13 @@ static int tegra_sor_connector_get_modes(struct drm_connector *connector)
struct tegra_sor *sor = to_sor(output);
int err;
if (sor->dpaux)
tegra_dpaux_enable(sor->dpaux);
if (sor->aux)
drm_dp_aux_enable(sor->aux);
err = tegra_output_connector_get_modes(connector);
if (sor->dpaux)
tegra_dpaux_disable(sor->dpaux);
if (sor->aux)
drm_dp_aux_disable(sor->aux);
return err;
}
......@@ -1128,8 +1128,8 @@ static void tegra_sor_edp_disable(struct drm_encoder *encoder)
if (err < 0)
dev_err(sor->dev, "failed to power down SOR: %d\n", err);
if (sor->dpaux) {
err = tegra_dpaux_disable(sor->dpaux);
if (sor->aux) {
err = drm_dp_aux_disable(sor->aux);
if (err < 0)
dev_err(sor->dev, "failed to disable DP: %d\n", err);
}
......@@ -1196,7 +1196,7 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
struct tegra_sor *sor = to_sor(output);
struct tegra_sor_config config;
struct drm_dp_link link;
struct drm_dp_aux *aux;
u8 rate, lanes;
int err = 0;
u32 value;
......@@ -1209,20 +1209,14 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
if (output->panel)
drm_panel_prepare(output->panel);
/* FIXME: properly convert to struct drm_dp_aux */
aux = (struct drm_dp_aux *)sor->dpaux;
if (sor->dpaux) {
err = tegra_dpaux_enable(sor->dpaux);
if (err < 0)
dev_err(sor->dev, "failed to enable DP: %d\n", err);
err = drm_dp_aux_enable(sor->aux);
if (err < 0)
dev_err(sor->dev, "failed to enable DP: %d\n", err);
err = drm_dp_link_probe(aux, &link);
if (err < 0) {
dev_err(sor->dev, "failed to probe eDP link: %d\n",
err);
return;
}
err = drm_dp_link_probe(sor->aux, &link);
if (err < 0) {
dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
return;
}
err = clk_set_parent(sor->clk, sor->clk_safe);
......@@ -1434,60 +1428,51 @@ static void tegra_sor_edp_enable(struct drm_encoder *encoder)
value |= SOR_DP_PADCTL_PAD_CAL_PD;
tegra_sor_writel(sor, value, SOR_DP_PADCTL0);
if (sor->dpaux) {
u8 rate, lanes;
err = drm_dp_link_probe(aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to probe eDP link: %d\n",
err);
err = drm_dp_link_probe(sor->aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to probe eDP link: %d\n", err);
err = drm_dp_link_power_up(aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to power up eDP link: %d\n",
err);
err = drm_dp_link_power_up(sor->aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to power up eDP link: %d\n", err);
err = drm_dp_link_configure(aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to configure eDP link: %d\n",
err);
err = drm_dp_link_configure(sor->aux, &link);
if (err < 0)
dev_err(sor->dev, "failed to configure eDP link: %d\n", err);
rate = drm_dp_link_rate_to_bw_code(link.rate);
lanes = link.num_lanes;
rate = drm_dp_link_rate_to_bw_code(link.rate);
lanes = link.num_lanes;
value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
value = tegra_sor_readl(sor, SOR_CLK_CNTRL);
value &= ~SOR_CLK_CNTRL_DP_LINK_SPEED_MASK;
value |= SOR_CLK_CNTRL_DP_LINK_SPEED(rate);
tegra_sor_writel(sor, value, SOR_CLK_CNTRL);
value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
value = tegra_sor_readl(sor, SOR_DP_LINKCTL0);
value &= ~SOR_DP_LINKCTL_LANE_COUNT_MASK;
value |= SOR_DP_LINKCTL_LANE_COUNT(lanes);
if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
if (link.capabilities & DP_LINK_CAP_ENHANCED_FRAMING)
value |= SOR_DP_LINKCTL_ENHANCED_FRAME;
tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
tegra_sor_writel(sor, value, SOR_DP_LINKCTL0);
/* disable training pattern generator */
/* disable training pattern generator */
for (i = 0; i < link.num_lanes; i++) {
unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
SOR_DP_TPG_SCRAMBLER_GALIOS |
SOR_DP_TPG_PATTERN_NONE;
value = (value << 8) | lane;
}
for (i = 0; i < link.num_lanes; i++) {
unsigned long lane = SOR_DP_TPG_CHANNEL_CODING |
SOR_DP_TPG_SCRAMBLER_GALIOS |
SOR_DP_TPG_PATTERN_NONE;
value = (value << 8) | lane;
}
tegra_sor_writel(sor, value, SOR_DP_TPG);
tegra_sor_writel(sor, value, SOR_DP_TPG);
err = tegra_sor_dp_train_fast(sor, &link);
if (err < 0) {
dev_err(sor->dev, "DP fast link training failed: %d\n",
err);
}
err = tegra_sor_dp_train_fast(sor, &link);
if (err < 0)
dev_err(sor->dev, "DP fast link training failed: %d\n", err);
dev_dbg(sor->dev, "fast link training succeeded\n");
}
dev_dbg(sor->dev, "fast link training succeeded\n");
err = tegra_sor_power_up(sor, 250);
if (err < 0)
......@@ -1961,9 +1946,9 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
/* production settings */
settings = tegra_sor_hdmi_find_settings(sor, mode->clock * 1000);
if (IS_ERR(settings)) {
dev_err(sor->dev, "no settings for pixel clock %d Hz: %ld\n",
mode->clock * 1000, PTR_ERR(settings));
if (!settings) {
dev_err(sor->dev, "no settings for pixel clock %d Hz\n",
mode->clock * 1000);
return;
}
......@@ -2148,7 +2133,7 @@ static int tegra_sor_init(struct host1x_client *client)
int encoder = DRM_MODE_ENCODER_NONE;
int err;
if (!sor->dpaux) {
if (!sor->aux) {
if (sor->soc->supports_hdmi) {
connector = DRM_MODE_CONNECTOR_HDMIA;
encoder = DRM_MODE_ENCODER_TMDS;
......@@ -2199,8 +2184,8 @@ static int tegra_sor_init(struct host1x_client *client)
dev_err(sor->dev, "debugfs setup failed: %d\n", err);
}
if (sor->dpaux) {
err = tegra_dpaux_attach(sor->dpaux, &sor->output);
if (sor->aux) {
err = drm_dp_aux_attach(sor->aux, &sor->output);
if (err < 0) {
dev_err(sor->dev, "failed to attach DP: %d\n", err);
return err;
......@@ -2249,8 +2234,8 @@ static int tegra_sor_exit(struct host1x_client *client)
tegra_output_exit(&sor->output);
if (sor->dpaux) {
err = tegra_dpaux_detach(sor->dpaux);
if (sor->aux) {
err = drm_dp_aux_detach(sor->aux);
if (err < 0) {
dev_err(sor->dev, "failed to detach DP: %d\n", err);
return err;
......@@ -2399,14 +2384,14 @@ static int tegra_sor_probe(struct platform_device *pdev)
np = of_parse_phandle(pdev->dev.of_node, "nvidia,dpaux", 0);
if (np) {
sor->dpaux = tegra_dpaux_find_by_of_node(np);
sor->aux = drm_dp_aux_find_by_of_node(np);
of_node_put(np);
if (!sor->dpaux)
if (!sor->aux)
return -EPROBE_DEFER;
}
if (!sor->dpaux) {
if (!sor->aux) {
if (sor->soc->supports_hdmi) {
sor->ops = &tegra_sor_hdmi_ops;
} else if (sor->soc->supports_lvds) {
......
......@@ -10,6 +10,7 @@ host1x-y = \
mipi.o \
hw/host1x01.o \
hw/host1x02.o \
hw/host1x04.o
hw/host1x04.o \
hw/host1x05.o
obj-$(CONFIG_TEGRA_HOST1X) += host1x.o
......@@ -538,6 +538,8 @@ EXPORT_SYMBOL(host1x_driver_register_full);
void host1x_driver_unregister(struct host1x_driver *driver)
{
driver_unregister(&driver->driver);
mutex_lock(&drivers_lock);
list_del_init(&driver->list);
mutex_unlock(&drivers_lock);
......
......@@ -35,6 +35,7 @@
#include "hw/host1x01.h"
#include "hw/host1x02.h"
#include "hw/host1x04.h"
#include "hw/host1x05.h"
void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r)
{
......@@ -87,7 +88,17 @@ static const struct host1x_info host1x04_info = {
.sync_offset = 0x2100,
};
static const struct host1x_info host1x05_info = {
.nb_channels = 14,
.nb_pts = 192,
.nb_mlocks = 16,
.nb_bases = 64,
.init = host1x05_init,
.sync_offset = 0x2100,
};
static struct of_device_id host1x_of_match[] = {
{ .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, },
{ .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, },
{ .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, },
{ .compatible = "nvidia,tegra30-host1x", .data = &host1x01_info, },
......@@ -212,6 +223,11 @@ static struct platform_driver tegra_host1x_driver = {
.remove = host1x_remove,
};
static struct platform_driver * const drivers[] = {
&tegra_host1x_driver,
&tegra_mipi_driver,
};
static int __init tegra_host1x_init(void)
{
int err;
......@@ -220,28 +236,17 @@ static int __init tegra_host1x_init(void)
if (err < 0)
return err;
err = platform_driver_register(&tegra_host1x_driver);
if (err < 0)
goto unregister_bus;
err = platform_driver_register(&tegra_mipi_driver);
err = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
if (err < 0)
goto unregister_host1x;
bus_unregister(&host1x_bus_type);
return 0;
unregister_host1x:
platform_driver_unregister(&tegra_host1x_driver);
unregister_bus:
bus_unregister(&host1x_bus_type);
return err;
}
module_init(tegra_host1x_init);
static void __exit tegra_host1x_exit(void)
{
platform_driver_unregister(&tegra_mipi_driver);
platform_driver_unregister(&tegra_host1x_driver);
platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
bus_unregister(&host1x_bus_type);
}
module_exit(tegra_host1x_exit);
......
/*
* Host1x init for Tegra210 SoCs
*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* include hw specification */
#include "host1x05.h"
#include "host1x05_hardware.h"
/* include code */
#include "cdma_hw.c"
#include "channel_hw.c"
#include "debug_hw.c"
#include "intr_hw.c"
#include "syncpt_hw.c"
#include "../dev.h"
int host1x05_init(struct host1x *host)
{
host->channel_op = &host1x_channel_ops;
host->cdma_op = &host1x_cdma_ops;
host->cdma_pb_op = &host1x_pushbuffer_ops;
host->syncpt_op = &host1x_syncpt_ops;
host->intr_op = &host1x_intr_ops;
host->debug_op = &host1x_debug_ops;
return 0;
}
/*
* Host1x init for Tegra210 SoCs
*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef HOST1X_HOST1X05_H
#define HOST1X_HOST1X05_H
struct host1x;
int host1x05_init(struct host1x *host);
#endif
/*
* Tegra host1x Register Offsets for Tegra210
*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __HOST1X_HOST1X05_HARDWARE_H
#define __HOST1X_HOST1X05_HARDWARE_H
#include <linux/types.h>
#include <linux/bitops.h>
#include "hw_host1x05_channel.h"
#include "hw_host1x05_sync.h"
#include "hw_host1x05_uclass.h"
static inline u32 host1x_class_host_wait_syncpt(
unsigned indx, unsigned threshold)
{
return host1x_uclass_wait_syncpt_indx_f(indx)
| host1x_uclass_wait_syncpt_thresh_f(threshold);
}
static inline u32 host1x_class_host_load_syncpt_base(
unsigned indx, unsigned threshold)
{
return host1x_uclass_load_syncpt_base_base_indx_f(indx)
| host1x_uclass_load_syncpt_base_value_f(threshold);
}
static inline u32 host1x_class_host_wait_syncpt_base(
unsigned indx, unsigned base_indx, unsigned offset)
{
return host1x_uclass_wait_syncpt_base_indx_f(indx)
| host1x_uclass_wait_syncpt_base_base_indx_f(base_indx)
| host1x_uclass_wait_syncpt_base_offset_f(offset);
}
static inline u32 host1x_class_host_incr_syncpt_base(
unsigned base_indx, unsigned offset)
{
return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx)
| host1x_uclass_incr_syncpt_base_offset_f(offset);
}
static inline u32 host1x_class_host_incr_syncpt(
unsigned cond, unsigned indx)
{
return host1x_uclass_incr_syncpt_cond_f(cond)
| host1x_uclass_incr_syncpt_indx_f(indx);
}
static inline u32 host1x_class_host_indoff_reg_write(
unsigned mod_id, unsigned offset, bool auto_inc)
{
u32 v = host1x_uclass_indoff_indbe_f(0xf)
| host1x_uclass_indoff_indmodid_f(mod_id)
| host1x_uclass_indoff_indroffset_f(offset);
if (auto_inc)
v |= host1x_uclass_indoff_autoinc_f(1);
return v;
}
static inline u32 host1x_class_host_indoff_reg_read(
unsigned mod_id, unsigned offset, bool auto_inc)
{
u32 v = host1x_uclass_indoff_indmodid_f(mod_id)
| host1x_uclass_indoff_indroffset_f(offset)
| host1x_uclass_indoff_rwn_read_v();
if (auto_inc)
v |= host1x_uclass_indoff_autoinc_f(1);
return v;
}
/* cdma opcodes */
static inline u32 host1x_opcode_setclass(
unsigned class_id, unsigned offset, unsigned mask)
{
return (0 << 28) | (offset << 16) | (class_id << 6) | mask;
}
static inline u32 host1x_opcode_incr(unsigned offset, unsigned count)
{
return (1 << 28) | (offset << 16) | count;
}
static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count)
{
return (2 << 28) | (offset << 16) | count;
}
static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask)
{
return (3 << 28) | (offset << 16) | mask;
}
static inline u32 host1x_opcode_imm(unsigned offset, unsigned value)
{
return (4 << 28) | (offset << 16) | value;
}
static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx)
{
return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(),
host1x_class_host_incr_syncpt(cond, indx));
}
static inline u32 host1x_opcode_restart(unsigned address)
{
return (5 << 28) | (address >> 4);
}
static inline u32 host1x_opcode_gather(unsigned count)
{
return (6 << 28) | count;
}
static inline u32 host1x_opcode_gather_nonincr(unsigned offset, unsigned count)
{
return (6 << 28) | (offset << 16) | BIT(15) | count;
}
static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count)
{
return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count;
}
#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0)
#endif
/*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Function naming determines intended use:
*
* <x>_r(void) : Returns the offset for register <x>.
*
* <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
*
* <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
*
* <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
* and masked to place it at field <y> of register <x>. This value
* can be |'d with others to produce a full register value for
* register <x>.
*
* <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
* value can be ~'d and then &'d to clear the value of field <y> for
* register <x>.
*
* <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
* to place it at field <y> of register <x>. This value can be |'d
* with others to produce a full register value for <x>.
*
* <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
* <x> value 'r' after being shifted to place its LSB at bit 0.
* This value is suitable for direct comparison with other unshifted
* values appropriate for use in field <y> of register <x>.
*
* <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
* field <y> of register <x>. This value is suitable for direct
* comparison with unshifted values appropriate for use in field <y>
* of register <x>.
*/
#ifndef HOST1X_HW_HOST1X05_CHANNEL_H
#define HOST1X_HW_HOST1X05_CHANNEL_H
static inline u32 host1x_channel_fifostat_r(void)
{
return 0x0;
}
#define HOST1X_CHANNEL_FIFOSTAT \
host1x_channel_fifostat_r()
static inline u32 host1x_channel_fifostat_cfempty_v(u32 r)
{
return (r >> 11) & 0x1;
}
#define HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(r) \
host1x_channel_fifostat_cfempty_v(r)
static inline u32 host1x_channel_dmastart_r(void)
{
return 0x14;
}
#define HOST1X_CHANNEL_DMASTART \
host1x_channel_dmastart_r()
static inline u32 host1x_channel_dmaput_r(void)
{
return 0x18;
}
#define HOST1X_CHANNEL_DMAPUT \
host1x_channel_dmaput_r()
static inline u32 host1x_channel_dmaget_r(void)
{
return 0x1c;
}
#define HOST1X_CHANNEL_DMAGET \
host1x_channel_dmaget_r()
static inline u32 host1x_channel_dmaend_r(void)
{
return 0x20;
}
#define HOST1X_CHANNEL_DMAEND \
host1x_channel_dmaend_r()
static inline u32 host1x_channel_dmactrl_r(void)
{
return 0x24;
}
#define HOST1X_CHANNEL_DMACTRL \
host1x_channel_dmactrl_r()
static inline u32 host1x_channel_dmactrl_dmastop(void)
{
return 1 << 0;
}
#define HOST1X_CHANNEL_DMACTRL_DMASTOP \
host1x_channel_dmactrl_dmastop()
static inline u32 host1x_channel_dmactrl_dmastop_v(u32 r)
{
return (r >> 0) & 0x1;
}
#define HOST1X_CHANNEL_DMACTRL_DMASTOP_V(r) \
host1x_channel_dmactrl_dmastop_v(r)
static inline u32 host1x_channel_dmactrl_dmagetrst(void)
{
return 1 << 1;
}
#define HOST1X_CHANNEL_DMACTRL_DMAGETRST \
host1x_channel_dmactrl_dmagetrst()
static inline u32 host1x_channel_dmactrl_dmainitget(void)
{
return 1 << 2;
}
#define HOST1X_CHANNEL_DMACTRL_DMAINITGET \
host1x_channel_dmactrl_dmainitget()
#endif
/*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Function naming determines intended use:
*
* <x>_r(void) : Returns the offset for register <x>.
*
* <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
*
* <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
*
* <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
* and masked to place it at field <y> of register <x>. This value
* can be |'d with others to produce a full register value for
* register <x>.
*
* <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
* value can be ~'d and then &'d to clear the value of field <y> for
* register <x>.
*
* <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
* to place it at field <y> of register <x>. This value can be |'d
* with others to produce a full register value for <x>.
*
* <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
* <x> value 'r' after being shifted to place its LSB at bit 0.
* This value is suitable for direct comparison with other unshifted
* values appropriate for use in field <y> of register <x>.
*
* <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
* field <y> of register <x>. This value is suitable for direct
* comparison with unshifted values appropriate for use in field <y>
* of register <x>.
*/
#ifndef HOST1X_HW_HOST1X05_SYNC_H
#define HOST1X_HW_HOST1X05_SYNC_H
#define REGISTER_STRIDE 4
static inline u32 host1x_sync_syncpt_r(unsigned int id)
{
return 0xf80 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT(id) \
host1x_sync_syncpt_r(id)
static inline u32 host1x_sync_syncpt_thresh_cpu0_int_status_r(unsigned int id)
{
return 0xe80 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(id) \
host1x_sync_syncpt_thresh_cpu0_int_status_r(id)
static inline u32 host1x_sync_syncpt_thresh_int_disable_r(unsigned int id)
{
return 0xf00 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(id) \
host1x_sync_syncpt_thresh_int_disable_r(id)
static inline u32 host1x_sync_syncpt_thresh_int_enable_cpu0_r(unsigned int id)
{
return 0xf20 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(id) \
host1x_sync_syncpt_thresh_int_enable_cpu0_r(id)
static inline u32 host1x_sync_cf_setup_r(unsigned int channel)
{
return 0xc00 + channel * REGISTER_STRIDE;
}
#define HOST1X_SYNC_CF_SETUP(channel) \
host1x_sync_cf_setup_r(channel)
static inline u32 host1x_sync_cf_setup_base_v(u32 r)
{
return (r >> 0) & 0x3ff;
}
#define HOST1X_SYNC_CF_SETUP_BASE_V(r) \
host1x_sync_cf_setup_base_v(r)
static inline u32 host1x_sync_cf_setup_limit_v(u32 r)
{
return (r >> 16) & 0x3ff;
}
#define HOST1X_SYNC_CF_SETUP_LIMIT_V(r) \
host1x_sync_cf_setup_limit_v(r)
static inline u32 host1x_sync_cmdproc_stop_r(void)
{
return 0xac;
}
#define HOST1X_SYNC_CMDPROC_STOP \
host1x_sync_cmdproc_stop_r()
static inline u32 host1x_sync_ch_teardown_r(void)
{
return 0xb0;
}
#define HOST1X_SYNC_CH_TEARDOWN \
host1x_sync_ch_teardown_r()
static inline u32 host1x_sync_usec_clk_r(void)
{
return 0x1a4;
}
#define HOST1X_SYNC_USEC_CLK \
host1x_sync_usec_clk_r()
static inline u32 host1x_sync_ctxsw_timeout_cfg_r(void)
{
return 0x1a8;
}
#define HOST1X_SYNC_CTXSW_TIMEOUT_CFG \
host1x_sync_ctxsw_timeout_cfg_r()
static inline u32 host1x_sync_ip_busy_timeout_r(void)
{
return 0x1bc;
}
#define HOST1X_SYNC_IP_BUSY_TIMEOUT \
host1x_sync_ip_busy_timeout_r()
static inline u32 host1x_sync_mlock_owner_r(unsigned int id)
{
return 0x340 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_MLOCK_OWNER(id) \
host1x_sync_mlock_owner_r(id)
static inline u32 host1x_sync_mlock_owner_chid_v(u32 r)
{
return (r >> 8) & 0xf;
}
#define HOST1X_SYNC_MLOCK_OWNER_CHID_V(v) \
host1x_sync_mlock_owner_chid_v(v)
static inline u32 host1x_sync_mlock_owner_cpu_owns_v(u32 r)
{
return (r >> 1) & 0x1;
}
#define HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(r) \
host1x_sync_mlock_owner_cpu_owns_v(r)
static inline u32 host1x_sync_mlock_owner_ch_owns_v(u32 r)
{
return (r >> 0) & 0x1;
}
#define HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(r) \
host1x_sync_mlock_owner_ch_owns_v(r)
static inline u32 host1x_sync_syncpt_int_thresh_r(unsigned int id)
{
return 0x1380 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_INT_THRESH(id) \
host1x_sync_syncpt_int_thresh_r(id)
static inline u32 host1x_sync_syncpt_base_r(unsigned int id)
{
return 0x600 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_BASE(id) \
host1x_sync_syncpt_base_r(id)
static inline u32 host1x_sync_syncpt_cpu_incr_r(unsigned int id)
{
return 0xf60 + id * REGISTER_STRIDE;
}
#define HOST1X_SYNC_SYNCPT_CPU_INCR(id) \
host1x_sync_syncpt_cpu_incr_r(id)
static inline u32 host1x_sync_cbread_r(unsigned int channel)
{
return 0xc80 + channel * REGISTER_STRIDE;
}
#define HOST1X_SYNC_CBREAD(channel) \
host1x_sync_cbread_r(channel)
static inline u32 host1x_sync_cfpeek_ctrl_r(void)
{
return 0x74c;
}
#define HOST1X_SYNC_CFPEEK_CTRL \
host1x_sync_cfpeek_ctrl_r()
static inline u32 host1x_sync_cfpeek_ctrl_addr_f(u32 v)
{
return (v & 0x3ff) << 0;
}
#define HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(v) \
host1x_sync_cfpeek_ctrl_addr_f(v)
static inline u32 host1x_sync_cfpeek_ctrl_channr_f(u32 v)
{
return (v & 0xf) << 16;
}
#define HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(v) \
host1x_sync_cfpeek_ctrl_channr_f(v)
static inline u32 host1x_sync_cfpeek_ctrl_ena_f(u32 v)
{
return (v & 0x1) << 31;
}
#define HOST1X_SYNC_CFPEEK_CTRL_ENA_F(v) \
host1x_sync_cfpeek_ctrl_ena_f(v)
static inline u32 host1x_sync_cfpeek_read_r(void)
{
return 0x750;
}
#define HOST1X_SYNC_CFPEEK_READ \
host1x_sync_cfpeek_read_r()
static inline u32 host1x_sync_cfpeek_ptrs_r(void)
{
return 0x754;
}
#define HOST1X_SYNC_CFPEEK_PTRS \
host1x_sync_cfpeek_ptrs_r()
static inline u32 host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(u32 r)
{
return (r >> 0) & 0x3ff;
}
#define HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(r) \
host1x_sync_cfpeek_ptrs_cf_rd_ptr_v(r)
static inline u32 host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(u32 r)
{
return (r >> 16) & 0x3ff;
}
#define HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(r) \
host1x_sync_cfpeek_ptrs_cf_wr_ptr_v(r)
static inline u32 host1x_sync_cbstat_r(unsigned int channel)
{
return 0xcc0 + channel * REGISTER_STRIDE;
}
#define HOST1X_SYNC_CBSTAT(channel) \
host1x_sync_cbstat_r(channel)
static inline u32 host1x_sync_cbstat_cboffset_v(u32 r)
{
return (r >> 0) & 0xffff;
}
#define HOST1X_SYNC_CBSTAT_CBOFFSET_V(r) \
host1x_sync_cbstat_cboffset_v(r)
static inline u32 host1x_sync_cbstat_cbclass_v(u32 r)
{
return (r >> 16) & 0x3ff;
}
#define HOST1X_SYNC_CBSTAT_CBCLASS_V(r) \
host1x_sync_cbstat_cbclass_v(r)
#endif
/*
* Copyright (c) 2015 NVIDIA Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Function naming determines intended use:
*
* <x>_r(void) : Returns the offset for register <x>.
*
* <x>_w(void) : Returns the word offset for word (4 byte) element <x>.
*
* <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits.
*
* <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted
* and masked to place it at field <y> of register <x>. This value
* can be |'d with others to produce a full register value for
* register <x>.
*
* <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This
* value can be ~'d and then &'d to clear the value of field <y> for
* register <x>.
*
* <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted
* to place it at field <y> of register <x>. This value can be |'d
* with others to produce a full register value for <x>.
*
* <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register
* <x> value 'r' after being shifted to place its LSB at bit 0.
* This value is suitable for direct comparison with other unshifted
* values appropriate for use in field <y> of register <x>.
*
* <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for
* field <y> of register <x>. This value is suitable for direct
* comparison with unshifted values appropriate for use in field <y>
* of register <x>.
*/
#ifndef HOST1X_HW_HOST1X05_UCLASS_H
#define HOST1X_HW_HOST1X05_UCLASS_H
static inline u32 host1x_uclass_incr_syncpt_r(void)
{
return 0x0;
}
#define HOST1X_UCLASS_INCR_SYNCPT \
host1x_uclass_incr_syncpt_r()
static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v)
{
return (v & 0xff) << 8;
}
#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \
host1x_uclass_incr_syncpt_cond_f(v)
static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v)
{
return (v & 0xff) << 0;
}
#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \
host1x_uclass_incr_syncpt_indx_f(v)
static inline u32 host1x_uclass_wait_syncpt_r(void)
{
return 0x8;
}
#define HOST1X_UCLASS_WAIT_SYNCPT \
host1x_uclass_wait_syncpt_r()
static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v)
{
return (v & 0xff) << 24;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \
host1x_uclass_wait_syncpt_indx_f(v)
static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v)
{
return (v & 0xffffff) << 0;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \
host1x_uclass_wait_syncpt_thresh_f(v)
static inline u32 host1x_uclass_wait_syncpt_base_r(void)
{
return 0x9;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \
host1x_uclass_wait_syncpt_base_r()
static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v)
{
return (v & 0xff) << 24;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \
host1x_uclass_wait_syncpt_base_indx_f(v)
static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v)
{
return (v & 0xff) << 16;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \
host1x_uclass_wait_syncpt_base_base_indx_f(v)
static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v)
{
return (v & 0xffff) << 0;
}
#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \
host1x_uclass_wait_syncpt_base_offset_f(v)
static inline u32 host1x_uclass_load_syncpt_base_r(void)
{
return 0xb;
}
#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \
host1x_uclass_load_syncpt_base_r()
static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v)
{
return (v & 0xff) << 24;
}
#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \
host1x_uclass_load_syncpt_base_base_indx_f(v)
static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v)
{
return (v & 0xffffff) << 0;
}
#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \
host1x_uclass_load_syncpt_base_value_f(v)
static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v)
{
return (v & 0xff) << 24;
}
#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \
host1x_uclass_incr_syncpt_base_base_indx_f(v)
static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v)
{
return (v & 0xffffff) << 0;
}
#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \
host1x_uclass_incr_syncpt_base_offset_f(v)
static inline u32 host1x_uclass_indoff_r(void)
{
return 0x2d;
}
#define HOST1X_UCLASS_INDOFF \
host1x_uclass_indoff_r()
static inline u32 host1x_uclass_indoff_indbe_f(u32 v)
{
return (v & 0xf) << 28;
}
#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \
host1x_uclass_indoff_indbe_f(v)
static inline u32 host1x_uclass_indoff_autoinc_f(u32 v)
{
return (v & 0x1) << 27;
}
#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \
host1x_uclass_indoff_autoinc_f(v)
static inline u32 host1x_uclass_indoff_indmodid_f(u32 v)
{
return (v & 0xff) << 18;
}
#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \
host1x_uclass_indoff_indmodid_f(v)
static inline u32 host1x_uclass_indoff_indroffset_f(u32 v)
{
return (v & 0xffff) << 2;
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
static inline u32 host1x_uclass_indoff_rwn_read_v(void)
{
return 1;
}
#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \
host1x_uclass_indoff_indroffset_f(v)
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment