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

Commit 82c68b6c authored by Dave Airlie's avatar Dave Airlie
Browse files

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

drm/tegra: Changes for v3.15-rc1

Implement eDP support for Tegra124 and support the PRIME vmap()/vunmap()
operations.

A symbol that is required for upcoming V4L2 support is now exported by
the host1x driver.

Relicense drivers under the GPL v2 for consistency. One exception is the
public header file, which is relicensed under MIT to abide by the common
rule.

* tag 'drm/tegra/for-3.15-rc1' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: Use standard GPL v2 license text
  drm/tegra: Relicense under GPL v2
  drm/tegra: Relicense public header under MIT
  drm/tegra: Add eDP support
  gpu: host1x: export host1x_syncpt_incr_max() function
  drm/tegra: prime: Add vmap support
parents 243b930f d105a6c9
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -190,6 +190,48 @@ of the following host1x client modules:
  - nvidia,edid: supplies a binary EDID blob
  - nvidia,panel: phandle of a display panel

- sor: serial output resource

  Required properties:
  - compatible: "nvidia,tegra124-sor"
  - 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
    - parent: input for the pixel clock
    - dp: reference clock for the SOR clock
    - safe: safe reference for the SOR clock during power up
  - 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

  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
  - nvidia,edid: supplies a binary EDID blob
  - nvidia,panel: phandle of a display panel

  Optional properties when driving an eDP output:
  - nvidia,dpaux: phandle to a DispayPort AUX interface

- dpaux: DisplayPort AUX interface
  - compatible: "nvidia,tegra124-dpaux"
  - 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:
    - dpaux: clock input for the DPAUX hardware
    - parent: reference clock
  - resets: Must contain an entry for each entry in reset-names.
    See ../reset/reset.txt for details.
  - reset-names: Must include the following entries:
    - dpaux
  - vdd-supply: phandle of a supply that powers the DisplayPort link

Example:

/ {
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,8 @@ tegra-drm-y := \
	hdmi.o \
	mipi-phy.o \
	dsi.o \
	sor.o \
	dpaux.o \
	gr2d.o \
	gr3d.o

+1 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@
#define DC_DISP_DISP_WIN_OPTIONS		0x402
#define HDMI_ENABLE (1 << 30)
#define DSI_ENABLE  (1 << 29)
#define SOR_ENABLE  (1 << 25)

#define DC_DISP_DISP_MEM_HIGH_PRIORITY		0x403
#define CURSOR_THRESHOLD(x)   (((x) & 0x03) << 24)
+544 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 NVIDIA Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/regulator/consumer.h>

#include <drm/drm_dp_helper.h>
#include <drm/drm_panel.h>

#include "dpaux.h"
#include "drm.h"

static DEFINE_MUTEX(dpaux_lock);
static LIST_HEAD(dpaux_list);

struct tegra_dpaux {
	struct drm_dp_aux aux;
	struct device *dev;

	void __iomem *regs;
	int irq;

	struct tegra_output *output;

	struct reset_control *rst;
	struct clk *clk_parent;
	struct clk *clk;

	struct regulator *vdd;

	struct completion complete;
	struct list_head list;
};

static inline struct tegra_dpaux *to_dpaux(struct drm_dp_aux *aux)
{
	return container_of(aux, struct tegra_dpaux, aux);
}

static inline unsigned long tegra_dpaux_readl(struct tegra_dpaux *dpaux,
					      unsigned long offset)
{
	return readl(dpaux->regs + (offset << 2));
}

static inline void tegra_dpaux_writel(struct tegra_dpaux *dpaux,
				      unsigned long value,
				      unsigned long offset)
{
	writel(value, dpaux->regs + (offset << 2));
}

static void tegra_dpaux_write_fifo(struct tegra_dpaux *dpaux, const u8 *buffer,
				   size_t size)
{
	unsigned long offset = DPAUX_DP_AUXDATA_WRITE(0);
	size_t i, j;

	for (i = 0; i < size; i += 4) {
		size_t num = min_t(size_t, size - i, 4);
		unsigned long value = 0;

		for (j = 0; j < num; j++)
			value |= buffer[i + j] << (j * 8);

		tegra_dpaux_writel(dpaux, value, offset++);
	}
}

static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer,
				  size_t size)
{
	unsigned long offset = DPAUX_DP_AUXDATA_READ(0);
	size_t i, j;

	for (i = 0; i < size; i += 4) {
		size_t num = min_t(size_t, size - i, 4);
		unsigned long value;

		value = tegra_dpaux_readl(dpaux, offset++);

		for (j = 0; j < num; j++)
			buffer[i + j] = value >> (j * 8);
	}
}

