aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge')
-rw-r--r--drivers/gpu/drm/bridge/Kconfig21
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_cec.c1
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c13
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx6345.c4
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c6
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.c251
-rw-r--r--drivers/gpu/drm/bridge/analogix/anx7625.h2
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c3
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c80
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h2
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c9
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h2
-rw-r--r--drivers/gpu/drm/bridge/chipone-icn6211.c4
-rw-r--r--drivers/gpu/drm/bridge/chrontel-ch7033.c4
-rw-r--r--drivers/gpu/drm/bridge/cros-ec-anx7688.c2
-rw-r--r--drivers/gpu/drm/bridge/display-connector.c62
-rw-r--r--drivers/gpu/drm/bridge/fsl-ldb.c15
-rw-r--r--drivers/gpu/drm/bridge/imx/Kconfig5
-rw-r--r--drivers/gpu/drm/bridge/imx/Makefile5
-rw-r--r--drivers/gpu/drm/bridge/imx/imx-ldb-helper.c17
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qm-ldb.c (renamed from drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c)2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c (renamed from drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c)1
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c137
-rw-r--r--drivers/gpu/drm/bridge/ite-it66121.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt8912b.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9211.c7
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611.c2
-rw-r--r--drivers/gpu/drm/bridge/lontium-lt9611uxc.c8
-rw-r--r--drivers/gpu/drm/bridge/lvds-codec.c1
-rw-r--r--drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c4
-rw-r--r--drivers/gpu/drm/bridge/nwl-dsi.c2
-rw-r--r--drivers/gpu/drm/bridge/nxp-ptn3460.c2
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8622.c3
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8640.c81
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c206
-rw-r--r--drivers/gpu/drm/bridge/sii902x.c42
-rw-r--r--drivers/gpu/drm/bridge/sii9234.c2
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c4
-rw-r--r--drivers/gpu/drm/bridge/simple-bridge.c3
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c37
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c60
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c30
-rw-r--r--drivers/gpu/drm/bridge/tc358762.c78
-rw-r--r--drivers/gpu/drm/bridge/tc358764.c14
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c232
-rw-r--r--drivers/gpu/drm/bridge/tc358768.c99
-rw-r--r--drivers/gpu/drm/bridge/tc358775.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-dlpc3433.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi83.c24
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c56
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c47
51 files changed, 1162 insertions, 538 deletions
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index f076a09afac0..44a660a4bdbf 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -74,19 +74,19 @@ config DRM_FSL_LDB
Support for i.MX8MP DPI-to-LVDS on-SoC encoder.
config DRM_ITE_IT6505
- tristate "ITE IT6505 DisplayPort bridge"
- depends on OF
+ tristate "ITE IT6505 DisplayPort bridge"
+ depends on OF
select DRM_DISPLAY_DP_HELPER
select DRM_DISPLAY_HDCP_HELPER
select DRM_DISPLAY_HELPER
- select DRM_DP_AUX_BUS
- select DRM_KMS_HELPER
- select DRM_DP_HELPER
- select EXTCON
- select CRYPTO
- select CRYPTO_HASH
- help
- ITE IT6505 DisplayPort bridge chip driver.
+ select DRM_DP_AUX_BUS
+ select DRM_KMS_HELPER
+ select DRM_DP_HELPER
+ select EXTCON
+ select CRYPTO
+ select CRYPTO_HASH
+ help
+ ITE IT6505 DisplayPort bridge chip driver.
config DRM_LONTIUM_LT8912B
tristate "Lontium LT8912B DSI/HDMI bridge"
@@ -227,6 +227,7 @@ config DRM_SAMSUNG_DSIM
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL_BRIDGE
+ select GENERIC_PHY_MIPI_DPHY
help
The Samsung MIPI DSIM bridge controller driver.
This MIPI DSIM bridge can be found it on Exynos SoCs and
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index 99964f5a5457..2a6b91f752cb 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -7,7 +7,6 @@
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index ddceafa7b637..2611afd2c1c1 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -9,7 +9,7 @@
#include <linux/device.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/slab.h>
#include <media/cec.h>
@@ -786,8 +786,13 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
else
low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE;
- regmap_update_bits(adv7511->regmap, 0xfb,
- 0x6, low_refresh_rate << 1);
+ if (adv7511->type == ADV7511)
+ regmap_update_bits(adv7511->regmap, 0xfb,
+ 0x6, low_refresh_rate << 1);
+ else
+ regmap_update_bits(adv7511->regmap, 0x4a,
+ 0xc, low_refresh_rate << 2);
+
regmap_update_bits(adv7511->regmap, 0x17,
0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
@@ -1393,7 +1398,7 @@ static struct i2c_driver adv7511_driver = {
.of_match_table = adv7511_of_ids,
},
.id_table = adv7511_i2c_ids,
- .probe_new = adv7511_probe,
+ .probe = adv7511_probe,
.remove = adv7511_remove,
};
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
index 3577c532abb4..c9e35731e6a1 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx6345.c
@@ -813,9 +813,9 @@ MODULE_DEVICE_TABLE(of, anx6345_match_table);
static struct i2c_driver anx6345_driver = {
.driver = {
.name = "anx6345",
- .of_match_table = of_match_ptr(anx6345_match_table),
+ .of_match_table = anx6345_match_table,
},
- .probe_new = anx6345_i2c_probe,
+ .probe = anx6345_i2c_probe,
.remove = anx6345_i2c_remove,
.id_table = anx6345_id,
};
diff --git a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
index a3a38bbe2786..800555aef97f 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix-anx78xx.c
@@ -1373,7 +1373,6 @@ static const struct i2c_device_id anx78xx_id[] = {
};
MODULE_DEVICE_TABLE(i2c, anx78xx_id);
-#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id anx78xx_match_table[] = {
{ .compatible = "analogix,anx7808", .data = anx7808_i2c_addresses },
{ .compatible = "analogix,anx7812", .data = anx781x_i2c_addresses },
@@ -1382,14 +1381,13 @@ static const struct of_device_id anx78xx_match_table[] = {
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, anx78xx_match_table);
-#endif
static struct i2c_driver anx78xx_driver = {
.driver = {
.name = "anx7814",
- .of_match_table = of_match_ptr(anx78xx_match_table),
+ .of_match_table = anx78xx_match_table,
},
- .probe_new = anx78xx_i2c_probe,
+ .probe = anx78xx_i2c_probe,
.remove = anx78xx_i2c_remove,
.id_table = anx78xx_id,
};
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 6846199a2ee1..51abe42c639e 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -17,7 +17,6 @@
#include <linux/types.h>
#include <linux/workqueue.h>
-#include <linux/of_gpio.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
@@ -207,7 +206,7 @@ static int anx7625_read_ctrl_status_p0(struct anx7625_data *ctx)
static int wait_aux_op_finish(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int val;
int ret;
@@ -234,7 +233,7 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
static int anx7625_aux_trans(struct anx7625_data *ctx, u8 op, u32 address,
u8 len, u8 *buf)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
u8 addrh, addrm, addrl;
u8 cmd;
@@ -427,7 +426,7 @@ static int anx7625_odfc_config(struct anx7625_data *ctx,
u8 post_divider)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Config input reference clock frequency 27MHz/19.2MHz */
ret = anx7625_write_and(ctx, ctx->i2c.rx_p1_client, MIPI_DIGITAL_PLL_16,
@@ -477,7 +476,7 @@ static int anx7625_set_k_value(struct anx7625_data *ctx)
static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
unsigned long m, n;
u16 htotal;
int ret;
@@ -575,7 +574,7 @@ static int anx7625_dsi_video_timing_config(struct anx7625_data *ctx)
static int anx7625_swap_dsi_lane3(struct anx7625_data *ctx)
{
int val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Swap MIPI-DSI data lane 3 P and N */
val = anx7625_reg_read(ctx, ctx->i2c.rx_p1_client, MIPI_SWAP);
@@ -592,7 +591,7 @@ static int anx7625_api_dsi_config(struct anx7625_data *ctx)
{
int val, ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Swap MIPI-DSI data lane 3 P and N */
ret = anx7625_swap_dsi_lane3(ctx);
@@ -657,7 +656,7 @@ static int anx7625_api_dsi_config(struct anx7625_data *ctx)
static int anx7625_dsi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
DRM_DEV_DEBUG_DRIVER(dev, "config dsi.\n");
@@ -689,7 +688,7 @@ static int anx7625_dsi_config(struct anx7625_data *ctx)
static int anx7625_api_dpi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u16 freq = ctx->dt.pixelclock.min / 1000;
int ret;
@@ -720,7 +719,7 @@ static int anx7625_api_dpi_config(struct anx7625_data *ctx)
static int anx7625_dpi_config(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
DRM_DEV_DEBUG_DRIVER(dev, "config dpi\n");
@@ -765,7 +764,7 @@ static int anx7625_read_flash_status(struct anx7625_data *ctx)
static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
{
int ret, val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 ident[FLASH_BUF_LEN];
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -815,7 +814,7 @@ static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Select HDCP 1.4 KEY */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -843,7 +842,7 @@ static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
static int anx7625_hdcp_disable(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
dev_dbg(dev, "disable HDCP 1.4\n");
@@ -864,7 +863,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx)
{
u8 bcap;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
ret = anx7625_hdcp_key_probe(ctx);
if (ret) {
@@ -873,11 +872,11 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx)
}
/* Read downstream capability */
- ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_READ, 0x68028, 1, &bcap);
+ ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_READ, DP_AUX_HDCP_BCAPS, 1, &bcap);
if (ret < 0)
return ret;
- if (!(bcap & 0x01)) {
+ if (!(bcap & DP_BCAPS_HDCP_CAPABLE)) {
pr_warn("downstream not support HDCP 1.4, cap(%x).\n", bcap);
return 0;
}
@@ -922,7 +921,7 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx)
static void anx7625_dp_start(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 data;
if (!ctx->display_timing_valid) {
@@ -932,8 +931,8 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
dev_dbg(dev, "set downstream sink into normal\n");
/* Downstream sink enter into normal mode */
- data = 1;
- ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_WRITE, 0x000600, 1, &data);
+ data = DP_SET_POWER_D0;
+ ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_WRITE, DP_SET_POWER, 1, &data);
if (ret < 0)
dev_err(dev, "IO error : set sink into normal mode fail\n");
@@ -955,7 +954,7 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
static void anx7625_dp_stop(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
u8 data;
@@ -972,8 +971,8 @@ static void anx7625_dp_stop(struct anx7625_data *ctx)
dev_dbg(dev, "notify downstream enter into standby\n");
/* Downstream monitor enter into standby mode */
- data = 2;
- ret |= anx7625_aux_trans(ctx, DP_AUX_NATIVE_WRITE, 0x000600, 1, &data);
+ data = DP_SET_POWER_D3;
+ ret |= anx7625_aux_trans(ctx, DP_AUX_NATIVE_WRITE, DP_SET_POWER, 1, &data);
if (ret < 0)
DRM_DEV_ERROR(dev, "IO error : mute video fail\n");
@@ -1020,7 +1019,7 @@ static int sp_tx_aux_rd(struct anx7625_data *ctx, u8 len_cmd)
static int sp_tx_get_edid_block(struct anx7625_data *ctx)
{
int c = 0;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
sp_tx_aux_wr(ctx, 0x7e);
sp_tx_aux_rd(ctx, 0x01);
@@ -1042,7 +1041,7 @@ static int edid_read(struct anx7625_data *ctx,
u8 offset, u8 *pblock_buf)
{
int ret, cnt;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
for (cnt = 0; cnt <= EDID_TRY_CNT; cnt++) {
sp_tx_aux_wr(ctx, offset);
@@ -1073,7 +1072,7 @@ static int segments_edid_read(struct anx7625_data *ctx,
{
u8 cnt;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Write address only */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -1128,7 +1127,7 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
u8 i, j;
int g_edid_break = 0;
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Address initial */
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
@@ -1235,7 +1234,7 @@ static int sp_tx_edid_read(struct anx7625_data *ctx,
static void anx7625_power_on(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret, i;
if (!ctx->pdata.low_power_mode) {
@@ -1271,7 +1270,7 @@ reg_err:
static void anx7625_power_standby(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
if (!ctx->pdata.low_power_mode) {
@@ -1301,7 +1300,7 @@ static void anx7625_config(struct anx7625_data *ctx)
static void anx7625_disable_pd_protocol(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
/* Reset main ocm */
@@ -1321,7 +1320,7 @@ static void anx7625_disable_pd_protocol(struct anx7625_data *ctx)
static int anx7625_ocm_loading_check(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Check interface workable */
ret = anx7625_reg_read(ctx, ctx->i2c.rx_p0_client,
@@ -1367,7 +1366,7 @@ static void anx7625_power_on_init(struct anx7625_data *ctx)
static void anx7625_init_gpio(struct anx7625_data *platform)
{
- struct device *dev = &platform->client->dev;
+ struct device *dev = platform->dev;
DRM_DEV_DEBUG_DRIVER(dev, "init gpio\n");
@@ -1407,7 +1406,7 @@ static void anx7625_stop_dp_work(struct anx7625_data *ctx)
static void anx7625_start_dp_work(struct anx7625_data *ctx)
{
int ret;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
if (ctx->hpd_high_cnt >= 2) {
DRM_DEV_DEBUG_DRIVER(dev, "filter useless HPD\n");
@@ -1459,7 +1458,7 @@ static int _anx7625_hpd_polling(struct anx7625_data *ctx,
unsigned long wait_us)
{
int ret, val;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* Interrupt mode, no need poll HPD status, just return */
if (ctx->pdata.intp_irq)
@@ -1493,7 +1492,7 @@ static int anx7625_wait_hpd_asserted(struct drm_dp_aux *aux,
unsigned long wait_us)
{
struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int ret;
pm_runtime_get_sync(dev);
@@ -1526,7 +1525,7 @@ static void anx7625_dp_adjust_swing(struct anx7625_data *ctx)
static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
/* HPD changed */
DRM_DEV_DEBUG_DRIVER(dev, "dp_hpd_change_default_func: %d\n",
@@ -1546,7 +1545,7 @@ static void dp_hpd_change_handler(struct anx7625_data *ctx, bool on)
static int anx7625_hpd_change_detect(struct anx7625_data *ctx)
{
int intr_vector, status;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
status = anx7625_reg_write(ctx, ctx->i2c.tcpc_client,
INTR_ALERT_1, 0xFF);
@@ -1594,18 +1593,20 @@ static void anx7625_work_func(struct work_struct *work)
mutex_lock(&ctx->lock);
- if (pm_runtime_suspended(&ctx->client->dev))
- goto unlock;
+ if (pm_runtime_suspended(ctx->dev)) {
+ mutex_unlock(&ctx->lock);
+ return;
+ }
event = anx7625_hpd_change_detect(ctx);
+
+ mutex_unlock(&ctx->lock);
+
if (event < 0)
- goto unlock;
+ return;
if (ctx->bridge_attached)
drm_helper_hpd_irq_event(ctx->bridge.dev);
-
-unlock:
- mutex_unlock(&ctx->lock);
}
static irqreturn_t anx7625_intr_hpd_isr(int irq, void *data)
@@ -1687,6 +1688,14 @@ static int anx7625_parse_dt(struct device *dev,
if (of_property_read_bool(np, "analogix,audio-enable"))
pdata->audio_en = 1;
+ return 0;
+}
+
+static int anx7625_parse_dt_panel(struct device *dev,
+ struct anx7625_platform_data *pdata)
+{
+ struct device_node *np = dev->of_node;
+
pdata->panel_bridge = devm_drm_of_get_bridge(dev, np, 1, 0);
if (IS_ERR(pdata->panel_bridge)) {
if (PTR_ERR(pdata->panel_bridge) == -ENODEV) {
@@ -1728,7 +1737,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg)
{
struct anx7625_data *ctx = container_of(aux, struct anx7625_data, aux);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u8 request = msg->request & ~DP_AUX_I2C_MOT;
int ret = 0;
@@ -1754,7 +1763,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux,
static struct edid *anx7625_get_edid(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct s_edid_data *p_edid = &ctx->slimport_edid_p;
int edid_num;
u8 *edid;
@@ -1790,7 +1799,7 @@ static struct edid *anx7625_get_edid(struct anx7625_data *ctx)
static enum drm_connector_status anx7625_sink_detect(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "sink detect\n");
@@ -1999,7 +2008,7 @@ static const struct hdmi_codec_ops anx7625_codec_ops = {
static void anx7625_unregister_audio(struct anx7625_data *ctx)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
if (ctx->audio_pdev) {
platform_device_unregister(ctx->audio_pdev);
@@ -2032,19 +2041,16 @@ static int anx7625_register_audio(struct device *dev, struct anx7625_data *ctx)
return 0;
}
-static int anx7625_attach_dsi(struct anx7625_data *ctx)
+static int anx7625_setup_dsi_device(struct anx7625_data *ctx)
{
struct mipi_dsi_device *dsi;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct mipi_dsi_host *host;
const struct mipi_dsi_device_info info = {
.type = "anx7625",
.channel = 0,
.node = NULL,
};
- int ret;
-
- DRM_DEV_DEBUG_DRIVER(dev, "attach dsi\n");
host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
if (!host) {
@@ -2065,14 +2071,24 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
MIPI_DSI_MODE_VIDEO_HSE |
MIPI_DSI_HS_PKT_END_ALIGNED;
- ret = devm_mipi_dsi_attach(dev, dsi);
+ ctx->dsi = dsi;
+
+ return 0;
+}
+
+static int anx7625_attach_dsi(struct anx7625_data *ctx)
+{
+ struct device *dev = ctx->dev;
+ int ret;
+
+ DRM_DEV_DEBUG_DRIVER(dev, "attach dsi\n");
+
+ ret = devm_mipi_dsi_attach(dev, ctx->dsi);
if (ret) {
DRM_DEV_ERROR(dev, "fail to attach dsi to host.\n");
return ret;
}
- ctx->dsi = dsi;
-
DRM_DEV_DEBUG_DRIVER(dev, "attach dsi succeeded.\n");
return 0;
@@ -2088,7 +2104,7 @@ static void hdcp_check_work_func(struct work_struct *work)
dwork = to_delayed_work(work);
ctx = container_of(dwork, struct anx7625_data, hdcp_work);
- dev = &ctx->client->dev;
+ dev = ctx->dev;
if (!ctx->connector) {
dev_err(dev, "HDCP connector is null!");
@@ -2115,7 +2131,7 @@ static void hdcp_check_work_func(struct work_struct *work)
static int anx7625_connector_atomic_check(struct anx7625_data *ctx,
struct drm_connector_state *state)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
int cp;
dev_dbg(dev, "hdcp state check\n");
@@ -2160,7 +2176,7 @@ static int anx7625_bridge_attach(struct drm_bridge *bridge,
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
int err;
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "drm attach\n");
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
@@ -2204,7 +2220,7 @@ anx7625_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "drm mode checking\n");
@@ -2225,7 +2241,7 @@ static void anx7625_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "drm mode set\n");
@@ -2271,7 +2287,7 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
struct drm_display_mode *adj)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
u32 hsync, hfp, hbp, hblanking;
u32 adj_hsync, adj_hfp, adj_hbp, adj_hblanking, delta_adj;
u32 vref, adj_clock;
@@ -2389,7 +2405,7 @@ static int anx7625_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_connector_state *conn_state)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
dev_dbg(dev, "drm bridge atomic check\n");
@@ -2403,7 +2419,7 @@ static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *state)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
struct drm_connector *connector;
dev_dbg(dev, "drm atomic enable\n");
@@ -2430,7 +2446,7 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
dev_dbg(dev, "drm atomic disable\n");
@@ -2444,7 +2460,7 @@ static enum drm_connector_status
anx7625_bridge_detect(struct drm_bridge *bridge)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n");
@@ -2455,7 +2471,7 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
DRM_DEV_DEBUG_DRIVER(dev, "drm bridge get edid\n");
@@ -2480,7 +2496,7 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs = {
static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
struct i2c_client *client)
{
- struct device *dev = &ctx->client->dev;
+ struct device *dev = ctx->dev;
ctx->i2c.tx_p0_client = devm_i2c_new_dummy_device(dev, client->adapter,
TX_P0_ADDR >> 1);
@@ -2560,6 +2576,40 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
}
+static int anx7625_link_bridge(struct drm_dp_aux *aux)
+{
+ struct anx7625_data *platform = container_of(aux, struct anx7625_data, aux);
+ struct device *dev = aux->dev;
+ int ret;
+
+ ret = anx7625_parse_dt_panel(dev, &platform->pdata);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "fail to parse DT for panel : %d\n", ret);
+ return ret;
+ }
+
+ platform->bridge.funcs = &anx7625_bridge_funcs;
+ platform->bridge.of_node = dev->of_node;
+ if (!anx7625_of_panel_on_aux_bus(dev))
+ platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
+ if (!platform->pdata.panel_bridge)
+ platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
+ DRM_BRIDGE_OP_DETECT;
+ platform->bridge.type = platform->pdata.panel_bridge ?
+ DRM_MODE_CONNECTOR_eDP :
+ DRM_MODE_CONNECTOR_DisplayPort;
+
+ drm_bridge_add(&platform->bridge);
+
+ if (!platform->pdata.is_dpi) {
+ ret = anx7625_attach_dsi(platform);
+ if (ret)
+ drm_bridge_remove(&platform->bridge);
+ }
+
+ return ret;
+}
+
static int anx7625_i2c_probe(struct i2c_client *client)
{
struct anx7625_data *platform;
@@ -2581,7 +2631,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
pdata = &platform->pdata;
- platform->client = client;
+ platform->dev = &client->dev;
i2c_set_clientdata(client, platform);
pdata->supplies[0].supply = "vdd10";
@@ -2634,6 +2684,24 @@ static int anx7625_i2c_probe(struct i2c_client *client)
platform->aux.wait_hpd_asserted = anx7625_wait_hpd_asserted;
drm_dp_aux_init(&platform->aux);
+ ret = anx7625_parse_dt(dev, pdata);
+ if (ret) {
+ if (ret != -EPROBE_DEFER)
+ DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret);
+ goto free_wq;
+ }
+
+ if (!platform->pdata.is_dpi) {
+ ret = anx7625_setup_dsi_device(platform);
+ if (ret < 0)
+ goto free_wq;
+ }
+
+ /*
+ * Registering the i2c devices will retrigger deferred probe, so it
+ * needs to be done after calls that might return EPROBE_DEFER,
+ * otherwise we can get an infinite loop.
+ */
if (anx7625_register_i2c_dummy_clients(platform, client) != 0) {
ret = -ENOMEM;
DRM_DEV_ERROR(dev, "fail to reserve I2C bus.\n");
@@ -2648,13 +2716,21 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (ret)
goto free_wq;
- devm_of_dp_aux_populate_ep_devices(&platform->aux);
-
- ret = anx7625_parse_dt(dev, pdata);
+ /*
+ * Populating the aux bus will retrigger deferred probe, so it needs to
+ * be done after calls that might return EPROBE_DEFER, otherwise we can
+ * get an infinite loop.
+ */
+ ret = devm_of_dp_aux_populate_bus(&platform->aux, anx7625_link_bridge);
if (ret) {
- if (ret != -EPROBE_DEFER)
- DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret);
- goto free_wq;
+ if (ret != -ENODEV) {
+ DRM_DEV_ERROR(dev, "failed to populate aux bus : %d\n", ret);
+ goto free_wq;
+ }
+
+ ret = anx7625_link_bridge(&platform->aux);
+ if (ret)
+ goto free_wq;
}
if (!platform->pdata.low_power_mode) {
@@ -2667,27 +2743,6 @@ static int anx7625_i2c_probe(struct i2c_client *client)
if (platform->pdata.intp_irq)
queue_work(platform->workqueue, &platform->work);
- platform->bridge.funcs = &anx7625_bridge_funcs;
- platform->bridge.of_node = client->dev.of_node;
- if (!anx7625_of_panel_on_aux_bus(&client->dev))
- platform->bridge.ops |= DRM_BRIDGE_OP_EDID;
- if (!platform->pdata.panel_bridge)
- platform->bridge.ops |= DRM_BRIDGE_OP_HPD |
- DRM_BRIDGE_OP_DETECT;
- platform->bridge.type = platform->pdata.panel_bridge ?
- DRM_MODE_CONNECTOR_eDP :
- DRM_MODE_CONNECTOR_DisplayPort;
-
- drm_bridge_add(&platform->bridge);
-
- if (!platform->pdata.is_dpi) {
- ret = anx7625_attach_dsi(platform);
- if (ret) {
- DRM_DEV_ERROR(dev, "Fail to attach to dsi : %d\n", ret);
- goto unregister_bridge;
- }
- }
-
if (platform->pdata.audio_en)
anx7625_register_audio(dev, platform);
@@ -2695,12 +2750,6 @@ static int anx7625_i2c_probe(struct i2c_client *client)
return 0;
-unregister_bridge:
- drm_bridge_remove(&platform->bridge);
-
- if (!platform->pdata.low_power_mode)
- pm_runtime_put_sync_suspend(&client->dev);
-
free_wq:
if (platform->workqueue)
destroy_workqueue(platform->workqueue);
@@ -2753,7 +2802,7 @@ static struct i2c_driver anx7625_driver = {
.of_match_table = anx_match_table,
.pm = &anx7625_pm_ops,
},
- .probe_new = anx7625_i2c_probe,
+ .probe = anx7625_i2c_probe,
.remove = anx7625_i2c_remove,
.id_table = anx7625_id,
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 14f33d6be289..5af819611ebc 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -458,7 +458,7 @@ struct anx7625_data {
int hdcp_cp;
/* Lock for work queue */
struct mutex lock;
- struct i2c_client *client;
+ struct device *dev;
struct anx7625_i2c_client i2c;
struct i2c_client *last_client;
struct timer_list hdcp_timer;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index f50d65f54314..7457d38622b0 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -14,8 +14,7 @@
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index f6822dfa3805..6af565ac307a 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -29,7 +29,6 @@
#include <linux/media-bus-format.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-dp.h>
#include <linux/platform_device.h>
@@ -54,6 +53,26 @@
#include "cdns-mhdp8546-hdcp.h"
#include "cdns-mhdp8546-j721e.h"
+static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge)
+{
+ struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
+
+ /* Enable SW event interrupts */
+ if (mhdp->bridge_attached)
+ writel(readl(mhdp->regs + CDNS_APB_INT_MASK) &
+ ~CDNS_APB_INT_MASK_SW_EVENT_INT,
+ mhdp->regs + CDNS_APB_INT_MASK);
+}
+
+static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge)
+{
+ struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
+
+ writel(readl(mhdp->regs + CDNS_APB_INT_MASK) |
+ CDNS_APB_INT_MASK_SW_EVENT_INT,
+ mhdp->regs + CDNS_APB_INT_MASK);
+}
+
static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
{
int ret, empty;
@@ -749,9 +768,7 @@ static int cdns_mhdp_fw_activate(const struct firmware *fw,
* MHDP_HW_STOPPED happens only due to driver removal when
* bridge should already be detached.
*/
- if (mhdp->bridge_attached)
- writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT,
- mhdp->regs + CDNS_APB_INT_MASK);
+ cdns_mhdp_bridge_hpd_enable(&mhdp->bridge);
spin_unlock(&mhdp->start_lock);
@@ -1740,8 +1757,7 @@ static int cdns_mhdp_attach(struct drm_bridge *bridge,
/* Enable SW event interrupts */
if (hw_ready)
- writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT,
- mhdp->regs + CDNS_APB_INT_MASK);
+ cdns_mhdp_bridge_hpd_enable(bridge);
return 0;
aux_unregister:
@@ -2146,6 +2162,27 @@ cdns_mhdp_bridge_atomic_reset(struct drm_bridge *bridge)
return &cdns_mhdp_state->base;
}
+static u32 *cdns_mhdp_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ *num_input_fmts = 1;
+ input_fmts[0] = MEDIA_BUS_FMT_RGB121212_1X36;
+
+ return input_fmts;
+}
+
static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
@@ -2165,6 +2202,13 @@ static int cdns_mhdp_atomic_check(struct drm_bridge *bridge,
return -EINVAL;
}
+ /*
+ * There might be flags negotiation supported in future.
+ * Set the bus flags in atomic_check statically for now.
+ */
+ if (mhdp->info)
+ bridge_state->input_bus_cfg.flags = *mhdp->info->input_bus_flags;
+
mutex_unlock(&mhdp->link_mutex);
return 0;
}
@@ -2184,23 +2228,6 @@ static struct edid *cdns_mhdp_bridge_get_edid(struct drm_bridge *bridge,
return cdns_mhdp_get_edid(mhdp, connector);
}
-static void cdns_mhdp_bridge_hpd_enable(struct drm_bridge *bridge)
-{
- struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
-
- /* Enable SW event interrupts */
- if (mhdp->bridge_attached)
- writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT,
- mhdp->regs + CDNS_APB_INT_MASK);
-}
-
-static void cdns_mhdp_bridge_hpd_disable(struct drm_bridge *bridge)
-{
- struct cdns_mhdp_device *mhdp = bridge_to_mhdp(bridge);
-
- writel(CDNS_APB_INT_MASK_SW_EVENT_INT, mhdp->regs + CDNS_APB_INT_MASK);
-}
-
static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
.atomic_enable = cdns_mhdp_atomic_enable,
.atomic_disable = cdns_mhdp_atomic_disable,
@@ -2210,6 +2237,7 @@ static const struct drm_bridge_funcs cdns_mhdp_bridge_funcs = {
.atomic_duplicate_state = cdns_mhdp_bridge_atomic_duplicate_state,
.atomic_destroy_state = cdns_mhdp_bridge_atomic_destroy_state,
.atomic_reset = cdns_mhdp_bridge_atomic_reset,
+ .atomic_get_input_bus_fmts = cdns_mhdp_get_input_bus_fmts,
.detect = cdns_mhdp_bridge_detect,
.get_edid = cdns_mhdp_bridge_get_edid,
.hpd_enable = cdns_mhdp_bridge_hpd_enable,
@@ -2529,8 +2557,6 @@ static int cdns_mhdp_probe(struct platform_device *pdev)
mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
DRM_BRIDGE_OP_HPD;
mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
- if (mhdp->info)
- mhdp->bridge.timings = mhdp->info->timings;
ret = phy_init(mhdp->phy);
if (ret) {
@@ -2617,7 +2643,7 @@ static const struct of_device_id mhdp_ids[] = {
#ifdef CONFIG_DRM_CDNS_MHDP8546_J721E
{ .compatible = "ti,j721e-mhdp8546",
.data = &(const struct cdns_mhdp_platform_info) {
- .timings = &mhdp_ti_j721e_bridge_timings,
+ .input_bus_flags = &mhdp_ti_j721e_bridge_input_bus_flags,
.ops = &mhdp_ti_j721e_ops,
},
},
@@ -2629,7 +2655,7 @@ MODULE_DEVICE_TABLE(of, mhdp_ids);
static struct platform_driver mhdp_driver = {
.driver = {
.name = "cdns-mhdp8546",
- .of_match_table = of_match_ptr(mhdp_ids),
+ .of_match_table = mhdp_ids,
},
.probe = cdns_mhdp_probe,
.remove = cdns_mhdp_remove,
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
index bedddd510d17..bad2fc0c7306 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
@@ -336,7 +336,7 @@ struct cdns_mhdp_bridge_state {
};
struct cdns_mhdp_platform_info {
- const struct drm_bridge_timings *timings;
+ const u32 *input_bus_flags;
const struct mhdp_platform_ops *ops;
};
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c
index dfe1b59514f7..12d04be4e242 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.c
@@ -71,8 +71,7 @@ const struct mhdp_platform_ops mhdp_ti_j721e_ops = {
.disable = cdns_mhdp_j721e_disable,
};
-const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings = {
- .input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
- DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE |
- DRM_BUS_FLAG_DE_HIGH,
-};
+const u32
+mhdp_ti_j721e_bridge_input_bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE |
+ DRM_BUS_FLAG_DE_HIGH;
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h
index 97d20d115a24..5ddca07a4255 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-j721e.h
@@ -14,6 +14,6 @@
struct mhdp_platform_ops;
extern const struct mhdp_platform_ops mhdp_ti_j721e_ops;
-extern const struct drm_bridge_timings mhdp_ti_j721e_bridge_timings;
+extern const u32 mhdp_ti_j721e_bridge_input_bus_flags;
#endif /* !CDNS_MHDP8546_J721E_H */
diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c
index 0e37840cd7a8..d205e755e524 100644
--- a/drivers/gpu/drm/bridge/chipone-icn6211.c
+++ b/drivers/gpu/drm/bridge/chipone-icn6211.c
@@ -17,7 +17,7 @@
#include <linux/i2c.h>
#include <linux/media-bus-format.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -795,7 +795,7 @@ static struct i2c_device_id chipone_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, chipone_i2c_id);
static struct i2c_driver chipone_i2c_driver = {
- .probe_new = chipone_i2c_probe,
+ .probe = chipone_i2c_probe,
.id_table = chipone_i2c_id,
.driver = {
.name = "chipone-icn6211-i2c",
diff --git a/drivers/gpu/drm/bridge/chrontel-ch7033.c b/drivers/gpu/drm/bridge/chrontel-ch7033.c
index 339b759e4c81..483c28c7fc99 100644
--- a/drivers/gpu/drm/bridge/chrontel-ch7033.c
+++ b/drivers/gpu/drm/bridge/chrontel-ch7033.c
@@ -603,11 +603,11 @@ static const struct i2c_device_id ch7033_ids[] = {
MODULE_DEVICE_TABLE(i2c, ch7033_ids);
static struct i2c_driver ch7033_driver = {
- .probe_new = ch7033_probe,
+ .probe = ch7033_probe,
.remove = ch7033_remove,
.driver = {
.name = "ch7033",
- .of_match_table = of_match_ptr(ch7033_dt_ids),
+ .of_match_table = ch7033_dt_ids,
},
.id_table = ch7033_ids,
};
diff --git a/drivers/gpu/drm/bridge/cros-ec-anx7688.c b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
index fa91bdeddef0..c8abd9920fee 100644
--- a/drivers/gpu/drm/bridge/cros-ec-anx7688.c
+++ b/drivers/gpu/drm/bridge/cros-ec-anx7688.c
@@ -173,7 +173,7 @@ static const struct of_device_id cros_ec_anx7688_bridge_match_table[] = {
MODULE_DEVICE_TABLE(of, cros_ec_anx7688_bridge_match_table);
static struct i2c_driver cros_ec_anx7688_bridge_driver = {
- .probe_new = cros_ec_anx7688_bridge_probe,
+ .probe = cros_ec_anx7688_bridge_probe,
.remove = cros_ec_anx7688_bridge_remove,
.driver = {
.name = "cros-ec-anx7688-bridge",
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index 56ae511367b1..08bd5695ddae 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
@@ -24,7 +23,7 @@ struct display_connector {
struct gpio_desc *hpd_gpio;
int hpd_irq;
- struct regulator *dp_pwr;
+ struct regulator *supply;
struct gpio_desc *ddc_en;
};
@@ -191,6 +190,18 @@ static irqreturn_t display_connector_hpd_irq(int irq, void *arg)
return IRQ_HANDLED;
}
+static int display_connector_get_supply(struct platform_device *pdev,
+ struct display_connector *conn,
+ const char *name)
+{
+ conn->supply = devm_regulator_get_optional(&pdev->dev, name);
+
+ if (conn->supply == ERR_PTR(-ENODEV))
+ conn->supply = NULL;
+
+ return PTR_ERR_OR_ZERO(conn->supply);
+}
+
static int display_connector_probe(struct platform_device *pdev)
{
struct display_connector *conn;
@@ -316,36 +327,15 @@ static int display_connector_probe(struct platform_device *pdev)
if (type == DRM_MODE_CONNECTOR_DisplayPort) {
int ret;
- conn->dp_pwr = devm_regulator_get_optional(&pdev->dev, "dp-pwr");
-
- if (IS_ERR(conn->dp_pwr)) {
- ret = PTR_ERR(conn->dp_pwr);
-
- switch (ret) {
- case -ENODEV:
- conn->dp_pwr = NULL;
- break;
-
- case -EPROBE_DEFER:
- return -EPROBE_DEFER;
-
- default:
- dev_err(&pdev->dev, "failed to get DP PWR regulator: %d\n", ret);
- return ret;
- }
- }
-
- if (conn->dp_pwr) {
- ret = regulator_enable(conn->dp_pwr);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable DP PWR regulator: %d\n", ret);
- return ret;
- }
- }
+ ret = display_connector_get_supply(pdev, conn, "dp-pwr");
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "failed to get DP PWR regulator\n");
}
/* enable DDC */
if (type == DRM_MODE_CONNECTOR_HDMIA) {
+ int ret;
+
conn->ddc_en = devm_gpiod_get_optional(&pdev->dev, "ddc-en",
GPIOD_OUT_HIGH);
@@ -353,6 +343,18 @@ static int display_connector_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Couldn't get ddc-en gpio\n");
return PTR_ERR(conn->ddc_en);
}
+
+ ret = display_connector_get_supply(pdev, conn, "hdmi-pwr");
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret, "failed to get HDMI +5V Power regulator\n");
+ }
+
+ if (conn->supply) {
+ ret = regulator_enable(conn->supply);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable PWR regulator: %d\n", ret);
+ return ret;
+ }
}
conn->bridge.funcs = &display_connector_bridge_funcs;
@@ -386,8 +388,8 @@ static void display_connector_remove(struct platform_device *pdev)
if (conn->ddc_en)
gpiod_set_value(conn->ddc_en, 0);
- if (conn->dp_pwr)
- regulator_disable(conn->dp_pwr);
+ if (conn->supply)
+ regulator_disable(conn->supply);
drm_bridge_remove(&conn->bridge);
diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
index 682623369498..0e4bac7dd04f 100644
--- a/drivers/gpu/drm/bridge/fsl-ldb.c
+++ b/drivers/gpu/drm/bridge/fsl-ldb.c
@@ -8,7 +8,6 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -56,6 +55,7 @@
#define LVDS_CTRL_VBG_ADJ_MASK GENMASK(19, 17)
enum fsl_ldb_devtype {
+ IMX6SX_LDB,
IMX8MP_LDB,
IMX93_LDB,
};
@@ -64,9 +64,14 @@ struct fsl_ldb_devdata {
u32 ldb_ctrl;
u32 lvds_ctrl;
bool lvds_en_bit;
+ bool single_ctrl_reg;
};
static const struct fsl_ldb_devdata fsl_ldb_devdata[] = {
+ [IMX6SX_LDB] = {
+ .ldb_ctrl = 0x18,
+ .single_ctrl_reg = true,
+ },
[IMX8MP_LDB] = {
.ldb_ctrl = 0x5c,
.lvds_ctrl = 0x128,
@@ -201,6 +206,9 @@ static void fsl_ldb_atomic_enable(struct drm_bridge *bridge,
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, reg);
+ if (fsl_ldb->devdata->single_ctrl_reg)
+ return;
+
/* Program LVDS_CTRL */
reg = LVDS_CTRL_CC_ADJ(2) | LVDS_CTRL_PRE_EMPH_EN |
LVDS_CTRL_PRE_EMPH_ADJ(3) | LVDS_CTRL_VBG_EN;
@@ -226,7 +234,8 @@ static void fsl_ldb_atomic_disable(struct drm_bridge *bridge,
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl,
LVDS_CTRL_LVDS_EN);
else
- regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0);
+ if (!fsl_ldb->devdata->single_ctrl_reg)
+ regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->lvds_ctrl, 0);
regmap_write(fsl_ldb->regmap, fsl_ldb->devdata->ldb_ctrl, 0);
clk_disable_unprepare(fsl_ldb->clk);
@@ -372,6 +381,8 @@ static void fsl_ldb_remove(struct platform_device *pdev)
}
static const struct of_device_id fsl_ldb_match[] = {
+ { .compatible = "fsl,imx6sx-ldb",
+ .data = &fsl_ldb_devdata[IMX6SX_LDB], },
{ .compatible = "fsl,imx8mp-ldb",
.data = &fsl_ldb_devdata[IMX8MP_LDB], },
{ .compatible = "fsl,imx93-ldb",
diff --git a/drivers/gpu/drm/bridge/imx/Kconfig b/drivers/gpu/drm/bridge/imx/Kconfig
index 608f47f41bcd..9fae28db6aa7 100644
--- a/drivers/gpu/drm/bridge/imx/Kconfig
+++ b/drivers/gpu/drm/bridge/imx/Kconfig
@@ -1,9 +1,13 @@
if ARCH_MXC || COMPILE_TEST
+config DRM_IMX_LDB_HELPER
+ tristate
+
config DRM_IMX8QM_LDB
tristate "Freescale i.MX8QM LVDS display bridge"
depends on OF
depends on COMMON_CLK
+ select DRM_IMX_LDB_HELPER
select DRM_KMS_HELPER
help
Choose this to enable the internal LVDS Display Bridge(LDB) found in
@@ -13,6 +17,7 @@ config DRM_IMX8QXP_LDB
tristate "Freescale i.MX8QXP LVDS display bridge"
depends on OF
depends on COMMON_CLK
+ select DRM_IMX_LDB_HELPER
select DRM_KMS_HELPER
help
Choose this to enable the internal LVDS Display Bridge(LDB) found in
diff --git a/drivers/gpu/drm/bridge/imx/Makefile b/drivers/gpu/drm/bridge/imx/Makefile
index aa90ec8d5433..8e2ebf3399a1 100644
--- a/drivers/gpu/drm/bridge/imx/Makefile
+++ b/drivers/gpu/drm/bridge/imx/Makefile
@@ -1,9 +1,6 @@
-imx8qm-ldb-objs := imx-ldb-helper.o imx8qm-ldb-drv.o
+obj-$(CONFIG_DRM_IMX_LDB_HELPER) += imx-ldb-helper.o
obj-$(CONFIG_DRM_IMX8QM_LDB) += imx8qm-ldb.o
-
-imx8qxp-ldb-objs := imx-ldb-helper.o imx8qxp-ldb-drv.o
obj-$(CONFIG_DRM_IMX8QXP_LDB) += imx8qxp-ldb.o
-
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_COMBINER) += imx8qxp-pixel-combiner.o
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK) += imx8qxp-pixel-link.o
obj-$(CONFIG_DRM_IMX8QXP_PIXEL_LINK_TO_DPI) += imx8qxp-pxl2dpi.o
diff --git a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
index 7338b84bc83d..6967325cd8ee 100644
--- a/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
+++ b/drivers/gpu/drm/bridge/imx/imx-ldb-helper.c
@@ -4,8 +4,10 @@
* Copyright 2019,2020,2022 NXP
*/
+#include <linux/export.h>
#include <linux/media-bus-format.h>
#include <linux/mfd/syscon.h>
+#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
@@ -19,12 +21,14 @@ bool ldb_channel_is_single_link(struct ldb_channel *ldb_ch)
{
return ldb_ch->link_type == LDB_CH_SINGLE_LINK;
}
+EXPORT_SYMBOL_GPL(ldb_channel_is_single_link);
bool ldb_channel_is_split_link(struct ldb_channel *ldb_ch)
{
return ldb_ch->link_type == LDB_CH_DUAL_LINK_EVEN_ODD_PIXELS ||
ldb_ch->link_type == LDB_CH_DUAL_LINK_ODD_EVEN_PIXELS;
}
+EXPORT_SYMBOL_GPL(ldb_channel_is_split_link);
int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
@@ -38,6 +42,7 @@ int ldb_bridge_atomic_check_helper(struct drm_bridge *bridge,
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_bridge_atomic_check_helper);
void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
@@ -69,6 +74,7 @@ void ldb_bridge_mode_set_helper(struct drm_bridge *bridge,
break;
}
}
+EXPORT_SYMBOL_GPL(ldb_bridge_mode_set_helper);
void ldb_bridge_enable_helper(struct drm_bridge *bridge)
{
@@ -81,6 +87,7 @@ void ldb_bridge_enable_helper(struct drm_bridge *bridge)
*/
regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_enable_helper);
void ldb_bridge_disable_helper(struct drm_bridge *bridge)
{
@@ -95,6 +102,7 @@ void ldb_bridge_disable_helper(struct drm_bridge *bridge)
regmap_write(ldb->regmap, ldb->ctrl_reg, ldb->ldb_ctrl);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_disable_helper);
int ldb_bridge_attach_helper(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
@@ -117,6 +125,7 @@ int ldb_bridge_attach_helper(struct drm_bridge *bridge,
ldb_ch->next_bridge, bridge,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
}
+EXPORT_SYMBOL_GPL(ldb_bridge_attach_helper);
int ldb_init_helper(struct ldb *ldb)
{
@@ -157,6 +166,7 @@ int ldb_init_helper(struct ldb *ldb)
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_init_helper);
int ldb_find_next_bridge_helper(struct ldb *ldb)
{
@@ -184,6 +194,7 @@ int ldb_find_next_bridge_helper(struct ldb *ldb)
return 0;
}
+EXPORT_SYMBOL_GPL(ldb_find_next_bridge_helper);
void ldb_add_bridge_helper(struct ldb *ldb,
const struct drm_bridge_funcs *bridge_funcs)
@@ -204,6 +215,7 @@ void ldb_add_bridge_helper(struct ldb *ldb,
drm_bridge_add(&ldb_ch->bridge);
}
}
+EXPORT_SYMBOL_GPL(ldb_add_bridge_helper);
void ldb_remove_bridge_helper(struct ldb *ldb)
{
@@ -219,3 +231,8 @@ void ldb_remove_bridge_helper(struct ldb *ldb)
drm_bridge_remove(&ldb_ch->bridge);
}
}
+EXPORT_SYMBOL_GPL(ldb_remove_bridge_helper);
+
+MODULE_DESCRIPTION("i.MX8 LVDS Display Bridge(LDB)/Pixel Mapper bridge helper");
+MODULE_AUTHOR("Liu Ying <[email protected]>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
index 386032a02599..21471a9a28b2 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qm-ldb-drv.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
@@ -9,9 +9,9 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
index c806576b1e22..7984da9c0a35 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb-drv.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
@@ -12,6 +12,7 @@
#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index abaf6e23775e..2f300f5ca051 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -404,7 +404,7 @@ struct debugfs_entries {
struct it6505 {
struct drm_dp_aux aux;
struct drm_bridge bridge;
- struct i2c_client *client;
+ struct device *dev;
struct it6505_drm_dp_link link;
struct it6505_platform_data pdata;
/*
@@ -524,7 +524,7 @@ static int it6505_read(struct it6505 *it6505, unsigned int reg_addr)
{
unsigned int value;
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (!it6505->powered)
return -ENODEV;
@@ -542,7 +542,7 @@ static int it6505_write(struct it6505 *it6505, unsigned int reg_addr,
unsigned int reg_val)
{
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (!it6505->powered)
return -ENODEV;
@@ -562,7 +562,7 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
unsigned int mask, unsigned int value)
{
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (!it6505->powered)
return -ENODEV;
@@ -580,7 +580,7 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
static void it6505_debug_print(struct it6505 *it6505, unsigned int reg,
const char *prefix)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int val;
if (!drm_debug_enabled(DRM_UT_DRIVER))
@@ -599,7 +599,7 @@ static int it6505_dpcd_read(struct it6505 *it6505, unsigned long offset)
{
u8 value;
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
ret = drm_dp_dpcd_readb(&it6505->aux, offset, &value);
if (ret < 0) {
@@ -613,7 +613,7 @@ static int it6505_dpcd_write(struct it6505 *it6505, unsigned long offset,
u8 datain)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
ret = drm_dp_dpcd_writeb(&it6505->aux, offset, datain);
if (ret < 0) {
@@ -626,7 +626,7 @@ static int it6505_dpcd_write(struct it6505 *it6505, unsigned long offset,
static int it6505_get_dpcd(struct it6505 *it6505, int offset, u8 *dpcd, int num)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
ret = drm_dp_dpcd_read(&it6505->aux, offset, dpcd, num);
@@ -643,7 +643,7 @@ static void it6505_dump(struct it6505 *it6505)
{
unsigned int i, j;
u8 regs[16];
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
for (i = 0; i <= 0xff; i += 16) {
for (j = 0; j < 16; j++)
@@ -682,7 +682,7 @@ static int it6505_read_word(struct it6505 *it6505, unsigned int reg)
static void it6505_calc_video_info(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int hsync_pol, vsync_pol, interlaced;
int htotal, hdes, hdew, hfph, hsyncw;
int vtotal, vdes, vdew, vfph, vsyncw;
@@ -926,7 +926,7 @@ static int it6505_aux_wait(struct it6505 *it6505)
{
int status;
unsigned long timeout;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
timeout = jiffies + msecs_to_jiffies(AUX_WAIT_TIMEOUT_MS) + 1;
@@ -1141,7 +1141,7 @@ static int it6505_get_edid_block(void *data, u8 *buf, unsigned int block,
size_t len)
{
struct it6505 *it6505 = data;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
enum aux_cmd_reply reply;
int offset, ret, aux_retry = 100;
@@ -1201,7 +1201,7 @@ static int it6505_send_video_infoframe(struct it6505 *it6505,
{
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
err = hdmi_avi_infoframe_pack(frame, buffer, sizeof(buffer));
if (err < 0) {
@@ -1231,7 +1231,7 @@ static void it6505_get_extcon_property(struct it6505 *it6505)
{
int err;
union extcon_property_value property;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (it6505->extcon && !it6505->lane_swap_disabled) {
err = extcon_get_property(it6505->extcon, EXTCON_DISP_DP,
@@ -1382,7 +1382,7 @@ static void it6505_enable_audio_source(struct it6505 *it6505)
static void it6505_enable_audio_infoframe(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 audio_info_ca[] = { 0x00, 0x00, 0x01, 0x03, 0x07, 0x0B, 0x0F, 0x1F };
DRM_DEV_DEBUG_DRIVER(dev, "infoframe channel_allocation:0x%02x",
@@ -1411,7 +1411,7 @@ static void it6505_disable_audio(struct it6505 *it6505)
static void it6505_enable_audio(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int regbe;
DRM_DEV_DEBUG_DRIVER(dev, "start");
@@ -1446,7 +1446,7 @@ static bool it6505_use_step_train_check(struct it6505 *it6505)
static void it6505_parse_link_capabilities(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_drm_dp_link *link = &it6505->link;
int bcaps;
@@ -1557,7 +1557,7 @@ static void it6505_lane_count_setup(struct it6505 *it6505)
static void it6505_link_training_setup(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (it6505->enable_enhanced_frame)
it6505_set_bits(it6505, REG_DATA_MUTE_CTRL,
@@ -1708,7 +1708,7 @@ it6505_step_cr_train(struct it6505 *it6505,
FORCE_CR_DONE);
return true;
}
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "cr not done");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "cr not done");
if (it6505_check_max_voltage_swing_reached(lane_level_config,
it6505->lane_count))
@@ -1785,7 +1785,7 @@ it6505_step_eq_train(struct it6505 *it6505,
FORCE_EQ_DONE);
return true;
}
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "eq not done");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "eq not done");
for (i = 0; i < it6505->lane_count; i++) {
lane_voltage_pre_emphasis->voltage_swing[i] =
@@ -1820,7 +1820,7 @@ static bool it6505_link_start_step_train(struct it6505 *it6505)
.pre_emphasis = { 0 },
};
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "start");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "start");
err = it6505_drm_dp_link_configure(it6505);
if (err < 0)
@@ -1854,7 +1854,7 @@ static void it6505_reset_hdcp(struct it6505 *it6505)
static void it6505_start_hdcp(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "start");
it6505_reset_hdcp(it6505);
@@ -1882,7 +1882,7 @@ static bool it6505_hdcp_is_ksv_valid(u8 *ksv)
static void it6505_hdcp_part1_auth(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 hdcp_bcaps;
it6505_set_bits(it6505, REG_RESET_CTRL, HDCP_RESET, 0x00);
@@ -1923,7 +1923,7 @@ static int it6505_sha1_digest(struct it6505 *it6505, u8 *sha1_input,
struct shash_desc *desc;
struct crypto_shash *tfm;
int err;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
tfm = crypto_alloc_shash("sha1", 0, 0);
if (IS_ERR(tfm)) {
@@ -1948,7 +1948,7 @@ static int it6505_sha1_digest(struct it6505 *it6505, u8 *sha1_input,
static int it6505_setup_sha1_input(struct it6505 *it6505, u8 *sha1_input)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 binfo[2];
int down_stream_count, i, err, msg_count = 0;
@@ -2012,7 +2012,7 @@ static int it6505_setup_sha1_input(struct it6505 *it6505, u8 *sha1_input)
static bool it6505_hdcp_part2_ksvlist_check(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
u8 av[5][4], bv[5][4];
int i, err;
@@ -2045,7 +2045,7 @@ static void it6505_hdcp_wait_ksv_list(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505,
hdcp_wait_ksv_list);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
unsigned int timeout = 5000;
u8 bstatus = 0;
bool ksv_list_check;
@@ -2087,7 +2087,7 @@ static void it6505_hdcp_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505,
hdcp_work.work);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;
u8 link_status[DP_LINK_STATUS_SIZE] = { 0 };
@@ -2128,7 +2128,7 @@ static void it6505_hdcp_work(struct work_struct *work)
static void it6505_show_hdcp_info(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int i;
u8 *sha1 = it6505->sha1_input;
@@ -2162,7 +2162,7 @@ static void it6505_stop_link_train(struct it6505 *it6505)
static void it6505_link_train_ok(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
it6505->link_state = LINK_OK;
/* disalbe mute enable avi info frame */
@@ -2181,7 +2181,7 @@ static void it6505_link_train_ok(struct it6505 *it6505)
static void it6505_link_step_train_process(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret, i, step_retry = 3;
DRM_DEV_DEBUG_DRIVER(dev, "Start step train");
@@ -2219,7 +2219,7 @@ static void it6505_link_step_train_process(struct it6505 *it6505)
static void it6505_link_training_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505, link_works);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;
DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
@@ -2267,7 +2267,7 @@ static void it6505_remove_edid(struct it6505 *it6505)
static int it6505_process_hpd_irq(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret, dpcd_sink_count, dp_irq_vector, bstatus;
u8 link_status[DP_LINK_STATUS_SIZE];
@@ -2331,7 +2331,7 @@ static int it6505_process_hpd_irq(struct it6505 *it6505)
static void it6505_irq_hpd(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int dp_sink_count;
it6505->hpd_state = it6505_get_sink_hpd_status(it6505);
@@ -2393,7 +2393,7 @@ static void it6505_irq_hpd(struct it6505 *it6505)
static void it6505_irq_hpd_irq(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "hpd_irq interrupt");
@@ -2403,7 +2403,7 @@ static void it6505_irq_hpd_irq(struct it6505 *it6505)
static void it6505_irq_scdt(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
bool data;
data = it6505_get_video_status(it6505);
@@ -2418,7 +2418,7 @@ static void it6505_irq_scdt(struct it6505 *it6505)
static void it6505_irq_hdcp_done(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "hdcp done interrupt");
it6505->hdcp_status = HDCP_AUTH_DONE;
@@ -2427,7 +2427,7 @@ static void it6505_irq_hdcp_done(struct it6505 *it6505)
static void it6505_irq_hdcp_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "hdcp fail interrupt");
it6505->hdcp_status = HDCP_AUTH_IDLE;
@@ -2437,14 +2437,14 @@ static void it6505_irq_hdcp_fail(struct it6505 *it6505)
static void it6505_irq_aux_cmd_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "AUX PC Request Fail Interrupt");
}
static void it6505_irq_hdcp_ksv_check(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "HDCP event Interrupt");
schedule_work(&it6505->hdcp_wait_ksv_list);
@@ -2452,7 +2452,7 @@ static void it6505_irq_hdcp_ksv_check(struct it6505 *it6505)
static void it6505_irq_audio_fifo_error(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "audio fifo error Interrupt");
@@ -2462,7 +2462,7 @@ static void it6505_irq_audio_fifo_error(struct it6505 *it6505)
static void it6505_irq_link_train_fail(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "link training fail interrupt");
schedule_work(&it6505->link_works);
@@ -2470,7 +2470,7 @@ static void it6505_irq_link_train_fail(struct it6505 *it6505)
static void it6505_irq_video_fifo_error(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "video fifo overflow interrupt");
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
@@ -2481,7 +2481,7 @@ static void it6505_irq_video_fifo_error(struct it6505 *it6505)
static void it6505_irq_io_latch_fifo_overflow(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "IO latch fifo overflow interrupt");
it6505->auto_train_retry = AUTO_TRAIN_RETRY;
@@ -2498,7 +2498,7 @@ static bool it6505_test_bit(unsigned int bit, const unsigned int *addr)
static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
{
struct it6505 *it6505 = data;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
static const struct {
int bit;
void (*handler)(struct it6505 *it6505);
@@ -2517,9 +2517,11 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
};
int int_status[3], i;
- if (it6505->enable_drv_hold || pm_runtime_get_if_in_use(dev) <= 0)
+ if (it6505->enable_drv_hold || !it6505->powered)
return IRQ_HANDLED;
+ pm_runtime_get_sync(dev);
+
int_status[0] = it6505_read(it6505, INT_STATUS_01);
int_status[1] = it6505_read(it6505, INT_STATUS_02);
int_status[2] = it6505_read(it6505, INT_STATUS_03);
@@ -2550,7 +2552,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
static int it6505_poweron(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_platform_data *pdata = &it6505->pdata;
int err;
@@ -2599,7 +2601,7 @@ static int it6505_poweron(struct it6505 *it6505)
static int it6505_poweroff(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct it6505_platform_data *pdata = &it6505->pdata;
int err;
@@ -2633,7 +2635,7 @@ static int it6505_poweroff(struct it6505 *it6505)
static enum drm_connector_status it6505_detect(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
enum drm_connector_status status = connector_status_disconnected;
int dp_sink_count;
@@ -2694,7 +2696,7 @@ static int it6505_extcon_notifier(struct notifier_block *self,
static void it6505_extcon_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int state, ret;
if (it6505->enable_drv_hold)
@@ -2739,11 +2741,11 @@ unlock:
static int it6505_use_notifier_module(struct it6505 *it6505)
{
int ret;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
it6505->event_nb.notifier_call = it6505_extcon_notifier;
INIT_WORK(&it6505->extcon_wq, it6505_extcon_work);
- ret = devm_extcon_register_notifier(&it6505->client->dev,
+ ret = devm_extcon_register_notifier(it6505->dev,
it6505->extcon, EXTCON_DISP_DP,
&it6505->event_nb);
if (ret) {
@@ -2759,7 +2761,7 @@ static int it6505_use_notifier_module(struct it6505 *it6505)
static void it6505_remove_notifier_module(struct it6505 *it6505)
{
if (it6505->extcon) {
- devm_extcon_unregister_notifier(&it6505->client->dev,
+ devm_extcon_unregister_notifier(it6505->dev,
it6505->extcon, EXTCON_DISP_DP,
&it6505->event_nb);
@@ -2772,7 +2774,7 @@ static void __maybe_unused it6505_delayed_audio(struct work_struct *work)
struct it6505 *it6505 = container_of(work, struct it6505,
delayed_audio.work);
- DRM_DEV_DEBUG_DRIVER(&it6505->client->dev, "start");
+ DRM_DEV_DEBUG_DRIVER(it6505->dev, "start");
if (!it6505->powered)
return;
@@ -2785,7 +2787,7 @@ static int __maybe_unused it6505_audio_setup_hw_params(struct it6505 *it6505,
struct hdmi_codec_params
*params)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int i = 0;
DRM_DEV_DEBUG_DRIVER(dev, "%s %d Hz, %d bit, %d channels\n", __func__,
@@ -2869,7 +2871,7 @@ static int it6505_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
int ret;
if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) {
@@ -2933,7 +2935,7 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct drm_atomic_state *state = old_state->base.state;
struct hdmi_avi_infoframe frame;
struct drm_crtc_state *crtc_state;
@@ -2989,7 +2991,7 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "start");
@@ -3004,7 +3006,7 @@ static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "start");
@@ -3015,7 +3017,7 @@ static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_state)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
DRM_DEV_DEBUG_DRIVER(dev, "start");
@@ -3034,7 +3036,7 @@ static struct edid *it6505_bridge_get_edid(struct drm_bridge *bridge,
struct drm_connector *connector)
{
struct it6505 *it6505 = bridge_to_it6505(bridge);
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
if (!it6505->cached_edid) {
it6505->cached_edid = drm_do_get_edid(connector, it6505_get_edid_block,
@@ -3086,7 +3088,7 @@ static const struct dev_pm_ops it6505_bridge_pm_ops = {
static int it6505_init_pdata(struct it6505 *it6505)
{
struct it6505_platform_data *pdata = &it6505->pdata;
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
/* 1.0V digital core power regulator */
pdata->pwr18 = devm_regulator_get(dev, "pwr18");
@@ -3128,7 +3130,7 @@ static int it6505_get_data_lanes_count(const struct device_node *endpoint,
static void it6505_parse_dt(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
struct device_node *np = dev->of_node, *ep = NULL;
int len;
u64 link_frequencies;
@@ -3207,7 +3209,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
struct it6505 *it6505 = file->private_data;
- struct drm_display_mode *vid = &it6505->video_info;
+ struct drm_display_mode *vid;
u8 read_buf[READ_BUFFER_SIZE];
u8 *str = read_buf, *end = read_buf + READ_BUFFER_SIZE;
ssize_t ret, count;
@@ -3216,6 +3218,7 @@ static ssize_t receive_timing_debugfs_show(struct file *file, char __user *buf,
return -ENODEV;
it6505_calc_video_info(it6505);
+ vid = &it6505->video_info;
str += scnprintf(str, end - str, "---video timing---\n");
str += scnprintf(str, end - str, "PCLK:%d.%03dMHz\n",
vid->clock / 1000, vid->clock % 1000);
@@ -3332,7 +3335,7 @@ static void debugfs_create_files(struct it6505 *it6505)
static void debugfs_init(struct it6505 *it6505)
{
- struct device *dev = &it6505->client->dev;
+ struct device *dev = it6505->dev;
it6505->debugfs = debugfs_create_dir(DEBUGFS_DIR_NAME, NULL);
@@ -3374,7 +3377,7 @@ static int it6505_i2c_probe(struct i2c_client *client)
it6505->bridge.of_node = client->dev.of_node;
it6505->connector_status = connector_status_disconnected;
- it6505->client = client;
+ it6505->dev = &client->dev;
i2c_set_clientdata(client, it6505);
/* get extcon device from DTS */
@@ -3478,7 +3481,7 @@ static struct i2c_driver it6505_i2c_driver = {
.of_match_table = it6505_of_match,
.pm = &it6505_bridge_pm_ops,
},
- .probe_new = it6505_i2c_probe,
+ .probe = it6505_i2c_probe,
.remove = it6505_i2c_remove,
.shutdown = it6505_shutdown,
.id_table = it6505_id,
diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c
index a2d723d6a4be..466641c77fe9 100644
--- a/drivers/gpu/drm/bridge/ite-it66121.c
+++ b/drivers/gpu/drm/bridge/ite-it66121.c
@@ -1640,7 +1640,7 @@ static struct i2c_driver it66121_driver = {
.name = "it66121",
.of_match_table = it66121_dt_match,
},
- .probe_new = it66121_probe,
+ .probe = it66121_probe,
.remove = it66121_remove,
.id_table = it66121_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
index 13c131ade268..4eaea67fb71c 100644
--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
+++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
@@ -773,7 +773,7 @@ static struct i2c_driver lt8912_i2c_driver = {
.name = "lt8912",
.of_match_table = lt8912_dt_match,
},
- .probe_new = lt8912_probe,
+ .probe = lt8912_probe,
.remove = lt8912_remove,
.id_table = lt8912_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9211.c b/drivers/gpu/drm/bridge/lontium-lt9211.c
index 3e19fff6547a..4d404f5ef87e 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9211.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9211.c
@@ -16,7 +16,6 @@
#include <linux/i2c.h>
#include <linux/media-bus-format.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -709,7 +708,9 @@ static int lt9211_host_attach(struct lt9211 *ctx)
dsi->lanes = dsi_lanes;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_VIDEO_HSE;
+ MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO_NO_HSA |
+ MIPI_DSI_MODE_VIDEO_NO_HFP | MIPI_DSI_MODE_VIDEO_NO_HBP |
+ MIPI_DSI_MODE_NO_EOT_PACKET;
ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) {
@@ -785,7 +786,7 @@ static const struct of_device_id lt9211_match_table[] = {
MODULE_DEVICE_TABLE(of, lt9211_match_table);
static struct i2c_driver lt9211_driver = {
- .probe_new = lt9211_probe,
+ .probe = lt9211_probe,
.remove = lt9211_remove,
.id_table = lt9211_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
index a25d21a7d5c1..9663601ce098 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
@@ -1190,7 +1190,7 @@ static struct i2c_driver lt9611_driver = {
.name = "lt9611",
.of_match_table = lt9611_match_table,
},
- .probe_new = lt9611_probe,
+ .probe = lt9611_probe,
.remove = lt9611_remove,
.id_table = lt9611_id,
};
diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
index 583daacf3705..22c84d29c2bc 100644
--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
@@ -28,6 +28,8 @@
#define EDID_BLOCK_SIZE 128
#define EDID_NUM_BLOCKS 2
+#define FW_FILE "lt9611uxc_fw.bin"
+
struct lt9611uxc {
struct device *dev;
struct drm_bridge bridge;
@@ -754,7 +756,7 @@ static int lt9611uxc_firmware_update(struct lt9611uxc *lt9611uxc)
REG_SEQ0(0x805a, 0x00),
};
- ret = request_firmware(&fw, "lt9611uxc_fw.bin", lt9611uxc->dev);
+ ret = request_firmware(&fw, FW_FILE, lt9611uxc->dev);
if (ret < 0)
return ret;
@@ -1011,7 +1013,7 @@ static struct i2c_driver lt9611uxc_driver = {
.of_match_table = lt9611uxc_match_table,
.dev_groups = lt9611uxc_attr_groups,
},
- .probe_new = lt9611uxc_probe,
+ .probe = lt9611uxc_probe,
.remove = lt9611uxc_remove,
.id_table = lt9611uxc_id,
};
@@ -1019,3 +1021,5 @@ module_i2c_driver(lt9611uxc_driver);
MODULE_AUTHOR("Dmitry Baryshkov <[email protected]>");
MODULE_LICENSE("GPL v2");
+
+MODULE_FIRMWARE(FW_FILE);
diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c
index 67368f23d4aa..8c5668dca0c4 100644
--- a/drivers/gpu/drm/bridge/lvds-codec.c
+++ b/drivers/gpu/drm/bridge/lvds-codec.c
@@ -7,7 +7,6 @@
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
index 4fc494d9084b..460db3c8a08c 100644
--- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
+++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match);
static struct i2c_driver stdp4028_ge_b850v3_fw_driver = {
.id_table = stdp4028_ge_b850v3_fw_i2c_table,
- .probe_new = stdp4028_ge_b850v3_fw_probe,
+ .probe = stdp4028_ge_b850v3_fw_probe,
.remove = stdp4028_ge_b850v3_fw_remove,
.driver = {
.name = "stdp4028-ge-b850v3-fw",
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match);
static struct i2c_driver stdp2690_ge_b850v3_fw_driver = {
.id_table = stdp2690_ge_b850v3_fw_i2c_table,
- .probe_new = stdp2690_ge_b850v3_fw_probe,
+ .probe = stdp2690_ge_b850v3_fw_probe,
.remove = stdp2690_ge_b850v3_fw_remove,
.driver = {
.name = "stdp2690-ge-b850v3-fw",
diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index 4a5f5c4f5dcc..8d54091ec66e 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -16,8 +16,8 @@
#include <linux/module.h>
#include <linux/mux/consumer.h>
#include <linux/of.h>
-#include <linux/of_platform.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/sys_soc.h>
diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c
index cd292a2f894c..d81920227a8a 100644
--- a/drivers/gpu/drm/bridge/nxp-ptn3460.c
+++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c
@@ -335,7 +335,7 @@ MODULE_DEVICE_TABLE(of, ptn3460_match);
static struct i2c_driver ptn3460_driver = {
.id_table = ptn3460_i2c_table,
- .probe_new = ptn3460_probe,
+ .probe = ptn3460_probe,
.remove = ptn3460_remove,
.driver = {
.name = "nxp,ptn3460",
diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c
index efa80e309b98..ae3ab9262ef1 100644
--- a/drivers/gpu/drm/bridge/parade-ps8622.c
+++ b/drivers/gpu/drm/bridge/parade-ps8622.c
@@ -12,7 +12,6 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/regulator/consumer.h>
@@ -538,7 +537,7 @@ MODULE_DEVICE_TABLE(i2c, ps8622_i2c_table);
static struct i2c_driver ps8622_driver = {
.id_table = ps8622_i2c_table,
- .probe_new = ps8622_probe,
+ .probe = ps8622_probe,
.remove = ps8622_remove,
.driver = {
.name = "ps8622",
diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
index c3eb45179405..8161b1a1a4b1 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -105,7 +105,6 @@ struct ps8640 {
struct gpio_desc *gpio_reset;
struct gpio_desc *gpio_powerdown;
struct device_link *link;
- struct edid *edid;
bool pre_enabled;
bool need_post_hpd_delay;
};
@@ -155,23 +154,6 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux)
return container_of(aux, struct ps8640, aux);
}
-static bool ps8640_of_panel_on_aux_bus(struct device *dev)
-{
- struct device_node *bus, *panel;
-
- bus = of_get_child_by_name(dev->of_node, "aux-bus");
- if (!bus)
- return false;
-
- panel = of_get_child_by_name(bus, "panel");
- of_node_put(bus);
- if (!panel)
- return false;
- of_node_put(panel);
-
- return true;
-}
-
static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long wait_us)
{
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
@@ -539,50 +521,6 @@ static void ps8640_bridge_detach(struct drm_bridge *bridge)
device_link_del(ps_bridge->link);
}
-static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,
- struct drm_connector *connector)
-{
- struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
- struct device *dev = &ps_bridge->page[PAGE0_DP_CNTL]->dev;
- bool poweroff = !ps_bridge->pre_enabled;
-
- if (!ps_bridge->edid) {
- /*
- * When we end calling get_edid() triggered by an ioctl, i.e
- *
- * drm_mode_getconnector (ioctl)
- * -> drm_helper_probe_single_connector_modes
- * -> drm_bridge_connector_get_modes
- * -> ps8640_bridge_get_edid
- *
- * We need to make sure that what we need is enabled before
- * reading EDID, for this chip, we need to do a full poweron,
- * otherwise it will fail.
- */
- if (poweroff)
- drm_atomic_bridge_chain_pre_enable(bridge,
- connector->state->state);
-
- ps_bridge->edid = drm_get_edid(connector,
- ps_bridge->page[PAGE0_DP_CNTL]->adapter);
-
- /*
- * If we call the get_edid() function without having enabled the
- * chip before, return the chip to its original power state.
- */
- if (poweroff)
- drm_atomic_bridge_chain_post_disable(bridge,
- connector->state->state);
- }
-
- if (!ps_bridge->edid) {
- dev_err(dev, "Failed to get EDID\n");
- return NULL;
- }
-
- return drm_edid_duplicate(ps_bridge->edid);
-}
-
static void ps8640_runtime_disable(void *data)
{
pm_runtime_dont_use_autosuspend(data);
@@ -592,7 +530,6 @@ static void ps8640_runtime_disable(void *data)
static const struct drm_bridge_funcs ps8640_bridge_funcs = {
.attach = ps8640_bridge_attach,
.detach = ps8640_bridge_detach,
- .get_edid = ps8640_bridge_get_edid,
.atomic_post_disable = ps8640_atomic_post_disable,
.atomic_pre_enable = ps8640_atomic_pre_enable,
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
@@ -706,14 +643,6 @@ static int ps8640_probe(struct i2c_client *client)
ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP;
/*
- * In the device tree, if panel is listed under aux-bus of the bridge
- * node, panel driver should be able to retrieve EDID by itself using
- * aux-bus. So let's not set DRM_BRIDGE_OP_EDID here.
- */
- if (!ps8640_of_panel_on_aux_bus(&client->dev))
- ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID;
-
- /*
* Get MIPI DSI resources early. These can return -EPROBE_DEFER so
* we want to get them out of the way sooner.
*/
@@ -777,13 +706,6 @@ static int ps8640_probe(struct i2c_client *client)
return ret;
}
-static void ps8640_remove(struct i2c_client *client)
-{
- struct ps8640 *ps_bridge = i2c_get_clientdata(client);
-
- kfree(ps_bridge->edid);
-}
-
static const struct of_device_id ps8640_match[] = {
{ .compatible = "parade,ps8640" },
{ }
@@ -791,8 +713,7 @@ static const struct of_device_id ps8640_match[] = {
MODULE_DEVICE_TABLE(of, ps8640_match);
static struct i2c_driver ps8640_driver = {
- .probe_new = ps8640_probe,
- .remove = ps8640_remove,
+ .probe = ps8640_probe,
.driver = {
.name = "ps8640",
.of_match_table = ps8640_match,
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index e0a402a85787..cf777bdb25d2 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -16,8 +16,9 @@
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/media-bus-format.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
#include <video/mipi_display.h>
@@ -183,6 +184,8 @@
#define DSIM_AFC_CTL(x) (((x) & 0x7) << 5)
/* DSIM_PLLCTRL */
+#define DSIM_PLL_DPDNSWAP_CLK (1 << 25)
+#define DSIM_PLL_DPDNSWAP_DAT (1 << 24)
#define DSIM_FREQ_BAND(x) ((x) << 24)
#define DSIM_PLL_EN BIT(23)
#define DSIM_PLL_P(x, offset) ((x) << (offset))
@@ -218,6 +221,8 @@
#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
+#define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL)
+
static const char *const clk_names[5] = {
"bus_clk",
"sclk_mipi",
@@ -405,6 +410,9 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
@@ -418,6 +426,9 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
@@ -429,6 +440,9 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
.num_bits_resol = 11,
.pll_p_offset = 13,
.reg_values = reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
@@ -441,6 +455,9 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5433_reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
@@ -453,6 +470,9 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
.num_bits_resol = 12,
.pll_p_offset = 13,
.reg_values = exynos5422_reg_values,
+ .m_min = 41,
+ .m_max = 125,
+ .min_freq = 500,
};
static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
@@ -469,6 +489,9 @@ static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
*/
.pll_p_offset = 14,
.reg_values = imx8mm_dsim_reg_values,
+ .m_min = 64,
+ .m_max = 1023,
+ .min_freq = 1050,
};
static const struct samsung_dsim_driver_data *
@@ -547,12 +570,12 @@ static unsigned long samsung_dsim_pll_find_pms(struct samsung_dsim *dsi,
tmp = (u64)fout * (_p << _s);
do_div(tmp, fin);
_m = tmp;
- if (_m < 41 || _m > 125)
+ if (_m < driver_data->m_min || _m > driver_data->m_max)
continue;
tmp = (u64)_m * fin;
do_div(tmp, _p);
- if (tmp < 500 * MHZ ||
+ if (tmp < driver_data->min_freq * MHZ ||
tmp > driver_data->max_freq * MHZ)
continue;
@@ -622,6 +645,11 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
reg |= DSIM_FREQ_BAND(band);
}
+ if (dsi->swap_dn_dp_clk)
+ reg |= DSIM_PLL_DPDNSWAP_CLK;
+ if (dsi->swap_dn_dp_data)
+ reg |= DSIM_PLL_DPDNSWAP_DAT;
+
samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
timeout = 1000;
@@ -633,16 +661,28 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
} while ((reg & DSIM_PLL_STABLE) == 0);
+ dsi->hs_clock = fout;
+
return fout;
}
static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
{
- unsigned long hs_clk, byte_clk, esc_clk;
+ unsigned long hs_clk, byte_clk, esc_clk, pix_clk;
unsigned long esc_div;
u32 reg;
+ struct drm_display_mode *m = &dsi->mode;
+ int bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+
+ /* m->clock is in KHz */
+ pix_clk = m->clock * 1000;
+
+ /* Use burst_clk_rate if available, otherwise use the pix_clk */
+ if (dsi->burst_clk_rate)
+ hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
+ else
+ hs_clk = samsung_dsim_set_pll(dsi, DIV_ROUND_UP(pix_clk * bpp, dsi->lanes));
- hs_clk = samsung_dsim_set_pll(dsi, dsi->burst_clk_rate);
if (!hs_clk) {
dev_err(dsi->dev, "failed to configure DSI PLL\n");
return -EFAULT;
@@ -680,13 +720,47 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
const unsigned int *reg_values = driver_data->reg_values;
u32 reg;
+ struct phy_configure_opts_mipi_dphy cfg;
+ int clk_prepare, lpx, clk_zero, clk_post, clk_trail;
+ int hs_exit, hs_prepare, hs_zero, hs_trail;
+ unsigned long long byte_clock = dsi->hs_clock / 8;
if (driver_data->has_freqband)
return;
+ phy_mipi_dphy_get_default_config_for_hsclk(dsi->hs_clock,
+ dsi->lanes, &cfg);
+
+ /*
+ * TODO:
+ * The tech Applications Processor manuals for i.MX8M Mini, Nano,
+ * and Plus don't state what the definition of the PHYTIMING
+ * bits are beyond their address and bit position.
+ * After reviewing NXP's downstream code, it appears
+ * that the various PHYTIMING registers take the number
+ * of cycles and use various dividers on them. This
+ * calculation does not result in an exact match to the
+ * downstream code, but it is very close to the values
+ * generated by their lookup table, and it appears
+ * to sync at a variety of resolutions. If someone
+ * can get a more accurate mathematical equation needed
+ * for these registers, this should be updated.
+ */
+
+ lpx = PS_TO_CYCLE(cfg.lpx, byte_clock);
+ hs_exit = PS_TO_CYCLE(cfg.hs_exit, byte_clock);
+ clk_prepare = PS_TO_CYCLE(cfg.clk_prepare, byte_clock);
+ clk_zero = PS_TO_CYCLE(cfg.clk_zero, byte_clock);
+ clk_post = PS_TO_CYCLE(cfg.clk_post, byte_clock);
+ clk_trail = PS_TO_CYCLE(cfg.clk_trail, byte_clock);
+ hs_prepare = PS_TO_CYCLE(cfg.hs_prepare, byte_clock);
+ hs_zero = PS_TO_CYCLE(cfg.hs_zero, byte_clock);
+ hs_trail = PS_TO_CYCLE(cfg.hs_trail, byte_clock);
+
/* B D-PHY: D-PHY Master & Slave Analog Block control */
reg = reg_values[PHYCTRL_ULPS_EXIT] | reg_values[PHYCTRL_VREG_LP] |
reg_values[PHYCTRL_SLEW_UP];
+
samsung_dsim_write(dsi, DSIM_PHYCTRL_REG, reg);
/*
@@ -694,7 +768,9 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T HS-EXIT: Time that the transmitter drives LP-11 following a HS
* burst
*/
- reg = reg_values[PHYTIMING_LPX] | reg_values[PHYTIMING_HS_EXIT];
+
+ reg = DSIM_PHYTIMING_LPX(lpx) | DSIM_PHYTIMING_HS_EXIT(hs_exit);
+
samsung_dsim_write(dsi, DSIM_PHYTIMING_REG, reg);
/*
@@ -710,10 +786,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
* the last payload clock bit of a HS transmission burst
*/
- reg = reg_values[PHYTIMING_CLK_PREPARE] |
- reg_values[PHYTIMING_CLK_ZERO] |
- reg_values[PHYTIMING_CLK_POST] |
- reg_values[PHYTIMING_CLK_TRAIL];
+
+ reg = DSIM_PHYTIMING1_CLK_PREPARE(clk_prepare) |
+ DSIM_PHYTIMING1_CLK_ZERO(clk_zero) |
+ DSIM_PHYTIMING1_CLK_POST(clk_post) |
+ DSIM_PHYTIMING1_CLK_TRAIL(clk_trail);
samsung_dsim_write(dsi, DSIM_PHYTIMING1_REG, reg);
@@ -726,8 +803,11 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
* T HS-TRAIL: Time that the transmitter drives the flipped differential
* state after last payload data bit of a HS transmission burst
*/
- reg = reg_values[PHYTIMING_HS_PREPARE] | reg_values[PHYTIMING_HS_ZERO] |
- reg_values[PHYTIMING_HS_TRAIL];
+
+ reg = DSIM_PHYTIMING2_HS_PREPARE(hs_prepare) |
+ DSIM_PHYTIMING2_HS_ZERO(hs_zero) |
+ DSIM_PHYTIMING2_HS_TRAIL(hs_trail);
+
samsung_dsim_write(dsi, DSIM_PHYTIMING2_REG, reg);
}
@@ -859,6 +939,10 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
reg &= ~DSIM_STOP_STATE_CNT_MASK;
reg |= DSIM_STOP_STATE_CNT(driver_data->reg_values[STOP_STATE_CNT]);
+
+ if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+ reg |= DSIM_FORCE_STOP_STATE;
+
samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
reg = DSIM_BTA_TIMEOUT(0xff) | DSIM_LPDR_TIMEOUT(0xffff);
@@ -874,17 +958,29 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
u32 reg;
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
+ int byte_clk_khz = dsi->hs_clock / 1000 / 8;
+ int hfp = (m->hsync_start - m->hdisplay) * byte_clk_khz / m->clock;
+ int hbp = (m->htotal - m->hsync_end) * byte_clk_khz / m->clock;
+ int hsa = (m->hsync_end - m->hsync_start) * byte_clk_khz / m->clock;
+
+ /* remove packet overhead when possible */
+ hfp = max(hfp - 6, 0);
+ hbp = max(hbp - 6, 0);
+ hsa = max(hsa - 6, 0);
+
+ dev_dbg(dsi->dev, "calculated hfp: %u, hbp: %u, hsa: %u",
+ hfp, hbp, hsa);
+
reg = DSIM_CMD_ALLOW(0xf)
| DSIM_STABLE_VFP(m->vsync_start - m->vdisplay)
| DSIM_MAIN_VBP(m->vtotal - m->vsync_end);
samsung_dsim_write(dsi, DSIM_MVPORCH_REG, reg);
- reg = DSIM_MAIN_HFP(m->hsync_start - m->hdisplay)
- | DSIM_MAIN_HBP(m->htotal - m->hsync_end);
+ reg = DSIM_MAIN_HFP(hfp) | DSIM_MAIN_HBP(hbp);
samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
- | DSIM_MAIN_HSA(m->hsync_end - m->hsync_start);
+ | DSIM_MAIN_HSA(hsa);
samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg);
}
reg = DSIM_MAIN_HRESOL(m->hdisplay, num_bits_resol) |
@@ -914,7 +1010,7 @@ static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi)
do {
u32 reg = samsung_dsim_read(dsi, DSIM_FIFOCTRL_REG);
- if (!(reg & DSIM_SFR_HEADER_FULL))
+ if (reg & DSIM_SFR_HEADER_EMPTY)
return 0;
if (!cond_resched())
@@ -1291,6 +1387,18 @@ static void samsung_dsim_disable_irq(struct samsung_dsim *dsi)
disable_irq(dsi->irq);
}
+static void samsung_dsim_set_stop_state(struct samsung_dsim *dsi, bool enable)
+{
+ u32 reg = samsung_dsim_read(dsi, DSIM_ESCMODE_REG);
+
+ if (enable)
+ reg |= DSIM_FORCE_STOP_STATE;
+ else
+ reg &= ~DSIM_FORCE_STOP_STATE;
+
+ samsung_dsim_write(dsi, DSIM_ESCMODE_REG, reg);
+}
+
static int samsung_dsim_init(struct samsung_dsim *dsi)
{
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
@@ -1340,6 +1448,9 @@ static void samsung_dsim_atomic_pre_enable(struct drm_bridge *bridge,
ret = samsung_dsim_init(dsi);
if (ret)
return;
+
+ samsung_dsim_set_display_mode(dsi);
+ samsung_dsim_set_display_enable(dsi, true);
}
}
@@ -1348,8 +1459,12 @@ static void samsung_dsim_atomic_enable(struct drm_bridge *bridge,
{
struct samsung_dsim *dsi = bridge_to_dsi(bridge);
- samsung_dsim_set_display_mode(dsi);
- samsung_dsim_set_display_enable(dsi, true);
+ if (samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type)) {
+ samsung_dsim_set_display_mode(dsi);
+ samsung_dsim_set_display_enable(dsi, true);
+ } else {
+ samsung_dsim_set_stop_state(dsi, false);
+ }
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1362,6 +1477,9 @@ static void samsung_dsim_atomic_disable(struct drm_bridge *bridge,
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
+ if (!samsung_dsim_hw_is_exynos(dsi->plat_data->hw_type))
+ samsung_dsim_set_stop_state(dsi, true);
+
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
}
@@ -1663,6 +1781,8 @@ static ssize_t samsung_dsim_host_transfer(struct mipi_dsi_host *host,
if (ret)
return ret;
+ samsung_dsim_set_stop_state(dsi, false);
+
ret = mipi_dsi_create_packet(&xfer.packet, msg);
if (ret < 0)
return ret;
@@ -1682,11 +1802,11 @@ static const struct mipi_dsi_host_ops samsung_dsim_ops = {
};
static int samsung_dsim_of_read_u32(const struct device_node *np,
- const char *propname, u32 *out_value)
+ const char *propname, u32 *out_value, bool optional)
{
int ret = of_property_read_u32(np, propname, out_value);
- if (ret < 0)
+ if (ret < 0 && !optional)
pr_err("%pOF: failed to get '%s' property\n", np, propname);
return ret;
@@ -1696,23 +1816,52 @@ static int samsung_dsim_parse_dt(struct samsung_dsim *dsi)
{
struct device *dev = dsi->dev;
struct device_node *node = dev->of_node;
- int ret;
+ u32 lane_polarities[5] = { 0 };
+ struct device_node *endpoint;
+ int i, nr_lanes, ret;
+ struct clk *pll_clk;
ret = samsung_dsim_of_read_u32(node, "samsung,pll-clock-frequency",
- &dsi->pll_clk_rate);
- if (ret < 0)
- return ret;
+ &dsi->pll_clk_rate, 1);
+ /* If it doesn't exist, read it from the clock instead of failing */
+ if (ret < 0) {
+ dev_dbg(dev, "Using sclk_mipi for pll clock frequency\n");
+ pll_clk = devm_clk_get(dev, "sclk_mipi");
+ if (!IS_ERR(pll_clk))
+ dsi->pll_clk_rate = clk_get_rate(pll_clk);
+ else
+ return PTR_ERR(pll_clk);
+ }
+ /* If it doesn't exist, use pixel clock instead of failing */
ret = samsung_dsim_of_read_u32(node, "samsung,burst-clock-frequency",
- &dsi->burst_clk_rate);
- if (ret < 0)
- return ret;
+ &dsi->burst_clk_rate, 1);
+ if (ret < 0) {
+ dev_dbg(dev, "Using pixel clock for HS clock frequency\n");
+ dsi->burst_clk_rate = 0;
+ }
ret = samsung_dsim_of_read_u32(node, "samsung,esc-clock-frequency",
- &dsi->esc_clk_rate);
+ &dsi->esc_clk_rate, 0);
if (ret < 0)
return ret;
+ endpoint = of_graph_get_endpoint_by_regs(node, 1, -1);
+ nr_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
+ if (nr_lanes > 0 && nr_lanes <= 4) {
+ /* Polarity 0 is clock lane, 1..4 are data lanes. */
+ of_property_read_u32_array(endpoint, "lane-polarities",
+ lane_polarities, nr_lanes + 1);
+ for (i = 1; i <= nr_lanes; i++) {
+ if (lane_polarities[1] != lane_polarities[i])
+ DRM_DEV_ERROR(dsi->dev, "Data lanes polarities do not match");
+ }
+ if (lane_polarities[0])
+ dsi->swap_dn_dp_clk = true;
+ if (lane_polarities[1])
+ dsi->swap_dn_dp_data = true;
+ }
+
return 0;
}
@@ -1954,7 +2103,6 @@ static struct platform_driver samsung_dsim_driver = {
.remove = samsung_dsim_remove,
.driver = {
.name = "samsung-dsim",
- .owner = THIS_MODULE,
.pm = &samsung_dsim_pm_ops,
.of_match_table = samsung_dsim_of_match,
},
diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
index ef66461e7f7c..2bdc5b439beb 100644
--- a/drivers/gpu/drm/bridge/sii902x.c
+++ b/drivers/gpu/drm/bridge/sii902x.c
@@ -473,6 +473,41 @@ static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge,
return sii902x_get_edid(sii902x, connector);
}
+static u32 *sii902x_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ input_fmts = kcalloc(1, sizeof(*input_fmts), GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+ *num_input_fmts = 1;
+
+ return input_fmts;
+}
+
+static int sii902x_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ /*
+ * There might be flags negotiation supported in future but
+ * set the bus flags in atomic_check statically for now.
+ */
+ bridge_state->input_bus_cfg.flags = bridge->timings->input_bus_flags;
+
+ return 0;
+}
+
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.attach = sii902x_bridge_attach,
.mode_set = sii902x_bridge_mode_set,
@@ -480,6 +515,11 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.enable = sii902x_bridge_enable,
.detect = sii902x_bridge_detect,
.get_edid = sii902x_bridge_get_edid,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts,
+ .atomic_check = sii902x_bridge_atomic_check,
};
static int sii902x_mute(struct sii902x *sii902x, bool mute)
@@ -1151,7 +1191,7 @@ static const struct i2c_device_id sii902x_i2c_ids[] = {
MODULE_DEVICE_TABLE(i2c, sii902x_i2c_ids);
static struct i2c_driver sii902x_driver = {
- .probe_new = sii902x_probe,
+ .probe = sii902x_probe,
.remove = sii902x_remove,
.driver = {
.name = "sii902x",
diff --git a/drivers/gpu/drm/bridge/sii9234.c b/drivers/gpu/drm/bridge/sii9234.c
index 2d17f227867b..d8373d918324 100644
--- a/drivers/gpu/drm/bridge/sii9234.c
+++ b/drivers/gpu/drm/bridge/sii9234.c
@@ -955,7 +955,7 @@ static struct i2c_driver sii9234_driver = {
.name = "sii9234",
.of_match_table = sii9234_dt_match,
},
- .probe_new = sii9234_probe,
+ .probe = sii9234_probe,
.remove = sii9234_remove,
.id_table = sii9234_id,
};
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index b96d03cd878d..599164e3877d 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -2376,9 +2376,9 @@ MODULE_DEVICE_TABLE(i2c, sii8620_id);
static struct i2c_driver sii8620_driver = {
.driver = {
.name = "sii8620",
- .of_match_table = of_match_ptr(sii8620_dt_match),
+ .of_match_table = sii8620_dt_match,
},
- .probe_new = sii8620_probe,
+ .probe = sii8620_probe,
.remove = sii8620_remove,
.id_table = sii8620_id,
};
diff --git a/drivers/gpu/drm/bridge/simple-bridge.c b/drivers/gpu/drm/bridge/simple-bridge.c
index d85d9ee463b8..cbe8e778d7c7 100644
--- a/drivers/gpu/drm/bridge/simple-bridge.c
+++ b/drivers/gpu/drm/bridge/simple-bridge.c
@@ -8,8 +8,9 @@
#include <linux/gpio/consumer.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
+#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <drm/drm_atomic_helper.h>
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index 9389ce526eb1..be21c11de1f2 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -62,6 +62,10 @@ struct dw_hdmi_cec {
bool rx_done;
struct cec_notifier *notify;
int irq;
+
+ u8 regs_polarity;
+ u8 regs_mask;
+ u8 regs_mute_stat0;
};
static void dw_hdmi_write(struct dw_hdmi_cec *cec, u8 val, int offset)
@@ -304,11 +308,44 @@ static void dw_hdmi_cec_remove(struct platform_device *pdev)
cec_unregister_adapter(cec->adap);
}
+static int __maybe_unused dw_hdmi_cec_resume(struct device *dev)
+{
+ struct dw_hdmi_cec *cec = dev_get_drvdata(dev);
+
+ /* Restore logical address */
+ dw_hdmi_write(cec, cec->addresses & 255, HDMI_CEC_ADDR_L);
+ dw_hdmi_write(cec, cec->addresses >> 8, HDMI_CEC_ADDR_H);
+
+ /* Restore interrupt status/mask registers */
+ dw_hdmi_write(cec, cec->regs_polarity, HDMI_CEC_POLARITY);
+ dw_hdmi_write(cec, cec->regs_mask, HDMI_CEC_MASK);
+ dw_hdmi_write(cec, cec->regs_mute_stat0, HDMI_IH_MUTE_CEC_STAT0);
+
+ return 0;
+}
+
+static int __maybe_unused dw_hdmi_cec_suspend(struct device *dev)
+{
+ struct dw_hdmi_cec *cec = dev_get_drvdata(dev);
+
+ /* store interrupt status/mask registers */
+ cec->regs_polarity = dw_hdmi_read(cec, HDMI_CEC_POLARITY);
+ cec->regs_mask = dw_hdmi_read(cec, HDMI_CEC_MASK);
+ cec->regs_mute_stat0 = dw_hdmi_read(cec, HDMI_IH_MUTE_CEC_STAT0);
+
+ return 0;
+}
+
+static const struct dev_pm_ops dw_hdmi_cec_pm = {
+ SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_cec_suspend, dw_hdmi_cec_resume)
+};
+
static struct platform_driver dw_hdmi_cec_driver = {
.probe = dw_hdmi_cec_probe,
.remove_new = dw_hdmi_cec_remove,
.driver = {
.name = "dw-hdmi-cec",
+ .pm = &dw_hdmi_cec_pm,
},
};
module_platform_driver(dw_hdmi_cec_driver);
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 603bb3c51027..6c1d79474505 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -14,7 +14,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/mutex.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regmap.h>
#include <linux/dma-mapping.h>
@@ -49,20 +49,6 @@
#define HDMI14_MAX_TMDSCLK 340000000
-enum hdmi_datamap {
- RGB444_8B = 0x01,
- RGB444_10B = 0x03,
- RGB444_12B = 0x05,
- RGB444_16B = 0x07,
- YCbCr444_8B = 0x09,
- YCbCr444_10B = 0x0B,
- YCbCr444_12B = 0x0D,
- YCbCr444_16B = 0x0F,
- YCbCr422_8B = 0x16,
- YCbCr422_10B = 0x14,
- YCbCr422_12B = 0x12,
-};
-
static const u16 csc_coeff_default[3][4] = {
{ 0x2000, 0x0000, 0x0000, 0x0000 },
{ 0x0000, 0x2000, 0x0000, 0x0000 },
@@ -533,7 +519,7 @@ static struct i2c_adapter *dw_hdmi_i2c_adapter(struct dw_hdmi *hdmi)
adap->owner = THIS_MODULE;
adap->dev.parent = hdmi->dev;
adap->algo = &dw_hdmi_algorithm;
- strlcpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
+ strscpy(adap->name, "DesignWare HDMI", sizeof(adap->name));
i2c_set_adapdata(adap, hdmi);
ret = i2c_add_adapter(adap);
@@ -856,10 +842,10 @@ static void dw_hdmi_gp_audio_enable(struct dw_hdmi *hdmi)
if (pdata->enable_audio)
pdata->enable_audio(hdmi,
- hdmi->channels,
- hdmi->sample_width,
- hdmi->sample_rate,
- hdmi->sample_non_pcm);
+ hdmi->channels,
+ hdmi->sample_width,
+ hdmi->sample_rate,
+ hdmi->sample_non_pcm);
}
static void dw_hdmi_gp_audio_disable(struct dw_hdmi *hdmi)
@@ -1426,9 +1412,9 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi,
/* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
if (dw_hdmi_support_scdc(hdmi, display)) {
if (mtmdsclock > HDMI14_MAX_TMDSCLK)
- drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 1);
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 1);
else
- drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 0);
+ drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 0);
}
}
EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio);
@@ -2116,7 +2102,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION));
/* Enabled Scrambling in the Sink */
- drm_scdc_set_scrambling(&hdmi->connector, 1);
+ drm_scdc_set_scrambling(hdmi->curr_conn, 1);
/*
* To activate the scrambler feature, you must ensure
@@ -2132,7 +2118,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL);
hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ,
HDMI_MC_SWRSTZ);
- drm_scdc_set_scrambling(&hdmi->connector, 0);
+ drm_scdc_set_scrambling(hdmi->curr_conn, 0);
}
}
@@ -2463,15 +2449,7 @@ static enum drm_connector_status dw_hdmi_detect(struct dw_hdmi *hdmi)
enum drm_connector_status result;
result = hdmi->phy.ops->read_hpd(hdmi, hdmi->phy.data);
-
- mutex_lock(&hdmi->mutex);
- if (result != hdmi->last_connector_result) {
- dev_dbg(hdmi->dev, "read_hpd result: %d", result);
- handle_plugged_change(hdmi,
- result == connector_status_connected);
- hdmi->last_connector_result = result;
- }
- mutex_unlock(&hdmi->mutex);
+ hdmi->last_connector_result = result;
return result;
}
@@ -2710,9 +2688,10 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
/* Default 8bit fallback */
output_fmts[i++] = MEDIA_BUS_FMT_UYYVYY8_0_5X24;
- *num_output_fmts = i;
-
- return output_fmts;
+ if (drm_mode_is_420_only(info, mode)) {
+ *num_output_fmts = i;
+ return output_fmts;
+ }
}
/*
@@ -2971,6 +2950,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge,
hdmi->curr_conn = NULL;
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
+ handle_plugged_change(hdmi, false);
mutex_unlock(&hdmi->mutex);
}
@@ -2989,6 +2969,7 @@ static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,
hdmi->curr_conn = connector;
dw_hdmi_update_power(hdmi);
dw_hdmi_update_phy_mask(hdmi);
+ handle_plugged_change(hdmi, true);
mutex_unlock(&hdmi->mutex);
}
@@ -3346,6 +3327,12 @@ static int dw_hdmi_parse_dt(struct dw_hdmi *hdmi)
return 0;
}
+bool dw_hdmi_bus_fmt_is_420(struct dw_hdmi *hdmi)
+{
+ return hdmi_bus_fmt_is_yuv420(hdmi->hdmi_data.enc_out_bus_format);
+}
+EXPORT_SYMBOL_GPL(dw_hdmi_bus_fmt_is_420);
+
struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
const struct dw_hdmi_plat_data *plat_data)
{
@@ -3553,6 +3540,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
| DRM_BRIDGE_OP_HPD;
hdmi->bridge.interlace_allowed = true;
+ hdmi->bridge.ddc = hdmi->ddc;
#ifdef CONFIG_OF
hdmi->bridge.of_node = pdev->dev.of_node;
#endif
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
index b2efecf7d160..04d4a1a10698 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c
@@ -13,7 +13,7 @@
#include <linux/debugfs.h>
#include <linux/iopoll.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -265,6 +265,7 @@ struct dw_mipi_dsi {
struct dw_mipi_dsi *master; /* dual-dsi master ptr */
struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */
+ struct drm_display_mode mode;
const struct dw_mipi_dsi_plat_data *plat_data;
};
@@ -332,6 +333,7 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
if (IS_ERR(bridge))
return PTR_ERR(bridge);
+ bridge->pre_enable_prev_first = true;
dsi->panel_bridge = bridge;
drm_bridge_add(&dsi->bridge);
@@ -859,15 +861,6 @@ static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
*/
dw_mipi_dsi_set_mode(dsi, 0);
- /*
- * TODO Only way found to call panel-bridge post_disable &
- * panel unprepare before the dsi "final" disable...
- * This needs to be fixed in the drm_bridge framework and the API
- * needs to be updated to manage our own call chains...
- */
- if (dsi->panel_bridge->funcs->post_disable)
- dsi->panel_bridge->funcs->post_disable(dsi->panel_bridge);
-
if (phy_ops->power_off)
phy_ops->power_off(dsi->plat_data->priv_data);
@@ -942,15 +935,25 @@ static void dw_mipi_dsi_mode_set(struct dw_mipi_dsi *dsi,
phy_ops->power_on(dsi->plat_data->priv_data);
}
+static void dw_mipi_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
+
+ /* Power up the dsi ctl into a command mode */
+ dw_mipi_dsi_mode_set(dsi, &dsi->mode);
+ if (dsi->slave)
+ dw_mipi_dsi_mode_set(dsi->slave, &dsi->mode);
+}
+
static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
const struct drm_display_mode *mode,
const struct drm_display_mode *adjusted_mode)
{
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
- dw_mipi_dsi_mode_set(dsi, adjusted_mode);
- if (dsi->slave)
- dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
+ /* Store the display mode for later use in pre_enable callback */
+ drm_mode_copy(&dsi->mode, adjusted_mode);
}
static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
@@ -1004,6 +1007,7 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_pre_enable = dw_mipi_dsi_bridge_atomic_pre_enable,
.atomic_enable = dw_mipi_dsi_bridge_atomic_enable,
.atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable,
.mode_set = dw_mipi_dsi_bridge_mode_set,
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 77f7f7f54757..46198af9eebb 100644
--- a/drivers/gpu/drm/bridge/tc358762.c
+++ b/drivers/gpu/drm/bridge/tc358762.c
@@ -11,6 +11,7 @@
*/
#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
@@ -40,8 +41,17 @@
#define DSI_LANEENABLE 0x0210 /* Enables each lane */
#define DSI_RX_START 1
-/* LCDC/DPI Host Registers */
-#define LCDCTRL 0x0420
+/* LCDC/DPI Host Registers, based on guesswork that this matches TC358764 */
+#define LCDCTRL 0x0420 /* Video Path Control */
+#define LCDCTRL_MSF BIT(0) /* Magic square in RGB666 */
+#define LCDCTRL_VTGEN BIT(4)/* Use chip clock for timing */
+#define LCDCTRL_UNK6 BIT(6) /* Unknown */
+#define LCDCTRL_EVTMODE BIT(5) /* Event mode */
+#define LCDCTRL_RGB888 BIT(8) /* RGB888 mode */
+#define LCDCTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */
+#define LCDCTRL_DEPOL BIT(18) /* Polarity of DE signal */
+#define LCDCTRL_VSPOL BIT(19) /* Polarity of VSYNC signal */
+#define LCDCTRL_VSDELAY(v) (((v) & 0xfff) << 20) /* VSYNC delay */
/* SPI Master Registers */
#define SPICMR 0x0450
@@ -63,6 +73,8 @@ struct tc358762 {
struct drm_bridge bridge;
struct regulator *regulator;
struct drm_bridge *panel_bridge;
+ struct gpio_desc *reset_gpio;
+ struct drm_display_mode mode;
bool pre_enabled;
int error;
};
@@ -103,6 +115,8 @@ static inline struct tc358762 *bridge_to_tc358762(struct drm_bridge *bridge)
static int tc358762_init(struct tc358762 *ctx)
{
+ u32 lcdctrl;
+
tc358762_write(ctx, DSI_LANEENABLE,
LANEENABLE_L0EN | LANEENABLE_CLEN);
tc358762_write(ctx, PPI_D0S_CLRSIPOCOUNT, 5);
@@ -112,7 +126,18 @@ static int tc358762_init(struct tc358762 *ctx)
tc358762_write(ctx, PPI_LPTXTIMECNT, LPX_PERIOD);
tc358762_write(ctx, SPICMR, 0x00);
- tc358762_write(ctx, LCDCTRL, 0x00100150);
+
+ lcdctrl = LCDCTRL_VSDELAY(1) | LCDCTRL_RGB888 |
+ LCDCTRL_UNK6 | LCDCTRL_VTGEN;
+
+ if (ctx->mode.flags & DRM_MODE_FLAG_NHSYNC)
+ lcdctrl |= LCDCTRL_HSPOL;
+
+ if (ctx->mode.flags & DRM_MODE_FLAG_NVSYNC)
+ lcdctrl |= LCDCTRL_VSPOL;
+
+ tc358762_write(ctx, LCDCTRL, lcdctrl);
+
tc358762_write(ctx, SYSCTRL, 0x040f);
msleep(100);
@@ -124,7 +149,7 @@ static int tc358762_init(struct tc358762 *ctx)
return tc358762_clear_error(ctx);
}
-static void tc358762_post_disable(struct drm_bridge *bridge)
+static void tc358762_post_disable(struct drm_bridge *bridge, struct drm_bridge_state *state)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
int ret;
@@ -138,12 +163,15 @@ static void tc358762_post_disable(struct drm_bridge *bridge)
ctx->pre_enabled = false;
+ if (ctx->reset_gpio)
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+
ret = regulator_disable(ctx->regulator);
if (ret < 0)
dev_err(ctx->dev, "error disabling regulators (%d)\n", ret);
}
-static void tc358762_pre_enable(struct drm_bridge *bridge)
+static void tc358762_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *state)
{
struct tc358762 *ctx = bridge_to_tc358762(bridge);
int ret;
@@ -152,11 +180,22 @@ static void tc358762_pre_enable(struct drm_bridge *bridge)
if (ret < 0)
dev_err(ctx->dev, "error enabling regulators (%d)\n", ret);
+ if (ctx->reset_gpio) {
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ usleep_range(5000, 10000);
+ }
+
+ ctx->pre_enabled = true;
+}
+
+static void tc358762_enable(struct drm_bridge *bridge, struct drm_bridge_state *state)
+{
+ struct tc358762 *ctx = bridge_to_tc358762(bridge);
+ int ret;
+
ret = tc358762_init(ctx);
if (ret < 0)
dev_err(ctx->dev, "error initializing bridge (%d)\n", ret);
-
- ctx->pre_enabled = true;
}
static int tc358762_attach(struct drm_bridge *bridge,
@@ -168,10 +207,24 @@ static int tc358762_attach(struct drm_bridge *bridge,
bridge, flags);
}
+static void tc358762_bridge_mode_set(struct drm_bridge *bridge,
+ const struct drm_display_mode *mode,
+ const struct drm_display_mode *adj)
+{
+ struct tc358762 *ctx = bridge_to_tc358762(bridge);
+
+ drm_mode_copy(&ctx->mode, mode);
+}
+
static const struct drm_bridge_funcs tc358762_bridge_funcs = {
- .post_disable = tc358762_post_disable,
- .pre_enable = tc358762_pre_enable,
+ .atomic_post_disable = tc358762_post_disable,
+ .atomic_pre_enable = tc358762_pre_enable,
+ .atomic_enable = tc358762_enable,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
.attach = tc358762_attach,
+ .mode_set = tc358762_bridge_mode_set,
};
static int tc358762_parse_dt(struct tc358762 *ctx)
@@ -185,6 +238,11 @@ static int tc358762_parse_dt(struct tc358762 *ctx)
ctx->panel_bridge = panel_bridge;
+ /* Reset GPIO is optional */
+ ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(ctx->reset_gpio))
+ return PTR_ERR(ctx->reset_gpio);
+
return 0;
}
@@ -216,7 +274,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
dsi->lanes = 1;
dsi->format = MIPI_DSI_FMT_RGB888;
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
- MIPI_DSI_MODE_LPM;
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_HSE;
ret = tc358762_parse_dt(ctx);
if (ret < 0)
diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c
index f85654f1b104..deccb3995022 100644
--- a/drivers/gpu/drm/bridge/tc358764.c
+++ b/drivers/gpu/drm/bridge/tc358764.c
@@ -42,10 +42,10 @@
/* Video path registers */
#define VP_CTRL 0x0450 /* Video Path Control */
-#define VP_CTRL_MSF(v) FLD_VAL(v, 0, 0) /* Magic square in RGB666 */
-#define VP_CTRL_VTGEN(v) FLD_VAL(v, 4, 4) /* Use chip clock for timing */
-#define VP_CTRL_EVTMODE(v) FLD_VAL(v, 5, 5) /* Event mode */
-#define VP_CTRL_RGB888(v) FLD_VAL(v, 8, 8) /* RGB888 mode */
+#define VP_CTRL_MSF BIT(0) /* Magic square in RGB666 */
+#define VP_CTRL_VTGEN BIT(4) /* Use chip clock for timing */
+#define VP_CTRL_EVTMODE BIT(5) /* Event mode */
+#define VP_CTRL_RGB888 BIT(8) /* RGB888 mode */
#define VP_CTRL_VSDELAY(v) FLD_VAL(v, 31, 20) /* VSYNC delay */
#define VP_CTRL_HSPOL BIT(17) /* Polarity of HSYNC signal */
#define VP_CTRL_DEPOL BIT(18) /* Polarity of DE signal */
@@ -176,7 +176,7 @@ static void tc358764_read(struct tc358764 *ctx, u16 addr, u32 *val)
if (ret >= 0)
le32_to_cpus(val);
- dev_dbg(ctx->dev, "read: %d, addr: %d\n", addr, *val);
+ dev_dbg(ctx->dev, "read: addr=0x%04x data=0x%08x\n", addr, *val);
}
static void tc358764_write(struct tc358764 *ctx, u16 addr, u32 val)
@@ -233,8 +233,8 @@ static int tc358764_init(struct tc358764 *ctx)
tc358764_write(ctx, DSI_STARTDSI, DSI_RX_START);
/* configure video path */
- tc358764_write(ctx, VP_CTRL, VP_CTRL_VSDELAY(15) | VP_CTRL_RGB888(1) |
- VP_CTRL_EVTMODE(1) | VP_CTRL_HSPOL | VP_CTRL_VSPOL);
+ tc358764_write(ctx, VP_CTRL, VP_CTRL_VSDELAY(15) | VP_CTRL_RGB888 |
+ VP_CTRL_EVTMODE | VP_CTRL_HSPOL | VP_CTRL_VSPOL);
/* reset PHY */
tc358764_write(ctx, LV_PHY0, LV_PHY0_RST(1) |
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 91f7cb56a654..b45bffab7c81 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -500,8 +500,8 @@ static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl)
if (ret)
return ret;
- /* Wait for PLL to lock: up to 2.09 ms, depending on refclk */
- usleep_range(3000, 6000);
+ /* Wait for PLL to lock: up to 7.5 ms, depending on refclk */
+ usleep_range(15000, 20000);
return 0;
}
@@ -817,7 +817,7 @@ static int tc_set_common_video_mode(struct tc_data *tc,
* sync signals
*/
ret = regmap_write(tc->regmap, VPCTRL0,
- FIELD_PREP(VSDELAY, 0) |
+ FIELD_PREP(VSDELAY, right_margin + 10) |
OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
if (ret)
return ret;
@@ -1781,7 +1781,200 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
static bool tc_readable_reg(struct device *dev, unsigned int reg)
{
- return reg != SYSCTRL;
+ switch (reg) {
+ /* DSI D-PHY Layer */
+ case 0x004:
+ case 0x020:
+ case 0x024:
+ case 0x028:
+ case 0x02c:
+ case 0x030:
+ case 0x038:
+ case 0x040:
+ case 0x044:
+ case 0x048:
+ case 0x04c:
+ case 0x050:
+ case 0x054:
+ /* DSI PPI Layer */
+ case PPI_STARTPPI:
+ case 0x108:
+ case 0x110:
+ case PPI_LPTXTIMECNT:
+ case PPI_LANEENABLE:
+ case PPI_TX_RX_TA:
+ case 0x140:
+ case PPI_D0S_ATMR:
+ case PPI_D1S_ATMR:
+ case 0x14c:
+ case 0x150:
+ case PPI_D0S_CLRSIPOCOUNT:
+ case PPI_D1S_CLRSIPOCOUNT:
+ case PPI_D2S_CLRSIPOCOUNT:
+ case PPI_D3S_CLRSIPOCOUNT:
+ case 0x180:
+ case 0x184:
+ case 0x188:
+ case 0x18c:
+ case 0x190:
+ case 0x1a0:
+ case 0x1a4:
+ case 0x1a8:
+ case 0x1ac:
+ case 0x1b0:
+ case 0x1c0:
+ case 0x1c4:
+ case 0x1c8:
+ case 0x1cc:
+ case 0x1d0:
+ case 0x1e0:
+ case 0x1e4:
+ case 0x1f0:
+ case 0x1f4:
+ /* DSI Protocol Layer */
+ case DSI_STARTDSI:
+ case 0x208:
+ case DSI_LANEENABLE:
+ case 0x214:
+ case 0x218:
+ case 0x220:
+ case 0x224:
+ case 0x228:
+ case 0x230:
+ /* DSI General */
+ case 0x300:
+ /* DSI Application Layer */
+ case 0x400:
+ case 0x404:
+ /* DPI */
+ case DPIPXLFMT:
+ /* Parallel Output */
+ case POCTRL:
+ /* Video Path0 Configuration */
+ case VPCTRL0:
+ case HTIM01:
+ case HTIM02:
+ case VTIM01:
+ case VTIM02:
+ case VFUEN0:
+ /* System */
+ case TC_IDREG:
+ case 0x504:
+ case SYSSTAT:
+ case SYSRSTENB:
+ case SYSCTRL:
+ /* I2C */
+ case 0x520:
+ /* GPIO */
+ case GPIOM:
+ case GPIOC:
+ case GPIOO:
+ case GPIOI:
+ /* Interrupt */
+ case INTCTL_G:
+ case INTSTS_G:
+ case 0x570:
+ case 0x574:
+ case INT_GP0_LCNT:
+ case INT_GP1_LCNT:
+ /* DisplayPort Control */
+ case DP0CTL:
+ /* DisplayPort Clock */
+ case DP0_VIDMNGEN0:
+ case DP0_VIDMNGEN1:
+ case DP0_VMNGENSTATUS:
+ case 0x628:
+ case 0x62c:
+ case 0x630:
+ /* DisplayPort Main Channel */
+ case DP0_SECSAMPLE:
+ case DP0_VIDSYNCDELAY:
+ case DP0_TOTALVAL:
+ case DP0_STARTVAL:
+ case DP0_ACTIVEVAL:
+ case DP0_SYNCVAL:
+ case DP0_MISC:
+ /* DisplayPort Aux Channel */
+ case DP0_AUXCFG0:
+ case DP0_AUXCFG1:
+ case DP0_AUXADDR:
+ case 0x66c:
+ case 0x670:
+ case 0x674:
+ case 0x678:
+ case 0x67c:
+ case 0x680:
+ case 0x684:
+ case 0x688:
+ case DP0_AUXSTATUS:
+ case DP0_AUXI2CADR:
+ /* DisplayPort Link Training */
+ case DP0_SRCCTRL:
+ case DP0_LTSTAT:
+ case DP0_SNKLTCHGREQ:
+ case DP0_LTLOOPCTRL:
+ case DP0_SNKLTCTRL:
+ case 0x6e8:
+ case 0x6ec:
+ case 0x6f0:
+ case 0x6f4:
+ /* DisplayPort Audio */
+ case 0x700:
+ case 0x704:
+ case 0x708:
+ case 0x70c:
+ case 0x710:
+ case 0x714:
+ case 0x718:
+ case 0x71c:
+ case 0x720:
+ /* DisplayPort Source Control */
+ case DP1_SRCCTRL:
+ /* DisplayPort PHY */
+ case DP_PHY_CTRL:
+ case 0x810:
+ case 0x814:
+ case 0x820:
+ case 0x840:
+ /* I2S */
+ case 0x880:
+ case 0x888:
+ case 0x88c:
+ case 0x890:
+ case 0x894:
+ case 0x898:
+ case 0x89c:
+ case 0x8a0:
+ case 0x8a4:
+ case 0x8a8:
+ case 0x8ac:
+ case 0x8b0:
+ case 0x8b4:
+ /* PLL */
+ case DP0_PLLCTRL:
+ case DP1_PLLCTRL:
+ case PXL_PLLCTRL:
+ case PXL_PLLPARAM:
+ case SYS_PLLPARAM:
+ /* HDCP */
+ case 0x980:
+ case 0x984:
+ case 0x988:
+ case 0x98c:
+ case 0x990:
+ case 0x994:
+ case 0x998:
+ case 0x99c:
+ case 0x9a0:
+ case 0x9a4:
+ case 0x9a8:
+ case 0x9ac:
+ /* Debug */
+ case TSTCTL:
+ case PLL_DBG:
+ return true;
+ }
+ return false;
}
static const struct regmap_range tc_volatile_ranges[] = {
@@ -1890,7 +2083,7 @@ static int tc_mipi_dsi_host_attach(struct tc_data *tc)
if (dsi_lanes < 0)
return dsi_lanes;
- dsi = mipi_dsi_device_register_full(host, &info);
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
if (IS_ERR(dsi))
return dev_err_probe(dev, PTR_ERR(dsi),
"failed to create dsi device\n");
@@ -1901,7 +2094,7 @@ static int tc_mipi_dsi_host_attach(struct tc_data *tc)
dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM | MIPI_DSI_CLOCK_NON_CONTINUOUS;
- ret = mipi_dsi_attach(dsi);
+ ret = devm_mipi_dsi_attach(dev, dsi);
if (ret < 0) {
dev_err(dev, "failed to attach dsi to host: %d\n", ret);
return ret;
@@ -2022,13 +2215,6 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc)
return -EINVAL;
}
-static void tc_clk_disable(void *data)
-{
- struct clk *refclk = data;
-
- clk_disable_unprepare(refclk);
-}
-
static int tc_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -2045,20 +2231,10 @@ static int tc_probe(struct i2c_client *client)
if (ret)
return ret;
- tc->refclk = devm_clk_get(dev, "ref");
- if (IS_ERR(tc->refclk)) {
- ret = PTR_ERR(tc->refclk);
- dev_err(dev, "Failed to get refclk: %d\n", ret);
- return ret;
- }
-
- ret = clk_prepare_enable(tc->refclk);
- if (ret)
- return ret;
-
- ret = devm_add_action_or_reset(dev, tc_clk_disable, tc->refclk);
- if (ret)
- return ret;
+ tc->refclk = devm_clk_get_enabled(dev, "ref");
+ if (IS_ERR(tc->refclk))
+ return dev_err_probe(dev, PTR_ERR(tc->refclk),
+ "Failed to get and enable the ref clk\n");
/* tRSTW = 100 cycles , at 13 MHz that is ~7.69 us */
usleep_range(10, 15);
@@ -2209,7 +2385,7 @@ static struct i2c_driver tc358767_driver = {
.of_match_table = tc358767_of_ids,
},
.id_table = tc358767_i2c_ids,
- .probe_new = tc_probe,
+ .probe = tc_probe,
.remove = tc_remove,
};
module_i2c_driver(tc358767_driver);
diff --git a/drivers/gpu/drm/bridge/tc358768.c b/drivers/gpu/drm/bridge/tc358768.c
index 7c0cbe84611b..819a4b6ec2a0 100644
--- a/drivers/gpu/drm/bridge/tc358768.c
+++ b/drivers/gpu/drm/bridge/tc358768.c
@@ -9,6 +9,8 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
+#include <linux/media-bus-format.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -146,6 +148,7 @@ struct tc358768_priv {
u32 pd_lines; /* number of Parallel Port Input Data Lines */
u32 dsi_lanes; /* number of DSI Lanes */
+ u32 dsi_bpp; /* number of Bits Per Pixel over DSI */
/* Parameters for PLL programming */
u32 fbd; /* PLL feedback divider */
@@ -284,12 +287,12 @@ static void tc358768_hw_disable(struct tc358768_priv *priv)
static u32 tc358768_pll_to_pclk(struct tc358768_priv *priv, u32 pll_clk)
{
- return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->pd_lines);
+ return (u32)div_u64((u64)pll_clk * priv->dsi_lanes, priv->dsi_bpp);
}
static u32 tc358768_pclk_to_pll(struct tc358768_priv *priv, u32 pclk)
{
- return (u32)div_u64((u64)pclk * priv->pd_lines, priv->dsi_lanes);
+ return (u32)div_u64((u64)pclk * priv->dsi_bpp, priv->dsi_lanes);
}
static int tc358768_calc_pll(struct tc358768_priv *priv,
@@ -334,13 +337,17 @@ static int tc358768_calc_pll(struct tc358768_priv *priv,
u32 fbd;
for (fbd = 0; fbd < 512; ++fbd) {
- u32 pll, diff;
+ u32 pll, diff, pll_in;
pll = (u32)div_u64((u64)refclk * (fbd + 1), divisor);
if (pll >= max_pll || pll < min_pll)
continue;
+ pll_in = (u32)div_u64((u64)refclk, prd + 1);
+ if (pll_in < 4000000)
+ continue;
+
diff = max(pll, target_pll) - min(pll, target_pll);
if (diff < best_diff) {
@@ -422,6 +429,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host,
priv->output.panel = panel;
priv->dsi_lanes = dev->lanes;
+ priv->dsi_bpp = mipi_dsi_pixel_format_to_bpp(dev->format);
/* get input ep (port0/endpoint0) */
ret = -EINVAL;
@@ -433,7 +441,7 @@ static int tc358768_dsi_host_attach(struct mipi_dsi_host *host,
}
if (ret)
- priv->pd_lines = mipi_dsi_pixel_format_to_bpp(dev->format);
+ priv->pd_lines = priv->dsi_bpp;
drm_bridge_add(&priv->bridge);
@@ -632,8 +640,9 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
struct mipi_dsi_device *dsi_dev = priv->output.dev;
unsigned long mode_flags = dsi_dev->mode_flags;
u32 val, val2, lptxcnt, hact, data_type;
+ s32 raw_val;
const struct drm_display_mode *mode;
- u32 dsibclk_nsk, dsiclk_nsk, ui_nsk, phy_delay_nsk;
+ u32 dsibclk_nsk, dsiclk_nsk, ui_nsk;
u32 dsiclk, dsibclk, video_start;
const u32 internal_delay = 40;
int ret, i;
@@ -717,11 +726,9 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
dsibclk);
dsiclk_nsk = (u32)div_u64((u64)1000000000 * TC358768_PRECISION, dsiclk);
ui_nsk = dsiclk_nsk / 2;
- phy_delay_nsk = dsibclk_nsk + 2 * dsiclk_nsk;
dev_dbg(priv->dev, "dsiclk_nsk: %u\n", dsiclk_nsk);
dev_dbg(priv->dev, "ui_nsk: %u\n", ui_nsk);
dev_dbg(priv->dev, "dsibclk_nsk: %u\n", dsibclk_nsk);
- dev_dbg(priv->dev, "phy_delay_nsk: %u\n", phy_delay_nsk);
/* LP11 > 100us for D-PHY Rx Init */
val = tc358768_ns_to_cnt(100 * 1000, dsibclk_nsk) - 1;
@@ -736,25 +743,26 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
/* 38ns < TCLK_PREPARE < 95ns */
val = tc358768_ns_to_cnt(65, dsibclk_nsk) - 1;
- /* TCLK_PREPARE > 300ns */
- val2 = tc358768_ns_to_cnt(300 + tc358768_to_ns(3 * ui_nsk),
- dsibclk_nsk);
- val |= (val2 - tc358768_to_ns(phy_delay_nsk - dsibclk_nsk)) << 8;
+ /* TCLK_PREPARE + TCLK_ZERO > 300ns */
+ val2 = tc358768_ns_to_cnt(300 - tc358768_to_ns(2 * ui_nsk),
+ dsibclk_nsk) - 2;
+ val |= val2 << 8;
dev_dbg(priv->dev, "TCLK_HEADERCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_HEADERCNT, val);
- /* TCLK_TRAIL > 60ns + 3*UI */
- val = 60 + tc358768_to_ns(3 * ui_nsk);
- val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 5;
+ /* TCLK_TRAIL > 60ns AND TEOT <= 105 ns + 12*UI */
+ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(2 * ui_nsk), dsibclk_nsk) - 5;
+ val = clamp(raw_val, 0, 127);
dev_dbg(priv->dev, "TCLK_TRAILCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_TRAILCNT, val);
/* 40ns + 4*UI < THS_PREPARE < 85ns + 6*UI */
val = 50 + tc358768_to_ns(4 * ui_nsk);
val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1;
- /* THS_ZERO > 145ns + 10*UI */
- val2 = tc358768_ns_to_cnt(145 - tc358768_to_ns(ui_nsk), dsibclk_nsk);
- val |= (val2 - tc358768_to_ns(phy_delay_nsk)) << 8;
+ /* THS_PREPARE + THS_ZERO > 145ns + 10*UI */
+ raw_val = tc358768_ns_to_cnt(145 - tc358768_to_ns(3 * ui_nsk), dsibclk_nsk) - 10;
+ val2 = clamp(raw_val, 0, 127);
+ val |= val2 << 8;
dev_dbg(priv->dev, "THS_HEADERCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_THS_HEADERCNT, val);
@@ -770,9 +778,10 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
dev_dbg(priv->dev, "TCLK_POSTCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_TCLK_POSTCNT, val);
- /* 60ns + 4*UI < THS_PREPARE < 105ns + 12*UI */
- val = tc358768_ns_to_cnt(60 + tc358768_to_ns(15 * ui_nsk),
- dsibclk_nsk) - 5;
+ /* max(60ns + 4*UI, 8*UI) < THS_TRAILCNT < 105ns + 12*UI */
+ raw_val = tc358768_ns_to_cnt(60 + tc358768_to_ns(18 * ui_nsk),
+ dsibclk_nsk) - 4;
+ val = clamp(raw_val, 0, 15);
dev_dbg(priv->dev, "THS_TRAILCNT: 0x%x\n", val);
tc358768_write(priv, TC358768_THS_TRAILCNT, val);
@@ -786,7 +795,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
/* TXTAGOCNT[26:16] RXTASURECNT[10:0] */
val = tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk * 4);
- val = tc358768_ns_to_cnt(val, dsibclk_nsk) - 1;
+ val = tc358768_ns_to_cnt(val, dsibclk_nsk) / 4 - 1;
val2 = tc358768_ns_to_cnt(tc358768_to_ns((lptxcnt + 1) * dsibclk_nsk),
dsibclk_nsk) - 2;
val = val << 16 | val2;
@@ -866,8 +875,7 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)
val = TC358768_DSI_CONFW_MODE_SET | TC358768_DSI_CONFW_ADDR_DSI_CONTROL;
val |= (dsi_dev->lanes - 1) << 1;
- if (!(dsi_dev->mode_flags & MIPI_DSI_MODE_LPM))
- val |= TC358768_DSI_CONTROL_TXMD;
+ val |= TC358768_DSI_CONTROL_TXMD;
if (!(mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
val |= TC358768_DSI_CONTROL_HSCKMD;
@@ -913,6 +921,44 @@ static void tc358768_bridge_enable(struct drm_bridge *bridge)
}
}
+#define MAX_INPUT_SEL_FORMATS 1
+
+static u32 *
+tc358768_atomic_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ struct tc358768_priv *priv = bridge_to_tc358768(bridge);
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts),
+ GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ switch (priv->pd_lines) {
+ case 16:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB565_1X16;
+ break;
+ case 18:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB666_1X18;
+ break;
+ default:
+ case 24:
+ input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24;
+ break;
+ }
+
+ *num_input_fmts = MAX_INPUT_SEL_FORMATS;
+
+ return input_fmts;
+}
+
static const struct drm_bridge_funcs tc358768_bridge_funcs = {
.attach = tc358768_bridge_attach,
.mode_valid = tc358768_bridge_mode_valid,
@@ -920,6 +966,11 @@ static const struct drm_bridge_funcs tc358768_bridge_funcs = {
.enable = tc358768_bridge_enable,
.disable = tc358768_bridge_disable,
.post_disable = tc358768_bridge_post_disable,
+
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_get_input_bus_fmts = tc358768_atomic_get_input_bus_fmts,
};
static const struct drm_bridge_timings default_tc358768_timings = {
@@ -1083,7 +1134,7 @@ static struct i2c_driver tc358768_driver = {
.of_match_table = tc358768_of_ids,
},
.id_table = tc358768_i2c_ids,
- .probe_new = tc358768_i2c_probe,
+ .probe = tc358768_i2c_probe,
.remove = tc358768_i2c_remove,
};
module_i2c_driver(tc358768_driver);
diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
index 19316994ddd1..90a89d70d832 100644
--- a/drivers/gpu/drm/bridge/tc358775.c
+++ b/drivers/gpu/drm/bridge/tc358775.c
@@ -728,7 +728,7 @@ static struct i2c_driver tc358775_driver = {
.of_match_table = tc358775_of_ids,
},
.id_table = tc358775_i2c_ids,
- .probe_new = tc_probe,
+ .probe = tc_probe,
.remove = tc_remove,
};
module_i2c_driver(tc358775_driver);
diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c
index 186a9e2ff24d..b65632ec7e7d 100644
--- a/drivers/gpu/drm/bridge/ti-dlpc3433.c
+++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c
@@ -400,7 +400,7 @@ static const struct of_device_id dlpc3433_match_table[] = {
MODULE_DEVICE_TABLE(of, dlpc3433_match_table);
static struct i2c_driver dlpc3433_driver = {
- .probe_new = dlpc3433_probe,
+ .probe = dlpc3433_probe,
.remove = dlpc3433_remove,
.id_table = dlpc3433_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
index 75286c9afbb9..061e8bd5915d 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c
@@ -31,7 +31,7 @@
#include <linux/i2c.h>
#include <linux/media-bus-format.h>
#include <linux/module.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -321,8 +321,8 @@ static u8 sn65dsi83_get_dsi_div(struct sn65dsi83 *ctx)
return dsi_div - 1;
}
-static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
struct drm_atomic_state *state = old_bridge_state->base.state;
@@ -478,17 +478,29 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
/* On failure, disable PLL again and exit. */
regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
+ regulator_disable(ctx->vcc);
return;
}
/* Trigger reset after CSR register update. */
regmap_write(ctx->regmap, REG_RC_RESET, REG_RC_RESET_SOFT_RESET);
+ /* Wait for 10ms after soft reset as specified in datasheet */
+ usleep_range(10000, 12000);
+}
+
+static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
+ unsigned int pval;
+
/* Clear all errors that got asserted during initialization. */
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
regmap_write(ctx->regmap, REG_IRQ_STAT, pval);
- usleep_range(10000, 12000);
+ /* Wait for 1ms and check for errors in status register */
+ usleep_range(1000, 1100);
regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
if (pval)
dev_err(ctx->dev, "Unexpected link status 0x%02x\n", pval);
@@ -555,6 +567,7 @@ static const struct drm_bridge_funcs sn65dsi83_funcs = {
.attach = sn65dsi83_attach,
.detach = sn65dsi83_detach,
.atomic_enable = sn65dsi83_atomic_enable,
+ .atomic_pre_enable = sn65dsi83_atomic_pre_enable,
.atomic_disable = sn65dsi83_atomic_disable,
.mode_valid = sn65dsi83_mode_valid,
@@ -697,6 +710,7 @@ static int sn65dsi83_probe(struct i2c_client *client)
ctx->bridge.funcs = &sn65dsi83_funcs;
ctx->bridge.of_node = dev->of_node;
+ ctx->bridge.pre_enable_prev_first = true;
drm_bridge_add(&ctx->bridge);
ret = sn65dsi83_host_attach(ctx);
@@ -734,7 +748,7 @@ static const struct of_device_id sn65dsi83_match_table[] = {
MODULE_DEVICE_TABLE(of, sn65dsi83_match_table);
static struct i2c_driver sn65dsi83_driver = {
- .probe_new = sn65dsi83_probe,
+ .probe = sn65dsi83_probe,
.remove = sn65dsi83_remove,
.id_table = sn65dsi83_id,
.driver = {
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 4676cf2900df..f448b903e190 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -170,10 +170,10 @@
* @pwm_refclk_freq: Cache for the reference clock input to the PWM.
*/
struct ti_sn65dsi86 {
- struct auxiliary_device bridge_aux;
- struct auxiliary_device gpio_aux;
- struct auxiliary_device aux_aux;
- struct auxiliary_device pwm_aux;
+ struct auxiliary_device *bridge_aux;
+ struct auxiliary_device *gpio_aux;
+ struct auxiliary_device *aux_aux;
+ struct auxiliary_device *pwm_aux;
struct device *dev;
struct regmap *regmap;
@@ -468,27 +468,34 @@ static void ti_sn65dsi86_delete_aux(void *data)
auxiliary_device_delete(data);
}
-/*
- * AUX bus docs say that a non-NULL release is mandatory, but it makes no
- * sense for the model used here where all of the aux devices are allocated
- * in the single shared structure. We'll use this noop as a workaround.
- */
-static void ti_sn65dsi86_noop(struct device *dev) {}
+static void ti_sn65dsi86_aux_device_release(struct device *dev)
+{
+ struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev);
+
+ kfree(aux);
+}
static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
- struct auxiliary_device *aux,
+ struct auxiliary_device **aux_out,
const char *name)
{
struct device *dev = pdata->dev;
+ struct auxiliary_device *aux;
int ret;
+ aux = kzalloc(sizeof(*aux), GFP_KERNEL);
+ if (!aux)
+ return -ENOMEM;
+
aux->name = name;
aux->dev.parent = dev;
- aux->dev.release = ti_sn65dsi86_noop;
+ aux->dev.release = ti_sn65dsi86_aux_device_release;
device_set_of_node_from_dev(&aux->dev, dev);
ret = auxiliary_device_init(aux);
- if (ret)
+ if (ret) {
+ kfree(aux);
return ret;
+ }
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux);
if (ret)
return ret;
@@ -497,6 +504,8 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux);
+ if (!ret)
+ *aux_out = aux;
return ret;
}
@@ -622,6 +631,24 @@ exit:
return len;
}
+static int ti_sn_aux_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long wait_us)
+{
+ /*
+ * The HPD in this chip is a bit useless (See comment in
+ * ti_sn65dsi86_enable_comms) so if our driver is expected to wait
+ * for HPD, we just assume it's asserted after the wait_us delay.
+ *
+ * In case we are asked to wait forever (wait_us=0) take conservative
+ * 500ms delay.
+ */
+ if (wait_us == 0)
+ wait_us = 500000;
+
+ usleep_range(wait_us, wait_us + 1000);
+
+ return 0;
+}
+
static int ti_sn_aux_probe(struct auxiliary_device *adev,
const struct auxiliary_device_id *id)
{
@@ -631,6 +658,7 @@ static int ti_sn_aux_probe(struct auxiliary_device *adev,
pdata->aux.name = "ti-sn65dsi86-aux";
pdata->aux.dev = &adev->dev;
pdata->aux.transfer = ti_sn_aux_transfer;
+ pdata->aux.wait_hpd_asserted = ti_sn_aux_wait_hpd_asserted;
drm_dp_aux_init(&pdata->aux);
ret = devm_of_dp_aux_populate_ep_devices(&pdata->aux);
@@ -1955,7 +1983,7 @@ static struct i2c_driver ti_sn65dsi86_driver = {
.of_match_table = ti_sn65dsi86_match_table,
.pm = &ti_sn65dsi86_pm_ops,
},
- .probe_new = ti_sn65dsi86_probe,
+ .probe = ti_sn65dsi86_probe,
.id_table = ti_sn65dsi86_id,
};
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index ab63225cd635..28848a8eb42e 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -206,12 +206,55 @@ static enum drm_mode_status tfp410_mode_valid(struct drm_bridge *bridge,
return MODE_OK;
}
+static u32 *tfp410_get_input_bus_fmts(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state,
+ u32 output_fmt,
+ unsigned int *num_input_fmts)
+{
+ struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
+ u32 *input_fmts;
+
+ *num_input_fmts = 0;
+
+ input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
+ if (!input_fmts)
+ return NULL;
+
+ *num_input_fmts = 1;
+ input_fmts[0] = dvi->bus_format;
+
+ return input_fmts;
+}
+
+static int tfp410_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct tfp410 *dvi = drm_bridge_to_tfp410(bridge);
+
+ /*
+ * There might be flags negotiation supported in future.
+ * Set the bus flags in atomic_check statically for now.
+ */
+ bridge_state->input_bus_cfg.flags = dvi->timings.input_bus_flags;
+
+ return 0;
+}
+
static const struct drm_bridge_funcs tfp410_bridge_funcs = {
.attach = tfp410_attach,
.detach = tfp410_detach,
.enable = tfp410_enable,
.disable = tfp410_disable,
.mode_valid = tfp410_mode_valid,
+ .atomic_reset = drm_atomic_helper_bridge_reset,
+ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
+ .atomic_get_input_bus_fmts = tfp410_get_input_bus_fmts,
+ .atomic_check = tfp410_atomic_check,
};
static const struct drm_bridge_timings tfp410_default_timings = {
@@ -405,10 +448,10 @@ MODULE_DEVICE_TABLE(i2c, tfp410_i2c_ids);
static struct i2c_driver tfp410_i2c_driver = {
.driver = {
.name = "tfp410",
- .of_match_table = of_match_ptr(tfp410_match),
+ .of_match_table = tfp410_match,
},
.id_table = tfp410_i2c_ids,
- .probe_new = tfp410_i2c_probe,
+ .probe = tfp410_i2c_probe,
.remove = tfp410_i2c_remove,
};
#endif /* IS_ENABLED(CONFIG_I2C) */