From 05b8bba67f0029d9143a21b7dd598178267c6db6 Mon Sep 17 00:00:00 2001 From: Shunqing Chen Date: Mon, 21 Sep 2020 15:55:31 +0800 Subject: [PATCH] drm/rockchip/rk628: Add scaler functions. Signed-off-by: Shunqing Chen Change-Id: Ia08c718e0a0967f69922f5a6ca11aacddcb09e2b --- .../drm/rockchip/rk628/rk628_post_process.c | 68 ++++++++++++++++++- include/linux/mfd/rk628.h | 24 +++++++ 2 files changed, 90 insertions(+), 2 deletions(-) mode change 100644 => 100755 include/linux/mfd/rk628.h diff --git a/drivers/gpu/drm/rockchip/rk628/rk628_post_process.c b/drivers/gpu/drm/rockchip/rk628/rk628_post_process.c index 1b7bad122717..686a33848004 100644 --- a/drivers/gpu/drm/rockchip/rk628/rk628_post_process.c +++ b/drivers/gpu/drm/rockchip/rk628/rk628_post_process.c @@ -30,6 +30,7 @@ struct rk628_post_process { struct reset_control *rstc_decoder; struct reset_control *rstc_clk_rx; struct reset_control *rstc_vop; + struct rk628 *parent; }; static inline struct rk628_post_process *bridge_to_pp(struct drm_bridge *bridge) @@ -260,11 +261,12 @@ static void rk628_post_process_bridge_mode_set(struct drm_bridge *bridge, struct drm_display_mode *adj) { struct rk628_post_process *pp = bridge_to_pp(bridge); + struct rk628 *rk628 = pp->parent; drm_mode_copy(&pp->src_mode, adj); - if (pp->bridge->driver_private) - drm_mode_copy(&pp->dst_mode, pp->bridge->driver_private); + if (rk628->dst_mode_valid) + drm_mode_copy(&pp->dst_mode, &rk628->dst_mode); else drm_mode_copy(&pp->dst_mode, &pp->src_mode); } @@ -311,11 +313,69 @@ static const struct drm_bridge_funcs rk628_post_process_bridge_funcs = { .attach = rk628_post_process_bridge_attach, }; + +/** + * rk628_scaler_add_src_mode - add source mode for scaler + * @rk628: parent device + * @connector: DRM connector + * If need scale, call the function at last of get_modes. + */ +int rk628_scaler_add_src_mode(struct rk628 *rk628, + struct drm_connector *connector) +{ + struct drm_display_mode *pmode; + struct drm_display_mode *dst; + + if (!rk628 || !connector) + return 0; + + if (drm_mode_validate_driver(connector->dev, &rk628->src_mode) != + MODE_OK) + return 0; + + list_for_each_entry(pmode, &connector->probed_modes, head) { + if (pmode->type & DRM_MODE_TYPE_PREFERRED) { + drm_mode_copy(&rk628->dst_mode, pmode); + drm_mode_copy(pmode, &rk628->src_mode); + pmode->type |= DRM_MODE_TYPE_PREFERRED; + rk628->dst_mode_valid = true; + break; + } + } + if (rk628->dst_mode_valid) { + dst = drm_mode_duplicate(connector->dev, &rk628->dst_mode); + dst->type &= ~DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, dst); + return 1; + } + + return 0; +} +EXPORT_SYMBOL(rk628_scaler_add_src_mode); + +/** + * rk628_mode_copy - rk628 mode copy + * @rk628: parent device + * @dst: dst mode + * @src: src mode + * Call the function at mode_set, replace drm_mode_copy. + */ +void rk628_mode_copy(struct rk628 *rk628, struct drm_display_mode *dst, + struct drm_display_mode *src) +{ + if (rk628->dst_mode_valid) + drm_mode_copy(dst, &rk628->dst_mode); + else + drm_mode_copy(dst, src); +} +EXPORT_SYMBOL(rk628_mode_copy); + static int rk628_post_process_probe(struct platform_device *pdev) { struct rk628 *rk628 = dev_get_drvdata(pdev->dev.parent); struct device *dev = &pdev->dev; struct rk628_post_process *pp; + u32 bus_flags; int ret; if (!of_device_is_available(dev->of_node)) @@ -328,6 +388,7 @@ static int rk628_post_process_probe(struct platform_device *pdev) pp->dev = dev; pp->grf = rk628->grf; platform_set_drvdata(pdev, pp); + pp->parent = rk628; pp->sclk_vop = devm_clk_get(dev, "sclk_vop"); if (IS_ERR(pp->sclk_vop)) { @@ -368,6 +429,9 @@ static int rk628_post_process_probe(struct platform_device *pdev) pp->base.of_node = dev->of_node; drm_bridge_add(&pp->base); + of_get_drm_display_mode(dev->of_node, &rk628->src_mode, &bus_flags, + OF_USE_NATIVE_MODE); + return 0; } diff --git a/include/linux/mfd/rk628.h b/include/linux/mfd/rk628.h old mode 100644 new mode 100755 index 27b5eb3b8bd9..ef1885620603 --- a/include/linux/mfd/rk628.h +++ b/include/linux/mfd/rk628.h @@ -14,6 +14,8 @@ #include #include +#include + #define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK((h), (l)) << 16)) @@ -224,6 +226,28 @@ struct rk628 { struct gpio_desc *reset_gpio; struct gpio_desc *enable_gpio; struct rk628_irq_chip_data *irq_data; + struct drm_display_mode src_mode; + struct drm_display_mode dst_mode; + bool dst_mode_valid; }; +/** + * rk628_scaler_add_src_mode - add source mode for scaler + * @rk628: parent device + * @connector: DRM connector + * If need scale, call the function at last of get_modes. + */ +int rk628_scaler_add_src_mode(struct rk628 *rk628, + struct drm_connector *connector); + +/** + * rk628_mode_copy - rk628 mode copy + * @rk628: parent device + * @dst: dst mode + * @src: src mode + * Call the function at mode_set, replace drm_mode_copy. + */ +void rk628_mode_copy(struct rk628 *rk628, struct drm_display_mode *dst, + struct drm_display_mode *src); + #endif