static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux,
				    struct drm_dp_aux_msg *msg)
{
	unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ;
	unsigned long timeout = msecs_to_jiffies(250);
	struct tegra_dpaux *dpaux = to_dpaux(aux);
	unsigned long status;
	ssize_t ret = 0;

	if (msg->size < 1 || msg->size > 16)
		return -EINVAL;

	tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR);

	switch (msg->request & ~DP_AUX_I2C_MOT) {
	case DP_AUX_I2C_WRITE:
		if (msg->request & DP_AUX_I2C_MOT)
			value = DPAUX_DP_AUXCTL_CMD_MOT_WR;
		else
			value = DPAUX_DP_AUXCTL_CMD_I2C_WR;

		break;

	case DP_AUX_I2C_READ:
		if (msg->request & DP_AUX_I2C_MOT)
			value = DPAUX_DP_AUXCTL_CMD_MOT_RD;
		else
			value = DPAUX_DP_AUXCTL_CMD_I2C_RD;

		break;

	case DP_AUX_I2C_STATUS:
		if (msg->request & DP_AUX_I2C_MOT)
			value = DPAUX_DP_AUXCTL_CMD_MOT_RQ;
		else
			value = DPAUX_DP_AUXCTL_CMD_I2C_RQ;

		break;

	case DP_AUX_NATIVE_WRITE:
		value = DPAUX_DP_AUXCTL_CMD_AUX_WR;
		break;

	case DP_AUX_NATIVE_READ:
		value = DPAUX_DP_AUXCTL_CMD_AUX_RD;
		break;

	default:
		return -EINVAL;
	}

	value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1);
	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);

	if ((msg->request & DP_AUX_I2C_READ) == 0) {
		tegra_dpaux_write_fifo(dpaux, msg->buffer, msg->size);
		ret = msg->size;
	}

	/* start transaction */
	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXCTL);
	value |= DPAUX_DP_AUXCTL_TRANSACTREQ;
	tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL);

	status = wait_for_completion_timeout(&dpaux->complete, timeout);
	if (!status)
		return -ETIMEDOUT;

	/* read status and clear errors */
	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);
	tegra_dpaux_writel(dpaux, 0xf00, DPAUX_DP_AUXSTAT);

	if (value & DPAUX_DP_AUXSTAT_TIMEOUT_ERROR)
		return -ETIMEDOUT;

	if ((value & DPAUX_DP_AUXSTAT_RX_ERROR) ||
	    (value & DPAUX_DP_AUXSTAT_SINKSTAT_ERROR) ||
	    (value & DPAUX_DP_AUXSTAT_NO_STOP_ERROR))
		return -EIO;

	switch ((value & DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK) >> 16) {
	case 0x00:
		msg->reply = DP_AUX_NATIVE_REPLY_ACK;
		break;

	case 0x01:
		msg->reply = DP_AUX_NATIVE_REPLY_NACK;
		break;

	case 0x02:
		msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
		break;

	case 0x04:
		msg->reply = DP_AUX_I2C_REPLY_NACK;
		break;

	case 0x08:
		msg->reply = DP_AUX_I2C_REPLY_DEFER;
		break;
	}

	if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) {
		if (msg->request & DP_AUX_I2C_READ) {
			size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK;

			if (WARN_ON(count != msg->size))
				count = min_t(size_t, count, msg->size);

			tegra_dpaux_read_fifo(dpaux, msg->buffer, count);
			ret = count;
		}
	}

	return ret;
}

