drm/rockchip: dsi: resolved dependency between mipi_tx0 and mipi_tx1

It has a shared pll for mipi_tx0/mipi_tx1 on RK3288/RK3399,
so we need to initialize mipi_tx0 as necessary before enabling mipi_tx1.

Change-Id: I2cd9ffe576c7a3d1e6c3081c2b174e3e971a0c4a
Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
Wyon Bi
2019-07-02 14:52:06 +08:00
committed by Tao Huang
parent bc3cc8c42f
commit c7b36a773e
2 changed files with 117 additions and 66 deletions

View File

@@ -31,7 +31,6 @@ Optional properties
- phys: phandle to Non-SNPS PHY node
- phy-names: the string "mipi_dphy" when is found in a node, along with "phys"
attribute, provides phandle to MIPI PHY node
- rockchip,dual-channel: for dual-channel panel, if not, don't configure
- rockchip,lane-rate: manually configure lane-rate, not necessary.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
@@ -52,7 +51,6 @@ For Rockchip RK3288:
#address-cells = <1>;
#size-cells = <0>;
rockchip,dual-channel = <&dsi1>;
rockchip,lane-rate = <900>;
status = "okay";

View File

@@ -282,12 +282,11 @@ struct dw_mipi_dsi {
struct clk *pclk;
struct clk *h2p_clk;
int irq;
/* dual-channel */
struct dw_mipi_dsi *master;
struct dw_mipi_dsi *slave;
struct device_node *panel_node;
int id;
struct mutex mutex;
bool prepared;
unsigned int id;
unsigned long mode_flags;
unsigned int lane_mbps; /* per lane */
@@ -802,6 +801,11 @@ static void dw_mipi_dsi_set_pll(struct dw_mipi_dsi *dsi, unsigned long rate)
dsi->slave->dphy.input_div = dsi->dphy.input_div;
dsi->slave->dphy.feedback_div = dsi->dphy.feedback_div;
}
if (dsi->master) {
dsi->master->lane_mbps = dsi->lane_mbps;
dsi->master->dphy.input_div = dsi->dphy.input_div;
dsi->master->dphy.feedback_div = dsi->dphy.feedback_div;
}
}
static void dw_mipi_dsi_set_hs_clk(struct dw_mipi_dsi *dsi, unsigned long rate)
@@ -816,9 +820,6 @@ static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host,
{
struct dw_mipi_dsi *dsi = host_to_dsi(host);
if (dsi->master)
return 0;
if (device->lanes < 1 || device->lanes > 8)
return -EINVAL;
@@ -1095,7 +1096,7 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi)
static void mipi_dphy_init(struct dw_mipi_dsi *dsi)
{
u32 map[] = {0x1, 0x3, 0x7, 0xf};
u32 map[] = {0x0, 0x1, 0x3, 0x7, 0xf};
mipi_dphy_enableclk_deassert(dsi);
mipi_dphy_shutdownz_assert(dsi);
@@ -1121,7 +1122,7 @@ static void mipi_dphy_init(struct dw_mipi_dsi *dsi)
dw_mipi_dsi_phy_init(dsi);
/* Enable Data Lane Module */
grf_field_write(dsi, ENABLE_N, map[dsi->lanes - 1]);
grf_field_write(dsi, ENABLE_N, map[dsi->lanes]);
/* Enable Clock Lane Module */
grf_field_write(dsi, ENABLECLK, 1);
@@ -1186,14 +1187,8 @@ static void dw_mipi_dsi_packet_handler_config(struct dw_mipi_dsi *dsi)
static void dw_mipi_dsi_video_packet_config(struct dw_mipi_dsi *dsi,
struct drm_display_mode *mode)
{
int pkt_size;
if (dsi->slave || dsi->master)
pkt_size = VID_PKT_SIZE(mode->hdisplay / 2);
else
pkt_size = VID_PKT_SIZE(mode->hdisplay);
regmap_write(dsi->regmap, DSI_VID_PKT_SIZE, pkt_size);
regmap_write(dsi->regmap, DSI_VID_PKT_SIZE,
VID_PKT_SIZE(mode->hdisplay));
}
static void dw_mipi_dsi_command_mode_config(struct dw_mipi_dsi *dsi)
@@ -1211,10 +1206,8 @@ static u32 dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi,
lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8;
if (dsi->mode.clock == 0) {
dev_err(dsi->dev, "dsi mode clock is 0!\n");
if (dsi->mode.clock == 0)
return 0;
}
return DIV_ROUND_CLOSEST_ULL(lbcc, dsi->mode.clock);
}
@@ -1288,8 +1281,10 @@ static void dw_mipi_dsi_encoder_mode_set(struct drm_encoder *encoder,
drm_mode_copy(&dsi->mode, adjusted_mode);
if (dsi->slave)
drm_mode_copy(&dsi->slave->mode, adjusted_mode);
if (dsi->slave) {
dsi->mode.hdisplay /= 2;
drm_mode_copy(&dsi->slave->mode, &dsi->mode);
}
}
static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
@@ -1308,14 +1303,28 @@ static void dw_mipi_dsi_disable(struct dw_mipi_dsi *dsi)
static void dw_mipi_dsi_post_disable(struct dw_mipi_dsi *dsi)
{
if (dsi->slave)
dw_mipi_dsi_post_disable(dsi->slave);
mutex_lock(&dsi->mutex);
if (!dsi->prepared) {
mutex_unlock(&dsi->mutex);
return;
}
dw_mipi_dsi_interrupt_disable(dsi);
dw_mipi_dsi_host_power_off(dsi);
mipi_dphy_power_off(dsi);
pm_runtime_put(dsi->dev);
if (dsi->slave)
dw_mipi_dsi_post_disable(dsi->slave);
dsi->prepared = false;
mutex_unlock(&dsi->mutex);
if (dsi->master)
dw_mipi_dsi_post_disable(dsi->master);
}
static void dw_mipi_dsi_encoder_disable(struct drm_encoder *encoder)
@@ -1352,6 +1361,16 @@ static void dw_mipi_dsi_host_init(struct dw_mipi_dsi *dsi)
static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi)
{
if (dsi->master)
dw_mipi_dsi_pre_enable(dsi->master);
mutex_lock(&dsi->mutex);
if (dsi->prepared) {
mutex_unlock(&dsi->mutex);
return;
}
pm_runtime_get_sync(dsi->dev);
/* MIPI DSI APB software reset request. */
@@ -1365,6 +1384,10 @@ static void dw_mipi_dsi_pre_enable(struct dw_mipi_dsi *dsi)
mipi_dphy_power_on(dsi);
dw_mipi_dsi_host_power_on(dsi);
dsi->prepared = true;
mutex_unlock(&dsi->mutex);
if (dsi->slave)
dw_mipi_dsi_pre_enable(dsi->slave);
}
@@ -1489,6 +1512,9 @@ static int dw_mipi_dsi_loader_protect(struct dw_mipi_dsi *dsi, bool on)
{
u32 int_st1;
if (dsi->master)
dw_mipi_dsi_loader_protect(dsi->master, on);
if (on) {
pm_runtime_get_sync(dsi->dev);
regmap_read(dsi->regmap, DSI_INT_ST1, &int_st1);
@@ -1573,32 +1599,6 @@ static const struct drm_connector_funcs dw_mipi_dsi_atomic_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static int dw_mipi_dsi_dual_channel_probe(struct dw_mipi_dsi *dsi)
{
struct device_node *np;
struct platform_device *secondary;
np = of_parse_phandle(dsi->dev->of_node, "rockchip,dual-channel", 0);
if (np) {
secondary = of_find_device_by_node(np);
dsi->slave = platform_get_drvdata(secondary);
of_node_put(np);
if (!dsi->slave)
return -EPROBE_DEFER;
dsi->slave->master = dsi;
dsi->lanes /= 2;
dsi->slave->lanes = dsi->lanes;
dsi->slave->channel = dsi->channel;
dsi->slave->format = dsi->format;
dsi->slave->mode_flags = dsi->mode_flags;
}
return 0;
}
static int dw_mipi_dsi_register(struct drm_device *drm,
struct dw_mipi_dsi *dsi)
{
@@ -1669,6 +1669,50 @@ encoder_cleanup:
return ret;
}
static int dw_mipi_dsi_match_by_id(struct device *dev, void *data)
{
struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
unsigned int *id = data;
return dsi->id == *id;
}
static struct dw_mipi_dsi *dw_mipi_dsi_find_by_id(struct device_driver *drv,
unsigned int id)
{
struct device *dev;
dev = driver_find_device(drv, NULL, &id, dw_mipi_dsi_match_by_id);
if (!dev)
return NULL;
return dev_get_drvdata(dev);
}
static void dw_mipi_dsi_rpm_enable(struct dw_mipi_dsi *dsi)
{
if (!pm_runtime_enabled(dsi->dev))
pm_runtime_enable(dsi->dev);
if (dsi->slave && !pm_runtime_enabled(dsi->slave->dev))
pm_runtime_enable(dsi->slave->dev);
if (dsi->master && !pm_runtime_enabled(dsi->master->dev))
pm_runtime_enable(dsi->master->dev);
}
static void dw_mipi_dsi_rpm_disable(struct dw_mipi_dsi *dsi)
{
if (pm_runtime_enabled(dsi->dev))
pm_runtime_disable(dsi->dev);
if (dsi->slave && pm_runtime_enabled(dsi->slave->dev))
pm_runtime_disable(dsi->slave->dev);
if (dsi->master && pm_runtime_enabled(dsi->master->dev))
pm_runtime_enable(dsi->master->dev);
}
static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
void *data)
{
@@ -1676,13 +1720,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
int ret;
ret = dw_mipi_dsi_dual_channel_probe(dsi);
if (ret)
return ret;
if (dsi->master)
return 0;
dsi->panel = of_drm_find_panel(dsi->client);
if (!dsi->panel) {
dsi->bridge = of_drm_find_bridge(dsi->client);
@@ -1690,6 +1727,24 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
return -EPROBE_DEFER;
}
if (dsi->id) {
dsi->master = dw_mipi_dsi_find_by_id(dev->driver, 0);
if (!dsi->master)
return -EPROBE_DEFER;
}
if (dsi->lanes > 4) {
dsi->slave = dw_mipi_dsi_find_by_id(dev->driver, 1);
if (!dsi->slave)
return -EPROBE_DEFER;
dsi->lanes /= 2;
dsi->slave->lanes = dsi->lanes;
dsi->slave->channel = dsi->channel;
dsi->slave->format = dsi->format;
dsi->slave->mode_flags = dsi->mode_flags;
}
ret = dw_mipi_dsi_register(drm, dsi);
if (ret) {
dev_err(dev, "Failed to register mipi_dsi: %d\n", ret);
@@ -1698,9 +1753,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
dev_set_drvdata(dev, dsi);
pm_runtime_enable(dev);
if (dsi->slave)
pm_runtime_enable(dsi->slave->dev);
dw_mipi_dsi_rpm_enable(dsi);
return ret;
}
@@ -1710,12 +1763,10 @@ static void dw_mipi_dsi_unbind(struct device *dev, struct device *master,
{
struct dw_mipi_dsi *dsi = dev_get_drvdata(dev);
dw_mipi_dsi_rpm_disable(dsi);
if (dsi->panel)
drm_panel_detach(dsi->panel);
pm_runtime_disable(dev);
if (dsi->slave)
pm_runtime_disable(dsi->slave->dev);
}
static const struct component_ops dw_mipi_dsi_ops = {
@@ -1898,6 +1949,8 @@ static int dw_mipi_dsi_probe(struct platform_device *pdev)
if (!dsi)
return -ENOMEM;
mutex_init(&dsi->mutex);
dsi_id = of_alias_get_id(np, "dsi");
if (dsi_id < 0)
dsi_id = 0;