mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-29 23:53:32 +00:00
Merge tag 'drm-misc-fixes-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
drm-misc-fixes for -rc2 - big pile of bridge driver (mostly tc358767), all handled by Archit and Andrez - rockchip dsi fix - atomic helper regression fix for spurious -EBUSY (Maarten) - fix deferred fbdev fallout (Maarten) * tag 'drm-misc-fixes-2017-11-30' of git://anongit.freedesktop.org/drm/drm-misc: drm/bridge: tc358767: fix 1-lane behavior drm/bridge: tc358767: fix AUXDATAn registers access drm/bridge: tc358767: fix timing calculations drm/bridge: tc358767: fix DP0_MISC register set drm/bridge: tc358767: filter out too high modes drm/bridge: tc358767: do no fail on hi-res displays drm/bridge: Fix lvds-encoder since the panel_bridge rework. drm/bridge: synopsys/dw-hdmi: Enable cec clock drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling drm/fb_helper: Disable all crtc's when initial setup fails. drm/atomic: make drm_atomic_helper_wait_for_vblanks more agressive drm/rockchip: dw-mipi-dsi: fix possible un-balanced runtime PM enable
This commit is contained in:
commit
e4b2eb13e0
9 changed files with 149 additions and 68 deletions
|
@ -372,9 +372,18 @@ struct adv7511 {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
|
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
|
||||||
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
|
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511);
|
||||||
unsigned int offset);
|
|
||||||
void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
|
void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
|
||||||
|
#else
|
||||||
|
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||||
|
{
|
||||||
|
unsigned int offset = adv7511->type == ADV7533 ?
|
||||||
|
ADV7533_REG_CEC_OFFSET : 0;
|
||||||
|
|
||||||
|
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
|
||||||
|
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_I2C_ADV7533
|
#ifdef CONFIG_DRM_I2C_ADV7533
|
||||||
|
|
|
@ -300,18 +300,21 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
|
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||||
unsigned int offset)
|
|
||||||
{
|
{
|
||||||
|
unsigned int offset = adv7511->type == ADV7533 ?
|
||||||
|
ADV7533_REG_CEC_OFFSET : 0;
|
||||||
int ret = adv7511_cec_parse_dt(dev, adv7511);
|
int ret = adv7511_cec_parse_dt(dev, adv7511);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto err_cec_parse_dt;
|
||||||
|
|
||||||
adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
|
adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
|
||||||
adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
|
adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
|
||||||
if (IS_ERR(adv7511->cec_adap))
|
if (IS_ERR(adv7511->cec_adap)) {
|
||||||
return PTR_ERR(adv7511->cec_adap);
|
ret = PTR_ERR(adv7511->cec_adap);
|
||||||
|
goto err_cec_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
|
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
|
||||||
/* cec soft reset */
|
/* cec soft reset */
|
||||||
|
@ -329,9 +332,18 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
|
||||||
((adv7511->cec_clk_freq / 750000) - 1) << 2);
|
((adv7511->cec_clk_freq / 750000) - 1) << 2);
|
||||||
|
|
||||||
ret = cec_register_adapter(adv7511->cec_adap, dev);
|
ret = cec_register_adapter(adv7511->cec_adap, dev);
|
||||||
if (ret) {
|
if (ret)
|
||||||
cec_delete_adapter(adv7511->cec_adap);
|
goto err_cec_register;
|
||||||
adv7511->cec_adap = NULL;
|
return 0;
|
||||||
}
|
|
||||||
return ret;
|
err_cec_register:
|
||||||
|
cec_delete_adapter(adv7511->cec_adap);
|
||||||
|
adv7511->cec_adap = NULL;
|
||||||
|
err_cec_alloc:
|
||||||
|
dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
|
||||||
|
ret);
|
||||||
|
err_cec_parse_dt:
|
||||||
|
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
|
||||||
|
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||||
|
return ret == -EPROBE_DEFER ? ret : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1084,7 +1084,6 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
||||||
struct device *dev = &i2c->dev;
|
struct device *dev = &i2c->dev;
|
||||||
unsigned int main_i2c_addr = i2c->addr << 1;
|
unsigned int main_i2c_addr = i2c->addr << 1;
|
||||||
unsigned int edid_i2c_addr = main_i2c_addr + 4;
|
unsigned int edid_i2c_addr = main_i2c_addr + 4;
|
||||||
unsigned int offset;
|
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -1192,24 +1191,16 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
|
||||||
if (adv7511->type == ADV7511)
|
if (adv7511->type == ADV7511)
|
||||||
adv7511_set_link_config(adv7511, &link_config);
|
adv7511_set_link_config(adv7511, &link_config);
|
||||||
|
|
||||||
|
ret = adv7511_cec_init(dev, adv7511);
|
||||||
|
if (ret)
|
||||||
|
goto err_unregister_cec;
|
||||||
|
|
||||||
adv7511->bridge.funcs = &adv7511_bridge_funcs;
|
adv7511->bridge.funcs = &adv7511_bridge_funcs;
|
||||||
adv7511->bridge.of_node = dev->of_node;
|
adv7511->bridge.of_node = dev->of_node;
|
||||||
|
|
||||||
drm_bridge_add(&adv7511->bridge);
|
drm_bridge_add(&adv7511->bridge);
|
||||||
|
|
||||||
adv7511_audio_init(dev, adv7511);
|
adv7511_audio_init(dev, adv7511);
|
||||||
|
|
||||||
offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;
|
|
||||||
|
|
||||||
#ifdef CONFIG_DRM_I2C_ADV7511_CEC
|
|
||||||
ret = adv7511_cec_init(dev, adv7511, offset);
|
|
||||||
if (ret)
|
|
||||||
goto err_unregister_cec;
|
|
||||||
#else
|
|
||||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
|
|
||||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_unregister_cec:
|
err_unregister_cec:
|
||||||
|
|
|
@ -13,13 +13,37 @@
|
||||||
|
|
||||||
#include <linux/of_graph.h>
|
#include <linux/of_graph.h>
|
||||||
|
|
||||||
|
struct lvds_encoder {
|
||||||
|
struct drm_bridge bridge;
|
||||||
|
struct drm_bridge *panel_bridge;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int lvds_encoder_attach(struct drm_bridge *bridge)
|
||||||
|
{
|
||||||
|
struct lvds_encoder *lvds_encoder = container_of(bridge,
|
||||||
|
struct lvds_encoder,
|
||||||
|
bridge);
|
||||||
|
|
||||||
|
return drm_bridge_attach(bridge->encoder, lvds_encoder->panel_bridge,
|
||||||
|
bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_bridge_funcs funcs = {
|
||||||
|
.attach = lvds_encoder_attach,
|
||||||
|
};
|
||||||
|
|
||||||
static int lvds_encoder_probe(struct platform_device *pdev)
|
static int lvds_encoder_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device_node *port;
|
struct device_node *port;
|
||||||
struct device_node *endpoint;
|
struct device_node *endpoint;
|
||||||
struct device_node *panel_node;
|
struct device_node *panel_node;
|
||||||
struct drm_panel *panel;
|
struct drm_panel *panel;
|
||||||
struct drm_bridge *bridge;
|
struct lvds_encoder *lvds_encoder;
|
||||||
|
|
||||||
|
lvds_encoder = devm_kzalloc(&pdev->dev, sizeof(*lvds_encoder),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!lvds_encoder)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Locate the panel DT node. */
|
/* Locate the panel DT node. */
|
||||||
port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
|
port = of_graph_get_port_by_id(pdev->dev.of_node, 1);
|
||||||
|
@ -49,20 +73,30 @@ static int lvds_encoder_probe(struct platform_device *pdev)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
bridge = drm_panel_bridge_add(panel, DRM_MODE_CONNECTOR_LVDS);
|
lvds_encoder->panel_bridge =
|
||||||
if (IS_ERR(bridge))
|
devm_drm_panel_bridge_add(&pdev->dev,
|
||||||
return PTR_ERR(bridge);
|
panel, DRM_MODE_CONNECTOR_LVDS);
|
||||||
|
if (IS_ERR(lvds_encoder->panel_bridge))
|
||||||
|
return PTR_ERR(lvds_encoder->panel_bridge);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, bridge);
|
/* The panel_bridge bridge is attached to the panel's of_node,
|
||||||
|
* but we need a bridge attached to our of_node for our user
|
||||||
|
* to look up.
|
||||||
|
*/
|
||||||
|
lvds_encoder->bridge.of_node = pdev->dev.of_node;
|
||||||
|
lvds_encoder->bridge.funcs = &funcs;
|
||||||
|
drm_bridge_add(&lvds_encoder->bridge);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, lvds_encoder);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lvds_encoder_remove(struct platform_device *pdev)
|
static int lvds_encoder_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct drm_bridge *bridge = platform_get_drvdata(pdev);
|
struct lvds_encoder *lvds_encoder = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
drm_bridge_remove(bridge);
|
drm_bridge_remove(&lvds_encoder->bridge);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,7 @@ struct dw_hdmi {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *isfr_clk;
|
struct clk *isfr_clk;
|
||||||
struct clk *iahb_clk;
|
struct clk *iahb_clk;
|
||||||
|
struct clk *cec_clk;
|
||||||
struct dw_hdmi_i2c *i2c;
|
struct dw_hdmi_i2c *i2c;
|
||||||
|
|
||||||
struct hdmi_data_info hdmi_data;
|
struct hdmi_data_info hdmi_data;
|
||||||
|
@ -2382,6 +2383,26 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
||||||
goto err_isfr;
|
goto err_isfr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hdmi->cec_clk = devm_clk_get(hdmi->dev, "cec");
|
||||||
|
if (PTR_ERR(hdmi->cec_clk) == -ENOENT) {
|
||||||
|
hdmi->cec_clk = NULL;
|
||||||
|
} else if (IS_ERR(hdmi->cec_clk)) {
|
||||||
|
ret = PTR_ERR(hdmi->cec_clk);
|
||||||
|
if (ret != -EPROBE_DEFER)
|
||||||
|
dev_err(hdmi->dev, "Cannot get HDMI cec clock: %d\n",
|
||||||
|
ret);
|
||||||
|
|
||||||
|
hdmi->cec_clk = NULL;
|
||||||
|
goto err_iahb;
|
||||||
|
} else {
|
||||||
|
ret = clk_prepare_enable(hdmi->cec_clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(hdmi->dev, "Cannot enable HDMI cec clock: %d\n",
|
||||||
|
ret);
|
||||||
|
goto err_iahb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Product and revision IDs */
|
/* Product and revision IDs */
|
||||||
hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
hdmi->version = (hdmi_readb(hdmi, HDMI_DESIGN_ID) << 8)
|
||||||
| (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
| (hdmi_readb(hdmi, HDMI_REVISION_ID) << 0);
|
||||||
|
@ -2518,6 +2539,8 @@ __dw_hdmi_probe(struct platform_device *pdev,
|
||||||
cec_notifier_put(hdmi->cec_notifier);
|
cec_notifier_put(hdmi->cec_notifier);
|
||||||
|
|
||||||
clk_disable_unprepare(hdmi->iahb_clk);
|
clk_disable_unprepare(hdmi->iahb_clk);
|
||||||
|
if (hdmi->cec_clk)
|
||||||
|
clk_disable_unprepare(hdmi->cec_clk);
|
||||||
err_isfr:
|
err_isfr:
|
||||||
clk_disable_unprepare(hdmi->isfr_clk);
|
clk_disable_unprepare(hdmi->isfr_clk);
|
||||||
err_res:
|
err_res:
|
||||||
|
@ -2541,6 +2564,8 @@ static void __dw_hdmi_remove(struct dw_hdmi *hdmi)
|
||||||
|
|
||||||
clk_disable_unprepare(hdmi->iahb_clk);
|
clk_disable_unprepare(hdmi->iahb_clk);
|
||||||
clk_disable_unprepare(hdmi->isfr_clk);
|
clk_disable_unprepare(hdmi->isfr_clk);
|
||||||
|
if (hdmi->cec_clk)
|
||||||
|
clk_disable_unprepare(hdmi->cec_clk);
|
||||||
|
|
||||||
if (hdmi->i2c)
|
if (hdmi->i2c)
|
||||||
i2c_del_adapter(&hdmi->i2c->adap);
|
i2c_del_adapter(&hdmi->i2c->adap);
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
#define DP0_ACTIVEVAL 0x0650
|
#define DP0_ACTIVEVAL 0x0650
|
||||||
#define DP0_SYNCVAL 0x0654
|
#define DP0_SYNCVAL 0x0654
|
||||||
#define DP0_MISC 0x0658
|
#define DP0_MISC 0x0658
|
||||||
#define TU_SIZE_RECOMMENDED (0x3f << 16) /* LSCLK cycles per TU */
|
#define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */
|
||||||
#define BPC_6 (0 << 5)
|
#define BPC_6 (0 << 5)
|
||||||
#define BPC_8 (1 << 5)
|
#define BPC_8 (1 << 5)
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
|
||||||
tmp = (tmp << 8) | buf[i];
|
tmp = (tmp << 8) | buf[i];
|
||||||
i++;
|
i++;
|
||||||
if (((i % 4) == 0) || (i == size)) {
|
if (((i % 4) == 0) || (i == size)) {
|
||||||
tc_write(DP0_AUXWDATA(i >> 2), tmp);
|
tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp);
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,8 +603,15 @@ static int tc_get_display_props(struct tc_data *tc)
|
||||||
ret = drm_dp_link_probe(&tc->aux, &tc->link.base);
|
ret = drm_dp_link_probe(&tc->aux, &tc->link.base);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_dpcd_read;
|
goto err_dpcd_read;
|
||||||
if ((tc->link.base.rate != 162000) && (tc->link.base.rate != 270000))
|
if (tc->link.base.rate != 162000 && tc->link.base.rate != 270000) {
|
||||||
goto err_dpcd_inval;
|
dev_dbg(tc->dev, "Falling to 2.7 Gbps rate\n");
|
||||||
|
tc->link.base.rate = 270000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tc->link.base.num_lanes > 2) {
|
||||||
|
dev_dbg(tc->dev, "Falling to 2 lanes\n");
|
||||||
|
tc->link.base.num_lanes = 2;
|
||||||
|
}
|
||||||
|
|
||||||
ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
|
ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -637,9 +644,6 @@ static int tc_get_display_props(struct tc_data *tc)
|
||||||
err_dpcd_read:
|
err_dpcd_read:
|
||||||
dev_err(tc->dev, "failed to read DPCD: %d\n", ret);
|
dev_err(tc->dev, "failed to read DPCD: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
err_dpcd_inval:
|
|
||||||
dev_err(tc->dev, "invalid DPCD\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||||
|
@ -655,6 +659,14 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||||
int lower_margin = mode->vsync_start - mode->vdisplay;
|
int lower_margin = mode->vsync_start - mode->vdisplay;
|
||||||
int vsync_len = mode->vsync_end - mode->vsync_start;
|
int vsync_len = mode->vsync_end - mode->vsync_start;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recommended maximum number of symbols transferred in a transfer unit:
|
||||||
|
* DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
|
||||||
|
* (output active video bandwidth in bytes))
|
||||||
|
* Must be less than tu_size.
|
||||||
|
*/
|
||||||
|
max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
|
||||||
|
|
||||||
dev_dbg(tc->dev, "set mode %dx%d\n",
|
dev_dbg(tc->dev, "set mode %dx%d\n",
|
||||||
mode->hdisplay, mode->vdisplay);
|
mode->hdisplay, mode->vdisplay);
|
||||||
dev_dbg(tc->dev, "H margin %d,%d sync %d\n",
|
dev_dbg(tc->dev, "H margin %d,%d sync %d\n",
|
||||||
|
@ -664,13 +676,18 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||||
dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
|
dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
|
||||||
|
|
||||||
|
|
||||||
/* LCD Ctl Frame Size */
|
/*
|
||||||
tc_write(VPCTRL0, (0x40 << 20) /* VSDELAY */ |
|
* LCD Ctl Frame Size
|
||||||
|
* datasheet is not clear of vsdelay in case of DPI
|
||||||
|
* assume we do not need any delay when DPI is a source of
|
||||||
|
* sync signals
|
||||||
|
*/
|
||||||
|
tc_write(VPCTRL0, (0 << 20) /* VSDELAY */ |
|
||||||
OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
|
OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
|
||||||
tc_write(HTIM01, (left_margin << 16) | /* H back porch */
|
tc_write(HTIM01, (ALIGN(left_margin, 2) << 16) | /* H back porch */
|
||||||
(hsync_len << 0)); /* Hsync */
|
(ALIGN(hsync_len, 2) << 0)); /* Hsync */
|
||||||
tc_write(HTIM02, (right_margin << 16) | /* H front porch */
|
tc_write(HTIM02, (ALIGN(right_margin, 2) << 16) | /* H front porch */
|
||||||
(mode->hdisplay << 0)); /* width */
|
(ALIGN(mode->hdisplay, 2) << 0)); /* width */
|
||||||
tc_write(VTIM01, (upper_margin << 16) | /* V back porch */
|
tc_write(VTIM01, (upper_margin << 16) | /* V back porch */
|
||||||
(vsync_len << 0)); /* Vsync */
|
(vsync_len << 0)); /* Vsync */
|
||||||
tc_write(VTIM02, (lower_margin << 16) | /* V front porch */
|
tc_write(VTIM02, (lower_margin << 16) | /* V front porch */
|
||||||
|
@ -689,7 +706,7 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||||
/* DP Main Stream Attributes */
|
/* DP Main Stream Attributes */
|
||||||
vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
|
vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
|
||||||
tc_write(DP0_VIDSYNCDELAY,
|
tc_write(DP0_VIDSYNCDELAY,
|
||||||
(0x003e << 16) | /* thresh_dly */
|
(max_tu_symbol << 16) | /* thresh_dly */
|
||||||
(vid_sync_dly << 0));
|
(vid_sync_dly << 0));
|
||||||
|
|
||||||
tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal));
|
tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal));
|
||||||
|
@ -705,14 +722,8 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
|
||||||
tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
|
tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
|
||||||
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
|
DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
|
||||||
|
|
||||||
/*
|
tc_write(DP0_MISC, (max_tu_symbol << 23) | (TU_SIZE_RECOMMENDED << 16) |
|
||||||
* Recommended maximum number of symbols transferred in a transfer unit:
|
BPC_8);
|
||||||
* DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
|
|
||||||
* (output active video bandwidth in bytes))
|
|
||||||
* Must be less than tu_size.
|
|
||||||
*/
|
|
||||||
max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
|
|
||||||
tc_write(DP0_MISC, (max_tu_symbol << 23) | TU_SIZE_RECOMMENDED | BPC_8);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
|
@ -808,8 +819,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||||
unsigned int rate;
|
unsigned int rate;
|
||||||
u32 dp_phy_ctrl;
|
u32 dp_phy_ctrl;
|
||||||
int timeout;
|
int timeout;
|
||||||
bool aligned;
|
|
||||||
bool ready;
|
|
||||||
u32 value;
|
u32 value;
|
||||||
int ret;
|
int ret;
|
||||||
u8 tmp[8];
|
u8 tmp[8];
|
||||||
|
@ -954,16 +963,15 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||||
ret = drm_dp_dpcd_read_link_status(aux, tmp + 2);
|
ret = drm_dp_dpcd_read_link_status(aux, tmp + 2);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_dpcd_read;
|
goto err_dpcd_read;
|
||||||
ready = (tmp[2] == ((DP_CHANNEL_EQ_BITS << 4) | /* Lane1 */
|
} while ((--timeout) &&
|
||||||
DP_CHANNEL_EQ_BITS)); /* Lane0 */
|
!(drm_dp_channel_eq_ok(tmp + 2, tc->link.base.num_lanes)));
|
||||||
aligned = tmp[4] & DP_INTERLANE_ALIGN_DONE;
|
|
||||||
} while ((--timeout) && !(ready && aligned));
|
|
||||||
|
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
/* Read DPCD 0x200-0x201 */
|
/* Read DPCD 0x200-0x201 */
|
||||||
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2);
|
ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto err_dpcd_read;
|
goto err_dpcd_read;
|
||||||
|
dev_err(dev, "channel(s) EQ not ok\n");
|
||||||
dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]);
|
dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]);
|
||||||
dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n",
|
dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n",
|
||||||
tmp[1]);
|
tmp[1]);
|
||||||
|
@ -974,10 +982,6 @@ static int tc_main_link_setup(struct tc_data *tc)
|
||||||
dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n",
|
dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n",
|
||||||
tmp[6]);
|
tmp[6]);
|
||||||
|
|
||||||
if (!ready)
|
|
||||||
dev_err(dev, "Lane0/1 not ready\n");
|
|
||||||
if (!aligned)
|
|
||||||
dev_err(dev, "Lane0/1 not aligned\n");
|
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,7 +1103,10 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||||
static int tc_connector_mode_valid(struct drm_connector *connector,
|
static int tc_connector_mode_valid(struct drm_connector *connector,
|
||||||
struct drm_display_mode *mode)
|
struct drm_display_mode *mode)
|
||||||
{
|
{
|
||||||
/* Accept any mode */
|
/* DPI interface clock limitation: upto 154 MHz */
|
||||||
|
if (mode->clock > 154000)
|
||||||
|
return MODE_CLOCK_HIGH;
|
||||||
|
|
||||||
return MODE_OK;
|
return MODE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1225,7 +1225,7 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
for_each_oldnew_crtc_in_state(old_state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||||
if (!new_crtc_state->active || !new_crtc_state->planes_changed)
|
if (!new_crtc_state->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ret = drm_crtc_vblank_get(crtc);
|
ret = drm_crtc_vblank_get(crtc);
|
||||||
|
|
|
@ -1809,6 +1809,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||||
|
|
||||||
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
if (crtc_count == 0 || sizes.fb_width == -1 || sizes.fb_height == -1) {
|
||||||
DRM_INFO("Cannot find any crtc or sizes\n");
|
DRM_INFO("Cannot find any crtc or sizes\n");
|
||||||
|
|
||||||
|
/* First time: disable all crtc's.. */
|
||||||
|
if (!fb_helper->deferred_setup && !READ_ONCE(fb_helper->dev->master))
|
||||||
|
restore_fbdev_mode(fb_helper);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1285,8 +1285,6 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
|
||||||
goto err_pllref;
|
goto err_pllref;
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_runtime_enable(dev);
|
|
||||||
|
|
||||||
dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
|
dsi->dsi_host.ops = &dw_mipi_dsi_host_ops;
|
||||||
dsi->dsi_host.dev = dev;
|
dsi->dsi_host.dev = dev;
|
||||||
ret = mipi_dsi_host_register(&dsi->dsi_host);
|
ret = mipi_dsi_host_register(&dsi->dsi_host);
|
||||||
|
@ -1301,6 +1299,7 @@ static int dw_mipi_dsi_bind(struct device *dev, struct device *master,
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_set_drvdata(dev, dsi);
|
dev_set_drvdata(dev, dsi);
|
||||||
|
pm_runtime_enable(dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_mipi_dsi_host:
|
err_mipi_dsi_host:
|
||||||
|
|
Loading…
Reference in a new issue