mfd: rkx110_x120: support pattern generator for V1

Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
Change-Id: I0fef8a64dd5602ac8642142b247b4198baef56cb
This commit is contained in:
Zhang Yubing
2023-05-22 18:02:26 +08:00
committed by Tao Huang
parent c17a354602
commit ad8f45b6ce
9 changed files with 374 additions and 20 deletions

View File

@@ -341,6 +341,8 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* link(dclk): Allowed to change PLL rate if need ! */
case RKX111_CPS_DCLK_D_DSI_0_REC:
case RKX111_CPS_DCLK_D_DSI_1_REC:
case RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:
case RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:
case RKX110_CPS_CLK_2X_LVDS_RKLINK_TX:
/* i2s */
case RKX110_CPS_CLK_I2S_SRC_RKLINK_TX:
@@ -384,9 +386,6 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName
/* bus */
case RKX110_CPS_DCLK_RX_PRE:
case RKX111_CPS_DCLK_RX_PRE_200M:
/* lvds */
case RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:
case RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:
/* camera */
case RKX110_CPS_CLK_CAM0_OUT2IO:
case RKX110_CPS_CLK_CAM1_OUT2IO:

View File

@@ -8,6 +8,8 @@
#include <linux/debugfs.h>
#include "rkx110_x120.h"
#include "rkx110_x120_display.h"
#include "hal/cru_api.h"
#define PATTERN_GEN_PATTERN_CTRL 0x0000
#define PATTERN_START_PCLK BIT(31)
@@ -29,11 +31,10 @@
#define PATTERN_GEN_VALUE0 0x0014
#define PATTERN_GEN_VALUE1 0x0018
static void pattern_gen_enable(struct pattern_gen *pattern_gen)
static void pattern_gen_config(struct i2c_client *client, struct pattern_gen *pattern_gen,
struct videomode *vm)
{
struct i2c_client *client = pattern_gen->chip->client;
struct rk_serdes *serdes = pattern_gen->chip->serdes;
const struct videomode *vm = serdes->vm;
serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
PATTERN_RECTANGLE_H | PATTERN_RECTANGLE_V,
@@ -53,24 +54,311 @@ static void pattern_gen_enable(struct pattern_gen *pattern_gen)
serdes->i2c_write_reg(client, pattern_gen->base + PATTERN_GEN_PATERN_VH_CFG3,
FIELD_PREP(PATTERN_HSA, vm->hsync_len));
serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
PATTERN_START_PCLK,
FIELD_PREP(PATTERN_START_PCLK, 1));
serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
BIT(pattern_gen->link_src_offset + 16) |
BIT(pattern_gen->link_src_offset));
}
static void pattern_stop_stream(struct pattern_gen *pattern_gen)
{
struct rk_serdes *serdes = pattern_gen->chip->serdes;
if (serdes->version != SERDES_V1)
return;
if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
return;
rk_serdes_display_video_start(serdes, pattern_gen->route, false);
if (!strcmp(pattern_gen->name, "lvds0")) {
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
} else if (!strcmp(pattern_gen->name, "lvds1")) {
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
} else if (!strcmp(pattern_gen->name, "dual-lvds")) {
rkx110_set_stream_source(serdes, RK_SERDES_RGB_RX, DEVICE_LOCAL);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
} else if (!strcmp(pattern_gen->name, "dsi0")) {
serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
0x1400140);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, false);
} else if (!strcmp(pattern_gen->name, "dsi1")) {
serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
0x2800280);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, false);
}
}
static void pattern_start_stream(struct pattern_gen *pattern_gen, bool is_pattern_stream)
{
struct rk_serdes *serdes = pattern_gen->chip->serdes;
struct videomode *vm = &pattern_gen->route->vm;
u32 delay_length;
if (serdes->version != SERDES_V1)
return;
if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
return;
if (!strcmp(pattern_gen->name, "lvds0")) {
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
} else if (!strcmp(pattern_gen->name, "lvds1")) {
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
} else if (!strcmp(pattern_gen->name, "dual-lvds")) {
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX);
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX);
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX);
rkx110_set_stream_source(serdes, RK_SERDES_DUAL_LVDS_RX,
DEVICE_LOCAL);
} else if (!strcmp(pattern_gen->name, "dsi0")) {
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX);
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX);
serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
0x1400000);
rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 0,
is_pattern_stream ? false : true);
if (is_pattern_stream)
delay_length = vm->hsync_len + vm->hback_porch +
vm->hactive + vm->hfront_porch;
else
delay_length = (vm->vfront_porch + 1) * (vm->hsync_len +
vm->hback_porch + vm->hactive + vm->hfront_porch);
rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 0, delay_length);
rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, true);
} else if (!strcmp(pattern_gen->name, "dsi1")) {
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX);
hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk,
RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX);
serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314,
0x2800000);
rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 1,
is_pattern_stream ? false : true);
if (is_pattern_stream)
delay_length = vm->hsync_len + vm->hback_porch +
vm->hactive + vm->hfront_porch;
else
delay_length = (vm->vfront_porch + 1) * (vm->hsync_len +
vm->hback_porch + vm->hactive + vm->hfront_porch);
rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 1, delay_length);
rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, true);
}
rk_serdes_display_video_start(serdes, pattern_gen->route, true);
}
static void pattern_switch_clk_to_pattern(struct pattern_gen *pattern_gen, struct videomode *vm)
{
struct rk_serdes *serdes = pattern_gen->chip->serdes;
struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk;
if (serdes->version != SERDES_V1)
return;
if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
return;
if (!strcmp(pattern_gen->name, "lvds0")) {
hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock);
dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n",
hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN));
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN);
} else if (!strcmp(pattern_gen->name, "lvds1")) {
hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock);
dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n",
hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN));
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN);
} else if (!strcmp(pattern_gen->name, "dual-lvds")) {
hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock);
dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n",
hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN));
hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock);
dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n",
hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN));
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN);
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN);
} else if (!strcmp(pattern_gen->name, "dsi0")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL,
RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_PATTERN_GEN);
} else if (!strcmp(pattern_gen->name, "dsi1")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL,
RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_PATTERN_GEN);
}
}
static void pattern_switch_clk_to_stream(struct pattern_gen *pattern_gen)
{
struct rk_serdes *serdes = pattern_gen->chip->serdes;
struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk;
if (serdes->version != SERDES_V1)
return;
if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL])
return;
if (!strcmp(pattern_gen->name, "lvds0")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE);
} else if (!strcmp(pattern_gen->name, "lvds1")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE);
} else if (!strcmp(pattern_gen->name, "dual-lvds")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE);
hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL,
RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE);
} else if (!strcmp(pattern_gen->name, "dsi0")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL,
RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_RKLINK_TX_PRE);
} else if (!strcmp(pattern_gen->name, "dsi1")) {
hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL,
RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_RKLINK_TX_PRE);
}
}
static int pattern_get_route(struct pattern_gen *pattern_gen)
{
struct rk_serdes *serdes = pattern_gen->chip->serdes;
struct rk_serdes_route *route;
int i;
for (i = 0; i < serdes->route_nr; i++) {
route = serdes->route[i];
if (pattern_gen->chip == &serdes->chip[DEVICE_LOCAL]) {
if ((pattern_gen->type == route->local_port0) ||
(pattern_gen->type == route->local_port1)) {
pattern_gen->route = route;
break;
}
}
if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE0]) {
if ((pattern_gen->type == route->remote0_port0) ||
(pattern_gen->type == route->remote0_port1)) {
pattern_gen->route = route;
break;
}
}
if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE1]) {
if ((pattern_gen->type == route->remote1_port0) ||
(pattern_gen->type == route->remote1_port1)) {
pattern_gen->route = route;
break;
}
}
}
if (i >= serdes->route_nr) {
dev_info(serdes->dev, "can't find the %s in route\n", pattern_gen->name);
return -EINVAL;
}
return 0;
}
static void pattern_gen_enable(struct pattern_gen *pattern_gen)
{
struct i2c_client *client = pattern_gen->chip->client;
struct rk_serdes *serdes = pattern_gen->chip->serdes;
struct videomode vm;
int ret;
ret = pattern_get_route(pattern_gen);
if (ret)
return;
memcpy(&vm, &pattern_gen->route->vm, sizeof(vm));
pattern_stop_stream(pattern_gen);
if (!strcmp(pattern_gen->name, "dual-lvds")) {
struct pattern_gen *lvds0_pat = pattern_gen + 1;
struct pattern_gen *lvds1_pat = pattern_gen + 2;
vm.hactive /= 2;
vm.hfront_porch /= 2;
vm.hback_porch /= 2;
vm.hsync_len /= 2;
vm.pixelclock /= 2;
pattern_switch_clk_to_pattern(pattern_gen, &vm);
pattern_gen_config(client, lvds0_pat, &vm);
pattern_gen_config(client, lvds1_pat, &vm);
serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
BIT(pattern_gen->link_src_offset + 16) |
BIT(pattern_gen->link_src_offset));
} else {
pattern_switch_clk_to_pattern(pattern_gen, &vm);
pattern_gen_config(client, pattern_gen, &vm);
serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
PATTERN_START_PCLK,
FIELD_PREP(PATTERN_START_PCLK, 1));
}
pattern_start_stream(pattern_gen, true);
}
static void pattern_gen_disable(struct pattern_gen *pattern_gen)
{
struct i2c_client *client = pattern_gen->chip->client;
struct rk_serdes *serdes = pattern_gen->chip->serdes;
int ret;
serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
BIT(pattern_gen->link_src_offset + 16));
serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
PATTERN_START_PCLK,
FIELD_PREP(PATTERN_START_PCLK, 0));
ret = pattern_get_route(pattern_gen);
if (ret)
return;
pattern_stop_stream(pattern_gen);
if (!strcmp(pattern_gen->name, "dual-lvds")) {
struct pattern_gen *lvds0_pat = pattern_gen + 1;
struct pattern_gen *lvds1_pat = pattern_gen + 2;
serdes->i2c_write_reg(client, lvds0_pat->link_src_reg,
BIT(lvds0_pat->link_src_offset + 16));
serdes->i2c_write_reg(client, lvds1_pat->link_src_reg,
BIT(lvds1_pat->link_src_offset + 16));
serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
BIT(pattern_gen->link_src_offset + 16));
} else {
serdes->i2c_write_reg(client, pattern_gen->link_src_reg,
BIT(pattern_gen->link_src_offset + 16));
serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL,
PATTERN_START_PCLK,
FIELD_PREP(PATTERN_START_PCLK, 0));
}
pattern_switch_clk_to_stream(pattern_gen);
pattern_start_stream(pattern_gen, false);
}
static ssize_t pattern_gen_write(struct file *file, const char __user *ubuf,

View File

@@ -15,21 +15,30 @@ static struct pattern_gen rkx110_pattern_gen[] = {
.base = RKX110_PATTERN_GEN_DSI0_BASE,
.link_src_reg = SER_GRF_SOC_CON4,
.link_src_offset = 12,
.type = RK_SERDES_DSI_RX0,
}, {
.name = "dsi1",
.base = RKX110_PATTERN_GEN_DSI1_BASE,
.link_src_reg = SER_GRF_SOC_CON4,
.link_src_offset = 13,
.type = RK_SERDES_DSI_RX1,
}, {
.name = "dual-lvds",
.link_src_reg = SER_GRF_SOC_CON1,
.link_src_offset = 14,
.type = RK_SERDES_DUAL_LVDS_RX,
}, {
.name = "lvds0",
.base = RKX110_PATTERN_GEN_LVDS0_BASE,
.link_src_reg = SER_GRF_SOC_CON4,
.link_src_offset = 14,
.type = RK_SERDES_LVDS_RX0,
}, {
.name = "lvds1",
.base = RKX110_PATTERN_GEN_LVDS1_BASE,
.link_src_reg = SER_GRF_SOC_CON4,
.link_src_offset = 15,
.type = RK_SERDES_LVDS_RX1,
},
{ /* sentinel */ }
};