static irqreturn_t tegra_dpaux_irq(int irq, void *data)
{
	struct tegra_dpaux *dpaux = data;
	irqreturn_t ret = IRQ_HANDLED;
	unsigned long value;

	/* clear interrupts */
	value = tegra_dpaux_readl(dpaux, DPAUX_INTR_AUX);
	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);

	if (value & DPAUX_INTR_PLUG_EVENT) {
		if (dpaux->output) {
			drm_helper_hpd_irq_event(dpaux->output->connector.dev);
		}
	}

	if (value & DPAUX_INTR_UNPLUG_EVENT) {
		if (dpaux->output)
			drm_helper_hpd_irq_event(dpaux->output->connector.dev);
	}

	if (value & DPAUX_INTR_IRQ_EVENT) {
		/* TODO: handle this */
	}

	if (value & DPAUX_INTR_AUX_DONE)
		complete(&dpaux->complete);

	return ret;
}

static int tegra_dpaux_probe(struct platform_device *pdev)
{
	struct tegra_dpaux *dpaux;
	struct resource *regs;
	unsigned long value;
	int err;

	dpaux = devm_kzalloc(&pdev->dev, sizeof(*dpaux), GFP_KERNEL);
	if (!dpaux)
		return -ENOMEM;

	init_completion(&dpaux->complete);
	INIT_LIST_HEAD(&dpaux->list);
	dpaux->dev = &pdev->dev;

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	dpaux->regs = devm_ioremap_resource(&pdev->dev, regs);
	if (IS_ERR(dpaux->regs))
		return PTR_ERR(dpaux->regs);

	dpaux->irq = platform_get_irq(pdev, 0);
	if (dpaux->irq < 0) {
		dev_err(&pdev->dev, "failed to get IRQ\n");
		return -ENXIO;
	}

	dpaux->rst = devm_reset_control_get(&pdev->dev, "dpaux");
	if (IS_ERR(dpaux->rst))
		return PTR_ERR(dpaux->rst);

	dpaux->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(dpaux->clk))
		return PTR_ERR(dpaux->clk);

	err = clk_prepare_enable(dpaux->clk);
	if (err < 0)
		return err;

	reset_control_deassert(dpaux->rst);

	dpaux->clk_parent = devm_clk_get(&pdev->dev, "parent");
	if (IS_ERR(dpaux->clk_parent))
		return PTR_ERR(dpaux->clk_parent);

	err = clk_prepare_enable(dpaux->clk_parent);
	if (err < 0)
		return err;

	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);
		return err;
	}

	dpaux->vdd = devm_regulator_get(&pdev->dev, "vdd");
	if (IS_ERR(dpaux->vdd))
		return PTR_ERR(dpaux->vdd);

	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);
		return err;
	}

	dpaux->aux.transfer = tegra_dpaux_transfer;
	dpaux->aux.dev = &pdev->dev;

	err = drm_dp_aux_register_i2c_bus(&dpaux->aux);
	if (err < 0)
		return err;

	/* enable and clear all interrupts */
	value = DPAUX_INTR_AUX_DONE | DPAUX_INTR_IRQ_EVENT |
		DPAUX_INTR_UNPLUG_EVENT | DPAUX_INTR_PLUG_EVENT;
	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_EN_AUX);
	tegra_dpaux_writel(dpaux, value, DPAUX_INTR_AUX);

	mutex_lock(&dpaux_lock);
	list_add_tail(&dpaux->list, &dpaux_list);
	mutex_unlock(&dpaux_lock);

	platform_set_drvdata(pdev, dpaux);

	return 0;
}

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

	drm_dp_aux_unregister_i2c_bus(&dpaux->aux);

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

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

	return 0;
}

static const struct of_device_id tegra_dpaux_of_match[] = {
	{ .compatible = "nvidia,tegra124-dpaux", },
	{ },
};

struct platform_driver tegra_dpaux_driver = {
	.driver = {
		.name = "tegra-dpaux",
		.of_match_table = tegra_dpaux_of_match,
	},
	.probe = tegra_dpaux_probe,
	.remove = tegra_dpaux_remove,
};

