From e847ed9deb20397f338d600b7830ddc25d0d6e98 Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Tue, 20 Dec 2022 17:40:08 +0800 Subject: [PATCH 1/9] drm/rockchip: vop3: update acm info when it change When update acm info, it need disable acm function in the first frame, then update the acm info and enable acm function in the second frame. If the acm info is not changed between 2 frames, it don't need update. Signed-off-by: Zhang Yubing Change-Id: Iaedead2fad5951844ca07b037c3588071499e50a --- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 31 ++++++++++++++ drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 31 -------------- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 45 ++++++++++++++------ drivers/gpu/drm/rockchip/rockchip_post_csc.c | 1 - drivers/gpu/drm/rockchip/rockchip_post_csc.h | 1 + drivers/gpu/drm/rockchip/rockchip_vop_reg.h | 2 + 6 files changed, 66 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 153ccd07de52..4030bfdb0efd 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -184,6 +184,37 @@ struct rockchip_dsc_sink_cap { u16 target_bits_per_pixel_x16; }; +#define ACM_GAIN_LUT_HY_LENGTH (9*17) +#define ACM_GAIN_LUT_HY_TOTAL_LENGTH (ACM_GAIN_LUT_HY_LENGTH * 3) +#define ACM_GAIN_LUT_HS_LENGTH (13*17) +#define ACM_GAIN_LUT_HS_TOTAL_LENGTH (ACM_GAIN_LUT_HS_LENGTH * 3) +#define ACM_DELTA_LUT_H_LENGTH 65 +#define ACM_DELTA_LUT_H_TOTAL_LENGTH (ACM_DELTA_LUT_H_LENGTH * 3) + +struct post_acm { + s16 delta_lut_h[ACM_DELTA_LUT_H_TOTAL_LENGTH]; + s16 gain_lut_hy[ACM_GAIN_LUT_HY_TOTAL_LENGTH]; + s16 gain_lut_hs[ACM_GAIN_LUT_HS_TOTAL_LENGTH]; + u16 y_gain; + u16 h_gain; + u16 s_gain; + u16 acm_enable; +}; + +struct post_csc { + u16 hue; + u16 saturation; + u16 contrast; + u16 brightness; + u16 r_gain; + u16 g_gain; + u16 b_gain; + u16 r_offset; + u16 g_offset; + u16 b_offset; + u16 csc_enable; +}; + struct rockchip_crtc_state { struct drm_crtc_state base; int vp_id; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 3243b0cec6ea..6ff1a20e5be3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -597,37 +597,6 @@ enum vop_hdr_format { HDR_FORMAT_MAX, }; -#define ACM_GAIN_LUT_HY_LENGTH (9*17) -#define ACM_GAIN_LUT_HY_TOTAL_LENGTH (ACM_GAIN_LUT_HY_LENGTH * 3) -#define ACM_GAIN_LUT_HS_LENGTH (13*17) -#define ACM_GAIN_LUT_HS_TOTAL_LENGTH (ACM_GAIN_LUT_HS_LENGTH * 3) -#define ACM_DELTA_LUT_H_LENGTH 65 -#define ACM_DELTA_LUT_H_TOTAL_LENGTH (ACM_DELTA_LUT_H_LENGTH * 3) - -struct post_acm { - s16 delta_lut_h[ACM_DELTA_LUT_H_TOTAL_LENGTH]; - s16 gain_lut_hy[ACM_GAIN_LUT_HY_TOTAL_LENGTH]; - s16 gain_lut_hs[ACM_GAIN_LUT_HS_TOTAL_LENGTH]; - u16 y_gain; - u16 h_gain; - u16 s_gain; - u16 acm_enable; -}; - -struct post_csc { - u16 hue; - u16 saturation; - u16 contrast; - u16 brightness; - u16 r_gain; - u16 g_gain; - u16 b_gain; - u16 r_offset; - u16 g_offset; - u16 b_offset; - u16 csc_enable; -}; - struct post_csc_coef { s32 csc_coef00; s32 csc_coef01; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index ecaacd9f8052..a3da4822a92c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -770,6 +770,9 @@ struct vop2_video_port { */ enum vop2_layer_phy_id primary_plane_phy_id; + struct post_acm acm_info; + struct post_csc csc_info; + /** * @refresh_rate_change: indicate whether refresh rate change */ @@ -9505,18 +9508,25 @@ static void vop3_post_acm_config(struct drm_crtc *crtc, struct post_acm *acm) u32 value; int i; - if (!acm) { - writel(0x2, vop2->acm_regs + RK3528_ACM_CTRL); - VOP_MODULE_SET(vop2, vp, acm_bypass_en, 1); + writel(0, vop2->acm_regs + RK3528_ACM_CTRL); + VOP_MODULE_SET(vop2, vp, acm_bypass_en, 0); + + if (!acm || !acm->acm_enable) return; - } - writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START); + /* + * If acm update parameters, it need disable acm in the first frame, + * then update parameters and enable acm in second frame. + */ + vop2_cfg_done(crtc); + readx_poll_timeout(readl, vop2->acm_regs + RK3528_ACM_CTRL, value, !value, 200, 50000); - value = (acm->acm_enable & 0x1) + ((adjusted_mode->hdisplay & 0xfff) << 8) + + value = RK3528_ACM_ENABLE + ((adjusted_mode->hdisplay & 0xfff) << 8) + ((adjusted_mode->vdisplay & 0xfff) << 20); writel(value, vop2->acm_regs + RK3528_ACM_CTRL); - VOP_MODULE_SET(vop2, vp, acm_bypass_en, acm->acm_enable ? 0 : 1); + + + writel(1, vop2->acm_regs + RK3528_ACM_FETCH_START); value = (acm->y_gain & 0x3ff) + ((acm->h_gain << 10) & 0xffc00) + ((acm->s_gain << 20) & 0x3ff00000); @@ -9555,14 +9565,23 @@ static void vop3_post_acm_config(struct drm_crtc *crtc, struct post_acm *acm) static void vop3_post_config(struct drm_crtc *crtc) { struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); + struct vop2_video_port *vp = to_vop2_video_port(crtc); struct post_acm *acm; struct post_csc *csc; - acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL; - vop3_post_acm_config(crtc, acm); - csc = vcstate->post_csc_data ? (struct post_csc *)vcstate->post_csc_data->data : NULL; - vop3_post_csc_config(crtc, acm, csc); + if (csc && memcmp(&vp->csc_info, csc, sizeof(struct post_csc))) + memcpy(&vp->csc_info, csc, sizeof(struct post_csc)); + vop3_post_csc_config(crtc, &vp->acm_info, &vp->csc_info); + + acm = vcstate->acm_lut_data ? (struct post_acm *)vcstate->acm_lut_data->data : NULL; + + if (acm && memcmp(&vp->acm_info, acm, sizeof(struct post_acm))) { + memcpy(&vp->acm_info, acm, sizeof(struct post_acm)); + vop3_post_acm_config(crtc, &vp->acm_info); + } else if (crtc->state->active_changed) { + vop3_post_acm_config(crtc, &vp->acm_info); + } } static void vop2_cfg_update(struct drm_crtc *crtc, @@ -9623,10 +9642,10 @@ static void vop2_cfg_update(struct drm_crtc *crtc, if (vp_data->feature & VOP_FEATURE_OVERSCAN) vop2_post_config(crtc); + spin_unlock(&vop2->reg_lock); + if (vp_data->feature & (VOP_FEATURE_POST_ACM | VOP_FEATURE_POST_CSC)) vop3_post_config(crtc); - - spin_unlock(&vop2->reg_lock); } static void vop2_sleep_scan_line_time(struct vop2_video_port *vp, int scan_line) diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.c b/drivers/gpu/drm/rockchip/rockchip_post_csc.c index 7160be22a0cb..212a4b4b89e6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.c +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.c @@ -5,7 +5,6 @@ */ #include "rockchip_post_csc.h" -#include "rockchip_drm_drv.h" #define PQ_CSC_HUE_TABLE_NUM 256 #define PQ_CSC_MODE_COEF_COMMENT_LEN 32 diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.h b/drivers/gpu/drm/rockchip/rockchip_post_csc.h index 6c96211aaebc..1215a5cd1c87 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.h +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.h @@ -9,6 +9,7 @@ #define _ROCKCHIP_POST_CSC_H #include +#include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" int rockchip_calc_post_csc(struct post_csc *csc, struct post_csc_coef *csc_coef, diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h index 56a34972b19b..a33f6fcecb78 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.h +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.h @@ -1759,6 +1759,8 @@ /* RK3588 ACM register definition */ #define RK3528_ACM_CTRL 0x0000 +#define RK3528_ACM_ENABLE BIT(0) +#define RK3528_ACM_BYPASS BIT(1) #define RK3528_ACM_DELTA_RANGE 0x0004 #define RK3528_ACM_FETCH_START 0x0008 #define RK3528_ACM_DEBUG_POINT0 0x0010 From 484d7b1bd6ec1acec8cf8374c58deb7c97260c5c Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Mon, 26 Jun 2023 17:11:37 +0800 Subject: [PATCH 2/9] misc: Add rk628 misc drivers Customers may use rk628 drivers on different platforms. Hence we need drivers that do not rely on the FB/DRM display framework. Signed-off-by: Algea Cao Change-Id: Iaab679e4a72d0fb0e5a76bee89b8e1bdac60f4a7 --- drivers/misc/Kconfig | 2 + drivers/misc/Makefile | 1 + drivers/misc/rk628/Kconfig | 27 + drivers/misc/rk628/Makefile | 10 + drivers/misc/rk628/panel.c | 245 +++++ drivers/misc/rk628/panel.h | 18 + drivers/misc/rk628/rk628.c | 1310 +++++++++++++++++++++++ drivers/misc/rk628/rk628.h | 484 +++++++++ drivers/misc/rk628/rk628_combrxphy.c | 567 ++++++++++ drivers/misc/rk628/rk628_combrxphy.h | 16 + drivers/misc/rk628/rk628_combtxphy.c | 309 ++++++ drivers/misc/rk628/rk628_combtxphy.h | 82 ++ drivers/misc/rk628/rk628_config.c | 52 + drivers/misc/rk628/rk628_config.h | 24 + drivers/misc/rk628/rk628_cru.c | 472 ++++++++ drivers/misc/rk628/rk628_cru.h | 159 +++ drivers/misc/rk628/rk628_csi.c | 434 ++++++++ drivers/misc/rk628/rk628_csi.h | 86 ++ drivers/misc/rk628/rk628_dsi.c | 1310 +++++++++++++++++++++++ drivers/misc/rk628/rk628_dsi.h | 158 +++ drivers/misc/rk628/rk628_gpio.h | 296 +++++ drivers/misc/rk628/rk628_grf.h | 263 +++++ drivers/misc/rk628/rk628_gvi.c | 230 ++++ drivers/misc/rk628/rk628_gvi.h | 218 ++++ drivers/misc/rk628/rk628_hdmirx.c | 777 ++++++++++++++ drivers/misc/rk628/rk628_hdmirx.h | 633 +++++++++++ drivers/misc/rk628/rk628_hdmitx.c | 1198 +++++++++++++++++++++ drivers/misc/rk628/rk628_hdmitx.h | 350 ++++++ drivers/misc/rk628/rk628_lvds.c | 126 +++ drivers/misc/rk628/rk628_lvds.h | 15 + drivers/misc/rk628/rk628_pinctrl.c | 326 ++++++ drivers/misc/rk628/rk628_pinctrl.h | 19 + drivers/misc/rk628/rk628_post_process.c | 268 +++++ drivers/misc/rk628/rk628_post_process.h | 15 + drivers/misc/rk628/rk628_rgb.c | 166 +++ drivers/misc/rk628/rk628_rgb.h | 17 + 36 files changed, 10683 insertions(+) create mode 100644 drivers/misc/rk628/Kconfig create mode 100644 drivers/misc/rk628/Makefile create mode 100644 drivers/misc/rk628/panel.c create mode 100644 drivers/misc/rk628/panel.h create mode 100644 drivers/misc/rk628/rk628.c create mode 100644 drivers/misc/rk628/rk628.h create mode 100644 drivers/misc/rk628/rk628_combrxphy.c create mode 100644 drivers/misc/rk628/rk628_combrxphy.h create mode 100644 drivers/misc/rk628/rk628_combtxphy.c create mode 100644 drivers/misc/rk628/rk628_combtxphy.h create mode 100644 drivers/misc/rk628/rk628_config.c create mode 100644 drivers/misc/rk628/rk628_config.h create mode 100644 drivers/misc/rk628/rk628_cru.c create mode 100644 drivers/misc/rk628/rk628_cru.h create mode 100644 drivers/misc/rk628/rk628_csi.c create mode 100644 drivers/misc/rk628/rk628_csi.h create mode 100644 drivers/misc/rk628/rk628_dsi.c create mode 100644 drivers/misc/rk628/rk628_dsi.h create mode 100644 drivers/misc/rk628/rk628_gpio.h create mode 100644 drivers/misc/rk628/rk628_grf.h create mode 100644 drivers/misc/rk628/rk628_gvi.c create mode 100644 drivers/misc/rk628/rk628_gvi.h create mode 100644 drivers/misc/rk628/rk628_hdmirx.c create mode 100644 drivers/misc/rk628/rk628_hdmirx.h create mode 100644 drivers/misc/rk628/rk628_hdmitx.c create mode 100644 drivers/misc/rk628/rk628_hdmitx.h create mode 100644 drivers/misc/rk628/rk628_lvds.c create mode 100644 drivers/misc/rk628/rk628_lvds.h create mode 100644 drivers/misc/rk628/rk628_pinctrl.c create mode 100644 drivers/misc/rk628/rk628_pinctrl.h create mode 100644 drivers/misc/rk628/rk628_post_process.c create mode 100644 drivers/misc/rk628/rk628_post_process.h create mode 100644 drivers/misc/rk628/rk628_rgb.c create mode 100644 drivers/misc/rk628/rk628_rgb.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 276c7c4fef15..8481b9613bc9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -5,6 +5,8 @@ menu "Misc devices" +source "drivers/misc/rk628/Kconfig" + config RK803 tristate "RK803" default n diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index b296e760fd47..14642c54a2bc 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -3,6 +3,7 @@ # Makefile for misc devices that really don't fit anywhere else. # +obj-y += rk628/ obj-$(CONFIG_RK803) += rk803.o obj-y += rockchip/ obj-$(CONFIG_LT7911D_FB_NOTIFIER) += lt7911d-fb-notifier.o diff --git a/drivers/misc/rk628/Kconfig b/drivers/misc/rk628/Kconfig new file mode 100644 index 000000000000..7f89f18f42a1 --- /dev/null +++ b/drivers/misc/rk628/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 +menu "RK628 misc driver" +config RK628_MISC + tristate "rk628 misc driver" + default n + help + Say y here to enable Rockchip rk628 misc driver. + This option is used to support rgb/hdmi/bt1120 input and dsi/lvds/gvi/hdmi output. + +config RK628_MISC_HDMITX + bool "rk628 misc hdmitx driver" + default n + depends on RK628_MISC + depends on DRM + help + Say y here to enable Rockchip rk628 misc hdmitx driver. + This option is used to support hdmi output. + +config ROCKCHIP_THUNDER_BOOT_RK628 + bool "Rockchip RK628 Thunder Boot support" + default n + depends on RK628_MISC + help + Say y here to enable Rockchip rk628 thunder boot support. + This option make the kernel boot faster. + +endmenu diff --git a/drivers/misc/rk628/Makefile b/drivers/misc/rk628/Makefile new file mode 100644 index 000000000000..cb4285a06f89 --- /dev/null +++ b/drivers/misc/rk628/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +rk628_misc-$(CONFIG_RK628_MISC) += rk628.o rk628_cru.o rk628_config.o rk628_post_process.o \ + rk628_combrxphy.o rk628_hdmirx.o rk628_combtxphy.o rk628_dsi.o \ + panel.o rk628_lvds.o rk628_rgb.o rk628_gvi.o rk628_pinctrl.o \ + rk628_csi.o + +rk628_misc-$(CONFIG_RK628_MISC_HDMITX) += rk628_hdmitx.o + +obj-$(CONFIG_RK628_MISC) += rk628_misc.o diff --git a/drivers/misc/rk628/panel.c b/drivers/misc/rk628/panel.c new file mode 100644 index 000000000000..a0a35030779f --- /dev/null +++ b/drivers/misc/rk628/panel.c @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Rockchip Electronics Co. Ltd. + * + * Author: Guochun Huang + */ + +#include "rk628.h" +#include +#include + +#include "panel.h" + +static int +dsi_panel_parse_cmds(const u8 *data, int blen, struct panel_cmds *pcmds) +{ + unsigned int len; + char *buf, *bp; + struct cmd_ctrl_hdr *dchdr; + int i, cnt; + + if (!pcmds) + return -EINVAL; + + buf = kmemdup(data, blen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* scan init commands */ + bp = buf; + len = blen; + cnt = 0; + while (len > sizeof(*dchdr)) { + dchdr = (struct cmd_ctrl_hdr *)bp; + + if (dchdr->dlen > len) { + pr_err("%s: error, len=%d", __func__, dchdr->dlen); + return -EINVAL; + } + + bp += sizeof(*dchdr); + len -= sizeof(*dchdr); + bp += dchdr->dlen; + len -= dchdr->dlen; + cnt++; + } + + if (len != 0) { + pr_err("%s: dcs_cmd=%x len=%d error!", __func__, buf[0], blen); + kfree(buf); + return -EINVAL; + } + + pcmds->cmds = kcalloc(cnt, sizeof(struct cmd_desc), GFP_KERNEL); + if (!pcmds->cmds) { + kfree(buf); + return -ENOMEM; + } + + pcmds->cmd_cnt = cnt; + pcmds->buf = buf; + pcmds->blen = blen; + + bp = buf; + len = blen; + for (i = 0; i < cnt; i++) { + dchdr = (struct cmd_ctrl_hdr *)bp; + len -= sizeof(*dchdr); + bp += sizeof(*dchdr); + pcmds->cmds[i].dchdr = *dchdr; + pcmds->cmds[i].payload = bp; + bp += dchdr->dlen; + len -= dchdr->dlen; + } + + return 0; +} + +static int dsi_panel_get_cmds(struct rk628 *rk628, struct device_node *dsi_np) +{ + struct device_node *np; + const void *data; + int len; + int ret, err; + + np = of_find_node_by_name(dsi_np, "rk628-panel"); + if (!np) + return -EINVAL; + + data = of_get_property(np, "panel-init-sequence", &len); + if (data) { + rk628->panel->on_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL); + if (!rk628->panel->on_cmds) + return -ENOMEM; + + err = dsi_panel_parse_cmds(data, len, rk628->panel->on_cmds); + if (err) { + dev_err(rk628->dev, "failed to parse dsi panel init sequence\n"); + ret = err; + goto init_err; + } + } + + data = of_get_property(np, "panel-exit-sequence", &len); + if (data) { + rk628->panel->off_cmds = kcalloc(1, sizeof(struct panel_cmds), GFP_KERNEL); + if (!rk628->panel->off_cmds) { + ret = -ENOMEM; + goto on_err; + } + + err = dsi_panel_parse_cmds(data, len, rk628->panel->off_cmds); + if (err) { + dev_err(rk628->dev, "failed to parse dsi panel exit sequence\n"); + ret = err; + goto exit_err; + } + } + + return 0; + +exit_err: + kfree(rk628->panel->off_cmds); +on_err: + kfree(rk628->panel->on_cmds->cmds); + kfree(rk628->panel->on_cmds->buf); +init_err: + kfree(rk628->panel->on_cmds); + + return ret; +} + +int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np) +{ + struct panel_simple *panel; + struct device *dev = rk628->dev; + struct device_node *backlight; + int ret; + + panel = devm_kzalloc(dev, sizeof(struct panel_simple), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + panel->supply = devm_regulator_get(dev, "power"); + if (IS_ERR(panel->supply)) { + ret = PTR_ERR(panel->supply); + dev_err(dev, "failed to get power regulator: %d\n", ret); + return ret; + } + + panel->enable_gpio = devm_gpiod_get_optional(dev, "panel-enable", GPIOD_OUT_LOW); + if (IS_ERR(panel->enable_gpio)) { + ret = PTR_ERR(panel->enable_gpio); + dev_err(dev, "failed to request panel enable GPIO: %d\n", ret); + return ret; + } + + panel->reset_gpio = devm_gpiod_get_optional(dev, "panel-reset", GPIOD_OUT_LOW); + if (IS_ERR(panel->reset_gpio)) { + ret = PTR_ERR(panel->reset_gpio); + dev_err(dev, "failed to request panel reset GPIO: %d\n", ret); + return ret; + } + + backlight = of_parse_phandle(dev->of_node, "panel-backlight", 0); + if (backlight) { + panel->backlight = of_find_backlight_by_node(backlight); + of_node_put(backlight); + + if (!panel->backlight) { + dev_err(dev, "failed to find backlight\n"); + return -EPROBE_DEFER; + } + + } + + rk628->panel = panel; + + if (rk628->output_mode == OUTPUT_MODE_DSI) { + ret = dsi_panel_get_cmds(rk628, np); + if (ret) { + dev_err(dev, "failed to get cmds\n"); + return ret; + } + } + + return 0; +} + +void rk628_panel_prepare(struct rk628 *rk628) +{ + int ret; + + if (rk628->panel->supply) { + ret = regulator_enable(rk628->panel->supply); + if (ret) + dev_info(rk628->dev, "failed to enable panel power supply\n"); + } + + if (rk628->panel->enable_gpio) { + gpiod_set_value(rk628->panel->enable_gpio, 0); + mdelay(120); + gpiod_set_value(rk628->panel->enable_gpio, 1); + mdelay(120); + } + + if (rk628->panel->reset_gpio) { + gpiod_set_value(rk628->panel->reset_gpio, 0); + mdelay(120); + gpiod_set_value(rk628->panel->reset_gpio, 1); + mdelay(120); + gpiod_set_value(rk628->panel->reset_gpio, 0); + mdelay(120); + } +} + +void rk628_panel_enable(struct rk628 *rk628) +{ + if (rk628->panel->backlight) + backlight_enable(rk628->panel->backlight); +} + +void rk628_panel_unprepare(struct rk628 *rk628) +{ + + if (rk628->panel->reset_gpio) { + gpiod_set_value(rk628->panel->reset_gpio, 1); + mdelay(120); + } + + if (rk628->panel->enable_gpio) { + gpiod_set_value(rk628->panel->enable_gpio, 0); + mdelay(120); + } + + if (rk628->panel->supply) + regulator_disable(rk628->panel->supply); +} + +void rk628_panel_disable(struct rk628 *rk628) +{ + if (rk628->panel->backlight) + backlight_disable(rk628->panel->backlight); + +} diff --git a/drivers/misc/rk628/panel.h b/drivers/misc/rk628/panel.h new file mode 100644 index 000000000000..07a34cf3ee17 --- /dev/null +++ b/drivers/misc/rk628/panel.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2021 Rockchip Electronics Co. Ltd. + * + * Author: Guochun Huang + */ +#ifndef _PANEL_H +#define _PANEL_H + +#include "rk628.h" + +int rk628_panel_info_get(struct rk628 *rk628, struct device_node *np); +void rk628_panel_prepare(struct rk628 *rk628); +void rk628_panel_enable(struct rk628 *rk628); +void rk628_panel_unprepare(struct rk628 *rk628); +void rk628_panel_disable(struct rk628 *rk628); +#endif + diff --git a/drivers/misc/rk628/rk628.c b/drivers/misc/rk628/rk628.c new file mode 100644 index 000000000000..15df730c8048 --- /dev/null +++ b/drivers/misc/rk628/rk628.c @@ -0,0 +1,1310 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Rockchip Electronics Co. Ltd. + * + * Author: Wyon Bi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include