Merge commit 'e6cc02852f60a1ad3a9d8061e0fbdf23125ff148'

* commit 'e6cc02852f60a1ad3a9d8061e0fbdf23125ff148':
  Revert "mfd: Add rk628 mfd driver"
  Revert "drm/rockchip: Add rk628 display driver"
  Revert "drm/rockchip: rk628: Add hdmi driver"
  Revert "drm/rockchip/rk628: Add GVI driver"
  Revert "drm: rockchip: rk628: Add rk628 combrx-phy driver"
  Revert "drm: rockchip: rk628: Add rk628 hdmirx driver"
  Revert "pinctrl: rk628: add rk628 pinctrl driver"
  Revert "nvmem: rk628-efuse: add rk628 efuse driver"

Change-Id: I11874bb11345600b610ac9e5422fd238297993aa
This commit is contained in:
Tao Huang
2024-01-24 11:08:33 +08:00
24 changed files with 0 additions and 10230 deletions

View File

@@ -165,6 +165,5 @@ config ROCKCHIP_DW_HDCP2
Designware HDCP2 Controller.
source "drivers/gpu/drm/rockchip/rk618/Kconfig"
source "drivers/gpu/drm/rockchip/rk628/Kconfig"
endif

View File

@@ -31,4 +31,3 @@ rockchipdrm-$(CONFIG_DRM_ROCKCHIP_VVOP) += rockchip_drm_vvop.o
obj-$(CONFIG_ROCKCHIP_DW_HDCP2) += dw_hdcp2.o
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o
obj-$(CONFIG_DRM_ROCKCHIP_RK618) += rk618/
obj-$(CONFIG_DRM_ROCKCHIP_RK628) += rk628/

View File

@@ -1,8 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
config DRM_ROCKCHIP_RK628
tristate "Rockchip RK628 display bridge driver"
depends on DRM_ROCKCHIP
depends on MFD_RK628
help
Rockchip RK628 display bridge chips driver.

View File

@@ -1,14 +0,0 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the Rockchip RK628 display bridge driver.
#
obj-$(CONFIG_DRM_ROCKCHIP_RK628) += rk628_combrxphy.o \
rk628_combtxphy.o \
rk628_dsi.o \
rk628_gvi.o \
rk628_lvds.o \
rk628_post_process.o \
rk628_rgb.o \
rk628_hdmi.o \
rk628_hdmirx.o

File diff suppressed because it is too large Load Diff

View File