View File

@@ -93,6 +93,7 @@
#define DSI_VSA(x) UPDATE(x, 9, 0)
#define SER_RKLINK_DSI_REC3(x) LINK_REG(0x0014 + 0x10 * x)
#define DSI_DELAY_LENGTH_MASK GENMASK(31, 12)
#define DSI_DELAY_LENGTH(x) UPDATE(x, 31, 12)
#define DSI_HSA(x) UPDATE(x, 11, 0)
@@ -552,6 +553,37 @@ static int rkx110_linktx_input_port_cfg(struct rk_serdes *serdes, u8 dev_id, u32
return 0;
}
int rkx110_linktx_dsi_rec_start(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool enable)
{
struct i2c_client *client = serdes->chip[dev_id].client;
serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC0(dsi_id), DSI_REC_START,
enable ? DSI_REC_START : 0);
return 0;
}
int rkx110_linktx_dsi_type_select(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool is_cmd)
{
struct i2c_client *client = serdes->chip[dev_id].client;
serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC0(dsi_id), DSI_CMD_TYPE,
is_cmd ? DSI_CMD_TYPE : 0);
return 0;
}
int rkx110_linktx_dsi_deley_length_config(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id,
u32 length)
{
struct i2c_client *client = serdes->chip[dev_id].client;
serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC3(dsi_id), DSI_DELAY_LENGTH_MASK,
DSI_DELAY_LENGTH(length));
return 0;
}
static int rk_serdes_link_tx_dsi_enable(struct rk_serdes *serdes, struct rk_serdes_route *route,
int id)
{

View File

@@ -13,7 +13,7 @@
#include <linux/i2c.h>
#include <video/videomode.h>
#define MAX_PANEL 2
#define RK_SERDES_MAX_ROUTE 2
#define RK_SERDES_PASSTHROUGH_CNT 11
#define SERDES_VERSION_V0(type) 0x2201
@@ -237,9 +237,11 @@ struct rk_serdes_chip {
struct pattern_gen {
const char *name;
struct rk_serdes_chip *chip;
struct rk_serdes_route *route;
u32 base;
u32 link_src_reg;
u8 link_src_offset;
u8 type;
};
struct rk_serdes_pt_pin {
@@ -283,7 +285,7 @@ struct rk_serdes {
struct dentry *debugfs_remote1;
struct dentry *debugfs_rate;
struct videomode *vm;
struct rk_serdes_route *route[RK_SERDES_MAX_ROUTE];
u32 stream_type;
u32 version;
u8 remote_nr;
@@ -384,4 +386,9 @@ int rkx110_irq_handler(struct rk_serdes *serdes, u8 dev_id);
void rkx120_irq_enable(struct rk_serdes *serdes, u8 dev_id);
void rkx120_irq_disable(struct rk_serdes *serdes, u8 dev_id);
int rkx120_irq_handler(struct rk_serdes *serdes, u8 dev_id);
int rkx110_linktx_dsi_rec_start(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool enable);
int rkx110_linktx_dsi_type_select(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool is_cmd);
int rkx110_linktx_dsi_deley_length_config(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id,
u32 length);
#endif

View File

@@ -67,7 +67,7 @@ int rk_serdes_display_route_prepare(struct rk_serdes *serdes, struct rk_serdes_r
return 0;
}
static int rk_serdes_display_video_start(struct rk_serdes *serdes,
int rk_serdes_display_video_start(struct rk_serdes *serdes,
struct rk_serdes_route *route, bool enable)
{
if (route->local_port0) {

View File

@@ -13,5 +13,7 @@ int rk_serdes_display_route_enable(struct rk_serdes *serdes, struct rk_serdes_ro
int rk_serdes_display_route_disable(struct rk_serdes *serdes, struct rk_serdes_route *route);
int rk_serdes_display_route_unprepare(struct rk_serdes *serdes, struct rk_serdes_route *route);
int rk_serdes_display_route_init(struct rk_serdes *serdes);
int rk_serdes_display_video_start(struct rk_serdes *serdes,
struct rk_serdes_route *route, bool enable);
#endif

View File

@@ -693,11 +693,15 @@ static int serdes_panel_probe(struct platform_device *pdev)
if (sd_panel->route.route_flag & ROUTE_MULTI_CHANNEL)
serdes->channel_nr = 2;
if (sd_panel->route.local_port0 && sd_panel->id == 0)
if (sd_panel->route.local_port0 && sd_panel->id == 0) {
serdes->route[0] = &sd_panel->route;
serdes->route_nr++;
}
if (sd_panel->route.local_port1 && sd_panel->id == 1)
if (sd_panel->route.local_port1 && sd_panel->id == 1) {
serdes->route[1] = &sd_panel->route;
serdes->route_nr++;
}
if (serdes->route_nr == 2)
serdes->channel_nr = 2;

View File

@@ -21,16 +21,24 @@ static struct pattern_gen rkx120_pattern_gen[] = {
.base = RKX120_PATTERN_GEN_DSI_BASE,
.link_src_reg = DES_GRF_SOC_CON2,
.link_src_offset = 12,
.type = RK_SERDES_DSI_TX0,
}, {
.name = "dual-lvds",
.link_src_reg = DES_GRF_SOC_CON1,
.link_src_offset = 14,
.type = RK_SERDES_DUAL_LVDS_TX,
}, {
.name = "lvds0",
.base = RKX120_PATTERN_GEN_LVDS0_BASE,
.link_src_reg = DES_GRF_SOC_CON2,
.link_src_offset = 13,
.type = RK_SERDES_LVDS_TX0,
}, {
.name = "lvds1",
.base = RKX120_PATTERN_GEN_LVDS1_BASE,
.link_src_reg = DES_GRF_SOC_CON2,
.link_src_offset = 14,
.type = RK_SERDES_LVDS_TX1,
},
{ /* sentinel */ }
};
@@ -236,9 +244,14 @@ static const struct file_operations rkx120_reg_fops = {
void rkx120_debugfs_init(struct rk_serdes_chip *chip, struct dentry *dentry)
{
const struct rk_serdes_reg *regs = rkx120_regs;
struct pattern_gen *pattern_gen = rkx120_pattern_gen;
struct pattern_gen *pattern_gen;
struct dentry *dir;
pattern_gen = devm_kmemdup(chip->serdes->dev, &rkx120_pattern_gen,
sizeof(rkx120_pattern_gen), GFP_KERNEL);
if (!pattern_gen)
return;
dir = debugfs_create_dir("registers", dentry);
if (!IS_ERR(dir)) {
while (regs->name) {