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

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

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

drm/tegra: Changes for v4.16-rc1

The bulk of these changes are preparation work and addition of support
for Tegra186. Currently only HDMI output (the primary output on Jetson
TX2) is supported, but the hardware is also capable of doing DSI and
DisplayPort.

Tegra DRM now also uses the atomic commit helpers instead of the open-
coded variant that was only doing half its job. As a bit of a byproduct
of the Tegra186 support the driver also gained HDMI 2.0 as well as zpos
property support.

Along the way there are also a few patches to clean up a few things and
fix minor issues.

* tag 'drm/tegra/for-4.16-rc1-fixes' of git://anongit.freedesktop.org/tegra/linux: (51 commits)
  drm/tegra: dc: Properly cleanup overlay planes
  drm/tegra: dc: Fix possible_crtcs mask for planes
  drm/tegra: dc: Restore YUV overlay support
  drm/tegra: dc: Implement legacy blending
  drm/tegra: Correct timeout in tegra_syncpt_wait
  drm/tegra: gem: Correct iommu_map_sg() error checking
  drm/tegra: dc: Link DC1 to DC0 on Tegra20
  drm/tegra: Fix non-debugfs builds
  drm/tegra: dpaux: Keep reset defaults for hybrid pad parameters
  drm/tegra: Mark Tegra186 display hub PM functions __maybe_unused
  drm/tegra: Use IOMMU groups
  gpu: host1x: Use IOMMU groups
  drm/tegra: Implement zpos property
  drm/tegra: dc: Remove redundant spinlock
  drm/tegra: dc: Use direct offset to plane registers
  drm/tegra: dc: Support more formats
  drm/tegra: fb: Force alpha formats
  drm/tegra: dpaux: Add Tegra186 support
  drm/tegra: dpaux: Implement runtime PM
  drm/tegra: sor: Support HDMI 2.0 modes
  ...
parents 323b20c4 8f62142e
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -206,21 +206,33 @@ of the following host1x client modules:
    - "nvidia,tegra132-sor": for Tegra132
    - "nvidia,tegra210-sor": for Tegra210
    - "nvidia,tegra210-sor1": for Tegra210
    - "nvidia,tegra186-sor": for Tegra186
    - "nvidia,tegra186-sor1": for Tegra186
  - reg: Physical base address and length of the controller's registers.
  - interrupts: The interrupt outputs from the controller.
  - clocks: Must contain an entry for each entry in clock-names.
    See ../clocks/clock-bindings.txt for details.
  - clock-names: Must include the following entries:
    - sor: clock input for the SOR hardware
    - source: source clock for the SOR clock
    - out: SOR output clock
    - parent: input for the pixel clock
    - dp: reference clock for the SOR clock
    - safe: safe reference for the SOR clock during power up

    For Tegra186 and later:
    - pad: SOR pad output clock (on Tegra186 and later)

    Obsolete:
    - source: source clock for the SOR clock (obsolete, use "out" instead)

  - resets: Must contain an entry for each entry in reset-names.
    See ../reset/reset.txt for details.
  - reset-names: Must include the following entries:
    - sor

  Required properties on Tegra186 and later:
  - nvidia,interface: index of the SOR interface

  Optional properties:
  - nvidia,ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing
  - nvidia,hpd-gpio: specifies a GPIO used for hotplug detection
+2 −0
Original line number Diff line number Diff line
@@ -5,6 +5,8 @@ tegra-drm-y := \
	drm.o \
	gem.o \
	fb.o \
	hub.o \
	plane.o \
	dc.o \
	output.o \
	rgb.o \
+1064 −866

File changed.

Preview size limit exceeded, changes collapsed.

+245 −44
Original line number Diff line number Diff line
@@ -18,6 +18,24 @@

struct tegra_output;

struct tegra_dc_state {
	struct drm_crtc_state base;

	struct clk *clk;
	unsigned long pclk;
	unsigned int div;

	u32 planes;
};

static inline struct tegra_dc_state *to_dc_state(struct drm_crtc_state *state)
{
	if (state)
		return container_of(state, struct tegra_dc_state, base);

	return NULL;
}