@@ -1,520 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <asm/bitsperlong.h>
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <linux/mfd/rk628.h>
#include "rk628_combtxphy.h"
#define REG(x) ((x) + 0x90000)
#define COMBTXPHY_CON0 REG(0x0000)
#define SW_TX_IDLE_MASK GENMASK(29, 20)
#define SW_TX_IDLE(x) UPDATE(x, 29, 20)
#define SW_TX_PD_MASK GENMASK(17, 8)
#define SW_TX_PD(x) UPDATE(x, 17, 8)
#define SW_BUS_WIDTH_MASK GENMASK(6, 5)
#define SW_BUS_WIDTH_7BIT UPDATE(0x3, 6, 5)
#define SW_BUS_WIDTH_8BIT UPDATE(0x2, 6, 5)
#define SW_BUS_WIDTH_9BIT UPDATE(0x1, 6, 5)
#define SW_BUS_WIDTH_10BIT UPDATE(0x0, 6, 5)
#define SW_PD_PLL_MASK BIT(4)
#define SW_PD_PLL BIT(4)
#define SW_GVI_LVDS_EN_MASK BIT(3)
#define SW_GVI_LVDS_EN BIT(3)
#define SW_MIPI_DSI_EN_MASK BIT(2)
#define SW_MIPI_DSI_EN BIT(2)
#define SW_MODULEB_EN_MASK BIT(1)
#define SW_MODULEB_EN BIT(1)
#define SW_MODULEA_EN_MASK BIT(0)
#define SW_MODULEA_EN BIT(0)
#define COMBTXPHY_CON1 REG(0x0004)
#define COMBTXPHY_CON2 REG(0x0008)
#define COMBTXPHY_CON3 REG(0x000c)
#define COMBTXPHY_CON4 REG(0x0010)
#define COMBTXPHY_CON5 REG(0x0014)
#define SW_RATE(x) UPDATE(x, 26, 24)
#define SW_REF_DIV(x) UPDATE(x, 20, 16)
#define SW_PLL_FB_DIV(x) UPDATE(x, 14, 10)
#define SW_PLL_FRAC_DIV(x) UPDATE(x, 9, 0)
#define COMBTXPHY_CON6 REG(0x0018)
#define COMBTXPHY_CON7 REG(0x001c)
#define SW_TX_RTERM_MASK GENMASK(22, 20)
#define SW_TX_RTERM(x) UPDATE(x, 22, 20)
#define SW_TX_MODE_MASK GENMASK(17, 16)
#define SW_TX_MODE(x) UPDATE(x, 17, 16)
#define SW_TX_CTL_CON5_MASK BIT(10)
#define SW_TX_CTL_CON5(x) UPDATE(x, 10, 10)
#define SW_TX_CTL_CON4_MASK GENMASK(9, 8)
#define SW_TX_CTL_CON4(x) UPDATE(x, 9, 8)
#define BYPASS_095V_LDO_MASK BIT(3)
#define BYPASS_095V_LDO(x) UPDATE(x, 3, 3)
#define TX_COM_VOLT_ADJ_MASK GENMASK(2, 0)
#define TX_COM_VOLT_ADJ(x) UPDATE(x, 2, 0)
#define COMBTXPHY_CON8 REG(0x0020)
#define COMBTXPHY_CON9 REG(0x0024)
#define SW_DSI_FSET_EN_MASK BIT(29)
#define SW_DSI_FSET_EN BIT(29)
#define SW_DSI_RCAL_EN_MASK BIT(28)
#define SW_DSI_RCAL_EN BIT(28)
#define COMBTXPHY_CON10 REG(0x0028)
#define TX9_CKDRV_EN BIT(9)
#define TX8_CKDRV_EN BIT(8)
#define TX7_CKDRV_EN BIT(7)
#define TX6_CKDRV_EN BIT(6)
#define TX5_CKDRV_EN BIT(5)
#define TX4_CKDRV_EN BIT(4)
#define TX3_CKDRV_EN BIT(3)
#define TX2_CKDRV_EN BIT(2)
#define TX1_CKDRV_EN BIT(1)
#define TX0_CKDRV_EN BIT(0)
#define COMBTXPHY_MAX_REGISTER COMBTXPHY_CON10
struct rk628_combtxphy {
struct device *dev;
struct rk628 *parent;
struct regmap *grf;
struct regmap *regmap;
struct clk *pclk;
struct clk *ref_clk;
struct reset_control *rstc;
unsigned int flags;
u16 frac_div;
u8 ref_div;
u8 fb_div;
u8 rate_div;
u8 division_mode;
};
static int rk628_combtxphy_dsi_power_on(struct rk628_combtxphy *combtxphy)
{
u32 val;
int ret;
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
SW_MIPI_DSI_EN_MASK,
SW_BUS_WIDTH_8BIT | SW_MIPI_DSI_EN);
if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_MODULEA_EN_MASK, SW_MODULEA_EN);
if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_MODULEB_EN_MASK, SW_MODULEB_EN);
regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
SW_REF_DIV(combtxphy->ref_div - 1) |
SW_PLL_FB_DIV(combtxphy->fb_div) |
SW_PLL_FRAC_DIV(combtxphy->frac_div) |
SW_RATE(combtxphy->rate_div / 2));
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_PD_PLL, 0);
ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS,
val, val & DPHY_PHYLOCK, 0, 1000);
if (ret < 0) {
dev_err(combtxphy->dev, "phy is not lock\n");
return ret;
}
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON9,
SW_DSI_FSET_EN_MASK | SW_DSI_RCAL_EN_MASK,
SW_DSI_FSET_EN | SW_DSI_RCAL_EN);
usleep_range(200, 400);
return 0;
}
static int rk628_combtxphy_lvds_power_on(struct rk628_combtxphy *combtxphy)
{
u32 val;
int ret;
/* Adjust terminal resistance 133 ohm, bypass 0.95v ldo for driver. */
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON7,
SW_TX_RTERM_MASK | SW_TX_MODE_MASK |
BYPASS_095V_LDO_MASK | TX_COM_VOLT_ADJ_MASK,
SW_TX_RTERM(6) | SW_TX_MODE(3) |
BYPASS_095V_LDO(1) | TX_COM_VOLT_ADJ(0));
regmap_write(combtxphy->regmap, COMBTXPHY_CON10,
TX7_CKDRV_EN | TX2_CKDRV_EN);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
SW_MIPI_DSI_EN_MASK,
SW_BUS_WIDTH_7BIT | SW_GVI_LVDS_EN);
if (combtxphy->flags & COMBTXPHY_MODULEA_EN)
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_MODULEA_EN_MASK, SW_MODULEA_EN);
if (combtxphy->flags & COMBTXPHY_MODULEB_EN)
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_MODULEB_EN_MASK, SW_MODULEB_EN);
regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
SW_REF_DIV(combtxphy->ref_div - 1) |
SW_PLL_FB_DIV(combtxphy->fb_div) |
SW_PLL_FRAC_DIV(combtxphy->frac_div) |
SW_RATE(combtxphy->rate_div / 2));
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_PD_PLL, 0);
ret = regmap_read_poll_timeout(combtxphy->grf, GRF_DPHY0_STATUS,
val, val & DPHY_PHYLOCK, 0, 1000);
if (ret < 0) {
dev_info(combtxphy->dev, "phy is not lock\n");
return ret;
}
usleep_range(100, 200);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_TX_IDLE_MASK | SW_TX_PD_MASK, 0);
return 0;
}
static int rk628_combtxphy_gvi_power_on(struct rk628_combtxphy *combtxphy)
{
int ref_div = 0;
if (combtxphy->ref_div % 2) {
ref_div = combtxphy->ref_div - 1;
} else {
ref_div = BIT(4);
ref_div |= combtxphy->ref_div / 2 - 1;
}
regmap_write(combtxphy->regmap, COMBTXPHY_CON5,
SW_REF_DIV(ref_div) |
SW_PLL_FB_DIV(combtxphy->fb_div) |
SW_PLL_FRAC_DIV(combtxphy->frac_div) |
SW_RATE(combtxphy->rate_div / 2));
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_BUS_WIDTH_MASK | SW_GVI_LVDS_EN_MASK |
SW_MIPI_DSI_EN_MASK |
SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
SW_BUS_WIDTH_10BIT | SW_GVI_LVDS_EN |
SW_MODULEB_EN | SW_MODULEA_EN);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_PD_PLL | SW_TX_PD_MASK, 0);
usleep_range(100, 200);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_TX_IDLE_MASK, 0);
return 0;
}
int rk628_combtxphy_set_gvi_division_mode(struct phy *phy, u8 mode)
{
struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
combtxphy->division_mode = mode;
return 0;
}
EXPORT_SYMBOL(rk628_combtxphy_set_gvi_division_mode);
static int rk628_combtxphy_power_on(struct phy *phy)
{
struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
enum phy_mode mode = phy_get_mode(phy);
clk_prepare_enable(combtxphy->pclk);
reset_control_assert(combtxphy->rstc);
udelay(10);
reset_control_deassert(combtxphy->rstc);
udelay(10);
regcache_mark_dirty(combtxphy->regmap);
regcache_sync(combtxphy->regmap);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK,
SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL);
switch (mode) {
case PHY_MODE_MIPI_DPHY:
regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
SW_TXPHY_REFCLK_SEL_MASK,
SW_TXPHY_REFCLK_SEL(0));
return rk628_combtxphy_dsi_power_on(combtxphy);
case PHY_MODE_LVDS:
regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
SW_TXPHY_REFCLK_SEL_MASK,
SW_TXPHY_REFCLK_SEL(1));
return rk628_combtxphy_lvds_power_on(combtxphy);
default:
regmap_update_bits(combtxphy->grf, GRF_POST_PROC_CON,
SW_TXPHY_REFCLK_SEL_MASK,
SW_TXPHY_REFCLK_SEL(2));
return rk628_combtxphy_gvi_power_on(combtxphy);
}
return 0;
}
static int rk628_combtxphy_power_off(struct phy *phy)
{
struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
regmap_update_bits(combtxphy->regmap, COMBTXPHY_CON0,
SW_TX_IDLE_MASK | SW_TX_PD_MASK | SW_PD_PLL_MASK |
SW_MODULEB_EN_MASK | SW_MODULEA_EN_MASK,
SW_TX_IDLE(0x3ff) | SW_TX_PD(0x3ff) | SW_PD_PLL);
clk_disable_unprepare(combtxphy->pclk);
return 0;
}
static int rk628_combtxphy_set_mode(struct phy *phy, enum phy_mode mode,
int submode)
{
struct rk628_combtxphy *combtxphy = phy_get_drvdata(phy);
unsigned int bus_width = phy_get_bus_width(phy);
unsigned int frac_rate, fin = 24;
unsigned long fvco, fpfd;
switch (mode) {
case PHY_MODE_MIPI_DPHY:
{
unsigned int fhsc = bus_width >> 8;
unsigned int flags = bus_width & 0xff;
fhsc = fin * (fhsc / fin);
if (fhsc < 80 || fhsc > 1500)
return -EINVAL;
else if (fhsc < 375)
combtxphy->rate_div = 4;
else if (fhsc < 750)
combtxphy->rate_div = 2;
else
combtxphy->rate_div = 1;
combtxphy->flags = flags;
fvco = fhsc * 2 * combtxphy->rate_div;
combtxphy->ref_div = 1;
combtxphy->fb_div = fvco / 8 / fin;
frac_rate = fvco - (fin * 8 * combtxphy->fb_div);
if (frac_rate) {
frac_rate <<= 10;
frac_rate /= fin * 8;
combtxphy->frac_div = frac_rate;
} else {
combtxphy->frac_div = 0;
}
fvco = fin * (1024 * combtxphy->fb_div + combtxphy->frac_div);
fvco *= 8;
fvco = DIV_ROUND_UP(fvco, 1024 * combtxphy->ref_div);
fhsc = fvco / 2 / combtxphy->rate_div;
phy_set_bus_width(phy, fhsc);
break;
}
case PHY_MODE_LVDS:
{
unsigned int flags = bus_width & 0xff;
unsigned int rate = (bus_width >> 8) * 7;
combtxphy->flags = flags;
combtxphy->ref_div = 1;
combtxphy->fb_div = 14;
combtxphy->frac_div = 0;
if (rate < 500)
combtxphy->rate_div = 4;
else if (rate < 1000)
combtxphy->rate_div = 2;
else
combtxphy->rate_div = 1;
break;
}
default:
{
unsigned int i, delta_freq, best_delta_freq, fb_div;
unsigned long ref_clk;
unsigned long long pre_clk;
if (bus_width < 500000 || bus_width > 4000000)
return -EINVAL;
else if (bus_width < 1000000)
combtxphy->rate_div = 4;
else if (bus_width < 2000000)
combtxphy->rate_div = 2;
else
combtxphy->rate_div = 1;
fvco = bus_width * combtxphy->rate_div;
ref_clk = clk_get_rate(combtxphy->ref_clk) / 1000; /* khz */
if (combtxphy->division_mode)
ref_clk /= 2;
if (!ref_clk)
return -EINVAL;
/*
* the reference clock at PFD(FPFD = ref_clk / ref_div) about
* 25MHz is recommende, FPFD must range from 16MHz to 35MHz,
* here to find the best rev_div.
*/
best_delta_freq = ref_clk;
for (i = 1; i <= 32; i++) {
fpfd = ref_clk / i;
delta_freq = abs(fpfd - 25000);
if (delta_freq < best_delta_freq) {
best_delta_freq = delta_freq;
combtxphy->ref_div = i;
}
}
/*
* ref_clk / ref_div * 8 * fb_div = FVCO
*/
pre_clk = (unsigned long long)fvco / 8 * combtxphy->ref_div * 1024;
do_div(pre_clk, ref_clk);
fb_div = pre_clk / 1024;
/*
* get the actually frequence
*/
bus_width = ref_clk / combtxphy->ref_div * 8;
bus_width *= fb_div;
bus_width /= combtxphy->rate_div;
combtxphy->frac_div = 0;
combtxphy->fb_div = fb_div;
phy_set_bus_width(phy, bus_width);
break;
}
}
return 0;
}
static const struct phy_ops rk628_combtxphy_ops = {
.set_mode = rk628_combtxphy_set_mode,
.power_on = rk628_combtxphy_power_on,
.power_off = rk628_combtxphy_power_off,
.owner = THIS_MODULE,
};
static const struct regmap_range rk628_combtxphy_readable_ranges[] = {
regmap_reg_range(COMBTXPHY_CON0, COMBTXPHY_CON10),
};
static const struct regmap_access_table rk628_combtxphy_readable_table = {
.yes_ranges = rk628_combtxphy_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(rk628_combtxphy_readable_ranges),
};
static const struct regmap_config rk628_combtxphy_regmap_cfg = {
.name = "combtxphy",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.cache_type = REGCACHE_RBTREE,
.max_register = COMBTXPHY_MAX_REGISTER,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
.rd_table = &rk628_combtxphy_readable_table,
};
static int rk628_combtxphy_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct rk628_combtxphy *combtxphy;
struct phy_provider *phy_provider;
struct phy *phy;
int ret;
combtxphy = devm_kzalloc(dev, sizeof(*combtxphy), GFP_KERNEL);
if (!combtxphy)
return -ENOMEM;
combtxphy->dev = dev;
combtxphy->parent = rk628;
combtxphy->grf = rk628->grf;
platform_set_drvdata(pdev, combtxphy);
combtxphy->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(combtxphy->pclk))
return PTR_ERR(combtxphy->pclk);
combtxphy->ref_clk = devm_clk_get(dev, "ref_clk");
if (IS_ERR(combtxphy->ref_clk)) {
dev_err(dev, "fail to get ref clk\n");
return PTR_ERR(combtxphy->ref_clk);
}
combtxphy->rstc = of_reset_control_get(dev->of_node, NULL);
if (IS_ERR(combtxphy->rstc)) {
ret = PTR_ERR(combtxphy->rstc);
dev_err(dev, "failed to get reset control: %d\n", ret);
return ret;
}
combtxphy->regmap = devm_regmap_init_i2c(rk628->client,
&rk628_combtxphy_regmap_cfg);
if (IS_ERR(combtxphy->regmap)) {
ret = PTR_ERR(combtxphy->regmap);
dev_err(dev, "failed to allocate register map: %d\n", ret);
return ret;
}
phy = devm_phy_create(dev, NULL, &rk628_combtxphy_ops);
if (IS_ERR(phy)) {
ret = PTR_ERR(phy);
dev_err(dev, "failed to create phy: %d\n", ret);
return ret;
}
phy_set_drvdata(phy, combtxphy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider);
dev_err(dev, "failed to register phy provider: %d\n", ret);
return ret;
}
return 0;
}
static const struct of_device_id rk628_combtxphy_of_match[] = {
{ .compatible = "rockchip,rk628-combtxphy", },
{}
};
MODULE_DEVICE_TABLE(of, rk628_combtxphy_of_match);
static struct platform_driver rk628_combtxphy_driver = {
.driver = {
.name = "rk628-combtxphy",
.of_match_table = of_match_ptr(rk628_combtxphy_of_match),
},
.probe = rk628_combtxphy_probe,
};
module_platform_driver(rk628_combtxphy_driver);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 GVI/LVDS/MIPI Combo TX PHY driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1,13 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*/
#ifndef RK628_COMBTXPHY_H_
#define RK628_COMBTXPHY_H_
#include <linux/phy/phy.h>
int rk628_combtxphy_set_gvi_division_mode(struct phy *phy, u8 mode);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,666 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Sandy Huang <hjc@rock-chips.com>
*/
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/media-bus-format.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/mfd/rk628.h>
#include <drm/drm_of.h>
#include <drm/drm_atomic.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include "rk628_combtxphy.h"
#define HOSTREG(x) ((x) + 0x80000)
#define GVI_SYS_CTRL0 HOSTREG(0x0000)
#define GVI_SYS_CTRL1 HOSTREG(0x0004)
#define GVI_SYS_CTRL2 HOSTREG(0x0008)
#define GVI_SYS_CTRL3 HOSTREG(0x000c)
#define GVI_VERSION HOSTREG(0x0010)
#define GVI_SYS_RST HOSTREG(0x0014)
#define GVI_LINE_FLAG HOSTREG(0x0018)
#define GVI_STATUS HOSTREG(0x001c)
#define GVI_PLL_LOCK_TIMEOUT HOSTREG(0x0030)
#define GVI_HTPDN_TIMEOUT HOSTREG(0x0034)
#define GVI_LOCKN_TIMEOUT HOSTREG(0x0038)
#define GVI_WAIT_LOCKN HOSTREG(0x003C)
#define GVI_WAIT_HTPDN HOSTREG(0x0040)
#define GVI_INTR_EN HOSTREG(0x0050)
#define GVI_INTR_CLR HOSTREG(0x0054)
#define GVI_INTR_RAW_STATUS HOSTREG(0x0058)
#define GVI_INTR_STATUS HOSTREG(0x005c)
#define GVI_COLOR_BAR_CTRL HOSTREG(0x0060)
#define GVI_COLOR_BAR_HTIMING0 HOSTREG(0x0070)
#define GVI_COLOR_BAR_HTIMING1 HOSTREG(0x0074)
#define GVI_COLOR_BAR_VTIMING0 HOSTREG(0x0078)
#define GVI_COLOR_BAR_VTIMING1 HOSTREG(0x007c)
/* SYS_CTRL0 */
#define SYS_CTRL0_GVI_EN BIT(0)
#define SYS_CTRL0_AUTO_GATING BIT(1)
#define SYS_CTRL0_FRM_RST_EN BIT(2)
#define SYS_CTRL0_FRM_RST_MODE BIT(3)
#define SYS_CTRL0_LANE_NUM_MASK GENMASK(7, 4)
#define SYS_CTRL0_LANE_NUM(x) UPDATE(x, 7, 4)
#define SYS_CTRL0_BYTE_MODE_MASK GENMASK(9, 8)
#define SYS_CTRL0_BYTE_MODE(x) UPDATE(x, 9, 8)
#define SYS_CTRL0_SECTION_NUM_MASK GENMASK(11, 10)
#define SYS_CTRL0_SECTION_NUM(x) UPDATE(x, 11, 10)
#define SYS_CTRL0_CDR_ENDIAN_SWAP BIT(12)
#define SYS_CTRL0_PACK_BYTE_SWAP BIT(13)
#define SYS_CTRL0_PACK_ENDIAN_SWAP BIT(14)
#define SYS_CTRL0_ENC8B10B_ENDIAN_SWAP BIT(15)
#define SYS_CTRL0_CDR_EN BIT(16)
#define SYS_CTRL0_ALN_EN BIT(17)
#define SYS_CTRL0_NOR_EN BIT(18)
#define SYS_CTRL0_ALN_NOR_MODE BIT(19)
#define SYS_CTRL0_GVI_MASK GENMASK(19, 16)
#define SYS_CTRL0_GVI_GN_EN(x) UPDATE(x, 19, 16)
#define SYS_CTRL0_SCRAMBLER_EN BIT(20)
#define SYS_CTRL0_ENCODE8B10B_EN BIT(21)
#define SYS_CTRL0_INIT_RD_EN BIT(22)
#define SYS_CTRL0_INIT_RD_VALUE BIT(23)
#define SYS_CTRL0_FORCE_HTPDN_EN BIT(24)
#define SYS_CTRL0_FORCE_HTPDN_VALUE BIT(25)
#define SYS_CTRL0_FORCE_PLL_EN BIT(26)
#define SYS_CTRL0_FORCE_PLL_VALUE BIT(27)
#define SYS_CTRL0_FORCE_LOCKN_EN BIT(28)
#define SYS_CTRL0_FORCE_LOCKN_VALUE BIT(29)
/* SYS_CTRL1 */
#define SYS_CTRL1_COLOR_DEPTH_MASK GENMASK(3, 0)
#define SYS_CTRL1_COLOR_DEPTH(x) UPDATE(x, 3, 0)
#define SYS_CTRL1_DUAL_PIXEL_EN BIT(4)
#define SYS_CTRL1_TIMING_ALIGN_EN BIT(8)
#define SYS_CTRL1_LANE_ALIGN_EN BIT(9)
#define SYS_CTRL1_DUAL_PIXEL_SWAP BIT(12)
#define SYS_CTRL1_RB_SWAP BIT(13)
#define SYS_CTRL1_YC_SWAP BIT(14)
#define SYS_CTRL1_WHOLE_FRM_EN BIT(16)
#define SYS_CTRL1_NOR_PROTECT BIT(17)
#define SYS_CTRL1_RD_WCNT_UPDATE BIT(31)
/* SYS_CTRL2 */
#define SYS_CTRL2_AFIFO_READ_THOLD_MASK GENMASK(7, 0)
#define SYS_CTRL2_AFIFO_READ_THOLD(x) UPDATE(x, 7, 0)
#define SYS_CTRL2_AFIFO_ALMOST_FULL_THOLD_MASK GENMASK(23, 16)
#define SYS_CTRL2_AFIFO_ALMOST_FULL_THOLD(x) UPDATE(x, 23, 16)
#define SYS_CTRL2_AFIFO_ALMOST_EMPTY_THOLD_MASK GENMASK(31, 24)
#define SYS_CTRL2_AFIFO_ALMOST_EMPTY_THOLD(x) UPDATE(x, 31, 24)
/* SYS_CTRL3 */
#define SYS_CTRL3_LANE0_SEL_MASK GENMASK(2, 0)
#define SYS_CTRL3_LANE0_SEL(x) UPDATE(x, 2, 0)
#define SYS_CTRL3_LANE1_SEL_MASK GENMASK(6, 4)
#define SYS_CTRL3_LANE1_SEL(x) UPDATE(x, 6, 4)
#define SYS_CTRL3_LANE2_SEL_MASK GENMASK(10, 8)
#define SYS_CTRL3_LANE2_SEL(x) UPDATE(x, 10, 8)
#define SYS_CTRL3_LANE3_SEL_MASK GENMASK(14, 12)
#define SYS_CTRL3_LANE3_SEL(x) UPDATE(x, 14, 12)
#define SYS_CTRL3_LANE4_SEL_MASK GENMASK(18, 16)
#define SYS_CTRL3_LANE4_SEL(x) UPDATE(x, 18, 16)
#define SYS_CTRL3_LANE5_SEL_MASK GENMASK(22, 20)
#define SYS_CTRL3_LANE5_SEL(x) UPDATE(x, 22, 20)
#define SYS_CTRL3_LANE6_SEL_MASK GENMASK(26, 24)
#define SYS_CTRL3_LANE6_SEL(x) UPDATE(x, 26, 24)
#define SYS_CTRL3_LANE7_SEL_MASK GENMASK(30, 28)
#define SYS_CTRL3_LANE7_SEL(x) UPDATE(x, 30, 28)
/* VERSIION */
#define VERSION_VERSION(x) UPDATE(x, 31, 0)
/* SYS_RESET*/
#define SYS_RST_SOFT_RST BIT(0)
/* LINE_FLAG */
#define LINE_FLAG_LANE_FLAG0_MASK GENMASK(15, 0)
#define LINE_FLAG_LANE_FLAG0(x) UPDATE(x, 15, 0)
#define LINE_FLAG_LANE_FLAG1_MASK GENMASK(31, 16)
#define LINE_FLAG_LANE_FLAG1(x) UPDATE(x, 31, 16)
/* STATUS */
#define STATUS_HTDPN BIT(4)
#define STATUS_LOCKN BIT(5)
#define STATUS_PLL_LOCKN BIT(6)
#define STATUS_AFIFO0_WCNT_MASK GENMASK(23, 16)
#define STATUS_AFIFO0_WCNT(x) UPDATE(x, 23, 16)
#define STATUS_AFIFO1_WCNT_MASK GENMASK(31, 24)
#define STATUS_AFIFO1_WCNT(x) UPDATE(x, 31, 24)
/* PLL_LTIMEOUT */
#define PLL_LOCK_TIMEOUT_PLL_LOCK_TIME_OUT_MASK GENMASK(31, 0)
#define PLL_LOCK_TIMEOUT_PLL_LOCK_TIME_OUT(x) UPDATE(x, 31, 0)
/* HTPDNEOUT */
#define HTPDN_TIMEOUT_HTPDN_TIME_OUT_MASK GENMASK(31, 0)
#define HTPDN_TIMEOUT_HTPDN_TIME_OUT(x) UPDATE(x, 31, 0)
/* LOCKNEOUT */
#define LOCKN_TIMEOUT_LOCKN_TIME_OUT_MASK GENMASK(31, 0)
#define LOCKN_TIMEOUT_LOCKN_TIME_OUT(x) UPDATE(x, 31, 0)
/* WAIT_LOCKN */
#define WAIT_LOCKN_WAIT_LOCKN_TIME_MASK GENMASK(30, 0)
#define WAIT_LOCKN_WAIT_LOCKN_TIME(x) UPDATE(x, 30, 0)
#define WAIT_LOCKN_WAIT_LOCKN_TIME_EN BIT(31)
/* WAIT_HTPDN */
#define WAIT_HTPDN_WAIT_HTPDN_TIME_MASK GENMASK(30, 0)
#define WAIT_HTPDN_WAIT_HTPDN_TIME(x) UPDATE(x, 30, 0)
#define WAIT_HTPDN_WAIT_HTPDN_EN BIT(31)
/* INTR_EN */
#define INTR_EN_INTR_FRM_ST_EN BIT(0)
#define INTR_EN_INTR_PLL_LOCK_EN BIT(1)
#define INTR_EN_INTR_HTPDN_EN BIT(2)
#define INTR_EN_INTR_LOCKN_EN BIT(3)
#define INTR_EN_INTR_PLL_TIMEOUT_EN BIT(4)
#define INTR_EN_INTR_HTPDN_TIMEOUT_EN BIT(5)
#define INTR_EN_INTR_LOCKN_TIMEOUT_EN BIT(6)
#define INTR_EN_INTR_LINE_FLAG0_EN BIT(8)
#define INTR_EN_INTR_LINE_FLAG1_EN BIT(9)
#define INTR_EN_INTR_AFIFO_OVERFLOW_EN BIT(10)
#define INTR_EN_INTR_AFIFO_UNDERFLOW_EN BIT(11)
#define INTR_EN_INTR_PLL_ERR_EN BIT(12)
#define INTR_EN_INTR_HTPDN_ERR_EN BIT(13)
#define INTR_EN_INTR_LOCKN_ERR_EN BIT(14)
/* INTR_CLR*/
#define INTR_CLR_INTR_FRM_ST_CLR BIT(0)
#define INTR_CLR_INTR_PLL_LOCK_CLR BIT(1)
#define INTR_CLR_INTR_HTPDN_CLR BIT(2)
#define INTR_CLR_INTR_LOCKN_CLR BIT(3)
#define INTR_CLR_INTR_PLL_TIMEOUT_CLR BIT(4)
#define INTR_CLR_INTR_HTPDN_TIMEOUT_CLR BIT(5)
#define INTR_CLR_INTR_LOCKN_TIMEOUT_CLR BIT(6)
#define INTR_CLR_INTR_LINE_FLAG0_CLR BIT(8)
#define INTR_CLR_INTR_LINE_FLAG1_CLR BIT(9)
#define INTR_CLR_INTR_AFIFO_OVERFLOW_CLR BIT(10)
#define INTR_CLR_INTR_AFIFO_UNDERFLOW_CLR BIT(11)
#define INTR_CLR_INTR_PLL_ERR_CLR BIT(12)
#define INTR_CLR_INTR_HTPDN_ERR_CLR BIT(13)
#define INTR_CLR_INTR_LOCKN_ERR_CLR BIT(14)
/* INTR_RAW_STATUS */
#define INTR_RAW_STATUS_RAW_INTR_FRM_ST BIT(0)
#define INTR_RAW_STATUS_RAW_INTR_PLL_LOCK BIT(1)
#define INTR_RAW_STATUS_RAW_INTR_HTPDN BIT(2)
#define INTR_RAW_STATUS_RAW_INTR_LOCKN BIT(3)
#define INTR_RAW_STATUS_RAW_INTR_PLL_TIMEOUT BIT(4)
#define INTR_RAW_STATUS_RAW_INTR_HTPDN_TIMEOUT BIT(5)
#define INTR_RAW_STATUS_RAW_INTR_LOCKN_TIMEOUT BIT(6)
#define INTR_RAW_STATUS_RAW_INTR_LINE_FLAG0 BIT(8)
#define INTR_RAW_STATUS_RAW_INTR_LINE_FLAG1 BIT(9)
#define INTR_RAW_STATUS_RAW_INTR_AFIFO_OVERFLOW BIT(10)
#define INTR_RAW_STATUS_RAW_INTR_AFIFO_UNDERFLOW BIT(11)
#define INTR_RAW_STATUS_RAW_INTR_PLL_ERR BIT(12)
#define INTR_RAW_STATUS_RAW_INTR_HTPDN_ERR BIT(13)
#define INTR_RAW_STATUS_RAW_INTR_LOCKN_ERR BIT(14)
/* INTR_STATUS */
#define INTR_STATUS_INTR_FRM_ST BIT(0)
#define INTR_STATUS_INTR_PLL_LOCK BIT(1)
#define INTR_STATUS_INTR_HTPDN BIT(2)
#define INTR_STATUS_INTR_LOCKN BIT(3)
#define INTR_STATUS_INTR_PLL_TIMEOUT BIT(4)
#define INTR_STATUS_INTR_HTPDN_TIMEOUT BIT(5)
#define INTR_STATUS_INTR_LOCKN_TIMEOUT BIT(6)
#define INTR_STATUS_INTR_LINE_FLAG0 BIT(8)
#define INTR_STATUS_INTR_LINE_FLAG1 BIT(9)
#define INTR_STATUS_INTR_AFIFO_OVERFLOW BIT(10)
#define INTR_STATUS_INTR_AFIFO_UNDERFLOW BIT(11)
#define INTR_STATUS_INTR_PLL_ERR BIT(12)
#define INTR_STATUS_INTR_HTPDN_ERR BIT(13)
#define INTR_STATUS_INTR_LOCKN_ERR BIT(14)
/* COLOR_BAR_CTRL */
#define COLOR_BAR_EN BIT(0)
#define COLOR_DEPTH_RGB_YUV444_18BIT 0
#define COLOR_DEPTH_RGB_YUV444_24BIT 1
#define COLOR_DEPTH_RGB_YUV444_30BIT 2
#define COLOR_DEPTH_YUV422_16BIT 8
#define COLOR_DEPTH_YUV422_20BIT 9
enum gvi_byte_mode {
GVI_3BYTE_MODE = 0,
GVI_4BYTE_MODE,
GVI_5BYTE_MODE,
};
struct rk628_gvi {
struct drm_bridge base;
struct drm_connector connector;
struct drm_panel *panel;
struct drm_display_mode mode;
struct device *dev;
struct regmap *grf;
struct regmap *regmap;
struct clk *pclk;
struct reset_control *rst;
struct phy *phy;
struct rk628 *parent;
u32 lane_mbps;
u32 bus_format;
u32 lane_num;
u8 color_depth;
u8 byte_mode;
bool division_mode;
};
static inline struct rk628_gvi *bridge_to_gvi(struct drm_bridge *b)
{
return container_of(b, struct rk628_gvi, base);
}
static inline struct rk628_gvi *connector_to_gvi(struct drm_connector *c)
{
return container_of(c, struct rk628_gvi, connector);
}
static struct drm_encoder *rk628_gvi_connector_best_encoder(struct drm_connector
*connector)
{
struct rk628_gvi *gvi = connector_to_gvi(connector);
return gvi->base.encoder;
}
static int rk628_gvi_connector_get_modes(struct drm_connector *connector)
{
struct rk628_gvi *gvi = connector_to_gvi(connector);
struct drm_display_info *info = &connector->display_info;
int num_modes;
num_modes = drm_panel_get_modes(gvi->panel, connector);
if (info->num_bus_formats)
gvi->bus_format = info->bus_formats[0];
else
gvi->bus_format = MEDIA_BUS_FMT_RGB888_1X24;
switch (gvi->bus_format) {
case MEDIA_BUS_FMT_RGB666_1X18:
gvi->byte_mode = 3;
gvi->color_depth = COLOR_DEPTH_RGB_YUV444_18BIT;
break;
case MEDIA_BUS_FMT_RGB888_1X24:
gvi->byte_mode = 4;
gvi->color_depth = COLOR_DEPTH_RGB_YUV444_24BIT;
break;
case MEDIA_BUS_FMT_RGB101010_1X30:
gvi->byte_mode = 4;
gvi->color_depth = COLOR_DEPTH_RGB_YUV444_30BIT;
break;
case MEDIA_BUS_FMT_YUYV8_1X16:
gvi->byte_mode = 3;
gvi->color_depth = COLOR_DEPTH_YUV422_16BIT;
break;
case MEDIA_BUS_FMT_YUYV10_1X20:
gvi->byte_mode = 3;
gvi->color_depth = COLOR_DEPTH_YUV422_20BIT;
break;
default:
gvi->byte_mode = 3;
gvi->color_depth = COLOR_DEPTH_RGB_YUV444_24BIT;
dev_info(gvi->dev, "unsupported bus_format: 0x%x\n",
gvi->bus_format);
break;
}
info->edid_hdmi_rgb444_dc_modes = 0;
info->edid_hdmi_ycbcr444_dc_modes = 0;
info->hdmi.y420_dc_modes = 0;
info->color_formats = 0;
info->max_tmds_clock = 300000;
connector->ycbcr_420_allowed = true;
num_modes += rk628_scaler_add_src_mode(gvi->parent, connector);
return num_modes;
}
static const
struct drm_connector_helper_funcs rk628_gvi_connector_helper_funcs = {
.get_modes = rk628_gvi_connector_get_modes,
.best_encoder = rk628_gvi_connector_best_encoder,
};
static enum drm_connector_status
rk628_gvi_connector_detect(struct drm_connector *connector, bool force)
{
return connector_status_connected;
}
static void rk628_gvi_connector_destroy(struct drm_connector *connector)
{
drm_connector_cleanup(connector);
}
static const struct drm_connector_funcs rk628_gvi_connector_funcs = {
.detect = rk628_gvi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rk628_gvi_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static unsigned int rk628_gvi_get_lane_rate(struct rk628_gvi *gvi)
{
struct device *dev = gvi->dev;
const struct drm_display_mode *mode = &gvi->mode;
u32 lane_bit_rate, min_lane_rate = 500000, max_lane_rate = 4000000;
u64 total_bw;
/* optional override of the desired bandwidth */
if (!of_property_read_u32
(dev->of_node, "rockchip,lane-rate", &lane_bit_rate))
return lane_bit_rate;
/**
* [ENCODER TOTAL BIT-RATE](bps) = [byte mode](byte) x 10 / [pixel clock](HZ)
*
* lane_bit_rate = [total bit-rate](bps) / [lane number]
*
* 500Mbps <= lane_bit_rate <= 4Gbps
*/
total_bw = (unsigned long long)gvi->byte_mode * 10 * mode->clock; /* Kbps */
do_div(total_bw, gvi->lane_num);
lane_bit_rate = total_bw;
if (lane_bit_rate < min_lane_rate)
lane_bit_rate = min_lane_rate;
if (lane_bit_rate > max_lane_rate)
lane_bit_rate = max_lane_rate;
return lane_bit_rate;
}
static void rk628_gvi_enable_color_bar(struct rk628_gvi *gvi)
{
const struct drm_display_mode *mode = &gvi->mode;
struct videomode vm;
u16 hsync_len, hact_st, hact_end, htotal;
u16 vsync_len, vact_st, vact_end, vtotal;
drm_display_mode_to_videomode(mode, &vm);
if (gvi->division_mode) {
hsync_len = vm.hsync_len / 2;
hact_st = (vm.hsync_len + vm.hback_porch) / 2;
hact_end = (vm.hsync_len + vm.hback_porch + vm.hactive) / 2;
htotal = mode->htotal / 2;
} else {
hsync_len = vm.hsync_len;
hact_st = vm.hsync_len + vm.hback_porch;
hact_end = vm.hsync_len + vm.hback_porch + vm.hactive;
htotal = mode->htotal;
}
vsync_len = vm.vsync_len;
vact_st = vsync_len + vm.vback_porch;
vact_end = vact_st + vm.vactive;
vtotal = mode->vtotal;
regmap_write(gvi->regmap, GVI_COLOR_BAR_HTIMING0,
hact_st << 16 | hsync_len);
regmap_write(gvi->regmap, GVI_COLOR_BAR_HTIMING1,
(htotal - 1) << 16 | hact_end);
regmap_write(gvi->regmap, GVI_COLOR_BAR_VTIMING0,
vact_st << 16 | vsync_len);
regmap_write(gvi->regmap, GVI_COLOR_BAR_VTIMING1,
(vtotal - 1) << 16 | vact_end);
regmap_write_bits(gvi->regmap, GVI_COLOR_BAR_CTRL, COLOR_BAR_EN, 0);
}
static void rk628_gvi_pre_enable(struct rk628_gvi *gvi)
{
clk_prepare_enable(gvi->pclk);
/* gvi reset */
regmap_write_bits(gvi->regmap, GVI_SYS_RST, SYS_RST_SOFT_RST,
SYS_RST_SOFT_RST);
udelay(10);
regmap_write_bits(gvi->regmap, GVI_SYS_RST, SYS_RST_SOFT_RST, 0);
udelay(10);
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_LANE_NUM_MASK,
SYS_CTRL0_LANE_NUM(gvi->lane_num - 1));
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_BYTE_MODE_MASK,
SYS_CTRL0_BYTE_MODE(gvi->byte_mode ==
3 ? 0 : (gvi->byte_mode ==
4 ? 1 : 2)));
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0,
SYS_CTRL0_SECTION_NUM_MASK,
SYS_CTRL0_SECTION_NUM(gvi->division_mode));
regmap_update_bits(gvi->grf, GRF_POST_PROC_CON, SW_SPLIT_EN,
gvi->division_mode ? SW_SPLIT_EN : 0);
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL1, SYS_CTRL1_DUAL_PIXEL_EN,
gvi->division_mode ? SYS_CTRL1_DUAL_PIXEL_EN : 0);
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_FRM_RST_EN, 0);
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL1, SYS_CTRL1_LANE_ALIGN_EN, 0);
}
static void rk628_gvi_post_enable(struct rk628_gvi *gvi)
{
u32 val;
val = SYS_CTRL0_GVI_EN | SYS_CTRL0_AUTO_GATING;
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, val, 3);
}
static void rk628_gvi_bridge_enable(struct drm_bridge *bridge)
{
struct rk628_gvi *gvi = bridge_to_gvi(bridge);
unsigned int rate = rk628_gvi_get_lane_rate(gvi);
int ret;
regmap_update_bits(gvi->grf, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
SW_OUTPUT_MODE(OUTPUT_MODE_GVI));
phy_set_bus_width(gvi->phy, rate);
rk628_combtxphy_set_gvi_division_mode(gvi->phy, gvi->division_mode);
ret = phy_set_mode(gvi->phy, 0);
if (ret) {
dev_err(gvi->dev, "failed to set phy mode: %d\n", ret);
return;
}
phy_power_on(gvi->phy);
gvi->lane_mbps = phy_get_bus_width(gvi->phy);
rk628_gvi_pre_enable(gvi);
drm_panel_prepare(gvi->panel);
rk628_gvi_enable_color_bar(gvi);
rk628_gvi_post_enable(gvi);
drm_panel_enable(gvi->panel);
dev_info(gvi->dev,
"GVI-Link bandwidth: %d x %d Mbps, Byte mode: %d, Color Depty: %d, %s division mode\n",
gvi->lane_mbps, gvi->lane_num, gvi->byte_mode,
gvi->color_depth, gvi->division_mode ? "two" : "one");
}
static void rk628_gvi_post_disable(struct drm_bridge *bridge)
{
struct rk628_gvi *gvi = bridge_to_gvi(bridge);
regmap_write_bits(gvi->regmap, GVI_SYS_CTRL0, SYS_CTRL0_GVI_EN, 0);
}
static void rk628_gvi_bridge_disable(struct drm_bridge *bridge)
{
struct rk628_gvi *gvi = bridge_to_gvi(bridge);
drm_panel_disable(gvi->panel);
drm_panel_unprepare(gvi->panel);
rk628_gvi_post_disable(bridge);
clk_disable_unprepare(gvi->pclk);
phy_power_off(gvi->phy);
}
static int rk628_gvi_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rk628_gvi *gvi = bridge_to_gvi(bridge);
struct drm_connector *connector = &gvi->connector;
struct drm_device *drm = bridge->dev;
int ret;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
ret = drm_connector_init(drm, connector, &rk628_gvi_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
if (ret) {
dev_err(gvi->dev, "Failed to initialize connector with drm\n");
return ret;
}
drm_connector_helper_add(connector, &rk628_gvi_connector_helper_funcs);
drm_connector_attach_encoder(connector, bridge->encoder);
return 0;
}
static void rk628_gvi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct rk628_gvi *gvi = bridge_to_gvi(bridge);
rk628_mode_copy(gvi->parent, &gvi->mode, mode);
dev_info(gvi->dev, "src mode: %dx%d, clk: %d, dst mode: %dx%d, clk: %d\n",
mode->hdisplay, mode->vdisplay, mode->clock,
gvi->mode.hdisplay, gvi->mode.vdisplay, gvi->mode.clock);
}
static const struct drm_bridge_funcs rk628_gvi_bridge_funcs = {
.attach = rk628_gvi_bridge_attach,
.enable = rk628_gvi_bridge_enable,
.disable = rk628_gvi_bridge_disable,
.mode_set = rk628_gvi_bridge_mode_set,
};
static const struct regmap_range rk628_gvi_readable_ranges[] = {
regmap_reg_range(GVI_SYS_CTRL0, GVI_COLOR_BAR_VTIMING1),
};
static const struct regmap_access_table rk628_gvi_readable_table = {
.yes_ranges = rk628_gvi_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(rk628_gvi_readable_ranges),
};
static const struct regmap_config rk628_gvi_regmap_cfg = {
.name = "gvi",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = GVI_COLOR_BAR_VTIMING1,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
.rd_table = &rk628_gvi_readable_table,
};
static int rk628_gvi_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct rk628_gvi *gvi;
int ret = 0;
if (!of_device_is_available(dev->of_node))
return -ENODEV;
gvi = devm_kzalloc(dev, sizeof(*gvi), GFP_KERNEL);
if (!gvi)
return -ENOMEM;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
&gvi->panel, NULL);
if (ret)
return ret;
gvi->dev = dev;
gvi->parent = rk628;
gvi->division_mode = of_property_read_bool(dev->of_node,
"rockchip,division-mode");
ret = of_property_read_u32(dev->of_node, "rockchip,lane-num",
&gvi->lane_num);
if (ret) {
dev_err(gvi->dev, "Failed to get lane num\n");
gvi->lane_num = 4;
}
platform_set_drvdata(pdev, gvi);
gvi->grf = rk628->grf;
if (!gvi->grf)
return -ENODEV;
gvi->regmap = devm_regmap_init_i2c(rk628->client,
&rk628_gvi_regmap_cfg);
if (IS_ERR(gvi->regmap)) {
ret = PTR_ERR(gvi->regmap);
dev_err(dev, "failed to allocate register map: %d\n", ret);
return ret;
}
gvi->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(gvi->pclk)) {
ret = PTR_ERR(gvi->pclk);
dev_err(dev, "failed to get pclk: %d\n", ret);
return ret;
}
gvi->rst = of_reset_control_get(dev->of_node, NULL);
if (IS_ERR(gvi->rst)) {
ret = PTR_ERR(gvi->rst);
dev_err(dev, "failed to get reset control: %d\n", ret);
return ret;
}
gvi->phy = devm_of_phy_get(dev, dev->of_node, NULL);
if (IS_ERR(gvi->phy)) {
ret = PTR_ERR(gvi->phy);
dev_err(dev, "failed to get phy: %d\n", ret);
return ret;
}
gvi->base.funcs = &rk628_gvi_bridge_funcs;
gvi->base.of_node = dev->of_node;
drm_bridge_add(&gvi->base);
return 0;
}
static int rk628_gvi_remove(struct platform_device *pdev)
{
struct rk628_gvi *gvi = platform_get_drvdata(pdev);
drm_bridge_remove(&gvi->base);
return 0;
}
static const struct of_device_id rk628_gvi_of_match[] = {
{.compatible = "rockchip,rk628-gvi",},
{},
};
MODULE_DEVICE_TABLE(of, rk628_gvi_of_match);
static struct platform_driver rk628_gvi_driver = {
.driver = {
.name = "rk628-gvi",
.of_match_table = of_match_ptr(rk628_gvi_of_match),
},
.probe = rk628_gvi_probe,
.remove = rk628_gvi_remove,
};
module_platform_driver(rk628_gvi_driver);
MODULE_AUTHOR("Sandy Huang <hjc@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 GVI driver");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load Diff