struct tegra_dpaux *tegra_dpaux_find_by_of_node(struct device_node *np)
{
	struct tegra_dpaux *dpaux;

	mutex_lock(&dpaux_lock);

	list_for_each_entry(dpaux, &dpaux_list, list)
		if (np == dpaux->dev->of_node) {
			mutex_unlock(&dpaux_lock);
			return dpaux;
		}

	mutex_unlock(&dpaux_lock);

	return NULL;
}

int tegra_dpaux_attach(struct tegra_dpaux *dpaux, struct tegra_output *output)
{
	unsigned long timeout;
	int err;

	dpaux->output = output;

	err = regulator_enable(dpaux->vdd);
	if (err < 0)
		return err;

	timeout = jiffies + msecs_to_jiffies(250);

	while (time_before(jiffies, timeout)) {
		enum drm_connector_status status;

		status = tegra_dpaux_detect(dpaux);
		if (status == connector_status_connected)
			return 0;

		usleep_range(1000, 2000);
	}

	return -ETIMEDOUT;
}

int tegra_dpaux_detach(struct tegra_dpaux *dpaux)
{
	unsigned long timeout;
	int err;

	err = regulator_disable(dpaux->vdd);
	if (err < 0)
		return err;

	timeout = jiffies + msecs_to_jiffies(250);

	while (time_before(jiffies, timeout)) {
		enum drm_connector_status status;

		status = tegra_dpaux_detect(dpaux);
		if (status == connector_status_disconnected) {
			dpaux->output = NULL;
			return 0;
		}

		usleep_range(1000, 2000);
	}

	return -ETIMEDOUT;
}

enum drm_connector_status tegra_dpaux_detect(struct tegra_dpaux *dpaux)
{
	unsigned long value;

	value = tegra_dpaux_readl(dpaux, DPAUX_DP_AUXSTAT);

	if (value & DPAUX_DP_AUXSTAT_HPD_STATUS)
		return connector_status_connected;

	return connector_status_disconnected;
}

int tegra_dpaux_enable(struct tegra_dpaux *dpaux)
{
	unsigned long value;

	value = DPAUX_HYBRID_PADCTL_AUX_CMH(2) |
		DPAUX_HYBRID_PADCTL_AUX_DRVZ(4) |
		DPAUX_HYBRID_PADCTL_AUX_DRVI(0x18) |
		DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV |
		DPAUX_HYBRID_PADCTL_MODE_AUX;
	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_PADCTL);

	value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
	value &= ~DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);

	return 0;
}

int tegra_dpaux_disable(struct tegra_dpaux *dpaux)
{
	unsigned long value;

	value = tegra_dpaux_readl(dpaux, DPAUX_HYBRID_SPARE);
	value |= DPAUX_HYBRID_SPARE_PAD_POWER_DOWN;
	tegra_dpaux_writel(dpaux, value, DPAUX_HYBRID_SPARE);

	return 0;
}

int tegra_dpaux_prepare(struct tegra_dpaux *dpaux, u8 encoding)
{
	int err;

	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
				 encoding);
	if (err < 0)
		return err;

	return 0;
}

int tegra_dpaux_train(struct tegra_dpaux *dpaux, 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);
	if (err < 0)
		return err;

	if (tp == DP_TRAINING_PATTERN_DISABLE)
		return 0;

	for (i = 0; i < link->num_lanes; i++)
		values[i] = DP_TRAIN_MAX_PRE_EMPHASIS_REACHED |
			    DP_TRAIN_PRE_EMPHASIS_0 |
			    DP_TRAIN_MAX_SWING_REACHED |
			    DP_TRAIN_VOLTAGE_SWING_400;

	err = drm_dp_dpcd_write(&dpaux->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);
	if (err < 0)
		return err;

	switch (tp) {
	case DP_TRAINING_PATTERN_1:
		if (!drm_dp_clock_recovery_ok(status, link->num_lanes))
			return -EAGAIN;

		break;

	case DP_TRAINING_PATTERN_2:
		if (!drm_dp_channel_eq_ok(status, link->num_lanes))
			return -EAGAIN;

		break;

	default:
		dev_err(dpaux->dev, "unsupported training pattern %u\n", tp);
		return -EINVAL;
	}

	err = drm_dp_dpcd_writeb(&dpaux->aux, DP_EDP_CONFIGURATION_SET, 0);
	if (err < 0)
		return err;

	return 0;
}
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 NVIDIA Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef DRM_TEGRA_DPAUX_H
#define DRM_TEGRA_DPAUX_H