struct tegra_dc_stats {
	unsigned long frames;
	unsigned long vblank;
@@ -25,21 +43,35 @@ struct tegra_dc_stats {
	unsigned long overflow;
};

struct tegra_windowgroup_soc {
	unsigned int index;
	unsigned int dc;
	const unsigned int *windows;
	unsigned int num_windows;
};

struct tegra_dc_soc_info {
	bool supports_border_color;
	bool supports_background_color;
	bool supports_interlacing;
	bool supports_cursor;
	bool supports_block_linear;
	bool supports_blending;
	unsigned int pitch_align;
	bool has_powergate;
	bool broken_reset;
	bool coupled_pm;
	bool has_nvdisplay;
	const struct tegra_windowgroup_soc *wgrps;
	unsigned int num_wgrps;
	const u32 *primary_formats;
	unsigned int num_primary_formats;
	const u32 *overlay_formats;
	unsigned int num_overlay_formats;
};

struct tegra_dc {
	struct host1x_client client;
	struct host1x_syncpt *syncpt;
	struct device *dev;
	spinlock_t lock;

	struct drm_crtc base;
	unsigned int powergate;
@@ -56,11 +88,6 @@ struct tegra_dc {
	struct list_head list;

	struct drm_info_list *debugfs_files;
	struct drm_minor *minor;
	struct dentry *debugfs;

	/* page-flip handling */
	struct drm_pending_vblank_event *event;

	const struct tegra_dc_soc_info *soc;

@@ -110,6 +137,7 @@ struct tegra_dc_window {
	unsigned int bits_per_pixel;
	unsigned int stride[2];
	unsigned long base[3];
	unsigned int zpos;
	bool bottom_up;

	struct tegra_bo_tiling tiling;
@@ -118,6 +146,7 @@ struct tegra_dc_window {
};

/* from dc.c */
bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev);
void tegra_dc_commit(struct tegra_dc *dc);
int tegra_dc_state_setup_clock(struct tegra_dc *dc,
			       struct drm_crtc_state *crtc_state,
@@ -170,12 +199,23 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define CTXSW_INT                (1 << 0)
#define FRAME_END_INT            (1 << 1)
#define VBLANK_INT               (1 << 2)
#define V_PULSE3_INT             (1 << 4)
#define V_PULSE2_INT             (1 << 5)
#define REGION_CRC_INT           (1 << 6)
#define REG_TMOUT_INT            (1 << 7)
#define WIN_A_UF_INT             (1 << 8)
#define WIN_B_UF_INT             (1 << 9)
#define WIN_C_UF_INT             (1 << 10)
#define MSF_INT                  (1 << 12)
#define WIN_A_OF_INT             (1 << 14)
#define WIN_B_OF_INT             (1 << 15)
#define WIN_C_OF_INT             (1 << 16)
#define HEAD_UF_INT              (1 << 23)
#define SD3_BUCKET_WALK_DONE_INT (1 << 24)
#define DSC_OBUF_UF_INT          (1 << 26)
#define DSC_RBUF_UF_INT          (1 << 27)
#define DSC_BBUF_UF_INT          (1 << 28)
#define DSC_TO_UF_INT            (1 << 29)

#define DC_CMD_SIGNAL_RAISE1			0x03c
#define DC_CMD_SIGNAL_RAISE2			0x03d
@@ -196,6 +236,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define WIN_B_UPDATE    (1 << 10)
#define WIN_C_UPDATE    (1 << 11)
#define CURSOR_UPDATE   (1 << 15)
#define COMMON_ACTREQ   (1 << 16)
#define COMMON_UPDATE   (1 << 17)
#define NC_HOST_TRIG    (1 << 24)

#define DC_CMD_DISPLAY_WINDOW_HEADER		0x042
@@ -238,6 +280,10 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define DC_COM_GPIO_DEBOUNCE_COUNTER		0x328
#define DC_COM_CRC_CHECKSUM_LATCHED		0x329

#define DC_COM_RG_UNDERFLOW			0x365
#define  UNDERFLOW_MODE_RED      (1 << 8)
#define  UNDERFLOW_REPORT_ENABLE (1 << 0)

#define DC_DISP_DISP_SIGNAL_OPTIONS0		0x400
#define H_PULSE0_ENABLE (1 <<  8)
#define H_PULSE1_ENABLE (1 << 10)
@@ -249,10 +295,10 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define HDMI_ENABLE	(1 << 30)
#define DSI_ENABLE	(1 << 29)
#define SOR1_TIMING_CYA	(1 << 27)
#define SOR1_ENABLE	(1 << 26)
#define SOR_ENABLE	(1 << 25)
#define CURSOR_ENABLE	(1 << 16)

#define SOR_ENABLE(x)	(1 << (25 + (x)))

#define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403
#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
#define WINDOW_A_THRESHOLD(x) (((x) & 0x7f) << 16)
@@ -369,6 +415,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define BASE_COLOR_SIZE565     ( 6 << 0)
#define BASE_COLOR_SIZE332     ( 7 << 0)
#define BASE_COLOR_SIZE888     ( 8 << 0)
#define BASE_COLOR_SIZE101010  (10 << 0)
#define BASE_COLOR_SIZE121212  (12 << 0)
#define DITHER_CONTROL_MASK    (3 << 8)
#define DITHER_CONTROL_DISABLE (0 << 8)
#define DITHER_CONTROL_ORDERED (2 << 8)
@@ -383,6 +431,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define BASE_COLOR_SIZE_565    (  6 << 0)
#define BASE_COLOR_SIZE_332    (  7 << 0)
#define BASE_COLOR_SIZE_888    (  8 << 0)
#define BASE_COLOR_SIZE_101010 ( 10 << 0)
#define BASE_COLOR_SIZE_121212 ( 12 << 0)

#define DC_DISP_SHIFT_CLOCK_OPTIONS		0x431
#define  SC1_H_QUALIFIER_NONE	(1 << 16)
@@ -449,6 +499,12 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define DC_DISP_SD_HW_K_VALUES			0x4dd
#define DC_DISP_SD_MAN_K_VALUES			0x4de

#define DC_DISP_BLEND_BACKGROUND_COLOR		0x4e4
#define  BACKGROUND_COLOR_ALPHA(x) (((x) & 0xff) << 24)
#define  BACKGROUND_COLOR_BLUE(x)  (((x) & 0xff) << 16)
#define  BACKGROUND_COLOR_GREEN(x) (((x) & 0xff) << 8)
#define  BACKGROUND_COLOR_RED(x)   (((x) & 0xff) << 0)

#define DC_DISP_INTERLACE_CONTROL		0x4e5
#define  INTERLACE_STATUS (1 << 2)
#define  INTERLACE_START  (1 << 1)
@@ -467,6 +523,35 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define CURSOR_SRC_BLEND_MASK			(3 << 8)
#define CURSOR_ALPHA				0xff

#define DC_WIN_CORE_ACT_CONTROL 0x50e
#define  VCOUNTER (0 << 0)
#define  HCOUNTER (1 << 0)

#define DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLA 0x543
#define  LATENCY_CTL_MODE_ENABLE (1 << 2)

#define DC_WIN_CORE_IHUB_WGRP_LATENCY_CTLB 0x544
#define  WATERMARK_MASK 0x1fffffff

#define DC_WIN_CORE_PRECOMP_WGRP_PIPE_METER 0x560
#define  PIPE_METER_INT(x)  (((x) & 0xff) << 8)
#define  PIPE_METER_FRAC(x) (((x) & 0xff) << 0)

#define DC_WIN_CORE_IHUB_WGRP_POOL_CONFIG 0x561
#define  MEMPOOL_ENTRIES(x) (((x) & 0xffff) << 0)

#define DC_WIN_CORE_IHUB_WGRP_FETCH_METER 0x562
#define  SLOTS(x) (((x) & 0xff) << 0)

#define DC_WIN_CORE_IHUB_LINEBUF_CONFIG 0x563
#define  MODE_TWO_LINES  (0 << 14)
#define  MODE_FOUR_LINES (1 << 14)

#define DC_WIN_CORE_IHUB_THREAD_GROUP 0x568
#define  THREAD_NUM_MASK (0x1f << 1)
#define  THREAD_NUM(x) (((x) & 0x1f) << 1)
#define  THREAD_GROUP_ENABLE (1 << 0)

#define DC_WIN_CSC_YOF				0x611
#define DC_WIN_CSC_KYRGB			0x612
#define DC_WIN_CSC_KUR				0x613
@@ -502,9 +587,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define WIN_COLOR_DEPTH_P4              2
#define WIN_COLOR_DEPTH_P8              3
#define WIN_COLOR_DEPTH_B4G4R4A4        4
#define WIN_COLOR_DEPTH_B5G5R5A         5
#define WIN_COLOR_DEPTH_B5G5R5A1        5
#define WIN_COLOR_DEPTH_B5G6R5          6
#define WIN_COLOR_DEPTH_AB5G5R5         7
#define WIN_COLOR_DEPTH_A1B5G5R5        7
#define WIN_COLOR_DEPTH_B8G8R8A8       12
#define WIN_COLOR_DEPTH_R8G8B8A8       13
#define WIN_COLOR_DEPTH_B6x2G6x2R6x2A8 14
@@ -519,18 +604,32 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define WIN_COLOR_DEPTH_YUV422R        23
#define WIN_COLOR_DEPTH_YCbCr422RA     24
#define WIN_COLOR_DEPTH_YUV422RA       25
#define WIN_COLOR_DEPTH_R4G4B4A4       27
#define WIN_COLOR_DEPTH_R5G5B5A        28
#define WIN_COLOR_DEPTH_AR5G5B5        29
#define WIN_COLOR_DEPTH_B5G5R5X1       30
#define WIN_COLOR_DEPTH_X1B5G5R5       31
#define WIN_COLOR_DEPTH_R5G5B5X1       32
#define WIN_COLOR_DEPTH_X1R5G5B5       33
#define WIN_COLOR_DEPTH_R5G6B5         34
#define WIN_COLOR_DEPTH_A8R8G8B8       35
#define WIN_COLOR_DEPTH_A8B8G8R8       36
#define WIN_COLOR_DEPTH_B8G8R8X8       37
#define WIN_COLOR_DEPTH_R8G8B8X8       38
#define WIN_COLOR_DEPTH_X8B8G8R8       65
#define WIN_COLOR_DEPTH_X8R8G8B8       66

#define DC_WIN_POSITION				0x704
#define H_POSITION(x) (((x) & 0x1fff) <<  0)
#define V_POSITION(x) (((x) & 0x1fff) << 16)
#define H_POSITION(x) (((x) & 0x1fff) <<  0) /* XXX 0x7fff on Tegra186 */
#define V_POSITION(x) (((x) & 0x1fff) << 16) /* XXX 0x7fff on Tegra186 */

#define DC_WIN_SIZE				0x705
#define H_SIZE(x) (((x) & 0x1fff) <<  0)
#define V_SIZE(x) (((x) & 0x1fff) << 16)
#define H_SIZE(x) (((x) & 0x1fff) <<  0) /* XXX 0x7fff on Tegra186 */
#define V_SIZE(x) (((x) & 0x1fff) << 16) /* XXX 0x7fff on Tegra186 */

#define DC_WIN_PRESCALED_SIZE			0x706
#define H_PRESCALED_SIZE(x) (((x) & 0x7fff) <<  0)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16)
#define V_PRESCALED_SIZE(x) (((x) & 0x1fff) << 16) /* XXX 0x7fff on Tegra186 */

#define DC_WIN_H_INITIAL_DDA			0x707
#define DC_WIN_V_INITIAL_DDA			0x708
@@ -546,11 +645,24 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define DC_WIN_BUFFER_ADDR_MODE_TILE		(1 <<  0)
#define DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV	(0 << 16)
#define DC_WIN_BUFFER_ADDR_MODE_TILE_UV		(1 << 16)

#define DC_WIN_DV_CONTROL			0x70e

#define DC_WIN_BLEND_NOKEY			0x70f
#define  BLEND_WEIGHT1(x) (((x) & 0xff) << 16)
#define  BLEND_WEIGHT0(x) (((x) & 0xff) <<  8)

#define DC_WIN_BLEND_1WIN			0x710
#define  BLEND_CONTROL_FIX    (0 << 2)
#define  BLEND_CONTROL_ALPHA  (1 << 2)
#define  BLEND_COLOR_KEY_NONE (0 << 0)
#define  BLEND_COLOR_KEY_0    (1 << 0)
#define  BLEND_COLOR_KEY_1    (2 << 0)
#define  BLEND_COLOR_KEY_BOTH (3 << 0)

#define DC_WIN_BLEND_2WIN_X			0x711
#define  BLEND_CONTROL_DEPENDENT (2 << 2)

#define DC_WIN_BLEND_2WIN_Y			0x712
#define DC_WIN_BLEND_3WIN_XY			0x713

@@ -575,8 +687,97 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define DC_WINBUF_SURFACE_KIND_BLOCK	(2 << 0)
#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)

#define DC_WINBUF_START_ADDR_HI			0x80d

#define DC_WINBUF_CDE_CONTROL			0x82f
#define  ENABLE_SURFACE (1 << 0)

#define DC_WINBUF_AD_UFLOW_STATUS		0xbca
#define DC_WINBUF_BD_UFLOW_STATUS		0xdca
#define DC_WINBUF_CD_UFLOW_STATUS		0xfca

/* Tegra186 and later */
#define DC_DISP_CORE_SOR_SET_CONTROL(x)		(0x403 + (x))
#define PROTOCOL_MASK (0xf << 8)
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)

#define DC_WIN_CORE_WINDOWGROUP_SET_CONTROL	0x702
#define OWNER_MASK (0xf << 0)
#define OWNER(x) (((x) & 0xf) << 0)

#define DC_WIN_CROPPED_SIZE			0x706

#define DC_WIN_PLANAR_STORAGE			0x709
#define PITCH(x) (((x) >> 6) & 0x1fff)

#define DC_WIN_SET_PARAMS			0x70d
#define  CLAMP_BEFORE_BLEND (1 << 15)
#define  DEGAMMA_NONE (0 << 13)
#define  DEGAMMA_SRGB (1 << 13)
#define  DEGAMMA_YUV8_10 (2 << 13)
#define  DEGAMMA_YUV12 (3 << 13)
#define  INPUT_RANGE_BYPASS (0 << 10)
#define  INPUT_RANGE_LIMITED (1 << 10)
#define  INPUT_RANGE_FULL (2 << 10)
#define  COLOR_SPACE_RGB (0 << 8)
#define  COLOR_SPACE_YUV_601 (1 << 8)
#define  COLOR_SPACE_YUV_709 (2 << 8)
#define  COLOR_SPACE_YUV_2020 (3 << 8)

#define DC_WIN_WINDOWGROUP_SET_CONTROL_INPUT_SCALER	0x70e
#define  HORIZONTAL_TAPS_2 (1 << 3)
#define  HORIZONTAL_TAPS_5 (4 << 3)
#define  VERTICAL_TAPS_2 (1 << 0)
#define  VERTICAL_TAPS_5 (4 << 0)

#define DC_WIN_WINDOWGROUP_SET_INPUT_SCALER_USAGE	0x711
#define  INPUT_SCALER_USE422  (1 << 2)
#define  INPUT_SCALER_VBYPASS (1 << 1)
#define  INPUT_SCALER_HBYPASS (1 << 0)

#define DC_WIN_BLEND_LAYER_CONTROL		0x716
#define  COLOR_KEY_NONE (0 << 25)
#define  COLOR_KEY_SRC (1 << 25)
#define  COLOR_KEY_DST (2 << 25)
#define  BLEND_BYPASS (1 << 24)
#define  K2(x) (((x) & 0xff) << 16)
#define  K1(x) (((x) & 0xff) << 8)
#define  WINDOW_LAYER_DEPTH(x) (((x) & 0xff) << 0)

#define DC_WIN_BLEND_MATCH_SELECT		0x717
#define  BLEND_FACTOR_DST_ALPHA_ZERO			(0 << 12)
#define  BLEND_FACTOR_DST_ALPHA_ONE			(1 << 12)
#define  BLEND_FACTOR_DST_ALPHA_NEG_K1_TIMES_SRC	(2 << 12)
#define  BLEND_FACTOR_DST_ALPHA_K2			(3 << 12)
#define  BLEND_FACTOR_SRC_ALPHA_ZERO			(0 << 8)
#define  BLEND_FACTOR_SRC_ALPHA_K1			(1 << 8)
#define  BLEND_FACTOR_SRC_ALPHA_K2			(2 << 8)
#define  BLEND_FACTOR_SRC_ALPHA_NEG_K1_TIMES_DST	(3 << 8)
#define  BLEND_FACTOR_DST_COLOR_ZERO			(0 << 4)
#define  BLEND_FACTOR_DST_COLOR_ONE			(1 << 4)
#define  BLEND_FACTOR_DST_COLOR_K1			(2 << 4)
#define  BLEND_FACTOR_DST_COLOR_K2			(3 << 4)
#define  BLEND_FACTOR_DST_COLOR_K1_TIMES_DST		(4 << 4)
#define  BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_DST	(5 << 4)
#define  BLEND_FACTOR_DST_COLOR_NEG_K1_TIMES_SRC	(6 << 4)
#define  BLEND_FACTOR_DST_COLOR_NEG_K1			(7 << 4)
#define  BLEND_FACTOR_SRC_COLOR_ZERO			(0 << 0)
#define  BLEND_FACTOR_SRC_COLOR_ONE			(1 << 0)
#define  BLEND_FACTOR_SRC_COLOR_K1			(2 << 0)
#define  BLEND_FACTOR_SRC_COLOR_K1_TIMES_DST		(3 << 0)
#define  BLEND_FACTOR_SRC_COLOR_NEG_K1_TIMES_DST	(4 << 0)
#define  BLEND_FACTOR_SRC_COLOR_K1_TIMES_SRC		(5 << 0)

#define DC_WIN_BLEND_NOMATCH_SELECT		0x718

#define DC_WIN_PRECOMP_WGRP_PARAMS		0x724
#define  SWAP_UV (1 << 0)

#define DC_WIN_WINDOW_SET_CONTROL		0x730
#define  CONTROL_CSC_ENABLE (1 << 5)

#define DC_WINBUF_CROPPED_POINT			0x806
#define OFFSET_Y(x) (((x) & 0xffff) << 16)
#define OFFSET_X(x) (((x) & 0xffff) << 0)

#endif /* TEGRA_DC_H */
+80 −40
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/regulator/consumer.h>
@@ -321,6 +322,9 @@ static int tegra_dpaux_pad_config(struct tegra_dpaux *dpaux, unsigned function)
	case DPAUX_PADCTL_FUNC_I2C:
		value = DPAUX_HYBRID_PADCTL_I2C_SDA_INPUT_RCV |
			DPAUX_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
			DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
			DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
			DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
			DPAUX_HYBRID_PADCTL_MODE_I2C;
		break;

@@ -467,52 +471,37 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
		return PTR_ERR(dpaux->clk);
	}

