diff --git a/arch/arm/boot/dts/rk3036-evb1-ddr3-v10.dts b/arch/arm/boot/dts/rk3036-evb1-ddr3-v10.dts index d709bea281bb..7959121cd0ae 100644 --- a/arch/arm/boot/dts/rk3036-evb1-ddr3-v10.dts +++ b/arch/arm/boot/dts/rk3036-evb1-ddr3-v10.dts @@ -231,8 +231,8 @@ reset-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; plugin-det-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; status = "okay"; - rk628,hdmi-in; - rk628-dsi { + rk628-hdmi-in; + rk628-dsi-out { //rockchip,dual-channel; dsi,eotp; dsi,video-mode; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts index 4ecd56149a24..1397d9b3522b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-ddr4-v10.dts @@ -24,8 +24,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,hdmi-in; - rk628-dsi { + rk628-hdmi-in; + rk628-dsi-out { //rockchip,dual-channel; dsi,eotp; dsi,video-mode; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts index 0892e5e9ee47..80a73eefe453 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2dsi-dual-ddr4-v10.dts @@ -22,8 +22,8 @@ panel-disable-delay-ms = <240>; panel-init-delay-ms = <240>; - rk628,hdmi-in; - rk628-dsi { + rk628-hdmi-in; + rk628-dsi-out { rockchip,lane-mbps = <1100>; rockchip,dual-channel; dsi,eotp; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts index 93631f254526..42e965bb0aa8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2gvi-ddr4-v10.dts @@ -31,8 +31,8 @@ clocks = <&pmucru CLK_WIFI>; clock-names = "soc_24M"; - rk628,hdmi-in; - rk628-gvi { + rk628-hdmi-in; + rk628-gvi-out { /* "rgb666" * "rgb888" * "rgb101010" diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts index 66f0401fb329..b26fd1b3d910 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-ddr4-v10.dts @@ -22,8 +22,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,hdmi-in; - rk628-lvds { + rk628-hdmi-in; + rk628-lvds-out { /* "jeida_18","vesa_24","vesa_18" */ bus-format = "jeida_24"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts index b48bb44cc2bf..faaeddaf437c 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-hdmi2lvds-dual-ddr4-v10.dts @@ -25,8 +25,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,hdmi-in; - rk628-lvds { + rk628-hdmi-in; + rk628-lvds-out { /* "jeida_18","vesa_24","vesa_18" */ bus-format = "vesa_24"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts index 804640323de1..8dd6d3e66cc8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2dsi-ddr4-v10.dts @@ -55,8 +55,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,rgb-in; - rk628-dsi { + rk628-rgb-in; + rk628-dsi-out { //rockchip,dual-channel; dsi,eotp; dsi,video-mode; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts index 9b47d9eda21a..cf252d31c559 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2gvi-ddr4-v10.dts @@ -62,8 +62,8 @@ clocks = <&pmucru CLK_WIFI>; clock-names = "soc_24M"; - rk628,rgb-in; - rk628-gvi { + rk628-rgb-in; + rk628-gvi-out { /* "rgb666" * "rgb888" * "rgb101010" diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts index 83b62f996aff..16d185cb7ad6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2hdmi-ddr4-v10.dts @@ -23,8 +23,8 @@ pinctrl-names = "default"; pinctrl-0 = <&rk628_reset &refclk_pins>; - rk628,rgb-in; - rk628,hdmi-out; + rk628-rgb-in; + rk628-hdmi-out; status = "okay"; port { diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts index 28adb73ce751..01a62e8f8850 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-ddr4-v10.dts @@ -56,8 +56,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,rgb-in; - rk628-lvds { + rk628-rgb-in; + rk628-lvds-out { /* "jeida_18","vesa_24","vesa_18" */ bus-format = "jeida_24"; diff --git a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts index 65321128ec17..82e344a37036 100644 --- a/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts +++ b/arch/arm64/boot/dts/rockchip/rk3568-evb-rk628-rgb2lvds-dual-ddr4-v10.dts @@ -57,8 +57,8 @@ panel-unprepare-delay-ms = <10>; panel-disable-delay-ms = <60>; - rk628,rgb-in; - rk628-lvds { + rk628-rgb-in; + rk628-lvds-out { /* "jeida_18","vesa_24","vesa_18" */ bus-format = "vesa_24"; diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 89238f75dfd1..205dacba201c 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -218,6 +218,8 @@ struct panel_simple { struct drm_dsc_picture_parameter_set *pps; enum drm_panel_orientation orientation; + + bool loader_protect; }; static inline void panel_simple_msleep(unsigned int msecs) @@ -536,6 +538,8 @@ int panel_simple_loader_protect(struct drm_panel *panel) struct panel_simple *p = to_panel_simple(panel); int err; + p->loader_protect = true; + err = pm_runtime_get_sync(panel->dev); if (err < 0) { pm_runtime_put_autosuspend(panel->dev); @@ -567,15 +571,25 @@ static int panel_simple_disable(struct drm_panel *panel) static int panel_simple_suspend(struct device *dev) { struct panel_simple *p = dev_get_drvdata(dev); + struct drm_panel *panel = &p->base; + + if (p->desc->exit_seq) { + if (p->desc->cmd_type == CMD_TYPE_SPI) { + if (panel_simple_xfer_spi_cmd_seq(p, p->desc->exit_seq)) { + dev_err(panel->dev, "failed to send exit spi cmds seq\n"); + return -EINVAL; + } + } else { + if (p->dsi) + panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq); + } + } gpiod_set_value_cansleep(p->reset_gpio, 1); gpiod_set_value_cansleep(p->enable_gpio, 0); panel_simple_regulator_disable(p); - if (p->desc->delay.unprepare) - panel_simple_msleep(p->desc->delay.unprepare); - p->unprepared_time = ktime_get_boottime(); kfree(p->edid); @@ -593,18 +607,6 @@ static int panel_simple_unprepare(struct drm_panel *panel) if (!p->prepared) return 0; - if (p->desc->exit_seq) { - if (p->desc->cmd_type == CMD_TYPE_SPI) { - if (panel_simple_xfer_spi_cmd_seq(p, p->desc->exit_seq)) { - dev_err(panel->dev, "failed to send exit spi cmds seq\n"); - return -EINVAL; - } - } else { - if (p->dsi) - panel_simple_xfer_dsi_cmd_seq(p, p->desc->exit_seq); - } - } - pm_runtime_mark_last_busy(panel->dev); ret = pm_runtime_put_autosuspend(panel->dev); if (ret < 0) @@ -617,6 +619,7 @@ static int panel_simple_unprepare(struct drm_panel *panel) static int panel_simple_resume(struct device *dev) { struct panel_simple *p = dev_get_drvdata(dev); + struct drm_panel *panel = &p->base; int err; panel_simple_wait(p->unprepared_time, p->desc->delay.unprepare); @@ -634,22 +637,9 @@ static int panel_simple_resume(struct device *dev) p->prepared_time = ktime_get_boottime(); - return 0; -} - -static int panel_simple_prepare(struct drm_panel *panel) -{ - struct panel_simple *p = to_panel_simple(panel); - int ret; - - /* Preparing when already prepared is a no-op */ - if (p->prepared) + if (p->loader_protect) { + p->loader_protect = false; return 0; - - ret = pm_runtime_get_sync(panel->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(panel->dev); - return ret; } gpiod_set_value_cansleep(p->reset_gpio, 1); @@ -674,6 +664,24 @@ static int panel_simple_prepare(struct drm_panel *panel) } } + return 0; +} + +static int panel_simple_prepare(struct drm_panel *panel) +{ + struct panel_simple *p = to_panel_simple(panel); + int ret; + + /* Preparing when already prepared is a no-op */ + if (p->prepared) + return 0; + + ret = pm_runtime_get_sync(panel->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(panel->dev); + return ret; + } + p->prepared = true; return 0; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index b9162f87f54e..e8c61d8fbbb6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -11299,6 +11299,12 @@ static int vop2_crtc_create_post_csc_property(struct vop2 *vop2, struct drm_crtc #define RK3566_MIRROR_PLANE_MASK (BIT(ROCKCHIP_VOP2_CLUSTER1) | BIT(ROCKCHIP_VOP2_ESMART1) | \ BIT(ROCKCHIP_VOP2_SMART1)) +static inline bool vop2_win_can_link_to_vp(struct vop2_video_port *vp, struct vop2_win *win) +{ + return (!win->possible_crtcs || + (win->possible_crtcs && (win->possible_crtcs & BIT(vp->id)))); +} + /* * Returns: * Registered crtc number on success, negative error code on failure. @@ -11414,14 +11420,17 @@ static int vop2_create_crtc(struct vop2 *vop2) plane_mask &= ~RK3566_MIRROR_PLANE_MASK; } } + find_primary_plane = false; if (vp->primary_plane_phy_id >= 0) { win = vop2_find_win_by_phys_id(vop2, vp->primary_plane_phy_id); - if (win) { + if (win && vop2_win_can_link_to_vp(vp, win)) { find_primary_plane = true; win->type = DRM_PLANE_TYPE_PRIMARY; } - } else { + } + + if (!find_primary_plane) { j = 0; while (j < vop2->registered_num_wins) { be_used_for_primary_plane = false; @@ -11434,6 +11443,9 @@ static int vop2_create_crtc(struct vop2 *vop2) if (win->type != DRM_PLANE_TYPE_PRIMARY) continue; + if (!vop2_win_can_link_to_vp(vp, win)) + continue; + for (k = 0; k < vop2_data->nr_vps; k++) { if (win->phys_id == vop2->vps[k].primary_plane_phy_id) { be_used_for_primary_plane = true; diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.c b/drivers/input/remotectl/rockchip_pwm_remotectl.c index fa3d7650d8ff..606c0857831a 100644 --- a/drivers/input/remotectl/rockchip_pwm_remotectl.c +++ b/drivers/input/remotectl/rockchip_pwm_remotectl.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +// SPDX-License-Identifier: GPL-2.0 #include #include @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,8 +20,6 @@ #include #include "rockchip_pwm_remotectl.h" - - /* * sys/module/rk_pwm_remotectl/parameters, * modify code_print to change the value @@ -56,8 +55,46 @@ struct rkxx_remotectl_button { struct rkxx_remote_key_table key_table[MAX_NUM_KEYS]; }; +struct rk_remote_pwm_regs { + unsigned long ctrl; + unsigned long version; + unsigned long enable; + unsigned long clk_ctrl; + unsigned long offset; + unsigned long rpt; + unsigned long hpr; + unsigned long lpr; + unsigned long intsts; + unsigned long int_en; + unsigned long pwrmatch_arbiter; + unsigned long pwrmatch_ctrl; + unsigned long pwrmatch_lpre; + unsigned long pwrmatch_hpre; + unsigned long pwrmatch_ld; + unsigned long pwrmatch_hd_zero; + unsigned long pwrmatch_hd_one; + unsigned long pwrmatch_value0; + unsigned long pwrcapture_value; +}; + +struct rk_remote_pwm_funcs { + irqreturn_t (*irq_handler)(int irq, void *data); + void (*int_ctrl)(struct platform_device *pdev, int work_mode); + int (*init_hw)(struct platform_device *pdev); +}; + +struct rk_remote_pwm_data { + struct rk_remote_pwm_regs regs; + struct rk_remote_pwm_funcs funcs; + unsigned int prescaler; + u32 enable_conf; + int pwm_version; + int pwrmactch_key_max; +}; + struct rkxx_remotectl_drvdata { void __iomem *base; + int pwm_version; int state; int nbuttons; int scandata; @@ -81,10 +118,60 @@ struct rkxx_remotectl_drvdata { struct timer_list timer; struct tasklet_struct remote_tasklet; struct wake_lock remotectl_wake_lock; + const struct rk_remote_pwm_data *pwm_data; }; +static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id); +static irqreturn_t rockchip_pwm_irq_v4(int irq, void *dev_id); +static int rk_pwm_remotectl_hw_init(struct platform_device *pdev); +static int rk_pwm_remotectl_hw_init_v4(struct platform_device *pdev); +static void rk_pwm_int_ctrl(struct platform_device *pdev, int work_mode); +static void rk_pwm_int_ctrl_v4(struct platform_device *pdev, int work_mode); + static struct rkxx_remotectl_button *remotectl_button; +struct rk_remote_pwm_data pwm_data_v1 = { + .regs = { + .version = 0x5c, + .ctrl = 0x0c, + }, + .prescaler = 1, + .pwm_version = 1, + .funcs = { + .irq_handler = rockchip_pwm_irq, + .int_ctrl = rk_pwm_int_ctrl, + .init_hw = rk_pwm_remotectl_hw_init, + }, +}; + +struct rk_remote_pwm_data pwm_data_v4 = { + .regs = { + .version = 0x0, + .enable = 0x4, + .clk_ctrl = 0x8, + .ctrl = 0xc, + .hpr = 0x2c, + .lpr = 0x30, + .intsts = 0x70, + .int_en = 0x74, + .pwrmatch_arbiter = 0x100, + .pwrmatch_ctrl = 0x104, + .pwrmatch_lpre = 0x108, + .pwrmatch_hpre = 0x10c, + .pwrmatch_ld = 0x110, + .pwrmatch_hd_zero = 0x114, + .pwrmatch_hd_one = 0x118, + .pwrmatch_value0 = 0x11c, + .pwrcapture_value = 0x15c, + }, + .pwm_version = 4, + .funcs = { + .irq_handler = rockchip_pwm_irq_v4, + .int_ctrl = rk_pwm_int_ctrl_v4, + .init_hw = rk_pwm_remotectl_hw_init_v4, + }, +}; + static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata) { int i; @@ -100,7 +187,6 @@ static int remotectl_keybd_num_lookup(struct rkxx_remotectl_drvdata *ddata) return 0; } - static int remotectl_keycode_lookup(struct rkxx_remotectl_drvdata *ddata) { int i; @@ -137,7 +223,6 @@ static int rk_remotectl_get_irkeybd_count(struct platform_device *pdev) return boardnum; } - static int rk_remotectl_parse_ir_keys(struct platform_device *pdev) { struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); @@ -182,8 +267,6 @@ static int rk_remotectl_parse_ir_keys(struct platform_device *pdev) return 0; } - - static void rk_pwm_remotectl_do_something(unsigned long data) { struct rkxx_remotectl_drvdata *ddata; @@ -359,70 +442,184 @@ static irqreturn_t rockchip_pwm_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int rk_pwm_pwrkey_wakeup_init(struct platform_device *pdev) +static irqreturn_t rockchip_pwm_irq_v4(int irq, void *dev_id) +{ + struct rkxx_remotectl_drvdata *ddata = dev_id; + int tmp; + int val; + irqreturn_t ret = IRQ_NONE; + + val = readl_relaxed(ddata->base + PWM_REG_INTSTS_V4); + + if (val & CAP_LPR_INT) { + writel_relaxed(CAP_LPR_INT, ddata->base + PWM_REG_INTSTS_V4); + tmp = readl_relaxed(ddata->base + PWM_REG_HPR_V4); + ddata->period = ddata->pwm_freq_nstime * tmp / 1000; + DBG("period = %ld\n", ddata->period); + tasklet_hi_schedule(&ddata->remote_tasklet); + ret = IRQ_HANDLED; + } else if (val & CAP_HPR_INT) { + writel_relaxed(CAP_HPR_INT, ddata->base + PWM_REG_INTSTS_V4); + tmp = readl_relaxed(ddata->base + PWM_REG_LPR_V4); + DBG("lpr = %d\n", tmp); + ret = IRQ_HANDLED; + } + + if (val & PWR_INT) { + writel_relaxed(PWR_INT, ddata->base + PWM_REG_INTSTS_V4); + tmp = readl_relaxed(ddata->base + PWM_REG_CAPTURE_VALUE_V4); + DBG("##### cap_val = 0x%0x\n", tmp); + ddata->pwrkey_wakeup = 1; + ret = IRQ_HANDLED; + } + + if (ddata->state == RMC_PRELOAD) + wake_lock_timeout(&ddata->remotectl_wake_lock, HZ); + + return ret; +} + +static int rk_pwmkey_convert_val(int min, int max, int freq_nstime) +{ + int val, min_temp, max_temp; + + min_temp = min * 1000 / freq_nstime; + max_temp = max * 1000 / freq_nstime; + val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); + + return val; +} + +static int rockchip_pwm_set_pwrmatch(struct platform_device *pdev) { struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); - int val, min_temp, max_temp; unsigned int pwm_id = ddata->remote_pwm_id; int version; - int i, j; - int num = 0; - int ret = -1; int pwr_irq; + int val; + int ret; - ddata->pwm_pwrkey_capture = 0; version = readl_relaxed(ddata->base + RK_PWM_VERSION_ID(pwm_id)); - dev_info(&pdev->dev, "pwm version is 0x%x\n", version & 0xffff0000); + DBG("remote pwm version is 0x%x\n", version); if (((version >> 24) & 0xFF) < 2) { dev_info(&pdev->dev, "pwm version is less v2.0\n"); + ret = -EINVAL; goto end; } pwr_irq = platform_get_irq(pdev, 1); if (pwr_irq < 0) { dev_err(&pdev->dev, "cannot find PWR IRQ\n"); + ret = pwr_irq; goto end; } ret = devm_request_irq(&pdev->dev, pwr_irq, rockchip_pwm_pwrirq, - IRQF_NO_SUSPEND, "rk_pwm_pwr_irq", ddata); + IRQF_NO_SUSPEND, "rk_pwm_pwr_irq", ddata); if (ret) { dev_err(&pdev->dev, "cannot claim PWR_IRQ!!!\n"); goto end; } - val = readl_relaxed(ddata->base + PWM_REG_CTRL); - val = (val & 0xFFFFFFFE) | PWM_DISABLE; - writel_relaxed(val, ddata->base + PWM_REG_CTRL); + val = readl_relaxed(ddata->base + PWM_REG_INT_EN(pwm_id)); + val = (val & 0xFFFFFF7F) | PWM_PWR_INT_ENABLE; + writel_relaxed(val, ddata->base + PWM_REG_INT_EN(pwm_id)); + val = CH3_PWRKEY_ENABLE; + writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_CTRL(pwm_id)); + + val = readl_relaxed(ddata->base + PWM_REG_CTRL); + val = (val & 0xFFFFFFFE) | PWM_ENABLE; + writel_relaxed(val, ddata->base + PWM_REG_CTRL); + return 0; +end: + return ret; +} + +static int rockchip_pwm_set_pwrmatch_v4(struct rkxx_remotectl_drvdata *pd) +{ + int version; + int channel_id; + int val; + + version = readl_relaxed(pd->base + PWM_REG_VERSION_V4); + DBG("remote pwm version is 0x%x\n", version); + channel_id = (version & CHANNLE_INDEX_MASK) >> CHANNLE_INDEX_SHIFT; + val = BIT(channel_id) << PWRMATCH_READ_LOCK_SHIFT | + BIT(channel_id) << PWRMATCH_GRANT_SHIFT; + writel_relaxed(val, pd->base + PWM_REG_MATCH_ARBITER_V4); + writel_relaxed(PWRKEY_EN(true), + pd->base + PWM_REG_MATCH_CTRL_V4); + + return 0; +} + +static void rockchip_pwrmatch_set_nec_param(struct rkxx_remotectl_drvdata *pd) +{ + unsigned int pwm_id = pd->remote_pwm_id; + void __iomem *reg; + int freq_nstime; + int val; + + freq_nstime = pd->pwm_freq_nstime; //preloader low min:8000us, max:10000us - min_temp = RK_PWM_TIME_PRE_MIN_LOW * 1000 / ddata->pwm_freq_nstime; - max_temp = RK_PWM_TIME_PRE_MAX_LOW * 1000 / ddata->pwm_freq_nstime; - val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_LPRE(pwm_id)); + val = rk_pwmkey_convert_val(RK_PWM_TIME_PRE_MIN_LOW, + RK_PWM_TIME_PRE_MAX_LOW, freq_nstime); + if (pd->pwm_data->pwm_version < 4) + reg = pd->base + PWM_REG_PWRMATCH_LPRE(pwm_id); + else + reg = pd->base + PWM_REG_MATCH_LPRE_V4; + writel_relaxed(val, reg); //preloader higt min:4000us, max:5000us - min_temp = RK_PWM_TIME_PRE_MIN * 1000 / ddata->pwm_freq_nstime; - max_temp = RK_PWM_TIME_PRE_MAX * 1000 / ddata->pwm_freq_nstime; - val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HPRE(pwm_id)); + val = rk_pwmkey_convert_val(RK_PWM_TIME_PRE_MIN, + RK_PWM_TIME_PRE_MAX, freq_nstime); + if (pd->pwm_data->pwm_version < 4) + reg = pd->base + PWM_REG_PWRMATCH_HPRE(pwm_id); + else + reg = pd->base + PWM_REG_MATCH_HPRE_V4; + writel_relaxed(val, reg); //logic 0/1 low min:480us, max 700us - min_temp = RK_PWM_TIME_BIT_MIN_LOW * 1000 / ddata->pwm_freq_nstime; - max_temp = RK_PWM_TIME_BIT_MAX_LOW * 1000 / ddata->pwm_freq_nstime; - val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_LD(pwm_id)); + val = rk_pwmkey_convert_val(RK_PWM_TIME_BIT_MIN_LOW, + RK_PWM_TIME_BIT_MAX_LOW, freq_nstime); + if (pd->pwm_data->pwm_version < 4) + reg = pd->base + PWM_REG_PWRMATCH_LD(pwm_id); + else + reg = pd->base + PWM_REG_MATCH_LD_V4; + writel_relaxed(val, reg); //logic 0 higt min:480us, max 700us - min_temp = RK_PWM_TIME_BIT0_MIN * 1000 / ddata->pwm_freq_nstime; - max_temp = RK_PWM_TIME_BIT0_MAX * 1000 / ddata->pwm_freq_nstime; - val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HD_ZERO(pwm_id)); + val = rk_pwmkey_convert_val(RK_PWM_TIME_BIT0_MIN, + RK_PWM_TIME_BIT0_MAX, freq_nstime); + if (pd->pwm_data->pwm_version < 4) + reg = pd->base + PWM_REG_PWRMATCH_HD_ZERO(pwm_id); + else + reg = pd->base + PWM_REG_MATCH_HD_ZERO_V4; + writel_relaxed(val, reg); //logic 1 higt min:1300us, max 2000us - min_temp = RK_PWM_TIME_BIT1_MIN * 1000 / ddata->pwm_freq_nstime; - max_temp = RK_PWM_TIME_BIT1_MAX * 1000 / ddata->pwm_freq_nstime; - val = (max_temp & 0xffff) << 16 | (min_temp & 0xffff); - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_HD_ONE(pwm_id)); + val = rk_pwmkey_convert_val(RK_PWM_TIME_BIT1_MIN, + RK_PWM_TIME_BIT1_MAX, freq_nstime); + if (pd->pwm_data->pwm_version < 4) + reg = pd->base + PWM_REG_PWRMATCH_HD_ONE(pwm_id); + else + reg = pd->base + PWM_REG_MATCH_HD_ONE_V4; + writel_relaxed(val, reg); +} - for (j = 0; j < ddata->maxkeybdnum; j++) { +static void rockchip_pwrmatch_set_pwrkey(struct rkxx_remotectl_drvdata *pd) +{ + unsigned int pwm_id = pd->remote_pwm_id; + void __iomem *reg; + int i, j; + int num = 0, num_max; + + if (pd->pwm_data->pwm_version < 4) { + reg = pd->base + PWM_PWRMATCH_VALUE(pwm_id); + num_max = PWM_PWR_KEY_CAPURURE_MAX; + } else { + reg = pd->base + PWM_REG_CAPTURE_VALUE0_V4; + num_max = PWM_PWR_KEY_CAPURURE_MAX_V4; + } + for (j = 0; j < pd->maxkeybdnum; j++) { for (i = 0; i < remotectl_button[j].nbuttons; i++) { int scancode, usercode, pwrkey; @@ -434,71 +631,122 @@ static int rk_pwm_pwrkey_wakeup_init(struct platform_device *pdev) pwrkey = usercode; pwrkey |= (scancode << 24) | ((~scancode & 0xff) << 16); DBG("pwrkey = %x\n", pwrkey); - writel_relaxed(pwrkey, ddata->base - + PWM_PWRMATCH_VALUE(pwm_id) + num * 4); + writel_relaxed(pwrkey, reg + num * 4); num++; - if (num >= PWM_PWR_KEY_CAPURURE_MAX) + if (num >= num_max) break; } } +} - val = readl_relaxed(ddata->base + PWM_REG_INT_EN(pwm_id)); - val = (val & 0xFFFFFF7F) | PWM_PWR_INT_ENABLE; - writel_relaxed(val, ddata->base + PWM_REG_INT_EN(pwm_id)); +static int rk_pwm_pwrkey_wakeup_init(struct platform_device *pdev) +{ + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); + int ret = -1; - val = CH3_PWRKEY_ENABLE; - writel_relaxed(val, ddata->base + PWM_REG_PWRMATCH_CTRL(pwm_id)); - - val = readl_relaxed(ddata->base + PWM_REG_CTRL); - val = (val & 0xFFFFFFFE) | PWM_ENABLE; - writel_relaxed(val, ddata->base + PWM_REG_CTRL); + ddata->pwm_pwrkey_capture = 0; + if (ddata->pwm_data->pwm_version < 4) { + ret = rockchip_pwm_set_pwrmatch(pdev); + if (ret < 0) + goto end; + } else { + rockchip_pwm_set_pwrmatch_v4(ddata); + } + rockchip_pwrmatch_set_nec_param(ddata); + rockchip_pwrmatch_set_pwrkey(ddata); ddata->pwm_pwrkey_capture = 1; end: return ret; } -static void rk_pwm_int_ctrl(void __iomem *pwm_base, uint pwm_id, int ctrl) +static void rk_pwm_int_ctrl(struct platform_device *pdev, int work_mode) { + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); int val; + int pwm_id = ddata->remote_pwm_id; if (pwm_id > 3) return; - val = readl_relaxed(pwm_base + PWM_REG_INT_EN(pwm_id)); - if (ctrl) { + val = readl_relaxed(ddata->base + PWM_REG_INT_EN(pwm_id)); + if (work_mode) { val |= PWM_CH_INT_ENABLE(pwm_id); DBG("pwm int enabled, value is 0x%x\n", val); - writel_relaxed(val, pwm_base + PWM_REG_INT_EN(pwm_id)); + writel_relaxed(val, ddata->base + PWM_REG_INT_EN(pwm_id)); } else { val &= ~PWM_CH_INT_ENABLE(pwm_id); DBG("pwm int disabled, value is 0x%x\n", val); } - writel_relaxed(val, pwm_base + PWM_REG_INT_EN(pwm_id)); + writel_relaxed(val, ddata->base + PWM_REG_INT_EN(pwm_id)); } -static int rk_pwm_remotectl_hw_init(void __iomem *pwm_base, uint pwm_id) +static void rk_pwm_int_ctrl_v4(struct platform_device *pdev, int work_mode) { + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); int val; - if (pwm_id > 3) - return -1; + if (work_mode) { + val = CAP_LPR_INT_EN(true) | CAP_HPR_INT_EN(true) | PWR_INT_EN(false); + writel_relaxed(val, ddata->base + PWM_REG_INT_EN_V4); + } else { + val = CAP_LPR_INT_EN(false) | CAP_HPR_INT_EN(false) | PWR_INT_EN(true); + writel_relaxed(val, ddata->base + PWM_REG_INT_EN_V4); + } +} + +static int rk_pwm_remotectl_hw_init(struct platform_device *pdev) +{ + int val; + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); + //1. disabled pwm - val = readl_relaxed(pwm_base + PWM_REG_CTRL); + val = readl_relaxed(ddata->base + PWM_REG_CTRL); val = (val & 0xFFFFFFFE) | PWM_DISABLE; - writel_relaxed(val, pwm_base + PWM_REG_CTRL); + writel_relaxed(val, ddata->base + PWM_REG_CTRL); + //2. capture mode - val = readl_relaxed(pwm_base + PWM_REG_CTRL); + val = readl_relaxed(ddata->base + PWM_REG_CTRL); val = (val & 0xFFFFFFF9) | PWM_MODE_CAPTURE; - writel_relaxed(val, pwm_base + PWM_REG_CTRL); + writel_relaxed(val, ddata->base + PWM_REG_CTRL); + //set clk div, clk div to 64 - val = readl_relaxed(pwm_base + PWM_REG_CTRL); + val = readl_relaxed(ddata->base + PWM_REG_CTRL); val = (val & 0xFF0001FF) | PWM_DIV64; - writel_relaxed(val, pwm_base + PWM_REG_CTRL); + writel_relaxed(val, ddata->base + PWM_REG_CTRL); + //4. enabled pwm int - rk_pwm_int_ctrl(pwm_base, pwm_id, PWM_INT_ENABLE); + ddata->pwm_data->funcs.int_ctrl(pdev, IR_WORK_MODE); + //5. enabled pwm - val = readl_relaxed(pwm_base + PWM_REG_CTRL); + val = readl_relaxed(ddata->base + PWM_REG_CTRL); val = (val & 0xFFFFFFFE) | PWM_ENABLE; - writel_relaxed(val, pwm_base + PWM_REG_CTRL); + writel_relaxed(val, ddata->base + PWM_REG_CTRL); + + return 0; +} + +static int rk_pwm_remotectl_hw_init_v4(struct platform_device *pdev) +{ + int val; + struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); + + //1. disabled pwm + val = PWM_EN(false) | PWM_CLK_EN(false); + writel_relaxed(val, ddata->base + PWM_REG_ENABLE_V4); + + //2. capture mode + val = PWM_MODE(CAPTURE_MODE); + writel_relaxed(val, ddata->base + PWM_REG_CTRL_V4); + + //3. set clk div, clk div to 64 + val = CLK_SCALE(32); + writel_relaxed(val, ddata->base + PWM_REG_CLK_CTRL_V4); + + //4. enabled pwm int + ddata->pwm_data->funcs.int_ctrl(pdev, IR_WORK_MODE); + + //5. enabled pwm + val = PWM_EN(true) | PWM_CLK_EN(true); + writel_relaxed(val, ddata->base + PWM_REG_ENABLE_V4); return 0; } @@ -573,9 +821,18 @@ static inline void rk_pwm_wakeup(struct input_dev *input) input_sync(input); } +static const struct of_device_id rk_pwm_of_match[] = { + { .compatible = "rockchip,remotectl-pwm", .data = &pwm_data_v1}, + { .compatible = "rockchip,remotectl-pwm-v4", .data = &pwm_data_v4}, + { } +}; + +MODULE_DEVICE_TABLE(of, rk_pwm_of_match); + static int rk_pwm_probe(struct platform_device *pdev) { struct rkxx_remotectl_drvdata *ddata; + const struct of_device_id *id; struct device_node *np = pdev->dev.of_node; struct resource *r; struct input_dev *input; @@ -592,20 +849,27 @@ static int rk_pwm_probe(struct platform_device *pdev) int count; pr_err(".. rk pwm remotectl v2.0 init\n"); + id = of_match_device(rk_pwm_of_match, &pdev->dev); + if (!id) + return -EINVAL; + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { dev_err(&pdev->dev, "no memory resources defined\n"); return -ENODEV; } + ddata = devm_kzalloc(&pdev->dev, sizeof(struct rkxx_remotectl_drvdata), GFP_KERNEL); if (!ddata) { - dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } + + ddata->pwm_data = id->data; ddata->state = RMC_PRELOAD; ddata->temp_period = 0; ddata->base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(ddata->base)) return PTR_ERR(ddata->base); count = of_property_count_strings(np, "clock-names"); @@ -675,14 +939,17 @@ static int rk_pwm_probe(struct platform_device *pdev) } ddata->irq = irq; ddata->wakeup = 1; - of_property_read_u32(np, "remote_pwm_id", &pwm_id); - pwm_id %= 4; - ddata->remote_pwm_id = pwm_id; - if (pwm_id > 3) { - dev_err(&pdev->dev, "pwm id error\n"); - goto error_pclk; + + if (ddata->pwm_data->pwm_version < 4) { + of_property_read_u32(np, "remote_pwm_id", &pwm_id); + pwm_id %= 4; + ddata->remote_pwm_id = pwm_id; + if (pwm_id > 3) { + dev_err(&pdev->dev, "pwm id error\n"); + goto error_pclk; + } + DBG("remotectl: remote pwm id=0x%x\n", pwm_id); } - DBG("remotectl: remote pwm id=0x%x\n", pwm_id); of_property_read_u32(np, "handle_cpu_id", &cpu_id); ddata->handle_cpu_id = cpu_id; DBG("remotectl: handle cpu id=0x%x\n", cpu_id); @@ -710,29 +977,25 @@ static int rk_pwm_probe(struct platform_device *pdev) cpumask_clear(&cpumask); cpumask_set_cpu(cpu_id, &cpumask); irq_set_affinity_hint(irq, &cpumask); - ret = devm_request_irq(&pdev->dev, irq, rockchip_pwm_irq, + ret = devm_request_irq(&pdev->dev, irq, ddata->pwm_data->funcs.irq_handler, IRQF_NO_SUSPEND, "rk_pwm_irq", ddata); if (ret) { dev_err(&pdev->dev, "cannot claim IRQ %d\n", irq); goto error_irq; } - pwm_freq = clk_get_rate(clk) / 64; ddata->pwm_freq_nstime = 1000000000 / pwm_freq; - rk_pwm_remotectl_hw_init(ddata->base, pwm_id); - + ddata->pwm_data->funcs.init_hw(pdev); ret = rk_pwm_pwrkey_wakeup_init(pdev); if (!ret) { dev_info(&pdev->dev, "Controller support pwrkey capture\n"); goto end; } - ret = rk_pwm_sip_wakeup_init(pdev); if (ret) dev_info(&pdev->dev, "Donot support ATF Wakeup\n"); else dev_info(&pdev->dev, "Support ATF Wakeup\n"); - DBG("rk pwm remotectl init end!\n"); end: return 0; @@ -754,15 +1017,13 @@ static int rk_pwm_remove(struct platform_device *pdev) static int remotectl_suspend(struct device *dev) { int cpu = 0; - int pwm_id; struct cpumask cpumask; struct platform_device *pdev = to_platform_device(dev); struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); if (ddata->pwm_pwrkey_capture) { - pwm_id = ddata->remote_pwm_id; ddata->pwrkey_wakeup = 0; - rk_pwm_int_ctrl(ddata->base, pwm_id, PWM_INT_DISABLE); + ddata->pwm_data->funcs.int_ctrl(pdev, IR_SUSPEND_MODE); } cpumask_clear(&cpumask); cpumask_set_cpu(cpu, &cpumask); @@ -770,11 +1031,9 @@ static int remotectl_suspend(struct device *dev) return 0; } - static int remotectl_resume(struct device *dev) { struct cpumask cpumask; - int pwm_id; struct platform_device *pdev = to_platform_device(dev); struct rkxx_remotectl_drvdata *ddata = platform_get_drvdata(pdev); int state; @@ -791,8 +1050,7 @@ static int remotectl_resume(struct device *dev) if (state == REMOTECTL_PWRKEY_WAKEUP) rk_pwm_wakeup(ddata->input); } else if (ddata->pwm_pwrkey_capture) { - pwm_id = ddata->remote_pwm_id; - rk_pwm_int_ctrl(ddata->base, pwm_id, PWM_INT_ENABLE); + ddata->pwm_data->funcs.int_ctrl(pdev, IR_WORK_MODE); if (ddata->pwrkey_wakeup == 0) return 0; ddata->pwrkey_wakeup = 0; @@ -808,13 +1066,6 @@ static const struct dev_pm_ops remotectl_pm_ops = { }; #endif -static const struct of_device_id rk_pwm_of_match[] = { - { .compatible = "rockchip,remotectl-pwm"}, - { } -}; - -MODULE_DEVICE_TABLE(of, rk_pwm_of_match); - static struct platform_driver rk_pwm_driver = { .driver = { .name = "remotectl-pwm", diff --git a/drivers/input/remotectl/rockchip_pwm_remotectl.h b/drivers/input/remotectl/rockchip_pwm_remotectl.h index 5126a3edb5d5..1232e799efb5 100644 --- a/drivers/input/remotectl/rockchip_pwm_remotectl.h +++ b/drivers/input/remotectl/rockchip_pwm_remotectl.h @@ -6,6 +6,7 @@ #define MAX_NUM_KEYS 60 #define PWM_PWR_KEY_CAPURURE_MAX 10 +#define PWM_PWR_KEY_CAPURURE_MAX_V4 16 /* PWM0 registers */ #define PWM_REG_CNTR 0x00 /* Counter Register */ @@ -93,52 +94,109 @@ enum pwm_div { PWM_DIV128 = (0x7 << 12), }; +/* + * regs for pwm v4 + */ +#define PWM_REG_VERSION_V4 0x0 +#define PWM_REG_ENABLE_V4 0x4 +#define PWM_REG_CLK_CTRL_V4 0x8 +#define PWM_REG_CTRL_V4 0xC +#define PWM_REG_HPR_V4 0x2C +#define PWM_REG_LPR_V4 0x30 +#define PWM_REG_INTSTS_V4 0x70 +#define PWM_REG_INT_EN_V4 0x74 +#define PWM_REG_MATCH_ARBITER_V4 0x100 +#define PWM_REG_MATCH_CTRL_V4 0x104 +#define PWM_REG_MATCH_LPRE_V4 0x108 +#define PWM_REG_MATCH_HPRE_V4 0x10C +#define PWM_REG_MATCH_LD_V4 0x110 +#define PWM_REG_MATCH_HD_ZERO_V4 0x114 +#define PWM_REG_MATCH_HD_ONE_V4 0x118 +#define PWM_REG_CAPTURE_VALUE0_V4 0x11C +#define PWM_REG_CAPTURE_VALUE_V4 0x15C + + +#define HIWORD_UPDATE(v, l, h) (((v) << (l)) | (GENMASK(h, l) << 16)) + +/* VERSION_ID */ +#define CHANNLE_INDEX_SHIFT 4 +#define CHANNLE_INDEX_MASK (0xf << CHANNLE_INDEX_SHIFT) + +/* PWM_CTRL */ +#define PWM_MODE(v) HIWORD_UPDATE(v, 0, 1) +#define CAPTURE_MODE 2 +#define CLK_SCALE(v) HIWORD_UPDATE(v, 4, 12) + +/* INTSTS */ +#define CAP_LPR_INTSTS_SHIFT 0 +#define CAP_HPR_INTSTS_SHIFT 1 +#define PWR_INTSTS_SHIFT 5 +#define CAP_LPR_INT BIT(CAP_LPR_INTSTS_SHIFT) +#define CAP_HPR_INT BIT(CAP_HPR_INTSTS_SHIFT) +#define PWR_INT BIT(PWR_INTSTS_SHIFT) + +/* INT_EN */ +#define CAP_LPR_INT_EN(v) HIWORD_UPDATE(v, 0, 0) +#define CAP_HPR_INT_EN(v) HIWORD_UPDATE(v, 1, 1) +#define PWR_INT_EN(v) HIWORD_UPDATE(v, 5, 5) + +/* INT_MASK */ +#define CAP_LPR_INT_MASK(v) HIWORD_UPDATE(v, 0, 0) +#define CAP_HPR_INT_MASK(v) HIWORD_UPDATE(v, 1, 1) +#define PWR_INT_MASK(v) HIWORD_UPDATE(v, 5, 5) + +/* PWRMATCH_ARBITER */ +#define PWRMATCH_GRANT_SHIFT 0 +#define PWRMATCH_READ_LOCK_SHIFT 16 +#define PWRKEY_EN(v) HIWORD_UPDATE(v, 0, 0) +#define PWM_CLK_EN(v) HIWORD_UPDATE(v, 0, 0) +#define PWM_EN(v) HIWORD_UPDATE(v, 1, 1) + + /* NEC Protocol */ -#define RK_PWM_TIME_PRE_MIN 4000 -#define RK_PWM_TIME_PRE_MAX 5000 +#define RK_PWM_TIME_PRE_MIN 4000 +#define RK_PWM_TIME_PRE_MAX 5000 -#define RK_PWM_TIME_PRE_MIN_LOW 8000 -#define RK_PWM_TIME_PRE_MAX_LOW 10000 +#define RK_PWM_TIME_PRE_MIN_LOW 8000 +#define RK_PWM_TIME_PRE_MAX_LOW 10000 -#define RK_PWM_TIME_BIT0_MIN 390 -#define RK_PWM_TIME_BIT0_MAX 730 +#define RK_PWM_TIME_BIT0_MIN 390 +#define RK_PWM_TIME_BIT0_MAX 730 -#define RK_PWM_TIME_BIT1_MIN 1300 -#define RK_PWM_TIME_BIT1_MAX 2000 +#define RK_PWM_TIME_BIT1_MIN 1300 +#define RK_PWM_TIME_BIT1_MAX 2000 -#define RK_PWM_TIME_BIT_MIN_LOW 390 -#define RK_PWM_TIME_BIT_MAX_LOW 730 +#define RK_PWM_TIME_BIT_MIN_LOW 390 +#define RK_PWM_TIME_BIT_MAX_LOW 730 -#define RK_PWM_TIME_RPT_MIN 2000 -#define RK_PWM_TIME_RPT_MAX 2500 +#define RK_PWM_TIME_RPT_MIN 2000 +#define RK_PWM_TIME_RPT_MAX 2500 -#define RK_PWM_TIME_SEQ1_MIN 95000 -#define RK_PWM_TIME_SEQ1_MAX 98000 +#define RK_PWM_TIME_SEQ1_MIN 95000 +#define RK_PWM_TIME_SEQ1_MAX 98000 -#define RK_PWM_TIME_SEQ2_MIN 30000 -#define RK_PWM_TIME_SEQ2_MAX 55000 +#define RK_PWM_TIME_SEQ2_MIN 30000 +#define RK_PWM_TIME_SEQ2_MAX 55000 -#define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10) -#define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14) -#define RK_PWM_VERSION_ID(n) ((3 - (n)) * 0x10 + 0x2c) -#define PWM_REG_PWRMATCH_CTRL(n) ((3 - (n)) * 0x10 + 0x50) -#define PWM_REG_PWRMATCH_LPRE(n) ((3 - (n)) * 0x10 + 0x54) -#define PWM_REG_PWRMATCH_HPRE(n) ((3 - (n)) * 0x10 + 0x58) -#define PWM_REG_PWRMATCH_LD(n) ((3 - (n)) * 0x10 + 0x5C) -#define PWM_REG_PWRMATCH_HD_ZERO(n) ((3 - (n)) * 0x10 + 0x60) -#define PWM_REG_PWRMATCH_HD_ONE(n) ((3 - (n)) * 0x10 + 0x64) -#define PWM_PWRMATCH_VALUE(n) ((3 - (n)) * 0x10 + 0x68) -#define PWM_PWRCAPTURE_VALUE(n) ((3 - (n)) * 0x10 + 0x9c) - -#define PWM_CH_INT(n) BIT(n) -#define PWM_CH_POL(n) BIT(n+8) - -#define PWM_CH_INT_ENABLE(n) BIT(n) -#define PWM_PWR_INT_ENABLE BIT(7) -#define CH3_PWRKEY_ENABLE BIT(3) +#define PWM_REG_INTSTS(n) ((3 - (n)) * 0x10 + 0x10) +#define PWM_REG_INT_EN(n) ((3 - (n)) * 0x10 + 0x14) +#define RK_PWM_VERSION_ID(n) ((3 - (n)) * 0x10 + 0x2c) +#define PWM_REG_PWRMATCH_CTRL(n) ((3 - (n)) * 0x10 + 0x50) +#define PWM_REG_PWRMATCH_LPRE(n) ((3 - (n)) * 0x10 + 0x54) +#define PWM_REG_PWRMATCH_HPRE(n) ((3 - (n)) * 0x10 + 0x58) +#define PWM_REG_PWRMATCH_LD(n) ((3 - (n)) * 0x10 + 0x5C) +#define PWM_REG_PWRMATCH_HD_ZERO(n) ((3 - (n)) * 0x10 + 0x60) +#define PWM_REG_PWRMATCH_HD_ONE(n) ((3 - (n)) * 0x10 + 0x64) +#define PWM_PWRMATCH_VALUE(n) ((3 - (n)) * 0x10 + 0x68) +#define PWM_PWRCAPTURE_VALUE(n) ((3 - (n)) * 0x10 + 0x9c) +#define PWM_CH_INT(n) BIT(n) +#define PWM_CH_POL(n) BIT(n+8) +#define PWM_CH_INT_ENABLE(n) BIT(n) +#define PWM_PWR_INT_ENABLE BIT(7) +#define CH3_PWRKEY_ENABLE BIT(3) typedef enum _RMC_STATE { @@ -149,6 +207,10 @@ typedef enum _RMC_STATE { RMC_SEQUENCE, } eRMC_STATE; +enum { + IR_SUSPEND_MODE = 0, + IR_WORK_MODE +}; struct RKxx_remotectl_platform_data { int nbuttons; diff --git a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c index 1c9d8655398e..e3053539e4e0 100644 --- a/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_bt1120_v4l2.c @@ -820,13 +820,12 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd) return 0; } - -static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd) +static void rk628_bt1120_initial(struct v4l2_subdev *sd) { struct rk628_bt1120 *bt1120 = to_bt1120(sd); struct v4l2_subdev_edid def_edid; - /* selete int io function */ + /* select int io function */ rk628_i2c_write(bt1120->rk628, GRF_GPIO3AB_SEL_CON, 0x30002000); rk628_i2c_write(bt1120->rk628, GRF_GPIO1AB_SEL_CON, HIWORD_UPDATE(0x7, 11, 8)); /* I2S_SCKM0 */ @@ -873,7 +872,13 @@ static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd) def_edid.edid = edid_init_data; rk628_bt1120_s_edid(sd, &def_edid); rk628_hdmirx_set_hdcp(bt1120->rk628, &bt1120->hdcp, false); +} +static void rk628_bt1120_initial_setup(struct v4l2_subdev *sd) +{ + struct rk628_bt1120 *bt1120 = to_bt1120(sd); + + rk628_bt1120_initial(sd); if (tx_5v_power_present(sd)) schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, 4000); } @@ -1685,6 +1690,91 @@ static irqreturn_t plugin_detect_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static int rk628_bt1120_power_on(struct rk628_bt1120 *bt1120) +{ + clk_prepare_enable(bt1120->soc_24M); + if (bt1120->enable_gpio) { + gpiod_set_value(bt1120->enable_gpio, 1); + usleep_range(10000, 11000); + } + gpiod_set_value(bt1120->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value(bt1120->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(bt1120->reset_gpio, 0); + usleep_range(10000, 11000); + + if (bt1120->power_gpio) { + gpiod_set_value(bt1120->power_gpio, 1); + usleep_range(10000, 11000); + } + + return 0; +} + +static int rk628_bt1120_power_off(struct rk628_bt1120 *bt1120) +{ + if (bt1120->enable_gpio) { + gpiod_set_value(bt1120->enable_gpio, 0); + usleep_range(10000, 11000); + } + gpiod_set_value(bt1120->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(bt1120->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value(bt1120->reset_gpio, 1); + usleep_range(10000, 11000); + + if (bt1120->power_gpio) { + gpiod_set_value(bt1120->power_gpio, 0); + usleep_range(10000, 11000); + } + clk_disable_unprepare(bt1120->soc_24M); + + return 0; +} + +static int rk628_bt1120_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_bt1120 *bt1120 = to_bt1120(sd); + + v4l2_info(sd, "%s: resume!\n", __func__); + + rk628_bt1120_power_on(bt1120); + rk628_cru_initialize(bt1120->rk628); + rk628_bt1120_initial(sd); + rk628_hdmirx_plugout(sd); + enable_irq(bt1120->hdmirx_irq); + schedule_delayed_work(&bt1120->delayed_work_enable_hotplug, + msecs_to_jiffies(500)); + + return 0; +} + +static int rk628_bt1120_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_bt1120 *bt1120 = to_bt1120(sd); + + v4l2_info(sd, "%s: suspend!\n", __func__); + + disable_irq(bt1120->hdmirx_irq); + cancel_delayed_work_sync(&bt1120->delayed_work_res_change); + cancel_delayed_work_sync(&bt1120->delayed_work_enable_hotplug); + rk628_hdmirx_audio_cancel_work_audio(bt1120->audio_info, true); + rk628_bt1120_power_off(bt1120); + + return 0; +} + +static const struct dev_pm_ops rk628_bt1120_pm_ops = { + .suspend = rk628_bt1120_suspend, + .resume = rk628_bt1120_resume, +}; + static int rk628_bt1120_probe_of(struct rk628_bt1120 *bt1120) { struct device *dev = bt1120->dev; @@ -1701,28 +1791,27 @@ static int rk628_bt1120_probe_of(struct rk628_bt1120 *bt1120) ret = PTR_ERR(bt1120->soc_24M); dev_err(dev, "Unable to get soc_24M: %d\n", ret); } - clk_prepare_enable(bt1120->soc_24M); bt1120->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(bt1120->enable_gpio)) { ret = PTR_ERR(bt1120->enable_gpio); dev_err(dev, "failed to request enable GPIO: %d\n", ret); - goto clk_put; + return ret; } bt1120->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(bt1120->reset_gpio)) { ret = PTR_ERR(bt1120->reset_gpio); dev_err(dev, "failed to request reset GPIO: %d\n", ret); - goto clk_put; + return ret; } bt1120->power_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(bt1120->power_gpio)) { dev_err(dev, "failed to get power gpio\n"); ret = PTR_ERR(bt1120->power_gpio); - goto clk_put; + return ret; } bt1120->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", @@ -1730,26 +1819,10 @@ static int rk628_bt1120_probe_of(struct rk628_bt1120 *bt1120) if (IS_ERR(bt1120->plugin_det_gpio)) { dev_err(dev, "failed to get hdmirx det gpio\n"); ret = PTR_ERR(bt1120->plugin_det_gpio); - goto clk_put; + return ret; } bt1120->rk628->hdmirx_det_gpio = bt1120->plugin_det_gpio; - if (bt1120->enable_gpio) { - gpiod_set_value(bt1120->enable_gpio, 1); - usleep_range(10000, 11000); - } - gpiod_set_value(bt1120->reset_gpio, 0); - usleep_range(10000, 11000); - gpiod_set_value(bt1120->reset_gpio, 1); - usleep_range(10000, 11000); - gpiod_set_value(bt1120->reset_gpio, 0); - usleep_range(10000, 11000); - - if (bt1120->power_gpio) { - gpiod_set_value(bt1120->power_gpio, 1); - usleep_range(500, 510); - } - if (of_property_read_bool(dev->of_node, "hdcp-enable")) hdcp1x_enable = true; @@ -1769,14 +1842,14 @@ static int rk628_bt1120_probe_of(struct rk628_bt1120 *bt1120) if (!ep) { dev_err(dev, "missing endpoint node\n"); ret = -EINVAL; - goto clk_put; + return ret; } ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint); of_node_put(ep); if (ret) { dev_err(dev, "failed to parse endpoint\n"); - goto clk_put; + return ret; } bt1120->enable_hdcp = hdcp1x_enable; @@ -1793,9 +1866,6 @@ static int rk628_bt1120_probe_of(struct rk628_bt1120 *bt1120) v4l2_fwnode_endpoint_free(&endpoint); -clk_put: - clk_disable_unprepare(bt1120->soc_24M); - return ret; } @@ -1855,6 +1925,7 @@ static int rk628_bt1120_probe(struct i2c_client *client, return err; } + rk628_bt1120_power_on(bt1120); rk628_cru_initialize(rk628); rk628_version_parse(rk628); @@ -2007,6 +2078,7 @@ err_hdl: mutex_destroy(&bt1120->confctl_mutex); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(&bt1120->hdl); + rk628_bt1120_power_off(bt1120); return err; } @@ -2039,6 +2111,7 @@ static void rk628_bt1120_remove(struct i2c_client *client) rk628_control_assert(bt1120->rk628, RGU_CLK_RX); rk628_control_assert(bt1120->rk628, RGU_VOP); rk628_control_assert(bt1120->rk628, RGU_BT1120DEC); + rk628_bt1120_power_off(bt1120); } static const struct i2c_device_id rk628_bt1120_i2c_id[] = { @@ -2057,6 +2130,7 @@ MODULE_DEVICE_TABLE(of, rk628_bt1120_of_match); static struct i2c_driver rk628_bt1120_i2c_driver = { .driver = { .name = "rk628-bt1120-v4l2", + .pm = &rk628_bt1120_pm_ops, .of_match_table = of_match_ptr(rk628_bt1120_of_match), }, .id_table = rk628_bt1120_i2c_id, diff --git a/drivers/media/i2c/rk628/rk628_csi_v4l2.c b/drivers/media/i2c/rk628/rk628_csi_v4l2.c index dd96d6d2ded4..15c970f73d2f 100644 --- a/drivers/media/i2c/rk628/rk628_csi_v4l2.c +++ b/drivers/media/i2c/rk628/rk628_csi_v4l2.c @@ -1277,14 +1277,14 @@ static int rk628_hdmirx_phy_setup(struct v4l2_subdev *sd) return 0; } -static void rk628_csi_initial_setup(struct v4l2_subdev *sd) +static void rk628_csi_initial(struct v4l2_subdev *sd) { struct rk628_csi *csi = to_csi(sd); struct v4l2_subdev_edid def_edid; u32 mask = SW_OUTPUT_MODE_MASK; u32 val = SW_OUTPUT_MODE(OUTPUT_MODE_CSI); - /* selete int io function */ + /* select int io function */ rk628_i2c_write(csi->rk628, GRF_GPIO3AB_SEL_CON, 0x30002000); rk628_i2c_write(csi->rk628, GRF_GPIO1AB_SEL_CON, HIWORD_UPDATE(0xf, 11, 8)); /* I2S_SCKM0 */ @@ -1341,7 +1341,13 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd) def_edid.edid = edid_init_data; rk628_csi_s_edid(sd, &def_edid); rk628_hdmirx_set_hdcp(csi->rk628, &csi->hdcp, false); +} +static void rk628_csi_initial_setup(struct v4l2_subdev *sd) +{ + struct rk628_csi *csi = to_csi(sd); + + rk628_csi_initial(sd); if (csi->rk628->version >= RK628F_VERSION) { csi->rk628->mipi_timing[0] = rk628f_csi0_mipi; csi->rk628->mipi_timing[1] = rk628f_csi1_mipi; @@ -2627,6 +2633,91 @@ static irqreturn_t plugin_detect_irq(int irq, void *dev_id) return IRQ_HANDLED; } +static int rk628_csi_power_on(struct rk628_csi *csi) +{ + clk_prepare_enable(csi->soc_24M); + if (csi->enable_gpio) { + gpiod_set_value(csi->enable_gpio, 1); + usleep_range(10000, 11000); + } + gpiod_set_value(csi->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value(csi->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(csi->reset_gpio, 0); + usleep_range(10000, 11000); + + if (csi->power_gpio) { + gpiod_set_value(csi->power_gpio, 1); + usleep_range(10000, 11000); + } + + return 0; +} + +static int rk628_csi_power_off(struct rk628_csi *csi) +{ + if (csi->enable_gpio) { + gpiod_set_value(csi->enable_gpio, 0); + usleep_range(10000, 11000); + } + gpiod_set_value(csi->reset_gpio, 1); + usleep_range(10000, 11000); + gpiod_set_value(csi->reset_gpio, 0); + usleep_range(10000, 11000); + gpiod_set_value(csi->reset_gpio, 1); + usleep_range(10000, 11000); + + if (csi->power_gpio) { + gpiod_set_value(csi->power_gpio, 0); + usleep_range(10000, 11000); + } + clk_disable_unprepare(csi->soc_24M); + + return 0; +} + +static int rk628_csi_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_csi *csi = to_csi(sd); + + v4l2_info(sd, "%s: resume!\n", __func__); + + rk628_csi_power_on(csi); + rk628_cru_initialize(csi->rk628); + rk628_csi_initial(sd); + rk628_hdmirx_plugout(sd); + enable_irq(csi->hdmirx_irq); + schedule_delayed_work(&csi->delayed_work_enable_hotplug, + msecs_to_jiffies(500)); + + return 0; +} + +static int rk628_csi_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct rk628_csi *csi = to_csi(sd); + + v4l2_info(sd, "%s: suspend!\n", __func__); + + disable_irq(csi->hdmirx_irq); + cancel_delayed_work_sync(&csi->delayed_work_res_change); + cancel_delayed_work_sync(&csi->delayed_work_enable_hotplug); + rk628_hdmirx_audio_cancel_work_audio(csi->audio_info, true); + rk628_csi_power_off(csi); + + return 0; +} + +static const struct dev_pm_ops rk628_csi_pm_ops = { + .suspend = rk628_csi_suspend, + .resume = rk628_csi_resume, +}; + static int rk628_csi_probe_of(struct rk628_csi *csi) { struct device *dev = csi->dev; @@ -2644,28 +2735,27 @@ static int rk628_csi_probe_of(struct rk628_csi *csi) ret = PTR_ERR(csi->soc_24M); dev_err(dev, "Unable to get soc_24M: %d\n", ret); } - clk_prepare_enable(csi->soc_24M); csi->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(csi->enable_gpio)) { ret = PTR_ERR(csi->enable_gpio); dev_err(dev, "failed to request enable GPIO: %d\n", ret); - goto clk_put; + return ret; } csi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(csi->reset_gpio)) { ret = PTR_ERR(csi->reset_gpio); dev_err(dev, "failed to request reset GPIO: %d\n", ret); - goto clk_put; + return ret; } csi->power_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_HIGH); if (IS_ERR(csi->power_gpio)) { dev_err(dev, "failed to get power gpio\n"); ret = PTR_ERR(csi->power_gpio); - goto clk_put; + return ret; } csi->plugin_det_gpio = devm_gpiod_get_optional(dev, "plugin-det", @@ -2673,26 +2763,10 @@ static int rk628_csi_probe_of(struct rk628_csi *csi) if (IS_ERR(csi->plugin_det_gpio)) { dev_err(dev, "failed to get hdmirx det gpio\n"); ret = PTR_ERR(csi->plugin_det_gpio); - goto clk_put; + return ret; } csi->rk628->hdmirx_det_gpio = csi->plugin_det_gpio; - if (csi->enable_gpio) { - gpiod_set_value(csi->enable_gpio, 1); - usleep_range(10000, 11000); - } - gpiod_set_value(csi->reset_gpio, 0); - usleep_range(10000, 11000); - gpiod_set_value(csi->reset_gpio, 1); - usleep_range(10000, 11000); - gpiod_set_value(csi->reset_gpio, 0); - usleep_range(10000, 11000); - - if (csi->power_gpio) { - gpiod_set_value(csi->power_gpio, 1); - usleep_range(500, 510); - } - if (of_property_read_bool(dev->of_node, "hdcp-enable")) hdcp1x_enable = true; @@ -2719,7 +2793,7 @@ static int rk628_csi_probe_of(struct rk628_csi *csi) if (!ep) { dev_err(dev, "missing endpoint node\n"); ret = -EINVAL; - goto clk_put; + return ret; } ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint); @@ -2754,8 +2828,6 @@ free_endpoint: v4l2_fwnode_endpoint_free(&endpoint); put_node: of_node_put(ep); -clk_put: - clk_disable_unprepare(csi->soc_24M); return ret; } @@ -2912,6 +2984,7 @@ static int rk628_csi_probe(struct i2c_client *client, return err; } + rk628_csi_power_on(csi); rk628_cru_initialize(csi->rk628); rk628_version_parse(rk628); @@ -2922,14 +2995,15 @@ static int rk628_csi_probe(struct i2c_client *client, v4l2_info(sd, "get multi dev info failed, not use dual mipi mode\n"); } - v4l2_subdev_init(sd, &rk628_csi_ops); + v4l2_i2c_subdev_init(sd, client, &rk628_csi_ops); sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS; /* i2c access, read chip id*/ err = rk628_i2c_read(csi->rk628, CSITX_CSITX_VERSION, &val); if (err) { v4l2_err(sd, "i2c access failed! err:%d\n", err); - return -ENODEV; + err = -ENODEV; + goto power_off; } v4l2_dbg(1, debug, sd, "CSITX VERSION: %#x\n", val); @@ -2937,7 +3011,8 @@ static int rk628_csi_probe(struct i2c_client *client, err = rk628_i2c_read(csi->rk628, CSITX1_CSITX_VERSION, &val); if (err) { v4l2_err(sd, "i2c access failed! err:%d\n", err); - return -ENODEV; + err = -ENODEV; + goto power_off; } v4l2_dbg(1, debug, sd, "CSITX1 VERSION: %#x\n", val); } @@ -2947,7 +3022,8 @@ static int rk628_csi_probe(struct i2c_client *client, csi->txphy = rk628_txphy_register(rk628); if (!csi->txphy) { v4l2_err(sd, "register txphy failed\n"); - return -ENOMEM; + err = -ENOMEM; + goto power_off; } /* control handlers */ @@ -3095,6 +3171,9 @@ err_hdl: mutex_destroy(&csi->confctl_mutex); media_entity_cleanup(&sd->entity); v4l2_ctrl_handler_free(&csi->hdl); +power_off: + rk628_csi_power_off(csi); + return err; } @@ -3136,6 +3215,7 @@ static int rk628_csi_remove(struct i2c_client *client) rk628_control_assert(csi->rk628, RGU_CSI); if (csi->rk628->version >= RK628F_VERSION) rk628_control_assert(csi->rk628, RGU_CSI1); + rk628_csi_power_off(csi); #if KERNEL_VERSION(6, 1, 0) > LINUX_VERSION_CODE return 0; #endif @@ -3144,6 +3224,7 @@ static int rk628_csi_remove(struct i2c_client *client) static struct i2c_driver rk628_csi_i2c_driver = { .driver = { .name = "rk628-csi-v4l2", + .pm = &rk628_csi_pm_ops, .of_match_table = of_match_ptr(rk628_csi_of_match), }, .id_table = rk628_csi_i2c_id, diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 85f85ae797bc..ab66e49ede13 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -1835,6 +1835,52 @@ RDBK_TOISP_UNMATCH: spin_unlock_irqrestore(&dev->hdr_lock, flags); } +static void rkcif_get_other_dev_update_frame_addr(struct rkcif_stream *stream, + int dev_idx, + u32 *frm_addr_y, + u32 *frm_addr_uv) +{ + struct v4l2_mbus_config *mbus_cfg = &stream->cifdev->active_sensor->mbus; + u32 intstat = stream->cifdev->other_intstat[dev_idx]; + int frame_phase = 0; + + switch (stream->id) { + case RKCIF_STREAM_MIPI_ID0: + frame_phase = SW_FRM_END_ID0(intstat); + break; + case RKCIF_STREAM_MIPI_ID1: + frame_phase = SW_FRM_END_ID1(intstat); + break; + case RKCIF_STREAM_MIPI_ID2: + frame_phase = SW_FRM_END_ID2(intstat); + break; + case RKCIF_STREAM_MIPI_ID3: + frame_phase = SW_FRM_END_ID3(intstat); + break; + } + + if (frame_phase == 0) + return; + + if (mbus_cfg->type == V4L2_MBUS_CSI2_DPHY || + mbus_cfg->type == V4L2_MBUS_CSI2_CPHY || + mbus_cfg->type == V4L2_MBUS_CCP2) { + *frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ? + get_reg_index_of_frm0_y_addr(stream->id) : + get_reg_index_of_frm1_y_addr(stream->id); + *frm_addr_uv = frame_phase & CIF_CSI_FRAME0_READY ? + get_reg_index_of_frm0_uv_addr(stream->id) : + get_reg_index_of_frm1_uv_addr(stream->id); + } else { + *frm_addr_y = frame_phase & CIF_CSI_FRAME0_READY ? + get_dvp_reg_index_of_frm0_y_addr(stream->id) : + get_dvp_reg_index_of_frm1_y_addr(stream->id); + *frm_addr_uv = frame_phase & CIF_CSI_FRAME0_READY ? + get_dvp_reg_index_of_frm0_uv_addr(stream->id) : + get_dvp_reg_index_of_frm1_uv_addr(stream->id); + } +} + static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream, u32 frm_addr_y, u32 frm_addr_uv, u32 buff_addr_y, u32 buff_addr_cbcr, @@ -1846,8 +1892,11 @@ static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream, int addr_offset = 0; int i = 0; int tmp_host_index = dev->csi_host_idx; + u32 tmp_frm_addr_y, tmp_frm_addr_uv; for (i = 0; i < capture_info->multi_dev.dev_num; i++) { + tmp_frm_addr_y = frm_addr_y; + tmp_frm_addr_uv = frm_addr_uv; if (is_dummy_buf) { addr_y = buff_addr_y; } else { @@ -1855,7 +1904,11 @@ static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream, addr_y = buff_addr_y + addr_offset * i; } dev->csi_host_idx = capture_info->multi_dev.dev_idx[i]; - rkcif_write_register(dev, frm_addr_y, addr_y); + if (i < capture_info->multi_dev.dev_num - 1) + rkcif_get_other_dev_update_frame_addr(stream, i, + &tmp_frm_addr_y, + &tmp_frm_addr_uv); + rkcif_write_register(dev, tmp_frm_addr_y, addr_y); if (stream->cif_fmt_out->fmt_type != CIF_FMT_TYPE_RAW && frm_addr_uv && buff_addr_cbcr) { if (is_dummy_buf) { @@ -1864,7 +1917,7 @@ static void rkcif_write_buff_addr_multi_dev_combine(struct rkcif_stream *stream, addr_offset = dev->channels[stream->id].left_virtual_width; addr_cbcr = buff_addr_cbcr + addr_offset * i; } - rkcif_write_register(dev, frm_addr_uv, addr_cbcr); + rkcif_write_register(dev, tmp_frm_addr_uv, addr_cbcr); } } dev->csi_host_idx = tmp_host_index; @@ -4939,12 +4992,26 @@ static void rkcif_do_cru_reset(struct rkcif_device *dev) void rkcif_do_soft_reset(struct rkcif_device *dev) { + struct csi_channel_info *channel = &dev->channels[0]; + int tmp_csi_host_idx = 0; + int i = 0; + if (dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_DPHY || dev->active_sensor->mbus.type == V4L2_MBUS_CSI2_CPHY || - dev->active_sensor->mbus.type == V4L2_MBUS_CCP2) - rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); - else + dev->active_sensor->mbus.type == V4L2_MBUS_CCP2) { + if (channel->capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + tmp_csi_host_idx = dev->csi_host_idx; + for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { + dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + } + dev->csi_host_idx = tmp_csi_host_idx; + } else { + rkcif_write_register_or(dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + } + } else { rkcif_write_register_or(dev, CIF_REG_DVP_CTRL, 0x000A0000); + } usleep_range(10, 20); v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev, "vicap do soft reset 0x%x\n", 0x000A0000); @@ -5044,6 +5111,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, struct rkcif_buffer *buf = NULL; int ret; struct rkcif_hw *hw_dev = dev->hw_dev; + struct rkmodule_capture_info *capture_info = &dev->channels[0].capture_info; bool can_reset = true; int i; unsigned long flags; @@ -5186,6 +5254,10 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, if (dev->can_be_reset && dev->chip_id >= CHIP_RK3588_CIF) { rkcif_do_soft_reset(dev); atomic_set(&dev->streamoff_cnt, 0); + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + for (i = 0; i < capture_info->multi_dev.dev_num - 1; i++) + dev->other_intstat[i] = 0; + } } if (dev->can_be_reset && can_reset) { dev->can_be_reset = false; @@ -11302,17 +11374,39 @@ static void rkcif_check_mipi_interlaced_frame_id(struct rkcif_stream *stream) stream->last_fs_interlaced_phase = fs_interlaced_phase; } +static void rkcif_save_other_intstat_with_combine_mode(struct rkcif_device *cif_dev) +{ + struct rkmodule_capture_info *capture_info = &cif_dev->channels[0].capture_info; + int i = 0; + int tmp_csi_host = 0; + + if (capture_info->mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + tmp_csi_host = cif_dev->csi_host_idx; + for (i = 0; i < capture_info->multi_dev.dev_num - 1; i++) { + cif_dev->csi_host_idx = capture_info->multi_dev.dev_idx[i]; + cif_dev->other_intstat[i] = rkcif_read_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT); + if (cif_dev->other_intstat[i]) + rkcif_write_register(cif_dev, + CIF_REG_MIPI_LVDS_INTSTAT, + cif_dev->other_intstat[i]); + } + cif_dev->csi_host_idx = tmp_csi_host; + } +} + /* pingpong irq for rk3588 and next */ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) { struct rkcif_stream *stream; struct rkcif_stream *detect_stream = &cif_dev->stream[0]; struct v4l2_mbus_config *mbus; + struct csi_channel_info *channel = &cif_dev->channels[0]; unsigned int intstat, i = 0xff; unsigned long flags; bool is_update = false; int ret = 0; int on = 0; + int tmp_csi_host_idx = 0; if (!cif_dev->active_sensor) return; @@ -11329,6 +11423,7 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) cif_dev->err_state_work.lastline = lastline; cif_dev->err_state_work.intstat = intstat; + rkcif_save_other_intstat_with_combine_mode(cif_dev); /* clear all interrupts that has been triggered */ if (intstat) { rkcif_write_register(cif_dev, CIF_REG_MIPI_LVDS_INTSTAT, intstat); @@ -11351,7 +11446,16 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } cif_dev->irq_stats.csi_size_err_cnt++; cif_dev->err_state |= RKCIF_ERR_SIZE; - rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + if (cif_dev->channels[0].capture_info.mode == RKMODULE_MULTI_DEV_COMBINE_ONE) { + tmp_csi_host_idx = cif_dev->csi_host_idx; + for (i = 0; i < channel->capture_info.multi_dev.dev_num; i++) { + cif_dev->csi_host_idx = channel->capture_info.multi_dev.dev_idx[i]; + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + } + cif_dev->csi_host_idx = tmp_csi_host_idx; + } else { + rkcif_write_register_or(cif_dev, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000); + } return; } diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 9f2113408f96..dfc0a690191c 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -939,6 +939,7 @@ struct rkcif_device { int sensor_state; u32 intr_mask; struct delayed_work work_deal_err; + u32 other_intstat[RKMODULE_MULTI_DEV_NUM]; }; extern struct platform_driver rkcif_plat_drv; diff --git a/drivers/misc/rk628/rk628.c b/drivers/misc/rk628/rk628.c index 4cbba8aa6cda..a2781653a3c7 100644 --- a/drivers/misc/rk628/rk628.c +++ b/drivers/misc/rk628/rk628.c @@ -672,49 +672,56 @@ static bool rk628_display_route_check(struct rk628 *rk628) return true; } -static void rk628_final_display_route(struct rk628 *rk628) +static void rk628_current_display_route(struct rk628 *rk628, char *input_s, + int input_s_len, char *output_s, + int output_s_len) { - char *input = NULL; - char *output = NULL; - char buf[20]; + *input_s = '\0'; + *output_s = '\0'; - if (rk628_input_is_hdmi(rk628)) - input = "hdmi"; + if (rk628_input_is_rgb(rk628)) + strlcat(input_s, "RGB", input_s_len); else if (rk628_input_is_bt1120(rk628)) - input = "bt1120"; + strlcat(input_s, "BT1120", input_s_len); + else if (rk628_input_is_hdmi(rk628)) + strlcat(input_s, "HDMI", input_s_len); else - input = "rgb"; + strlcat(input_s, "unknown", input_s_len); + + if (rk628_output_is_rgb(rk628)) + strlcat(output_s, "RGB ", output_s_len); + + if (rk628_output_is_bt1120(rk628)) + strlcat(output_s, "BT1120 ", output_s_len); if (rk628_output_is_gvi(rk628)) - output = "gvi"; - else if (rk628_output_is_lvds(rk628)) - output = "lvds"; - else if (rk628_output_is_dsi(rk628)) - output = "dsi"; - else if (rk628_output_is_csi(rk628)) - output = "csi"; + strlcat(output_s, "GVI ", output_s_len); - if (rk628_output_is_bt1120(rk628)) { - if (output) - sprintf(buf, "%s & %s", output, "bt1120"); - else - output = "bt1120"; - } else if (rk628_output_is_rgb(rk628)) { - if (output) - sprintf(buf, "%s & %s", output, "rgb"); - else - output = "rgb"; - } + if (rk628_output_is_lvds(rk628)) + strncat(output_s, "LVDS ", output_s_len); - if (rk628_output_is_hdmi(rk628)) { - if (output) - sprintf(buf, "%s & %s", output, "hdmi"); - else - output = "hdmi"; - } + if (rk628_output_is_dsi(rk628)) + strlcat(output_s, "DSI ", output_s_len); - dev_info(rk628->dev, "input_mode:%s output_mode:%s\n", input, - hweight32(rk628->output_mode) > 1 ? buf : output); + if (rk628_output_is_csi(rk628)) + strlcat(output_s, "CSI ", output_s_len); + + if (rk628_output_is_hdmi(rk628)) + strlcat(output_s, "HDMI ", output_s_len); + + if (!strlen(output_s)) + strlcat(output_s, "unknown", output_s_len); +} + +static void rk628_show_current_display_route(struct rk628 *rk628) +{ + char input_s[10], output_s[30]; + + rk628_current_display_route(rk628, input_s, sizeof(input_s), + output_s, sizeof(output_s)); + + dev_info(rk628->dev, "input_mode: %s, output_mode: %s\n", input_s, + output_s); } static int rk628_display_route_info_parse(struct rk628 *rk628) @@ -723,40 +730,50 @@ static int rk628_display_route_info_parse(struct rk628 *rk628) int ret = 0; u32 val; - if (of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-in")) { + if (of_property_read_bool(rk628->dev->of_node, "rk628-hdmi-in") || + of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-in")) { rk628->input_mode = BIT(INPUT_MODE_HDMI); - } else if (of_property_read_bool(rk628->dev->of_node, "rk628,rgb-in")) { + } else if (of_property_read_bool(rk628->dev->of_node, "rk628-rgb-in") || + of_property_read_bool(rk628->dev->of_node, "rk628,rgb-in")) { rk628->input_mode = BIT(INPUT_MODE_RGB); ret = rk628_rgb_parse(rk628, NULL); - } else if (of_property_read_bool(rk628->dev->of_node, "rk628,bt1120-in")) { + } else if (of_property_read_bool(rk628->dev->of_node, "rk628-bt1120-in") || + of_property_read_bool(rk628->dev->of_node, "rk628,bt1120-in")) { rk628->input_mode = BIT(INPUT_MODE_BT1120); ret = rk628_rgb_parse(rk628, NULL); } else { rk628->input_mode = BIT(INPUT_MODE_RGB); } - if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-gvi"))) { + if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-gvi-out")) || + (np = of_get_child_by_name(rk628->dev->of_node, "rk628-gvi"))) { rk628->output_mode |= BIT(OUTPUT_MODE_GVI); ret = rk628_gvi_parse(rk628, np); - } else if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-lvds"))) { + } else if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-lvds-out")) || + (np = of_get_child_by_name(rk628->dev->of_node, "rk628-lvds"))) { rk628->output_mode |= BIT(OUTPUT_MODE_LVDS); ret = rk628_lvds_parse(rk628, np); - } else if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-dsi"))) { + } else if ((np = of_get_child_by_name(rk628->dev->of_node, "rk628-dsi-out")) || + (np = of_get_child_by_name(rk628->dev->of_node, "rk628-dsi"))) { rk628->output_mode |= BIT(OUTPUT_MODE_DSI); ret = rk628_dsi_parse(rk628, np); - } else if (of_property_read_bool(rk628->dev->of_node, "rk628,csi-out")) { + } else if (of_property_read_bool(rk628->dev->of_node, "rk628-csi-out") || + of_property_read_bool(rk628->dev->of_node, "rk628,csi-out")) { rk628->output_mode |= BIT(OUTPUT_MODE_CSI); } if (np) of_node_put(np); - if (of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-out")) + if (of_property_read_bool(rk628->dev->of_node, "rk628-hdmi-out") || + of_property_read_bool(rk628->dev->of_node, "rk628,hdmi-out")) rk628->output_mode |= BIT(OUTPUT_MODE_HDMI); - if (of_property_read_bool(rk628->dev->of_node, "rk628-rgb")) { + if (of_property_read_bool(rk628->dev->of_node, "rk628-rgb-out") || + of_property_read_bool(rk628->dev->of_node, "rk628-rgb")) { rk628->output_mode |= BIT(OUTPUT_MODE_RGB); ret = rk628_rgb_parse(rk628, NULL); - } else if (of_property_read_bool(rk628->dev->of_node, "rk628-bt1120")) { + } else if (of_property_read_bool(rk628->dev->of_node, "rk628-bt1120-out") || + of_property_read_bool(rk628->dev->of_node, "rk628-bt1120")) { rk628->output_mode |= BIT(OUTPUT_MODE_BT1120); ret = rk628_rgb_parse(rk628, NULL); } @@ -879,25 +896,6 @@ static int rk628_display_timings_get(struct rk628 *rk628) pr_info(args); \ } while (0) -static void rk628_show_input_mode(struct seq_file *s) -{ - struct rk628 *rk628 = s->private; - char input_s[10] = {0}; - - /* show input mode */ - if (rk628_input_is_hdmi(rk628)) - strcpy(input_s, "HDMI"); - else if (rk628_input_is_bt1120(rk628)) - strcpy(input_s, "BT1120"); - else if (rk628_input_is_rgb(rk628)) - strcpy(input_s, "RGB"); - - if (!strlen(input_s)) - strcpy(input_s, "unknown "); - - DEBUG_PRINT("input: %s\n", input_s); -} - static void rk628_show_resolution(struct seq_file *s) { struct rk628 *rk628 = s->private; @@ -995,38 +993,6 @@ static void rk628_show_input_resolution(struct seq_file *s) rk628_show_resolution(s); } -static void rk628_show_output_mode(struct seq_file *s) -{ - struct rk628 *rk628 = s->private; - char output_s[30] = {0}; - char *p = output_s; - - if (rk628_output_is_gvi(rk628)) - strcpy(p, "GVI "); - else if (rk628_output_is_lvds(rk628)) - strcpy(p, "LVDS "); - else if (rk628_output_is_dsi(rk628)) - strcpy(p, "DSI "); - else if (rk628_output_is_csi(rk628)) - strcpy(p, "CSI "); - p += strlen(p); - - if (rk628_output_is_hdmi(rk628)) { - strcpy(p, "HDMI "); - p += strlen(p); - } - - if (rk628_output_is_rgb(rk628)) - strcpy(p, "RGB "); - else if (rk628_output_is_bt1120(rk628)) - strcpy(p, "BT1120 "); - - if (!strlen(output_s)) - strcpy(p, "unknown "); - - DEBUG_PRINT("output: %s\n", output_s); -} - static void rk628_show_output_resolution(struct seq_file *s) { struct rk628 *rk628 = s->private; @@ -1137,16 +1103,20 @@ static void rk628_show_csc_info(struct seq_file *s) static int rk628_debugfs_dump(struct seq_file *s, void *data) { struct rk628 *rk628 = s->private; + char input_s[10], output_s[30]; u32 val; int sw_hsync_pol, sw_vsync_pol; u32 dsp_frame_v_start, dsp_frame_h_start; + rk628_current_display_route(rk628, input_s, sizeof(input_s), + output_s, sizeof(output_s)); + /* show input info */ - rk628_show_input_mode(s); + DEBUG_PRINT("input: %s\n", input_s); rk628_show_input_resolution(s); /* show output info */ - rk628_show_output_mode(s); + DEBUG_PRINT("output: %s\n", output_s); rk628_show_output_resolution(s); /* show csc info */ @@ -1443,13 +1413,14 @@ rk628_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret) goto err_clk; + rk628_show_current_display_route(rk628); + if (!rk628_display_route_check(rk628)) { dev_err(dev, "display route check err\n"); ret = -EINVAL; goto err_clk; } - rk628_final_display_route(rk628); rk628_pwr_consumption_init(rk628); #ifdef CONFIG_FB diff --git a/drivers/misc/rk628/rk628_dsi.c b/drivers/misc/rk628/rk628_dsi.c index 9f93bfe35ffe..6a49ed10e783 100644 --- a/drivers/misc/rk628/rk628_dsi.c +++ b/drivers/misc/rk628/rk628_dsi.c @@ -830,7 +830,10 @@ static u32 rk628_dsi_get_lane_rate(const struct rk628_dsi *dsi) u32 max_lane_rate = 1500; u8 bpp, lanes; - dsi_np = of_find_node_by_name(dsi->rk628->dev->of_node, "rk628-dsi"); + dsi_np = of_find_node_by_name(dsi->rk628->dev->of_node, "rk628-dsi-out"); + if (!dsi_np) + dsi_np = of_find_node_by_name(dsi->rk628->dev->of_node, + "rk628-dsi"); if (dsi_np && !of_property_read_u32(dsi_np, "rockchip,lane-mbps", &value)) { lane_rate = value; } else { diff --git a/drivers/soc/rockchip/rockchip_ipa.c b/drivers/soc/rockchip/rockchip_ipa.c index e8982b7defee..51cbdabfd88f 100644 --- a/drivers/soc/rockchip/rockchip_ipa.c +++ b/drivers/soc/rockchip/rockchip_ipa.c @@ -200,6 +200,9 @@ rockchip_ipa_get_static_power(struct ipa_power_model_data *data, int temp; int ret; + if (!data) + return 0; + ret = data->tz->ops->get_temp(data->tz, &temp); if (ret) { pr_err("%s:failed to read %s temp\n", diff --git a/drivers/video/rockchip/mpp/mpp_av1dec.c b/drivers/video/rockchip/mpp/mpp_av1dec.c index 5dd5f59639d3..2d2055afc1a4 100644 --- a/drivers/video/rockchip/mpp/mpp_av1dec.c +++ b/drivers/video/rockchip/mpp/mpp_av1dec.c @@ -994,7 +994,7 @@ static int av1dec_probe(struct platform_device *pdev) return -ENOMEM; mpp = &dec->mpp; - platform_set_drvdata(pdev, dec); + platform_set_drvdata(pdev, mpp); if (pdev->dev.of_node) { match = of_match_node(mpp_av1dec_dt_match, pdev->dev.of_node); @@ -1042,39 +1042,19 @@ failed_get_irq: static int av1dec_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct av1dec_dev *dec = platform_get_drvdata(pdev); + struct mpp_dev *mpp = platform_get_drvdata(pdev); dev_info(dev, "remove device\n"); - mpp_dev_remove(&dec->mpp); - av1dec_procfs_remove(&dec->mpp); + mpp_dev_remove(mpp); + av1dec_procfs_remove(mpp); return 0; } -static void av1dec_shutdown(struct platform_device *pdev) -{ - int ret; - int val; - struct device *dev = &pdev->dev; - struct av1dec_dev *dec = platform_get_drvdata(pdev); - struct mpp_dev *mpp = &dec->mpp; - - dev_info(dev, "shutdown device\n"); - - atomic_inc(&mpp->srv->shutdown_request); - ret = readx_poll_timeout(atomic_read, - &mpp->task_count, - val, val == 0, 1000, 200000); - if (ret == -ETIMEDOUT) - dev_err(dev, "wait total running time out\n"); - - dev_info(dev, "shutdown success\n"); -} - struct platform_driver rockchip_av1dec_driver = { .probe = av1dec_probe, .remove = av1dec_remove, - .shutdown = av1dec_shutdown, + .shutdown = mpp_dev_shutdown, .driver = { .name = AV1DEC_DRIVER_NAME, .of_match_table = of_match_ptr(mpp_av1dec_dt_match), diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec.c b/drivers/video/rockchip/mpp/mpp_rkvdec.c index 629ddcb218c1..b060e12b20a8 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec.c @@ -325,8 +325,8 @@ static int devfreq_target(struct device *dev, struct dev_pm_opp *opp; unsigned long target_volt, target_freq; unsigned long aclk_rate_hz, core_rate_hz, cabac_rate_hz; - - struct rkvdec_dev *dec = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvdec_dev *dec = to_rkvdec_dev(mpp); struct devfreq *devfreq = dec->devfreq; struct devfreq_dev_status *stat = &devfreq->last_status; unsigned long old_clk_rate = stat->current_frequency; @@ -392,7 +392,8 @@ static int devfreq_target(struct device *dev, static int devfreq_get_cur_freq(struct device *dev, unsigned long *freq) { - struct rkvdec_dev *dec = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvdec_dev *dec = to_rkvdec_dev(mpp); *freq = clk_get_rate(dec->aclk_info.clk); @@ -402,7 +403,8 @@ static int devfreq_get_cur_freq(struct device *dev, static int devfreq_get_dev_status(struct device *dev, struct devfreq_dev_status *stat) { - struct rkvdec_dev *dec = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvdec_dev *dec = to_rkvdec_dev(mpp); struct devfreq *devfreq = dec->devfreq; memcpy(stat, &devfreq->last_status, sizeof(*stat)); @@ -1904,11 +1906,11 @@ static int rkvdec_probe(struct platform_device *pdev) static int rkvdec_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct rkvdec_dev *dec = platform_get_drvdata(pdev); + struct mpp_dev *mpp = platform_get_drvdata(pdev); dev_info(dev, "remove device\n"); - mpp_dev_remove(&dec->mpp); - rkvdec_procfs_remove(&dec->mpp); + mpp_dev_remove(mpp); + rkvdec_procfs_remove(mpp); return 0; } diff --git a/drivers/video/rockchip/mpp/mpp_rkvdec2.c b/drivers/video/rockchip/mpp/mpp_rkvdec2.c index 305996c676fe..65b477be400b 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvdec2.c +++ b/drivers/video/rockchip/mpp/mpp_rkvdec2.c @@ -711,8 +711,8 @@ static int rkvdec2_devfreq_target(struct device *dev, struct dev_pm_opp *opp; unsigned long target_volt, target_freq; int ret = 0; - - struct rkvdec2_dev *dec = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); struct devfreq *devfreq = dec->devfreq; struct devfreq_dev_status *stat = &devfreq->last_status; unsigned long old_clk_rate = stat->current_frequency; @@ -774,7 +774,8 @@ static int rkvdec2_devfreq_get_dev_status(struct device *dev, static int rkvdec2_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) { - struct rkvdec2_dev *dec = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvdec2_dev *dec = to_rkvdec2_dev(mpp); *freq = dec->core_last_rate_hz; diff --git a/drivers/video/rockchip/mpp/mpp_rkvenc.c b/drivers/video/rockchip/mpp/mpp_rkvenc.c index 5419954a8017..3e02712b0f60 100644 --- a/drivers/video/rockchip/mpp/mpp_rkvenc.c +++ b/drivers/video/rockchip/mpp/mpp_rkvenc.c @@ -850,8 +850,8 @@ static int rkvenc_devfreq_target(struct device *dev, struct dev_pm_opp *opp; unsigned long target_volt, target_freq; int ret = 0; - - struct rkvenc_dev *enc = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvenc_dev *enc = to_rkvenc_dev(mpp); struct devfreq *devfreq = enc->devfreq; struct devfreq_dev_status *stat = &devfreq->last_status; unsigned long old_clk_rate = stat->current_frequency; @@ -913,7 +913,8 @@ static int rkvenc_devfreq_get_dev_status(struct device *dev, static int rkvenc_devfreq_get_cur_freq(struct device *dev, unsigned long *freq) { - struct rkvenc_dev *enc = dev_get_drvdata(dev); + struct mpp_dev *mpp = dev_get_drvdata(dev); + struct rkvenc_dev *enc = to_rkvenc_dev(mpp); *freq = enc->core_last_rate_hz; diff --git a/drivers/video/rockchip/mpp/mpp_vdpp.c b/drivers/video/rockchip/mpp/mpp_vdpp.c index c0dc382a1872..031a975e00bf 100644 --- a/drivers/video/rockchip/mpp/mpp_vdpp.c +++ b/drivers/video/rockchip/mpp/mpp_vdpp.c @@ -696,9 +696,8 @@ static int vdpp_probe(struct platform_device *pdev) vdpp = devm_kzalloc(dev, sizeof(struct vdpp_dev), GFP_KERNEL); if (!vdpp) return -ENOMEM; - platform_set_drvdata(pdev, vdpp); - mpp = &vdpp->mpp; + platform_set_drvdata(pdev, mpp); if (pdev->dev.of_node) { match = of_match_node(mpp_vdpp_dt_match, pdev->dev.of_node); if (match) @@ -745,37 +744,19 @@ static int vdpp_probe(struct platform_device *pdev) static int vdpp_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct vdpp_dev *vdpp = platform_get_drvdata(pdev); + struct mpp_dev *mpp = platform_get_drvdata(pdev); dev_info(dev, "remove device\n"); - mpp_dev_remove(&vdpp->mpp); - vdpp_procfs_remove(&vdpp->mpp); + mpp_dev_remove(mpp); + vdpp_procfs_remove(mpp); return 0; } -static void vdpp_shutdown(struct platform_device *pdev) -{ - int ret; - int val; - struct device *dev = &pdev->dev; - struct vdpp_dev *vdpp = platform_get_drvdata(pdev); - struct mpp_dev *mpp = &vdpp->mpp; - - dev_info(dev, "shutdown device\n"); - - atomic_inc(&mpp->srv->shutdown_request); - ret = readx_poll_timeout(atomic_read, - &mpp->task_count, - val, val == 0, 20000, 200000); - if (ret == -ETIMEDOUT) - dev_err(dev, "wait total running time out\n"); -} - struct platform_driver rockchip_vdpp_driver = { .probe = vdpp_probe, .remove = vdpp_remove, - .shutdown = vdpp_shutdown, + .shutdown = mpp_dev_shutdown, .driver = { .name = VDPP_DRIVER_NAME, .of_match_table = of_match_ptr(mpp_vdpp_dt_match), diff --git a/sound/soc/codecs/rk817_codec.c b/sound/soc/codecs/rk817_codec.c index 51388b2e6d48..400be6d5c3d4 100644 --- a/sound/soc/codecs/rk817_codec.c +++ b/sound/soc/codecs/rk817_codec.c @@ -231,16 +231,22 @@ static int rk817_codec_ctl_gpio(struct rk817_codec_priv *rk817, { if ((gpio & CODEC_SET_SPK) && rk817->spk_ctl_gpio) { + if (level && rk817->spk_mute_delay) + msleep(rk817->spk_mute_delay); gpiod_set_value(rk817->spk_ctl_gpio, level); DBG("%s set spk clt %d\n", __func__, level); - msleep(rk817->spk_mute_delay); + if (!level && rk817->spk_mute_delay) + msleep(rk817->spk_mute_delay); } if ((gpio & CODEC_SET_HP) && rk817->hp_ctl_gpio) { + if (level && rk817->hp_mute_delay) + msleep(rk817->hp_mute_delay); gpiod_set_value(rk817->hp_ctl_gpio, level); DBG("%s set hp clt %d\n", __func__, level); - msleep(rk817->hp_mute_delay); + if (!level && rk817->hp_mute_delay) + msleep(rk817->hp_mute_delay); } return 0; @@ -260,12 +266,12 @@ static int rk817_reset(struct snd_soc_component *component) snd_soc_component_write(component, RK817_CODEC_APLL_CFG5, 0x00); snd_soc_component_write(component, RK817_CODEC_DTOP_DIGEN_CLKE, 0x00); if (rk817->chip_ver <= 0x4) { - DBG("%s (%d): SMIC TudorAG and previous versions\n", + DBG("%s (%d): 0x4 and previous versions\n", __func__, __LINE__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95); } else { - DBG("%s (%d): SMIC TudorAG version later\n", + DBG("%s (%d): 0x4 version later\n", __func__, __LINE__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5); @@ -275,6 +281,77 @@ static int rk817_reset(struct snd_soc_component *component) return 0; } +static int rk817_restart_dac_digital_clk(struct snd_soc_component *component) +{ + snd_soc_component_update_bits(component, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_MASK, PWD_DACBIAS_DOWN); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); + DBG("%s: %d - Playback DIG CLK OPS\n", __func__, __LINE__); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_MASK, PWD_DACBIAS_ON); + + return 0; +} + +static int rk817_restart_dac_digital_clk_and_apll(struct snd_soc_component *component) +{ + snd_soc_component_update_bits(component, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_MASK, PWD_DACBIAS_DOWN); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); + DBG("%s: %d - Playback DIG CLK OPS\n", __func__, __LINE__); + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, + PLL_PW_DOWN, PLL_PW_DOWN); + usleep_range(50, 60); + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, + PLL_PW_DOWN, PLL_PW_UP); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_ADAC_CFG1, + PWD_DACBIAS_MASK, PWD_DACBIAS_ON); + + return 0; +} + +static int rk817_restart_adc_digital_clk(struct snd_soc_component *component) +{ + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); + DBG("%s: %d - Capture DIG CLK OPS\n", __func__, __LINE__); + + return 0; +} + +static int rk817_restart_adc_digital_clk_and_apll(struct snd_soc_component *component) +{ + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); + usleep_range(500, 600); + snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, + ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); + DBG("%s: %d - Capture DIG CLK OPS\n", __func__, __LINE__); + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, + PLL_PW_DOWN, PLL_PW_DOWN); + usleep_range(50, 60); + snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, + PLL_PW_DOWN, PLL_PW_UP); + usleep_range(500, 600); + + return 0; +} + static struct rk817_reg_val_typ playback_power_up_list[] = { {RK817_CODEC_AREF_RTCFG1, 0x40}, {RK817_CODEC_DDAC_POPD_DACST, 0x02}, @@ -373,22 +450,16 @@ static int rk817_codec_power_up(struct snd_soc_component *component, int type) /* configure APLL CFG0/4 */ if (rk817->chip_ver <= 0x4) { - DBG("%s (%d): SMIC TudorAG and previous versions\n", + DBG("%s (%d): 0x4 and previous versions\n", __func__, __LINE__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95); } else { - DBG("%s: SMIC TudorAG version later\n", __func__); + DBG("%s: 0x4 version later\n", __func__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5); } - - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - DAC_DIG_CLK_MASK, DAC_DIG_CLK_DIS); - usleep_range(2000, 2500); - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - DAC_DIG_CLK_MASK, DAC_DIG_CLK_EN); - DBG("%s: %d - Playback DIG CLK OPS\n", __func__, __LINE__); + rk817_restart_dac_digital_clk(component); } if (type & RK817_CODEC_CAPTURE) { @@ -404,22 +475,17 @@ static int rk817_codec_power_up(struct snd_soc_component *component, int type) /* configure APLL CFG0/4 */ if (rk817->chip_ver <= 0x4) { - DBG("%s (%d): SMIC TudorAG and previous versions\n", + DBG("%s (%d): 0x4 and previous versions\n", __func__, __LINE__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95); } else { - DBG("%s: SMIC TudorAG version later\n", __func__); + DBG("%s: 0x4 version later\n", __func__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5); } - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - ADC_DIG_CLK_MASK, ADC_DIG_CLK_DIS); - usleep_range(2000, 2500); - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - ADC_DIG_CLK_MASK, ADC_DIG_CLK_EN); - DBG("%s: %d - Capture DIG CLK OPS\n", __func__, __LINE__); + rk817_restart_adc_digital_clk(component); if (rk817->mic_in_differential) snd_soc_component_update_bits(component, @@ -941,25 +1007,19 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, unsigned int rate = params_rate(params); unsigned char apll_cfg3_val; unsigned char dtop_digen_sr_lmt0; - unsigned char dtop_digen_clke; DBG("%s : sample rate = %dHz\n", __func__, rate); if (rk817->chip_ver <= 0x4) { - DBG("%s: SMIC TudorAG and previous versions\n", __func__); + DBG("%s: 0x4 and previous versions\n", __func__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x0c); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0x95); } else { - DBG("%s: SMIC TudorAG version later\n", __func__); + DBG("%s: 0x4 version later\n", __func__); snd_soc_component_write(component, RK817_CODEC_APLL_CFG0, 0x04); snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5); } - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dtop_digen_clke = DAC_DIG_CLK_EN; - else - dtop_digen_clke = ADC_DIG_CLK_EN; - switch (rate) { case 8000: apll_cfg3_val = 0x03; @@ -991,19 +1051,12 @@ static int rk817_hw_params(struct snd_pcm_substream *substream, */ if (!((substream->stream == SNDRV_PCM_STREAM_CAPTURE) && rk817->pdmdata_out_enable)) { snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, apll_cfg3_val); - /* The 0x00 contains ADC_DIG_CLK_DIS and DAC_DIG_CLK_DIS */ - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - dtop_digen_clke, 0x00); snd_soc_component_update_bits(component, RK817_CODEC_DDAC_SR_LMT0, DACSRT_MASK, dtop_digen_sr_lmt0); - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - dtop_digen_clke, dtop_digen_clke); - snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, - PLL_PW_DOWN, PLL_PW_DOWN); - usleep_range(50, 60); - snd_soc_component_update_bits(component, RK817_CODEC_APLL_CFG5, - PLL_PW_DOWN, PLL_PW_UP); - usleep_range(500, 600); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + rk817_restart_dac_digital_clk_and_apll(component); + else + rk817_restart_adc_digital_clk_and_apll(component); } switch (params_format(params)) { @@ -1041,14 +1094,7 @@ static int rk817_digital_mute_dac(struct snd_soc_dai *dai, int mute, int stream) snd_soc_component_update_bits(component, RK817_CODEC_DDAC_MUTE_MIXCTL, DACMT_ENABLE, DACMT_ENABLE); - snd_soc_component_write(component, RK817_CODEC_ADAC_CFG1, - PWD_DACBIAS_DOWN | PWD_DACD_DOWN | - PWD_DACL_DOWN | PWD_DACR_DOWN); - /* Reset DAC DTOP_DIGEN_CLKE for playback stopped */ - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - DAC_DIG_CLK_EN, DAC_DIG_CLK_DIS); - snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, - DAC_DIG_CLK_EN, DAC_DIG_CLK_EN); + rk817_restart_dac_digital_clk(component); snd_soc_component_update_bits(component, RK817_CODEC_DTOP_DIGEN_CLKE, I2SRX_EN_MASK, I2SRX_DIS); } else {