View File

@@ -1,980 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Algea Cao <algea.cao@rock-chips.com>
*/
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <linux/mfd/rk628.h>
#include <linux/phy/phy.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_print.h>
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_of.h>
#define REG(x) ((x) + 0x30000)
#define HDMI_RX_HDMI_SETUP_CTRL REG(0x0000)
#define HOT_PLUG_DETECT_MASK BIT(0)
#define HOT_PLUG_DETECT(x) UPDATE(x, 0, 0)
#define HDMI_RX_HDMI_OVR_CTRL REG(0x0004)
#define HDMI_RX_HDMI_TIMER_CTRL REG(0x0008)
#define HDMI_RX_HDMI_RES_OVR REG(0x0010)
#define HDMI_RX_HDMI_RES_STS REG(0x0014)
#define HDMI_RX_HDMI_PLL_CTRL REG(0x0018)
#define HDMI_RX_HDMI_PLL_FRQSET1 REG(0x001c)
#define HDMI_RX_HDMI_PLL_FRQSET2 REG(0x0020)
#define HDMI_RX_HDMI_PLL_PAR1 REG(0x0024)
#define HDMI_RX_HDMI_PLL_PAR2 REG(0x0028)
#define HDMI_RX_HDMI_PLL_PAR3 REG(0x002c)
#define HDMI_RX_HDMI_PLL_LCK_STS REG(0x0030)
#define HDMI_RX_HDMI_CLK_CTRL REG(0x0034)
#define HDMI_RX_HDMI_PCB_CTRL REG(0x0038)
#define SEL_PIXCLKSRC_MASK GENMASK(19, 18)
#define SEL_PIXCLKSRC(x) UPDATE(x, 19, 18)
#define HDMI_RX_HDMI_PHS_CTR REG(0x0040)
#define HDMI_RX_HDMI_PHS_USED REG(0x0044)
#define HDMI_RX_HDMI_MISC_CTRL REG(0x0048)
#define HDMI_RX_HDMI_EQOFF_CTRL REG(0x004c)
#define HDMI_RX_HDMI_EQGAIN_CTRL REG(0x0050)
#define HDMI_RX_HDMI_EQCAL_STS REG(0x0054)
#define HDMI_RX_HDMI_EQRESULT REG(0x0058)
#define HDMI_RX_HDMI_EQ_MEAS_CTRL REG(0x005c)
#define HDMI_RX_HDMI_WR_CFG REG(0x0060)
#define HDMI_RX_HDMI_CTRL REG(0x0064)
#define HDMI_RX_HDMI_MODE_RECOVER REG(0x0080)
#define PREAMBLE_CNT_LIMIT_MASK GENMASK(31, 27)
#define PREAMBLE_CNT_LIMIT(x) UPDATE(x, 31, 27)
#define OESSCTL3_THR_MASK GENMASK(20, 19)
#define OESSCTL3_THR(x) UPDATE(x, 20, 19)
#define SPIKE_FILTER_EN_MASK BIT(18)
#define SPIKE_FILTER_EN(x) UPDATE(x, 18, 18)
#define DVI_MODE_HYST_MASK GENMASK(17, 13)
#define DVI_MODE_HYST(x) UPDATE(x, 17, 13)
#define HDMI_MODE_HYST_MASK GENMASK(12, 8)
#define HDMI_MODE_HYST(x) UPDATE(x, 12, 8)
#define HDMI_MODE_MASK GENMASK(7, 6)
#define HDMI_MODE(x) UPDATE(x, 7, 6)
#define GB_DET_MASK GENMASK(5, 4)
#define GB_DET(x) UPDATE(x, 5, 4)
#define EESS_OESS_MASK GENMASK(3, 2)
#define EESS_OESS(x) UPDATE(x, 3, 2)
#define SEL_CTL01_MASK GENMASK(1, 0)
#define SEL_CTL01(x) UPDATE(x, 1, 0)
#define HDMI_RX_HDMI_ERROR_PROTECT REG(0x0084)
#define RG_BLOCK_OFF_MASK BIT(20)
#define RG_BLOCK_OFF(x) UPDATE(x, 20, 20)
#define BLOCK_OFF_MASK BIT(19)
#define BLOCK_OFF(x) UPDATE(x, 19, 19)
#define VALID_MODE_MASK GENMASK(18, 16)
#define VALID_MODE(x) UPDATE(x, 18, 16)
#define CTRL_FILT_SEN_MASK GENMASK(13, 12)
#define CTRL_FILT_SEN(x) UPDATE(x, 13, 12)
#define VS_FILT_SENS_MASK GENMASK(11, 10)
#define VS_FILT_SENS(x) UPDATE(x, 11, 10)
#define HS_FILT_SENS_MASK GENMASK(9, 8)
#define HS_FILT_SENS(x) UPDATE(x, 9, 8)
#define DE_MEASURE_MODE_MASK GENMASK(7, 6)
#define DE_MEASURE_MODE(x) UPDATE(x, 7, 6)
#define DE_REGEN_MASK BIT(5)
#define DE_REGEN(x) UPDATE(x, 5, 5)
#define DE_FILTER_SENS_MASK GENMASK(4, 3)
#define DE_FILTER_SENS(x) UPDATE(x, 4, 3)
#define HDMI_RX_HDMI_ERD_STS REG(0x0088)
#define HDMI_RX_HDMI_SYNC_CTRL REG(0x0090)
#define VS_POL_ADJ_MODE_MASK GENMASK(4, 3)
#define VS_POL_ADJ_MODE(x) UPDATE(x, 4, 3)
#define HS_POL_ADJ_MODE_MASK GENMASK(2, 1)
#define HS_POL_ADJ_MODE(x) UPDATE(x, 2, 1)
#define HDMI_RX_HDMI_CKM_EVLTM REG(0x0094)
#define LOCK_HYST_MASK GENMASK(21, 20)
#define LOCK_HYST(x) UPDATE(x, 21, 20)
#define CLK_HYST_MASK GENMASK(18, 16)
#define CLK_HYST(x) UPDATE(x, 18, 16)
#define EVAL_TIME_MASK GENMASK(15, 4)
#define EVAL_TIME(x) UPDATE(x, 15, 4)
#define HDMI_RX_HDMI_CKM_F REG(0x0098)
#define HDMIRX_MAXFREQ_MASK GENMASK(31, 16)
#define HDMIRX_MAXFREQ(x) UPDATE(x, 31, 16)
#define MINFREQ_MASK GENMASK(15, 0)
#define MINFREQ(x) UPDATE(x, 15, 0)
#define HDMI_RX_HDMI_CKM_RESULT REG(0x009c)
#define HDMI_RX_HDMI_PVO_CONFIG REG(0x00a0)
#define HDMI_RX_HDMI_RESMPL_CTRL REG(0x00a4)
#define MAN_VID_DEREPEAT_MASK GENMASK(4, 1)
#define MAN_VID_DEREPEAT(x) UPDATE(x, 4, 1)
#define AUTO_DEREPEAT_MASK BIT(0)
#define AUTO_DEREPEAT(x) UPDATE(x, 0, 0)
#define HDMI_RX_HDMI_DCM_CTRL REG(0x00a8)
#define DCM_DEFAULT_PHASE_MASK BIT(18)
#define DCM_DEFAULT_PHASE(x) UPDATE(x, 18, 18)
#define DCM_COLOUR_DEPTH_SEL_MASK BIT(12)
#define DCM_COLOUR_DEPTH_SEL(x) UPDATE(x, 12, 12)
#define DCM_COLOUR_DEPTH_MASK GENMASK(11, 8)
#define DCM_COLOUR_DEPTH(x) UPDATE(x, 11, 8)
#define DCM_GCP_ZERO_FIELDS_MASK GENMASK(5, 2)
#define DCM_GCP_ZERO_FIELDS(x) UPDATE(x, 5, 2)
#define HDMI_RX_HDMI_VM_CFG_CH_0_1 REG(0x00b0)
#define HDMI_RX_HDMI_VM_CFG_CH2 REG(0x00b4)
#define HDMI_RX_HDMI_SPARE REG(0x00b8)
#define HDMI_RX_HDMI_STS REG(0x00bc)
#define HDMI_RX_HDCP_CTRL REG(0x00c0)
#define HDCP_ENABLE_MASK BIT(24)
#define HDCP_ENABLE(x) UPDATE(x, 24, 24)
#define FREEZE_HDCP_FSM_MASK BIT(21)
#define FREEZE_HDCP_FSM(x) UPDATE(x, 21, 21)
#define FREEZE_HDCP_STATE_MASK GENMASK(20, 15)
#define FREEZE_HDCP_STATE(x) UPDATE(x, 20, 15)
#define HDCP_CTL_MASK GENMASK(9, 8)
#define HDCP_CTL(x) UPDATE(x, 9, 8)
#define HDCP_RI_RATE_MASK GENMASK(7, 6)
#define HDCP_RI_RATE(x) UPDATE(x, 7, 6)
#define KEY_DECRYPT_ENABLE_MASK BIT(1)
#define KEY_DECRYPT_ENABLE(x) UPDATE(x, 1, 1)
#define HDCP_ENC_EN_MASK BIT(0)
#define HDCP_ENC_EN(x) UPDATE(x, 0, 0)
#define HDMI_RX_HDCP_SETTINGS REG(0x00c4)
#define HDMI_RX_HDCP_SEED REG(0x00c8)
#define HDMI_RX_HDCP_BKSV1 REG(0x00cc)
#define HDMI_RX_HDCP_BKSV0 REG(0x00d0)
#define HDMI_RX_HDCP_KIDX REG(0x00d4)
#define HDMI_RX_HDCP_KEY1 REG(0x00d8)
#define HDMI_RX_HDCP_KEY0 REG(0x00dc)
#define HDMI_RX_HDCP_DBG REG(0x00e0)
#define HDMI_RX_HDCP_AKSV1 REG(0x00e4)
#define HDMI_RX_HDCP_AKSV0 REG(0x00e8)
#define HDMI_RX_HDCP_AN1 REG(0x00ec)
#define HDMI_RX_HDCP_AN0 REG(0x00f0)
#define HDMI_RX_HDCP_EESS_WOO REG(0x00f4)
#define HDMI_RX_HDCP_I2C_TIMEOUT REG(0x00f8)
#define HDMI_RX_HDCP_STS REG(0x00fc)
#define HDMI_RX_MD_HCTRL1 REG(0x0140)
#define HACT_PIX_ITH_MASK GENMASK(10, 8)
#define HACT_PIX_ITH(x) UPDATE(x, 10, 8)
#define HACT_PIX_SRC_MASK BIT(5)
#define HACT_PIX_SRC(x) UPDATE(x, 5, 5)
#define HTOT_PIX_SRC_MASK BIT(4)
#define HTOT_PIX_SRC(x) UPDATE(x, 4, 4)
#define HDMI_RX_MD_HCTRL2 REG(0x0144)
#define HS_CLK_ITH_MASK GENMASK(14, 12)
#define HS_CLK_ITH(x) UPDATE(x, 14, 12)
#define HTOT32_CLK_ITH_MASK GENMASK(9, 8)
#define HTOT32_CLK_ITH(x) UPDATE(x, 9, 8)
#define VS_ACT_TIME_MASK BIT(5)
#define VS_ACT_TIME(x) UPDATE(x, 5, 5)
#define HS_ACT_TIME_MASK GENMASK(4, 3)
#define HS_ACT_TIME(x) UPDATE(x, 4, 3)
#define H_START_POS_MASK GENMASK(1, 0)
#define H_START_POS(x) UPDATE(x, 1, 0)
#define HDMI_RX_MD_HT0 REG(0x0148)
#define HDMI_RX_MD_HT1 REG(0x014c)
#define HDMI_RX_MD_HACT_PX REG(0x0150)
#define HDMI_RX_MD_HACT_RSV REG(0x0154)
#define HDMI_RX_MD_VCTRL REG(0x0158)
#define V_OFFS_LIN_MODE_MASK BIT(4)
#define V_OFFS_LIN_MODE(x) UPDATE(x, 4, 4)
#define V_EDGE_MASK BIT(1)
#define V_EDGE(x) UPDATE(x, 1, 1)
#define V_MODE_MASK BIT(0)
#define V_MODE(x) UPDATE(x, 0, 0)
#define HDMI_RX_MD_VSC REG(0x015c)
#define HDMI_RX_MD_VTC REG(0x0160)
#define HDMI_RX_MD_VOL REG(0x0164)
#define HDMI_RX_MD_VAL REG(0x0168)
#define HDMI_RX_MD_VTH REG(0x016c)
#define VOFS_LIN_ITH_MASK GENMASK(11, 10)
#define VOFS_LIN_ITH(x) UPDATE(x, 11, 10)
#define VACT_LIN_ITH_MASK GENMASK(9, 8)
#define VACT_LIN_ITH(x) UPDATE(x, 9, 8)
#define VTOT_LIN_ITH_MASK GENMASK(7, 6)
#define VTOT_LIN_ITH(x) UPDATE(x, 7, 6)
#define VS_CLK_ITH_MASK GENMASK(5, 3)
#define VS_CLK_ITH(x) UPDATE(x, 5, 3)
#define VTOT_CLK_ITH_MASK GENMASK(2, 0)
#define VTOT_CLK_ITH(x) UPDATE(x, 2, 0)
#define HDMI_RX_MD_VTL REG(0x0170)
#define HDMI_RX_MD_IL_CTRL REG(0x0174)
#define HDMI_RX_MD_IL_SKEW REG(0x0178)
#define HDMI_RX_MD_IL_POL REG(0x017c)
#define FAFIELDDET_EN_MASK BIT(2)
#define FAFIELDDET_EN(x) UPDATE(x, 2, 2)
#define FIELD_POL_MODE_MASK GENMASK(1, 0)
#define FIELD_POL_MODE(x) UPDATE(x, 1, 0)
#define HDMI_RX_MD_STS REG(0x0180)
#define HDMI_RX_AUD_CTRL REG(0x0200)
#define HDMI_RX_AUD_PLL_CTRL REG(0x0208)
#define PLL_LOCK_TOGGLE_DIV_MASK GENMASK(27, 24)
#define PLL_LOCK_TOGGLE_DIV(x) UPDATE(x, 27, 24)
#define HDMI_RX_AUD_CLK_CTRL REG(0x0214)
#define CTS_N_REF_MASK BIT(4)
#define CTS_N_REF(x) UPDATE(x, 4, 4)
#define HDMI_RX_AUD_CLK_STS REG(0x023c)
#define HDMI_RX_AUD_FIFO_CTRL REG(0x0240)
#define AFIF_SUBPACKET_DESEL_MASK GENMASK(27, 24)
#define AFIF_SUBPACKET_DESEL(x) UPDATE(x, 27, 24)
#define AFIF_SUBPACKETS_MASK BIT(16)
#define AFIF_SUBPACKETS(x) UPDATE(x, 16, 16)
#define MSA_CHANNEL_DESELECT BIT(24)
#define HDMI_RX_AUD_FIFO_TH REG(0x0244)
#define AFIF_TH_START_MASK GENMASK(26, 18)
#define AFIF_TH_START(x) UPDATE(x, 26, 18)
#define AFIF_TH_MAX_MASK GENMASK(17, 9)
#define AFIF_TH_MAX(x) UPDATE(x, 17, 9)
#define AFIF_TH_MIN_MASK GENMASK(8, 0)
#define AFIF_TH_MIN(x) UPDATE(x, 8, 0)
#define HDMI_RX_AUD_FIFO_FILL_S REG(0x0248)
#define HDMI_RX_AUD_FIFO_CLR_MM REG(0x024c)
#define HDMI_RX_AUD_FIFO_FILLSTS REG(0x0250)
#define HDMI_RX_AUD_CHEXTR_CTRL REG(0x0254)
#define AUD_LAYOUT_CTRL(x) UPDATE(x, 1, 0)
#define HDMI_RX_AUD_MUTE_CTRL REG(0x0258)
#define APPLY_INT_MUTE_MASK BIT(31)
#define APPLY_INT_MUTE(x) UPDATE(x, 31, 31)
#define APORT_SHDW_CTRL_MASK GENMASK(22, 21)
#define APORT_SHDW_CTRL(x) UPDATE(x, 22, 21)
#define AUTO_ACLK_MUTE_MASK GENMASK(20, 19)
#define AUTO_ACLK_MUTE(x) UPDATE(x, 20, 19)
#define AUD_MUTE_SPEED_MASK GENMASK(16, 10)
#define AUD_MUTE_SPEED(x) UPDATE(x, 16, 10)
#define AUD_AVMUTE_EN_MASK BIT(7)
#define AUD_AVMUTE_EN(x) UPDATE(x, 7, 7)
#define AUD_MUTE_SEL_MASK GENMASK(6, 5)
#define AUD_MUTE_SEL(x) UPDATE(x, 6, 5)
#define AUD_MUTE_MODE_MASK GENMASK(4, 3)
#define AUD_MUTE_MODE(x) UPDATE(x, 4, 3)
#define HDMI_RX_AUD_FIFO_FILLSTS1 REG(0x025c)
#define HDMI_RX_AUD_SAO_CTRL REG(0x0260)
#define I2S_LPCM_BPCUV_MASK BIT(11)
#define I2S_LPCM_BPCUV(x) UPDATE(x, 11, 11)
#define I2S_32_16_MASK BIT(0)
#define I2S_32_16(x) UPDATE(x, 0, 0)
#define HDMI_RX_AUD_PAO_CTRL REG(0x0264)
#define PAO_RATE_MASK GENMASK(17, 16)
#define PAO_RATE(x) UPDATE(x, 17, 16)
#define HDMI_RX_AUD_SPARE REG(0x0268)
#define HDMI_RX_AUD_FIFO_STS REG(0x027c)
#define HDMI_RX_AUDPLL_GEN_CTS REG(0x0280)
#define AUDPLL_CTS_MANUAL(x) UPDATE(x, 19, 0)
#define HDMI_RX_AUDPLL_GEN_N REG(0x0284)
#define AUDPLL_N_MANUAL(x) UPDATE(x, 19, 0)
#define HDMI_RX_AUDPLL_GEN_CTRL_RW1 REG(0x0288)
#define HDMI_RX_AUDPLL_GEN_CTRL_RW2 REG(0x028c)
#define HDMI_RX_AUDPLL_GEN_CTRL_W1 REG(0x0298)
#define HDMI_RX_AUDPLL_GEN_STS_RO1 REG(0x02a0)
#define HDMI_RX_AUDPLL_GEN_STS_RO2 REG(0x02a4)
#define HDMI_RX_AUDPLL_SC_NDIVCTSTH REG(0x02a8)
#define HDMI_RX_AUDPLL_SC_CTS REG(0x02ac)
#define HDMI_RX_AUDPLL_SC_N REG(0x02b0)
#define HDMI_RX_AUDPLL_SC_CTRL REG(0x02b4)
#define HDMI_RX_AUDPLL_SC_STS1 REG(0x02b8)
#define HDMI_RX_AUDPLL_SC_STS2 REG(0x02bc)
#define HDMI_RX_SNPS_PHYG3_CTRL REG(0x02c0)
#define PORTSELECT_MASK GENMASK(3, 2)
#define PORTSELECT(x) UPDATE(x, 3, 2)
#define HDMI_RX_I2CM_PHYG3_SLAVE REG(0x02c4)
#define HDMI_RX_I2CM_PHYG3_ADDRESS REG(0x02c8)
#define HDMI_RX_I2CM_PHYG3_DATAO REG(0x02cc)
#define HDMI_RX_I2CM_PHYG3_DATAI REG(0x02d0)
#define HDMI_RX_I2CM_PHYG3_OPERATION REG(0x02d4)
#define HDMI_RX_I2CM_PHYG3_MODE REG(0x02d8)
#define HDMI_RX_I2CM_PHYG3_SOFTRST REG(0x02dc)
#define HDMI_RX_I2CM_PHYG3_SS_CNTS REG(0x02e0)
#define HDMI_RX_I2CM_PHYG3_FS_HCNT REG(0x02e4)
#define HDMI_RX_JTAG_CONF REG(0x02ec)
#define HDMI_RX_JTAG_TAP_TCLK REG(0x02f0)
#define HDMI_RX_JTAG_TAP_IN REG(0x02f4)
#define HDMI_RX_JTAG_TAP_OUT REG(0x02f8)
#define HDMI_RX_JTAG_ADDR REG(0x02fc)
#define HDMI_RX_PDEC_CTRL REG(0x0300)
#define PFIFO_SCORE_FILTER_EN BIT(31)
#define PFIFO_SCORE_HDP_IF BIT(29)
#define PFIFO_SCORE_AMP_IF BIT(28)
#define PFIFO_SCORE_NTSCVBI_IF BIT(27)
#define PFIFO_SCORE_MPEGS_IF BIT(26)
#define PFIFO_SCORE_AUD_IF BIT(25)
#define PFIFO_SCORE_SPD_IF BIT(24)
#define PFIFO_SCORE_AVI_IF BIT(23)
#define PFIFO_SCORE_VS_IF BIT(22)
#define PFIFO_SCORE_GMTP BIT(21)
#define PFIFO_SCORE_ISRC2 BIT(20)
#define PFIFO_SCORE_ISRC1 BIT(19)
#define PFIFO_SCORE_ACP BIT(18)
#define PFIFO_SCORE_GCP BIT(17)
#define PFIFO_SCORE_ACR BIT(16)
#define GCP_GLOBAVMUTE BIT(15)
#define PD_FIFO_WE BIT(4)
#define PDEC_BCH_EN BIT(0)
#define HDMI_RX_PDEC_FIFO_CFG REG(0x0304)
#define PD_FIFO_TH_START_MASK GENMASK(29, 20)
#define PD_FIFO_TH_START(x) UPDATE(x, 29, 20)
#define PD_FIFO_TH_MAX_MASK GENMASK(19, 10)
#define PD_FIFO_TH_MAX(x) UPDATE(x, 19, 10)
#define PD_FIFO_TH_MIN_MASK GENMASK(9, 0)
#define PD_FIFO_TH_MIN(x) UPDATE(x, 9, 0)
#define HDMI_RX_PDEC_FIFO_STS REG(0x0308)
#define HDMI_RX_PDEC_FIFO_DATA REG(0x030c)
#define HDMI_RX_PDEC_AUDIODET_CTRL REG(0x0310)
#define AUDIODET_THRESHOLD_MASK GENMASK(13, 9)
#define AUDIODET_THRESHOLD(x) UPDATE(x, 13, 9)
#define HDMI_RX_PDEC_DBG_ACP REG(0x031c)
#define HDMI_RX_PDEC_DBG_ERR_CORR REG(0x0320)
#define HDMI_RX_PDEC_FIFO_STS1 REG(0x0324)
#define HDMI_RX_PDEC_ACRM_CTRL REG(0x0330)
#define DELTACTS_IRQTRIG_MASK GENMASK(4, 2)
#define DELTACTS_IRQTRIG(x) UPDATE(x, 4, 2)
#define HDMI_RX_PDEC_ACRM_MAX REG(0x0334)
#define HDMI_RX_PDEC_ACRM_MIN REG(0x0338)
#define HDMI_RX_PDEC_ERR_FILTER REG(0x033c)
#define HDMI_RX_PDEC_ASP_CTRL REG(0x0340)
#define HDMI_RX_PDEC_ASP_ERR REG(0x0344)
#define HDMI_RX_PDEC_STS REG(0x0360)
#define HDMI_RX_PDEC_AUD_STS REG(0x0364)
#define HDMI_RX_PDEC_VSI_PAYLOAD0 REG(0x0368)
#define HDMI_RX_PDEC_VSI_PAYLOAD1 REG(0x036c)
#define HDMI_RX_PDEC_VSI_PAYLOAD2 REG(0x0370)
#define HDMI_RX_PDEC_VSI_PAYLOAD3 REG(0x0374)
#define HDMI_RX_PDEC_VSI_PAYLOAD4 REG(0x0378)
#define HDMI_RX_PDEC_VSI_PAYLOAD5 REG(0x037c)
#define HDMI_RX_PDEC_GCP_AVMUTE REG(0x0380)
#define PKTDEC_GCP_CD_MASK GENMASK(7, 4)
#define HDMI_RX_PDEC_ACR_CTS REG(0x0390)
#define HDMI_RX_PDEC_ACR_N REG(0x0394)
#define HDMI_RX_PDEC_AVI_HB REG(0x03a0)
#define HDMI_RX_PDEC_AVI_PB REG(0x03a4)
#define VID_IDENT_CODE_VIC7 BIT(31)
#define VID_IDENT_CODE GENMASK(30, 24)
#define VIDEO_FORMAT GENMASK(6, 5)
#define HDMI_RX_PDEC_AVI_TBB REG(0x03a8)
#define HDMI_RX_PDEC_AVI_LRB REG(0x03ac)
#define HDMI_RX_PDEC_AIF_CTRL REG(0x03c0)
#define FC_LFE_EXCHG BIT(18)
#define HDMI_RX_PDEC_AIF_HB REG(0x03c4)
#define HDMI_RX_PDEC_AIF_PB0 REG(0x03c8)
#define HDMI_RX_PDEC_AIF_PB1 REG(0x03cc)
#define HDMI_RX_PDEC_GMD_HB REG(0x03d0)
#define HDMI_RX_PDEC_GMD_PB REG(0x03d4)
#define HDMI_RX_PDEC_VSI_ST0 REG(0x03e0)
#define HDMI_RX_PDEC_VSI_ST1 REG(0x03e4)
#define HDMI_RX_PDEC_VSI_PB0 REG(0x03e8)
#define HDMI_RX_PDEC_VSI_PB1 REG(0x03ec)
#define HDMI_RX_PDEC_VSI_PB2 REG(0x03f0)
#define HDMI_RX_PDEC_VSI_PB3 REG(0x03f4)
#define HDMI_RX_PDEC_VSI_PB4 REG(0x03f8)
#define HDMI_RX_PDEC_VSI_PB5 REG(0x03fc)
#define HDMI_RX_CEAVID_CONFIG REG(0x0400)
#define HDMI_RX_CEAVID_3DCONFIG REG(0x0404)
#define HDMI_RX_CEAVID_HCONFIG_LO REG(0x0408)
#define HDMI_RX_CEAVID_HCONFIG_HI REG(0x040c)
#define HDMI_RX_CEAVID_VCONFIG_LO REG(0x0410)
#define HDMI_RX_CEAVID_VCONFIG_HI REG(0x0414)
#define HDMI_RX_CEAVID_STATUS REG(0x0418)
#define HDMI_RX_PDEC_AMP_HB REG(0x0480)
#define HDMI_RX_PDEC_AMP_PAYLOAD0 REG(0x0484)
#define HDMI_RX_PDEC_AMP_PAYLOAD1 REG(0x0488)
#define HDMI_RX_PDEC_AMP_PAYLOAD2 REG(0x048c)
#define HDMI_RX_PDEC_AMP_PAYLOAD3 REG(0x0490)
#define HDMI_RX_PDEC_AMP_PAYLOAD4 REG(0x0494)
#define HDMI_RX_PDEC_AMP_PAYLOAD5 REG(0x0498)
#define HDMI_RX_PDEC_AMP_PAYLOAD6 REG(0x049c)
#define HDMI_RX_PDEC_NTSCVBI_HB REG(0x04a0)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD0 REG(0x04a4)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD1 REG(0x04a8)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD2 REG(0x04ac)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD3 REG(0x04b0)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD4 REG(0x04b4)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD5 REG(0x04b8)
#define HDMI_RX_PDEC_NTSCVBI_PAYLOAD6 REG(0x04bc)
#define HDMI_RX_PDEC_DRM_HB REG(0x04c0)
#define HDMI_RX_PDEC_DRM_PAYLOAD0 REG(0x04c4)
#define HDMI_RX_PDEC_DRM_PAYLOAD1 REG(0x04c8)
#define HDMI_RX_PDEC_DRM_PAYLOAD2 REG(0x04cc)
#define HDMI_RX_PDEC_DRM_PAYLOAD3 REG(0x04d0)
#define HDMI_RX_PDEC_DRM_PAYLOAD4 REG(0x04d4)
#define HDMI_RX_PDEC_DRM_PAYLOAD5 REG(0x04d8)
#define HDMI_RX_PDEC_DRM_PAYLOAD6 REG(0x04dc)
#define HDMI_RX_MHLMODE_CTRL REG(0x0500)
#define HDMI_RX_CDSENSE_STATUS REG(0x0504)
#define HDMI_RX_DESERFIFO_CTRL REG(0x0508)
#define HDMI_RX_DESER_INTTRSHCTRL REG(0x050c)
#define HDMI_RX_DESER_INTCNTCTRL REG(0x0510)
#define HDMI_RX_DESER_INTCNT REG(0x0514)
#define HDMI_RX_HDCP_RPT_CTRL REG(0x0600)
#define HDMI_RX_HDCP_RPT_BSTATUS REG(0x0604)
#define HDMI_RX_HDCP_RPT_KSVFIFO_CTRL REG(0x0608)
#define HDMI_RX_HDCP_RPT_KSVFIFO1 REG(0x060c)
#define HDMI_RX_HDCP_RPT_KSVFIFO0 REG(0x0610)
#define HDMI_RX_HDMI20_CONTROL REG(0x0800)
#define HDMI_RX_SCDC_I2CCONFIG REG(0x0804)
#define I2CSPIKESUPPR_MASK GENMASK(25, 24)
#define I2CSPIKESUPPR(x) UPDATE(x, 25, 24)
#define HDMI_RX_SCDC_CONFIG REG(0x0808)
#define HDMI_RX_CHLOCK_CONFIG REG(0x080c)
#define CHLOCKMAXER_MASK GENMASK(29, 20)
#define CHLOCKMAXER(x) UPDATE(x, 29, 20)
#define MILISECTIMERLIMIT_MASK GENMASK(15, 0)
#define MILISECTIMERLIMIT(x) UPDATE(x, 15, 0)
#define HDMI_RX_HDCP22_CONTROL REG(0x081c)
#define HDMI_RX_SCDC_REGS0 REG(0x0820)
#define HDMI_RX_SCDC_REGS1 REG(0x0824)
#define HDMI_RX_SCDC_REGS2 REG(0x0828)
#define HDMI_RX_SCDC_REGS3 REG(0x082c)
#define HDMI_RX_SCDC_MANSPEC0 REG(0x0840)
#define HDMI_RX_SCDC_MANSPEC1 REG(0x0844)
#define HDMI_RX_SCDC_MANSPEC2 REG(0x0848)
#define HDMI_RX_SCDC_MANSPEC3 REG(0x084c)
#define HDMI_RX_SCDC_MANSPEC4 REG(0x0850)
#define HDMI_RX_SCDC_WRDATA0 REG(0x0860)
#define MANUFACTUREROUI_MASK GENMASK(31, 8)
#define MANUFACTUREROUI(x) UPDATE(x, 31, 8)
#define SINKVERSION_MASK GENMASK(7, 0)
#define SINKVERSION(x) UPDATE(x, 7, 0)
#define HDMI_RX_SCDC_WRDATA1 REG(0x0864)
#define HDMI_RX_SCDC_WRDATA2 REG(0x0868)
#define HDMI_RX_SCDC_WRDATA3 REG(0x086c)
#define HDMI_RX_SCDC_WRDATA4 REG(0x0870)
#define HDMI_RX_SCDC_WRDATA5 REG(0x0874)
#define HDMI_RX_SCDC_WRDATA6 REG(0x0878)
#define HDMI_RX_SCDC_WRDATA7 REG(0x087c)
#define HDMI_RX_HDMI20_STATUS REG(0x08e0)
#define HDMI_RX_HDCP2_ESM_GLOBAL_GPIO_IN REG(0x08e8)
#define HDMI_RX_HDCP2_ESM_GLOBAL_GPIO_OUT REG(0x08ec)
#define HDMI_RX_HDCP2_ESM_P0_GPIO_IN REG(0x08f0)
#define HDMI_RX_HDCP2_ESM_P0_GPIO_OUT REG(0x08f4)
#define HDMI_RX_HDCP22_STATUS REG(0x08fc)
#define HDMI_RX_HDMI2_IEN_CLR REG(0x0f60)
#define HDMI_RX_HDMI2_IEN_SET REG(0x0f64)
#define HDMI_RX_HDMI2_ISTS REG(0x0f68)
#define HDMI_RX_HDMI2_IEN REG(0x0f6c)
#define HDMI_RX_HDMI2_ICLR REG(0x0f70)
#define HDMI_RX_HDMI2_ISET REG(0x0f74)
#define HDMI_RX_PDEC_IEN_CLR REG(0x0f78)
#define HDMI_RX_PDEC_IEN_SET REG(0x0f7c)
#define HDMI_RX_PDEC_ISTS REG(0x0f80)
#define HDMI_RX_PDEC_IEN REG(0x0f84)
#define HDMI_RX_PDEC_ICLR REG(0x0f88)
#define HDMI_RX_PDEC_ISET REG(0x0f8c)
#define HDMI_RX_AUD_CEC_IEN_CLR REG(0x0f90)
#define HDMI_RX_AUD_CEC_IEN_SET REG(0x0f94)
#define HDMI_RX_AUD_CEC_ISTS REG(0x0f98)
#define HDMI_RX_AUD_CEC_IEN REG(0x0f9c)
#define HDMI_RX_AUD_CEC_ICLR REG(0x0fa0)
#define HDMI_RX_AUD_CEC_ISET REG(0x0fa4)
#define HDMI_RX_AUD_FIFO_IEN_CLR REG(0x0fa8)
#define HDMI_RX_AUD_FIFO_IEN_SET REG(0x0fac)
#define HDMI_RX_AUD_FIFO_ISTS REG(0x0fb0)
#define HDMI_RX_AUD_FIFO_IEN REG(0x0fb4)
#define HDMI_RX_AUD_FIFO_ICLR REG(0x0fb8)
#define HDMI_RX_AUD_FIFO_ISET REG(0x0fbc)
#define HDMI_RX_MD_IEN_CLR REG(0x0fc0)
#define HDMI_RX_MD_IEN_SET REG(0x0fc4)
#define HDMI_RX_MD_ISTS REG(0x0fc8)
#define HDMI_RX_MD_IEN REG(0x0fcc)
#define HDMI_RX_MD_ICLR REG(0x0fd0)
#define HDMI_RX_MD_ISET REG(0x0fd4)
#define HDMI_RX_HDMI_IEN_CLR REG(0x0fd8)
#define HDMI_RX_HDMI_IEN_SET REG(0x0fdc)
#define HDCP_DKSET_DONE_ENCLR_MASK BIT(31)
#define HDCP_DKSET_DONE_ENCLR(x) UPDATE(x, 31, 31)
#define HDMI_RX_HDMI_ISTS REG(0x0fe0)
#define HDMI_RX_HDMI_IEN REG(0x0fe4)
#define HDMI_RX_HDMI_ICLR REG(0x0fe8)
#define HDMI_RX_HDMI_ISET REG(0x0fec)
#define HDMI_RX_DMI_SW_RST REG(0x0ff0)
#define HDMI_RX_DMI_DISABLE_IF REG(0x0ff4)
#define MAIN_ENABLE BIT(0)
#define MODET_ENABLE BIT(1)
#define HDMI_ENABLE BIT(2)
#define BUS_ENABLE BIT(3)
#define AUD_ENABLE BIT(4)
#define CEC_ENABLE BIT(5)
#define PIXEL_ENABLE BIT(6)
#define VID_ENABLE BIT(7)
#define TMDS_ENABLE_MASK BIT(16)
#define TMDS_ENABLE(x) UPDATE(x, 16, 16)
#define HDMI_RX_DMI_MODULE_ID_EXT REG(0x0ff8)
#define HDMI_RX_DMI_MODULE_ID REG(0x0ffc)
#define HDMI_RX_CEC_CTRL REG(0x1f00)
#define HDMI_RX_CEC_MASK REG(0x1f08)
#define HDMI_RX_CEC_ADDR_L REG(0x1f14)
#define HDMI_RX_CEC_ADDR_H REG(0x1f18)
#define HDMI_RX_CEC_TX_CNT REG(0x1f1c)
#define HDMI_RX_CEC_RX_CNT REG(0x1f20)
#define HDMI_RX_CEC_TX_DATA_0 REG(0x1f40)
#define HDMI_RX_CEC_TX_DATA_1 REG(0x1f44)
#define HDMI_RX_CEC_TX_DATA_2 REG(0x1f48)
#define HDMI_RX_CEC_TX_DATA_3 REG(0x1f4c)
#define HDMI_RX_CEC_TX_DATA_4 REG(0x1f50)
#define HDMI_RX_CEC_TX_DATA_5 REG(0x1f54)
#define HDMI_RX_CEC_TX_DATA_6 REG(0x1f58)
#define HDMI_RX_CEC_TX_DATA_7 REG(0x1f5c)
#define HDMI_RX_CEC_TX_DATA_8 REG(0x1f60)
#define HDMI_RX_CEC_TX_DATA_9 REG(0x1f64)
#define HDMI_RX_CEC_TX_DATA_10 REG(0x1f68)
#define HDMI_RX_CEC_TX_DATA_11 REG(0x1f6c)
#define HDMI_RX_CEC_TX_DATA_12 REG(0x1f70)
#define HDMI_RX_CEC_TX_DATA_13 REG(0x1f74)
#define HDMI_RX_CEC_TX_DATA_14 REG(0x1f78)
#define HDMI_RX_CEC_TX_DATA_15 REG(0x1f7c)
#define HDMI_RX_CEC_RX_DATA_0 REG(0x1f80)
#define HDMI_RX_CEC_RX_DATA_1 REG(0x1f84)
#define HDMI_RX_CEC_RX_DATA_2 REG(0x1f88)
#define HDMI_RX_CEC_RX_DATA_3 REG(0x1f8c)
#define HDMI_RX_CEC_RX_DATA_4 REG(0x1f90)
#define HDMI_RX_CEC_RX_DATA_5 REG(0x1f94)
#define HDMI_RX_CEC_RX_DATA_6 REG(0x1f98)
#define HDMI_RX_CEC_RX_DATA_7 REG(0x1f9c)
#define HDMI_RX_CEC_RX_DATA_8 REG(0x1fa0)
#define HDMI_RX_CEC_RX_DATA_9 REG(0x1fa4)
#define HDMI_RX_CEC_RX_DATA_10 REG(0x1fa8)
#define HDMI_RX_CEC_RX_DATA_11 REG(0x1fac)
#define HDMI_RX_CEC_RX_DATA_12 REG(0x1fb0)
#define HDMI_RX_CEC_RX_DATA_13 REG(0x1fb4)
#define HDMI_RX_CEC_RX_DATA_14 REG(0x1fb8)
#define HDMI_RX_CEC_RX_DATA_15 REG(0x1fbc)
#define HDMI_RX_CEC_LOCK REG(0x1fc0)
#define HDMI_RX_CEC_WAKEUPCTRL REG(0x1fc4)
#define HDMI_RX_CBUSSWRESETREQ REG(0x3000)
#define HDMI_RX_CBUSENABLEIF REG(0x3004)
#define HDMI_RX_CB_LOCKONCLOCK_STS REG(0x3010)
#define HDMI_RX_CB_LOCKONCLOCKCLR REG(0x3014)
#define HDMI_RX_CBUSIOCTRL REG(0x3020)
#define HDMI_RX_DD_CTRL REG(0x3040)
#define HDMI_RX_DD_OP_CTRL REG(0x3044)
#define HDMI_RX_DD_STS REG(0x3048)
#define HDMI_RX_DD_BYPASS_EN REG(0x304c)
#define HDMI_RX_DD_BYPASS_CTRL REG(0x3050)
#define HDMI_RX_DD_BYPASS_CBUS REG(0x3054)
#define HDMI_RX_LL_TXPCKFIFO REG(0x3080)
#define HDMI_RX_LL_RXPCKFIFO_RD_CLR REG(0x3084)
#define HDMI_RX_LL_RXPCKFIFO_A REG(0x3088)
#define HDMI_RX_LL_RXPCKFIFO_B REG(0x308c)
#define HDMI_RX_LL_TXPCKCTRL_0 REG(0x3090)
#define HDMI_RX_LL_TXPCKCTRL_1 REG(0x3094)
#define HDMI_RX_LL_PCKFIFO_STS REG(0x309c)
#define HDMI_RX_LL_RXPCKCTRL_0 REG(0x30a0)
#define HDMI_RX_LL_RXPCKCTRL_1 REG(0x30a4)
#define HDMI_RX_LL_INTTRSHLDCTRL REG(0x30b0)
#define HDMI_RX_LL_INTCNTCTRL REG(0x30b4)
#define HDMI_RX_LL_INTCNT_0 REG(0x30b8)
#define HDMI_RX_LL_INTCNT_1 REG(0x30bc)
#define HDMI_RX_CBHDCP_OPCTRL REG(0x3100)
#define HDMI_RX_CBHDCP_WDATA_0 REG(0x3104)
#define HDMI_RX_CBHDCP_WDATA_1 REG(0x3108)
#define HDMI_RX_CBHDCP_RDATA_0 REG(0x310c)
#define HDMI_RX_CBHDCP_RDATA_1 REG(0x3110)
#define HDMI_RX_CBHDCP_STATUS REG(0x3114)
#define HDMI_RX_CBHDCP_DDC_REPORT REG(0x3118)
#define HDMI_RX_ISTAT_CB_DD REG(0x3200)
#define HDMI_RX_IMASK_CB_DD REG(0x3204)
#define HDMI_RX_IFORCE_CB_DD REG(0x3208)
#define HDMI_RX_ICLEAR_CB_DD REG(0x320c)
#define HDMI_RX_IMUTE_CB_DD REG(0x3210)
#define HDMI_RX_ISTAT_CB_LL REG(0x3220)
#define HDMI_RX_IMASK_CB_LL REG(0x3224)
#define HDMI_RX_IFORCE_CB_LL REG(0x3228)
#define HDMI_RX_ICLEAR_CB_LL REG(0x322c)
#define HDMI_RX_IMUTE_CB_LL REG(0x3230)
#define HDMI_RX_ISTAT_CB_HDCP REG(0x3240)
#define HDMI_RX_IMASK_CB_HDCP REG(0x3244)
#define HDMI_RX_IFORCE_CB_HDCP REG(0x3248)
#define HDMI_RX_ICLEAR_CB_HDCP REG(0x324c)
#define HDMI_RX_IMUTE_CB_HDCP REG(0x3250)
#define HDMI_RX_ISTAT_CB_MCTRL REG(0x3260)
#define HDMI_RX_IMASK_CB_MCTRL REG(0x3264)
#define HDMI_RX_IFORCE_CB_MCTRL REG(0x3268)
#define HDMI_RX_ICLEAR_CB_MCTRL REG(0x326c)
#define HDMI_RX_IMUTE_CB_MCTRL REG(0x3270)
#define HDMI_RX_IMASTER_MUTE_CB REG(0x32e0)
#define HDMI_RX_IVECTOR_INDEX_CB REG(0x32e4)
#define HDMI_RX_MAX_REGISTER HDMI_RX_IVECTOR_INDEX_CB
struct rk628_hdmirx {
struct drm_bridge base;
struct drm_bridge *bridge;
struct device *dev;
struct regmap *regmap;
struct regmap *grf;
struct phy *phy;
struct clk *pclk;
struct clk *cec_clk;
struct clk *aud_clk;
struct clk *imodet_clk;
struct reset_control *hdmirx;
struct reset_control *hdmirx_pon;
struct rk628 *parent;
struct drm_display_mode mode;
};
static const struct regmap_range rk628_hdmirx_readable_ranges[] = {
regmap_reg_range(HDMI_RX_HDMI_SETUP_CTRL, HDMI_RX_HDMI_TIMER_CTRL),
regmap_reg_range(HDMI_RX_HDMI_MODE_RECOVER, HDMI_RX_HDMI_ERD_STS),
regmap_reg_range(HDMI_RX_MD_HCTRL1, HDMI_RX_MD_STS),
regmap_reg_range(HDMI_RX_PDEC_ACRM_CTRL, HDMI_RX_PDEC_ASP_ERR),
regmap_reg_range(HDMI_RX_PDEC_AVI_HB, HDMI_RX_PDEC_AVI_LRB),
regmap_reg_range(HDMI_RX_PDEC_AIF_CTRL, HDMI_RX_PDEC_GMD_PB),
regmap_reg_range(HDMI_RX_HDMI20_CONTROL, HDMI_RX_CHLOCK_CONFIG),
regmap_reg_range(HDMI_RX_SCDC_REGS1, HDMI_RX_SCDC_REGS3),
regmap_reg_range(HDMI_RX_SCDC_WRDATA0, HDMI_RX_SCDC_WRDATA7),
regmap_reg_range(HDMI_RX_DMI_DISABLE_IF, HDMI_RX_DMI_DISABLE_IF),
};
static const struct regmap_access_table rk628_hdmirx_readable_table = {
.yes_ranges = rk628_hdmirx_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(rk628_hdmirx_readable_ranges),
};
static const struct regmap_config rk628_hdmirx_regmap_config = {
.name = "hdmirx",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = HDMI_RX_MAX_REGISTER,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
.rd_table = &rk628_hdmirx_readable_table,
};
static inline struct rk628_hdmirx *bridge_to_hdmirx(struct drm_bridge *bridge)
{
return container_of(bridge, struct rk628_hdmirx, base);
}
static void rk628_hdmirx_ctrl_enable(struct rk628_hdmirx *hdmirx)
{
clk_prepare_enable(hdmirx->pclk);
clk_prepare_enable(hdmirx->aud_clk);
clk_prepare_enable(hdmirx->imodet_clk);
reset_control_deassert(hdmirx->hdmirx);
reset_control_deassert(hdmirx->hdmirx_pon);
regmap_update_bits(hdmirx->grf, GRF_SYSTEM_CON0,
SW_INPUT_MODE_MASK,
SW_INPUT_MODE(INPUT_MODE_HDMI));
regmap_write(hdmirx->regmap, HDMI_RX_DMI_SW_RST, 0x000101ff);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF, 0x00000000);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF, 0x0000017f);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF, 0x0001017f);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI20_CONTROL, 0x10001f10);
regmap_update_bits(hdmirx->regmap, HDMI_RX_CHLOCK_CONFIG,
CHLOCKMAXER_MASK | MILISECTIMERLIMIT_MASK,
CHLOCKMAXER(0x1) | MILISECTIMERLIMIT(49500));
regmap_write(hdmirx->regmap, HDMI_RX_SCDC_CONFIG, 0x00000001);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_SW_RST, 0x000001fe);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_CKM_EVLTM, 0x0016fff0);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_CKM_F, 0xf98a0190);
regmap_update_bits(hdmirx->regmap, HDMI_RX_HDMI_MODE_RECOVER,
SPIKE_FILTER_EN_MASK | DVI_MODE_HYST_MASK |
HDMI_MODE_HYST_MASK | HDMI_MODE_MASK |
GB_DET_MASK | EESS_OESS_MASK | SEL_CTL01_MASK,
SPIKE_FILTER_EN(0) |
DVI_MODE_HYST(0) |
HDMI_MODE_HYST(0) |
HDMI_MODE(3) |
GB_DET(2) |
EESS_OESS(0) |
SEL_CTL01(1));
regmap_write(hdmirx->regmap, HDMI_RX_PDEC_CTRL, 0xbfff8011);
regmap_write(hdmirx->regmap, HDMI_RX_PDEC_ASP_CTRL, 0x00000040);
regmap_update_bits(hdmirx->regmap, HDMI_RX_HDMI_RESMPL_CTRL,
MAN_VID_DEREPEAT_MASK, MAN_VID_DEREPEAT(1));
regmap_update_bits(hdmirx->regmap, HDMI_RX_HDMI_SYNC_CTRL,
VS_POL_ADJ_MODE_MASK | HS_POL_ADJ_MODE_MASK,
VS_POL_ADJ_MODE(2) | HS_POL_ADJ_MODE(2));
regmap_write(hdmirx->regmap, HDMI_RX_PDEC_ERR_FILTER, 0x00000008);
regmap_update_bits(hdmirx->regmap, HDMI_RX_SCDC_I2CCONFIG,
I2CSPIKESUPPR_MASK, I2CSPIKESUPPR(1));
regmap_write(hdmirx->regmap, HDMI_RX_SCDC_CONFIG, 0x00000001);
regmap_write(hdmirx->regmap, HDMI_RX_SCDC_WRDATA0, 0xabcdef01);
regmap_update_bits(hdmirx->regmap, HDMI_RX_CHLOCK_CONFIG,
CHLOCKMAXER_MASK | MILISECTIMERLIMIT_MASK,
CHLOCKMAXER(0x1) | MILISECTIMERLIMIT(49500));
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_ERROR_PROTECT, 0x000d0c98);
regmap_write(hdmirx->regmap, HDMI_RX_MD_HCTRL1, 0x00000010);
regmap_write(hdmirx->regmap, HDMI_RX_MD_HCTRL2, 0x00001738);
regmap_write(hdmirx->regmap, HDMI_RX_MD_VCTRL, 0x00000012);
regmap_write(hdmirx->regmap, HDMI_RX_MD_VTH, 0x0000073a);
regmap_write(hdmirx->regmap, HDMI_RX_MD_IL_POL, 0x00000004);
regmap_write(hdmirx->regmap, HDMI_RX_PDEC_ACRM_CTRL, 0x00000000);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_DCM_CTRL, 0x00040414);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_PCB_CTRL, 0x00100000);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_SETUP_CTRL, 0x0f000fff);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_CKM_EVLTM, 0x00104260);
regmap_write(hdmirx->regmap, HDMI_RX_HDMI_CKM_F, 0x0f2d0eed);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF, 0x00000001);
udelay(400);
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF, 0x0001017f);
regmap_update_bits(hdmirx->regmap, HDMI_RX_HDMI_RESMPL_CTRL,
MAN_VID_DEREPEAT_MASK, MAN_VID_DEREPEAT(1));
regmap_write(hdmirx->regmap, HDMI_RX_DMI_SW_RST, 0x000001fe);
}
static void rk628_hdmirx_ctrl_disable(struct rk628_hdmirx *hdmirx)
{
reset_control_assert(hdmirx->hdmirx);
reset_control_assert(hdmirx->hdmirx_pon);
clk_disable_unprepare(hdmirx->pclk);
clk_disable_unprepare(hdmirx->aud_clk);
clk_disable_unprepare(hdmirx->imodet_clk);
}
static void rk628_hdmirx_bridge_enable(struct drm_bridge *bridge)
{
bool locked;
u32 value, i, hact, vact, bus_width, hdisplay, vdisplay;
struct rk628_hdmirx *hdmirx = bridge_to_hdmirx(bridge);
/* force 594m mode to yuv420 format */
if (hdmirx->mode.clock == 594000) {
/*
* bit30 is used to indicate whether it is
* yuv420 format
*/
bus_width = hdmirx->mode.clock | BIT(30);
hdisplay = hdmirx->mode.hdisplay / 2;
} else {
bus_width = hdmirx->mode.clock;
hdisplay = hdmirx->mode.hdisplay;
}
vdisplay = hdmirx->mode.vdisplay;
phy_set_bus_width(hdmirx->phy, bus_width);
phy_power_on(hdmirx->phy);
usleep_range(10*1000, 11*1000);
rk628_hdmirx_ctrl_enable(hdmirx);
/* if hdmirx ctrl unlock or get incorrect timing, reset ctrl and phy */
for (i = 0; i < 5; i++) {
usleep_range(100*1000, 110*1000);
regmap_read(hdmirx->regmap, HDMI_RX_SCDC_REGS1, &value);
dev_dbg(hdmirx->dev, "HDMI_RX_SCDC_REGS1:0x%x\n", value);
value = (value >> 8) & 0xf;
regmap_read(hdmirx->regmap, HDMI_RX_MD_HACT_PX, &hact);
regmap_read(hdmirx->regmap, HDMI_RX_MD_VAL, &vact);
hact = hact & 0xffff;
vact = vact & 0xffff;
dev_dbg(hdmirx->dev, "hact:%d,vact:%d\n", hact, vact);
if (value == 0xf && hact == hdisplay && vact == vdisplay)
locked = true;
else
locked = false;
if (!locked) {
rk628_hdmirx_ctrl_disable(hdmirx);
usleep_range(10*1000, 11*1000);
phy_power_off(hdmirx->phy);
usleep_range(10*1000, 11*1000);
phy_power_on(hdmirx->phy);
usleep_range(10*1000, 11*1000);
rk628_hdmirx_ctrl_enable(hdmirx);
} else {
/* hdmirx ctrl get correct timing, enable output */
regmap_write(hdmirx->regmap, HDMI_RX_DMI_DISABLE_IF,
0x000001ff);
return;
}
}
dev_err(hdmirx->dev, "hdmirx channel can't lock!\n");
}
static void rk628_hdmirx_bridge_disable(struct drm_bridge *bridge)
{
struct rk628_hdmirx *hdmirx = bridge_to_hdmirx(bridge);
rk628_hdmirx_ctrl_disable(hdmirx);
phy_power_off(hdmirx->phy);
}
static int rk628_hdmirx_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rk628_hdmirx *hdmirx = bridge_to_hdmirx(bridge);
struct device *dev = hdmirx->dev;
int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
NULL, &hdmirx->bridge);
if (ret) {
dev_err(dev, "failed to find next bridge\n");
return ret;
}
ret = drm_bridge_attach(bridge->encoder, hdmirx->bridge, bridge, flags);
if (ret) {
dev_err(dev, "failed to attach bridge\n");
return ret;
}
return 0;
}
static void rk628_hdmirx_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct rk628_hdmirx *hdmirx = bridge_to_hdmirx(bridge);
drm_mode_copy(&hdmirx->mode, adj);
}
static const struct drm_bridge_funcs rk628_hdmirx_bridge_funcs = {
.attach = rk628_hdmirx_bridge_attach,
.enable = rk628_hdmirx_bridge_enable,
.disable = rk628_hdmirx_bridge_disable,
.mode_set = rk628_hdmirx_bridge_mode_set,
};
static int rk628_hdmirx_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct platform_device_info pdevinfo;
struct rk628_hdmirx *hdmirx;
int ret, irq;
if (!of_device_is_available(dev->of_node))
return -ENODEV;
hdmirx = devm_kzalloc(dev, sizeof(*hdmirx), GFP_KERNEL);
if (!hdmirx)
return -ENOMEM;
hdmirx->dev = dev;
hdmirx->parent = rk628;
platform_set_drvdata(pdev, hdmirx);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
hdmirx->grf = rk628->grf;
if (!hdmirx->grf)
return -ENODEV;
hdmirx->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(hdmirx->pclk)) {
ret = PTR_ERR(hdmirx->pclk);
dev_err(dev, "failed to get pclk: %d\n", ret);
return ret;
}
hdmirx->cec_clk = devm_clk_get(dev, "cec");
if (IS_ERR(hdmirx->cec_clk)) {
ret = PTR_ERR(hdmirx->cec_clk);
dev_err(dev, "failed to get cec clk: %d\n", ret);
return ret;
}
hdmirx->aud_clk = devm_clk_get(dev, "audio");
if (IS_ERR(hdmirx->aud_clk)) {
ret = PTR_ERR(hdmirx->aud_clk);
dev_err(dev, "failed to get audio clk: %d\n", ret);
return ret;
}
hdmirx->imodet_clk = devm_clk_get(dev, "imodet");
if (IS_ERR(hdmirx->imodet_clk)) {
ret = PTR_ERR(hdmirx->imodet_clk);
dev_err(dev, "failed to get imodet clk: %d\n", ret);
return ret;
}
hdmirx->hdmirx = of_reset_control_get(dev->of_node, "hdmirx");
if (IS_ERR(hdmirx->hdmirx)) {
ret = PTR_ERR(hdmirx->hdmirx);
DRM_DEV_ERROR(dev, "failed to get hdmirx control: %d\n", ret);
return ret;
}
hdmirx->hdmirx_pon = of_reset_control_get(dev->of_node, "hdmirx_pon");
if (IS_ERR(hdmirx->hdmirx_pon)) {
ret = PTR_ERR(hdmirx->hdmirx_pon);
DRM_DEV_ERROR(dev, "failed to get hdmirx_pon control: %d\n", ret);
return ret;
}
hdmirx->phy = devm_of_phy_get(dev, dev->of_node, NULL);
if (IS_ERR(hdmirx->phy)) {
ret = PTR_ERR(hdmirx->phy);
dev_err(dev, "failed to get phy: %d\n", ret);
return ret;
}
hdmirx->regmap = devm_regmap_init_i2c(rk628->client,
&rk628_hdmirx_regmap_config);
if (IS_ERR(hdmirx->regmap)) {
ret = PTR_ERR(hdmirx->regmap);
dev_err(dev, "failed to allocate register map: %d\n", ret);
return ret;
}
hdmirx->base.funcs = &rk628_hdmirx_bridge_funcs;
hdmirx->base.of_node = dev->of_node;
drm_bridge_add(&hdmirx->base);
memset(&pdevinfo, 0, sizeof(pdevinfo));
pdevinfo.parent = dev;
pdevinfo.id = PLATFORM_DEVID_AUTO;
return 0;
}
static int rk628_hdmirx_remove(struct platform_device *pdev)
{
struct rk628_hdmirx *hdmirx = platform_get_drvdata(pdev);
drm_bridge_remove(&hdmirx->base);
return 0;
}
static const struct of_device_id rk628_hdmirx_of_match[] = {
{ .compatible = "rockchip,rk628-hdmirx", },
{},
};
MODULE_DEVICE_TABLE(of, rk628_hdmirx_of_match);
static struct platform_driver rk628_hdmirx_driver = {
.driver = {
.name = "rk628-hdmirx",
.of_match_table = of_match_ptr(rk628_hdmirx_of_match),
},
.probe = rk628_hdmirx_probe,
.remove = rk628_hdmirx_remove,
};
module_platform_driver(rk628_hdmirx_driver);
MODULE_AUTHOR("Algea Cao <algea.cao@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 HDMI RX driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1,320 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/media-bus-format.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/mfd/rk628.h>
#include <linux/phy/phy.h>
#include <drm/drm_of.h>
#include <drm/drm_atomic.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
enum lvds_format {
LVDS_FORMAT_VESA_24BIT,
LVDS_FORMAT_JEIDA_24BIT,
LVDS_FORMAT_JEIDA_18BIT,
LVDS_FORMAT_VESA_18BIT,
};
enum lvds_link_type {
LVDS_SINGLE_LINK,
LVDS_DUAL_LINK_ODD_EVEN_PIXELS,
LVDS_DUAL_LINK_EVEN_ODD_PIXELS,
LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS,
LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS,
};
struct rk628_lvds {
struct drm_bridge base;
struct drm_connector connector;
struct drm_panel *panel;
struct drm_display_mode mode;
struct device *dev;
struct regmap *grf;
struct phy *phy;
struct rk628 *parent;
enum lvds_format format;
enum lvds_link_type link_type;
};
static inline struct rk628_lvds *bridge_to_lvds(struct drm_bridge *b)
{
return container_of(b, struct rk628_lvds, base);
}
static inline struct rk628_lvds *connector_to_lvds(struct drm_connector *c)
{
return container_of(c, struct rk628_lvds, connector);
}
static enum lvds_format rk628_lvds_get_format(u32 bus_format)
{
switch (bus_format) {
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
return LVDS_FORMAT_JEIDA_24BIT;
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
return LVDS_FORMAT_VESA_18BIT;
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
default:
return LVDS_FORMAT_VESA_24BIT;
}
}
static enum lvds_link_type rk628_lvds_get_link_type(struct rk628_lvds *lvds)
{
struct device *dev = lvds->dev;
const char *str;
int ret;
ret = of_property_read_string(dev->of_node, "rockchip,link-type", &str);
if (ret < 0)
return LVDS_SINGLE_LINK;
if (!strcmp(str, "dual-link-odd-even-pixels"))
return LVDS_DUAL_LINK_ODD_EVEN_PIXELS;
else if (!strcmp(str, "dual-link-even-odd-pixels"))
return LVDS_DUAL_LINK_EVEN_ODD_PIXELS;
else if (!strcmp(str, "dual-link-left-right-pixels"))
return LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS;
else if (!strcmp(str, "dual-link-right-left-pixels"))
return LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS;
else
return LVDS_SINGLE_LINK;
}
static struct drm_encoder *
rk628_lvds_connector_best_encoder(struct drm_connector *connector)
{
struct rk628_lvds *lvds = connector_to_lvds(connector);
return lvds->base.encoder;
}
static int rk628_lvds_connector_get_modes(struct drm_connector *connector)
{
struct rk628_lvds *lvds = connector_to_lvds(connector);
struct drm_display_info *info = &connector->display_info;
int num_modes = 0;
num_modes = drm_panel_get_modes(lvds->panel, connector);
if (info->num_bus_formats)
lvds->format = rk628_lvds_get_format(info->bus_formats[0]);
else
lvds->format = LVDS_FORMAT_VESA_24BIT;
return num_modes;
}
static const struct drm_connector_helper_funcs
rk628_lvds_connector_helper_funcs = {
.get_modes = rk628_lvds_connector_get_modes,
.best_encoder = rk628_lvds_connector_best_encoder,
};
static void rk628_lvds_connector_destroy(struct drm_connector *connector)
{
drm_connector_cleanup(connector);
}
static const struct drm_connector_funcs rk628_lvds_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rk628_lvds_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static void rk628_lvds_bridge_enable(struct drm_bridge *bridge)
{
struct rk628_lvds *lvds = bridge_to_lvds(bridge);
const struct drm_display_mode *mode = &lvds->mode;
u32 val, bus_width;
int ret;
regmap_update_bits(lvds->grf, GRF_SYSTEM_CON0, SW_OUTPUT_MODE_MASK,
SW_OUTPUT_MODE(OUTPUT_MODE_LVDS));
switch (lvds->link_type) {
case LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
val = SW_LVDS_CON_CHASEL(1) | SW_LVDS_CON_STARTSEL(0) |
SW_LVDS_CON_DUAL_SEL(0);
bus_width = COMBTXPHY_MODULEA_EN | COMBTXPHY_MODULEB_EN;
break;
case LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
val = SW_LVDS_CON_CHASEL(1) | SW_LVDS_CON_STARTSEL(1) |
SW_LVDS_CON_DUAL_SEL(0);
bus_width = COMBTXPHY_MODULEA_EN | COMBTXPHY_MODULEB_EN;
break;
case LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS:
val = SW_LVDS_CON_CHASEL(1) | SW_LVDS_CON_STARTSEL(0) |
SW_LVDS_CON_DUAL_SEL(1);
regmap_update_bits(lvds->grf, GRF_POST_PROC_CON,
SW_SPLIT_EN, SW_SPLIT_EN);
bus_width = COMBTXPHY_MODULEA_EN | COMBTXPHY_MODULEB_EN;
break;
case LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS:
val = SW_LVDS_CON_CHASEL(1) | SW_LVDS_CON_STARTSEL(1) |
SW_LVDS_CON_DUAL_SEL(1);
regmap_update_bits(lvds->grf, GRF_POST_PROC_CON,
SW_SPLIT_EN, SW_SPLIT_EN);
bus_width = COMBTXPHY_MODULEA_EN | COMBTXPHY_MODULEB_EN;
break;
case LVDS_SINGLE_LINK:
default:
val = SW_LVDS_CON_CHASEL(0) | SW_LVDS_CON_STARTSEL(0) |
SW_LVDS_CON_DUAL_SEL(0);
bus_width = COMBTXPHY_MODULEA_EN;
break;
}
val |= SW_LVDS_CON_SELECT(lvds->format) |
SW_LVDS_CON_MSBSEL(0) |
SW_LVDS_CON_CLKINV(0);
regmap_write(lvds->grf, GRF_LVDS_TX_CON, val);
bus_width |= (mode->clock / 1000) << 8;
phy_set_bus_width(lvds->phy, bus_width);
ret = phy_set_mode(lvds->phy, PHY_MODE_LVDS);
if (ret) {
dev_err(lvds->dev, "failed to set phy mode: %d\n", ret);
return;
}
phy_power_on(lvds->phy);
drm_panel_prepare(lvds->panel);
drm_panel_enable(lvds->panel);
}
static void rk628_lvds_bridge_disable(struct drm_bridge *bridge)
{
struct rk628_lvds *lvds = bridge_to_lvds(bridge);
drm_panel_disable(lvds->panel);
drm_panel_unprepare(lvds->panel);
phy_power_off(lvds->phy);
}
static int rk628_lvds_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rk628_lvds *lvds = bridge_to_lvds(bridge);
struct drm_connector *connector = &lvds->connector;
struct drm_device *drm = bridge->dev;
int ret;
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
ret = drm_connector_init(drm, connector, &rk628_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
if (ret) {
dev_err(lvds->dev, "Failed to initialize connector with drm\n");
return ret;
}
drm_connector_helper_add(connector, &rk628_lvds_connector_helper_funcs);
drm_connector_attach_encoder(connector, bridge->encoder);
return 0;
}
static void rk628_lvds_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct rk628_lvds *lvds = bridge_to_lvds(bridge);
drm_mode_copy(&lvds->mode, mode);
}
static const struct drm_bridge_funcs rk628_lvds_bridge_funcs = {
.attach = rk628_lvds_bridge_attach,
.enable = rk628_lvds_bridge_enable,
.disable = rk628_lvds_bridge_disable,
.mode_set = rk628_lvds_bridge_mode_set,
};
static int rk628_lvds_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct rk628_lvds *lvds;
int ret;
if (!of_device_is_available(dev->of_node))
return -ENODEV;
lvds = devm_kzalloc(dev, sizeof(*lvds), GFP_KERNEL);
if (!lvds)
return -ENOMEM;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
&lvds->panel, NULL);
if (ret)
return ret;
lvds->dev = dev;
lvds->parent = rk628;
lvds->grf = rk628->grf;
lvds->link_type = rk628_lvds_get_link_type(lvds);
platform_set_drvdata(pdev, lvds);
lvds->phy = devm_of_phy_get(dev, dev->of_node, NULL);
if (IS_ERR(lvds->phy)) {
ret = PTR_ERR(lvds->phy);
dev_err(dev, "failed to get phy: %d\n", ret);
return ret;
}
lvds->base.funcs = &rk628_lvds_bridge_funcs;
lvds->base.of_node = dev->of_node;
drm_bridge_add(&lvds->base);
return 0;
}
static int rk628_lvds_remove(struct platform_device *pdev)
{
struct rk628_lvds *lvds = platform_get_drvdata(pdev);
drm_bridge_remove(&lvds->base);
return 0;
}
static const struct of_device_id rk628_lvds_of_match[] = {
{ .compatible = "rockchip,rk628-lvds", },
{},
};
MODULE_DEVICE_TABLE(of, rk628_lvds_of_match);
static struct platform_driver rk628_lvds_driver = {
.driver = {
.name = "rk628-lvds",
.of_match_table = of_match_ptr(rk628_lvds_of_match),
},
.probe = rk628_lvds_probe,
.remove = rk628_lvds_remove,
};
module_platform_driver(rk628_lvds_driver);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 LVDS driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1,495 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/mfd/rk628.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include <drm/drm_of.h>
enum rk628_mode_sync_pol {
MODE_FLAG_NSYNC,
MODE_FLAG_PSYNC,
};
struct rk628_post_process {
struct drm_bridge base;
struct drm_bridge *bridge;
struct drm_display_mode src_mode;
struct drm_display_mode dst_mode;
struct device *dev;
struct regmap *grf;
struct clk *sclk_vop;
struct clk *clk_rx_read;
struct reset_control *rstc_decoder;
struct reset_control *rstc_clk_rx;
struct reset_control *rstc_vop;
struct rk628 *parent;
int sync_pol;
};
static inline struct rk628_post_process *bridge_to_pp(struct drm_bridge *bridge)
{
return container_of(bridge, struct rk628_post_process, base);
}
static void calc_dsp_frm_hst_vst(const struct videomode *src,
const struct videomode *dst,
u32 *dsp_frame_hst, u32 *dsp_frame_vst)
{
u32 bp_in, bp_out;
u32 v_scale_ratio;
u64 t_frm_st;
u64 t_bp_in, t_bp_out, t_delta, tin;
u32 src_pixclock, dst_pixclock;
u32 dsp_htotal, src_htotal, src_vtotal;
src_pixclock = div_u64(1000000000000llu, src->pixelclock);
dst_pixclock = div_u64(1000000000000llu, dst->pixelclock);
src_htotal = src->hsync_len + src->hback_porch + src->hactive +
src->hfront_porch;
src_vtotal = src->vsync_len + src->vback_porch + src->vactive +
src->vfront_porch;
dsp_htotal = dst->hsync_len + dst->hback_porch + dst->hactive +
dst->hfront_porch;
bp_in = (src->vback_porch + src->vsync_len) * src_htotal +
src->hsync_len + src->hback_porch;
bp_out = (dst->vback_porch + dst->vsync_len) * dsp_htotal +
dst->hsync_len + dst->hback_porch;
t_bp_in = bp_in * src_pixclock;
t_bp_out = bp_out * dst_pixclock;
tin = src_vtotal * src_htotal * src_pixclock;
v_scale_ratio = src->vactive / dst->vactive;
if (v_scale_ratio <= 2)
t_delta = 5 * src_htotal * src_pixclock;
else
t_delta = 12 * src_htotal * src_pixclock;
if (t_bp_in + t_delta > t_bp_out)
t_frm_st = (t_bp_in + t_delta - t_bp_out);
else
t_frm_st = tin - (t_bp_out - (t_bp_in + t_delta));
do_div(t_frm_st, src_pixclock);
*dsp_frame_hst = do_div(t_frm_st, src_htotal);
*dsp_frame_vst = t_frm_st;
}
static void rk628_post_process_scaler_init(struct rk628_post_process *pp,
const struct drm_display_mode *s,
const struct drm_display_mode *d)
{
struct videomode src, dst;
u32 dsp_frame_hst, dsp_frame_vst;
u32 scl_hor_mode, scl_ver_mode;
u32 scl_v_factor, scl_h_factor;
u32 dsp_htotal, dsp_hs_end, dsp_hact_st, dsp_hact_end;
u32 dsp_vtotal, dsp_vs_end, dsp_vact_st, dsp_vact_end;
u32 dsp_hbor_end, dsp_hbor_st, dsp_vbor_end, dsp_vbor_st;
u16 bor_right = 0, bor_left = 0, bor_up = 0, bor_down = 0;
u8 hor_down_mode = 0, ver_down_mode = 0;
drm_display_mode_to_videomode(s, &src);
drm_display_mode_to_videomode(d, &dst);
dsp_htotal = dst.hsync_len + dst.hback_porch + dst.hactive +
dst.hfront_porch;
dsp_vtotal = dst.vsync_len + dst.vback_porch + dst.vactive +
dst.vfront_porch;
dsp_hs_end = dst.hsync_len;
dsp_vs_end = dst.vsync_len;
dsp_hbor_end = dst.hsync_len + dst.hback_porch + dst.hactive;
dsp_hbor_st = dst.hsync_len + dst.hback_porch;
dsp_vbor_end = dst.vsync_len + dst.vback_porch + dst.vactive;
dsp_vbor_st = dst.vsync_len + dst.vback_porch;
dsp_hact_st = dsp_hbor_st + bor_left;
dsp_hact_end = dsp_hbor_end - bor_right;
dsp_vact_st = dsp_vbor_st + bor_up;
dsp_vact_end = dsp_vbor_end - bor_down;
calc_dsp_frm_hst_vst(&src, &dst, &dsp_frame_hst, &dsp_frame_vst);
dev_dbg(pp->dev, "dsp_frame_vst=%d, dsp_frame_hst=%d\n",
dsp_frame_vst, dsp_frame_hst);
if (src.hactive > dst.hactive) {
scl_hor_mode = 2;
if (hor_down_mode == 0) {
if ((src.hactive - 1) / (dst.hactive - 1) > 2)
scl_h_factor = ((src.hactive - 1) << 14) /
(dst.hactive - 1);
else
scl_h_factor = ((src.hactive - 2) << 14) /
(dst.hactive - 1);
} else {
scl_h_factor = (dst.hactive << 16) /
(src.hactive - 1);
}
dev_dbg(pp->dev, "horizontal scale down\n");
} else if (src.hactive == dst.hactive) {
scl_hor_mode = 0;
scl_h_factor = 0;
dev_dbg(pp->dev, "horizontal no scale\n");
} else {
scl_hor_mode = 1;
scl_h_factor = ((src.hactive - 1) << 16) / (dst.hactive - 1);
dev_dbg(pp->dev, "horizontal scale up\n");
}
if (src.vactive > dst.vactive) {
scl_ver_mode = 2;
if (ver_down_mode == 0) {
if ((src.vactive - 1) / (dst.vactive - 1) > 2)
scl_v_factor = ((src.vactive - 1) << 14) /
(dst.vactive - 1);
else
scl_v_factor = ((src.vactive - 2) << 14) /
(dst.vactive - 1);
} else {
scl_v_factor = (dst.vactive << 16) /
(src.vactive - 1);
}
dev_dbg(pp->dev, "vertical scale down\n");
} else if (src.vactive == dst.vactive) {
scl_ver_mode = 0;
scl_v_factor = 0;
dev_dbg(pp->dev, "vertical no scale\n");
} else {
scl_ver_mode = 1;
scl_v_factor = ((src.vactive - 1) << 16) / (dst.vactive - 1);
dev_dbg(pp->dev, "vertical scale up\n");
}
regmap_update_bits(pp->grf, GRF_RGB_DEC_CON0,
SW_HRES_MASK, SW_HRES(src.hactive));
regmap_write(pp->grf, GRF_SCALER_CON0,
SCL_VER_DOWN_MODE(ver_down_mode) |
SCL_HOR_DOWN_MODE(hor_down_mode) |
SCL_VER_MODE(scl_ver_mode) | SCL_HOR_MODE(scl_hor_mode));
regmap_write(pp->grf, GRF_SCALER_CON1,
SCL_V_FACTOR(scl_v_factor) | SCL_H_FACTOR(scl_h_factor));
regmap_write(pp->grf, GRF_SCALER_CON2,
DSP_FRAME_VST(dsp_frame_vst) |
DSP_FRAME_HST(dsp_frame_hst));
regmap_write(pp->grf, GRF_SCALER_CON3,
DSP_HS_END(dsp_hs_end) | DSP_HTOTAL(dsp_htotal));
regmap_write(pp->grf, GRF_SCALER_CON4,
DSP_HACT_END(dsp_hact_end) | DSP_HACT_ST(dsp_hact_st));
regmap_write(pp->grf, GRF_SCALER_CON5,
DSP_VS_END(dsp_vs_end) | DSP_VTOTAL(dsp_vtotal));
regmap_write(pp->grf, GRF_SCALER_CON6,
DSP_VACT_END(dsp_vact_end) | DSP_VACT_ST(dsp_vact_st));
regmap_write(pp->grf, GRF_SCALER_CON7,
DSP_HBOR_END(dsp_hbor_end) | DSP_HBOR_ST(dsp_hbor_st));
regmap_write(pp->grf, GRF_SCALER_CON8,
DSP_VBOR_END(dsp_vbor_end) | DSP_VBOR_ST(dsp_vbor_st));
}
static void rk628_post_process_bridge_pre_enable(struct drm_bridge *bridge)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
struct drm_display_mode *src = &pp->src_mode;
struct drm_display_mode *dst = &pp->dst_mode;
u64 dst_rate, src_rate;
reset_control_assert(pp->rstc_decoder);
udelay(10);
reset_control_deassert(pp->rstc_decoder);
udelay(10);
clk_set_rate(pp->clk_rx_read, src->clock * 1000);
clk_prepare_enable(pp->clk_rx_read);
reset_control_assert(pp->rstc_clk_rx);
udelay(10);
reset_control_deassert(pp->rstc_clk_rx);
udelay(10);
src_rate = src->clock * 1000;
dst_rate = src_rate * dst->vdisplay * dst->htotal;
do_div(dst_rate, src->vdisplay * src->htotal);
do_div(dst_rate, 1000);
dst->clock = dst_rate;
clk_set_rate(pp->sclk_vop, dst->clock * 1000);
clk_prepare_enable(pp->sclk_vop);
reset_control_assert(pp->rstc_vop);
udelay(10);
reset_control_deassert(pp->rstc_vop);
udelay(10);
regmap_update_bits(pp->grf, GRF_SYSTEM_CON0, SW_VSYNC_POL_MASK,
SW_VSYNC_POL(pp->sync_pol));
regmap_update_bits(pp->grf, GRF_SYSTEM_CON0, SW_HSYNC_POL_MASK,
SW_HSYNC_POL(pp->sync_pol));
rk628_post_process_scaler_init(pp, src, dst);
}
static void rk628_post_process_bridge_post_disable(struct drm_bridge *bridge)
{
}
static void rk628_post_process_bridge_enable(struct drm_bridge *bridge)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
regmap_write(pp->grf, GRF_SCALER_CON0, SCL_EN(1));
}
static void rk628_post_process_bridge_disable(struct drm_bridge *bridge)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
regmap_write(pp->grf, GRF_SCALER_CON0, SCL_EN(0));
clk_disable_unprepare(pp->sclk_vop);
clk_disable_unprepare(pp->clk_rx_read);
}
static void rk628_post_process_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
struct rk628 *rk628 = pp->parent;
drm_mode_copy(&pp->src_mode, adj);
if (rk628->dst_mode_valid)
drm_mode_copy(&pp->dst_mode, &rk628->dst_mode);
else
drm_mode_copy(&pp->dst_mode, &pp->src_mode);
/* hdmirx 4k-60Hz mode only support yuv420 */
if (pp->src_mode.clock == 594000)
regmap_write(pp->grf, GRF_CSC_CTRL_CON, SW_Y2R_EN(1));
}
static int rk628_post_process_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
struct device *dev = pp->dev;
int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
NULL, &pp->bridge);
if (ret)
return ret;
ret = drm_bridge_attach(bridge->encoder, pp->bridge, bridge, flags);
if (ret) {
dev_err(dev, "failed to attach bridge\n");
return ret;
}
return 0;
}
static bool
rk628_post_process_bridge_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
struct drm_display_mode *adj)
{
struct rk628_post_process *pp = bridge_to_pp(bridge);
if (pp->sync_pol == MODE_FLAG_NSYNC) {
adj->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
adj->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
} else {
adj->flags &= ~(DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
adj->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
}
return true;
}
static const struct drm_bridge_funcs rk628_post_process_bridge_funcs = {
.pre_enable = rk628_post_process_bridge_pre_enable,
.post_disable = rk628_post_process_bridge_post_disable,
.enable = rk628_post_process_bridge_enable,
.disable = rk628_post_process_bridge_disable,
.mode_set = rk628_post_process_bridge_mode_set,
.mode_fixup = rk628_post_process_bridge_mode_fixup,
.attach = rk628_post_process_bridge_attach,
};
/**
* rk628_scaler_add_src_mode - add source mode for scaler
* @rk628: parent device
* @connector: DRM connector
* If need scale, call the function at last of get_modes.
*/
int rk628_scaler_add_src_mode(struct rk628 *rk628,
struct drm_connector *connector)
{
struct drm_display_mode *pmode;
struct drm_display_mode *dst;
if (!rk628 || !connector)
return 0;
if (drm_mode_validate_driver(connector->dev, &rk628->src_mode) !=
MODE_OK)
return 0;
list_for_each_entry(pmode, &connector->probed_modes, head) {
if (pmode->type & DRM_MODE_TYPE_PREFERRED) {
drm_mode_copy(&rk628->dst_mode, pmode);
drm_mode_copy(pmode, &rk628->src_mode);
pmode->type |= DRM_MODE_TYPE_PREFERRED;
rk628->dst_mode_valid = true;
break;
}
}
if (rk628->dst_mode_valid) {
dst = drm_mode_duplicate(connector->dev, &rk628->dst_mode);
dst->type &= ~DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, dst);
return 1;
}
return 0;
}
EXPORT_SYMBOL(rk628_scaler_add_src_mode);
/**
* rk628_mode_copy - rk628 mode copy
* @rk628: parent device
* @dst: dst mode
* @src: src mode
* Call the function at mode_set, replace drm_mode_copy.
*/
void rk628_mode_copy(struct rk628 *rk628, struct drm_display_mode *dst,
const struct drm_display_mode *src)
{
if (rk628->dst_mode_valid)
drm_mode_copy(dst, &rk628->dst_mode);
else
drm_mode_copy(dst, src);
}
EXPORT_SYMBOL(rk628_mode_copy);
static int rk628_post_process_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct rk628_post_process *pp;
u32 bus_flags;
u32 val;
int ret;
if (!of_device_is_available(dev->of_node))
return -ENODEV;
pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
pp->dev = dev;
pp->grf = rk628->grf;
platform_set_drvdata(pdev, pp);
pp->parent = rk628;
pp->sclk_vop = devm_clk_get(dev, "sclk_vop");
if (IS_ERR(pp->sclk_vop)) {
ret = PTR_ERR(pp->sclk_vop);
dev_err(dev, "failed to get sclk: %d\n", ret);
return ret;
}
pp->clk_rx_read = devm_clk_get(dev, "rx_read");
if (IS_ERR(pp->clk_rx_read)) {
ret = PTR_ERR(pp->clk_rx_read);
dev_err(dev, "failed to get clk_rx_read: %d\n", ret);
return ret;
}
pp->rstc_decoder = of_reset_control_get(dev->of_node, "decoder");
if (IS_ERR(pp->rstc_decoder)) {
ret = PTR_ERR(pp->rstc_decoder);
dev_err(dev, "failed to get decoder reset: %d\n", ret);
return ret;
}
pp->rstc_clk_rx = of_reset_control_get(dev->of_node, "clk_rx");
if (IS_ERR(pp->rstc_clk_rx)) {
ret = PTR_ERR(pp->rstc_clk_rx);
dev_err(dev, "failed to get clk_rx reset: %d\n", ret);
return ret;
}
pp->rstc_vop = of_reset_control_get(dev->of_node, "vop");
if (IS_ERR(pp->rstc_vop)) {
ret = PTR_ERR(pp->rstc_vop);
dev_err(dev, "failed to get vop reset: %d\n", ret);
return ret;
}
ret = of_property_read_u32(dev->of_node, "mode-sync-pol", &val);
if (ret < 0)
pp->sync_pol = MODE_FLAG_PSYNC;
else
pp->sync_pol = (!val ? MODE_FLAG_NSYNC : MODE_FLAG_PSYNC);
pp->base.funcs = &rk628_post_process_bridge_funcs;
pp->base.of_node = dev->of_node;
drm_bridge_add(&pp->base);
of_get_drm_display_mode(dev->of_node, &rk628->src_mode, &bus_flags,
OF_USE_NATIVE_MODE);
return 0;
}
static int rk628_post_process_remove(struct platform_device *pdev)
{
struct rk628_post_process *pp = platform_get_drvdata(pdev);
drm_bridge_remove(&pp->base);
return 0;
}
static const struct of_device_id rk628_post_process_of_match[] = {
{ .compatible = "rockchip,rk628-post-process", },
{},
};
MODULE_DEVICE_TABLE(of, rk628_post_process_of_match);
static struct platform_driver rk628_post_process_driver = {
.driver = {
.name = "rk628-post-process",
.of_match_table = of_match_ptr(rk628_post_process_of_match),
},
.probe = rk628_post_process_probe,
.remove = rk628_post_process_remove,
};
module_platform_driver(rk628_post_process_driver);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 Post Process driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1,378 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/mfd/rk628.h>
#include <linux/phy/phy.h>
#include <linux/reset.h>
#include <drm/drm_of.h>
#include <drm/drm_atomic.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_panel.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
enum interface_type {
RGB_TX,
YUV_RX,
YUV_TX,
BT1120_RX,
BT1120_TX,
};
struct rk628_rgb {
struct drm_bridge base;
struct drm_connector connector;
struct drm_display_mode mode;
struct drm_panel *panel;
struct drm_bridge *bridge;
struct device *dev;
struct regmap *grf;
struct rk628 *parent;
struct clk *decclk;
struct reset_control *rstc;
bool dual_edge;
enum interface_type interface_type;
};
static inline struct rk628_rgb *bridge_to_rgb(struct drm_bridge *b)
{
return container_of(b, struct rk628_rgb, base);
}
static inline struct rk628_rgb *connector_to_rgb(struct drm_connector *c)
{
return container_of(c, struct rk628_rgb, connector);
}
static enum interface_type rk628_rgb_get_interface_type(struct rk628_rgb *rgb)
{
const struct device_node *of_node = rgb->dev->of_node;
if (of_device_is_compatible(of_node, "rockchip,rk628-yuv-rx"))
return YUV_RX;
else if (of_device_is_compatible(of_node, "rockchip,rk628-yuv-tx"))
return YUV_TX;
else if (of_device_is_compatible(of_node, "rockchip,rk628-bt1120-rx"))
return BT1120_RX;
else if (of_device_is_compatible(of_node, "rockchip,rk628-bt1120-tx"))
return BT1120_TX;
else
return RGB_TX;
}
static struct drm_encoder *
rk628_rgb_connector_best_encoder(struct drm_connector *connector)
{
struct rk628_rgb *rgb = connector_to_rgb(connector);
return rgb->base.encoder;
}
static int rk628_rgb_connector_get_modes(struct drm_connector *connector)
{
struct rk628_rgb *rgb = connector_to_rgb(connector);
return drm_panel_get_modes(rgb->panel, connector);
}
static const struct drm_connector_helper_funcs
rk628_rgb_connector_helper_funcs = {
.get_modes = rk628_rgb_connector_get_modes,
.best_encoder = rk628_rgb_connector_best_encoder,
};
static void rk628_rgb_connector_destroy(struct drm_connector *connector)
{
drm_connector_cleanup(connector);
}
static const struct drm_connector_funcs rk628_rgb_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = rk628_rgb_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static void rk628_bt1120_rx_enable(struct rk628_rgb *rgb)
{
const struct drm_display_mode *mode = &rgb->mode;
reset_control_assert(rgb->rstc);
udelay(10);
reset_control_deassert(rgb->rstc);
udelay(10);
clk_set_rate(rgb->decclk, mode->clock * 1000);
clk_prepare_enable(rgb->decclk);
if (rgb->dual_edge) {
regmap_update_bits(rgb->grf, GRF_RGB_DEC_CON0,
DEC_DUALEDGE_EN, DEC_DUALEDGE_EN);
regmap_write(rgb->grf,
GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
regmap_write(rgb->grf, GRF_BT1120_DCLK_DELAY_CON1, 0);
} else
regmap_update_bits(rgb->grf, GRF_RGB_DEC_CON0,
DEC_DUALEDGE_EN, 0);
regmap_update_bits(rgb->grf, GRF_RGB_DEC_CON1,
SW_SET_X_MASK, SW_SET_X(mode->hdisplay));
regmap_update_bits(rgb->grf, GRF_RGB_DEC_CON2,
SW_SET_Y_MASK, SW_SET_Y(mode->vdisplay));
regmap_update_bits(rgb->grf, GRF_SYSTEM_CON0,
SW_BT_DATA_OEN_MASK | SW_INPUT_MODE_MASK,
SW_BT_DATA_OEN | SW_INPUT_MODE(INPUT_MODE_BT1120));
regmap_write(rgb->grf, GRF_CSC_CTRL_CON, SW_Y2R_EN(1));
regmap_update_bits(rgb->grf, GRF_RGB_DEC_CON0,
SW_CAP_EN_PSYNC | SW_CAP_EN_ASYNC | SW_PROGRESS_EN,
SW_CAP_EN_PSYNC | SW_CAP_EN_ASYNC | SW_PROGRESS_EN);
}
static void rk628_bt1120_tx_enable(struct rk628_rgb *rgb)
{
u32 val = 0;
regmap_update_bits(rgb->grf, GRF_SYSTEM_CON0,
SW_BT_DATA_OEN_MASK | SW_OUTPUT_MODE_MASK,
SW_OUTPUT_MODE(OUTPUT_MODE_BT1120));
regmap_write(rgb->grf, GRF_CSC_CTRL_CON, SW_R2Y_EN(1));
regmap_update_bits(rgb->grf, GRF_POST_PROC_CON,
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
if (rgb->dual_edge) {
val |= ENC_DUALEDGE_EN(1);
regmap_write(rgb->grf, GRF_BT1120_DCLK_DELAY_CON0, 0x10000000);
regmap_write(rgb->grf, GRF_BT1120_DCLK_DELAY_CON1, 0);
}
val |= BT1120_UV_SWAP(1);
regmap_write(rgb->grf, GRF_RGB_ENC_CON, val);
}
static void rk628_rgb_bridge_enable(struct drm_bridge *bridge)
{
struct rk628_rgb *rgb = bridge_to_rgb(bridge);
switch (rgb->interface_type) {
case YUV_RX:
regmap_write(rgb->grf, GRF_CSC_CTRL_CON, SW_Y2R_EN(1));
regmap_update_bits(rgb->grf, GRF_SYSTEM_CON0,
SW_BT_DATA_OEN_MASK | SW_INPUT_MODE_MASK,
SW_BT_DATA_OEN | SW_INPUT_MODE(INPUT_MODE_YUV));
break;
case YUV_TX:
regmap_write(rgb->grf, GRF_CSC_CTRL_CON, SW_R2Y_EN(1));
regmap_update_bits(rgb->grf, GRF_POST_PROC_CON,
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
regmap_update_bits(rgb->grf, GRF_SYSTEM_CON0,
SW_BT_DATA_OEN_MASK | SW_OUTPUT_MODE_MASK,
SW_OUTPUT_MODE(OUTPUT_MODE_YUV));
break;
case BT1120_RX:
rk628_bt1120_rx_enable(rgb);
break;
case BT1120_TX:
rk628_bt1120_tx_enable(rgb);
break;
case RGB_TX:
default:
regmap_update_bits(rgb->grf, GRF_SYSTEM_CON0,
SW_BT_DATA_OEN_MASK | SW_OUTPUT_MODE_MASK,
SW_OUTPUT_MODE(OUTPUT_MODE_RGB));
regmap_update_bits(rgb->grf, GRF_POST_PROC_CON,
SW_DCLK_OUT_INV_EN, SW_DCLK_OUT_INV_EN);
break;
}
if (rgb->panel) {
drm_panel_prepare(rgb->panel);
drm_panel_enable(rgb->panel);
}
}
static void rk628_rgb_bridge_disable(struct drm_bridge *bridge)
{
struct rk628_rgb *rgb = bridge_to_rgb(bridge);
if (rgb->panel) {
drm_panel_disable(rgb->panel);
drm_panel_unprepare(rgb->panel);
}
if (rgb->decclk)
clk_disable_unprepare(rgb->decclk);
if (rgb->rstc)
reset_control_assert(rgb->rstc);
}
static int rk628_rgb_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct rk628_rgb *rgb = bridge_to_rgb(bridge);
struct drm_connector *connector = &rgb->connector;
struct drm_device *drm = bridge->dev;
struct device *dev = rgb->dev;
int ret;
ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1,
&rgb->panel, &rgb->bridge);
if (ret)
return ret;
if (rgb->interface_type == YUV_RX || rgb->interface_type == BT1120_RX) {
if (!rgb->bridge) {
dev_err(dev, "decoder failed to find bridge\n");
return -EPROBE_DEFER;
}
ret = drm_bridge_attach(bridge->encoder, rgb->bridge, bridge,
flags);
if (ret) {
dev_err(dev, "failed to attach bridge\n");
return ret;
}
} else {
if (rgb->bridge) {
ret = drm_bridge_attach(bridge->encoder, rgb->bridge,
bridge, flags);
if (ret) {
dev_err(dev, "failed to attach bridge\n");
return ret;
}
}
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
return 0;
if (rgb->panel) {
ret = drm_connector_init(drm, connector,
&rk628_rgb_connector_funcs,
DRM_MODE_CONNECTOR_DPI);
if (ret) {
dev_err(dev,
"Failed to initialize connector with drm\n");
return ret;
}
drm_connector_helper_add(connector,
&rk628_rgb_connector_helper_funcs);
drm_connector_attach_encoder(connector,
bridge->encoder);
}
}
return 0;
}
static void rk628_rgb_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adj)
{
struct rk628_rgb *rgb = bridge_to_rgb(bridge);
drm_mode_copy(&rgb->mode, adj);
}
static const struct drm_bridge_funcs rk628_rgb_bridge_funcs = {
.attach = rk628_rgb_bridge_attach,
.enable = rk628_rgb_bridge_enable,
.disable = rk628_rgb_bridge_disable,
.mode_set = rk628_rgb_bridge_mode_set,
};
static int rk628_rgb_probe(struct platform_device *pdev)
{
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
struct device *dev = &pdev->dev;
struct rk628_rgb *rgb;
int ret;
if (!of_device_is_available(dev->of_node))
return -ENODEV;
rgb = devm_kzalloc(dev, sizeof(*rgb), GFP_KERNEL);
if (!rgb)
return -ENOMEM;
rgb->dev = dev;
rgb->parent = rk628;
rgb->grf = rk628->grf;
rgb->interface_type = rk628_rgb_get_interface_type(rgb);
rgb->dual_edge = of_property_read_bool(dev->of_node, "dual-edge");
platform_set_drvdata(pdev, rgb);
if (rgb->interface_type == BT1120_RX) {
rgb->decclk = devm_clk_get(dev, "bt1120dec");
if (IS_ERR(rgb->decclk)) {
ret = PTR_ERR(rgb->decclk);
dev_err(dev, "failed to get dec clk: %d\n", ret);
return ret;
}
rgb->rstc = of_reset_control_get(dev->of_node, NULL);
if (IS_ERR(rgb->rstc)) {
ret = PTR_ERR(rgb->rstc);
dev_err(dev, "failed to get reset control: %d\n", ret);
return ret;
}
}
rgb->base.funcs = &rk628_rgb_bridge_funcs;
rgb->base.of_node = dev->of_node;
drm_bridge_add(&rgb->base);
return 0;
}
static int rk628_rgb_remove(struct platform_device *pdev)
{
struct rk628_rgb *rgb = platform_get_drvdata(pdev);
drm_bridge_remove(&rgb->base);
return 0;
}
static const struct of_device_id rk628_rgb_of_match[] = {
{ .compatible = "rockchip,rk628-rgb-tx", },
{ .compatible = "rockchip,rk628-yuv-rx", },
{ .compatible = "rockchip,rk628-yuv-tx", },
{ .compatible = "rockchip,rk628-bt1120-rx", },
{ .compatible = "rockchip,rk628-bt1120-tx", },
{},
};
MODULE_DEVICE_TABLE(of, rk628_rgb_of_match);
static struct platform_driver rk628_rgb_driver = {
.driver = {
.name = "rk628-rgb",
.of_match_table = of_match_ptr(rk628_rgb_of_match),
},
.probe = rk628_rgb_probe,
.remove = rk628_rgb_remove,
};
module_platform_driver(rk628_rgb_driver);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 RGB driver");
MODULE_LICENSE("GPL v2");