	err = clk_prepare_enable(dpaux->clk);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to enable module clock: %d\n",
			err);
		return err;
	}

	if (dpaux->rst)
		reset_control_deassert(dpaux->rst);

	dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
	if (IS_ERR(dpaux->clk_parent)) {
		dev_err(&pdev->dev, "failed to get parent clock: %ld\n",
			PTR_ERR(dpaux->clk_parent));
		err = PTR_ERR(dpaux->clk_parent);
		goto assert_reset;
	}

	err = clk_prepare_enable(dpaux->clk_parent);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to enable parent clock: %d\n",
			err);
		goto assert_reset;
		return PTR_ERR(dpaux->clk_parent);
	}

	err = clk_set_rate(dpaux->clk_parent, 270000000);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to set clock to 270 MHz: %d\n",
			err);
		goto disable_parent_clk;
		return err;
	}

	dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
	if (IS_ERR(dpaux->vdd)) {
		dev_err(&pdev->dev, "failed to get VDD supply: %ld\n",
			PTR_ERR(dpaux->vdd));
		err = PTR_ERR(dpaux->vdd);
		goto disable_parent_clk;
		return PTR_ERR(dpaux->vdd);
	}

	platform_set_drvdata(pdev, dpaux);
	pm_runtime_enable(&pdev->dev);
	pm_runtime_get_sync(&pdev->dev);

	err = devm_request_irq(dpaux->dev, dpaux->irq, tegra_dpaux_irq, 0,
			       dev_name(dpaux->dev), dpaux);
	if (err < 0) {
		dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
			dpaux->irq, err);
		goto disable_parent_clk;
		return err;
	}

	disable_irq(dpaux->irq);