#define DPAUX_CTXSW 0x00

#define DPAUX_INTR_EN_AUX 0x01
#define DPAUX_INTR_AUX 0x05
#define DPAUX_INTR_AUX_DONE (1 << 3)
#define DPAUX_INTR_IRQ_EVENT (1 << 2)
#define DPAUX_INTR_UNPLUG_EVENT (1 << 1)
#define DPAUX_INTR_PLUG_EVENT (1 << 0)

#define DPAUX_DP_AUXDATA_WRITE(x) (0x09 + ((x) << 2))
#define DPAUX_DP_AUXDATA_READ(x) (0x19 + ((x) << 2))
#define DPAUX_DP_AUXADDR 0x29

#define DPAUX_DP_AUXCTL 0x2d
#define DPAUX_DP_AUXCTL_TRANSACTREQ (1 << 16)
#define DPAUX_DP_AUXCTL_CMD_AUX_RD (9 << 12)
#define DPAUX_DP_AUXCTL_CMD_AUX_WR (8 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOT_RQ (6 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOT_RD (5 << 12)
#define DPAUX_DP_AUXCTL_CMD_MOT_WR (4 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12)
#define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12)
#define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff)

#define DPAUX_DP_AUXSTAT 0x31
#define DPAUX_DP_AUXSTAT_HPD_STATUS (1 << 28)
#define DPAUX_DP_AUXSTAT_REPLY_TYPE_MASK (0xf0000)
#define DPAUX_DP_AUXSTAT_NO_STOP_ERROR (1 << 11)
#define DPAUX_DP_AUXSTAT_SINKSTAT_ERROR (1 << 10)
#define DPAUX_DP_AUXSTAT_RX_ERROR (1 << 9)
#define DPAUX_DP_AUXSTAT_TIMEOUT_ERROR (1 << 8)
#define DPAUX_DP_AUXSTAT_REPLY_MASK (0xff)

#define DPAUX_DP_AUX_SINKSTAT_LO 0x35
#define DPAUX_DP_AUX_SINKSTAT_HI 0x39

#define DPAUX_HPD_CONFIG 0x3d
#define DPAUX_HPD_CONFIG_UNPLUG_MIN_TIME(x) (((x) & 0xffff) << 16)
#define DPAUX_HPD_CONFIG_PLUG_MIN_TIME(x) ((x) & 0xffff)

#define DPAUX_HPD_IRQ_CONFIG 0x41
#define DPAUX_HPD_IRQ_CONFIG_MIN_LOW_TIME(x) ((x) & 0xffff)

#define DPAUX_DP_AUX_CONFIG 0x45

#define DPAUX_HYBRID_PADCTL 0x49
#define DPAUX_HYBRID_PADCTL_AUX_CMH(x) (((x) & 0x3) << 12)
#define DPAUX_HYBRID_PADCTL_AUX_DRVZ(x) (((x) & 0x7) << 8)
#define DPAUX_HYBRID_PADCTL_AUX_DRVI(x) (((x) & 0x3f) << 2)
#define DPAUX_HYBRID_PADCTL_AUX_INPUT_RCV (1 << 1)
#define DPAUX_HYBRID_PADCTL_MODE_I2C (1 << 0)
#define DPAUX_HYBRID_PADCTL_MODE_AUX (0 << 0)

#define DPAUX_HYBRID_SPARE 0x4d
#define DPAUX_HYBRID_SPARE_PAD_POWER_DOWN (1 << 0)

#define DPAUX_SCRATCH_REG0 0x51
#define DPAUX_SCRATCH_REG1 0x55
#define DPAUX_SCRATCH_REG2 0x59

#endif
Loading