View File

@@ -1229,17 +1229,6 @@ config MFD_RK618
help
if you say yes here you get support for the RK618 from Rockchip.
config MFD_RK628
tristate "Rockchip RK628 MFD Driver"
depends on I2C
depends on OF
select MFD_CORE
select REGMAP_I2C
select REGMAP_IRQ
select PINCTRL_RK628
help
if you say yes here you get support for the RK628 from Rockchip.
config MFD_RK630
tristate "RK630 CORE module support"
select MFD_CORE

View File

@@ -226,7 +226,6 @@ obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
obj-$(CONFIG_MFD_NTXEC) += ntxec.o
obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
obj-$(CONFIG_MFD_RK618) += rk618.o
obj-$(CONFIG_MFD_RK628) += rk628.o
obj-$(CONFIG_MFD_RK630) += rk630.o
obj-$(CONFIG_MFD_RK630_I2C) += rk630-i2c.o
obj-$(CONFIG_MFD_RK630_SPI) += rk630-spi.o

View File

@@ -1,482 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/gpio/consumer.h>
#include <linux/regmap.h>
#include <linux/mfd/core.h>
#include <linux/mfd/rk628.h>
enum {
RK628_IRQ_HDMITX_HPD_HIGH,
RK628_IRQ_HDMITX_HPD_LOW,
RK628_IRQ_HDMITX,
RK628_IRQ_GVI,
RK628_IRQ_DSI1,
RK628_IRQ_DSI0,
RK628_IRQ_CSI,
RK628_IRQ_HDMIRX,
RK628_IRQ_GPIO0,
RK628_IRQ_GPIO1,
RK628_IRQ_GPIO2,
RK628_IRQ_GPIO3,
RK628_IRQ_EFUSE,
};
static struct resource rk628_gpio_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_GPIO0),
DEFINE_RES_IRQ(RK628_IRQ_GPIO1),
DEFINE_RES_IRQ(RK628_IRQ_GPIO2),
DEFINE_RES_IRQ(RK628_IRQ_GPIO3),
};
static struct resource rk628_dsi0_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_DSI0),
};
static struct resource rk628_dsi1_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_DSI1),
};
static struct resource rk628_csi_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_CSI),
DEFINE_RES_IRQ(RK628_IRQ_HDMIRX),
};
static struct resource rk628_gvi_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_GVI),
};
static struct resource rk628_hdmi_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_HDMITX),
DEFINE_RES_IRQ(RK628_IRQ_HDMITX_HPD_HIGH),
DEFINE_RES_IRQ(RK628_IRQ_HDMITX_HPD_LOW),
};
static struct resource rk628_hdmirx_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_HDMIRX),
};
static struct resource rk628_efuse_resources[] = {
DEFINE_RES_IRQ(RK628_IRQ_EFUSE),
};
static const struct mfd_cell rk628_devs[] = {
{
.name = "rk628-cru",
.of_compatible = "rockchip,rk628-cru",
}, {
.name = "rk628-pinctrl",
.of_compatible = "rockchip,rk628-pinctrl",
.resources = rk628_gpio_resources,
.num_resources = ARRAY_SIZE(rk628_gpio_resources),
}, {
.name = "rk628-combrxphy",
.of_compatible = "rockchip,rk628-combrxphy",
}, {
.name = "rk628-combtxphy",
.of_compatible = "rockchip,rk628-combtxphy",
}, {
.name = "rk628-csi",
.of_compatible = "rockchip,rk628-csi",
.resources = rk628_csi_resources,
.num_resources = ARRAY_SIZE(rk628_csi_resources),
}, {
.name = "rk628-hdmirx",
.of_compatible = "rockchip,rk628-hdmirx",
.resources = rk628_hdmirx_resources,
.num_resources = ARRAY_SIZE(rk628_hdmirx_resources),
}, {
.name = "rk628-dsi1",
.of_compatible = "rockchip,rk628-dsi1",
.resources = rk628_dsi1_resources,
.num_resources = ARRAY_SIZE(rk628_dsi1_resources),
}, {
.name = "rk628-dsi0",
.of_compatible = "rockchip,rk628-dsi0",
.resources = rk628_dsi0_resources,
.num_resources = ARRAY_SIZE(rk628_dsi0_resources),
}, {
.name = "rk628-rgb-tx",
.of_compatible = "rockchip,rk628-rgb-tx",
}, {
.name = "rk628-yuv-rx",
.of_compatible = "rockchip,rk628-yuv-rx",
}, {
.name = "rk628-yuv-tx",
.of_compatible = "rockchip,rk628-yuv-tx",
}, {
.name = "rk628-bt1120-rx",
.of_compatible = "rockchip,rk628-bt1120-rx",
}, {
.name = "rk628-bt1120-tx",
.of_compatible = "rockchip,rk628-bt1120-tx",
}, {
.name = "rk628-lvds",
.of_compatible = "rockchip,rk628-lvds",
}, {
.name = "rk628-gvi",
.of_compatible = "rockchip,rk628-gvi",
.resources = rk628_gvi_resources,
.num_resources = ARRAY_SIZE(rk628_gvi_resources),
}, {
.name = "rk628-hdmi",
.of_compatible = "rockchip,rk628-hdmi",
.resources = rk628_hdmi_resources,
.num_resources = ARRAY_SIZE(rk628_hdmi_resources),
}, {
.name = "rk628-efuse",
.of_compatible = "rockchip,rk628-efuse",
.resources = rk628_efuse_resources,
.num_resources = ARRAY_SIZE(rk628_efuse_resources),
}, {
.name = "rk628-post-process",
.of_compatible = "rockchip,rk628-post-process",
},
};
static const struct regmap_irq rk628_irqs[] = {
REGMAP_IRQ_REG(RK628_IRQ_HDMITX_HPD_HIGH, 0, BIT(0)),
REGMAP_IRQ_REG(RK628_IRQ_HDMITX_HPD_LOW, 0, BIT(1)),
REGMAP_IRQ_REG(RK628_IRQ_HDMITX, 0, BIT(2)),
REGMAP_IRQ_REG(RK628_IRQ_GVI, 0, BIT(3)),
REGMAP_IRQ_REG(RK628_IRQ_DSI1, 0, BIT(4)),
REGMAP_IRQ_REG(RK628_IRQ_DSI0, 0, BIT(5)),
REGMAP_IRQ_REG(RK628_IRQ_CSI, 0, BIT(6)),
REGMAP_IRQ_REG(RK628_IRQ_HDMIRX, 0, BIT(8)),
REGMAP_IRQ_REG(RK628_IRQ_GPIO0, 4, BIT(0)),
REGMAP_IRQ_REG(RK628_IRQ_GPIO1, 4, BIT(1)),
REGMAP_IRQ_REG(RK628_IRQ_GPIO2, 4, BIT(2)),
REGMAP_IRQ_REG(RK628_IRQ_GPIO3, 4, BIT(3)),
REGMAP_IRQ_REG(RK628_IRQ_EFUSE, 4, BIT(4)),
};
static struct rk628_irq_chip_data rk628_irq_chip_data = {
.name = "rk628",
.irqs = rk628_irqs,
.num_irqs = ARRAY_SIZE(rk628_irqs),
.num_regs = 2,
.irq_reg_stride = (GRF_INTR1_STATUS - GRF_INTR0_STATUS) / 4,
.reg_stride = 4,
.status_base = GRF_INTR0_STATUS,
.mask_base = GRF_INTR0_EN,
.ack_base = GRF_INTR0_CLR_EN,
};
static const struct regmap_config rk628_grf_regmap_config = {
.name = "grf",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = GRF_MAX_REGISTER,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
};
static inline const struct regmap_irq *
irq_to_regmap_irq(struct rk628_irq_chip_data *d, int irq)
{
return &d->irqs[irq];
}
static void rk628_irq_lock(struct irq_data *data)
{
struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data);
mutex_lock(&d->lock);
}
static void rk628_irq_sync_unlock(struct irq_data *data)
{
struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data);
int i;
u32 reg, mask, val;
for (i = 0; i < d->num_regs; i++) {
reg = d->mask_base + (i * d->reg_stride * d->irq_reg_stride);
mask = d->mask_buf_def[i];
val = mask << 16 | (~d->mask_buf[i] & mask);
regmap_write(d->map, reg, val);
}
mutex_unlock(&d->lock);
}
static void rk628_irq_enable(struct irq_data *data)
{
struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data);
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
d->mask_buf[irq_data->reg_offset / d->reg_stride] &= ~irq_data->mask;
}
static void rk628_irq_disable(struct irq_data *data)
{
struct rk628_irq_chip_data *d = irq_data_get_irq_chip_data(data);
const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
d->mask_buf[irq_data->reg_offset / d->reg_stride] |= irq_data->mask;
}
static const struct irq_chip rk628_irq_chip = {
.irq_bus_lock = rk628_irq_lock,
.irq_bus_sync_unlock = rk628_irq_sync_unlock,
.irq_disable = rk628_irq_disable,
.irq_enable = rk628_irq_enable,
};
static irqreturn_t rk628_irq_thread(int irq, void *data)
{
struct rk628_irq_chip_data *d = data;
int i;
bool handled = false;
u32 reg;
for (i = 0; i < d->num_regs; i++) {
reg = d->status_base + (i * d->reg_stride * d->irq_reg_stride);
regmap_read(d->map, reg, &d->status_buf[i]);
}
for (i = 0; i < d->num_irqs; i++) {
if (d->status_buf[d->irqs[i].reg_offset / d->reg_stride] & d->irqs[i].mask) {
handle_nested_irq(irq_find_mapping(d->domain, i));
handled = true;
}
}
for (i = 0; i < d->num_regs; i++) {
if (d->status_buf[i]) {
reg = d->ack_base + (i * d->reg_stride * d->irq_reg_stride);
regmap_write(d->map, reg,
d->status_buf[i] << 16 | d->status_buf[i]);
}
}
if (handled)
return IRQ_HANDLED;
else
return IRQ_NONE;
}
static int rk628_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
struct rk628_irq_chip_data *d = h->host_data;
irq_set_chip_data(virq, d);
irq_set_chip(virq, &d->irq_chip);
irq_set_nested_thread(virq, 1);
irq_set_parent(virq, d->irq);
irq_set_noprobe(virq);
return 0;
}
static const struct irq_domain_ops rk628_irq_domain_ops = {
.map = rk628_irq_map,
.xlate = irq_domain_xlate_onetwocell,
};
static int rk628_irq_init(struct rk628 *rk628, int irq)
{
struct device *dev = rk628->dev;
struct rk628_irq_chip_data *d = rk628->irq_data;
struct regmap *map = rk628->grf;
u32 reg, mask, val;
int i;
int ret;
if (d->num_regs <= 0)
return -EINVAL;
d->status_buf = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->status_buf)
return -ENOMEM;
d->mask_buf = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->mask_buf)
return -ENOMEM;
d->mask_buf_def = devm_kcalloc(dev, d->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->mask_buf_def)
return -ENOMEM;
d->irq_chip = rk628_irq_chip;
d->irq_chip.name = d->name;
d->irq = irq;
d->map = map;
mutex_init(&d->lock);
for (i = 0; i < d->num_irqs; i++)
d->mask_buf_def[d->irqs[i].reg_offset / d->reg_stride] |= d->irqs[i].mask;
/* Mask all the interrupts by default */
for (i = 0; i < d->num_regs; i++) {
d->mask_buf[i] = d->mask_buf_def[i];
reg = d->mask_base + (i * d->reg_stride * d->irq_reg_stride);
mask = d->mask_buf[i];
val = mask << 16 | (~d->mask_buf[i] & mask);
regmap_write(d->map, reg, val);
}
d->domain = irq_domain_add_linear(dev->of_node, d->num_irqs,
&rk628_irq_domain_ops, d);
if (!d->domain) {
dev_err(dev, "Failed to create IRQ domain\n");
return -ENOMEM;
}
ret = devm_request_threaded_irq(dev, irq, NULL, rk628_irq_thread,
IRQF_ONESHOT, d->name, d);
if (ret != 0) {
irq_domain_remove(d->domain);
dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
return ret;
}
return 0;
}
static void rk628_irq_exit(struct rk628 *rk628)
{
struct rk628_irq_chip_data *d = rk628->irq_data;
unsigned int virq;
int hwirq;
/* Dispose all virtual irq from irq domain before removing it */
for (hwirq = 0; hwirq < d->num_irqs; hwirq++) {
/* Ignore hwirq if holes in the IRQ list */
if (!d->irqs[hwirq].mask)
continue;
/*
* Find the virtual irq of hwirq on chip and if it is
* there then dispose it
*/
virq = irq_find_mapping(d->domain, hwirq);
if (virq)
irq_dispose_mapping(virq);
}
irq_domain_remove(d->domain);
}
static int
rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct rk628 *rk628;
int ret;
rk628 = devm_kzalloc(dev, sizeof(*rk628), GFP_KERNEL);
if (!rk628)
return -ENOMEM;
rk628->dev = dev;
rk628->client = client;
rk628->irq_data = &rk628_irq_chip_data;
i2c_set_clientdata(client, rk628);
rk628->enable_gpio = devm_gpiod_get_optional(dev, "enable",
GPIOD_OUT_LOW);
if (IS_ERR(rk628->enable_gpio)) {
ret = PTR_ERR(rk628->enable_gpio);
dev_err(dev, "failed to request enable GPIO: %d\n", ret);
return ret;
}
rk628->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(rk628->reset_gpio)) {
ret = PTR_ERR(rk628->reset_gpio);
dev_err(dev, "failed to request reset GPIO: %d\n", ret);
return ret;
}
gpiod_set_value(rk628->enable_gpio, 1);
usleep_range(10000, 11000);
gpiod_set_value(rk628->reset_gpio, 0);
usleep_range(10000, 11000);
gpiod_set_value(rk628->reset_gpio, 1);
usleep_range(10000, 11000);
gpiod_set_value(rk628->reset_gpio, 0);
usleep_range(10000, 11000);
rk628->grf = devm_regmap_init_i2c(client, &rk628_grf_regmap_config);
if (IS_ERR(rk628->grf)) {
ret = PTR_ERR(rk628->grf);
dev_err(dev, "failed to allocate register map: %d\n", ret);
return ret;
}
/* selete int io function */
ret = regmap_write(rk628->grf, GRF_GPIO3AB_SEL_CON, 0x30002000);
if (ret) {
dev_err(dev, "failed to access register: %d\n", ret);
return ret;
}
ret = rk628_irq_init(rk628, client->irq);
if (ret) {
dev_err(dev, "failed to add IRQ chip: %d\n", ret);
return ret;
}
ret = mfd_add_devices(dev, PLATFORM_DEVID_NONE,
rk628_devs, ARRAY_SIZE(rk628_devs),
NULL, 0, rk628->irq_data->domain);
if (ret) {
rk628_irq_exit(rk628);
dev_err(dev, "Failed to add MFD children: %d\n", ret);
return ret;
}
return 0;
}
static void rk628_i2c_remove(struct i2c_client *client)
{
struct rk628 *rk628 = i2c_get_clientdata(client);
mfd_remove_devices(rk628->dev);
rk628_irq_exit(rk628);
}
static const struct of_device_id rk628_of_match[] = {
{ .compatible = "rockchip,rk628", },
{}
};
MODULE_DEVICE_TABLE(of, rk628_of_match);
static const struct i2c_device_id rk628_i2c_id[] = {
{ "rk628", 0 },
{}
};
MODULE_DEVICE_TABLE(i2c, rk628_i2c_id);
static struct i2c_driver rk628_i2c_driver = {
.driver = {
.name = "rk628",
.of_match_table = of_match_ptr(rk628_of_match),
},
.probe = rk628_i2c_probe,
.remove = rk628_i2c_remove,
.id_table = rk628_i2c_id,
};
module_i2c_driver(rk628_i2c_driver);
MODULE_AUTHOR("Wyon Bi <bivvy.bi@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip RK628 MFD driver");
MODULE_LICENSE("GPL v2");