@@ -522,7 +511,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)

	err = drm_dp_aux_register(&dpaux->aux);
	if (err < 0)
		goto disable_parent_clk;
		return err;

	/*
	 * Assume that by default the DPAUX/I2C pads will be used for HDMI,
@@ -560,47 +549,97 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
	list_add_tail(&dpaux->list, &dpaux_list);
	mutex_unlock(&dpaux_lock);

	platform_set_drvdata(pdev, dpaux);

	return 0;

disable_parent_clk:
	clk_disable_unprepare(dpaux->clk_parent);
assert_reset:
	if (dpaux->rst)
		reset_control_assert(dpaux->rst);

	clk_disable_unprepare(dpaux->clk);

	return err;
}

static int tegra_dpaux_remove(struct platform_device *pdev)
{
	struct tegra_dpaux *dpaux = platform_get_drvdata(pdev);

	cancel_work_sync(&dpaux->work);

	/* make sure pads are powered down when not in use */
	tegra_dpaux_pad_power_down(dpaux);

	pm_runtime_put(&pdev->dev);
	pm_runtime_disable(&pdev->dev);

	drm_dp_aux_unregister(&dpaux->aux);

	mutex_lock(&dpaux_lock);
	list_del(&dpaux->list);
	mutex_unlock(&dpaux_lock);

	cancel_work_sync(&dpaux->work);
	return 0;
}

	clk_disable_unprepare(dpaux->clk_parent);
