Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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++;
		}
+23 −18
Original line number Diff line number Diff line
@@ -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,7 +568,7 @@ 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,
int drm_dp_aux_train(struct drm_dp_aux *aux, struct drm_dp_link *link,
		     u8 pattern)
{
	u8 tp = pattern & DP_TRAINING_PATTERN_MASK;
@@ -571,7 +576,7 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
	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;

+34 −55
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ 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",
		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);
+15 −12
Original line number Diff line number Diff line
@@ -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,17 +249,16 @@ 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,
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 */
@@ -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;

+24 −0
Original line number Diff line number Diff line
@@ -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
}
Loading