View File

@@ -218,18 +218,6 @@ config NVMEM_RAVE_SP_EEPROM
help
Say y here to enable Rave SP EEPROM support.
config NVMEM_RK628_EFUSE
tristate "RK628 eFuse Support"
depends on ARCH_ROCKCHIP || COMPILE_TEST
depends on HAS_IOMEM
depends on MFD_RK628
help
This is a simple drive to dump specified values of Rk628 SoC
from eFuse, such as cpu-leakage.
This driver can also be built as a module. If so, the module
will be called nvmem_rk628_efuse.
config NVMEM_RMEM
tristate "Reserved Memory Based Driver Support"
depends on HAS_IOMEM

View File

@@ -45,8 +45,6 @@ obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
nvmem_qfprom-y := qfprom.o
obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
obj-$(CONFIG_NVMEM_RK628_EFUSE) += nvmem_rk628_efuse.o
nvmem_rk628_efuse-y := rk628-efuse.o
obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
nvmem-rmem-y := rmem.o
obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o

View File

@@ -1,299 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* RK628 eFuse Driver
*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Weixin Zhou <zwx@rock-chips.com>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/slab.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/rk628.h>
#define EFUSE_SIZE 64
#define T_CSB_P_S 0
#define T_PGENB_P_S (15 + 200)
#define T_LOAD_P_S 0
#define T_ADDR_P_S (15 + 200 + 5)
#define T_STROBE_P_S ((150 + 2000 + 100) / 9)
#define T_CSB_P_L 0
#define T_PGENB_P_L (15 + 200 + 10 + 200 + 190 + 10)
#define T_LOAD_P_L (15 + 200 + 200 + 190 + 10 + 100 + 15)
#define T_ADDR_P_L (15 + 200 + 5 + 200 + 5)
#define T_STROBE_P_L ((150 + 2000 + 100 + 2000) / 9)
#define T_CSB_R_S 0
#define T_PGENB_R_S 0
#define T_LOAD_R_S 15
#define T_ADDR_R_S (15 + 9)
#define T_STROBE_R_S ((150 + 100) / 9)
#define T_CSB_R_L 0
#define T_PGENB_R_L 0
#define T_LOAD_R_L (15 + 5 + 5 + 10 + 15)
#define T_ADDR_R_L (15 + 10 + 5 + 1)
#define T_STROBE_R_L ((150 + 100 + 50) / 8)
#define T_CSB_P 0x28
#define T_PGENB_P 0x2c
#define T_LOAD_P 0x30
#define T_ADDR_P 0x34
#define T_STROBE_P 0x38
#define T_CSB_R 0x3c
#define T_PGENB_R 0x40
#define T_LOAD_R 0x44
#define T_ADDR_R 0x48
#define T_STROBE_R 0x4c
#define EFUSE_REVISION 0x50
#define RK628_EFUSE_BASE 0xb0000
#define RK628_MOD 0x00
#define RK628_INT_STATUS 0x0018
#define RK628_DOUT 0x0020
#define RK628_AUTO_CTRL 0x0024
#define RK628_USER_MODE BIT(0)
#define RK628_INT_FINISH BIT(0)
#define RK628_AUTO_ENB BIT(0)
#define RK628_AUTO_RD BIT(1)
#define RK628_ADDR_ROW 16
#define RK628_ADDR_COL 22
#define RK628_A_SHIFT 16
#define RK628_A_MASK 0x3ff
#define RK628_NBYTES 1
#define REG_EFUSE_CTRL 0x0000
#define REG_EFUSE_DOUT 0x0004
struct rk628_efuse_chip {
struct device *dev;
u32 base;
struct clk *clk;
struct regmap *regmap;
struct gpio_desc *avdd_gpio;
};
static int rk628_read(struct regmap *regmap, u32 reg)
{
int ret;
u32 val;
struct rk628_efuse_chip *efuse = container_of(regmap, struct rk628_efuse_chip, regmap);
ret = regmap_read(regmap, reg, &val);
if (ret) {
dev_err(efuse->dev, "rk628-efuse:failed to read reg 0x%x\n", reg);
return ret;
}
return val;
}
static int rk628_write(struct regmap *regmap, u32 val, u32 reg)
{
int ret;
struct rk628_efuse_chip *efuse = container_of(regmap, struct rk628_efuse_chip, regmap);
ret = regmap_write(regmap, reg, val);
if (ret)
dev_err(efuse->dev, "rk628-efuse:failed to write reg 0x%x\n", reg);
return ret;
}
static void rk628_efuse_timing_init(struct rk628_efuse_chip *efuse)
{
u32 base = efuse->base;
/* enable auto mode */
rk628_write(efuse->regmap,
rk628_read(efuse->regmap, base + RK628_MOD) & (~RK628_USER_MODE),
base + RK628_MOD);
/* setup efuse timing */
rk628_write(efuse->regmap, (T_CSB_P_S << 16) | T_CSB_P_L, base + T_CSB_P);
rk628_write(efuse->regmap, (T_PGENB_P_S << 16) | T_PGENB_P_L, base + T_PGENB_P);
rk628_write(efuse->regmap, (T_LOAD_P_S << 16) | T_LOAD_P_L, base + T_LOAD_P);
rk628_write(efuse->regmap, (T_ADDR_P_S << 16) | T_ADDR_P_L, base + T_ADDR_P);
rk628_write(efuse->regmap, (T_STROBE_P_S << 16) | T_STROBE_P_L, base + T_STROBE_P);
rk628_write(efuse->regmap, (T_CSB_R_S << 16) | T_CSB_R_L, base + T_CSB_R);
rk628_write(efuse->regmap, (T_PGENB_R_S << 16) | T_PGENB_R_L, base + T_PGENB_R);
rk628_write(efuse->regmap, (T_LOAD_R_S << 16) | T_LOAD_R_L, base + T_LOAD_R);
rk628_write(efuse->regmap, (T_ADDR_R_S << 16) | T_ADDR_R_L, base + T_ADDR_R);
rk628_write(efuse->regmap, (T_STROBE_R_S << 16) | T_STROBE_R_L, base + T_STROBE_R);
}
static void rk628_efuse_timing_deinit(struct rk628_efuse_chip *efuse)
{
u32 base = efuse->base;
/* disable auto mode */
rk628_write(efuse->regmap,
rk628_read(efuse->regmap, base + RK628_MOD) | RK628_USER_MODE, base + RK628_MOD);
/* clear efuse timing */
rk628_write(efuse->regmap, 0, base + T_CSB_P);
rk628_write(efuse->regmap, 0, base + T_PGENB_P);
rk628_write(efuse->regmap, 0, base + T_LOAD_P);
rk628_write(efuse->regmap, 0, base + T_ADDR_P);
rk628_write(efuse->regmap, 0, base + T_STROBE_P);
rk628_write(efuse->regmap, 0, base + T_CSB_R);
rk628_write(efuse->regmap, 0, base + T_PGENB_R);
rk628_write(efuse->regmap, 0, base + T_LOAD_R);
rk628_write(efuse->regmap, 0, base + T_ADDR_R);
rk628_write(efuse->regmap, 0, base + T_STROBE_R);
}
static int rk628_efuse_read(void *context, unsigned int offset,
void *val, size_t bytes)
{
struct rk628_efuse_chip *efuse = context;
unsigned int addr_start, addr_end, addr_offset, addr_len;
u32 out_value, status;
u8 *buf;
int ret, i = 0;
ret = clk_prepare_enable(efuse->clk);
if (ret < 0) {
dev_err(efuse->dev, "failed to prepare/enable efuse pclk\n");
return ret;
}
addr_start = rounddown(offset, RK628_NBYTES) / RK628_NBYTES;
addr_end = roundup(offset + bytes, RK628_NBYTES) / RK628_NBYTES;
addr_offset = offset % RK628_NBYTES;
addr_len = addr_end - addr_start;
buf = kzalloc(sizeof(*buf) * addr_len * RK628_NBYTES, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto nomem;
}
rk628_efuse_timing_init(efuse);
while (addr_len--) {
rk628_write(efuse->regmap, RK628_AUTO_RD | RK628_AUTO_ENB |
((addr_start++ & RK628_A_MASK) << RK628_A_SHIFT),
efuse->base + RK628_AUTO_CTRL);
udelay(2);
status = rk628_read(efuse->regmap, efuse->base + RK628_INT_STATUS);
if (!(status & RK628_INT_FINISH)) {
ret = -EIO;
goto err;
}
out_value = rk628_read(efuse->regmap, efuse->base + RK628_DOUT);
rk628_write(efuse->regmap, RK628_INT_FINISH, efuse->base + RK628_INT_STATUS);
memcpy(&buf[i], &out_value, RK628_NBYTES);
i += RK628_NBYTES;
}
memcpy(val, buf + addr_offset, bytes);
err:
rk628_efuse_timing_deinit(efuse);
kfree(buf);
nomem:
clk_disable_unprepare(efuse->clk);
return ret;
}
static struct nvmem_config econfig = {
.name = "rk628-efuse",
.owner = THIS_MODULE,
.stride = 1,
.word_size = 1,
.read_only = true,
};
static const struct regmap_range rk628_efuse_readable_ranges[] = {
regmap_reg_range(RK628_EFUSE_BASE, RK628_EFUSE_BASE + EFUSE_REVISION),
};
static const struct regmap_access_table rk628_efuse_readable_table = {
.yes_ranges = rk628_efuse_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(rk628_efuse_readable_ranges),
};
static const struct regmap_config rk628_efuse_regmap_config = {
.name = "rk628-efuse",
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
.max_register = RK628_EFUSE_BASE + EFUSE_REVISION,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
.rd_table = &rk628_efuse_readable_table,
};
static const struct of_device_id rk628_efuse_match[] = {
{
.compatible = "rockchip,rk628-efuse",
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, rk628_efuse_match);
static int __init rk628_efuse_probe(struct platform_device *pdev)
{
struct nvmem_device *nvmem;
struct rk628_efuse_chip *efuse;
struct device *dev = &pdev->dev;
struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent);
int ret;
efuse = devm_kzalloc(&pdev->dev, sizeof(struct rk628_efuse_chip),
GFP_KERNEL);
if (!efuse)
return -ENOMEM;
efuse->regmap = devm_regmap_init_i2c(rk628->client,
&rk628_efuse_regmap_config);
if (IS_ERR(efuse->regmap)) {
ret = PTR_ERR(efuse->regmap);
dev_err(dev, "failed to allocate register map: %d\n",
ret);
return ret;
}
efuse->clk = devm_clk_get(&pdev->dev, "pclk");
if (IS_ERR(efuse->clk)) {
dev_err(dev, "failed to get pclk: %ld\n", PTR_ERR(efuse->clk));
return PTR_ERR(efuse->clk);
}
efuse->avdd_gpio = devm_gpiod_get_optional(dev, "efuse", GPIOD_OUT_LOW);
efuse->base = RK628_EFUSE_BASE;
efuse->dev = &pdev->dev;
econfig.size = EFUSE_SIZE;
econfig.reg_read = (void *)&rk628_efuse_read;
econfig.priv = efuse;
econfig.dev = efuse->dev;
nvmem = devm_nvmem_register(&econfig);
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
platform_set_drvdata(pdev, nvmem);
return 0;
}
static struct platform_driver rk628_efuse_driver = {
.probe = rk628_efuse_probe,
.driver = {
.name = "rk628-efuse",
.of_match_table = rk628_efuse_match,
},
};
module_platform_driver(rk628_efuse_driver);
MODULE_DESCRIPTION("rk628_efuse driver");
MODULE_LICENSE("GPL v2");