#ifdef CONFIG_PM
static int tegra_dpaux_suspend(struct device *dev)
{
	struct tegra_dpaux *dpaux = dev_get_drvdata(dev);
	int err = 0;

	if (dpaux->rst) {
		err = reset_control_assert(dpaux->rst);
		if (err < 0) {
			dev_err(dev, "failed to assert reset: %d\n", err);
			return err;
		}
	}

	if (dpaux->rst)
		reset_control_assert(dpaux->rst);
	usleep_range(1000, 2000);

	clk_disable_unprepare(dpaux->clk_parent);
	clk_disable_unprepare(dpaux->clk);

	return err;
}

static int tegra_dpaux_resume(struct device *dev)
{
	struct tegra_dpaux *dpaux = dev_get_drvdata(dev);
	int err;

	err = clk_prepare_enable(dpaux->clk);
	if (err < 0) {
		dev_err(dev, "failed to enable clock: %d\n", err);
		return err;
	}

	err = clk_prepare_enable(dpaux->clk_parent);
	if (err < 0) {
		dev_err(dev, "failed to enable parent clock: %d\n", err);
		goto disable_clk;
	}

	usleep_range(1000, 2000);

	if (dpaux->rst) {
		err = reset_control_deassert(dpaux->rst);
		if (err < 0) {
			dev_err(dev, "failed to deassert reset: %d\n", err);
			goto disable_parent;
		}

		usleep_range(1000, 2000);
	}

	return 0;

disable_parent:
	clk_disable_unprepare(dpaux->clk_parent);
disable_clk:
	clk_disable_unprepare(dpaux->clk);
	return err;
}
#endif

static const struct dev_pm_ops tegra_dpaux_pm_ops = {
	SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
};

static const struct of_device_id tegra_dpaux_of_match[] = {
	{ .compatible = "nvidia,tegra186-dpaux", },
	{ .compatible = "nvidia,tegra210-dpaux", },
	{ .compatible = "nvidia,tegra124-dpaux", },
	{ },
@@ -611,6 +650,7 @@ struct platform_driver tegra_dpaux_driver = {
	.driver = {
		.name = "tegra-dpaux",
		.of_match_table = tegra_dpaux_of_match,
		.pm = &tegra_dpaux_pm_ops,
	},
	.probe = tegra_dpaux_probe,
	.remove = tegra_dpaux_remove,
Loading