target/rockchip: add hdmi tx driver for rk3588
Based on: *2dc8224e37/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c* https://lore.kernel.org/all/20241016-b4-rk3588-bridge-upstream-v10-1-87ef92a6d14e@collabora.com/ *a52dffaa46/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c*a52dffaa46/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c*a52dffaa46/drivers/gpu/drm/rockchip/rockchip_vop2_reg.cSigned-off-by: Liangbin Lian <jjm2473@gmail.com>
This commit is contained in:
parent
8fa60fdb47
commit
ade13ffdaa
@ -0,0 +1,647 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
|
||||||
|
* Copyright (c) 2024 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Author: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
* Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
*/
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <linux/hdmi.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#include <drm/bridge/dw_hdmi_qp.h>
|
||||||
|
#include <drm/display/drm_hdmi_helper.h>
|
||||||
|
#include <drm/display/drm_hdmi_state_helper.h>
|
||||||
|
#include <drm/drm_atomic.h>
|
||||||
|
#include <drm/drm_atomic_helper.h>
|
||||||
|
#include <drm/drm_bridge.h>
|
||||||
|
#include <drm/drm_connector.h>
|
||||||
|
#include <drm/drm_edid.h>
|
||||||
|
#include <drm/drm_modes.h>
|
||||||
|
|
||||||
|
#include <sound/hdmi-codec.h>
|
||||||
|
|
||||||
|
#include "dw-hdmi-qp.h"
|
||||||
|
|
||||||
|
#define DDC_CI_ADDR 0x37
|
||||||
|
#define DDC_SEGMENT_ADDR 0x30
|
||||||
|
|
||||||
|
#define HDMI14_MAX_TMDSCLK 340000000
|
||||||
|
|
||||||
|
#define SCRAMB_POLL_DELAY_MS 3000
|
||||||
|
|
||||||
|
struct dw_hdmi_qp_i2c {
|
||||||
|
struct i2c_adapter adap;
|
||||||
|
|
||||||
|
struct mutex lock; /* used to serialize data transfers */
|
||||||
|
struct completion cmp;
|
||||||
|
u8 stat;
|
||||||
|
|
||||||
|
u8 slave_reg;
|
||||||
|
bool is_regaddr;
|
||||||
|
bool is_segment;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dw_hdmi_qp {
|
||||||
|
struct drm_bridge bridge;
|
||||||
|
|
||||||
|
struct device *dev;
|
||||||
|
struct dw_hdmi_qp_i2c *i2c;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
const struct dw_hdmi_qp_phy_ops *ops;
|
||||||
|
void *data;
|
||||||
|
} phy;
|
||||||
|
|
||||||
|
struct regmap *regm;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_write(struct dw_hdmi_qp *hdmi, unsigned int val,
|
||||||
|
int offset)
|
||||||
|
{
|
||||||
|
regmap_write(hdmi->regm, offset, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int dw_hdmi_qp_read(struct dw_hdmi_qp *hdmi, int offset)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regm, offset, &val);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_mod(struct dw_hdmi_qp *hdmi, unsigned int data,
|
||||||
|
unsigned int mask, unsigned int reg)
|
||||||
|
{
|
||||||
|
regmap_update_bits(hdmi->regm, reg, mask, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_i2c_read(struct dw_hdmi_qp *hdmi,
|
||||||
|
unsigned char *buf, unsigned int length)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
|
||||||
|
int stat;
|
||||||
|
|
||||||
|
if (!i2c->is_regaddr) {
|
||||||
|
dev_dbg(hdmi->dev, "set read register address to 0\n");
|
||||||
|
i2c->slave_reg = 0x00;
|
||||||
|
i2c->is_regaddr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (length--) {
|
||||||
|
reinit_completion(&i2c->cmp);
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
|
||||||
|
I2CM_INTERFACE_CONTROL0);
|
||||||
|
|
||||||
|
if (i2c->is_segment)
|
||||||
|
dw_hdmi_qp_mod(hdmi, I2CM_EXT_READ, I2CM_WR_MASK,
|
||||||
|
I2CM_INTERFACE_CONTROL0);
|
||||||
|
else
|
||||||
|
dw_hdmi_qp_mod(hdmi, I2CM_FM_READ, I2CM_WR_MASK,
|
||||||
|
I2CM_INTERFACE_CONTROL0);
|
||||||
|
|
||||||
|
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
|
||||||
|
if (!stat) {
|
||||||
|
dev_err(hdmi->dev, "i2c read timed out\n");
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for error condition on the bus */
|
||||||
|
if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
|
||||||
|
dev_err(hdmi->dev, "i2c read error\n");
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
*buf++ = dw_hdmi_qp_read(hdmi, I2CM_INTERFACE_RDDATA_0_3) & 0xff;
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c->is_segment = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_i2c_write(struct dw_hdmi_qp *hdmi,
|
||||||
|
unsigned char *buf, unsigned int length)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
|
||||||
|
int stat;
|
||||||
|
|
||||||
|
if (!i2c->is_regaddr) {
|
||||||
|
/* Use the first write byte as register address */
|
||||||
|
i2c->slave_reg = buf[0];
|
||||||
|
length--;
|
||||||
|
buf++;
|
||||||
|
i2c->is_regaddr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (length--) {
|
||||||
|
reinit_completion(&i2c->cmp);
|
||||||
|
|
||||||
|
dw_hdmi_qp_write(hdmi, *buf++, I2CM_INTERFACE_WRDATA_0_3);
|
||||||
|
dw_hdmi_qp_mod(hdmi, i2c->slave_reg++ << 12, I2CM_ADDR,
|
||||||
|
I2CM_INTERFACE_CONTROL0);
|
||||||
|
dw_hdmi_qp_mod(hdmi, I2CM_FM_WRITE, I2CM_WR_MASK,
|
||||||
|
I2CM_INTERFACE_CONTROL0);
|
||||||
|
|
||||||
|
stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10);
|
||||||
|
if (!stat) {
|
||||||
|
dev_err(hdmi->dev, "i2c write time out!\n");
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for error condition on the bus */
|
||||||
|
if (i2c->stat & I2CM_NACK_RCVD_IRQ) {
|
||||||
|
dev_err(hdmi->dev, "i2c write nack!\n");
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_i2c_xfer(struct i2c_adapter *adap,
|
||||||
|
struct i2c_msg *msgs, int num)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = i2c_get_adapdata(adap);
|
||||||
|
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
|
||||||
|
u8 addr = msgs[0].addr;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
if (addr == DDC_CI_ADDR)
|
||||||
|
/*
|
||||||
|
* The internal I2C controller does not support the multi-byte
|
||||||
|
* read and write operations needed for DDC/CI.
|
||||||
|
* FIXME: Blacklist the DDC/CI address until we filter out
|
||||||
|
* unsupported I2C operations.
|
||||||
|
*/
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
if (msgs[i].len == 0) {
|
||||||
|
dev_err(hdmi->dev,
|
||||||
|
"unsupported transfer %d/%d, no data\n",
|
||||||
|
i + 1, num);
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard(mutex)(&i2c->lock);
|
||||||
|
|
||||||
|
/* Unmute DONE and ERROR interrupts */
|
||||||
|
dw_hdmi_qp_mod(hdmi, I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
|
||||||
|
I2CM_NACK_RCVD_MASK_N | I2CM_OP_DONE_MASK_N,
|
||||||
|
MAINUNIT_1_INT_MASK_N);
|
||||||
|
|
||||||
|
/* Set slave device address taken from the first I2C message */
|
||||||
|
if (addr == DDC_SEGMENT_ADDR && msgs[0].len == 1)
|
||||||
|
addr = DDC_ADDR;
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, addr << 5, I2CM_SLVADDR, I2CM_INTERFACE_CONTROL0);
|
||||||
|
|
||||||
|
/* Set slave device register address on transfer */
|
||||||
|
i2c->is_regaddr = false;
|
||||||
|
|
||||||
|
/* Set segment pointer for I2C extended read mode operation */
|
||||||
|
i2c->is_segment = false;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
if (msgs[i].addr == DDC_SEGMENT_ADDR && msgs[i].len == 1) {
|
||||||
|
i2c->is_segment = true;
|
||||||
|
dw_hdmi_qp_mod(hdmi, DDC_SEGMENT_ADDR, I2CM_SEG_ADDR,
|
||||||
|
I2CM_INTERFACE_CONTROL1);
|
||||||
|
dw_hdmi_qp_mod(hdmi, *msgs[i].buf << 7, I2CM_SEG_PTR,
|
||||||
|
I2CM_INTERFACE_CONTROL1);
|
||||||
|
} else {
|
||||||
|
if (msgs[i].flags & I2C_M_RD)
|
||||||
|
ret = dw_hdmi_qp_i2c_read(hdmi, msgs[i].buf,
|
||||||
|
msgs[i].len);
|
||||||
|
else
|
||||||
|
ret = dw_hdmi_qp_i2c_write(hdmi, msgs[i].buf,
|
||||||
|
msgs[i].len);
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
ret = num;
|
||||||
|
|
||||||
|
/* Mute DONE and ERROR interrupts */
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, I2CM_OP_DONE_MASK_N | I2CM_NACK_RCVD_MASK_N,
|
||||||
|
MAINUNIT_1_INT_MASK_N);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 dw_hdmi_qp_i2c_func(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_algorithm dw_hdmi_qp_algorithm = {
|
||||||
|
.master_xfer = dw_hdmi_qp_i2c_xfer,
|
||||||
|
.functionality = dw_hdmi_qp_i2c_func,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct i2c_adapter *dw_hdmi_qp_i2c_adapter(struct dw_hdmi_qp *hdmi)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp_i2c *i2c;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
|
||||||
|
if (!i2c)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
mutex_init(&i2c->lock);
|
||||||
|
init_completion(&i2c->cmp);
|
||||||
|
|
||||||
|
adap = &i2c->adap;
|
||||||
|
adap->owner = THIS_MODULE;
|
||||||
|
adap->dev.parent = hdmi->dev;
|
||||||
|
adap->algo = &dw_hdmi_qp_algorithm;
|
||||||
|
strscpy(adap->name, "DesignWare HDMI QP", sizeof(adap->name));
|
||||||
|
|
||||||
|
i2c_set_adapdata(adap, hdmi);
|
||||||
|
|
||||||
|
ret = devm_i2c_add_adapter(hdmi->dev, adap);
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
|
||||||
|
devm_kfree(hdmi->dev, i2c);
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->i2c = i2c;
|
||||||
|
dev_info(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
|
||||||
|
|
||||||
|
return adap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi,
|
||||||
|
const u8 *buffer, size_t len)
|
||||||
|
{
|
||||||
|
u32 val, i, j;
|
||||||
|
|
||||||
|
if (len != HDMI_INFOFRAME_SIZE(AVI)) {
|
||||||
|
dev_err(hdmi->dev, "failed to configure avi infoframe\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DW HDMI QP IP uses a different byte format from standard AVI info
|
||||||
|
* frames, though generally the bits are in the correct bytes.
|
||||||
|
*/
|
||||||
|
val = buffer[1] << 8 | buffer[2] << 16;
|
||||||
|
dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
if (i * 4 + j >= 14)
|
||||||
|
break;
|
||||||
|
if (!j)
|
||||||
|
val = buffer[i * 4 + j + 3];
|
||||||
|
val |= buffer[i * 4 + j + 3] << (8 * j);
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
|
||||||
|
PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi,
|
||||||
|
const u8 *buffer, size_t len)
|
||||||
|
{
|
||||||
|
u32 val, i;
|
||||||
|
|
||||||
|
if (len != HDMI_INFOFRAME_SIZE(DRM)) {
|
||||||
|
dev_err(hdmi->dev, "failed to configure drm infoframe\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
|
||||||
|
val = buffer[1] << 8 | buffer[2] << 16;
|
||||||
|
dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0);
|
||||||
|
|
||||||
|
for (i = 0; i <= buffer[2]; i++) {
|
||||||
|
if (i % 4 == 0)
|
||||||
|
val = buffer[3 + i];
|
||||||
|
val |= buffer[3 + i] << ((i % 4) * 8);
|
||||||
|
|
||||||
|
if ((i % 4 == 3) || i == buffer[2])
|
||||||
|
dw_hdmi_qp_write(hdmi, val,
|
||||||
|
PKT_DRMI_CONTENTS1 + ((i / 4) * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
|
||||||
|
dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN,
|
||||||
|
PKTSCHED_PKT_EN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_bridge_atomic_check(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = drm_atomic_helper_connector_hdmi_check(conn_state->connector,
|
||||||
|
conn_state->state);
|
||||||
|
if (ret)
|
||||||
|
dev_dbg(hdmi->dev, "%s failed: %d\n", __func__, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *old_state)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
struct drm_atomic_state *state = old_state->base.state;
|
||||||
|
struct drm_connector_state *conn_state;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
unsigned int op_mode;
|
||||||
|
|
||||||
|
connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
|
||||||
|
if (WARN_ON(!connector))
|
||||||
|
return;
|
||||||
|
|
||||||
|
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||||
|
if (WARN_ON(!conn_state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (connector->display_info.is_hdmi) {
|
||||||
|
dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n",
|
||||||
|
__func__, conn_state->hdmi.tmds_char_rate);
|
||||||
|
op_mode = 0;
|
||||||
|
} else {
|
||||||
|
dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__);
|
||||||
|
op_mode = OPMODE_DVI;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->phy.ops->init(hdmi, hdmi->phy.data);
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||||
|
dw_hdmi_qp_mod(hdmi, op_mode, OPMODE_DVI, LINK_CONFIG0);
|
||||||
|
|
||||||
|
drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *old_state)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
|
||||||
|
hdmi->phy.ops->disable(hdmi, hdmi->phy.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
dw_hdmi_qp_bridge_detect(struct drm_bridge *bridge)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
|
||||||
|
return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_edid *
|
||||||
|
dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge,
|
||||||
|
struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
const struct drm_edid *drm_edid;
|
||||||
|
|
||||||
|
drm_edid = drm_edid_read_ddc(connector, bridge->ddc);
|
||||||
|
if (!drm_edid)
|
||||||
|
dev_dbg(hdmi->dev, "failed to get edid\n");
|
||||||
|
|
||||||
|
return drm_edid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_mode_status
|
||||||
|
dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge,
|
||||||
|
const struct drm_display_info *info,
|
||||||
|
const struct drm_display_mode *mode)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
unsigned long long rate;
|
||||||
|
|
||||||
|
rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
|
||||||
|
if (rate > HDMI14_MAX_TMDSCLK) {
|
||||||
|
dev_dbg(hdmi->dev, "Unsupported mode clock: %d\n", mode->clock);
|
||||||
|
return MODE_CLOCK_HIGH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge,
|
||||||
|
enum hdmi_infoframe_type type)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case HDMI_INFOFRAME_TYPE_AVI:
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
|
||||||
|
PKTSCHED_PKT_EN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HDMI_INFOFRAME_TYPE_DRM:
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge,
|
||||||
|
enum hdmi_infoframe_type type,
|
||||||
|
const u8 *buffer, size_t len)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
|
||||||
|
dw_hdmi_qp_bridge_clear_infoframe(bridge, type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case HDMI_INFOFRAME_TYPE_AVI:
|
||||||
|
return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len);
|
||||||
|
|
||||||
|
case HDMI_INFOFRAME_TYPE_DRM:
|
||||||
|
return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len);
|
||||||
|
|
||||||
|
default:
|
||||||
|
dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = {
|
||||||
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
|
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||||
|
.atomic_check = dw_hdmi_qp_bridge_atomic_check,
|
||||||
|
.atomic_enable = dw_hdmi_qp_bridge_atomic_enable,
|
||||||
|
.atomic_disable = dw_hdmi_qp_bridge_atomic_disable,
|
||||||
|
.detect = dw_hdmi_qp_bridge_detect,
|
||||||
|
.edid_read = dw_hdmi_qp_bridge_edid_read,
|
||||||
|
.mode_valid = dw_hdmi_qp_bridge_mode_valid,
|
||||||
|
.hdmi_clear_infoframe = dw_hdmi_qp_bridge_clear_infoframe,
|
||||||
|
.hdmi_write_infoframe = dw_hdmi_qp_bridge_write_infoframe,
|
||||||
|
};
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = dev_id;
|
||||||
|
struct dw_hdmi_qp_i2c *i2c = hdmi->i2c;
|
||||||
|
u32 stat;
|
||||||
|
|
||||||
|
stat = dw_hdmi_qp_read(hdmi, MAINUNIT_1_INT_STATUS);
|
||||||
|
|
||||||
|
i2c->stat = stat & (I2CM_OP_DONE_IRQ | I2CM_READ_REQUEST_IRQ |
|
||||||
|
I2CM_NACK_RCVD_IRQ);
|
||||||
|
|
||||||
|
if (i2c->stat) {
|
||||||
|
dw_hdmi_qp_write(hdmi, i2c->stat, MAINUNIT_1_INT_CLEAR);
|
||||||
|
complete(&i2c->cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat)
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config dw_hdmi_qp_regmap_config = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.val_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.max_register = EARCRX_1_INT_FORCE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_init_hw(struct dw_hdmi_qp *hdmi)
|
||||||
|
{
|
||||||
|
dw_hdmi_qp_write(hdmi, 0, MAINUNIT_0_INT_MASK_N);
|
||||||
|
dw_hdmi_qp_write(hdmi, 0, MAINUNIT_1_INT_MASK_N);
|
||||||
|
dw_hdmi_qp_write(hdmi, 428571429, TIMER_BASE_CONFIG0);
|
||||||
|
|
||||||
|
/* Software reset */
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x01, I2CM_CONTROL0);
|
||||||
|
|
||||||
|
dw_hdmi_qp_write(hdmi, 0x085c085c, I2CM_FM_SCL_CONFIG0);
|
||||||
|
|
||||||
|
dw_hdmi_qp_mod(hdmi, 0, I2CM_FM_EN, I2CM_INTERFACE_CONTROL0);
|
||||||
|
|
||||||
|
/* Clear DONE and ERROR interrupts */
|
||||||
|
dw_hdmi_qp_write(hdmi, I2CM_OP_DONE_CLEAR | I2CM_NACK_RCVD_CLEAR,
|
||||||
|
MAINUNIT_1_INT_CLEAR);
|
||||||
|
|
||||||
|
if (hdmi->phy.ops->setup_hpd)
|
||||||
|
hdmi->phy.ops->setup_hpd(hdmi, hdmi->phy.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
|
||||||
|
struct drm_encoder *encoder,
|
||||||
|
const struct dw_hdmi_qp_plat_data *plat_data)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct dw_hdmi_qp *hdmi;
|
||||||
|
void __iomem *regs;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!plat_data->phy_ops || !plat_data->phy_ops->init ||
|
||||||
|
!plat_data->phy_ops->disable || !plat_data->phy_ops->read_hpd) {
|
||||||
|
dev_err(dev, "Missing platform PHY ops\n");
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
|
||||||
|
if (!hdmi)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
hdmi->dev = dev;
|
||||||
|
|
||||||
|
regs = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(regs))
|
||||||
|
return ERR_CAST(regs);
|
||||||
|
|
||||||
|
hdmi->regm = devm_regmap_init_mmio(dev, regs, &dw_hdmi_qp_regmap_config);
|
||||||
|
if (IS_ERR(hdmi->regm)) {
|
||||||
|
dev_err(dev, "Failed to configure regmap\n");
|
||||||
|
return ERR_CAST(hdmi->regm);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->phy.ops = plat_data->phy_ops;
|
||||||
|
hdmi->phy.data = plat_data->phy_data;
|
||||||
|
|
||||||
|
dw_hdmi_qp_init_hw(hdmi);
|
||||||
|
|
||||||
|
ret = devm_request_threaded_irq(dev, plat_data->main_irq,
|
||||||
|
dw_hdmi_qp_main_hardirq, NULL,
|
||||||
|
IRQF_SHARED, dev_name(dev), hdmi);
|
||||||
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
|
hdmi->bridge.driver_private = hdmi;
|
||||||
|
hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs;
|
||||||
|
hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
|
||||||
|
DRM_BRIDGE_OP_EDID |
|
||||||
|
DRM_BRIDGE_OP_HDMI |
|
||||||
|
DRM_BRIDGE_OP_HPD;
|
||||||
|
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||||
|
hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||||
|
hdmi->bridge.vendor = "Synopsys";
|
||||||
|
hdmi->bridge.product = "DW HDMI QP TX";
|
||||||
|
|
||||||
|
hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
|
||||||
|
if (IS_ERR(hdmi->bridge.ddc))
|
||||||
|
return ERR_CAST(hdmi->bridge.ddc);
|
||||||
|
|
||||||
|
ret = devm_drm_bridge_add(dev, &hdmi->bridge);
|
||||||
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
|
ret = drm_bridge_attach(encoder, &hdmi->bridge, NULL,
|
||||||
|
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||||
|
if (ret)
|
||||||
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
|
return hdmi;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
|
||||||
|
|
||||||
|
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
|
||||||
|
{
|
||||||
|
dw_hdmi_qp_init_hw(hdmi);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
|
||||||
|
MODULE_AUTHOR("Cristian Ciocaltea <cristian.ciocaltea@collabora.com>");
|
||||||
|
MODULE_DESCRIPTION("DW HDMI QP transmitter library");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
@ -0,0 +1,834 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Copyright (C) Rockchip Electronics Co.Ltd
|
||||||
|
* Author:
|
||||||
|
* Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
*/
|
||||||
|
#ifndef __DW_HDMI_QP_H__
|
||||||
|
#define __DW_HDMI_QP_H__
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
|
|
||||||
|
/* Main Unit Registers */
|
||||||
|
#define CORE_ID 0x0
|
||||||
|
#define VER_NUMBER 0x4
|
||||||
|
#define VER_TYPE 0x8
|
||||||
|
#define CONFIG_REG 0xc
|
||||||
|
#define CONFIG_CEC BIT(28)
|
||||||
|
#define CONFIG_AUD_UD BIT(23)
|
||||||
|
#define CORE_TIMESTAMP_HHMM 0x14
|
||||||
|
#define CORE_TIMESTAMP_MMDD 0x18
|
||||||
|
#define CORE_TIMESTAMP_YYYY 0x1c
|
||||||
|
/* Reset Manager Registers */
|
||||||
|
#define GLOBAL_SWRESET_REQUEST 0x40
|
||||||
|
#define EARCRX_CMDC_SWINIT_P BIT(27)
|
||||||
|
#define AVP_DATAPATH_PACKET_AUDIO_SWINIT_P BIT(10)
|
||||||
|
#define GLOBAL_SWDISABLE 0x44
|
||||||
|
#define CEC_SWDISABLE BIT(17)
|
||||||
|
#define AVP_DATAPATH_PACKET_AUDIO_SWDISABLE BIT(10)
|
||||||
|
#define AVP_DATAPATH_VIDEO_SWDISABLE BIT(6)
|
||||||
|
#define RESET_MANAGER_CONFIG0 0x48
|
||||||
|
#define RESET_MANAGER_STATUS0 0x50
|
||||||
|
#define RESET_MANAGER_STATUS1 0x54
|
||||||
|
#define RESET_MANAGER_STATUS2 0x58
|
||||||
|
/* Timer Base Registers */
|
||||||
|
#define TIMER_BASE_CONFIG0 0x80
|
||||||
|
#define TIMER_BASE_STATUS0 0x84
|
||||||
|
/* CMU Registers */
|
||||||
|
#define CMU_CONFIG0 0xa0
|
||||||
|
#define CMU_CONFIG1 0xa4
|
||||||
|
#define CMU_CONFIG2 0xa8
|
||||||
|
#define CMU_CONFIG3 0xac
|
||||||
|
#define CMU_STATUS 0xb0
|
||||||
|
#define DISPLAY_CLK_MONITOR 0x3f
|
||||||
|
#define DISPLAY_CLK_LOCKED 0X15
|
||||||
|
#define EARC_BPCLK_OFF BIT(9)
|
||||||
|
#define AUDCLK_OFF BIT(7)
|
||||||
|
#define LINKQPCLK_OFF BIT(5)
|
||||||
|
#define VIDQPCLK_OFF BIT(3)
|
||||||
|
#define IPI_CLK_OFF BIT(1)
|
||||||
|
#define CMU_IPI_CLK_FREQ 0xb4
|
||||||
|
#define CMU_VIDQPCLK_FREQ 0xb8
|
||||||
|
#define CMU_LINKQPCLK_FREQ 0xbc
|
||||||
|
#define CMU_AUDQPCLK_FREQ 0xc0
|
||||||
|
#define CMU_EARC_BPCLK_FREQ 0xc4
|
||||||
|
/* I2CM Registers */
|
||||||
|
#define I2CM_SM_SCL_CONFIG0 0xe0
|
||||||
|
#define I2CM_FM_SCL_CONFIG0 0xe4
|
||||||
|
#define I2CM_CONFIG0 0xe8
|
||||||
|
#define I2CM_CONTROL0 0xec
|
||||||
|
#define I2CM_STATUS0 0xf0
|
||||||
|
#define I2CM_INTERFACE_CONTROL0 0xf4
|
||||||
|
#define I2CM_ADDR 0xff000
|
||||||
|
#define I2CM_SLVADDR 0xfe0
|
||||||
|
#define I2CM_WR_MASK 0x1e
|
||||||
|
#define I2CM_EXT_READ BIT(4)
|
||||||
|
#define I2CM_SHORT_READ BIT(3)
|
||||||
|
#define I2CM_FM_READ BIT(2)
|
||||||
|
#define I2CM_FM_WRITE BIT(1)
|
||||||
|
#define I2CM_FM_EN BIT(0)
|
||||||
|
#define I2CM_INTERFACE_CONTROL1 0xf8
|
||||||
|
#define I2CM_SEG_PTR 0x7f80
|
||||||
|
#define I2CM_SEG_ADDR 0x7f
|
||||||
|
#define I2CM_INTERFACE_WRDATA_0_3 0xfc
|
||||||
|
#define I2CM_INTERFACE_WRDATA_4_7 0x100
|
||||||
|
#define I2CM_INTERFACE_WRDATA_8_11 0x104
|
||||||
|
#define I2CM_INTERFACE_WRDATA_12_15 0x108
|
||||||
|
#define I2CM_INTERFACE_RDDATA_0_3 0x10c
|
||||||
|
#define I2CM_INTERFACE_RDDATA_4_7 0x110
|
||||||
|
#define I2CM_INTERFACE_RDDATA_8_11 0x114
|
||||||
|
#define I2CM_INTERFACE_RDDATA_12_15 0x118
|
||||||
|
/* SCDC Registers */
|
||||||
|
#define SCDC_CONFIG0 0x140
|
||||||
|
#define SCDC_I2C_FM_EN BIT(12)
|
||||||
|
#define SCDC_UPD_FLAGS_AUTO_CLR BIT(6)
|
||||||
|
#define SCDC_UPD_FLAGS_POLL_EN BIT(4)
|
||||||
|
#define SCDC_CONTROL0 0x148
|
||||||
|
#define SCDC_STATUS0 0x150
|
||||||
|
#define STATUS_UPDATE BIT(0)
|
||||||
|
#define FRL_START BIT(4)
|
||||||
|
#define FLT_UPDATE BIT(5)
|
||||||
|
/* FLT Registers */
|
||||||
|
#define FLT_CONFIG0 0x160
|
||||||
|
#define FLT_CONFIG1 0x164
|
||||||
|
#define FLT_CONFIG2 0x168
|
||||||
|
#define FLT_CONTROL0 0x170
|
||||||
|
/* Main Unit 2 Registers */
|
||||||
|
#define MAINUNIT_STATUS0 0x180
|
||||||
|
/* Video Interface Registers */
|
||||||
|
#define VIDEO_INTERFACE_CONFIG0 0x800
|
||||||
|
#define VIDEO_INTERFACE_CONFIG1 0x804
|
||||||
|
#define VIDEO_INTERFACE_CONFIG2 0x808
|
||||||
|
#define VIDEO_INTERFACE_CONTROL0 0x80c
|
||||||
|
#define VIDEO_INTERFACE_STATUS0 0x814
|
||||||
|
/* Video Packing Registers */
|
||||||
|
#define VIDEO_PACKING_CONFIG0 0x81c
|
||||||
|
/* Audio Interface Registers */
|
||||||
|
#define AUDIO_INTERFACE_CONFIG0 0x820
|
||||||
|
#define AUD_IF_SEL_MSK 0x3
|
||||||
|
#define AUD_IF_SPDIF 0x2
|
||||||
|
#define AUD_IF_I2S 0x1
|
||||||
|
#define AUD_IF_PAI 0x0
|
||||||
|
#define AUD_FIFO_INIT_ON_OVF_MSK BIT(2)
|
||||||
|
#define AUD_FIFO_INIT_ON_OVF_EN BIT(2)
|
||||||
|
#define I2S_LINES_EN_MSK GENMASK(7, 4)
|
||||||
|
#define I2S_LINES_EN(x) BIT((x) + 4)
|
||||||
|
#define I2S_BPCUV_RCV_MSK BIT(12)
|
||||||
|
#define I2S_BPCUV_RCV_EN BIT(12)
|
||||||
|
#define I2S_BPCUV_RCV_DIS 0
|
||||||
|
#define SPDIF_LINES_EN GENMASK(19, 16)
|
||||||
|
#define AUD_FORMAT_MSK GENMASK(26, 24)
|
||||||
|
#define AUD_3DOBA (0x7 << 24)
|
||||||
|
#define AUD_3DASP (0x6 << 24)
|
||||||
|
#define AUD_MSOBA (0x5 << 24)
|
||||||
|
#define AUD_MSASP (0x4 << 24)
|
||||||
|
#define AUD_HBR (0x3 << 24)
|
||||||
|
#define AUD_DST (0x2 << 24)
|
||||||
|
#define AUD_OBA (0x1 << 24)
|
||||||
|
#define AUD_ASP (0x0 << 24)
|
||||||
|
#define AUDIO_INTERFACE_CONFIG1 0x824
|
||||||
|
#define AUDIO_INTERFACE_CONTROL0 0x82c
|
||||||
|
#define AUDIO_FIFO_CLR_P BIT(0)
|
||||||
|
#define AUDIO_INTERFACE_STATUS0 0x834
|
||||||
|
/* Frame Composer Registers */
|
||||||
|
#define FRAME_COMPOSER_CONFIG0 0x840
|
||||||
|
#define FRAME_COMPOSER_CONFIG1 0x844
|
||||||
|
#define FRAME_COMPOSER_CONFIG2 0x848
|
||||||
|
#define FRAME_COMPOSER_CONFIG3 0x84c
|
||||||
|
#define FRAME_COMPOSER_CONFIG4 0x850
|
||||||
|
#define FRAME_COMPOSER_CONFIG5 0x854
|
||||||
|
#define FRAME_COMPOSER_CONFIG6 0x858
|
||||||
|
#define FRAME_COMPOSER_CONFIG7 0x85c
|
||||||
|
#define FRAME_COMPOSER_CONFIG8 0x860
|
||||||
|
#define FRAME_COMPOSER_CONFIG9 0x864
|
||||||
|
#define FRAME_COMPOSER_CONTROL0 0x86c
|
||||||
|
/* Video Monitor Registers */
|
||||||
|
#define VIDEO_MONITOR_CONFIG0 0x880
|
||||||
|
#define VIDEO_MONITOR_STATUS0 0x884
|
||||||
|
#define VIDEO_MONITOR_STATUS1 0x888
|
||||||
|
#define VIDEO_MONITOR_STATUS2 0x88c
|
||||||
|
#define VIDEO_MONITOR_STATUS3 0x890
|
||||||
|
#define VIDEO_MONITOR_STATUS4 0x894
|
||||||
|
#define VIDEO_MONITOR_STATUS5 0x898
|
||||||
|
#define VIDEO_MONITOR_STATUS6 0x89c
|
||||||
|
/* HDCP2 Logic Registers */
|
||||||
|
#define HDCP2LOGIC_CONFIG0 0x8e0
|
||||||
|
#define HDCP2_BYPASS BIT(0)
|
||||||
|
#define HDCP2LOGIC_ESM_GPIO_IN 0x8e4
|
||||||
|
#define HDCP2LOGIC_ESM_GPIO_OUT 0x8e8
|
||||||
|
/* HDCP14 Registers */
|
||||||
|
#define HDCP14_CONFIG0 0x900
|
||||||
|
#define HDCP14_CONFIG1 0x904
|
||||||
|
#define HDCP14_CONFIG2 0x908
|
||||||
|
#define HDCP14_CONFIG3 0x90c
|
||||||
|
#define HDCP14_KEY_SEED 0x914
|
||||||
|
#define HDCP14_KEY_H 0x918
|
||||||
|
#define HDCP14_KEY_L 0x91c
|
||||||
|
#define HDCP14_KEY_STATUS 0x920
|
||||||
|
#define HDCP14_AKSV_H 0x924
|
||||||
|
#define HDCP14_AKSV_L 0x928
|
||||||
|
#define HDCP14_AN_H 0x92c
|
||||||
|
#define HDCP14_AN_L 0x930
|
||||||
|
#define HDCP14_STATUS0 0x934
|
||||||
|
#define HDCP14_STATUS1 0x938
|
||||||
|
/* Scrambler Registers */
|
||||||
|
#define SCRAMB_CONFIG0 0x960
|
||||||
|
/* Video Configuration Registers */
|
||||||
|
#define LINK_CONFIG0 0x968
|
||||||
|
#define OPMODE_FRL_4LANES BIT(8)
|
||||||
|
#define OPMODE_DVI BIT(4)
|
||||||
|
#define OPMODE_FRL BIT(0)
|
||||||
|
/* TMDS FIFO Registers */
|
||||||
|
#define TMDS_FIFO_CONFIG0 0x970
|
||||||
|
#define TMDS_FIFO_CONTROL0 0x974
|
||||||
|
/* FRL RSFEC Registers */
|
||||||
|
#define FRL_RSFEC_CONFIG0 0xa20
|
||||||
|
#define FRL_RSFEC_STATUS0 0xa30
|
||||||
|
/* FRL Packetizer Registers */
|
||||||
|
#define FRL_PKTZ_CONFIG0 0xa40
|
||||||
|
#define FRL_PKTZ_CONTROL0 0xa44
|
||||||
|
#define FRL_PKTZ_CONTROL1 0xa50
|
||||||
|
#define FRL_PKTZ_STATUS1 0xa54
|
||||||
|
/* Packet Scheduler Registers */
|
||||||
|
#define PKTSCHED_CONFIG0 0xa80
|
||||||
|
#define PKTSCHED_PRQUEUE0_CONFIG0 0xa84
|
||||||
|
#define PKTSCHED_PRQUEUE1_CONFIG0 0xa88
|
||||||
|
#define PKTSCHED_PRQUEUE2_CONFIG0 0xa8c
|
||||||
|
#define PKTSCHED_PRQUEUE2_CONFIG1 0xa90
|
||||||
|
#define PKTSCHED_PRQUEUE2_CONFIG2 0xa94
|
||||||
|
#define PKTSCHED_PKT_CONFIG0 0xa98
|
||||||
|
#define PKTSCHED_PKT_CONFIG1 0xa9c
|
||||||
|
#define PKTSCHED_DRMI_FIELDRATE BIT(13)
|
||||||
|
#define PKTSCHED_AVI_FIELDRATE BIT(12)
|
||||||
|
#define PKTSCHED_PKT_CONFIG2 0xaa0
|
||||||
|
#define PKTSCHED_PKT_CONFIG3 0xaa4
|
||||||
|
#define PKTSCHED_PKT_EN 0xaa8
|
||||||
|
#define PKTSCHED_DRMI_TX_EN BIT(17)
|
||||||
|
#define PKTSCHED_AUDI_TX_EN BIT(15)
|
||||||
|
#define PKTSCHED_AVI_TX_EN BIT(13)
|
||||||
|
#define PKTSCHED_EMP_CVTEM_TX_EN BIT(10)
|
||||||
|
#define PKTSCHED_AMD_TX_EN BIT(8)
|
||||||
|
#define PKTSCHED_GCP_TX_EN BIT(3)
|
||||||
|
#define PKTSCHED_AUDS_TX_EN BIT(2)
|
||||||
|
#define PKTSCHED_ACR_TX_EN BIT(1)
|
||||||
|
#define PKTSCHED_NULL_TX_EN BIT(0)
|
||||||
|
#define PKTSCHED_PKT_CONTROL0 0xaac
|
||||||
|
#define PKTSCHED_PKT_SEND 0xab0
|
||||||
|
#define PKTSCHED_PKT_STATUS0 0xab4
|
||||||
|
#define PKTSCHED_PKT_STATUS1 0xab8
|
||||||
|
#define PKT_NULL_CONTENTS0 0xb00
|
||||||
|
#define PKT_NULL_CONTENTS1 0xb04
|
||||||
|
#define PKT_NULL_CONTENTS2 0xb08
|
||||||
|
#define PKT_NULL_CONTENTS3 0xb0c
|
||||||
|
#define PKT_NULL_CONTENTS4 0xb10
|
||||||
|
#define PKT_NULL_CONTENTS5 0xb14
|
||||||
|
#define PKT_NULL_CONTENTS6 0xb18
|
||||||
|
#define PKT_NULL_CONTENTS7 0xb1c
|
||||||
|
#define PKT_ACP_CONTENTS0 0xb20
|
||||||
|
#define PKT_ACP_CONTENTS1 0xb24
|
||||||
|
#define PKT_ACP_CONTENTS2 0xb28
|
||||||
|
#define PKT_ACP_CONTENTS3 0xb2c
|
||||||
|
#define PKT_ACP_CONTENTS4 0xb30
|
||||||
|
#define PKT_ACP_CONTENTS5 0xb34
|
||||||
|
#define PKT_ACP_CONTENTS6 0xb38
|
||||||
|
#define PKT_ACP_CONTENTS7 0xb3c
|
||||||
|
#define PKT_ISRC1_CONTENTS0 0xb40
|
||||||
|
#define PKT_ISRC1_CONTENTS1 0xb44
|
||||||
|
#define PKT_ISRC1_CONTENTS2 0xb48
|
||||||
|
#define PKT_ISRC1_CONTENTS3 0xb4c
|
||||||
|
#define PKT_ISRC1_CONTENTS4 0xb50
|
||||||
|
#define PKT_ISRC1_CONTENTS5 0xb54
|
||||||
|
#define PKT_ISRC1_CONTENTS6 0xb58
|
||||||
|
#define PKT_ISRC1_CONTENTS7 0xb5c
|
||||||
|
#define PKT_ISRC2_CONTENTS0 0xb60
|
||||||
|
#define PKT_ISRC2_CONTENTS1 0xb64
|
||||||
|
#define PKT_ISRC2_CONTENTS2 0xb68
|
||||||
|
#define PKT_ISRC2_CONTENTS3 0xb6c
|
||||||
|
#define PKT_ISRC2_CONTENTS4 0xb70
|
||||||
|
#define PKT_ISRC2_CONTENTS5 0xb74
|
||||||
|
#define PKT_ISRC2_CONTENTS6 0xb78
|
||||||
|
#define PKT_ISRC2_CONTENTS7 0xb7c
|
||||||
|
#define PKT_GMD_CONTENTS0 0xb80
|
||||||
|
#define PKT_GMD_CONTENTS1 0xb84
|
||||||
|
#define PKT_GMD_CONTENTS2 0xb88
|
||||||
|
#define PKT_GMD_CONTENTS3 0xb8c
|
||||||
|
#define PKT_GMD_CONTENTS4 0xb90
|
||||||
|
#define PKT_GMD_CONTENTS5 0xb94
|
||||||
|
#define PKT_GMD_CONTENTS6 0xb98
|
||||||
|
#define PKT_GMD_CONTENTS7 0xb9c
|
||||||
|
#define PKT_AMD_CONTENTS0 0xba0
|
||||||
|
#define PKT_AMD_CONTENTS1 0xba4
|
||||||
|
#define PKT_AMD_CONTENTS2 0xba8
|
||||||
|
#define PKT_AMD_CONTENTS3 0xbac
|
||||||
|
#define PKT_AMD_CONTENTS4 0xbb0
|
||||||
|
#define PKT_AMD_CONTENTS5 0xbb4
|
||||||
|
#define PKT_AMD_CONTENTS6 0xbb8
|
||||||
|
#define PKT_AMD_CONTENTS7 0xbbc
|
||||||
|
#define PKT_VSI_CONTENTS0 0xbc0
|
||||||
|
#define PKT_VSI_CONTENTS1 0xbc4
|
||||||
|
#define PKT_VSI_CONTENTS2 0xbc8
|
||||||
|
#define PKT_VSI_CONTENTS3 0xbcc
|
||||||
|
#define PKT_VSI_CONTENTS4 0xbd0
|
||||||
|
#define PKT_VSI_CONTENTS5 0xbd4
|
||||||
|
#define PKT_VSI_CONTENTS6 0xbd8
|
||||||
|
#define PKT_VSI_CONTENTS7 0xbdc
|
||||||
|
#define PKT_AVI_CONTENTS0 0xbe0
|
||||||
|
#define HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT BIT(4)
|
||||||
|
#define HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR 0x04
|
||||||
|
#define HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR 0x08
|
||||||
|
#define HDMI_FC_AVICONF2_IT_CONTENT_VALID 0x80
|
||||||
|
#define PKT_AVI_CONTENTS1 0xbe4
|
||||||
|
#define PKT_AVI_CONTENTS2 0xbe8
|
||||||
|
#define PKT_AVI_CONTENTS3 0xbec
|
||||||
|
#define PKT_AVI_CONTENTS4 0xbf0
|
||||||
|
#define PKT_AVI_CONTENTS5 0xbf4
|
||||||
|
#define PKT_AVI_CONTENTS6 0xbf8
|
||||||
|
#define PKT_AVI_CONTENTS7 0xbfc
|
||||||
|
#define PKT_SPDI_CONTENTS0 0xc00
|
||||||
|
#define PKT_SPDI_CONTENTS1 0xc04
|
||||||
|
#define PKT_SPDI_CONTENTS2 0xc08
|
||||||
|
#define PKT_SPDI_CONTENTS3 0xc0c
|
||||||
|
#define PKT_SPDI_CONTENTS4 0xc10
|
||||||
|
#define PKT_SPDI_CONTENTS5 0xc14
|
||||||
|
#define PKT_SPDI_CONTENTS6 0xc18
|
||||||
|
#define PKT_SPDI_CONTENTS7 0xc1c
|
||||||
|
#define PKT_AUDI_CONTENTS0 0xc20
|
||||||
|
#define PKT_AUDI_CONTENTS1 0xc24
|
||||||
|
#define PKT_AUDI_CONTENTS2 0xc28
|
||||||
|
#define PKT_AUDI_CONTENTS3 0xc2c
|
||||||
|
#define PKT_AUDI_CONTENTS4 0xc30
|
||||||
|
#define PKT_AUDI_CONTENTS5 0xc34
|
||||||
|
#define PKT_AUDI_CONTENTS6 0xc38
|
||||||
|
#define PKT_AUDI_CONTENTS7 0xc3c
|
||||||
|
#define PKT_NVI_CONTENTS0 0xc40
|
||||||
|
#define PKT_NVI_CONTENTS1 0xc44
|
||||||
|
#define PKT_NVI_CONTENTS2 0xc48
|
||||||
|
#define PKT_NVI_CONTENTS3 0xc4c
|
||||||
|
#define PKT_NVI_CONTENTS4 0xc50
|
||||||
|
#define PKT_NVI_CONTENTS5 0xc54
|
||||||
|
#define PKT_NVI_CONTENTS6 0xc58
|
||||||
|
#define PKT_NVI_CONTENTS7 0xc5c
|
||||||
|
#define PKT_DRMI_CONTENTS0 0xc60
|
||||||
|
#define PKT_DRMI_CONTENTS1 0xc64
|
||||||
|
#define PKT_DRMI_CONTENTS2 0xc68
|
||||||
|
#define PKT_DRMI_CONTENTS3 0xc6c
|
||||||
|
#define PKT_DRMI_CONTENTS4 0xc70
|
||||||
|
#define PKT_DRMI_CONTENTS5 0xc74
|
||||||
|
#define PKT_DRMI_CONTENTS6 0xc78
|
||||||
|
#define PKT_DRMI_CONTENTS7 0xc7c
|
||||||
|
#define PKT_GHDMI1_CONTENTS0 0xc80
|
||||||
|
#define PKT_GHDMI1_CONTENTS1 0xc84
|
||||||
|
#define PKT_GHDMI1_CONTENTS2 0xc88
|
||||||
|
#define PKT_GHDMI1_CONTENTS3 0xc8c
|
||||||
|
#define PKT_GHDMI1_CONTENTS4 0xc90
|
||||||
|
#define PKT_GHDMI1_CONTENTS5 0xc94
|
||||||
|
#define PKT_GHDMI1_CONTENTS6 0xc98
|
||||||
|
#define PKT_GHDMI1_CONTENTS7 0xc9c
|
||||||
|
#define PKT_GHDMI2_CONTENTS0 0xca0
|
||||||
|
#define PKT_GHDMI2_CONTENTS1 0xca4
|
||||||
|
#define PKT_GHDMI2_CONTENTS2 0xca8
|
||||||
|
#define PKT_GHDMI2_CONTENTS3 0xcac
|
||||||
|
#define PKT_GHDMI2_CONTENTS4 0xcb0
|
||||||
|
#define PKT_GHDMI2_CONTENTS5 0xcb4
|
||||||
|
#define PKT_GHDMI2_CONTENTS6 0xcb8
|
||||||
|
#define PKT_GHDMI2_CONTENTS7 0xcbc
|
||||||
|
/* EMP Packetizer Registers */
|
||||||
|
#define PKT_EMP_CONFIG0 0xce0
|
||||||
|
#define PKT_EMP_CONTROL0 0xcec
|
||||||
|
#define PKT_EMP_CONTROL1 0xcf0
|
||||||
|
#define PKT_EMP_CONTROL2 0xcf4
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS0 0xd00
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS1 0xd04
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS2 0xd08
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS3 0xd0c
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS4 0xd10
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS5 0xd14
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS6 0xd18
|
||||||
|
#define PKT_EMP_VTEM_CONTENTS7 0xd1c
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS0 0xd20
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS1 0xd24
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS2 0xd28
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS3 0xd2c
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS4 0xd30
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS5 0xd34
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS6 0xd38
|
||||||
|
#define PKT0_EMP_CVTEM_CONTENTS7 0xd3c
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS0 0xd40
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS1 0xd44
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS2 0xd48
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS3 0xd4c
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS4 0xd50
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS5 0xd54
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS6 0xd58
|
||||||
|
#define PKT1_EMP_CVTEM_CONTENTS7 0xd5c
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS0 0xd60
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS1 0xd64
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS2 0xd68
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS3 0xd6c
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS4 0xd70
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS5 0xd74
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS6 0xd78
|
||||||
|
#define PKT2_EMP_CVTEM_CONTENTS7 0xd7c
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS0 0xd80
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS1 0xd84
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS2 0xd88
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS3 0xd8c
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS4 0xd90
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS5 0xd94
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS6 0xd98
|
||||||
|
#define PKT3_EMP_CVTEM_CONTENTS7 0xd9c
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS0 0xda0
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS1 0xda4
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS2 0xda8
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS3 0xdac
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS4 0xdb0
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS5 0xdb4
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS6 0xdb8
|
||||||
|
#define PKT4_EMP_CVTEM_CONTENTS7 0xdbc
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS0 0xdc0
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS1 0xdc4
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS2 0xdc8
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS3 0xdcc
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS4 0xdd0
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS5 0xdd4
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS6 0xdd8
|
||||||
|
#define PKT5_EMP_CVTEM_CONTENTS7 0xddc
|
||||||
|
/* Audio Packetizer Registers */
|
||||||
|
#define AUDPKT_CONTROL0 0xe20
|
||||||
|
#define AUDPKT_PBIT_FORCE_EN_MASK BIT(12)
|
||||||
|
#define AUDPKT_PBIT_FORCE_EN BIT(12)
|
||||||
|
#define AUDPKT_CHSTATUS_OVR_EN_MASK BIT(0)
|
||||||
|
#define AUDPKT_CHSTATUS_OVR_EN BIT(0)
|
||||||
|
#define AUDPKT_CONTROL1 0xe24
|
||||||
|
#define AUDPKT_ACR_CONTROL0 0xe40
|
||||||
|
#define AUDPKT_ACR_N_VALUE 0xfffff
|
||||||
|
#define AUDPKT_ACR_CONTROL1 0xe44
|
||||||
|
#define AUDPKT_ACR_CTS_OVR_VAL_MSK GENMASK(23, 4)
|
||||||
|
#define AUDPKT_ACR_CTS_OVR_VAL(x) ((x) << 4)
|
||||||
|
#define AUDPKT_ACR_CTS_OVR_EN_MSK BIT(1)
|
||||||
|
#define AUDPKT_ACR_CTS_OVR_EN BIT(1)
|
||||||
|
#define AUDPKT_ACR_STATUS0 0xe4c
|
||||||
|
#define AUDPKT_CHSTATUS_OVR0 0xe60
|
||||||
|
#define AUDPKT_CHSTATUS_OVR1 0xe64
|
||||||
|
/* IEC60958 Byte 3: Sampleing frenuency Bits 24 to 27 */
|
||||||
|
#define AUDPKT_CHSTATUS_SR_MASK GENMASK(3, 0)
|
||||||
|
#define AUDPKT_CHSTATUS_SR_22050 0x4
|
||||||
|
#define AUDPKT_CHSTATUS_SR_24000 0x6
|
||||||
|
#define AUDPKT_CHSTATUS_SR_32000 0x3
|
||||||
|
#define AUDPKT_CHSTATUS_SR_44100 0x0
|
||||||
|
#define AUDPKT_CHSTATUS_SR_48000 0x2
|
||||||
|
#define AUDPKT_CHSTATUS_SR_88200 0x8
|
||||||
|
#define AUDPKT_CHSTATUS_SR_96000 0xa
|
||||||
|
#define AUDPKT_CHSTATUS_SR_176400 0xc
|
||||||
|
#define AUDPKT_CHSTATUS_SR_192000 0xe
|
||||||
|
#define AUDPKT_CHSTATUS_SR_768000 0x9
|
||||||
|
#define AUDPKT_CHSTATUS_SR_NOT_INDICATED 0x1
|
||||||
|
/* IEC60958 Byte 4: Original Sampleing frenuency Bits 36 to 39 */
|
||||||
|
#define AUDPKT_CHSTATUS_0SR_MASK GENMASK(15, 12)
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_8000 0x6
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_11025 0xa
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_12000 0x2
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_16000 0x8
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_22050 0xb
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_24000 0x9
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_32000 0xc
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_44100 0xf
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_48000 0xd
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_88200 0x7
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_96000 0x5
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_176400 0x3
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_192000 0x1
|
||||||
|
#define AUDPKT_CHSTATUS_OSR_NOT_INDICATED 0x0
|
||||||
|
#define AUDPKT_CHSTATUS_OVR2 0xe68
|
||||||
|
#define AUDPKT_CHSTATUS_OVR3 0xe6c
|
||||||
|
#define AUDPKT_CHSTATUS_OVR4 0xe70
|
||||||
|
#define AUDPKT_CHSTATUS_OVR5 0xe74
|
||||||
|
#define AUDPKT_CHSTATUS_OVR6 0xe78
|
||||||
|
#define AUDPKT_CHSTATUS_OVR7 0xe7c
|
||||||
|
#define AUDPKT_CHSTATUS_OVR8 0xe80
|
||||||
|
#define AUDPKT_CHSTATUS_OVR9 0xe84
|
||||||
|
#define AUDPKT_CHSTATUS_OVR10 0xe88
|
||||||
|
#define AUDPKT_CHSTATUS_OVR11 0xe8c
|
||||||
|
#define AUDPKT_CHSTATUS_OVR12 0xe90
|
||||||
|
#define AUDPKT_CHSTATUS_OVR13 0xe94
|
||||||
|
#define AUDPKT_CHSTATUS_OVR14 0xe98
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC0 0xea0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC1 0xea4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC2 0xea8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC3 0xeac
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC4 0xeb0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC5 0xeb4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC6 0xeb8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC7 0xebc
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC8 0xec0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC9 0xec4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC10 0xec8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC11 0xecc
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC12 0xed0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC13 0xed4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC14 0xed8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC15 0xedc
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC16 0xee0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC17 0xee4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC18 0xee8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC19 0xeec
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC20 0xef0
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC21 0xef4
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC22 0xef8
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC23 0xefc
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC24 0xf00
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC25 0xf04
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC26 0xf08
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC27 0xf0c
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC28 0xf10
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC29 0xf14
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC30 0xf18
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC31 0xf1c
|
||||||
|
#define AUDPKT_USRDATA_OVR_MSG_GENERIC32 0xf20
|
||||||
|
#define AUDPKT_VBIT_OVR0 0xf24
|
||||||
|
/* CEC Registers */
|
||||||
|
#define CEC_TX_CONTROL 0x1000
|
||||||
|
#define CEC_STATUS 0x1004
|
||||||
|
#define CEC_CONFIG 0x1008
|
||||||
|
#define CEC_ADDR 0x100c
|
||||||
|
#define CEC_TX_COUNT 0x1020
|
||||||
|
#define CEC_TX_DATA3_0 0x1024
|
||||||
|
#define CEC_TX_DATA7_4 0x1028
|
||||||
|
#define CEC_TX_DATA11_8 0x102c
|
||||||
|
#define CEC_TX_DATA15_12 0x1030
|
||||||
|
#define CEC_RX_COUNT_STATUS 0x1040
|
||||||
|
#define CEC_RX_DATA3_0 0x1044
|
||||||
|
#define CEC_RX_DATA7_4 0x1048
|
||||||
|
#define CEC_RX_DATA11_8 0x104c
|
||||||
|
#define CEC_RX_DATA15_12 0x1050
|
||||||
|
#define CEC_LOCK_CONTROL 0x1054
|
||||||
|
#define CEC_RXQUAL_BITTIME_CONFIG 0x1060
|
||||||
|
#define CEC_RX_BITTIME_CONFIG 0x1064
|
||||||
|
#define CEC_TX_BITTIME_CONFIG 0x1068
|
||||||
|
/* eARC RX CMDC Registers */
|
||||||
|
#define EARCRX_CMDC_CONFIG0 0x1800
|
||||||
|
#define EARCRX_XACTREAD_STOP_CFG BIT(26)
|
||||||
|
#define EARCRX_XACTREAD_RETRY_CFG BIT(25)
|
||||||
|
#define EARCRX_CMDC_DSCVR_EARCVALID0_TO_DISC1 BIT(24)
|
||||||
|
#define EARCRX_CMDC_XACT_RESTART_EN BIT(18)
|
||||||
|
#define EARCRX_CMDC_CONFIG1 0x1804
|
||||||
|
#define EARCRX_CMDC_CONTROL 0x1808
|
||||||
|
#define EARCRX_CMDC_HEARTBEAT_LOSS_EN BIT(4)
|
||||||
|
#define EARCRX_CMDC_DISCOVERY_EN BIT(3)
|
||||||
|
#define EARCRX_CONNECTOR_HPD BIT(1)
|
||||||
|
#define EARCRX_CMDC_WHITELIST0_CONFIG 0x180c
|
||||||
|
#define EARCRX_CMDC_WHITELIST1_CONFIG 0x1810
|
||||||
|
#define EARCRX_CMDC_WHITELIST2_CONFIG 0x1814
|
||||||
|
#define EARCRX_CMDC_WHITELIST3_CONFIG 0x1818
|
||||||
|
#define EARCRX_CMDC_STATUS 0x181c
|
||||||
|
#define EARCRX_CMDC_XACT_INFO 0x1820
|
||||||
|
#define EARCRX_CMDC_XACT_ACTION 0x1824
|
||||||
|
#define EARCRX_CMDC_HEARTBEAT_RXSTAT_SE 0x1828
|
||||||
|
#define EARCRX_CMDC_HEARTBEAT_STATUS 0x182c
|
||||||
|
#define EARCRX_CMDC_XACT_WR0 0x1840
|
||||||
|
#define EARCRX_CMDC_XACT_WR1 0x1844
|
||||||
|
#define EARCRX_CMDC_XACT_WR2 0x1848
|
||||||
|
#define EARCRX_CMDC_XACT_WR3 0x184c
|
||||||
|
#define EARCRX_CMDC_XACT_WR4 0x1850
|
||||||
|
#define EARCRX_CMDC_XACT_WR5 0x1854
|
||||||
|
#define EARCRX_CMDC_XACT_WR6 0x1858
|
||||||
|
#define EARCRX_CMDC_XACT_WR7 0x185c
|
||||||
|
#define EARCRX_CMDC_XACT_WR8 0x1860
|
||||||
|
#define EARCRX_CMDC_XACT_WR9 0x1864
|
||||||
|
#define EARCRX_CMDC_XACT_WR10 0x1868
|
||||||
|
#define EARCRX_CMDC_XACT_WR11 0x186c
|
||||||
|
#define EARCRX_CMDC_XACT_WR12 0x1870
|
||||||
|
#define EARCRX_CMDC_XACT_WR13 0x1874
|
||||||
|
#define EARCRX_CMDC_XACT_WR14 0x1878
|
||||||
|
#define EARCRX_CMDC_XACT_WR15 0x187c
|
||||||
|
#define EARCRX_CMDC_XACT_WR16 0x1880
|
||||||
|
#define EARCRX_CMDC_XACT_WR17 0x1884
|
||||||
|
#define EARCRX_CMDC_XACT_WR18 0x1888
|
||||||
|
#define EARCRX_CMDC_XACT_WR19 0x188c
|
||||||
|
#define EARCRX_CMDC_XACT_WR20 0x1890
|
||||||
|
#define EARCRX_CMDC_XACT_WR21 0x1894
|
||||||
|
#define EARCRX_CMDC_XACT_WR22 0x1898
|
||||||
|
#define EARCRX_CMDC_XACT_WR23 0x189c
|
||||||
|
#define EARCRX_CMDC_XACT_WR24 0x18a0
|
||||||
|
#define EARCRX_CMDC_XACT_WR25 0x18a4
|
||||||
|
#define EARCRX_CMDC_XACT_WR26 0x18a8
|
||||||
|
#define EARCRX_CMDC_XACT_WR27 0x18ac
|
||||||
|
#define EARCRX_CMDC_XACT_WR28 0x18b0
|
||||||
|
#define EARCRX_CMDC_XACT_WR29 0x18b4
|
||||||
|
#define EARCRX_CMDC_XACT_WR30 0x18b8
|
||||||
|
#define EARCRX_CMDC_XACT_WR31 0x18bc
|
||||||
|
#define EARCRX_CMDC_XACT_WR32 0x18c0
|
||||||
|
#define EARCRX_CMDC_XACT_WR33 0x18c4
|
||||||
|
#define EARCRX_CMDC_XACT_WR34 0x18c8
|
||||||
|
#define EARCRX_CMDC_XACT_WR35 0x18cc
|
||||||
|
#define EARCRX_CMDC_XACT_WR36 0x18d0
|
||||||
|
#define EARCRX_CMDC_XACT_WR37 0x18d4
|
||||||
|
#define EARCRX_CMDC_XACT_WR38 0x18d8
|
||||||
|
#define EARCRX_CMDC_XACT_WR39 0x18dc
|
||||||
|
#define EARCRX_CMDC_XACT_WR40 0x18e0
|
||||||
|
#define EARCRX_CMDC_XACT_WR41 0x18e4
|
||||||
|
#define EARCRX_CMDC_XACT_WR42 0x18e8
|
||||||
|
#define EARCRX_CMDC_XACT_WR43 0x18ec
|
||||||
|
#define EARCRX_CMDC_XACT_WR44 0x18f0
|
||||||
|
#define EARCRX_CMDC_XACT_WR45 0x18f4
|
||||||
|
#define EARCRX_CMDC_XACT_WR46 0x18f8
|
||||||
|
#define EARCRX_CMDC_XACT_WR47 0x18fc
|
||||||
|
#define EARCRX_CMDC_XACT_WR48 0x1900
|
||||||
|
#define EARCRX_CMDC_XACT_WR49 0x1904
|
||||||
|
#define EARCRX_CMDC_XACT_WR50 0x1908
|
||||||
|
#define EARCRX_CMDC_XACT_WR51 0x190c
|
||||||
|
#define EARCRX_CMDC_XACT_WR52 0x1910
|
||||||
|
#define EARCRX_CMDC_XACT_WR53 0x1914
|
||||||
|
#define EARCRX_CMDC_XACT_WR54 0x1918
|
||||||
|
#define EARCRX_CMDC_XACT_WR55 0x191c
|
||||||
|
#define EARCRX_CMDC_XACT_WR56 0x1920
|
||||||
|
#define EARCRX_CMDC_XACT_WR57 0x1924
|
||||||
|
#define EARCRX_CMDC_XACT_WR58 0x1928
|
||||||
|
#define EARCRX_CMDC_XACT_WR59 0x192c
|
||||||
|
#define EARCRX_CMDC_XACT_WR60 0x1930
|
||||||
|
#define EARCRX_CMDC_XACT_WR61 0x1934
|
||||||
|
#define EARCRX_CMDC_XACT_WR62 0x1938
|
||||||
|
#define EARCRX_CMDC_XACT_WR63 0x193c
|
||||||
|
#define EARCRX_CMDC_XACT_WR64 0x1940
|
||||||
|
#define EARCRX_CMDC_XACT_RD0 0x1960
|
||||||
|
#define EARCRX_CMDC_XACT_RD1 0x1964
|
||||||
|
#define EARCRX_CMDC_XACT_RD2 0x1968
|
||||||
|
#define EARCRX_CMDC_XACT_RD3 0x196c
|
||||||
|
#define EARCRX_CMDC_XACT_RD4 0x1970
|
||||||
|
#define EARCRX_CMDC_XACT_RD5 0x1974
|
||||||
|
#define EARCRX_CMDC_XACT_RD6 0x1978
|
||||||
|
#define EARCRX_CMDC_XACT_RD7 0x197c
|
||||||
|
#define EARCRX_CMDC_XACT_RD8 0x1980
|
||||||
|
#define EARCRX_CMDC_XACT_RD9 0x1984
|
||||||
|
#define EARCRX_CMDC_XACT_RD10 0x1988
|
||||||
|
#define EARCRX_CMDC_XACT_RD11 0x198c
|
||||||
|
#define EARCRX_CMDC_XACT_RD12 0x1990
|
||||||
|
#define EARCRX_CMDC_XACT_RD13 0x1994
|
||||||
|
#define EARCRX_CMDC_XACT_RD14 0x1998
|
||||||
|
#define EARCRX_CMDC_XACT_RD15 0x199c
|
||||||
|
#define EARCRX_CMDC_XACT_RD16 0x19a0
|
||||||
|
#define EARCRX_CMDC_XACT_RD17 0x19a4
|
||||||
|
#define EARCRX_CMDC_XACT_RD18 0x19a8
|
||||||
|
#define EARCRX_CMDC_XACT_RD19 0x19ac
|
||||||
|
#define EARCRX_CMDC_XACT_RD20 0x19b0
|
||||||
|
#define EARCRX_CMDC_XACT_RD21 0x19b4
|
||||||
|
#define EARCRX_CMDC_XACT_RD22 0x19b8
|
||||||
|
#define EARCRX_CMDC_XACT_RD23 0x19bc
|
||||||
|
#define EARCRX_CMDC_XACT_RD24 0x19c0
|
||||||
|
#define EARCRX_CMDC_XACT_RD25 0x19c4
|
||||||
|
#define EARCRX_CMDC_XACT_RD26 0x19c8
|
||||||
|
#define EARCRX_CMDC_XACT_RD27 0x19cc
|
||||||
|
#define EARCRX_CMDC_XACT_RD28 0x19d0
|
||||||
|
#define EARCRX_CMDC_XACT_RD29 0x19d4
|
||||||
|
#define EARCRX_CMDC_XACT_RD30 0x19d8
|
||||||
|
#define EARCRX_CMDC_XACT_RD31 0x19dc
|
||||||
|
#define EARCRX_CMDC_XACT_RD32 0x19e0
|
||||||
|
#define EARCRX_CMDC_XACT_RD33 0x19e4
|
||||||
|
#define EARCRX_CMDC_XACT_RD34 0x19e8
|
||||||
|
#define EARCRX_CMDC_XACT_RD35 0x19ec
|
||||||
|
#define EARCRX_CMDC_XACT_RD36 0x19f0
|
||||||
|
#define EARCRX_CMDC_XACT_RD37 0x19f4
|
||||||
|
#define EARCRX_CMDC_XACT_RD38 0x19f8
|
||||||
|
#define EARCRX_CMDC_XACT_RD39 0x19fc
|
||||||
|
#define EARCRX_CMDC_XACT_RD40 0x1a00
|
||||||
|
#define EARCRX_CMDC_XACT_RD41 0x1a04
|
||||||
|
#define EARCRX_CMDC_XACT_RD42 0x1a08
|
||||||
|
#define EARCRX_CMDC_XACT_RD43 0x1a0c
|
||||||
|
#define EARCRX_CMDC_XACT_RD44 0x1a10
|
||||||
|
#define EARCRX_CMDC_XACT_RD45 0x1a14
|
||||||
|
#define EARCRX_CMDC_XACT_RD46 0x1a18
|
||||||
|
#define EARCRX_CMDC_XACT_RD47 0x1a1c
|
||||||
|
#define EARCRX_CMDC_XACT_RD48 0x1a20
|
||||||
|
#define EARCRX_CMDC_XACT_RD49 0x1a24
|
||||||
|
#define EARCRX_CMDC_XACT_RD50 0x1a28
|
||||||
|
#define EARCRX_CMDC_XACT_RD51 0x1a2c
|
||||||
|
#define EARCRX_CMDC_XACT_RD52 0x1a30
|
||||||
|
#define EARCRX_CMDC_XACT_RD53 0x1a34
|
||||||
|
#define EARCRX_CMDC_XACT_RD54 0x1a38
|
||||||
|
#define EARCRX_CMDC_XACT_RD55 0x1a3c
|
||||||
|
#define EARCRX_CMDC_XACT_RD56 0x1a40
|
||||||
|
#define EARCRX_CMDC_XACT_RD57 0x1a44
|
||||||
|
#define EARCRX_CMDC_XACT_RD58 0x1a48
|
||||||
|
#define EARCRX_CMDC_XACT_RD59 0x1a4c
|
||||||
|
#define EARCRX_CMDC_XACT_RD60 0x1a50
|
||||||
|
#define EARCRX_CMDC_XACT_RD61 0x1a54
|
||||||
|
#define EARCRX_CMDC_XACT_RD62 0x1a58
|
||||||
|
#define EARCRX_CMDC_XACT_RD63 0x1a5c
|
||||||
|
#define EARCRX_CMDC_XACT_RD64 0x1a60
|
||||||
|
#define EARCRX_CMDC_SYNC_CONFIG 0x1b00
|
||||||
|
/* eARC RX DMAC Registers */
|
||||||
|
#define EARCRX_DMAC_PHY_CONTROL 0x1c00
|
||||||
|
#define EARCRX_DMAC_CONFIG 0x1c08
|
||||||
|
#define EARCRX_DMAC_CONTROL0 0x1c0c
|
||||||
|
#define EARCRX_DMAC_AUDIO_EN BIT(1)
|
||||||
|
#define EARCRX_DMAC_EN BIT(0)
|
||||||
|
#define EARCRX_DMAC_CONTROL1 0x1c10
|
||||||
|
#define EARCRX_DMAC_STATUS 0x1c14
|
||||||
|
#define EARCRX_DMAC_CHSTATUS0 0x1c18
|
||||||
|
#define EARCRX_DMAC_CHSTATUS1 0x1c1c
|
||||||
|
#define EARCRX_DMAC_CHSTATUS2 0x1c20
|
||||||
|
#define EARCRX_DMAC_CHSTATUS3 0x1c24
|
||||||
|
#define EARCRX_DMAC_CHSTATUS4 0x1c28
|
||||||
|
#define EARCRX_DMAC_CHSTATUS5 0x1c2c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC0 0x1c30
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC1 0x1c34
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC2 0x1c38
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC3 0x1c3c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC4 0x1c40
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC5 0x1c44
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC6 0x1c48
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC7 0x1c4c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC8 0x1c50
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC9 0x1c54
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC10 0x1c58
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_AC11 0x1c5c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT0 0x1c60
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT1 0x1c64
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT2 0x1c68
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT3 0x1c6c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT4 0x1c70
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT5 0x1c74
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT6 0x1c78
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT7 0x1c7c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT8 0x1c80
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT9 0x1c84
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT10 0x1c88
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC1_PKT11 0x1c8c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT0 0x1c90
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT1 0x1c94
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT2 0x1c98
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT3 0x1c9c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT4 0x1ca0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT5 0x1ca4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT6 0x1ca8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT7 0x1cac
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT8 0x1cb0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT9 0x1cb4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT10 0x1cb8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_HDMI_ISRC2_PKT11 0x1cbc
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC0 0x1cc0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC1 0x1cc4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC2 0x1cc8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC3 0x1ccc
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC4 0x1cd0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC5 0x1cd4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC6 0x1cd8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC7 0x1cdc
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC8 0x1ce0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC9 0x1ce4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC10 0x1ce8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC11 0x1cec
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC12 0x1cf0
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC13 0x1cf4
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC14 0x1cf8
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC15 0x1cfc
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC16 0x1d00
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC17 0x1d04
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC18 0x1d08
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC19 0x1d0c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC20 0x1d10
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC21 0x1d14
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC22 0x1d18
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC23 0x1d1c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC24 0x1d20
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC25 0x1d24
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC26 0x1d28
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC27 0x1d2c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC28 0x1d30
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC29 0x1d34
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC30 0x1d38
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC31 0x1d3c
|
||||||
|
#define EARCRX_DMAC_USRDATA_MSG_GENERIC32 0x1d40
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER0 0x1d44
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER1 0x1d48
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER2 0x1d4c
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER3 0x1d50
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER4 0x1d54
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER5 0x1d58
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER6 0x1d5c
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER7 0x1d60
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER8 0x1d64
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER9 0x1d68
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER10 0x1d6c
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER11 0x1d70
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER12 0x1d74
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER13 0x1d78
|
||||||
|
#define EARCRX_DMAC_CHSTATUS_STREAMER14 0x1d7c
|
||||||
|
#define EARCRX_DMAC_USRDATA_STREAMER0 0x1d80
|
||||||
|
/* Main Unit Interrupt Registers */
|
||||||
|
#define MAIN_INTVEC_INDEX 0x3000
|
||||||
|
#define MAINUNIT_0_INT_STATUS 0x3010
|
||||||
|
#define MAINUNIT_0_INT_MASK_N 0x3014
|
||||||
|
#define MAINUNIT_0_INT_CLEAR 0x3018
|
||||||
|
#define MAINUNIT_0_INT_FORCE 0x301c
|
||||||
|
#define MAINUNIT_1_INT_STATUS 0x3020
|
||||||
|
#define FLT_EXIT_TO_LTSL_IRQ BIT(22)
|
||||||
|
#define FLT_EXIT_TO_LTS4_IRQ BIT(21)
|
||||||
|
#define FLT_EXIT_TO_LTSP_IRQ BIT(20)
|
||||||
|
#define SCDC_NACK_RCVD_IRQ BIT(12)
|
||||||
|
#define SCDC_RR_REPLY_STOP_IRQ BIT(11)
|
||||||
|
#define SCDC_UPD_FLAGS_CLR_IRQ BIT(10)
|
||||||
|
#define SCDC_UPD_FLAGS_CHG_IRQ BIT(9)
|
||||||
|
#define SCDC_UPD_FLAGS_RD_IRQ BIT(8)
|
||||||
|
#define I2CM_NACK_RCVD_IRQ BIT(2)
|
||||||
|
#define I2CM_READ_REQUEST_IRQ BIT(1)
|
||||||
|
#define I2CM_OP_DONE_IRQ BIT(0)
|
||||||
|
#define MAINUNIT_1_INT_MASK_N 0x3024
|
||||||
|
#define I2CM_NACK_RCVD_MASK_N BIT(2)
|
||||||
|
#define I2CM_READ_REQUEST_MASK_N BIT(1)
|
||||||
|
#define I2CM_OP_DONE_MASK_N BIT(0)
|
||||||
|
#define MAINUNIT_1_INT_CLEAR 0x3028
|
||||||
|
#define I2CM_NACK_RCVD_CLEAR BIT(2)
|
||||||
|
#define I2CM_READ_REQUEST_CLEAR BIT(1)
|
||||||
|
#define I2CM_OP_DONE_CLEAR BIT(0)
|
||||||
|
#define MAINUNIT_1_INT_FORCE 0x302c
|
||||||
|
/* AVPUNIT Interrupt Registers */
|
||||||
|
#define AVP_INTVEC_INDEX 0x3800
|
||||||
|
#define AVP_0_INT_STATUS 0x3810
|
||||||
|
#define AVP_0_INT_MASK_N 0x3814
|
||||||
|
#define AVP_0_INT_CLEAR 0x3818
|
||||||
|
#define AVP_0_INT_FORCE 0x381c
|
||||||
|
#define AVP_1_INT_STATUS 0x3820
|
||||||
|
#define AVP_1_INT_MASK_N 0x3824
|
||||||
|
#define HDCP14_AUTH_CHG_MASK_N BIT(6)
|
||||||
|
#define AVP_1_INT_CLEAR 0x3828
|
||||||
|
#define AVP_1_INT_FORCE 0x382c
|
||||||
|
#define AVP_2_INT_STATUS 0x3830
|
||||||
|
#define AVP_2_INT_MASK_N 0x3834
|
||||||
|
#define AVP_2_INT_CLEAR 0x3838
|
||||||
|
#define AVP_2_INT_FORCE 0x383c
|
||||||
|
#define AVP_3_INT_STATUS 0x3840
|
||||||
|
#define AVP_3_INT_MASK_N 0x3844
|
||||||
|
#define AVP_3_INT_CLEAR 0x3848
|
||||||
|
#define AVP_3_INT_FORCE 0x384c
|
||||||
|
#define AVP_4_INT_STATUS 0x3850
|
||||||
|
#define AVP_4_INT_MASK_N 0x3854
|
||||||
|
#define AVP_4_INT_CLEAR 0x3858
|
||||||
|
#define AVP_4_INT_FORCE 0x385c
|
||||||
|
#define AVP_5_INT_STATUS 0x3860
|
||||||
|
#define AVP_5_INT_MASK_N 0x3864
|
||||||
|
#define AVP_5_INT_CLEAR 0x3868
|
||||||
|
#define AVP_5_INT_FORCE 0x386c
|
||||||
|
#define AVP_6_INT_STATUS 0x3870
|
||||||
|
#define AVP_6_INT_MASK_N 0x3874
|
||||||
|
#define AVP_6_INT_CLEAR 0x3878
|
||||||
|
#define AVP_6_INT_FORCE 0x387c
|
||||||
|
/* CEC Interrupt Registers */
|
||||||
|
#define CEC_INT_STATUS 0x4000
|
||||||
|
#define CEC_INT_MASK_N 0x4004
|
||||||
|
#define CEC_INT_CLEAR 0x4008
|
||||||
|
#define CEC_INT_FORCE 0x400c
|
||||||
|
/* eARC RX Interrupt Registers */
|
||||||
|
#define EARCRX_INTVEC_INDEX 0x4800
|
||||||
|
#define EARCRX_0_INT_STATUS 0x4810
|
||||||
|
#define EARCRX_CMDC_DISCOVERY_TIMEOUT_IRQ BIT(9)
|
||||||
|
#define EARCRX_CMDC_DISCOVERY_DONE_IRQ BIT(8)
|
||||||
|
#define EARCRX_0_INT_MASK_N 0x4814
|
||||||
|
#define EARCRX_0_INT_CLEAR 0x4818
|
||||||
|
#define EARCRX_0_INT_FORCE 0x481c
|
||||||
|
#define EARCRX_1_INT_STATUS 0x4820
|
||||||
|
#define EARCRX_1_INT_MASK_N 0x4824
|
||||||
|
#define EARCRX_1_INT_CLEAR 0x4828
|
||||||
|
#define EARCRX_1_INT_FORCE 0x482c
|
||||||
|
|
||||||
|
#endif /* __DW_HDMI_QP_H__ */
|
||||||
@ -0,0 +1,628 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
|
||||||
|
* Copyright (c) 2024 Collabora Ltd.
|
||||||
|
*
|
||||||
|
* Author: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
* Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/phy/phy.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
|
#include <drm/bridge/dw_hdmi_qp.h>
|
||||||
|
#include <drm/display/drm_hdmi_helper.h>
|
||||||
|
#include <drm/drm_bridge_connector.h>
|
||||||
|
#include <drm/drm_of.h>
|
||||||
|
#include <drm/drm_probe_helper.h>
|
||||||
|
#include <drm/drm_simple_kms_helper.h>
|
||||||
|
|
||||||
|
#include "rockchip_drm_drv.h"
|
||||||
|
|
||||||
|
#define RK3576_IOC_MISC_CON0 0xa400
|
||||||
|
#define RK3576_HDMI_HPD_INT_MSK BIT(2)
|
||||||
|
#define RK3576_HDMI_HPD_INT_CLR BIT(1)
|
||||||
|
|
||||||
|
#define RK3576_IOC_HDMI_HPD_STATUS 0xa440
|
||||||
|
#define RK3576_HDMI_LEVEL_INT BIT(3)
|
||||||
|
|
||||||
|
#define RK3576_VO0_GRF_SOC_CON1 0x0004
|
||||||
|
#define RK3576_HDMI_FRL_MOD BIT(0)
|
||||||
|
#define RK3576_HDMI_HDCP14_MEM_EN BIT(15)
|
||||||
|
|
||||||
|
#define RK3576_VO0_GRF_SOC_CON8 0x0020
|
||||||
|
#define RK3576_COLOR_FORMAT_MASK (0xf << 4)
|
||||||
|
#define RK3576_COLOR_DEPTH_MASK (0xf << 8)
|
||||||
|
#define RK3576_RGB (0 << 4)
|
||||||
|
#define RK3576_YUV422 (0x1 << 4)
|
||||||
|
#define RK3576_YUV444 (0x2 << 4)
|
||||||
|
#define RK3576_YUV420 (0x3 << 4)
|
||||||
|
#define RK3576_8BPC (0x0 << 8)
|
||||||
|
#define RK3576_10BPC (0x6 << 8)
|
||||||
|
#define RK3576_CECIN_MASK BIT(3)
|
||||||
|
|
||||||
|
#define RK3576_VO0_GRF_SOC_CON12 0x0030
|
||||||
|
#define RK3576_GRF_OSDA_DLYN (0xf << 12)
|
||||||
|
#define RK3576_GRF_OSDA_DIV (0x7f << 1)
|
||||||
|
#define RK3576_GRF_OSDA_DLY_EN BIT(0)
|
||||||
|
|
||||||
|
#define RK3576_VO0_GRF_SOC_CON14 0x0038
|
||||||
|
#define RK3576_I2S_SEL_MASK BIT(0)
|
||||||
|
#define RK3576_SPDIF_SEL_MASK BIT(1)
|
||||||
|
#define HDCP0_P1_GPIO_IN BIT(2)
|
||||||
|
#define RK3576_SCLIN_MASK BIT(4)
|
||||||
|
#define RK3576_SDAIN_MASK BIT(5)
|
||||||
|
#define RK3576_HDMI_GRANT_SEL BIT(6)
|
||||||
|
|
||||||
|
#define RK3588_GRF_SOC_CON2 0x0308
|
||||||
|
#define RK3588_HDMI0_HPD_INT_MSK BIT(13)
|
||||||
|
#define RK3588_HDMI0_HPD_INT_CLR BIT(12)
|
||||||
|
#define RK3588_HDMI1_HPD_INT_MSK BIT(15)
|
||||||
|
#define RK3588_HDMI1_HPD_INT_CLR BIT(14)
|
||||||
|
#define RK3588_GRF_SOC_CON7 0x031c
|
||||||
|
#define RK3588_SET_HPD_PATH_MASK GENMASK(13, 12)
|
||||||
|
#define RK3588_GRF_SOC_STATUS1 0x0384
|
||||||
|
#define RK3588_HDMI0_LEVEL_INT BIT(16)
|
||||||
|
#define RK3588_HDMI1_LEVEL_INT BIT(24)
|
||||||
|
#define RK3588_GRF_VO1_CON3 0x000c
|
||||||
|
#define RK3588_GRF_VO1_CON6 0x0018
|
||||||
|
#define RK3588_SCLIN_MASK BIT(9)
|
||||||
|
#define RK3588_SDAIN_MASK BIT(10)
|
||||||
|
#define RK3588_MODE_MASK BIT(11)
|
||||||
|
#define RK3588_I2S_SEL_MASK BIT(13)
|
||||||
|
#define RK3588_GRF_VO1_CON9 0x0024
|
||||||
|
#define RK3588_HDMI0_GRANT_SEL BIT(10)
|
||||||
|
#define RK3588_HDMI1_GRANT_SEL BIT(12)
|
||||||
|
|
||||||
|
#define HIWORD_UPDATE(val, mask) ((val) | (mask) << 16)
|
||||||
|
#define HOTPLUG_DEBOUNCE_MS 150
|
||||||
|
#define MAX_HDMI_PORT_NUM 2
|
||||||
|
|
||||||
|
struct rockchip_hdmi_qp {
|
||||||
|
struct device *dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct regmap *vo_regmap;
|
||||||
|
struct rockchip_encoder encoder;
|
||||||
|
struct dw_hdmi_qp *hdmi;
|
||||||
|
struct phy *phy;
|
||||||
|
struct gpio_desc *enable_gpio;
|
||||||
|
struct delayed_work hpd_work;
|
||||||
|
int port_id;
|
||||||
|
const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rockchip_hdmi_qp_ctrl_ops {
|
||||||
|
void (*io_init)(struct rockchip_hdmi_qp *hdmi);
|
||||||
|
irqreturn_t (*irq_callback)(int irq, void *dev_id);
|
||||||
|
irqreturn_t (*hardirq_callback)(int irq, void *dev_id);
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
|
||||||
|
{
|
||||||
|
struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
|
||||||
|
|
||||||
|
return container_of(rkencoder, struct rockchip_hdmi_qp, encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
|
||||||
|
struct drm_crtc *crtc = encoder->crtc;
|
||||||
|
unsigned long long rate;
|
||||||
|
|
||||||
|
/* Unconditionally switch to TMDS as FRL is not yet supported */
|
||||||
|
gpiod_set_value(hdmi->enable_gpio, 1);
|
||||||
|
|
||||||
|
if (crtc && crtc->state) {
|
||||||
|
rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode,
|
||||||
|
8, HDMI_COLORSPACE_RGB);
|
||||||
|
/*
|
||||||
|
* FIXME: Temporary workaround to pass pixel clock rate
|
||||||
|
* to the PHY driver until phy_configure_opts_hdmi
|
||||||
|
* becomes available in the PHY API. See also the related
|
||||||
|
* comment in rk_hdptx_phy_power_on() from
|
||||||
|
* drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
*/
|
||||||
|
phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
|
||||||
|
|
||||||
|
s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
|
||||||
|
s->output_type = DRM_MODE_CONNECTOR_HDMIA;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = {
|
||||||
|
.enable = dw_hdmi_qp_rockchip_encoder_enable,
|
||||||
|
.atomic_check = dw_hdmi_qp_rockchip_encoder_atomic_check,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
|
||||||
|
return phy_power_on(hdmi->phy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
|
||||||
|
phy_power_off(hdmi->phy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
|
||||||
|
val &= hdmi->port_id ? RK3588_HDMI1_LEVEL_INT : RK3588_HDMI0_LEVEL_INT;
|
||||||
|
|
||||||
|
return val ? connector_status_connected : connector_status_disconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
|
||||||
|
RK3588_HDMI1_HPD_INT_CLR | RK3588_HDMI1_HPD_INT_MSK);
|
||||||
|
else
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
|
||||||
|
RK3588_HDMI0_HPD_INT_CLR | RK3588_HDMI0_HPD_INT_MSK);
|
||||||
|
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
|
||||||
|
.init = dw_hdmi_qp_rk3588_phy_init,
|
||||||
|
.disable = dw_hdmi_qp_rk3588_phy_disable,
|
||||||
|
.read_hpd = dw_hdmi_qp_rk3588_read_hpd,
|
||||||
|
.setup_hpd = dw_hdmi_qp_rk3588_setup_hpd,
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum drm_connector_status
|
||||||
|
dw_hdmi_qp_rk3576_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &val);
|
||||||
|
|
||||||
|
return val & RK3576_HDMI_LEVEL_INT ?
|
||||||
|
connector_status_connected : connector_status_disconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3576_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR,
|
||||||
|
RK3576_HDMI_HPD_INT_CLR | RK3576_HDMI_HPD_INT_MSK);
|
||||||
|
|
||||||
|
regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
|
||||||
|
regmap_write(hdmi->regmap, 0xa404, 0xffff0102);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dw_hdmi_qp_phy_ops rk3576_hdmi_phy_ops = {
|
||||||
|
.init = dw_hdmi_qp_rk3588_phy_init,
|
||||||
|
.disable = dw_hdmi_qp_rk3588_phy_disable,
|
||||||
|
.read_hpd = dw_hdmi_qp_rk3576_read_hpd,
|
||||||
|
.setup_hpd = dw_hdmi_qp_rk3576_setup_hpd,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = container_of(work,
|
||||||
|
struct rockchip_hdmi_qp,
|
||||||
|
hpd_work.work);
|
||||||
|
struct drm_device *drm = hdmi->encoder.encoder.dev;
|
||||||
|
bool changed;
|
||||||
|
|
||||||
|
if (drm) {
|
||||||
|
changed = drm_helper_hpd_irq_event(drm);
|
||||||
|
if (changed)
|
||||||
|
dev_dbg(hdmi->dev, "connector status changed\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_id;
|
||||||
|
u32 intr_stat, val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat);
|
||||||
|
if (intr_stat) {
|
||||||
|
val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_MSK, RK3576_HDMI_HPD_INT_MSK);
|
||||||
|
|
||||||
|
regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
|
||||||
|
return IRQ_WAKE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_rk3576_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_id;
|
||||||
|
u32 intr_stat, val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat);
|
||||||
|
|
||||||
|
if (!intr_stat)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(RK3576_HDMI_HPD_INT_CLR, RK3576_HDMI_HPD_INT_CLR);
|
||||||
|
regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
|
||||||
|
mod_delayed_work(system_wq, &hdmi->hpd_work,
|
||||||
|
msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK);
|
||||||
|
regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_id;
|
||||||
|
u32 intr_stat, val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
|
||||||
|
|
||||||
|
if (intr_stat) {
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK,
|
||||||
|
RK3588_HDMI1_HPD_INT_MSK);
|
||||||
|
else
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK,
|
||||||
|
RK3588_HDMI0_HPD_INT_MSK);
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
|
||||||
|
return IRQ_WAKE_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_id;
|
||||||
|
u32 intr_stat, val;
|
||||||
|
|
||||||
|
regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
|
||||||
|
if (!intr_stat)
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_CLR,
|
||||||
|
RK3588_HDMI1_HPD_INT_CLR);
|
||||||
|
else
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_CLR,
|
||||||
|
RK3588_HDMI0_HPD_INT_CLR);
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
|
||||||
|
|
||||||
|
mod_delayed_work(system_wq, &hdmi->hpd_work,
|
||||||
|
msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
|
||||||
|
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val |= HIWORD_UPDATE(0, RK3588_HDMI1_HPD_INT_MSK);
|
||||||
|
else
|
||||||
|
val |= HIWORD_UPDATE(0, RK3588_HDMI0_HPD_INT_MSK);
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
|
||||||
|
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3576_io_init(struct rockchip_hdmi_qp *hdmi)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(RK3576_SCLIN_MASK, RK3576_SCLIN_MASK) |
|
||||||
|
HIWORD_UPDATE(RK3576_SDAIN_MASK, RK3576_SDAIN_MASK) |
|
||||||
|
HIWORD_UPDATE(RK3576_HDMI_GRANT_SEL, RK3576_HDMI_GRANT_SEL) |
|
||||||
|
HIWORD_UPDATE(RK3576_I2S_SEL_MASK, RK3576_I2S_SEL_MASK);
|
||||||
|
|
||||||
|
regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON14, val);
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(0, RK3576_HDMI_HPD_INT_MSK);
|
||||||
|
regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(RK3588_SCLIN_MASK, RK3588_SCLIN_MASK) |
|
||||||
|
HIWORD_UPDATE(RK3588_SDAIN_MASK, RK3588_SDAIN_MASK) |
|
||||||
|
HIWORD_UPDATE(RK3588_MODE_MASK, RK3588_MODE_MASK) |
|
||||||
|
HIWORD_UPDATE(RK3588_I2S_SEL_MASK, RK3588_I2S_SEL_MASK);
|
||||||
|
regmap_write(hdmi->vo_regmap,
|
||||||
|
hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
|
||||||
|
val);
|
||||||
|
|
||||||
|
val = HIWORD_UPDATE(RK3588_SET_HPD_PATH_MASK, RK3588_SET_HPD_PATH_MASK);
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
|
||||||
|
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI1_GRANT_SEL, RK3588_HDMI1_GRANT_SEL);
|
||||||
|
else
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI0_GRANT_SEL, RK3588_HDMI0_GRANT_SEL);
|
||||||
|
regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
|
||||||
|
|
||||||
|
if (hdmi->port_id)
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI1_HPD_INT_MSK, RK3588_HDMI1_HPD_INT_MSK);
|
||||||
|
else
|
||||||
|
val = HIWORD_UPDATE(RK3588_HDMI0_HPD_INT_MSK, RK3588_HDMI0_HPD_INT_MSK);
|
||||||
|
regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = {
|
||||||
|
.io_init = dw_hdmi_qp_rk3576_io_init,
|
||||||
|
.irq_callback = dw_hdmi_qp_rk3576_irq,
|
||||||
|
.hardirq_callback = dw_hdmi_qp_rk3576_hardirq,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = {
|
||||||
|
.io_init = dw_hdmi_qp_rk3588_io_init,
|
||||||
|
.irq_callback = dw_hdmi_qp_rk3588_irq,
|
||||||
|
.hardirq_callback = dw_hdmi_qp_rk3588_hardirq,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rockchip_hdmi_qp_cfg {
|
||||||
|
unsigned int num_ports;
|
||||||
|
unsigned int port_ids[MAX_HDMI_PORT_NUM];
|
||||||
|
const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
|
||||||
|
const struct dw_hdmi_qp_phy_ops *phy_ops;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_hdmi_qp_cfg rk3576_hdmi_cfg = {
|
||||||
|
.num_ports = 1,
|
||||||
|
.port_ids = {
|
||||||
|
0x27da0000,
|
||||||
|
},
|
||||||
|
.ctrl_ops = &rk3576_hdmi_ctrl_ops,
|
||||||
|
.phy_ops = &rk3576_hdmi_phy_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = {
|
||||||
|
.num_ports = 2,
|
||||||
|
.port_ids = {
|
||||||
|
0xfde80000,
|
||||||
|
0xfdea0000,
|
||||||
|
},
|
||||||
|
.ctrl_ops = &rk3588_hdmi_ctrl_ops,
|
||||||
|
.phy_ops = &rk3588_hdmi_phy_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rk3576-dw-hdmi-qp",
|
||||||
|
.data = &rk3576_hdmi_cfg
|
||||||
|
}, {
|
||||||
|
.compatible = "rockchip,rk3588-dw-hdmi-qp",
|
||||||
|
.data = &rk3588_hdmi_cfg
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
|
const struct rockchip_hdmi_qp_cfg *cfg;
|
||||||
|
struct dw_hdmi_qp_plat_data plat_data;
|
||||||
|
struct drm_device *drm = data;
|
||||||
|
struct drm_connector *connector;
|
||||||
|
struct drm_encoder *encoder;
|
||||||
|
struct rockchip_hdmi_qp *hdmi;
|
||||||
|
struct resource *res;
|
||||||
|
struct clk_bulk_data *clks;
|
||||||
|
int ret, irq, i;
|
||||||
|
|
||||||
|
if (!pdev->dev.of_node)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
|
||||||
|
if (!hdmi)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!res)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
cfg = of_device_get_match_data(dev);
|
||||||
|
if (!cfg)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!cfg->ctrl_ops || !cfg->ctrl_ops->io_init ||
|
||||||
|
!cfg->ctrl_ops->irq_callback || !cfg->ctrl_ops->hardirq_callback) {
|
||||||
|
dev_err(dev, "Missing platform ctrl ops\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->ctrl_ops = cfg->ctrl_ops;
|
||||||
|
hdmi->dev = &pdev->dev;
|
||||||
|
hdmi->port_id = -ENODEV;
|
||||||
|
|
||||||
|
/* Identify port ID by matching base IO address */
|
||||||
|
for (i = 0; i < cfg->num_ports; i++) {
|
||||||
|
if (res->start == cfg->port_ids[i]) {
|
||||||
|
hdmi->port_id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hdmi->port_id < 0) {
|
||||||
|
dev_err(hdmi->dev, "Failed to match HDMI port ID\n");
|
||||||
|
return hdmi->port_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
plat_data.phy_ops = cfg->phy_ops;
|
||||||
|
plat_data.phy_data = hdmi;
|
||||||
|
|
||||||
|
encoder = &hdmi->encoder.encoder;
|
||||||
|
encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
|
||||||
|
|
||||||
|
rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder,
|
||||||
|
dev->of_node, 0, 0);
|
||||||
|
/*
|
||||||
|
* If we failed to find the CRTC(s) which this encoder is
|
||||||
|
* supposed to be connected to, it's because the CRTC has
|
||||||
|
* not been registered yet. Defer probing, and hope that
|
||||||
|
* the required CRTC is added later.
|
||||||
|
*/
|
||||||
|
if (encoder->possible_crtcs == 0)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
|
hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||||
|
"rockchip,grf");
|
||||||
|
if (IS_ERR(hdmi->regmap)) {
|
||||||
|
dev_err(hdmi->dev, "Unable to get rockchip,grf\n");
|
||||||
|
return PTR_ERR(hdmi->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||||
|
"rockchip,vo-grf");
|
||||||
|
if (IS_ERR(hdmi->vo_regmap)) {
|
||||||
|
dev_err(hdmi->dev, "Unable to get rockchip,vo-grf\n");
|
||||||
|
return PTR_ERR(hdmi->vo_regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_clk_bulk_get_all_enabled(hdmi->dev, &clks);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(hdmi->dev, "Failed to get clocks: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->enable_gpio = devm_gpiod_get_optional(hdmi->dev, "enable",
|
||||||
|
GPIOD_OUT_HIGH);
|
||||||
|
if (IS_ERR(hdmi->enable_gpio)) {
|
||||||
|
ret = PTR_ERR(hdmi->enable_gpio);
|
||||||
|
dev_err(hdmi->dev, "Failed to request enable GPIO: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
hdmi->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
|
||||||
|
if (IS_ERR(hdmi->phy)) {
|
||||||
|
ret = PTR_ERR(hdmi->phy);
|
||||||
|
if (ret != -EPROBE_DEFER)
|
||||||
|
dev_err(hdmi->dev, "failed to get phy: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg->ctrl_ops->io_init(hdmi);
|
||||||
|
|
||||||
|
INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work);
|
||||||
|
|
||||||
|
plat_data.main_irq = platform_get_irq_byname(pdev, "main");
|
||||||
|
if (plat_data.main_irq < 0)
|
||||||
|
return plat_data.main_irq;
|
||||||
|
|
||||||
|
irq = platform_get_irq_byname(pdev, "hpd");
|
||||||
|
if (irq < 0)
|
||||||
|
return irq;
|
||||||
|
|
||||||
|
ret = devm_request_threaded_irq(hdmi->dev, irq,
|
||||||
|
cfg->ctrl_ops->hardirq_callback,
|
||||||
|
cfg->ctrl_ops->irq_callback,
|
||||||
|
IRQF_SHARED, "dw-hdmi-qp-hpd",
|
||||||
|
hdmi);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs);
|
||||||
|
drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, hdmi);
|
||||||
|
|
||||||
|
hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data);
|
||||||
|
if (IS_ERR(hdmi->hdmi)) {
|
||||||
|
ret = PTR_ERR(hdmi->hdmi);
|
||||||
|
drm_encoder_cleanup(encoder);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
connector = drm_bridge_connector_init(drm, encoder);
|
||||||
|
if (IS_ERR(connector)) {
|
||||||
|
ret = PTR_ERR(connector);
|
||||||
|
dev_err(hdmi->dev, "failed to init bridge connector: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return drm_connector_attach_encoder(connector, encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rockchip_unbind(struct device *dev,
|
||||||
|
struct device *master,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&hdmi->hpd_work);
|
||||||
|
|
||||||
|
drm_encoder_cleanup(&hdmi->encoder.encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct component_ops dw_hdmi_qp_rockchip_ops = {
|
||||||
|
.bind = dw_hdmi_qp_rockchip_bind,
|
||||||
|
.unbind = dw_hdmi_qp_rockchip_unbind,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
hdmi->ctrl_ops->io_init(hdmi);
|
||||||
|
|
||||||
|
dw_hdmi_qp_resume(dev, hdmi->hdmi);
|
||||||
|
|
||||||
|
if (hdmi->encoder.encoder.dev)
|
||||||
|
drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
|
||||||
|
SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
|
||||||
|
.probe = dw_hdmi_qp_rockchip_probe,
|
||||||
|
.remove = dw_hdmi_qp_rockchip_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "dwhdmiqp-rockchip",
|
||||||
|
.pm = &dw_hdmi_qp_rockchip_pm,
|
||||||
|
.of_match_table = dw_hdmi_qp_rockchip_dt_ids,
|
||||||
|
},
|
||||||
|
};
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,867 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
/*
|
||||||
|
* Copyright (C) Rockchip Electronics Co., Ltd.
|
||||||
|
* Author:Mark Yao <mark.yao@rock-chips.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ROCKCHIP_DRM_VOP2_H
|
||||||
|
#define _ROCKCHIP_DRM_VOP2_H
|
||||||
|
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <drm/drm_modes.h>
|
||||||
|
#include <dt-bindings/soc/rockchip,vop2.h>
|
||||||
|
#include "rockchip_drm_drv.h"
|
||||||
|
#include "rockchip_drm_vop.h"
|
||||||
|
|
||||||
|
#define VOP2_VERSION(major, minor, build) ((major) << 24 | (minor) << 16 | (build))
|
||||||
|
|
||||||
|
/* The VOP version of new SoC is bigger than the old */
|
||||||
|
#define VOP_VERSION_RK3568 VOP2_VERSION(0x40, 0x15, 0x8023)
|
||||||
|
#define VOP_VERSION_RK3588 VOP2_VERSION(0x40, 0x17, 0x6786)
|
||||||
|
#define VOP_VERSION_RK3528 VOP2_VERSION(0x50, 0x17, 0x1263)
|
||||||
|
#define VOP_VERSION_RK3562 VOP2_VERSION(0x50, 0x17, 0x4350)
|
||||||
|
#define VOP_VERSION_RK3576 VOP2_VERSION(0x50, 0x19, 0x9765)
|
||||||
|
|
||||||
|
#define VOP2_VP_FEATURE_OUTPUT_10BIT BIT(0)
|
||||||
|
|
||||||
|
#define VOP2_FEATURE_HAS_SYS_GRF BIT(0)
|
||||||
|
#define VOP2_FEATURE_HAS_VO0_GRF BIT(1)
|
||||||
|
#define VOP2_FEATURE_HAS_VO1_GRF BIT(2)
|
||||||
|
#define VOP2_FEATURE_HAS_VOP_GRF BIT(3)
|
||||||
|
#define VOP2_FEATURE_HAS_SYS_PMU BIT(4)
|
||||||
|
|
||||||
|
#define WIN_FEATURE_AFBDC BIT(0)
|
||||||
|
#define WIN_FEATURE_CLUSTER BIT(1)
|
||||||
|
|
||||||
|
#define HIWORD_UPDATE(v, h, l) ((GENMASK(h, l) << 16) | ((v) << (l)))
|
||||||
|
/*
|
||||||
|
* the delay number of a window in different mode.
|
||||||
|
*/
|
||||||
|
enum win_dly_mode {
|
||||||
|
VOP2_DLY_MODE_DEFAULT, /**< default mode */
|
||||||
|
VOP2_DLY_MODE_HISO_S, /** HDR in SDR out mode, as a SDR window */
|
||||||
|
VOP2_DLY_MODE_HIHO_H, /** HDR in HDR out mode, as a HDR window */
|
||||||
|
VOP2_DLY_MODE_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum vop2_dly_module {
|
||||||
|
VOP2_DLY_WIN, /** Win delay cycle for this VP */
|
||||||
|
VOP2_DLY_LAYER_MIX, /** Layer Mix delay cycle for this VP */
|
||||||
|
VOP2_DLY_HDR_MIX, /** HDR delay cycle for this VP */
|
||||||
|
VOP2_DLY_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum vop2_scale_up_mode {
|
||||||
|
VOP2_SCALE_UP_NRST_NBOR,
|
||||||
|
VOP2_SCALE_UP_BIL,
|
||||||
|
VOP2_SCALE_UP_BIC,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum vop2_scale_down_mode {
|
||||||
|
VOP2_SCALE_DOWN_NRST_NBOR,
|
||||||
|
VOP2_SCALE_DOWN_BIL,
|
||||||
|
VOP2_SCALE_DOWN_AVG,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vop2 internal power domain id,
|
||||||
|
* should be all none zero, 0 will be treat as invalid;
|
||||||
|
*/
|
||||||
|
#define VOP2_PD_CLUSTER0 BIT(0)
|
||||||
|
#define VOP2_PD_CLUSTER1 BIT(1)
|
||||||
|
#define VOP2_PD_CLUSTER2 BIT(2)
|
||||||
|
#define VOP2_PD_CLUSTER3 BIT(3)
|
||||||
|
#define VOP2_PD_DSC_8K BIT(5)
|
||||||
|
#define VOP2_PD_DSC_4K BIT(6)
|
||||||
|
#define VOP2_PD_ESMART BIT(7)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_hdmi(x) ((x) == ROCKCHIP_VOP2_EP_HDMI0 || \
|
||||||
|
(x) == ROCKCHIP_VOP2_EP_HDMI1)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_dp(x) ((x) == ROCKCHIP_VOP2_EP_DP0 || \
|
||||||
|
(x) == ROCKCHIP_VOP2_EP_DP1)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_edp(x) ((x) == ROCKCHIP_VOP2_EP_EDP0 || \
|
||||||
|
(x) == ROCKCHIP_VOP2_EP_EDP1)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_mipi(x) ((x) == ROCKCHIP_VOP2_EP_MIPI0 || \
|
||||||
|
(x) == ROCKCHIP_VOP2_EP_MIPI1)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_lvds(x) ((x) == ROCKCHIP_VOP2_EP_LVDS0 || \
|
||||||
|
(x) == ROCKCHIP_VOP2_EP_LVDS1)
|
||||||
|
|
||||||
|
#define vop2_output_if_is_dpi(x) ((x) == ROCKCHIP_VOP2_EP_RGB0)
|
||||||
|
|
||||||
|
enum vop2_win_regs {
|
||||||
|
VOP2_WIN_ENABLE,
|
||||||
|
VOP2_WIN_FORMAT,
|
||||||
|
VOP2_WIN_CSC_MODE,
|
||||||
|
VOP2_WIN_XMIRROR,
|
||||||
|
VOP2_WIN_YMIRROR,
|
||||||
|
VOP2_WIN_RB_SWAP,
|
||||||
|
VOP2_WIN_UV_SWAP,
|
||||||
|
VOP2_WIN_ACT_INFO,
|
||||||
|
VOP2_WIN_DSP_INFO,
|
||||||
|
VOP2_WIN_DSP_ST,
|
||||||
|
VOP2_WIN_YRGB_MST,
|
||||||
|
VOP2_WIN_UV_MST,
|
||||||
|
VOP2_WIN_YRGB_VIR,
|
||||||
|
VOP2_WIN_UV_VIR,
|
||||||
|
VOP2_WIN_YUV_CLIP,
|
||||||
|
VOP2_WIN_Y2R_EN,
|
||||||
|
VOP2_WIN_R2Y_EN,
|
||||||
|
VOP2_WIN_COLOR_KEY,
|
||||||
|
VOP2_WIN_COLOR_KEY_EN,
|
||||||
|
VOP2_WIN_DITHER_UP,
|
||||||
|
VOP2_WIN_AXI_BUS_ID,
|
||||||
|
VOP2_WIN_AXI_YRGB_R_ID,
|
||||||
|
VOP2_WIN_AXI_UV_R_ID,
|
||||||
|
|
||||||
|
/* scale regs */
|
||||||
|
VOP2_WIN_SCALE_YRGB_X,
|
||||||
|
VOP2_WIN_SCALE_YRGB_Y,
|
||||||
|
VOP2_WIN_SCALE_CBCR_X,
|
||||||
|
VOP2_WIN_SCALE_CBCR_Y,
|
||||||
|
VOP2_WIN_YRGB_HOR_SCL_MODE,
|
||||||
|
VOP2_WIN_YRGB_HSCL_FILTER_MODE,
|
||||||
|
VOP2_WIN_YRGB_VER_SCL_MODE,
|
||||||
|
VOP2_WIN_YRGB_VSCL_FILTER_MODE,
|
||||||
|
VOP2_WIN_CBCR_VER_SCL_MODE,
|
||||||
|
VOP2_WIN_CBCR_HSCL_FILTER_MODE,
|
||||||
|
VOP2_WIN_CBCR_HOR_SCL_MODE,
|
||||||
|
VOP2_WIN_CBCR_VSCL_FILTER_MODE,
|
||||||
|
VOP2_WIN_VSD_CBCR_GT2,
|
||||||
|
VOP2_WIN_VSD_CBCR_GT4,
|
||||||
|
VOP2_WIN_VSD_YRGB_GT2,
|
||||||
|
VOP2_WIN_VSD_YRGB_GT4,
|
||||||
|
VOP2_WIN_BIC_COE_SEL,
|
||||||
|
|
||||||
|
/* cluster regs */
|
||||||
|
VOP2_WIN_CLUSTER_ENABLE,
|
||||||
|
VOP2_WIN_AFBC_ENABLE,
|
||||||
|
VOP2_WIN_CLUSTER_LB_MODE,
|
||||||
|
|
||||||
|
/* afbc regs */
|
||||||
|
VOP2_WIN_AFBC_FORMAT,
|
||||||
|
VOP2_WIN_AFBC_RB_SWAP,
|
||||||
|
VOP2_WIN_AFBC_UV_SWAP,
|
||||||
|
VOP2_WIN_AFBC_AUTO_GATING_EN,
|
||||||
|
VOP2_WIN_AFBC_BLOCK_SPLIT_EN,
|
||||||
|
VOP2_WIN_AFBC_PLD_OFFSET_EN,
|
||||||
|
VOP2_WIN_AFBC_PIC_VIR_WIDTH,
|
||||||
|
VOP2_WIN_AFBC_TILE_NUM,
|
||||||
|
VOP2_WIN_AFBC_PIC_OFFSET,
|
||||||
|
VOP2_WIN_AFBC_PIC_SIZE,
|
||||||
|
VOP2_WIN_AFBC_DSP_OFFSET,
|
||||||
|
VOP2_WIN_AFBC_PLD_OFFSET,
|
||||||
|
VOP2_WIN_TRANSFORM_OFFSET,
|
||||||
|
VOP2_WIN_AFBC_HDR_PTR,
|
||||||
|
VOP2_WIN_AFBC_HALF_BLOCK_EN,
|
||||||
|
VOP2_WIN_AFBC_ROTATE_270,
|
||||||
|
VOP2_WIN_AFBC_ROTATE_90,
|
||||||
|
|
||||||
|
VOP2_WIN_VP_SEL,
|
||||||
|
VOP2_WIN_DLY_NUM,
|
||||||
|
|
||||||
|
VOP2_WIN_MAX_REG,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_regs_dump {
|
||||||
|
const char *name;
|
||||||
|
u32 base;
|
||||||
|
u32 size;
|
||||||
|
u32 en_reg;
|
||||||
|
u32 en_val;
|
||||||
|
u32 en_mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_win_data {
|
||||||
|
const char *name;
|
||||||
|
unsigned int phys_id;
|
||||||
|
|
||||||
|
u32 base;
|
||||||
|
u32 possible_vp_mask;
|
||||||
|
enum drm_plane_type type;
|
||||||
|
|
||||||
|
u32 nformats;
|
||||||
|
const u32 *formats;
|
||||||
|
const uint64_t *format_modifiers;
|
||||||
|
const unsigned int supported_rotations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @layer_sel_id: defined by register OVERLAY_LAYER_SEL or PORTn_LAYER_SEL
|
||||||
|
*/
|
||||||
|
unsigned int layer_sel_id[ROCKCHIP_MAX_CRTC];
|
||||||
|
uint64_t feature;
|
||||||
|
|
||||||
|
uint8_t axi_bus_id;
|
||||||
|
uint8_t axi_yrgb_r_id;
|
||||||
|
uint8_t axi_uv_r_id;
|
||||||
|
|
||||||
|
unsigned int max_upscale_factor;
|
||||||
|
unsigned int max_downscale_factor;
|
||||||
|
const u8 dly[VOP2_DLY_MODE_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_win {
|
||||||
|
struct vop2 *vop2;
|
||||||
|
struct drm_plane base;
|
||||||
|
const struct vop2_win_data *data;
|
||||||
|
struct regmap_field *reg[VOP2_WIN_MAX_REG];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @win_id: graphic window id, a cluster may be split into two
|
||||||
|
* graphics windows.
|
||||||
|
*/
|
||||||
|
u8 win_id;
|
||||||
|
u8 delay;
|
||||||
|
u32 offset;
|
||||||
|
|
||||||
|
enum drm_plane_type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_video_port_data {
|
||||||
|
unsigned int id;
|
||||||
|
u32 feature;
|
||||||
|
u16 gamma_lut_len;
|
||||||
|
u16 cubic_lut_len;
|
||||||
|
struct vop_rect max_output;
|
||||||
|
const u8 pre_scan_max_dly[4];
|
||||||
|
unsigned int offset;
|
||||||
|
/**
|
||||||
|
* @pixel_rate: pixel per cycle
|
||||||
|
*/
|
||||||
|
u8 pixel_rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_video_port {
|
||||||
|
struct drm_crtc crtc;
|
||||||
|
struct vop2 *vop2;
|
||||||
|
struct clk *dclk;
|
||||||
|
struct clk *dclk_src;
|
||||||
|
unsigned int id;
|
||||||
|
const struct vop2_video_port_data *data;
|
||||||
|
|
||||||
|
struct completion dsp_hold_completion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @win_mask: Bitmask of windows attached to the video port;
|
||||||
|
*/
|
||||||
|
u32 win_mask;
|
||||||
|
|
||||||
|
struct vop2_win *primary_plane;
|
||||||
|
struct drm_pending_vblank_event *event;
|
||||||
|
|
||||||
|
unsigned int nlayers;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct vop2_ops - helper operations for vop2 hardware
|
||||||
|
*
|
||||||
|
* These hooks are used by the common part of the vop2 driver to
|
||||||
|
* implement the proper behaviour of different variants.
|
||||||
|
*/
|
||||||
|
struct vop2_ops {
|
||||||
|
unsigned long (*setup_intf_mux)(struct vop2_video_port *vp, int ep_id, u32 polflags);
|
||||||
|
void (*setup_bg_dly)(struct vop2_video_port *vp);
|
||||||
|
void (*setup_overlay)(struct vop2_video_port *vp);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2_data {
|
||||||
|
u8 nr_vps;
|
||||||
|
u64 feature;
|
||||||
|
u32 version;
|
||||||
|
const struct vop2_ops *ops;
|
||||||
|
const struct vop2_win_data *win;
|
||||||
|
const struct vop2_video_port_data *vp;
|
||||||
|
const struct reg_field *cluster_reg;
|
||||||
|
const struct reg_field *smart_reg;
|
||||||
|
const struct vop2_regs_dump *regs_dump;
|
||||||
|
struct vop_rect max_input;
|
||||||
|
struct vop_rect max_output;
|
||||||
|
|
||||||
|
unsigned int nr_cluster_regs;
|
||||||
|
unsigned int nr_smart_regs;
|
||||||
|
unsigned int win_size;
|
||||||
|
unsigned int regs_dump_size;
|
||||||
|
unsigned int soc_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vop2 {
|
||||||
|
u32 version;
|
||||||
|
struct device *dev;
|
||||||
|
struct drm_device *drm;
|
||||||
|
struct vop2_video_port vps[ROCKCHIP_MAX_CRTC];
|
||||||
|
|
||||||
|
const struct vop2_data *data;
|
||||||
|
const struct vop2_ops *ops;
|
||||||
|
/*
|
||||||
|
* Number of windows that are registered as plane, may be less than the
|
||||||
|
* total number of hardware windows.
|
||||||
|
*/
|
||||||
|
u32 registered_num_wins;
|
||||||
|
|
||||||
|
struct resource *res;
|
||||||
|
void __iomem *regs;
|
||||||
|
struct regmap *map;
|
||||||
|
|
||||||
|
struct regmap *sys_grf;
|
||||||
|
struct regmap *vop_grf;
|
||||||
|
struct regmap *vo1_grf;
|
||||||
|
struct regmap *sys_pmu;
|
||||||
|
|
||||||
|
/* physical map length of vop2 register */
|
||||||
|
u32 len;
|
||||||
|
|
||||||
|
void __iomem *lut_regs;
|
||||||
|
|
||||||
|
/* protects crtc enable/disable */
|
||||||
|
struct mutex vop2_lock;
|
||||||
|
|
||||||
|
int irq;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some global resources are shared between all video ports(crtcs), so
|
||||||
|
* we need a ref counter here.
|
||||||
|
*/
|
||||||
|
unsigned int enable_count;
|
||||||
|
struct clk *hclk;
|
||||||
|
struct clk *aclk;
|
||||||
|
struct clk *pclk;
|
||||||
|
struct clk *pll_hdmiphy0;
|
||||||
|
struct clk *pll_hdmiphy1;
|
||||||
|
|
||||||
|
/* optional internal rgb encoder */
|
||||||
|
struct rockchip_rgb *rgb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used to record layer selection configuration on rk356x/rk3588
|
||||||
|
* as register RK3568_OVL_LAYER_SEL and RK3568_OVL_PORT_SEL are
|
||||||
|
* shared for all the Video Ports.
|
||||||
|
*/
|
||||||
|
u32 old_layer_sel;
|
||||||
|
u32 old_port_sel;
|
||||||
|
/*
|
||||||
|
* Ensure that the updates to these two registers(RKK3568_OVL_LAYER_SEL/RK3568_OVL_PORT_SEL)
|
||||||
|
* take effect in sequence.
|
||||||
|
*/
|
||||||
|
struct mutex ovl_lock;
|
||||||
|
|
||||||
|
/* must be put at the end of the struct */
|
||||||
|
struct vop2_win win[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* interrupt define */
|
||||||
|
#define FS_NEW_INTR BIT(4)
|
||||||
|
#define ADDR_SAME_INTR BIT(5)
|
||||||
|
#define LINE_FLAG1_INTR BIT(6)
|
||||||
|
#define WIN0_EMPTY_INTR BIT(7)
|
||||||
|
#define WIN1_EMPTY_INTR BIT(8)
|
||||||
|
#define WIN2_EMPTY_INTR BIT(9)
|
||||||
|
#define WIN3_EMPTY_INTR BIT(10)
|
||||||
|
#define HWC_EMPTY_INTR BIT(11)
|
||||||
|
#define POST_BUF_EMPTY_INTR BIT(12)
|
||||||
|
#define PWM_GEN_INTR BIT(13)
|
||||||
|
#define DMA_FINISH_INTR BIT(14)
|
||||||
|
#define FS_FIELD_INTR BIT(15)
|
||||||
|
#define FE_INTR BIT(16)
|
||||||
|
#define WB_UV_FIFO_FULL_INTR BIT(17)
|
||||||
|
#define WB_YRGB_FIFO_FULL_INTR BIT(18)
|
||||||
|
#define WB_COMPLETE_INTR BIT(19)
|
||||||
|
|
||||||
|
|
||||||
|
enum vop_csc_format {
|
||||||
|
CSC_BT601L,
|
||||||
|
CSC_BT709L,
|
||||||
|
CSC_BT601F,
|
||||||
|
CSC_BT2020,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum src_factor_mode {
|
||||||
|
SRC_FAC_ALPHA_ZERO,
|
||||||
|
SRC_FAC_ALPHA_ONE,
|
||||||
|
SRC_FAC_ALPHA_DST,
|
||||||
|
SRC_FAC_ALPHA_DST_INVERSE,
|
||||||
|
SRC_FAC_ALPHA_SRC,
|
||||||
|
SRC_FAC_ALPHA_SRC_GLOBAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum dst_factor_mode {
|
||||||
|
DST_FAC_ALPHA_ZERO,
|
||||||
|
DST_FAC_ALPHA_ONE,
|
||||||
|
DST_FAC_ALPHA_SRC,
|
||||||
|
DST_FAC_ALPHA_SRC_INVERSE,
|
||||||
|
DST_FAC_ALPHA_DST,
|
||||||
|
DST_FAC_ALPHA_DST_GLOBAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RK3568_GRF_VO_CON1 0x0364
|
||||||
|
|
||||||
|
#define RK3588_GRF_SOC_CON1 0x0304
|
||||||
|
#define RK3588_GRF_VOP_CON2 0x08
|
||||||
|
#define RK3588_GRF_VO1_CON0 0x00
|
||||||
|
|
||||||
|
/* System registers definition */
|
||||||
|
#define RK3568_REG_CFG_DONE 0x000
|
||||||
|
#define RK3568_VERSION_INFO 0x004
|
||||||
|
#define RK3568_SYS_AUTO_GATING_CTRL 0x008
|
||||||
|
#define RK3576_SYS_MMU_CTRL_IMD 0x020
|
||||||
|
#define RK3568_SYS_AXI_LUT_CTRL 0x024
|
||||||
|
#define RK3568_DSP_IF_EN 0x028
|
||||||
|
#define RK3576_SYS_PORT_CTRL_IMD 0x028
|
||||||
|
#define RK3568_DSP_IF_CTRL 0x02c
|
||||||
|
#define RK3568_DSP_IF_POL 0x030
|
||||||
|
#define RK3576_SYS_CLUSTER_PD_CTRL_IMD 0x030
|
||||||
|
#define RK3588_SYS_PD_CTRL 0x034
|
||||||
|
#define RK3568_WB_CTRL 0x40
|
||||||
|
#define RK3568_WB_XSCAL_FACTOR 0x44
|
||||||
|
#define RK3568_WB_YRGB_MST 0x48
|
||||||
|
#define RK3568_WB_CBR_MST 0x4C
|
||||||
|
#define RK3568_OTP_WIN_EN 0x050
|
||||||
|
#define RK3568_LUT_PORT_SEL 0x058
|
||||||
|
#define RK3568_SYS_STATUS0 0x060
|
||||||
|
#define RK3568_VP_LINE_FLAG(vp) (0x70 + (vp) * 0x4)
|
||||||
|
#define RK3568_SYS0_INT_EN 0x80
|
||||||
|
#define RK3568_SYS0_INT_CLR 0x84
|
||||||
|
#define RK3568_SYS0_INT_STATUS 0x88
|
||||||
|
#define RK3568_SYS1_INT_EN 0x90
|
||||||
|
#define RK3568_SYS1_INT_CLR 0x94
|
||||||
|
#define RK3568_SYS1_INT_STATUS 0x98
|
||||||
|
#define RK3568_VP_INT_EN(vp) (0xA0 + (vp) * 0x10)
|
||||||
|
#define RK3568_VP_INT_CLR(vp) (0xA4 + (vp) * 0x10)
|
||||||
|
#define RK3568_VP_INT_STATUS(vp) (0xA8 + (vp) * 0x10)
|
||||||
|
#define RK3568_VP_INT_RAW_STATUS(vp) (0xAC + (vp) * 0x10)
|
||||||
|
#define RK3576_WB_CTRL 0x100
|
||||||
|
#define RK3576_WB_XSCAL_FACTOR 0x104
|
||||||
|
#define RK3576_WB_YRGB_MST 0x108
|
||||||
|
#define RK3576_WB_CBR_MST 0x10C
|
||||||
|
#define RK3576_WB_VIR_STRIDE 0x110
|
||||||
|
#define RK3576_WB_TIMEOUT_CTRL 0x114
|
||||||
|
#define RK3576_MIPI0_IF_CTRL 0x180
|
||||||
|
#define RK3576_HDMI0_IF_CTRL 0x184
|
||||||
|
#define RK3576_EDP0_IF_CTRL 0x188
|
||||||
|
#define RK3576_DP0_IF_CTRL 0x18C
|
||||||
|
#define RK3576_RGB_IF_CTRL 0x194
|
||||||
|
#define RK3576_DP1_IF_CTRL 0x1A4
|
||||||
|
#define RK3576_DP2_IF_CTRL 0x1B0
|
||||||
|
|
||||||
|
/* Extra OVL register definition */
|
||||||
|
#define RK3576_SYS_EXTRA_ALPHA_CTRL 0x500
|
||||||
|
#define RK3576_CLUSTER0_MIX_SRC_COLOR_CTRL 0x530
|
||||||
|
#define RK3576_CLUSTER0_MIX_DST_COLOR_CTRL 0x534
|
||||||
|
#define RK3576_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x538
|
||||||
|
#define RK3576_CLUSTER0_MIX_DST_ALPHA_CTRL 0x53c
|
||||||
|
#define RK3576_CLUSTER1_MIX_SRC_COLOR_CTRL 0x540
|
||||||
|
#define RK3576_CLUSTER1_MIX_DST_COLOR_CTRL 0x544
|
||||||
|
#define RK3576_CLUSTER1_MIX_SRC_ALPHA_CTRL 0x548
|
||||||
|
#define RK3576_CLUSTER1_MIX_DST_ALPHA_CTRL 0x54c
|
||||||
|
|
||||||
|
/* OVL registers for Video Port definition */
|
||||||
|
#define RK3576_OVL_CTRL(vp) (0x600 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_LAYER_SEL(vp) (0x604 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX0_SRC_COLOR_CTRL(vp) (0x620 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX0_DST_COLOR_CTRL(vp) (0x624 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX0_SRC_ALPHA_CTRL(vp) (0x628 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX0_DST_ALPHA_CTRL(vp) (0x62C + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX1_SRC_COLOR_CTRL(vp) (0x630 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX1_DST_COLOR_CTRL(vp) (0x634 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX1_SRC_ALPHA_CTRL(vp) (0x638 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX1_DST_ALPHA_CTRL(vp) (0x63C + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX2_SRC_COLOR_CTRL(vp) (0x640 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX2_DST_COLOR_CTRL(vp) (0x644 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX2_SRC_ALPHA_CTRL(vp) (0x648 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_MIX2_DST_ALPHA_CTRL(vp) (0x64C + (vp) * 0x100)
|
||||||
|
#define RK3576_EXTRA_OVL_SRC_COLOR_CTRL(vp) (0x650 + (vp) * 0x100)
|
||||||
|
#define RK3576_EXTRA_OVL_DST_COLOR_CTRL(vp) (0x654 + (vp) * 0x100)
|
||||||
|
#define RK3576_EXTRA_OVL_SRC_ALPHA_CTRL(vp) (0x658 + (vp) * 0x100)
|
||||||
|
#define RK3576_EXTRA_OVL_DST_ALPHA_CTRL(vp) (0x65C + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_HDR_SRC_COLOR_CTRL(vp) (0x660 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_HDR_DST_COLOR_CTRL(vp) (0x664 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_HDR_SRC_ALPHA_CTRL(vp) (0x668 + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_HDR_DST_ALPHA_CTRL(vp) (0x66C + (vp) * 0x100)
|
||||||
|
#define RK3576_OVL_BG_MIX_CTRL(vp) (0x670 + (vp) * 0x100)
|
||||||
|
|
||||||
|
/* Video Port registers definition */
|
||||||
|
#define RK3568_VP0_CTRL_BASE 0x0C00
|
||||||
|
#define RK3568_VP1_CTRL_BASE 0x0D00
|
||||||
|
#define RK3568_VP2_CTRL_BASE 0x0E00
|
||||||
|
#define RK3588_VP3_CTRL_BASE 0x0F00
|
||||||
|
#define RK3568_VP_DSP_CTRL 0x00
|
||||||
|
#define RK3568_VP_MIPI_CTRL 0x04
|
||||||
|
#define RK3568_VP_COLOR_BAR_CTRL 0x08
|
||||||
|
#define RK3588_VP_CLK_CTRL 0x0C
|
||||||
|
#define RK3568_VP_3D_LUT_CTRL 0x10
|
||||||
|
#define RK3568_VP_3D_LUT_MST 0x20
|
||||||
|
#define RK3568_VP_DSP_BG 0x2C
|
||||||
|
#define RK3568_VP_PRE_SCAN_HTIMING 0x30
|
||||||
|
#define RK3568_VP_POST_DSP_HACT_INFO 0x34
|
||||||
|
#define RK3568_VP_POST_DSP_VACT_INFO 0x38
|
||||||
|
#define RK3568_VP_POST_SCL_FACTOR_YRGB 0x3C
|
||||||
|
#define RK3568_VP_POST_SCL_CTRL 0x40
|
||||||
|
#define RK3568_VP_POST_DSP_VACT_INFO_F1 0x44
|
||||||
|
#define RK3568_VP_DSP_HTOTAL_HS_END 0x48
|
||||||
|
#define RK3568_VP_DSP_HACT_ST_END 0x4C
|
||||||
|
#define RK3568_VP_DSP_VTOTAL_VS_END 0x50
|
||||||
|
#define RK3568_VP_DSP_VACT_ST_END 0x54
|
||||||
|
#define RK3568_VP_DSP_VS_ST_END_F1 0x58
|
||||||
|
#define RK3568_VP_DSP_VACT_ST_END_F1 0x5C
|
||||||
|
#define RK3568_VP_BCSH_CTRL 0x60
|
||||||
|
#define RK3568_VP_BCSH_BCS 0x64
|
||||||
|
#define RK3568_VP_BCSH_H 0x68
|
||||||
|
#define RK3568_VP_BCSH_COLOR_BAR 0x6C
|
||||||
|
|
||||||
|
/* Overlay registers definition */
|
||||||
|
#define RK3568_OVL_CTRL 0x600
|
||||||
|
#define RK3568_OVL_LAYER_SEL 0x604
|
||||||
|
#define RK3568_OVL_PORT_SEL 0x608
|
||||||
|
#define RK3568_CLUSTER0_MIX_SRC_COLOR_CTRL 0x610
|
||||||
|
#define RK3568_CLUSTER0_MIX_DST_COLOR_CTRL 0x614
|
||||||
|
#define RK3568_CLUSTER0_MIX_SRC_ALPHA_CTRL 0x618
|
||||||
|
#define RK3568_CLUSTER0_MIX_DST_ALPHA_CTRL 0x61C
|
||||||
|
#define RK3568_MIX0_SRC_COLOR_CTRL 0x650
|
||||||
|
#define RK3568_MIX0_DST_COLOR_CTRL 0x654
|
||||||
|
#define RK3568_MIX0_SRC_ALPHA_CTRL 0x658
|
||||||
|
#define RK3568_MIX0_DST_ALPHA_CTRL 0x65C
|
||||||
|
#define RK3568_HDR0_SRC_COLOR_CTRL 0x6C0
|
||||||
|
#define RK3568_HDR0_DST_COLOR_CTRL 0x6C4
|
||||||
|
#define RK3568_HDR0_SRC_ALPHA_CTRL 0x6C8
|
||||||
|
#define RK3568_HDR0_DST_ALPHA_CTRL 0x6CC
|
||||||
|
#define RK3568_VP_BG_MIX_CTRL(vp) (0x6E0 + (vp) * 4)
|
||||||
|
#define RK3568_CLUSTER_DLY_NUM 0x6F0
|
||||||
|
#define RK3568_SMART_DLY_NUM 0x6F8
|
||||||
|
|
||||||
|
/* Cluster register definition, offset relative to window base */
|
||||||
|
#define RK3568_CLUSTER0_CTRL_BASE 0x1000
|
||||||
|
#define RK3568_CLUSTER1_CTRL_BASE 0x1200
|
||||||
|
#define RK3588_CLUSTER2_CTRL_BASE 0x1400
|
||||||
|
#define RK3588_CLUSTER3_CTRL_BASE 0x1600
|
||||||
|
#define RK3568_ESMART0_CTRL_BASE 0x1800
|
||||||
|
#define RK3568_ESMART1_CTRL_BASE 0x1A00
|
||||||
|
#define RK3568_SMART0_CTRL_BASE 0x1C00
|
||||||
|
#define RK3568_SMART1_CTRL_BASE 0x1E00
|
||||||
|
#define RK3588_ESMART2_CTRL_BASE 0x1C00
|
||||||
|
#define RK3588_ESMART3_CTRL_BASE 0x1E00
|
||||||
|
|
||||||
|
#define RK3568_CLUSTER_WIN_CTRL0 0x00
|
||||||
|
#define RK3568_CLUSTER_WIN_CTRL1 0x04
|
||||||
|
#define RK3568_CLUSTER_WIN_CTRL2 0x08
|
||||||
|
#define RK3568_CLUSTER_WIN_YRGB_MST 0x10
|
||||||
|
#define RK3568_CLUSTER_WIN_CBR_MST 0x14
|
||||||
|
#define RK3568_CLUSTER_WIN_VIR 0x18
|
||||||
|
#define RK3568_CLUSTER_WIN_ACT_INFO 0x20
|
||||||
|
#define RK3568_CLUSTER_WIN_DSP_INFO 0x24
|
||||||
|
#define RK3568_CLUSTER_WIN_DSP_ST 0x28
|
||||||
|
#define RK3568_CLUSTER_WIN_SCL_FACTOR_YRGB 0x30
|
||||||
|
#define RK3568_CLUSTER_WIN_TRANSFORM_OFFSET 0x3C
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_OUTPUT_CTRL 0x50
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_ROTATE_MODE 0x54
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_HDR_PTR 0x58
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_VIR_WIDTH 0x5C
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_PIC_SIZE 0x60
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_PIC_OFFSET 0x64
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_DSP_OFFSET 0x68
|
||||||
|
#define RK3568_CLUSTER_WIN_AFBCD_CTRL 0x6C
|
||||||
|
|
||||||
|
#define RK3576_CLUSTER_WIN_AFBCD_PLD_PTR_OFFSET 0x78
|
||||||
|
|
||||||
|
#define RK3568_CLUSTER_CTRL 0x100
|
||||||
|
#define RK3576_CLUSTER_PORT_SEL_IMD 0x1F4
|
||||||
|
#define RK3576_CLUSTER_DLY_NUM 0x1F8
|
||||||
|
|
||||||
|
/* (E)smart register definition, offset relative to window base */
|
||||||
|
#define RK3568_SMART_CTRL0 0x00
|
||||||
|
#define RK3568_SMART_CTRL1 0x04
|
||||||
|
#define RK3588_SMART_AXI_CTRL 0x08
|
||||||
|
#define RK3568_SMART_REGION0_CTRL 0x10
|
||||||
|
#define RK3568_SMART_REGION0_YRGB_MST 0x14
|
||||||
|
#define RK3568_SMART_REGION0_CBR_MST 0x18
|
||||||
|
#define RK3568_SMART_REGION0_VIR 0x1C
|
||||||
|
#define RK3568_SMART_REGION0_ACT_INFO 0x20
|
||||||
|
#define RK3568_SMART_REGION0_DSP_INFO 0x24
|
||||||
|
#define RK3568_SMART_REGION0_DSP_ST 0x28
|
||||||
|
#define RK3568_SMART_REGION0_SCL_CTRL 0x30
|
||||||
|
#define RK3568_SMART_REGION0_SCL_FACTOR_YRGB 0x34
|
||||||
|
#define RK3568_SMART_REGION0_SCL_FACTOR_CBR 0x38
|
||||||
|
#define RK3568_SMART_REGION0_SCL_OFFSET 0x3C
|
||||||
|
#define RK3568_SMART_REGION1_CTRL 0x40
|
||||||
|
#define RK3568_SMART_REGION1_YRGB_MST 0x44
|
||||||
|
#define RK3568_SMART_REGION1_CBR_MST 0x48
|
||||||
|
#define RK3568_SMART_REGION1_VIR 0x4C
|
||||||
|
#define RK3568_SMART_REGION1_ACT_INFO 0x50
|
||||||
|
#define RK3568_SMART_REGION1_DSP_INFO 0x54
|
||||||
|
#define RK3568_SMART_REGION1_DSP_ST 0x58
|
||||||
|
#define RK3568_SMART_REGION1_SCL_CTRL 0x60
|
||||||
|
#define RK3568_SMART_REGION1_SCL_FACTOR_YRGB 0x64
|
||||||
|
#define RK3568_SMART_REGION1_SCL_FACTOR_CBR 0x68
|
||||||
|
#define RK3568_SMART_REGION1_SCL_OFFSET 0x6C
|
||||||
|
#define RK3568_SMART_REGION2_CTRL 0x70
|
||||||
|
#define RK3568_SMART_REGION2_YRGB_MST 0x74
|
||||||
|
#define RK3568_SMART_REGION2_CBR_MST 0x78
|
||||||
|
#define RK3568_SMART_REGION2_VIR 0x7C
|
||||||
|
#define RK3568_SMART_REGION2_ACT_INFO 0x80
|
||||||
|
#define RK3568_SMART_REGION2_DSP_INFO 0x84
|
||||||
|
#define RK3568_SMART_REGION2_DSP_ST 0x88
|
||||||
|
#define RK3568_SMART_REGION2_SCL_CTRL 0x90
|
||||||
|
#define RK3568_SMART_REGION2_SCL_FACTOR_YRGB 0x94
|
||||||
|
#define RK3568_SMART_REGION2_SCL_FACTOR_CBR 0x98
|
||||||
|
#define RK3568_SMART_REGION2_SCL_OFFSET 0x9C
|
||||||
|
#define RK3568_SMART_REGION3_CTRL 0xA0
|
||||||
|
#define RK3568_SMART_REGION3_YRGB_MST 0xA4
|
||||||
|
#define RK3568_SMART_REGION3_CBR_MST 0xA8
|
||||||
|
#define RK3568_SMART_REGION3_VIR 0xAC
|
||||||
|
#define RK3568_SMART_REGION3_ACT_INFO 0xB0
|
||||||
|
#define RK3568_SMART_REGION3_DSP_INFO 0xB4
|
||||||
|
#define RK3568_SMART_REGION3_DSP_ST 0xB8
|
||||||
|
#define RK3568_SMART_REGION3_SCL_CTRL 0xC0
|
||||||
|
#define RK3568_SMART_REGION3_SCL_FACTOR_YRGB 0xC4
|
||||||
|
#define RK3568_SMART_REGION3_SCL_FACTOR_CBR 0xC8
|
||||||
|
#define RK3568_SMART_REGION3_SCL_OFFSET 0xCC
|
||||||
|
#define RK3568_SMART_COLOR_KEY_CTRL 0xD0
|
||||||
|
#define RK3576_SMART_ALPHA_MAP 0xD8
|
||||||
|
#define RK3576_SMART_PORT_SEL_IMD 0xF4
|
||||||
|
#define RK3576_SMART_DLY_NUM 0xF8
|
||||||
|
|
||||||
|
/* HDR register definition */
|
||||||
|
#define RK3568_HDR_LUT_CTRL 0x2000
|
||||||
|
#define RK3568_HDR_LUT_MST 0x2004
|
||||||
|
#define RK3568_SDR2HDR_CTRL 0x2010
|
||||||
|
#define RK3568_HDR2SDR_CTRL 0x2020
|
||||||
|
#define RK3568_HDR2SDR_SRC_RANGE 0x2024
|
||||||
|
#define RK3568_HDR2SDR_NORMFACEETF 0x2028
|
||||||
|
#define RK3568_HDR2SDR_DST_RANGE 0x202C
|
||||||
|
#define RK3568_HDR2SDR_NORMFACCGAMMA 0x2030
|
||||||
|
#define RK3568_HDR_EETF_OETF_Y0 0x203C
|
||||||
|
#define RK3568_HDR_SAT_Y0 0x20C0
|
||||||
|
#define RK3568_HDR_EOTF_OETF_Y0 0x20F0
|
||||||
|
#define RK3568_HDR_OETF_DX_POW1 0x2200
|
||||||
|
#define RK3568_HDR_OETF_XN1 0x2300
|
||||||
|
|
||||||
|
#define RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN BIT(15)
|
||||||
|
|
||||||
|
#define RK3568_VP_DSP_CTRL__STANDBY BIT(31)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_LUT_EN BIT(28)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_MODE BIT(20)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_SEL GENMASK(19, 18)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DITHER_DOWN_EN BIT(17)
|
||||||
|
#define RK3568_VP_DSP_CTRL__PRE_DITHER_DOWN_EN BIT(16)
|
||||||
|
#define RK3568_VP_DSP_CTRL__POST_DSP_OUT_R2Y BIT(15)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_RG_SWAP BIT(10)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_RB_SWAP BIT(9)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_BG_SWAP BIT(8)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_INTERLACE BIT(7)
|
||||||
|
#define RK3568_VP_DSP_CTRL__DSP_FILED_POL BIT(6)
|
||||||
|
#define RK3568_VP_DSP_CTRL__P2I_EN BIT(5)
|
||||||
|
#define RK3568_VP_DSP_CTRL__CORE_DCLK_DIV BIT(4)
|
||||||
|
#define RK3568_VP_DSP_CTRL__OUT_MODE GENMASK(3, 0)
|
||||||
|
|
||||||
|
#define RK3588_VP_DSP_CTRL__GAMMA_UPDATE_EN BIT(22)
|
||||||
|
|
||||||
|
#define RK3588_VP_CLK_CTRL__DCLK_OUT_DIV GENMASK(3, 2)
|
||||||
|
#define RK3588_VP_CLK_CTRL__DCLK_CORE_DIV GENMASK(1, 0)
|
||||||
|
|
||||||
|
#define RK3568_VP_POST_SCL_CTRL__VSCALEDOWN BIT(1)
|
||||||
|
#define RK3568_VP_POST_SCL_CTRL__HSCALEDOWN BIT(0)
|
||||||
|
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_LVDS1_MUX GENMASK(26, 25)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_LVDS1 BIT(24)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_MIPI1 BIT(20)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_LVDS0_MUX GENMASK(19, 18)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(17, 16)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_EDP_MUX GENMASK(15, 14)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_HDMI_MUX GENMASK(11, 10)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_RGB_MUX GENMASK(9, 8)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_LVDS0 BIT(5)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_MIPI0 BIT(4)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_EDP BIT(3)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_HDMI BIT(1)
|
||||||
|
#define RK3568_SYS_DSP_INFACE_EN_RGB BIT(0)
|
||||||
|
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_MIPI1_MUX GENMASK(22, 21)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_MIPI0_MUX GENMASK(20, 20)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_EDP_HDMI1_MUX GENMASK(19, 18)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_EDP_HDMI0_MUX GENMASK(17, 16)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_DP1_MUX GENMASK(15, 14)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_DP0_MUX GENMASK(13, 12)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_DPI GENMASK(9, 8)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_MIPI1 BIT(7)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_MIPI0 BIT(6)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_HDMI1 BIT(5)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_EDP1 BIT(4)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_HDMI0 BIT(3)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_EDP0 BIT(2)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_DP1 BIT(1)
|
||||||
|
#define RK3588_SYS_DSP_INFACE_EN_DP0 BIT(0)
|
||||||
|
|
||||||
|
#define RK3588_DSP_IF_MIPI1_PCLK_DIV GENMASK(27, 26)
|
||||||
|
#define RK3588_DSP_IF_MIPI0_PCLK_DIV GENMASK(25, 24)
|
||||||
|
#define RK3588_DSP_IF_EDP_HDMI1_PCLK_DIV GENMASK(22, 22)
|
||||||
|
#define RK3588_DSP_IF_EDP_HDMI1_DCLK_DIV GENMASK(21, 20)
|
||||||
|
#define RK3588_DSP_IF_EDP_HDMI0_PCLK_DIV GENMASK(18, 18)
|
||||||
|
#define RK3588_DSP_IF_EDP_HDMI0_DCLK_DIV GENMASK(17, 16)
|
||||||
|
|
||||||
|
#define RK3568_DSP_IF_POL__MIPI_PIN_POL GENMASK(19, 16)
|
||||||
|
#define RK3568_DSP_IF_POL__EDP_PIN_POL GENMASK(15, 12)
|
||||||
|
#define RK3568_DSP_IF_POL__HDMI_PIN_POL GENMASK(7, 4)
|
||||||
|
#define RK3568_DSP_IF_POL__RGB_LVDS_PIN_POL GENMASK(3, 0)
|
||||||
|
|
||||||
|
#define RK3588_DSP_IF_POL__DP1_PIN_POL GENMASK(14, 12)
|
||||||
|
#define RK3588_DSP_IF_POL__DP0_PIN_POL GENMASK(10, 8)
|
||||||
|
|
||||||
|
#define RK3588_LUT_PORT_SEL__GAMMA_AHB_WRITE_SEL GENMASK(13, 12)
|
||||||
|
|
||||||
|
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2_PHASE_LOCK BIT(5)
|
||||||
|
#define RK3568_VP0_MIPI_CTRL__DCLK_DIV2 BIT(4)
|
||||||
|
|
||||||
|
#define RK3568_SYS_AUTO_GATING_CTRL__AUTO_GATING_EN BIT(31)
|
||||||
|
|
||||||
|
#define RK3568_DSP_IF_POL__CFG_DONE_IMD BIT(28)
|
||||||
|
|
||||||
|
#define VOP2_SYS_AXI_BUS_NUM 2
|
||||||
|
|
||||||
|
#define VOP2_CLUSTER_YUV444_10 0x12
|
||||||
|
|
||||||
|
#define VOP2_COLOR_KEY_MASK BIT(31)
|
||||||
|
|
||||||
|
#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_SEL GENMASK(31, 30)
|
||||||
|
#define RK3568_OVL_CTRL__LAYERSEL_REGDONE_IMD BIT(28)
|
||||||
|
#define RK3568_OVL_CTRL__YUV_MODE(vp) BIT(vp)
|
||||||
|
|
||||||
|
#define RK3568_VP_BG_MIX_CTRL__BG_DLY GENMASK(31, 24)
|
||||||
|
|
||||||
|
#define RK3568_OVL_PORT_SEL__SEL_PORT GENMASK(31, 16)
|
||||||
|
#define RK3568_OVL_PORT_SEL__SMART1 GENMASK(31, 30)
|
||||||
|
#define RK3568_OVL_PORT_SEL__SMART0 GENMASK(29, 28)
|
||||||
|
#define RK3588_OVL_PORT_SEL__ESMART3 GENMASK(31, 30)
|
||||||
|
#define RK3588_OVL_PORT_SEL__ESMART2 GENMASK(29, 28)
|
||||||
|
#define RK3568_OVL_PORT_SEL__ESMART1 GENMASK(27, 26)
|
||||||
|
#define RK3568_OVL_PORT_SEL__ESMART0 GENMASK(25, 24)
|
||||||
|
#define RK3588_OVL_PORT_SEL__CLUSTER3 GENMASK(23, 22)
|
||||||
|
#define RK3588_OVL_PORT_SEL__CLUSTER2 GENMASK(21, 20)
|
||||||
|
#define RK3568_OVL_PORT_SEL__CLUSTER1 GENMASK(19, 18)
|
||||||
|
#define RK3568_OVL_PORT_SEL__CLUSTER0 GENMASK(17, 16)
|
||||||
|
#define RK3588_OVL_PORT_SET__PORT3_MUX GENMASK(15, 12)
|
||||||
|
#define RK3568_OVL_PORT_SET__PORT2_MUX GENMASK(11, 8)
|
||||||
|
#define RK3568_OVL_PORT_SET__PORT1_MUX GENMASK(7, 4)
|
||||||
|
#define RK3568_OVL_PORT_SET__PORT0_MUX GENMASK(3, 0)
|
||||||
|
#define RK3568_OVL_LAYER_SEL__LAYER(layer, x) ((x) << ((layer) * 4))
|
||||||
|
|
||||||
|
#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_1 GENMASK(31, 24)
|
||||||
|
#define RK3568_CLUSTER_DLY_NUM__CLUSTER1_0 GENMASK(23, 16)
|
||||||
|
#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_1 GENMASK(15, 8)
|
||||||
|
#define RK3568_CLUSTER_DLY_NUM__CLUSTER0_0 GENMASK(7, 0)
|
||||||
|
|
||||||
|
#define RK3568_CLUSTER_WIN_CTRL0__WIN0_EN BIT(0)
|
||||||
|
|
||||||
|
#define RK3568_SMART_REGION0_CTRL__WIN0_EN BIT(0)
|
||||||
|
|
||||||
|
#define RK3568_SMART_DLY_NUM__SMART1 GENMASK(31, 24)
|
||||||
|
#define RK3568_SMART_DLY_NUM__SMART0 GENMASK(23, 16)
|
||||||
|
#define RK3568_SMART_DLY_NUM__ESMART1 GENMASK(15, 8)
|
||||||
|
#define RK3568_SMART_DLY_NUM__ESMART0 GENMASK(7, 0)
|
||||||
|
|
||||||
|
#define VP_INT_DSP_HOLD_VALID BIT(6)
|
||||||
|
#define VP_INT_FS_FIELD BIT(5)
|
||||||
|
#define VP_INT_POST_BUF_EMPTY BIT(4)
|
||||||
|
#define VP_INT_LINE_FLAG1 BIT(3)
|
||||||
|
#define VP_INT_LINE_FLAG0 BIT(2)
|
||||||
|
#define VOP2_INT_BUS_ERRPR BIT(1)
|
||||||
|
#define VP_INT_FS BIT(0)
|
||||||
|
|
||||||
|
#define POLFLAG_DCLK_INV BIT(3)
|
||||||
|
|
||||||
|
#define RK3576_OVL_CTRL__YUV_MODE BIT(0)
|
||||||
|
#define RK3576_OVL_BG_MIX_CTRL__BG_DLY GENMASK(31, 24)
|
||||||
|
|
||||||
|
#define RK3576_DSP_IF_CFG_DONE_IMD BIT(31)
|
||||||
|
#define RK3576_DSP_IF_DCLK_SEL_OUT BIT(21)
|
||||||
|
#define RK3576_DSP_IF_PCLK_DIV BIT(20)
|
||||||
|
#define RK3576_DSP_IF_PIN_POL GENMASK(5, 4)
|
||||||
|
#define RK3576_DSP_IF_MUX GENMASK(3, 2)
|
||||||
|
#define RK3576_DSP_IF_CLK_OUT_EN BIT(1)
|
||||||
|
#define RK3576_DSP_IF_EN BIT(0)
|
||||||
|
|
||||||
|
enum vop2_layer_phy_id {
|
||||||
|
ROCKCHIP_VOP2_CLUSTER0 = 0,
|
||||||
|
ROCKCHIP_VOP2_CLUSTER1,
|
||||||
|
ROCKCHIP_VOP2_ESMART0,
|
||||||
|
ROCKCHIP_VOP2_ESMART1,
|
||||||
|
ROCKCHIP_VOP2_SMART0,
|
||||||
|
ROCKCHIP_VOP2_SMART1,
|
||||||
|
ROCKCHIP_VOP2_CLUSTER2,
|
||||||
|
ROCKCHIP_VOP2_CLUSTER3,
|
||||||
|
ROCKCHIP_VOP2_ESMART2,
|
||||||
|
ROCKCHIP_VOP2_ESMART3,
|
||||||
|
ROCKCHIP_VOP2_PHY_ID_INVALID = -1,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const struct component_ops vop2_component_ops;
|
||||||
|
|
||||||
|
static inline void vop2_writel(struct vop2 *vop2, u32 offset, u32 v)
|
||||||
|
{
|
||||||
|
regmap_write(vop2->map, offset, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vop2_vp_write(struct vop2_video_port *vp, u32 offset, u32 v)
|
||||||
|
{
|
||||||
|
regmap_write(vp->vop2->map, vp->data->offset + offset, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 vop2_readl(struct vop2 *vop2, u32 offset)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
regmap_read(vop2->map, offset, &val);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 vop2_vp_read(struct vop2_video_port *vp, u32 offset)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
regmap_read(vp->vop2->map, vp->data->offset + offset, &val);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vop2_win_write(const struct vop2_win *win, unsigned int reg, u32 v)
|
||||||
|
{
|
||||||
|
regmap_field_write(win->reg[reg], v);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool vop2_cluster_window(const struct vop2_win *win)
|
||||||
|
{
|
||||||
|
return win->data->feature & WIN_FEATURE_CLUSTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
return container_of(crtc, struct vop2_video_port, crtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct vop2_win *to_vop2_win(struct drm_plane *p)
|
||||||
|
{
|
||||||
|
return container_of(p, struct vop2_win, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note:
|
||||||
|
* The write mask function is documented but missing on rk3566/8, writes
|
||||||
|
* to these bits have no effect. For newer soc(rk3588 and following) the
|
||||||
|
* write mask is needed for register writes.
|
||||||
|
*
|
||||||
|
* GLB_CFG_DONE_EN has no write mask bit.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static inline void vop2_cfg_done(struct vop2_video_port *vp)
|
||||||
|
{
|
||||||
|
struct vop2 *vop2 = vp->vop2;
|
||||||
|
u32 val = RK3568_REG_CFG_DONE__GLB_CFG_DONE_EN;
|
||||||
|
|
||||||
|
val |= BIT(vp->id) | (BIT(vp->id) << 16);
|
||||||
|
|
||||||
|
regmap_set_bits(vop2->map, RK3568_REG_CFG_DONE, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _ROCKCHIP_DRM_VOP2_H */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
32
target/linux/rockchip/files/include/drm/bridge/dw_hdmi_qp.h
Normal file
32
target/linux/rockchip/files/include/drm/bridge/dw_hdmi_qp.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
|
||||||
|
* Copyright (c) 2024 Collabora Ltd.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __DW_HDMI_QP__
|
||||||
|
#define __DW_HDMI_QP__
|
||||||
|
|
||||||
|
struct device;
|
||||||
|
struct drm_encoder;
|
||||||
|
struct dw_hdmi_qp;
|
||||||
|
struct platform_device;
|
||||||
|
|
||||||
|
struct dw_hdmi_qp_phy_ops {
|
||||||
|
int (*init)(struct dw_hdmi_qp *hdmi, void *data);
|
||||||
|
void (*disable)(struct dw_hdmi_qp *hdmi, void *data);
|
||||||
|
enum drm_connector_status (*read_hpd)(struct dw_hdmi_qp *hdmi, void *data);
|
||||||
|
void (*setup_hpd)(struct dw_hdmi_qp *hdmi, void *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dw_hdmi_qp_plat_data {
|
||||||
|
const struct dw_hdmi_qp_phy_ops *phy_ops;
|
||||||
|
void *phy_data;
|
||||||
|
int main_irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
|
||||||
|
struct drm_encoder *encoder,
|
||||||
|
const struct dw_hdmi_qp_plat_data *plat_data);
|
||||||
|
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi);
|
||||||
|
#endif /* __DW_HDMI_QP__ */
|
||||||
@ -28,11 +28,14 @@ define KernelPackage/drm-rockchip
|
|||||||
CONFIG_DRM_DISPLAY_CONNECTOR \
|
CONFIG_DRM_DISPLAY_CONNECTOR \
|
||||||
CONFIG_HDMI=y \
|
CONFIG_HDMI=y \
|
||||||
CONFIG_DRM_DW_HDMI \
|
CONFIG_DRM_DW_HDMI \
|
||||||
|
CONFIG_DRM_DW_HDMI_QP \
|
||||||
CONFIG_DRM_DW_HDMI_CEC \
|
CONFIG_DRM_DW_HDMI_CEC \
|
||||||
CONFIG_DRM_DW_HDMI_GP_AUDIO=n \
|
CONFIG_DRM_DW_HDMI_GP_AUDIO=n \
|
||||||
|
CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX \
|
||||||
CONFIG_ROCKCHIP_ANALOGIX_DP=n \
|
CONFIG_ROCKCHIP_ANALOGIX_DP=n \
|
||||||
CONFIG_ROCKCHIP_CDN_DP=n \
|
CONFIG_ROCKCHIP_CDN_DP=n \
|
||||||
CONFIG_ROCKCHIP_DW_HDMI=y \
|
CONFIG_ROCKCHIP_DW_HDMI=y \
|
||||||
|
CONFIG_ROCKCHIP_DW_HDMI_QP=y \
|
||||||
CONFIG_ROCKCHIP_DW_MIPI_DSI=n \
|
CONFIG_ROCKCHIP_DW_MIPI_DSI=n \
|
||||||
CONFIG_ROCKCHIP_INNO_HDMI=n \
|
CONFIG_ROCKCHIP_INNO_HDMI=n \
|
||||||
CONFIG_ROCKCHIP_LVDS=n \
|
CONFIG_ROCKCHIP_LVDS=n \
|
||||||
@ -44,11 +47,13 @@ define KernelPackage/drm-rockchip
|
|||||||
CONFIG_DRM_PANEL_BRIDGE=y
|
CONFIG_DRM_PANEL_BRIDGE=y
|
||||||
FILES:= \
|
FILES:= \
|
||||||
$(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi.ko \
|
$(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi.ko \
|
||||||
|
$(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.ko \
|
||||||
$(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.ko \
|
$(LINUX_DIR)/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.ko \
|
||||||
$(LINUX_DIR)/drivers/gpu/drm/bridge/display-connector.ko \
|
$(LINUX_DIR)/drivers/gpu/drm/bridge/display-connector.ko \
|
||||||
$(LINUX_DIR)/drivers/gpu/drm/rockchip/rockchipdrm.ko \
|
$(LINUX_DIR)/drivers/gpu/drm/rockchip/rockchipdrm.ko \
|
||||||
|
$(LINUX_DIR)/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.ko \
|
||||||
$(LINUX_DIR)/drivers/media/cec/core/cec.ko
|
$(LINUX_DIR)/drivers/media/cec/core/cec.ko
|
||||||
AUTOLOAD:=$(call AutoLoad,80,dw-hdmi-cec rockchipdrm display-connector)
|
AUTOLOAD:=$(call AutoLoad,80,phy-rockchip-samsung-hdptx dw-hdmi-cec rockchipdrm display-connector)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define KernelPackage/drm-rockchip/description
|
define KernelPackage/drm-rockchip/description
|
||||||
|
|||||||
@ -0,0 +1,297 @@
|
|||||||
|
--- a/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/rockchip/rk3588-base.dtsi
|
||||||
|
@@ -378,6 +378,22 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hdmi0_sound: hdmi0-sound {
|
||||||
|
+ compatible = "simple-audio-card";
|
||||||
|
+ simple-audio-card,format = "i2s";
|
||||||
|
+ simple-audio-card,mclk-fs = <128>;
|
||||||
|
+ simple-audio-card,name = "hdmi0";
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ simple-audio-card,codec {
|
||||||
|
+ sound-dai = <&hdmi0>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ simple-audio-card,cpu {
|
||||||
|
+ sound-dai = <&i2s5_8ch>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
pmu-a55 {
|
||||||
|
compatible = "arm,cortex-a55-pmu";
|
||||||
|
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH &ppi_partition0>;
|
||||||
|
@@ -1146,14 +1162,16 @@
|
||||||
|
<&cru DCLK_VOP1>,
|
||||||
|
<&cru DCLK_VOP2>,
|
||||||
|
<&cru DCLK_VOP3>,
|
||||||
|
- <&cru PCLK_VOP_ROOT>;
|
||||||
|
+ <&cru PCLK_VOP_ROOT>,
|
||||||
|
+ <&hdptxphy0>;
|
||||||
|
clock-names = "aclk",
|
||||||
|
"hclk",
|
||||||
|
"dclk_vp0",
|
||||||
|
"dclk_vp1",
|
||||||
|
"dclk_vp2",
|
||||||
|
"dclk_vp3",
|
||||||
|
- "pclk_vop";
|
||||||
|
+ "pclk_vop",
|
||||||
|
+ "pll_hdmiphy0";
|
||||||
|
iommus = <&vop_mmu>;
|
||||||
|
power-domains = <&power RK3588_PD_VOP>;
|
||||||
|
rockchip,grf = <&sys_grf>;
|
||||||
|
@@ -1254,6 +1272,48 @@
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hdmi0: hdmi@fde80000 {
|
||||||
|
+ compatible = "rockchip,rk3588-dw-hdmi-qp";
|
||||||
|
+ reg = <0x0 0xfde80000 0x0 0x20000>;
|
||||||
|
+ clocks = <&cru PCLK_HDMITX0>,
|
||||||
|
+ <&cru CLK_HDMITX0_EARC>,
|
||||||
|
+ <&cru CLK_HDMITX0_REF>,
|
||||||
|
+ <&cru MCLK_I2S5_8CH_TX>,
|
||||||
|
+ <&cru CLK_HDMIHDP0>,
|
||||||
|
+ <&cru HCLK_VO1>;
|
||||||
|
+ clock-names = "pclk", "earc", "ref", "aud", "hdp", "hclk_vo1";
|
||||||
|
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||||
|
+ interrupt-names = "avp", "cec", "earc", "main", "hpd";
|
||||||
|
+ phys = <&hdptxphy0>;
|
||||||
|
+ pinctrl-names = "default";
|
||||||
|
+ pinctrl-0 = <&hdmim0_tx0_cec &hdmim0_tx0_hpd
|
||||||
|
+ &hdmim0_tx0_scl &hdmim0_tx0_sda>;
|
||||||
|
+ power-domains = <&power RK3588_PD_VO1>;
|
||||||
|
+ resets = <&cru SRST_HDMITX0_REF>, <&cru SRST_HDMIHDP0>;
|
||||||
|
+ reset-names = "ref", "hdp";
|
||||||
|
+ rockchip,grf = <&sys_grf>;
|
||||||
|
+ rockchip,vo-grf = <&vo1_grf>;
|
||||||
|
+ #sound-dai-cells = <0>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ ports {
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+
|
||||||
|
+ hdmi0_in: port@0 {
|
||||||
|
+ reg = <0>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ hdmi0_out: port@1 {
|
||||||
|
+ reg = <1>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
qos_gpu_m0: qos@fdf35000 {
|
||||||
|
compatible = "rockchip,rk3588-qos", "syscon";
|
||||||
|
reg = <0x0 0xfdf35000 0x0 0x20>;
|
||||||
|
@@ -2657,11 +2717,12 @@
|
||||||
|
#dma-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
- hdptxphy_hdmi0: phy@fed60000 {
|
||||||
|
+ hdptxphy0: phy@fed60000 {
|
||||||
|
compatible = "rockchip,rk3588-hdptx-phy";
|
||||||
|
reg = <0x0 0xfed60000 0x0 0x2000>;
|
||||||
|
clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX0>;
|
||||||
|
clock-names = "ref", "apb";
|
||||||
|
+ #clock-cells = <0>;
|
||||||
|
#phy-cells = <0>;
|
||||||
|
resets = <&cru SRST_HDPTX0>, <&cru SRST_P_HDPTX0>,
|
||||||
|
<&cru SRST_HDPTX0_INIT>, <&cru SRST_HDPTX0_CMN>,
|
||||||
|
--- a/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
|
||||||
|
+++ b/arch/arm64/boot/dts/rockchip/rk3588-extra.dtsi
|
||||||
|
@@ -7,6 +7,46 @@
|
||||||
|
#include "rk3588-extra-pinctrl.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
+ hdmi1_sound: hdmi1-sound {
|
||||||
|
+ compatible = "simple-audio-card";
|
||||||
|
+ simple-audio-card,format = "i2s";
|
||||||
|
+ simple-audio-card,mclk-fs = <128>;
|
||||||
|
+ simple-audio-card,name = "hdmi1";
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ simple-audio-card,codec {
|
||||||
|
+ sound-dai = <&hdmi1>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ simple-audio-card,cpu {
|
||||||
|
+ sound-dai = <&i2s6_8ch>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ reserved-memory {
|
||||||
|
+ #address-cells = <2>;
|
||||||
|
+ #size-cells = <2>;
|
||||||
|
+ ranges;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The 4k HDMI capture controller works only with 32bit
|
||||||
|
+ * phys addresses and doesn't support IOMMU. HDMI RX CMA
|
||||||
|
+ * must be reserved below 4GB.
|
||||||
|
+ * The size of 160MB was determined as follows:
|
||||||
|
+ * (3840 * 2160 pixels) * (4 bytes/pixel) * (2 frames/buffer) / 10^6 = 66MB
|
||||||
|
+ * To ensure sufficient support for practical use-cases,
|
||||||
|
+ * we doubled the 66MB value.
|
||||||
|
+ */
|
||||||
|
+ hdmi_receiver_cma: hdmi-receiver-cma {
|
||||||
|
+ compatible = "shared-dma-pool";
|
||||||
|
+ alloc-ranges = <0x0 0x0 0x0 0xffffffff>;
|
||||||
|
+ size = <0x0 (160 * 0x100000)>; /* 160MiB */
|
||||||
|
+ alignment = <0x0 0x40000>; /* 64K */
|
||||||
|
+ no-map;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usb_host1_xhci: usb@fc400000 {
|
||||||
|
compatible = "rockchip,rk3588-dwc3", "snps,dwc3";
|
||||||
|
reg = <0x0 0xfc400000 0x0 0x400000>;
|
||||||
|
@@ -67,6 +107,11 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hdptxphy1_grf: syscon@fd5e4000 {
|
||||||
|
+ compatible = "rockchip,rk3588-hdptxphy-grf", "syscon";
|
||||||
|
+ reg = <0x0 0xfd5e4000 0x0 0x100>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
i2s8_8ch: i2s@fddc8000 {
|
||||||
|
compatible = "rockchip,rk3588-i2s-tdm";
|
||||||
|
reg = <0x0 0xfddc8000 0x0 0x1000>;
|
||||||
|
@@ -135,6 +180,79 @@
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hdmi1: hdmi@fdea0000 {
|
||||||
|
+ compatible = "rockchip,rk3588-dw-hdmi-qp";
|
||||||
|
+ reg = <0x0 0xfdea0000 0x0 0x20000>;
|
||||||
|
+ clocks = <&cru PCLK_HDMITX1>,
|
||||||
|
+ <&cru CLK_HDMITX1_EARC>,
|
||||||
|
+ <&cru CLK_HDMITX1_REF>,
|
||||||
|
+ <&cru MCLK_I2S6_8CH_TX>,
|
||||||
|
+ <&cru CLK_HDMIHDP1>,
|
||||||
|
+ <&cru HCLK_VO1>;
|
||||||
|
+ clock-names = "pclk", "earc", "ref", "aud", "hdp", "hclk_vo1";
|
||||||
|
+ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||||
|
+ interrupt-names = "avp", "cec", "earc", "main", "hpd";
|
||||||
|
+ phys = <&hdptxphy1>;
|
||||||
|
+ pinctrl-names = "default";
|
||||||
|
+ pinctrl-0 = <&hdmim2_tx1_cec &hdmim0_tx1_hpd
|
||||||
|
+ &hdmim1_tx1_scl &hdmim1_tx1_sda>;
|
||||||
|
+ power-domains = <&power RK3588_PD_VO1>;
|
||||||
|
+ resets = <&cru SRST_HDMITX1_REF>, <&cru SRST_HDMIHDP1>;
|
||||||
|
+ reset-names = "ref", "hdp";
|
||||||
|
+ rockchip,grf = <&sys_grf>;
|
||||||
|
+ rockchip,vo-grf = <&vo1_grf>;
|
||||||
|
+ #sound-dai-cells = <0>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+
|
||||||
|
+ ports {
|
||||||
|
+ #address-cells = <1>;
|
||||||
|
+ #size-cells = <0>;
|
||||||
|
+
|
||||||
|
+ hdmi1_in: port@0 {
|
||||||
|
+ reg = <0>;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ hdmi1_out: port@1 {
|
||||||
|
+ reg = <1>;
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ hdmi_receiver: hdmi_receiver@fdee0000 {
|
||||||
|
+ compatible = "rockchip,rk3588-hdmirx-ctrler", "snps,dw-hdmi-rx";
|
||||||
|
+ reg = <0x0 0xfdee0000 0x0 0x6000>;
|
||||||
|
+ interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH 0>,
|
||||||
|
+ <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||||
|
+ interrupt-names = "cec", "hdmi", "dma";
|
||||||
|
+ clocks = <&cru ACLK_HDMIRX>,
|
||||||
|
+ <&cru CLK_HDMIRX_AUD>,
|
||||||
|
+ <&cru CLK_CR_PARA>,
|
||||||
|
+ <&cru PCLK_HDMIRX>,
|
||||||
|
+ <&cru CLK_HDMIRX_REF>,
|
||||||
|
+ <&cru PCLK_S_HDMIRX>,
|
||||||
|
+ <&cru HCLK_VO1>;
|
||||||
|
+ clock-names = "aclk",
|
||||||
|
+ "audio",
|
||||||
|
+ "cr_para",
|
||||||
|
+ "pclk",
|
||||||
|
+ "ref",
|
||||||
|
+ "hclk_s_hdmirx",
|
||||||
|
+ "hclk_vo1";
|
||||||
|
+ memory-region = <&hdmi_receiver_cma>;
|
||||||
|
+ power-domains = <&power RK3588_PD_VO1>;
|
||||||
|
+ resets = <&cru SRST_A_HDMIRX>, <&cru SRST_P_HDMIRX>,
|
||||||
|
+ <&cru SRST_HDMIRX_REF>, <&cru SRST_A_HDMIRX_BIU>;
|
||||||
|
+ reset-names = "axi", "apb", "ref", "biu";
|
||||||
|
+ rockchip,grf = <&sys_grf>;
|
||||||
|
+ rockchip,vo1-grf = <&vo1_grf>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
pcie3x4: pcie@fe150000 {
|
||||||
|
compatible = "rockchip,rk3588-pcie", "rockchip,rk3568-pcie";
|
||||||
|
#address-cells = <3>;
|
||||||
|
@@ -360,6 +478,23 @@
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
+ hdptxphy1: phy@fed70000 {
|
||||||
|
+ compatible = "rockchip,rk3588-hdptx-phy";
|
||||||
|
+ reg = <0x0 0xfed70000 0x0 0x2000>;
|
||||||
|
+ clocks = <&cru CLK_USB2PHY_HDPTXRXPHY_REF>, <&cru PCLK_HDPTX1>;
|
||||||
|
+ clock-names = "ref", "apb";
|
||||||
|
+ #clock-cells = <0>;
|
||||||
|
+ #phy-cells = <0>;
|
||||||
|
+ resets = <&cru SRST_HDPTX1>, <&cru SRST_P_HDPTX1>,
|
||||||
|
+ <&cru SRST_HDPTX1_INIT>, <&cru SRST_HDPTX1_CMN>,
|
||||||
|
+ <&cru SRST_HDPTX1_LANE>, <&cru SRST_HDPTX1_ROPLL>,
|
||||||
|
+ <&cru SRST_HDPTX1_LCPLL>;
|
||||||
|
+ reset-names = "phy", "apb", "init", "cmn", "lane", "ropll",
|
||||||
|
+ "lcpll";
|
||||||
|
+ rockchip,grf = <&hdptxphy1_grf>;
|
||||||
|
+ status = "disabled";
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
usbdp_phy1: phy@fed90000 {
|
||||||
|
compatible = "rockchip,rk3588-usbdp-phy";
|
||||||
|
reg = <0x0 0xfed90000 0x0 0x10000>;
|
||||||
|
@@ -411,3 +546,24 @@
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
+
|
||||||
|
+&vop {
|
||||||
|
+ clocks = <&cru ACLK_VOP>,
|
||||||
|
+ <&cru HCLK_VOP>,
|
||||||
|
+ <&cru DCLK_VOP0>,
|
||||||
|
+ <&cru DCLK_VOP1>,
|
||||||
|
+ <&cru DCLK_VOP2>,
|
||||||
|
+ <&cru DCLK_VOP3>,
|
||||||
|
+ <&cru PCLK_VOP_ROOT>,
|
||||||
|
+ <&hdptxphy0>,
|
||||||
|
+ <&hdptxphy1>;
|
||||||
|
+ clock-names = "aclk",
|
||||||
|
+ "hclk",
|
||||||
|
+ "dclk_vp0",
|
||||||
|
+ "dclk_vp1",
|
||||||
|
+ "dclk_vp2",
|
||||||
|
+ "dclk_vp3",
|
||||||
|
+ "pclk_vop",
|
||||||
|
+ "pll_hdmiphy0",
|
||||||
|
+ "pll_hdmiphy1";
|
||||||
|
+};
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
--- a/drivers/phy/rockchip/Kconfig
|
||||||
|
+++ b/drivers/phy/rockchip/Kconfig
|
||||||
|
@@ -91,6 +91,18 @@ config PHY_ROCKCHIP_PCIE
|
||||||
|
help
|
||||||
|
Enable this to support the Rockchip PCIe PHY.
|
||||||
|
|
||||||
|
+config PHY_ROCKCHIP_SAMSUNG_HDPTX
|
||||||
|
+ tristate "Rockchip Samsung HDMI/eDP Combo PHY driver"
|
||||||
|
+ depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
|
||||||
|
+ depends on COMMON_CLK
|
||||||
|
+ depends on HAS_IOMEM
|
||||||
|
+ select GENERIC_PHY
|
||||||
|
+ select MFD_SYSCON
|
||||||
|
+ select RATIONAL
|
||||||
|
+ help
|
||||||
|
+ Enable this to support the Rockchip HDMI/eDP Combo PHY
|
||||||
|
+ with Samsung IP block.
|
||||||
|
+
|
||||||
|
config PHY_ROCKCHIP_SNPS_PCIE3
|
||||||
|
tristate "Rockchip Snps PCIe3 PHY Driver"
|
||||||
|
depends on (ARCH_ROCKCHIP && OF) || COMPILE_TEST
|
||||||
|
--- a/drivers/phy/rockchip/Makefile
|
||||||
|
+++ b/drivers/phy/rockchip/Makefile
|
||||||
|
@@ -9,6 +9,7 @@ obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) +=
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB3) += phy-rockchip-inno-usb3.o
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY) += phy-rockchip-naneng-combphy.o
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
|
||||||
|
+obj-$(CONFIG_PHY_ROCKCHIP_SAMSUNG_HDPTX) += phy-rockchip-samsung-hdptx.o
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
|
||||||
|
obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
From bf34d14a2d506e4f94e57f70861b45cb2b9e85dc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||||
|
Date: Thu, 6 Mar 2025 20:29:23 +0100
|
||||||
|
Subject: [PATCH 01/11] phy: phy-rockchip-samsung-hdptx: Add support for RK3576
|
||||||
|
|
||||||
|
Despite the compatible already being listed in the bindings, the PHY
|
||||||
|
driver never gained explicit support for it. This is especially a
|
||||||
|
problem because the explicitly listed PHY addresses need to be specified
|
||||||
|
for each SoC.
|
||||||
|
|
||||||
|
To solve this, add the compatible, and a PHY config, with the address
|
||||||
|
gleaned from rk3576.dtsi.
|
||||||
|
|
||||||
|
Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
|
||||||
|
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Reviewed-by: Heiko Stuebner <heiko@sntech.de>
|
||||||
|
Link: https://lore.kernel.org/r/20250306-rk3576-hdptx-phy-v1-1-288cc4b0611a@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index c3c8bd23beae..d793454a7512 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -1159,6 +1159,13 @@ static const struct dev_pm_ops rk_hdptx_phy_pm_ops = {
|
||||||
|
rk_hdptx_phy_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
|
+static const struct rk_hdptx_phy_cfg rk3576_hdptx_phy_cfgs = {
|
||||||
|
+ .num_phys = 1,
|
||||||
|
+ .phy_ids = {
|
||||||
|
+ 0x2b000000,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = {
|
||||||
|
.num_phys = 2,
|
||||||
|
.phy_ids = {
|
||||||
|
@@ -1168,6 +1175,10 @@ static const struct rk_hdptx_phy_cfg rk3588_hdptx_phy_cfgs = {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id rk_hdptx_phy_of_match[] = {
|
||||||
|
+ {
|
||||||
|
+ .compatible = "rockchip,rk3576-hdptx-phy",
|
||||||
|
+ .data = &rk3576_hdptx_phy_cfgs
|
||||||
|
+ },
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rk3588-hdptx-phy",
|
||||||
|
.data = &rk3588_hdptx_phy_cfgs
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
From ff2555a62e27661472f2777b976eeefed4e06ee8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:37 +0200
|
||||||
|
Subject: [PATCH 02/11] phy: rockchip: samsung-hdptx: Fix clock ratio setup
|
||||||
|
|
||||||
|
The switch from 1/10 to 1/40 clock ratio must happen when exceeding the
|
||||||
|
340 MHz rate limit of HDMI 1.4, i.e. when entering the HDMI 2.0 domain,
|
||||||
|
and not before.
|
||||||
|
|
||||||
|
Therefore, use the correct comparison operator '>' instead of '>=' when
|
||||||
|
checking the max rate. While at it, introduce a define for this rate
|
||||||
|
limit constant.
|
||||||
|
|
||||||
|
Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
|
||||||
|
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-3-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index d793454a7512..2e1c50b2895d 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -192,6 +192,7 @@
|
||||||
|
#define LN3_TX_SER_RATE_SEL_HBR2_MASK BIT(3)
|
||||||
|
#define LN3_TX_SER_RATE_SEL_HBR3_MASK BIT(2)
|
||||||
|
|
||||||
|
+#define HDMI14_MAX_RATE 340000000
|
||||||
|
#define HDMI20_MAX_RATE 600000000
|
||||||
|
|
||||||
|
struct lcpll_config {
|
||||||
|
@@ -837,7 +838,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
|
||||||
|
regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
|
||||||
|
|
||||||
|
- if (rate >= 3400000) {
|
||||||
|
+ if (rate > HDMI14_MAX_RATE / 100) {
|
||||||
|
/* For 1/40 bitrate clk */
|
||||||
|
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
|
||||||
|
} else {
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
From 9d47e7deb8f1d42c220afb43ff965a4b11f6c7dc Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:38 +0200
|
||||||
|
Subject: [PATCH 03/11] phy: rockchip: samsung-hdptx: Do no set
|
||||||
|
rk_hdptx_phy->rate in case of errors
|
||||||
|
|
||||||
|
Ensure rk_hdptx_ropll_tmds_cmn_config() updates hdptx->rate only after
|
||||||
|
all the other operations have been successful.
|
||||||
|
|
||||||
|
Fixes: c4b09c562086 ("phy: phy-rockchip-samsung-hdptx: Add clock provider support")
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-4-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 10 ++++++----
|
||||||
|
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 2e1c50b2895d..6a062e509a01 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -771,9 +771,7 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
{
|
||||||
|
const struct ropll_config *cfg = NULL;
|
||||||
|
struct ropll_config rc = {0};
|
||||||
|
- int i;
|
||||||
|
-
|
||||||
|
- hdptx->rate = rate * 100;
|
||||||
|
+ int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
|
||||||
|
if (rate == ropll_tmds_cfg[i].bit_rate) {
|
||||||
|
@@ -828,7 +826,11 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
regmap_update_bits(hdptx->regmap, CMN_REG(0086), PLL_PCG_CLK_EN_MASK,
|
||||||
|
FIELD_PREP(PLL_PCG_CLK_EN_MASK, 0x1));
|
||||||
|
|
||||||
|
- return rk_hdptx_post_enable_pll(hdptx);
|
||||||
|
+ ret = rk_hdptx_post_enable_pll(hdptx);
|
||||||
|
+ if (!ret)
|
||||||
|
+ hdptx->rate = rate * 100;
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
From 23261a7c4c546ae151344efa5bbf0c8a6b8806f6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:39 +0200
|
||||||
|
Subject: [PATCH 04/11] phy: rockchip: samsung-hdptx: Drop unused struct
|
||||||
|
lcpll_config
|
||||||
|
|
||||||
|
This is just a leftover from downstream support for HDMI 2.1.
|
||||||
|
Remove the unused struct for now.
|
||||||
|
|
||||||
|
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-5-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 31 -------------------
|
||||||
|
1 file changed, 31 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 6a062e509a01..59d7ced84032 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -195,37 +195,6 @@
|
||||||
|
#define HDMI14_MAX_RATE 340000000
|
||||||
|
#define HDMI20_MAX_RATE 600000000
|
||||||
|
|
||||||
|
-struct lcpll_config {
|
||||||
|
- u32 bit_rate;
|
||||||
|
- u8 lcvco_mode_en;
|
||||||
|
- u8 pi_en;
|
||||||
|
- u8 clk_en_100m;
|
||||||
|
- u8 pms_mdiv;
|
||||||
|
- u8 pms_mdiv_afc;
|
||||||
|
- u8 pms_pdiv;
|
||||||
|
- u8 pms_refdiv;
|
||||||
|
- u8 pms_sdiv;
|
||||||
|
- u8 pi_cdiv_rstn;
|
||||||
|
- u8 pi_cdiv_sel;
|
||||||
|
- u8 sdm_en;
|
||||||
|
- u8 sdm_rstn;
|
||||||
|
- u8 sdc_frac_en;
|
||||||
|
- u8 sdc_rstn;
|
||||||
|
- u8 sdm_deno;
|
||||||
|
- u8 sdm_num_sign;
|
||||||
|
- u8 sdm_num;
|
||||||
|
- u8 sdc_n;
|
||||||
|
- u8 sdc_n2;
|
||||||
|
- u8 sdc_num;
|
||||||
|
- u8 sdc_deno;
|
||||||
|
- u8 sdc_ndiv_rstn;
|
||||||
|
- u8 ssc_en;
|
||||||
|
- u8 ssc_fm_dev;
|
||||||
|
- u8 ssc_fm_freq;
|
||||||
|
- u8 ssc_clk_div_sel;
|
||||||
|
- u8 cd_tx_ser_rate_sel;
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
struct ropll_config {
|
||||||
|
u32 bit_rate;
|
||||||
|
u8 pms_mdiv;
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
From a51cb3b76218a09777c62b8421ba1aab569f51ff Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:40 +0200
|
||||||
|
Subject: [PATCH 05/11] phy: rockchip: samsung-hdptx: Drop unused phy_cfg
|
||||||
|
driver data
|
||||||
|
|
||||||
|
There is no usage of phy_cfg in the upstream driver data, nor in the
|
||||||
|
downstream one, hence remove it.
|
||||||
|
|
||||||
|
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-6-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 1 -
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 59d7ced84032..4e082ab31cae 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -250,7 +250,6 @@ struct rk_hdptx_phy {
|
||||||
|
int phy_id;
|
||||||
|
|
||||||
|
struct phy *phy;
|
||||||
|
- struct phy_config *phy_cfg;
|
||||||
|
struct clk_bulk_data *clks;
|
||||||
|
int nr_clks;
|
||||||
|
struct reset_control_bulk_data rsts[RST_MAX];
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
From 7562f48e8f344af19a71d0a6c626bc16f22e6ad3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:41 +0200
|
||||||
|
Subject: [PATCH 06/11] phy: rockchip: samsung-hdptx: Drop superfluous cfgs
|
||||||
|
driver data
|
||||||
|
|
||||||
|
The ->cfgs member has been introduced via commit f08d1c085638 ("phy:
|
||||||
|
phy-rockchip-samsung-hdptx: Don't use dt aliases to determine phy-id"),
|
||||||
|
but it is only used during probe() in order to setup ->phy_id.
|
||||||
|
|
||||||
|
Use a probe() local variable to store device match data and remove the
|
||||||
|
now unnecessary member from struct rk_hdptx_phy.
|
||||||
|
|
||||||
|
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-7-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 12 +++++-------
|
||||||
|
1 file changed, 5 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 4e082ab31cae..de333b743810 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -245,10 +245,7 @@ struct rk_hdptx_phy {
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct regmap *grf;
|
||||||
|
|
||||||
|
- /* PHY const config */
|
||||||
|
- const struct rk_hdptx_phy_cfg *cfgs;
|
||||||
|
int phy_id;
|
||||||
|
-
|
||||||
|
struct phy *phy;
|
||||||
|
struct clk_bulk_data *clks;
|
||||||
|
int nr_clks;
|
||||||
|
@@ -1036,6 +1033,7 @@ static int rk_hdptx_phy_runtime_resume(struct device *dev)
|
||||||
|
|
||||||
|
static int rk_hdptx_phy_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
+ const struct rk_hdptx_phy_cfg *cfgs;
|
||||||
|
struct phy_provider *phy_provider;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct rk_hdptx_phy *hdptx;
|
||||||
|
@@ -1054,14 +1052,14 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
|
||||||
|
return dev_err_probe(dev, PTR_ERR(regs),
|
||||||
|
"Failed to ioremap resource\n");
|
||||||
|
|
||||||
|
- hdptx->cfgs = device_get_match_data(dev);
|
||||||
|
- if (!hdptx->cfgs)
|
||||||
|
+ cfgs = device_get_match_data(dev);
|
||||||
|
+ if (!cfgs)
|
||||||
|
return dev_err_probe(dev, -EINVAL, "missing match data\n");
|
||||||
|
|
||||||
|
/* find the phy-id from the io address */
|
||||||
|
hdptx->phy_id = -ENODEV;
|
||||||
|
- for (id = 0; id < hdptx->cfgs->num_phys; id++) {
|
||||||
|
- if (res->start == hdptx->cfgs->phy_ids[id]) {
|
||||||
|
+ for (id = 0; id < cfgs->num_phys; id++) {
|
||||||
|
+ if (res->start == cfgs->phy_ids[id]) {
|
||||||
|
hdptx->phy_id = id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,241 @@
|
|||||||
|
From 85bc910629a9f31b879aeb4f1a1c5fa211406f4a Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:42 +0200
|
||||||
|
Subject: [PATCH 07/11] phy: rockchip: samsung-hdptx: Avoid Hz<->hHz unit
|
||||||
|
conversion overhead
|
||||||
|
|
||||||
|
The ropll_tmds_cfg table used to identify the configuration params for
|
||||||
|
the supported rates expects the search key, i.e. bit_rate member of
|
||||||
|
struct ropll_config, to be provided in hHz rather than Hz (1 hHz = 100
|
||||||
|
Hz). This requires multiple conversions between these units being
|
||||||
|
performed at runtime.
|
||||||
|
|
||||||
|
Improve implementation clarity and efficiency by consistently using the
|
||||||
|
Hz unit throughout driver's internal data structures and functions.
|
||||||
|
Also rename the rather misleading struct member.
|
||||||
|
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-8-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
.../phy/rockchip/phy-rockchip-samsung-hdptx.c | 79 +++++++++----------
|
||||||
|
1 file changed, 39 insertions(+), 40 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index de333b743810..36b01a2e414b 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -196,7 +196,7 @@
|
||||||
|
#define HDMI20_MAX_RATE 600000000
|
||||||
|
|
||||||
|
struct ropll_config {
|
||||||
|
- u32 bit_rate;
|
||||||
|
+ unsigned long long rate;
|
||||||
|
u8 pms_mdiv;
|
||||||
|
u8 pms_mdiv_afc;
|
||||||
|
u8 pms_pdiv;
|
||||||
|
@@ -259,45 +259,45 @@ struct rk_hdptx_phy {
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ropll_config ropll_tmds_cfg[] = {
|
||||||
|
- { 5940000, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 594000000ULL, 124, 124, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 3712500, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 371250000ULL, 155, 155, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 2970000, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 297000000ULL, 124, 124, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1620000, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
|
||||||
|
+ { 162000000ULL, 135, 135, 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, 4, 0, 3, 5, 5, 0x10,
|
||||||
|
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1856250, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 185625000ULL, 155, 155, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1540000, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
|
||||||
|
+ { 154000000ULL, 193, 193, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 193, 1, 32, 2, 1,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1485000, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
|
||||||
|
+ { 148500000ULL, 0x7b, 0x7b, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 4, 0, 3, 5, 5,
|
||||||
|
0x10, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1462500, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
|
||||||
|
+ { 146250000ULL, 122, 122, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 244, 1, 16, 2, 1, 1,
|
||||||
|
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1190000, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
|
||||||
|
+ { 119000000ULL, 149, 149, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 149, 1, 16, 2, 1, 1,
|
||||||
|
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1065000, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
|
||||||
|
+ { 106500000ULL, 89, 89, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 89, 1, 16, 1, 0, 1,
|
||||||
|
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 1080000, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
+ { 108000000ULL, 135, 135, 1, 1, 5, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 855000, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
|
||||||
|
+ { 85500000ULL, 214, 214, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 214, 1, 16, 2, 1,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 835000, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
|
||||||
|
+ { 83500000ULL, 105, 105, 1, 1, 5, 1, 1, 1, 1, 1, 1, 1, 42, 1, 16, 1, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 928125, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 92812500ULL, 155, 155, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 742500, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
+ { 74250000ULL, 124, 124, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 62, 1, 16, 5, 0,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 650000, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
|
||||||
|
+ { 65000000ULL, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 337500, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
|
||||||
|
+ { 33750000ULL, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
|
||||||
|
1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 400000, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
+ { 40000000ULL, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 270000, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
+ { 27000000ULL, 0x5a, 0x5a, 1, 1, 0xf, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
0x14, 0x18, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
- { 251750, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
|
||||||
|
+ { 25175000ULL, 84, 84, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 168, 1, 16, 4, 1, 1,
|
||||||
|
1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -659,10 +659,10 @@ static void rk_hdptx_phy_disable(struct rk_hdptx_phy *hdptx)
|
||||||
|
regmap_write(hdptx->grf, GRF_HDPTX_CON0, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
|
||||||
|
+static bool rk_hdptx_phy_clk_pll_calc(unsigned long long rate,
|
||||||
|
struct ropll_config *cfg)
|
||||||
|
{
|
||||||
|
- const unsigned int fout = data_rate / 2, fref = 24000;
|
||||||
|
+ const unsigned int fout = div_u64(rate, 200), fref = 24000;
|
||||||
|
unsigned long k = 0, lc, k_sub, lc_sub;
|
||||||
|
unsigned int fvco, sdc;
|
||||||
|
u32 mdiv, sdiv, n = 8;
|
||||||
|
@@ -732,14 +732,14 @@ static bool rk_hdptx_phy_clk_pll_calc(unsigned int data_rate,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
- unsigned int rate)
|
||||||
|
+ unsigned long long rate)
|
||||||
|
{
|
||||||
|
const struct ropll_config *cfg = NULL;
|
||||||
|
struct ropll_config rc = {0};
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
|
||||||
|
- if (rate == ropll_tmds_cfg[i].bit_rate) {
|
||||||
|
+ if (rate == ropll_tmds_cfg[i].rate) {
|
||||||
|
cfg = &ropll_tmds_cfg[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -753,8 +753,8 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- dev_dbg(hdptx->dev, "mdiv=%u, sdiv=%u, sdm_en=%u, k_sign=%u, k=%u, lc=%u\n",
|
||||||
|
- cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
|
||||||
|
+ dev_dbg(hdptx->dev, "%s rate=%llu mdiv=%u sdiv=%u sdm_en=%u k_sign=%u k=%u lc=%u\n",
|
||||||
|
+ __func__, rate, cfg->pms_mdiv, cfg->pms_sdiv + 1, cfg->sdm_en,
|
||||||
|
cfg->sdm_num_sign, cfg->sdm_num, cfg->sdm_deno);
|
||||||
|
|
||||||
|
rk_hdptx_pre_power_up(hdptx);
|
||||||
|
@@ -793,19 +793,19 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
|
||||||
|
ret = rk_hdptx_post_enable_pll(hdptx);
|
||||||
|
if (!ret)
|
||||||
|
- hdptx->rate = rate * 100;
|
||||||
|
+ hdptx->rate = rate;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
- unsigned int rate)
|
||||||
|
+ unsigned long long rate)
|
||||||
|
{
|
||||||
|
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_common_sb_init_seq);
|
||||||
|
|
||||||
|
regmap_write(hdptx->regmap, LNTOP_REG(0200), 0x06);
|
||||||
|
|
||||||
|
- if (rate > HDMI14_MAX_RATE / 100) {
|
||||||
|
+ if (rate > HDMI14_MAX_RATE) {
|
||||||
|
/* For 1/40 bitrate clk */
|
||||||
|
rk_hdptx_multi_reg_write(hdptx, rk_hdtpx_tmds_lntop_highbr_seq);
|
||||||
|
} else {
|
||||||
|
@@ -823,7 +823,7 @@ static int rk_hdptx_ropll_tmds_mode_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rk_hdptx_phy_consumer_get(struct rk_hdptx_phy *hdptx,
|
||||||
|
- unsigned int rate)
|
||||||
|
+ unsigned long long rate)
|
||||||
|
{
|
||||||
|
u32 status;
|
||||||
|
int ret;
|
||||||
|
@@ -881,7 +881,7 @@ static int rk_hdptx_phy_consumer_put(struct rk_hdptx_phy *hdptx, bool force)
|
||||||
|
static int rk_hdptx_phy_power_on(struct phy *phy)
|
||||||
|
{
|
||||||
|
struct rk_hdptx_phy *hdptx = phy_get_drvdata(phy);
|
||||||
|
- int bus_width = phy_get_bus_width(hdptx->phy);
|
||||||
|
+ unsigned long long rate;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -889,10 +889,10 @@ static int rk_hdptx_phy_power_on(struct phy *phy)
|
||||||
|
* from the HDMI bridge driver until phy_configure_opts_hdmi
|
||||||
|
* becomes available in the PHY API.
|
||||||
|
*/
|
||||||
|
- unsigned int rate = bus_width & 0xfffffff;
|
||||||
|
+ rate = phy_get_bus_width(hdptx->phy) & 0xfffffff;
|
||||||
|
+ rate *= 100;
|
||||||
|
|
||||||
|
- dev_dbg(hdptx->dev, "%s bus_width=%x rate=%u\n",
|
||||||
|
- __func__, bus_width, rate);
|
||||||
|
+ dev_dbg(hdptx->dev, "%s rate=%llu\n", __func__, rate);
|
||||||
|
|
||||||
|
ret = rk_hdptx_phy_consumer_get(hdptx, rate);
|
||||||
|
if (ret)
|
||||||
|
@@ -927,7 +927,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
|
||||||
|
|
||||||
|
- return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate / 100);
|
||||||
|
+ return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
|
||||||
|
@@ -948,18 +948,17 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
|
||||||
|
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *parent_rate)
|
||||||
|
{
|
||||||
|
- u32 bit_rate = rate / 100;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (rate > HDMI20_MAX_RATE)
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ropll_tmds_cfg); i++)
|
||||||
|
- if (bit_rate == ropll_tmds_cfg[i].bit_rate)
|
||||||
|
+ if (rate == ropll_tmds_cfg[i].rate)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (i == ARRAY_SIZE(ropll_tmds_cfg) &&
|
||||||
|
- !rk_hdptx_phy_clk_pll_calc(bit_rate, NULL))
|
||||||
|
+ !rk_hdptx_phy_clk_pll_calc(rate, NULL))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
@@ -970,7 +969,7 @@ static int rk_hdptx_phy_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
{
|
||||||
|
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
|
||||||
|
|
||||||
|
- return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate / 100);
|
||||||
|
+ return rk_hdptx_ropll_tmds_cmn_config(hdptx, rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops hdptx_phy_clk_ops = {
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
From beaf90d69c97acc54f1b20533650499c9ca8ab01 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 18 Mar 2025 14:35:46 +0200
|
||||||
|
Subject: [PATCH 08/11] phy: rockchip: samsung-hdptx: Rename ambiguous
|
||||||
|
rk_hdptx_phy->rate
|
||||||
|
|
||||||
|
The main purpose of the ->rate member of struct rk_hdptx_phy is to
|
||||||
|
implement rk_hdptx_phy_clk_recalc_rate() by providing the actual rate
|
||||||
|
programmed in hardware. Hence the current naming is too generic and
|
||||||
|
rather ambiguous.
|
||||||
|
|
||||||
|
Improve clarity by renaming ->rate to ->hw_rate.
|
||||||
|
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Link: https://lore.kernel.org/r/20250318-phy-sam-hdptx-bpc-v6-12-8cb1678e7663@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 8 ++++----
|
||||||
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 36b01a2e414b..4c713616963a 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -253,7 +253,7 @@ struct rk_hdptx_phy {
|
||||||
|
|
||||||
|
/* clk provider */
|
||||||
|
struct clk_hw hw;
|
||||||
|
- unsigned long rate;
|
||||||
|
+ unsigned long hw_rate;
|
||||||
|
|
||||||
|
atomic_t usage_count;
|
||||||
|
};
|
||||||
|
@@ -793,7 +793,7 @@ static int rk_hdptx_ropll_tmds_cmn_config(struct rk_hdptx_phy *hdptx,
|
||||||
|
|
||||||
|
ret = rk_hdptx_post_enable_pll(hdptx);
|
||||||
|
if (!ret)
|
||||||
|
- hdptx->rate = rate;
|
||||||
|
+ hdptx->hw_rate = rate;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -927,7 +927,7 @@ static int rk_hdptx_phy_clk_prepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
|
||||||
|
|
||||||
|
- return rk_hdptx_phy_consumer_get(hdptx, hdptx->rate);
|
||||||
|
+ return rk_hdptx_phy_consumer_get(hdptx, hdptx->hw_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rk_hdptx_phy_clk_unprepare(struct clk_hw *hw)
|
||||||
|
@@ -942,7 +942,7 @@ static unsigned long rk_hdptx_phy_clk_recalc_rate(struct clk_hw *hw,
|
||||||
|
{
|
||||||
|
struct rk_hdptx_phy *hdptx = to_rk_hdptx_phy(hw);
|
||||||
|
|
||||||
|
- return hdptx->rate;
|
||||||
|
+ return hdptx->hw_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long rk_hdptx_phy_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
From 36afb795a27c8631a2e34ba1b761f0435eaaed25 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Date: Sun, 27 Apr 2025 17:51:24 +0800
|
||||||
|
Subject: [PATCH 09/11] phy: phy-rockchip-samsung-hdptx: Fix PHY PLL output
|
||||||
|
50.25MHz error
|
||||||
|
|
||||||
|
When using HDMI PLL frequency division coefficient at 50.25MHz
|
||||||
|
that is calculated by rk_hdptx_phy_clk_pll_calc(), it fails to
|
||||||
|
get PHY LANE lock. Although the calculated values are within the
|
||||||
|
allowable range of PHY PLL configuration.
|
||||||
|
|
||||||
|
In order to fix the PHY LANE lock error and provide the expected
|
||||||
|
50.25MHz output, manually compute the required PHY PLL frequency
|
||||||
|
division coefficient and add it to ropll_tmds_cfg configuration
|
||||||
|
table.
|
||||||
|
|
||||||
|
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Reviewed-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Acked-by: Heiko Stuebner <heiko@sntech.de>
|
||||||
|
Link: https://lore.kernel.org/r/20250427095124.3354439-1-algea.cao@rock-chips.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index 4c713616963a..be504439c767 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -291,6 +291,8 @@ static const struct ropll_config ropll_tmds_cfg[] = {
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
{ 65000000ULL, 162, 162, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 54, 0, 16, 4, 1,
|
||||||
|
1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
+ { 50250000ULL, 84, 84, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 11, 1, 4, 5,
|
||||||
|
+ 4, 11, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
{ 33750000ULL, 0x70, 0x70, 1, 1, 0xf, 1, 1, 1, 1, 1, 1, 1, 0x2, 0, 0x01, 5,
|
||||||
|
1, 1, 1, 0, 0x20, 0x0c, 1, 0x0e, 0, 0, },
|
||||||
|
{ 40000000ULL, 100, 100, 1, 1, 11, 1, 1, 0, 1, 0, 1, 1, 0x9, 0, 0x05, 0,
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
From 6bde631bd5caf3a5b6719c535d62b96fbd068a5e Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 28 Oct 2025 10:00:55 +0200
|
||||||
|
Subject: [PATCH 10/11] phy: rockchip: samsung-hdptx: Reduce ROPLL loop
|
||||||
|
bandwidth
|
||||||
|
|
||||||
|
Due to its relatively low frequency, a noise stemming from the 24MHz PLL
|
||||||
|
reference clock may traverse the low-pass loop filter of ROPLL, which
|
||||||
|
could potentially generate some HDMI flash artifacts.
|
||||||
|
|
||||||
|
Reduce ROPLL loop bandwidth in an attempt to mitigate the problem.
|
||||||
|
|
||||||
|
Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
|
||||||
|
Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
|
||||||
|
Link: https://patch.msgid.link/20251028-phy-hdptx-fixes-v1-2-ecc642a59d94@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 4 ++--
|
||||||
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index be504439c767..bdc52495774d 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -347,9 +347,7 @@ static const struct reg_sequence rk_hdtpx_common_cmn_init_seq[] = {
|
||||||
|
REG_SEQ0(CMN_REG(0043), 0x00),
|
||||||
|
REG_SEQ0(CMN_REG(0044), 0x46),
|
||||||
|
REG_SEQ0(CMN_REG(0045), 0x24),
|
||||||
|
- REG_SEQ0(CMN_REG(0046), 0xff),
|
||||||
|
REG_SEQ0(CMN_REG(0047), 0x00),
|
||||||
|
- REG_SEQ0(CMN_REG(0048), 0x44),
|
||||||
|
REG_SEQ0(CMN_REG(0049), 0xfa),
|
||||||
|
REG_SEQ0(CMN_REG(004a), 0x08),
|
||||||
|
REG_SEQ0(CMN_REG(004b), 0x00),
|
||||||
|
@@ -422,6 +420,8 @@ static const struct reg_sequence rk_hdtpx_tmds_cmn_init_seq[] = {
|
||||||
|
REG_SEQ0(CMN_REG(0034), 0x00),
|
||||||
|
REG_SEQ0(CMN_REG(003d), 0x40),
|
||||||
|
REG_SEQ0(CMN_REG(0042), 0x78),
|
||||||
|
+ REG_SEQ0(CMN_REG(0046), 0xdd),
|
||||||
|
+ REG_SEQ0(CMN_REG(0048), 0x11),
|
||||||
|
REG_SEQ0(CMN_REG(004e), 0x34),
|
||||||
|
REG_SEQ0(CMN_REG(005c), 0x25),
|
||||||
|
REG_SEQ0(CMN_REG(005e), 0x4f),
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
From 402fc28c3a92e42200b15d5fac63f78e7a50d2e8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Date: Tue, 28 Oct 2025 10:00:56 +0200
|
||||||
|
Subject: [PATCH 11/11] phy: rockchip: samsung-hdptx: Prevent Inter-Pair Skew
|
||||||
|
from exceeding the limits
|
||||||
|
|
||||||
|
Fixup PHY deskew FIFO to prevent the phase of D2 lane going ahead of
|
||||||
|
other lanes. It's worth noting this might only happen when dealing with
|
||||||
|
HDMI 2.0 rates.
|
||||||
|
|
||||||
|
Fixes: 553be2830c5f ("phy: rockchip: Add Samsung HDMI/eDP Combo PHY driver")
|
||||||
|
Co-developed-by: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
|
||||||
|
Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
|
||||||
|
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
|
||||||
|
Link: https://patch.msgid.link/20251028-phy-hdptx-fixes-v1-3-ecc642a59d94@collabora.com
|
||||||
|
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||||
|
---
|
||||||
|
drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c | 9 +++++----
|
||||||
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
index bdc52495774d..47c2a3811685 100644
|
||||||
|
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
|
||||||
|
@@ -515,13 +515,9 @@ static const struct reg_sequence rk_hdtpx_common_lane_init_seq[] = {
|
||||||
|
|
||||||
|
static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = {
|
||||||
|
REG_SEQ0(LANE_REG(0312), 0x00),
|
||||||
|
- REG_SEQ0(LANE_REG(031e), 0x00),
|
||||||
|
REG_SEQ0(LANE_REG(0412), 0x00),
|
||||||
|
- REG_SEQ0(LANE_REG(041e), 0x00),
|
||||||
|
REG_SEQ0(LANE_REG(0512), 0x00),
|
||||||
|
- REG_SEQ0(LANE_REG(051e), 0x00),
|
||||||
|
REG_SEQ0(LANE_REG(0612), 0x00),
|
||||||
|
- REG_SEQ0(LANE_REG(061e), 0x08),
|
||||||
|
REG_SEQ0(LANE_REG(0303), 0x2f),
|
||||||
|
REG_SEQ0(LANE_REG(0403), 0x2f),
|
||||||
|
REG_SEQ0(LANE_REG(0503), 0x2f),
|
||||||
|
@@ -534,6 +530,11 @@ static const struct reg_sequence rk_hdtpx_tmds_lane_init_seq[] = {
|
||||||
|
REG_SEQ0(LANE_REG(0406), 0x1c),
|
||||||
|
REG_SEQ0(LANE_REG(0506), 0x1c),
|
||||||
|
REG_SEQ0(LANE_REG(0606), 0x1c),
|
||||||
|
+ /* Keep Inter-Pair Skew in the limits */
|
||||||
|
+ REG_SEQ0(LANE_REG(031e), 0x02),
|
||||||
|
+ REG_SEQ0(LANE_REG(041e), 0x02),
|
||||||
|
+ REG_SEQ0(LANE_REG(051e), 0x02),
|
||||||
|
+ REG_SEQ0(LANE_REG(061e), 0x0a),
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool rk_hdptx_phy_is_rw_reg(struct device *dev, unsigned int reg)
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
|
|
||||||
@ -0,0 +1,258 @@
|
|||||||
|
--- a/drivers/gpu/drm/bridge/synopsys/Kconfig
|
||||||
|
+++ b/drivers/gpu/drm/bridge/synopsys/Kconfig
|
||||||
|
@@ -46,6 +46,14 @@ config DRM_DW_HDMI_CEC
|
||||||
|
Support the CE interface which is part of the Synopsys
|
||||||
|
Designware HDMI block.
|
||||||
|
|
||||||
|
+config DRM_DW_HDMI_QP
|
||||||
|
+ tristate
|
||||||
|
+ select DRM_DISPLAY_HDMI_HELPER
|
||||||
|
+ select DRM_DISPLAY_HDMI_STATE_HELPER
|
||||||
|
+ select DRM_DISPLAY_HELPER
|
||||||
|
+ select DRM_KMS_HELPER
|
||||||
|
+ select REGMAP_MMIO
|
||||||
|
+
|
||||||
|
config DRM_DW_MIPI_DSI
|
||||||
|
tristate
|
||||||
|
select DRM_KMS_HELPER
|
||||||
|
--- a/drivers/gpu/drm/bridge/synopsys/Makefile
|
||||||
|
+++ b/drivers/gpu/drm/bridge/synopsys/Makefile
|
||||||
|
@@ -5,4 +5,6 @@ obj-$(CONFIG_DRM_DW_HDMI_GP_AUDIO) += dw
|
||||||
|
obj-$(CONFIG_DRM_DW_HDMI_I2S_AUDIO) += dw-hdmi-i2s-audio.o
|
||||||
|
obj-$(CONFIG_DRM_DW_HDMI_CEC) += dw-hdmi-cec.o
|
||||||
|
|
||||||
|
+obj-$(CONFIG_DRM_DW_HDMI_QP) += dw-hdmi-qp.o
|
||||||
|
+
|
||||||
|
obj-$(CONFIG_DRM_DW_MIPI_DSI) += dw-mipi-dsi.o
|
||||||
|
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
||||||
|
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
||||||
|
@@ -17,7 +17,7 @@
|
||||||
|
|
||||||
|
#include <drm/bridge/dw_hdmi_qp.h>
|
||||||
|
#include <drm/display/drm_hdmi_helper.h>
|
||||||
|
-#include <drm/display/drm_hdmi_state_helper.h>
|
||||||
|
+//#include <drm/display/drm_hdmi_state_helper.h>
|
||||||
|
#include <drm/drm_atomic.h>
|
||||||
|
#include <drm/drm_atomic_helper.h>
|
||||||
|
#include <drm/drm_bridge.h>
|
||||||
|
@@ -292,89 +292,18 @@ static struct i2c_adapter *dw_hdmi_qp_i2
|
||||||
|
return adap;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int dw_hdmi_qp_config_avi_infoframe(struct dw_hdmi_qp *hdmi,
|
||||||
|
- const u8 *buffer, size_t len)
|
||||||
|
-{
|
||||||
|
- u32 val, i, j;
|
||||||
|
-
|
||||||
|
- if (len != HDMI_INFOFRAME_SIZE(AVI)) {
|
||||||
|
- dev_err(hdmi->dev, "failed to configure avi infoframe\n");
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- /*
|
||||||
|
- * DW HDMI QP IP uses a different byte format from standard AVI info
|
||||||
|
- * frames, though generally the bits are in the correct bytes.
|
||||||
|
- */
|
||||||
|
- val = buffer[1] << 8 | buffer[2] << 16;
|
||||||
|
- dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS0);
|
||||||
|
-
|
||||||
|
- for (i = 0; i < 4; i++) {
|
||||||
|
- for (j = 0; j < 4; j++) {
|
||||||
|
- if (i * 4 + j >= 14)
|
||||||
|
- break;
|
||||||
|
- if (!j)
|
||||||
|
- val = buffer[i * 4 + j + 3];
|
||||||
|
- val |= buffer[i * 4 + j + 3] << (8 * j);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_write(hdmi, val, PKT_AVI_CONTENTS1 + i * 4);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_mod(hdmi, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
|
||||||
|
- PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int dw_hdmi_qp_config_drm_infoframe(struct dw_hdmi_qp *hdmi,
|
||||||
|
- const u8 *buffer, size_t len)
|
||||||
|
-{
|
||||||
|
- u32 val, i;
|
||||||
|
-
|
||||||
|
- if (len != HDMI_INFOFRAME_SIZE(DRM)) {
|
||||||
|
- dev_err(hdmi->dev, "failed to configure drm infoframe\n");
|
||||||
|
- return -EINVAL;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
-
|
||||||
|
- val = buffer[1] << 8 | buffer[2] << 16;
|
||||||
|
- dw_hdmi_qp_write(hdmi, val, PKT_DRMI_CONTENTS0);
|
||||||
|
-
|
||||||
|
- for (i = 0; i <= buffer[2]; i++) {
|
||||||
|
- if (i % 4 == 0)
|
||||||
|
- val = buffer[3 + i];
|
||||||
|
- val |= buffer[3 + i] << ((i % 4) * 8);
|
||||||
|
-
|
||||||
|
- if ((i % 4 == 3) || i == buffer[2])
|
||||||
|
- dw_hdmi_qp_write(hdmi, val,
|
||||||
|
- PKT_DRMI_CONTENTS1 + ((i / 4) * 4));
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_FIELDRATE, PKTSCHED_PKT_CONFIG1);
|
||||||
|
- dw_hdmi_qp_mod(hdmi, PKTSCHED_DRMI_TX_EN, PKTSCHED_DRMI_TX_EN,
|
||||||
|
- PKTSCHED_PKT_EN);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int dw_hdmi_qp_bridge_atomic_check(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
- int ret;
|
||||||
|
|
||||||
|
- ret = drm_atomic_helper_connector_hdmi_check(conn_state->connector,
|
||||||
|
- conn_state->state);
|
||||||
|
- if (ret)
|
||||||
|
- dev_dbg(hdmi->dev, "%s failed: %d\n", __func__, ret);
|
||||||
|
+ dev_dbg(hdmi->dev, "input format 0x%04x, output format 0x%04x\n",
|
||||||
|
+ bridge_state->input_bus_cfg.format,
|
||||||
|
+ bridge_state->output_bus_cfg.format);
|
||||||
|
|
||||||
|
- return ret;
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||||
|
@@ -395,8 +324,7 @@ static void dw_hdmi_qp_bridge_atomic_ena
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (connector->display_info.is_hdmi) {
|
||||||
|
- dev_dbg(hdmi->dev, "%s mode=HDMI rate=%llu\n",
|
||||||
|
- __func__, conn_state->hdmi.tmds_char_rate);
|
||||||
|
+ dev_dbg(hdmi->dev, "%s mode=HDMI\n", __func__);
|
||||||
|
op_mode = 0;
|
||||||
|
} else {
|
||||||
|
dev_dbg(hdmi->dev, "%s mode=DVI\n", __func__);
|
||||||
|
@@ -408,7 +336,7 @@ static void dw_hdmi_qp_bridge_atomic_ena
|
||||||
|
dw_hdmi_qp_mod(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||||
|
dw_hdmi_qp_mod(hdmi, op_mode, OPMODE_DVI, LINK_CONFIG0);
|
||||||
|
|
||||||
|
- drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||||
|
+ //drm_atomic_helper_connector_hdmi_update_infoframes(connector, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||||
|
@@ -441,6 +369,26 @@ dw_hdmi_qp_bridge_edid_read(struct drm_b
|
||||||
|
return drm_edid;
|
||||||
|
}
|
||||||
|
|
||||||
|
+
|
||||||
|
+static unsigned long long
|
||||||
|
+dw_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
|
||||||
|
+ unsigned int bpc,
|
||||||
|
+ enum hdmi_colorspace fmt)
|
||||||
|
+{
|
||||||
|
+ unsigned long long clock = mode->clock * 1000ULL;
|
||||||
|
+
|
||||||
|
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
|
+ clock = clock * 2;
|
||||||
|
+
|
||||||
|
+ if (fmt == HDMI_COLORSPACE_YUV422)
|
||||||
|
+ bpc = 8;
|
||||||
|
+
|
||||||
|
+ clock = clock * bpc;
|
||||||
|
+ do_div(clock, 8);
|
||||||
|
+
|
||||||
|
+ return clock;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static enum drm_mode_status
|
||||||
|
dw_hdmi_qp_bridge_mode_valid(struct drm_bridge *bridge,
|
||||||
|
const struct drm_display_info *info,
|
||||||
|
@@ -449,7 +397,7 @@ dw_hdmi_qp_bridge_mode_valid(struct drm_
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
unsigned long long rate;
|
||||||
|
|
||||||
|
- rate = drm_hdmi_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
|
||||||
|
+ rate = dw_hdmi_encoder_compute_mode_clock(mode, 8, HDMI_COLORSPACE_RGB);
|
||||||
|
if (rate > HDMI14_MAX_TMDSCLK) {
|
||||||
|
dev_dbg(hdmi->dev, "Unsupported mode clock: %d\n", mode->clock);
|
||||||
|
return MODE_CLOCK_HIGH;
|
||||||
|
@@ -458,49 +406,6 @@ dw_hdmi_qp_bridge_mode_valid(struct drm_
|
||||||
|
return MODE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int dw_hdmi_qp_bridge_clear_infoframe(struct drm_bridge *bridge,
|
||||||
|
- enum hdmi_infoframe_type type)
|
||||||
|
-{
|
||||||
|
- struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
-
|
||||||
|
- switch (type) {
|
||||||
|
- case HDMI_INFOFRAME_TYPE_AVI:
|
||||||
|
- dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_AVI_TX_EN | PKTSCHED_GCP_TX_EN,
|
||||||
|
- PKTSCHED_PKT_EN);
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- case HDMI_INFOFRAME_TYPE_DRM:
|
||||||
|
- dw_hdmi_qp_mod(hdmi, 0, PKTSCHED_DRMI_TX_EN, PKTSCHED_PKT_EN);
|
||||||
|
- break;
|
||||||
|
-
|
||||||
|
- default:
|
||||||
|
- dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int dw_hdmi_qp_bridge_write_infoframe(struct drm_bridge *bridge,
|
||||||
|
- enum hdmi_infoframe_type type,
|
||||||
|
- const u8 *buffer, size_t len)
|
||||||
|
-{
|
||||||
|
- struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
-
|
||||||
|
- dw_hdmi_qp_bridge_clear_infoframe(bridge, type);
|
||||||
|
-
|
||||||
|
- switch (type) {
|
||||||
|
- case HDMI_INFOFRAME_TYPE_AVI:
|
||||||
|
- return dw_hdmi_qp_config_avi_infoframe(hdmi, buffer, len);
|
||||||
|
-
|
||||||
|
- case HDMI_INFOFRAME_TYPE_DRM:
|
||||||
|
- return dw_hdmi_qp_config_drm_infoframe(hdmi, buffer, len);
|
||||||
|
-
|
||||||
|
- default:
|
||||||
|
- dev_dbg(hdmi->dev, "Unsupported infoframe type %x\n", type);
|
||||||
|
- return 0;
|
||||||
|
- }
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static const struct drm_bridge_funcs dw_hdmi_qp_bridge_funcs = {
|
||||||
|
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||||
|
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||||
|
@@ -511,8 +416,6 @@ static const struct drm_bridge_funcs dw_
|
||||||
|
.detect = dw_hdmi_qp_bridge_detect,
|
||||||
|
.edid_read = dw_hdmi_qp_bridge_edid_read,
|
||||||
|
.mode_valid = dw_hdmi_qp_bridge_mode_valid,
|
||||||
|
- .hdmi_clear_infoframe = dw_hdmi_qp_bridge_clear_infoframe,
|
||||||
|
- .hdmi_write_infoframe = dw_hdmi_qp_bridge_write_infoframe,
|
||||||
|
};
|
||||||
|
|
||||||
|
static irqreturn_t dw_hdmi_qp_main_hardirq(int irq, void *dev_id)
|
||||||
|
@@ -611,12 +514,9 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struc
|
||||||
|
hdmi->bridge.funcs = &dw_hdmi_qp_bridge_funcs;
|
||||||
|
hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT |
|
||||||
|
DRM_BRIDGE_OP_EDID |
|
||||||
|
- DRM_BRIDGE_OP_HDMI |
|
||||||
|
DRM_BRIDGE_OP_HPD;
|
||||||
|
hdmi->bridge.of_node = pdev->dev.of_node;
|
||||||
|
hdmi->bridge.type = DRM_MODE_CONNECTOR_HDMIA;
|
||||||
|
- hdmi->bridge.vendor = "Synopsys";
|
||||||
|
- hdmi->bridge.product = "DW HDMI QP TX";
|
||||||
|
|
||||||
|
hdmi->bridge.ddc = dw_hdmi_qp_i2c_adapter(hdmi);
|
||||||
|
if (IS_ERR(hdmi->bridge.ddc))
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
||||||
|
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c
|
||||||
|
@@ -355,18 +355,18 @@ dw_hdmi_qp_bridge_detect(struct drm_brid
|
||||||
|
return hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static const struct drm_edid *
|
||||||
|
-dw_hdmi_qp_bridge_edid_read(struct drm_bridge *bridge,
|
||||||
|
+static struct edid *
|
||||||
|
+dw_hdmi_qp_bridge_get_edid(struct drm_bridge *bridge,
|
||||||
|
struct drm_connector *connector)
|
||||||
|
{
|
||||||
|
struct dw_hdmi_qp *hdmi = bridge->driver_private;
|
||||||
|
- const struct drm_edid *drm_edid;
|
||||||
|
+ struct edid *edid;
|
||||||
|
|
||||||
|
- drm_edid = drm_edid_read_ddc(connector, bridge->ddc);
|
||||||
|
- if (!drm_edid)
|
||||||
|
+ edid = drm_get_edid(connector, bridge->ddc);
|
||||||
|
+ if (!edid)
|
||||||
|
dev_dbg(hdmi->dev, "failed to get edid\n");
|
||||||
|
|
||||||
|
- return drm_edid;
|
||||||
|
+ return edid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -414,7 +414,7 @@ static const struct drm_bridge_funcs dw_
|
||||||
|
.atomic_enable = dw_hdmi_qp_bridge_atomic_enable,
|
||||||
|
.atomic_disable = dw_hdmi_qp_bridge_atomic_disable,
|
||||||
|
.detect = dw_hdmi_qp_bridge_detect,
|
||||||
|
- .edid_read = dw_hdmi_qp_bridge_edid_read,
|
||||||
|
+ .get_edid = dw_hdmi_qp_bridge_get_edid,
|
||||||
|
.mode_valid = dw_hdmi_qp_bridge_mode_valid,
|
||||||
|
};
|
||||||
|
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
From 728c15b4b5f3369cbde73d5e0f14701ab370f985 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jonas Karlman <jonas@kwiboo.se>
|
||||||
|
Date: Mon, 23 Oct 2023 17:37:14 +0000
|
||||||
|
Subject: [PATCH] drm/fourcc: Add NV20 and NV30 YUV formats
|
||||||
|
|
||||||
|
DRM_FORMAT_NV20 and DRM_FORMAT_NV30 formats is the 2x1 and non-subsampled
|
||||||
|
variant of NV15, a 10-bit 2-plane YUV format that has no padding between
|
||||||
|
components. Instead, luminance and chrominance samples are grouped into 4s
|
||||||
|
so that each group is packed into an integer number of bytes:
|
||||||
|
|
||||||
|
YYYY = UVUV = 4 * 10 bits = 40 bits = 5 bytes
|
||||||
|
|
||||||
|
The '20' and '30' suffix refers to the optimum effective bits per pixel
|
||||||
|
which is achieved when the total number of luminance samples is a multiple
|
||||||
|
of 4.
|
||||||
|
|
||||||
|
V2: Added NV30 format
|
||||||
|
|
||||||
|
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||||
|
Reviewed-by: Sandy Huang <hjc@rock-chips.com>
|
||||||
|
Reviewed-by: Christopher Obbard <chris.obbard@collabora.com>
|
||||||
|
Tested-by: Christopher Obbard <chris.obbard@collabora.com>
|
||||||
|
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
|
||||||
|
Link: https://patchwork.freedesktop.org/patch/msgid/20231023173718.188102-2-jonas@kwiboo.se
|
||||||
|
---
|
||||||
|
drivers/gpu/drm/drm_fourcc.c | 8 ++++++++
|
||||||
|
include/uapi/drm/drm_fourcc.h | 2 ++
|
||||||
|
2 files changed, 10 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/gpu/drm/drm_fourcc.c
|
||||||
|
+++ b/drivers/gpu/drm/drm_fourcc.c
|
||||||
|
@@ -299,6 +299,14 @@ const struct drm_format_info *__drm_form
|
||||||
|
.num_planes = 2, .char_per_block = { 5, 5, 0 },
|
||||||
|
.block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
|
||||||
|
.vsub = 2, .is_yuv = true },
|
||||||
|
+ { .format = DRM_FORMAT_NV20, .depth = 0,
|
||||||
|
+ .num_planes = 2, .char_per_block = { 5, 5, 0 },
|
||||||
|
+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 2,
|
||||||
|
+ .vsub = 1, .is_yuv = true },
|
||||||
|
+ { .format = DRM_FORMAT_NV30, .depth = 0,
|
||||||
|
+ .num_planes = 2, .char_per_block = { 5, 5, 0 },
|
||||||
|
+ .block_w = { 4, 2, 0 }, .block_h = { 1, 1, 0 }, .hsub = 1,
|
||||||
|
+ .vsub = 1, .is_yuv = true },
|
||||||
|
{ .format = DRM_FORMAT_Q410, .depth = 0,
|
||||||
|
.num_planes = 3, .char_per_block = { 2, 2, 2 },
|
||||||
|
.block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1,
|
||||||
|
--- a/include/uapi/drm/drm_fourcc.h
|
||||||
|
+++ b/include/uapi/drm/drm_fourcc.h
|
||||||
|
@@ -323,6 +323,8 @@ extern "C" {
|
||||||
|
* index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian
|
||||||
|
*/
|
||||||
|
#define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */
|
||||||
|
+#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */
|
||||||
|
+#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2 plane YCbCr MSB aligned
|
||||||
@ -0,0 +1,235 @@
|
|||||||
|
--- a/drivers/gpu/drm/rockchip/Kconfig
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/Kconfig
|
||||||
|
@@ -8,6 +8,7 @@ config DRM_ROCKCHIP
|
||||||
|
select VIDEOMODE_HELPERS
|
||||||
|
select DRM_ANALOGIX_DP if ROCKCHIP_ANALOGIX_DP
|
||||||
|
select DRM_DW_HDMI if ROCKCHIP_DW_HDMI
|
||||||
|
+ select DRM_DW_HDMI_QP if ROCKCHIP_DW_HDMI_QP
|
||||||
|
select DRM_DW_MIPI_DSI if ROCKCHIP_DW_MIPI_DSI
|
||||||
|
select GENERIC_PHY if ROCKCHIP_DW_MIPI_DSI
|
||||||
|
select GENERIC_PHY_MIPI_DPHY if ROCKCHIP_DW_MIPI_DSI
|
||||||
|
@@ -63,6 +64,14 @@ config ROCKCHIP_DW_HDMI
|
||||||
|
enable HDMI on RK3288 or RK3399 based SoC, you should select
|
||||||
|
this option.
|
||||||
|
|
||||||
|
+config ROCKCHIP_DW_HDMI_QP
|
||||||
|
+ bool "Rockchip specific extensions for Synopsys DW HDMI QP"
|
||||||
|
+ select DRM_KMS_HELPER
|
||||||
|
+ help
|
||||||
|
+ This selects support for Rockchip SoC specific extensions
|
||||||
|
+ for the Synopsys DesignWare HDMI QP driver. If you want to
|
||||||
|
+ enable HDMI on RK3588 based SoC, you should select this option.
|
||||||
|
+
|
||||||
|
config ROCKCHIP_DW_MIPI_DSI
|
||||||
|
bool "Rockchip specific extensions for Synopsys DW MIPI DSI"
|
||||||
|
select GENERIC_PHY_MIPI_DPHY
|
||||||
|
--- a/drivers/gpu/drm/rockchip/Makefile
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/Makefile
|
||||||
|
@@ -11,6 +11,7 @@ rockchipdrm-$(CONFIG_ROCKCHIP_VOP) += ro
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_CDN_DP) += cdn-dp-core.o cdn-dp-reg.o
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o
|
||||||
|
+rockchipdrm-$(CONFIG_ROCKCHIP_DW_HDMI_QP) += dw_hdmi_qp-rockchip.o
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_DW_MIPI_DSI) += dw-mipi-dsi-rockchip.o
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_INNO_HDMI) += inno_hdmi.o
|
||||||
|
rockchipdrm-$(CONFIG_ROCKCHIP_LVDS) += rockchip_lvds.o
|
||||||
|
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
|
||||||
|
@@ -19,6 +19,7 @@
|
||||||
|
#include <drm/bridge/dw_hdmi_qp.h>
|
||||||
|
#include <drm/display/drm_hdmi_helper.h>
|
||||||
|
#include <drm/drm_bridge_connector.h>
|
||||||
|
+#include <drm/drm_edid.h>
|
||||||
|
#include <drm/drm_of.h>
|
||||||
|
#include <drm/drm_probe_helper.h>
|
||||||
|
#include <drm/drm_simple_kms_helper.h>
|
||||||
|
@@ -110,6 +111,66 @@ static struct rockchip_hdmi_qp *to_rockc
|
||||||
|
return container_of(rkencoder, struct rockchip_hdmi_qp, encoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * drm_hdmi_compute_mode_clock() - Computes the TMDS Character Rate
|
||||||
|
+ * @mode: Display mode to compute the clock for
|
||||||
|
+ * @bpc: Bits per character
|
||||||
|
+ * @fmt: Output Pixel Format used
|
||||||
|
+ *
|
||||||
|
+ * Returns the TMDS Character Rate for a given mode, bpc count and output format.
|
||||||
|
+ *
|
||||||
|
+ * RETURNS:
|
||||||
|
+ * The TMDS Character Rate, in Hertz, or 0 on error.
|
||||||
|
+ */
|
||||||
|
+static unsigned long long
|
||||||
|
+rk_hdmi_compute_mode_clock(const struct drm_display_mode *mode,
|
||||||
|
+ unsigned int bpc, enum hdmi_colorspace fmt)
|
||||||
|
+{
|
||||||
|
+ unsigned long long clock = mode->clock * 1000ULL;
|
||||||
|
+ unsigned int vic = drm_match_cea_mode(mode);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * CTA-861-G Spec, section 5.4 - Color Coding and Quantization
|
||||||
|
+ * mandates that VIC 1 always uses 8 bpc.
|
||||||
|
+ */
|
||||||
|
+ if (vic == 1 && bpc != 8)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (fmt == HDMI_COLORSPACE_YUV422) {
|
||||||
|
+ /*
|
||||||
|
+ * HDMI 1.0 Spec, section 6.5 - Pixel Encoding states that
|
||||||
|
+ * YUV422 sends 24 bits over three channels, with Cb and Cr
|
||||||
|
+ * components being sent on odd and even pixels, respectively.
|
||||||
|
+ *
|
||||||
|
+ * If fewer than 12 bpc are sent, data are left justified.
|
||||||
|
+ */
|
||||||
|
+ if (bpc > 12)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * HDMI 1.0 Spec, section 6.5 - Pixel Encoding
|
||||||
|
+ * specifies that YUV422 sends two 12-bits components over
|
||||||
|
+ * three TMDS channels per pixel clock, which is equivalent to
|
||||||
|
+ * three 8-bits components over three channels used by RGB as
|
||||||
|
+ * far as the clock rate goes.
|
||||||
|
+ */
|
||||||
|
+ bpc = 8;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * HDMI 2.0 Spec, Section 7.1 - YCbCr 4:2:0 Pixel Encoding
|
||||||
|
+ * specifies that YUV420 encoding is carried at a TMDS Character Rate
|
||||||
|
+ * equal to half the pixel clock rate.
|
||||||
|
+ */
|
||||||
|
+ if (fmt == HDMI_COLORSPACE_YUV420)
|
||||||
|
+ clock = clock / 2;
|
||||||
|
+
|
||||||
|
+ if (mode->flags & DRM_MODE_FLAG_DBLCLK)
|
||||||
|
+ clock = clock * 2;
|
||||||
|
+
|
||||||
|
+ return DIV_ROUND_CLOSEST_ULL(clock * bpc, 8);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
|
||||||
|
{
|
||||||
|
struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
|
||||||
|
@@ -120,7 +181,7 @@ static void dw_hdmi_qp_rockchip_encoder_
|
||||||
|
gpiod_set_value(hdmi->enable_gpio, 1);
|
||||||
|
|
||||||
|
if (crtc && crtc->state) {
|
||||||
|
- rate = drm_hdmi_compute_mode_clock(&crtc->state->adjusted_mode,
|
||||||
|
+ rate = rk_hdmi_compute_mode_clock(&crtc->state->adjusted_mode,
|
||||||
|
8, HDMI_COLORSPACE_RGB);
|
||||||
|
/*
|
||||||
|
* FIXME: Temporary workaround to pass pixel clock rate
|
||||||
|
@@ -427,6 +488,51 @@ static const struct of_device_id dw_hdmi
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
|
||||||
|
|
||||||
|
+struct clk_bulk_devres {
|
||||||
|
+ struct clk_bulk_data *clks;
|
||||||
|
+ int num_clks;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static void rk_devm_clk_bulk_release_all_enable(struct device *dev, void *res)
|
||||||
|
+{
|
||||||
|
+ struct clk_bulk_devres *devres = res;
|
||||||
|
+
|
||||||
|
+ clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
|
||||||
|
+ clk_bulk_put_all(devres->num_clks, devres->clks);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __must_check rk_devm_clk_bulk_get_all_enabled(struct device *dev,
|
||||||
|
+ struct clk_bulk_data **clks)
|
||||||
|
+{
|
||||||
|
+ struct clk_bulk_devres *devres;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ devres = devres_alloc(rk_devm_clk_bulk_release_all_enable,
|
||||||
|
+ sizeof(*devres), GFP_KERNEL);
|
||||||
|
+ if (!devres)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ ret = clk_bulk_get_all(dev, &devres->clks);
|
||||||
|
+ if (ret > 0) {
|
||||||
|
+ *clks = devres->clks;
|
||||||
|
+ devres->num_clks = ret;
|
||||||
|
+ } else {
|
||||||
|
+ devres_free(devres);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = clk_bulk_prepare_enable(devres->num_clks, *clks);
|
||||||
|
+ if (!ret) {
|
||||||
|
+ devres_add(dev, devres);
|
||||||
|
+ } else {
|
||||||
|
+ clk_bulk_put_all(devres->num_clks, devres->clks);
|
||||||
|
+ devres_free(devres);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return devres->num_clks;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
@@ -509,7 +615,7 @@ static int dw_hdmi_qp_rockchip_bind(stru
|
||||||
|
return PTR_ERR(hdmi->vo_regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
- ret = devm_clk_bulk_get_all_enabled(hdmi->dev, &clks);
|
||||||
|
+ ret = rk_devm_clk_bulk_get_all_enabled(hdmi->dev, &clks);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(hdmi->dev, "Failed to get clocks: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
@@ -619,7 +725,7 @@ static const struct dev_pm_ops dw_hdmi_q
|
||||||
|
|
||||||
|
struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
|
||||||
|
.probe = dw_hdmi_qp_rockchip_probe,
|
||||||
|
- .remove = dw_hdmi_qp_rockchip_remove,
|
||||||
|
+ .remove_new = dw_hdmi_qp_rockchip_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "dwhdmiqp-rockchip",
|
||||||
|
.pm = &dw_hdmi_qp_rockchip_pm,
|
||||||
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
|
||||||
|
@@ -503,6 +503,8 @@ static int __init rockchip_drm_init(void
|
||||||
|
ADD_ROCKCHIP_SUB_DRIVER(cdn_dp_driver, CONFIG_ROCKCHIP_CDN_DP);
|
||||||
|
ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_rockchip_pltfm_driver,
|
||||||
|
CONFIG_ROCKCHIP_DW_HDMI);
|
||||||
|
+ ADD_ROCKCHIP_SUB_DRIVER(dw_hdmi_qp_rockchip_pltfm_driver,
|
||||||
|
+ CONFIG_ROCKCHIP_DW_HDMI_QP);
|
||||||
|
ADD_ROCKCHIP_SUB_DRIVER(dw_mipi_dsi_rockchip_driver,
|
||||||
|
CONFIG_ROCKCHIP_DW_MIPI_DSI);
|
||||||
|
ADD_ROCKCHIP_SUB_DRIVER(inno_hdmi_driver, CONFIG_ROCKCHIP_INNO_HDMI);
|
||||||
|
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
|
||||||
|
@@ -87,6 +87,7 @@ int rockchip_drm_encoder_set_crtc_endpoi
|
||||||
|
int rockchip_drm_endpoint_is_subdriver(struct device_node *ep);
|
||||||
|
extern struct platform_driver cdn_dp_driver;
|
||||||
|
extern struct platform_driver dw_hdmi_rockchip_pltfm_driver;
|
||||||
|
+extern struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver;
|
||||||
|
extern struct platform_driver dw_mipi_dsi_rockchip_driver;
|
||||||
|
extern struct platform_driver inno_hdmi_driver;
|
||||||
|
extern struct platform_driver rockchip_dp_driver;
|
||||||
|
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
|
||||||
|
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
|
||||||
|
@@ -2566,7 +2566,7 @@ static void vop2_remove(struct platform_
|
||||||
|
|
||||||
|
struct platform_driver vop2_platform_driver = {
|
||||||
|
.probe = vop2_probe,
|
||||||
|
- .remove = vop2_remove,
|
||||||
|
+ .remove_new = vop2_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "rockchip-vop2",
|
||||||
|
.of_match_table = vop2_dt_match,
|
||||||
|
--- a/include/dt-bindings/soc/rockchip,vop2.h
|
||||||
|
+++ b/include/dt-bindings/soc/rockchip,vop2.h
|
||||||
|
@@ -10,5 +10,9 @@
|
||||||
|
#define ROCKCHIP_VOP2_EP_LVDS0 5
|
||||||
|
#define ROCKCHIP_VOP2_EP_MIPI1 6
|
||||||
|
#define ROCKCHIP_VOP2_EP_LVDS1 7
|
||||||
|
+#define ROCKCHIP_VOP2_EP_HDMI1 8
|
||||||
|
+#define ROCKCHIP_VOP2_EP_EDP1 9
|
||||||
|
+#define ROCKCHIP_VOP2_EP_DP0 10
|
||||||
|
+#define ROCKCHIP_VOP2_EP_DP1 11
|
||||||
|
|
||||||
|
#endif /* __DT_BINDINGS_ROCKCHIP_VOP2_H */
|
||||||
Loading…
Reference in New Issue
Block a user