View File

@@ -414,16 +414,6 @@ config PINCTRL_PISTACHIO
help
This support pinctrl and GPIO driver for IMG Pistachio SoC.
config PINCTRL_RK628
tristate "Pinctrl and GPIO driver for RK628 PMIC"
depends on MFD_RK628
select GPIOLIB
select PINMUX
select GENERIC_PINCONF
select REGMAP_IRQ
help
This selects the pinctrl driver for RK628.
config PINCTRL_RK805
tristate "Pinctrl and GPIO driver for RK805 PMIC"
depends on MFD_RK808

View File

@@ -42,7 +42,6 @@ obj-$(CONFIG_PINCTRL_OXNAS) += pinctrl-oxnas.o
obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o
obj-$(CONFIG_PINCTRL_PIC32) += pinctrl-pic32.o
obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
obj-$(CONFIG_PINCTRL_RK628) += pinctrl-rk628.o
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
obj-$(CONFIG_PINCTRL_RK806) += pinctrl-rk806.o
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o

File diff suppressed because it is too large Load Diff

View File

@@ -1,272 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#ifndef _RK628_H
#define _RK628_H
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <drm/drm_crtc_helper.h>
#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16))
#define GRF_SYSTEM_CON0 0x0000
#define SW_VSYNC_POL_MASK BIT(26)
#define SW_VSYNC_POL(x) UPDATE(x, 26, 26)
#define SW_HSYNC_POL_MASK BIT(25)
#define SW_HSYNC_POL(x) UPDATE(x, 25, 25)
#define SW_ADAPTER_I2CSLADR_MASK GENMASK(24, 22)
#define SW_ADAPTER_I2CSLADR(x) UPDATE(x, 24, 22)
#define SW_EDID_MODE_MASK BIT(21)
#define SW_EDID_MODE(x) UPDATE(x, 21, 21)
#define SW_I2S_DATA_OEN_MASK BIT(10)
#define SW_I2S_DATA_OEN(x) UPDATE(x, 10, 10)
#define SW_BT_DATA_OEN_MASK BIT(9)
#define SW_BT_DATA_OEN BIT(9)
#define SW_EFUSE_HDCP_EN_MASK BIT(8)
#define SW_EFUSE_HDCP_EN(x) UPDATE(x, 8, 8)
#define SW_OUTPUT_MODE_MASK GENMASK(7, 3)
#define SW_OUTPUT_MODE(x) UPDATE(x, 7, 3)
#define SW_INPUT_MODE_MASK GENMASK(2, 0)
#define SW_INPUT_MODE(x) UPDATE(x, 2, 0)
#define GRF_SYSTEM_CON1 0x0004
#define GRF_SYSTEM_CON2 0x0008
#define GRF_SYSTEM_CON3 0x000c
#define GRF_GPIO_RX_CEC_SEL_MASK BIT(7)
#define GRF_GPIO_RX_CEC_SEL(x) UPDATE(x, 7, 7)
#define GRF_GPIO_RXDDC_SDA_SEL_MASK BIT(6)
#define GRF_GPIO_RXDDC_SDA_SEL(x) UPDATE(x, 6, 6)
#define GRF_GPIO_RXDDC_SCL_SEL_MASK BIT(5)
#define GRF_GPIO_RXDDC_SCL_SEL(x) UPDATE(x, 5, 5)
#define GRF_SCALER_CON0 0x0010
#define SCL_VER_DOWN_MODE(x) HIWORD_UPDATE(x, 8, 8)
#define SCL_HOR_DOWN_MODE(x) HIWORD_UPDATE(x, 7, 7)
#define SCL_BIC_COE_SEL(x) HIWORD_UPDATE(x, 6, 5)
#define SCL_VER_MODE(x) HIWORD_UPDATE(x, 4, 3)
#define SCL_HOR_MODE(x) HIWORD_UPDATE(x, 2, 1)
#define SCL_EN(x) HIWORD_UPDATE(x, 0, 0)
#define GRF_SCALER_CON1 0x0014
#define SCL_V_FACTOR(x) UPDATE(x, 31, 16)
#define SCL_H_FACTOR(x) UPDATE(x, 15, 0)
#define GRF_SCALER_CON2 0x0018
#define DSP_FRAME_VST(x) UPDATE(x, 28, 16)
#define DSP_FRAME_HST(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON3 0x001c
#define DSP_HS_END(x) UPDATE(x, 23, 16)
#define DSP_HTOTAL(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON4 0x0020
#define DSP_HACT_ST(x) UPDATE(x, 28, 16)
#define DSP_HACT_END(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON5 0x0024
#define DSP_VS_END(x) UPDATE(x, 23, 16)
#define DSP_VTOTAL(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON6 0x0028
#define DSP_VACT_ST(x) UPDATE(x, 28, 16)
#define DSP_VACT_END(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON7 0x002c
#define DSP_HBOR_ST(x) UPDATE(x, 28, 16)
#define DSP_HBOR_END(x) UPDATE(x, 12, 0)
#define GRF_SCALER_CON8 0x0030
#define DSP_VBOR_ST(x) UPDATE(x, 28, 16)
#define DSP_VBOR_END(x) UPDATE(x, 12, 0)
#define GRF_POST_PROC_CON 0x0034
#define SW_DCLK_OUT_INV_EN BIT(9)
#define SW_DCLK_IN_INV_EN BIT(8)
#define SW_TXPHY_REFCLK_SEL_MASK GENMASK(6, 5)
#define SW_TXPHY_REFCLK_SEL(x) UPDATE(x, 6, 5)
#define SW_HDMITX_VCLK_PLLREF_SEL_MASK BIT(4)
#define SW_HDMITX_VCLK_PLLREF_SEL(x) UPDATE(x, 4, 4)
#define SW_HDMITX_DCLK_INV_EN BIT(3)
#define SW_SPLIT_MODE(x) UPDATE(x, 1, 1)
#define SW_SPLIT_EN BIT(0)
#define GRF_CSC_CTRL_CON 0x0038
#define SW_YUV2VYU_SWP(x) HIWORD_UPDATE(x, 8, 8)
#define SW_R2Y_EN(x) HIWORD_UPDATE(x, 4, 4)
#define SW_Y2R_EN(x) HIWORD_UPDATE(x, 0, 0)
#define GRF_LVDS_TX_CON 0x003c
#define SW_LVDS_CON_DUAL_SEL(x) HIWORD_UPDATE(x, 12, 12)
#define SW_LVDS_CON_DEN_POLARITY(x) HIWORD_UPDATE(x, 11, 11)
#define SW_LVDS_CON_HS_POLARITY(x) HIWORD_UPDATE(x, 10, 10)
#define SW_LVDS_CON_CLKINV(x) HIWORD_UPDATE(x, 9, 9)
#define SW_LVDS_STARTPHASE(x) HIWORD_UPDATE(x, 8, 8)
#define SW_LVDS_CON_STARTSEL(x) HIWORD_UPDATE(x, 7, 7)
#define SW_LVDS_CON_CHASEL(x) HIWORD_UPDATE(x, 6, 6)
#define SW_LVDS_TIE_VSYNC_VALUE(x) HIWORD_UPDATE(x, 5, 5)
#define SW_LVDS_TIE_HSYNC_VALUE(x) HIWORD_UPDATE(x, 4, 4)
#define SW_LVDS_TIE_DEN_ONLY(x) HIWORD_UPDATE(x, 3, 3)
#define SW_LVDS_CON_MSBSEL(x) HIWORD_UPDATE(x, 2, 2)
#define SW_LVDS_CON_SELECT(x) HIWORD_UPDATE(x, 1, 0)
#define GRF_RGB_DEC_CON0 0x0040
#define SW_HRES_MASK GENMASK(28, 16)
#define SW_HRES(x) UPDATE(x, 28, 16)
#define DUAL_DATA_SWAP BIT(6)
#define DEC_DUALEDGE_EN BIT(5)
#define SW_PROGRESS_EN BIT(4)
#define SW_YC_SWAP BIT(3)
#define SW_CAP_EN_ASYNC BIT(1)
#define SW_CAP_EN_PSYNC BIT(0)
#define GRF_RGB_DEC_CON1 0x0044
#define SW_SET_X_MASK GENMASK(28, 16)
#define SW_SET_X(x) HIWORD_UPDATE(x, 28, 16)
#define SW_SET_Y_MASK GENMASK(28, 16)
#define SW_SET_Y(x) HIWORD_UPDATE(x, 28, 16)
#define GRF_RGB_DEC_CON2 0x0048
#define GRF_RGB_ENC_CON 0x004c
#define BT1120_UV_SWAP(x) HIWORD_UPDATE(x, 5, 5)
#define ENC_DUALEDGE_EN(x) HIWORD_UPDATE(x, 3, 3)
#define GRF_MIPI_LANE_DELAY_CON0 0x0050
#define GRF_MIPI_LANE_DELAY_CON1 0x0054
#define GRF_BT1120_DCLK_DELAY_CON0 0x0058
#define GRF_BT1120_DCLK_DELAY_CON1 0x005c
#define GRF_MIPI_TX0_CON 0x0060
#define DPIUPDATECFG BIT(26)
#define DPICOLORM BIT(25)
#define DPISHUTDN BIT(24)
#define CSI_PHYRSTZ BIT(21)
#define CSI_PHYSHUTDOWNZ BIT(20)
#define FORCETXSTOPMODE_MASK GENMASK(19, 16)
#define FORCETXSTOPMODE(x) UPDATE(x, 19, 16)
#define FORCERXMODE_MASK GENMASK(15, 12)
#define FORCERXMODE(x) UPDATE(x, 15, 12)
#define PHY_TESTCLR BIT(10)
#define PHY_TESTCLK BIT(9)
#define PHY_TESTEN BIT(8)
#define PHY_TESTDIN_MASK GENMASK(7, 0)
#define PHY_TESTDIN(x) UPDATE(x, 7, 0)
#define GRF_DPHY0_STATUS 0x0064
#define DPHY_PHYLOCK BIT(24)
#define PHY_TESTDOUT_SHIFT 8
#define GRF_MIPI_TX1_CON 0x0068
#define GRF_DPHY1_STATUS 0x006c
#define GRF_GPIO0AB_SEL_CON 0x0070
#define GRF_GPIO1AB_SEL_CON 0x0074
#define GRF_GPIO2AB_SEL_CON 0x0078
#define GRF_GPIO2C_SEL_CON 0x007c
#define GRF_GPIO3AB_SEL_CON 0x0080
#define GRF_GPIO2A_SMT 0x0090
#define GRF_GPIO2B_SMT 0x0094
#define GRF_GPIO2C_SMT 0x0098
#define GRF_GPIO3AB_SMT 0x009c
#define GRF_GPIO0A_P_CON 0x00a0
#define GRF_GPIO1A_P_CON 0x00a4
#define GRF_GPIO2A_P_CON 0x00a8
#define GRF_GPIO2B_P_CON 0x00ac
#define GRF_GPIO2C_P_CON 0x00b0
#define GRF_GPIO3A_P_CON 0x00b4
#define GRF_GPIO3B_P_CON 0x00b8
#define GRF_GPIO0B_D_CON 0x00c0
#define GRF_GPIO1B_D_CON 0x00c4
#define GRF_GPIO2A_D0_CON 0x00c8
#define GRF_GPIO2A_D1_CON 0x00cc
#define GRF_GPIO2B_D0_CON 0x00d0
#define GRF_GPIO2B_D1_CON 0x00d4
#define GRF_GPIO2C_D0_CON 0x00d8
#define GRF_GPIO2C_D1_CON 0x00dc
#define GRF_GPIO3A_D0_CON 0x00e0
#define GRF_GPIO3A_D1_CON 0x00e4
#define GRF_GPIO3B_D_CON 0x00e8
#define GRF_GPIO_SR_CON 0x00ec
#define GRF_INTR0_EN 0x0100
#define GRF_INTR0_CLR_EN 0x0104
#define GRF_INTR0_STATUS 0x0108
#define GRF_INTR0_RAW_STATUS 0x010c
#define GRF_INTR1_EN 0x0110
#define GRF_INTR1_CLR_EN 0x0114
#define GRF_INTR1_STATUS 0x0118
#define GRF_INTR1_RAW_STATUS 0x011c
#define GRF_SYSTEM_STATUS0 0x0120
/* 0: i2c mode and mcu mode; 1: i2c mode only */
#define I2C_ONLY_FLAG BIT(6)
#define GRF_SYSTEM_STATUS3 0x012c
#define GRF_SYSTEM_STATUS4 0x0130
#define GRF_OS_REG0 0x0140
#define GRF_OS_REG1 0x0144
#define GRF_OS_REG2 0x0148
#define GRF_OS_REG3 0x014c
#define GRF_SOC_VERSION 0x0150
#define GRF_MAX_REGISTER GRF_SOC_VERSION
enum {
COMBTXPHY_MODULEA_EN = BIT(0),
COMBTXPHY_MODULEB_EN = BIT(1),
};
enum {
OUTPUT_MODE_GVI = 1,
OUTPUT_MODE_LVDS,
OUTPUT_MODE_HDMI,
OUTPUT_MODE_CSI,
OUTPUT_MODE_DSI,
OUTPUT_MODE_BT1120 = 8,
OUTPUT_MODE_RGB = 16,
OUTPUT_MODE_YUV = 24,
};
enum {
INPUT_MODE_HDMI,
INPUT_MODE_BT1120 = 2,
INPUT_MODE_RGB,
INPUT_MODE_YUV,
};
struct rk628_irq_chip_data {
const char *name;
unsigned int status_base;
unsigned int mask_base;
unsigned int ack_base;
int num_regs;
const struct regmap_irq *irqs;
int num_irqs;
struct mutex lock;
struct irq_chip irq_chip;
struct regmap *map;
struct irq_domain *domain;
int irq;
unsigned int *status_buf;
unsigned int *mask_buf;
unsigned int *mask_buf_def;
unsigned int irq_reg_stride;
unsigned int reg_stride;
};
struct rk628 {
struct device *dev;
struct i2c_client *client;
struct regmap *grf;
struct gpio_desc *reset_gpio;
struct gpio_desc *enable_gpio;
struct rk628_irq_chip_data *irq_data;
struct drm_display_mode src_mode;
struct drm_display_mode dst_mode;
bool dst_mode_valid;
};
/**
* rk628_scaler_add_src_mode - add source mode for scaler
* @rk628: parent device
* @connector: DRM connector
* If need scale, call the function at last of get_modes.
*/
int rk628_scaler_add_src_mode(struct rk628 *rk628,
struct drm_connector *connector);
/**
* rk628_mode_copy - rk628 mode copy
* @rk628: parent device
* @dst: dst mode
* @src: src mode
* Call the function at mode_set, replace drm_mode_copy.
*/
void rk628_mode_copy(struct rk628 *rk628, struct drm_display_mode *dst,
const struct drm_display_mode *src);
#endif