mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
drm/rockchip: tve: add .loader_protect() support for tve
If logo display enabled, the rockchip_tve_encoder_loader_protect() helps to set the tve enable/disable status and call pm_runtime_get_sync()/pm_runtime_put(), which allows for the continuation of the display state from the U-Boot stage. In addition, fix the check of tve mode setting in .mode_set() to avoid display flashing, which caused by the off/on switch of dac. Change-Id: I6f1fcaf05cb6e362ce375e447c566fb5356c5380 Signed-off-by: Damon Ding <damon.ding@rock-chips.com>
This commit is contained in:
@@ -486,15 +486,17 @@ static void rockchip_tve_encoder_mode_set(struct drm_encoder *encoder,
|
|||||||
struct drm_display_mode *adjusted_mode)
|
struct drm_display_mode *adjusted_mode)
|
||||||
{
|
{
|
||||||
struct rockchip_tve *tve = encoder_to_tve(encoder);
|
struct rockchip_tve *tve = encoder_to_tve(encoder);
|
||||||
|
u32 tv_format;
|
||||||
|
|
||||||
dev_dbg(tve->dev, "encoder mode set:%s\n", adjusted_mode->name);
|
dev_dbg(tve->dev, "encoder mode set:%s\n", adjusted_mode->name);
|
||||||
|
|
||||||
if (adjusted_mode->vdisplay == 576)
|
if (adjusted_mode->vdisplay == 576)
|
||||||
tve->tv_format = TVOUT_CVBS_PAL;
|
tv_format = TVOUT_CVBS_PAL;
|
||||||
else
|
else
|
||||||
tve->tv_format = TVOUT_CVBS_NTSC;
|
tv_format = TVOUT_CVBS_NTSC;
|
||||||
|
|
||||||
if (tve->enable) {
|
if (tve->enable && tve->tv_format != tv_format) {
|
||||||
|
tve->tv_format = tv_format;
|
||||||
dac_enable(tve, false);
|
dac_enable(tve, false);
|
||||||
msleep(200);
|
msleep(200);
|
||||||
|
|
||||||
@@ -541,6 +543,81 @@ rockchip_tve_encoder_atomic_check(struct drm_encoder *encoder,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rockchip_tve_encoder_loader_protect(struct drm_encoder *encoder, bool on)
|
||||||
|
{
|
||||||
|
struct rockchip_tve *tve = encoder_to_tve(encoder);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
ret = pm_runtime_get_sync(tve->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(tve->dev, "failed to get pm runtime: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tve->aclk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(tve->dev, "Cannot enable tve aclk: %d\n", ret);
|
||||||
|
goto err_pm_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tve->hclk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(tve->dev, "Cannot enable tve hclk: %d\n", ret);
|
||||||
|
goto err_disable_aclk;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tve->pclk_vdac);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(tve->dev, "Cannot enable vdac pclk: %d\n", ret);
|
||||||
|
goto err_disable_hclk;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tve->dclk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(tve->dev, "Cannot enable tve dclk: %d\n", ret);
|
||||||
|
goto err_disable_pclk;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(tve->dclk_4x);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(tve->dev, "Cannot enable tve dclk_4x: %d\n", ret);
|
||||||
|
goto err_disable_dclk;
|
||||||
|
}
|
||||||
|
|
||||||
|
tve->enable = 1;
|
||||||
|
} else {
|
||||||
|
ret = pm_runtime_put(tve->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(tve->dev, "failed to put pm runtime: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_disable_unprepare(tve->dclk_4x);
|
||||||
|
clk_disable_unprepare(tve->dclk);
|
||||||
|
clk_disable_unprepare(tve->pclk_vdac);
|
||||||
|
clk_disable_unprepare(tve->hclk);
|
||||||
|
clk_disable_unprepare(tve->aclk);
|
||||||
|
|
||||||
|
tve->enable = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_disable_dclk:
|
||||||
|
clk_disable_unprepare(tve->dclk);
|
||||||
|
err_disable_pclk:
|
||||||
|
clk_disable_unprepare(tve->pclk_vdac);
|
||||||
|
err_disable_hclk:
|
||||||
|
clk_disable_unprepare(tve->hclk);
|
||||||
|
err_disable_aclk:
|
||||||
|
clk_disable_unprepare(tve->aclk);
|
||||||
|
err_pm_put:
|
||||||
|
pm_runtime_put_sync(tve->dev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_connector_helper_funcs
|
static const struct drm_connector_helper_funcs
|
||||||
rockchip_tve_connector_helper_funcs = {
|
rockchip_tve_connector_helper_funcs = {
|
||||||
.mode_valid = rockchip_tve_mode_valid,
|
.mode_valid = rockchip_tve_mode_valid,
|
||||||
@@ -1006,6 +1083,7 @@ static int rockchip_tve_bind(struct device *dev, struct device *master,
|
|||||||
}
|
}
|
||||||
tve->sub_dev.connector = &tve->connector;
|
tve->sub_dev.connector = &tve->connector;
|
||||||
tve->sub_dev.of_node = tve->dev->of_node;
|
tve->sub_dev.of_node = tve->dev->of_node;
|
||||||
|
tve->sub_dev.loader_protect = rockchip_tve_encoder_loader_protect;
|
||||||
rockchip_drm_register_sub_dev(&tve->sub_dev);
|
rockchip_drm_register_sub_dev(&tve->sub_dev);
|
||||||
|
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
|
|||||||
Reference in New Issue
Block a user