diff --git a/Documentation/devicetree/bindings/gpio/gpio-detection.txt b/Documentation/devicetree/bindings/gpio/gpio-detection.txt deleted file mode 100644 index 78bd530c8290..000000000000 --- a/Documentation/devicetree/bindings/gpio/gpio-detection.txt +++ /dev/null @@ -1,37 +0,0 @@ -Required properties: -- compatible: should be "gpio-detection" -- status: -- pinctrl-0 : phandle referencing pin configuration of the gpio controller -- pinctrl-names : a pinctrl state named "default" must be defined -- car-reverse : a describtion to show the gpio will be use to car reverse -- car-acc : a describtion to show the gpio will be use to car accelerate -- gpios : The GPIO to set high/low, see "gpios property" in - Documentation/devicetree/bindings/gpio/gpio.txt. If the pin should be - low to power down the board set it to "Active Low", otherwise set - gpio to "Active High". -- linux,debounce-ms: interrupt debounce time. (u32) -- label : The label / name for this partition. If omitted, the label is taken -- gpio,wakeup : To enable the wakeup comparator in probe - -Example: - - gpio_det: gpio-det { - compatible = "gpio-detection"; - status = "okay"; - - pinctrl-0 = <&gpio3_b1 &gpio3_b2>; - pinctrl-names = "default"; - car-reverse { - car-reverse-gpios = <&gpio3 10 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-reverse"; - gpio,wakeup; - }; - - car-acc { - car-acc-gpios = <&gpio3 9 GPIO_ACTIVE_HIGH>; - linux,debounce-ms = <5>; - label = "car-acc"; - gpio,wakeup; - }; - }; diff --git a/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt b/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt deleted file mode 100644 index 2e7a44ed65de..000000000000 --- a/Documentation/devicetree/bindings/misc/usb_cam_gpio.txt +++ /dev/null @@ -1,16 +0,0 @@ -* Rockchip USB camera GPIO control driver - -Required properties: -- compatible: should be "usb-cam-gpio" -- hd-cam-pin: HD camera on gpio pin -- ir-cam-pin: IR camera on gpio pin - -Example: - usb_cam_gpio: usb-cam-gpio { - compatible = "usb-cam-gpio"; - pinctrl-names = "default"; - pinctrl-0 = <&usb_cam_on_gpio>; - hd-cam-pin = <&gpio3 GPIO_A1 GPIO_ACTIVE_LOW>; - ir-cam-pin = <&gpio3 GPIO_A2 GPIO_ACTIVE_HIGH>; - status = "okay"; - }; diff --git a/Documentation/devicetree/bindings/power/ec_battery.txt b/Documentation/devicetree/bindings/power/ec_battery.txt deleted file mode 100644 index 5d761d9fc532..000000000000 --- a/Documentation/devicetree/bindings/power/ec_battery.txt +++ /dev/null @@ -1,20 +0,0 @@ -Binding for EC Battery - -Required properties: -- compatible: Should contain one of the following: - * "rockchip,ec-battery" -- reg: integer, smbus address of the device. -- tvirtual_power: integer, test power, if battery is not exist; -- monitor_sec: integer, delay time of queue_delayed_work (s); - - -Optional properties: - -Example: - -ec_battery: ec_battery09 { - compatible = "rockchip,ec-battery"; - reg = <0x76>; - virtual_power = <0>; - monitor_sec = <5>; -}; diff --git a/Documentation/devicetree/bindings/power/sy6982c-charger.txt b/Documentation/devicetree/bindings/power/sy6982c-charger.txt deleted file mode 100644 index 9ec4d54b24de..000000000000 --- a/Documentation/devicetree/bindings/power/sy6982c-charger.txt +++ /dev/null @@ -1,14 +0,0 @@ -Binding for sy6982c Charger - -Required properties: -- compatible: Should contain one of the following: - * "sy6982c-charger" -- extcon: extcon specifier for the Charger. - -Example: - - sy6982c { - status = "okay"; - compatible = "sy6982c-charger"; - extcon = <&u2phy0>; - }; diff --git a/Documentation/devicetree/bindings/power/universal_charger.txt b/Documentation/devicetree/bindings/power/universal_charger.txt deleted file mode 100644 index a328ecf1e3d7..000000000000 --- a/Documentation/devicetree/bindings/power/universal_charger.txt +++ /dev/null @@ -1,16 +0,0 @@ -Binding for UNIVERSAL Charger - -Required properties: -- compatible: Should contain one of the following: - * "universal-charger" -- extcon: extcon specifier for the Charger. -- dc-det-gpio: gpio for dc detect. - -Example: - - universal_charger { - status = "okay"; - compatible = "universal-charger"; - extcon = <&u2phy0>; - dc-det-gpio = <&gpio3 1 GPIO_ACTIVE_HIGH>; - }; diff --git a/arch/arm64/boot/dts/rockchip/rk3528.dtsi b/arch/arm64/boot/dts/rockchip/rk3528.dtsi index a8ff558a524f..2993e406fc91 100644 --- a/arch/arm64/boot/dts/rockchip/rk3528.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3528.dtsi @@ -452,6 +452,7 @@ compatible = "rockchip,mpp-service"; rockchip,taskqueue-count = <5>; rockchip,resetgroup-count = <5>; + rockchip,iommu-shared-mask = <0xa>; /* 0x2: avsd, 0x8: vdpu */ status = "disabled"; }; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 6ac47ad2cc36..d253ebcf3ce4 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -341,6 +341,43 @@ static bool analogix_dp_get_vrr_capable(struct analogix_dp_device *dp) return true; } +static int analogix_dp_enable_sink_to_assr_mode(struct analogix_dp_device *dp, bool enable) +{ + u8 data; + int ret; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_EDP_CONFIGURATION_SET, &data); + if (ret != 1) + return ret; + + if (enable) + ret = drm_dp_dpcd_writeb(&dp->aux, DP_EDP_CONFIGURATION_SET, + data | DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + else + ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, + data & ~DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); + + return ret < 0 ? ret : 0; +} + +static int analogix_dp_set_assr_mode(struct analogix_dp_device *dp) +{ + bool assr_en; + int ret; + + assr_en = drm_dp_alternate_scrambler_reset_cap(dp->dpcd); + + ret = analogix_dp_enable_sink_to_assr_mode(dp, assr_en); + if (ret < 0) + return ret; + + analogix_dp_enable_assr_mode(dp, assr_en); + + dp->link_train.assr = assr_en; + + return 0; +} + static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; @@ -380,6 +417,13 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) if (retval < 0) return retval; + /* set ASSR if available */ + retval = analogix_dp_set_assr_mode(dp); + if (retval < 0) { + dev_err(dp->dev, "failed to set assr mode\n"); + return retval; + } + /* set enhanced mode if available */ retval = analogix_dp_set_enhanced_mode(dp); if (retval < 0) { @@ -908,6 +952,7 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); analogix_dp_set_lane_count(dp, dp->link_train.lane_count); analogix_dp_set_lane_link_training(dp); + analogix_dp_enable_assr_mode(dp, dp->link_train.assr); analogix_dp_enable_enhanced_mode(dp, dp->link_train.enhanced_framing); /* source Set training pattern 1 */ @@ -2392,6 +2437,7 @@ static void analogix_dp_link_train_restore(struct analogix_dp_device *dp) dp->link_train.link_rate = link_rate; dp->link_train.lane_count = lane_count; + dp->link_train.assr = analogix_dp_get_assr_mode(dp); dp->link_train.enhanced_framing = analogix_dp_get_enhanced_mode(dp); dp->link_train.ssc = !!(spread & DP_MAX_DOWNSPREAD_0_5); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 2b2883029c5b..915bf6969ca1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -160,6 +160,7 @@ struct link_train { u8 training_lane[4]; bool ssc; bool enhanced_framing; + bool assr; enum link_training_state lt_state; }; @@ -279,5 +280,7 @@ void analogix_dp_init(struct analogix_dp_device *dp); void analogix_dp_irq_handler(struct analogix_dp_device *dp); void analogix_dp_phy_test(struct analogix_dp_device *dp); void analogix_dp_check_device_service_irq(struct analogix_dp_device *dp); +void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable); +bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp); #endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index e72524eab4c2..5b58f8219ccc 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1390,3 +1390,27 @@ void analogix_dp_init(struct analogix_dp_device *dp) analogix_dp_init_hpd(dp); analogix_dp_init_aux(dp); } + +void analogix_dp_enable_assr_mode(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + reg |= ALTERNATE_SR_ENABLE; + analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg); + } else { + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + reg &= ~ALTERNATE_SR_ENABLE; + analogix_dp_write(dp, ANALOGIX_DP_LINK_POLICY, reg); + } +} + +bool analogix_dp_get_assr_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = analogix_dp_read(dp, ANALOGIX_DP_LINK_POLICY); + + return !!(reg & ALTERNATE_SR_ENABLE); +} diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index 0a368b1722ec..a14305148ce5 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -146,6 +146,8 @@ #define ANALOGIX_DP_CRC_CON 0x890 #define ANALOGIX_DP_I2S_CTRL 0x9C8 +#define ANALOGIX_DP_LINK_POLICY 0x9D8 + /* ANALOGIX_DP_TX_SW_RESET */ #define RESET_DP_TX (0x1 << 0) @@ -515,4 +517,7 @@ /* ANALOGIX_DP_I2S_CTRL */ #define I2S_EN (0x1 << 4) +/* ANALOGIX_DP_LINK_POLICY */ +#define ALTERNATE_SR_ENABLE (0x1 << 7) + #endif /* _ANALOGIX_DP_REG_H */ diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c index f9b8632a280a..d7a67bc80a20 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c @@ -151,7 +151,7 @@ #define DSI2_IPI_VID_VACT_MAN_CFG 0X0334 #define VID_VACT_LINES(x) UPDATE(x, 13, 0) #define DSI2_IPI_VID_VFP_MAN_CFG 0X033C -#define VID_VFP_LINES(x) UPDATE(x, 9, 0) +#define VID_VFP_LINES(x) UPDATE(x, 12, 0) #define DSI2_IPI_PIX_PKT_CFG 0x0344 #define MAX_PIX_PKT(x) UPDATE(x, 15, 0) @@ -227,7 +227,9 @@ struct dw_mipi_dsi2_plat_data { const u32 *dsi1_grf_reg_fields; unsigned long long dphy_max_bit_rate_per_lane; unsigned long long cphy_max_symbol_rate_per_lane; - + const u32 max_vfp; + const u32 max_vsync; + const u32 max_vbp; }; struct dw_mipi_dsi2 { @@ -1213,10 +1215,11 @@ dw_mipi_dsi2_connector_mode_valid(struct drm_connector *connector, if (vm.vactive > 16383) return MODE_VIRTUAL_Y; - if (vm.vsync_len > 1023) + if (vm.vsync_len > dsi2->pdata->max_vsync) return MODE_VSYNC_WIDE; - if (vm.vback_porch > 1023 || vm.vfront_porch > 1023) + if (vm.vback_porch > dsi2->pdata->max_vbp || + vm.vfront_porch > dsi2->pdata->max_vfp) return MODE_VBLANK_WIDE; /* @@ -2056,6 +2059,9 @@ static const struct dw_mipi_dsi2_plat_data rk3576_mipi_dsi2_plat_data = { .dsi0_grf_reg_fields = rk3576_dsi_grf_reg_fields, .dphy_max_bit_rate_per_lane = 2500000000ULL, .cphy_max_symbol_rate_per_lane = 1700000000ULL, + .max_vfp = 8191, + .max_vsync = 1023, + .max_vbp = 1023, }; static const struct dw_mipi_dsi2_plat_data rk3588_mipi_dsi2_plat_data = { @@ -2064,6 +2070,9 @@ static const struct dw_mipi_dsi2_plat_data rk3588_mipi_dsi2_plat_data = { .dsi1_grf_reg_fields = rk3588_dsi1_grf_reg_fields, .dphy_max_bit_rate_per_lane = 4500000000ULL, .cphy_max_symbol_rate_per_lane = 2000000000ULL, + .max_vfp = 1023, + .max_vsync = 1023, + .max_vbp = 1023, }; static const struct of_device_id dw_mipi_dsi2_dt_ids[] = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 1c0d3c4df190..949da8ff3066 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -858,6 +858,11 @@ struct vop2_video_port { * @irq: independent irq for each vp */ int irq; + /** + * @sharp_disabled: Sharp is mutually exclusive with post-scaler and split, + * we configure whether sharp is disabled in dts + */ + bool sharp_disabled; }; struct vop2_extend_pll { @@ -4578,7 +4583,7 @@ static void vop2_initial(struct drm_crtc *crtc) * After vop initialization, keep sw_sharp_enable always on. * Only enable/disable sharp submodule to avoid black screen. */ - if (vp_data->feature & VOP_FEATURE_POST_SHARP) + if (vp_data->feature & VOP_FEATURE_POST_SHARP && vp->sharp_disabled) writel(0x1, vop2->sharp_res.regs); /* disable immediately enable bit for dp */ @@ -9507,6 +9512,27 @@ static void vop2_setup_dual_channel_if(struct drm_crtc *crtc) struct vop2_video_port *vp = to_vop2_video_port(crtc); struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; + const struct vop2_data *vop2_data = vop2->data; + const struct vop2_video_port_data *vp_data = &vop2_data->vp[vp->id]; + + /* + * RK3576 VOP split and post-scaler use the same line buffer. + * If enable split, post-scaler must be disabled. + */ + if (vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, post-scaler shouldn't be set\n"); + vcstate->left_margin = 100; + vcstate->right_margin = 100; + vcstate->top_margin = 100; + vcstate->bottom_margin = 100; + } + + /* + * VOP split and sharp use the same line buffer. If enable + * split, sharp must be disabled completely. + */ + if (vp_data->feature & VOP_FEATURE_POST_SHARP) + writel(0, vop2->sharp_res.regs); if (output_if_is_lvds(vcstate->output_if) && (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)) { @@ -9818,6 +9844,15 @@ static inline char *vop2_output_if_to_string(unsigned long inf) ARRAY_SIZE(vop2_output_if_name_list)); } +static bool vop2_is_left_right_or_odd_even_mode(struct rockchip_crtc_state *vcstate) +{ + if (!(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE) && + !(vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE)) + return false; + + return true; +} + static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state) { struct vop2_video_port *vp = to_vop2_video_port(crtc); @@ -10038,8 +10073,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta } } - if (vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE || - vcstate->output_flags & ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE) + if (vop2_is_left_right_or_odd_even_mode(vcstate)) vop2_setup_dual_channel_if(crtc); if (vcstate->output_if & VOP_OUTPUT_IF_eDP0) { @@ -12470,6 +12504,17 @@ static void vop2_post_sharp_config(struct drm_crtc *crtc) struct post_sharp *post_sharp; int i; + if (vp->sharp_disabled) + return; + + if (vop2_is_left_right_or_odd_even_mode(vcstate)) { + if (post_sharp_enabled(crtc)) + DRM_WARN("split is enabled, can't enable sharp\n"); + + vcstate->sharp_en = false; + return; + } + /* sharp work in yuv color space, if it is rgb overlay sharp shouldn't be enabled */ if (!vcstate->yuv_overlay || !post_sharp_enabled(crtc)) { /* @@ -13089,6 +13134,7 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(state); struct drm_mode_config *mode_config = &drm_dev->mode_config; struct vop2_video_port *vp = to_vop2_video_port(crtc); + struct vop2 *vop2 = vp->vop2; bool replaced = false; int ret; @@ -13097,6 +13143,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->left_margin = val; return 0; } @@ -13106,6 +13158,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->right_margin = val; return 0; } @@ -13115,6 +13173,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->top_margin = val; return 0; } @@ -13124,6 +13188,12 @@ static int vop2_crtc_atomic_set_property(struct drm_crtc *crtc, DRM_ERROR("sharp is enabled, failed to set %s\n", property->name); return 0; } + + if (vop2_is_left_right_or_odd_even_mode(vcstate) && + vop2->version == VOP_VERSION_RK3576) { + DRM_ERROR("split is enabled, failed to set %s\n", property->name); + return 0; + } vcstate->bottom_margin = val; return 0; } @@ -14319,6 +14389,8 @@ static int vop2_create_crtc(struct vop2 *vop2, uint8_t enabled_vp_mask) crtc->port = port; of_property_read_u32(port, "cursor-win-id", &vp->cursor_win_id); + vp->sharp_disabled = of_property_read_bool(port, "sharp-disabled"); + plane_mask = vp->plane_mask; if (vop2_soc_is_rk3566()) { if ((vp->plane_mask & RK3566_MIRROR_PLANE_MASK) && diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index bd47d9d2c67f..a0091aaaf0f1 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -80,10 +80,10 @@ struct rockchip_saradc { bool suspended; #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN bool test; - u32 chn; - spinlock_t lock; - struct workqueue_struct *wq; - struct delayed_work work; + u32 test_chn; + spinlock_t test_lock; + struct workqueue_struct *test_wq; + struct delayed_work test_work; #endif }; @@ -138,7 +138,7 @@ static int rockchip_saradc_read_v2(struct rockchip_saradc *info) writel_relaxed(0x1, info->regs + SARADC2_END_INT_ST); #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - channel = info->chn; + channel = info->test_chn; #else channel = info->last_chan->channel; #endif @@ -229,6 +229,10 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) unsigned long flags; #endif + /* Nothing need to do if info->last_chan not ready */ + if (!info->last_chan) + return IRQ_HANDLED; + /* Read value */ info->last_val = rockchip_saradc_read(info); #ifndef CONFIG_ROCKCHIP_SARADC_TEST_CHN @@ -239,12 +243,13 @@ static irqreturn_t rockchip_saradc_isr(int irq, void *dev_id) complete(&info->completion); #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - spin_lock_irqsave(&info->lock, flags); + spin_lock_irqsave(&info->test_lock, flags); if (info->test) { - pr_info("chn[%d] val = %d\n", info->chn, info->last_val); - mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100)); + pr_info("chn[%d] val = %d\n", info->test_chn, info->last_val); + mod_delayed_work(info->test_wq, &info->test_work, + msecs_to_jiffies(100)); } - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock_irqrestore(&info->test_lock, flags); #endif return IRQ_HANDLED; } @@ -538,22 +543,23 @@ static ssize_t saradc_test_chn_store(struct device *dev, if (err) return err; - spin_lock_irqsave(&info->lock, flags); + spin_lock_irqsave(&info->test_lock, flags); if (val > SARADC_CTRL_CHN_MASK && info->test) { info->test = false; - spin_unlock_irqrestore(&info->lock, flags); - cancel_delayed_work_sync(&info->work); + spin_unlock_irqrestore(&info->test_lock, flags); + cancel_delayed_work_sync(&info->test_work); return size; } if (!info->test && val <= SARADC_CTRL_CHN_MASK) { info->test = true; - info->chn = val; - mod_delayed_work(info->wq, &info->work, msecs_to_jiffies(100)); + info->test_chn = val; + mod_delayed_work(info->test_wq, &info->test_work, + msecs_to_jiffies(100)); } - spin_unlock_irqrestore(&info->lock, flags); + spin_unlock_irqrestore(&info->test_lock, flags); return size; } @@ -580,15 +586,15 @@ static void rockchip_saradc_destroy_wq(void *data) { struct rockchip_saradc *info = data; - destroy_workqueue(info->wq); + destroy_workqueue(info->test_wq); } static void rockchip_saradc_test_work(struct work_struct *work) { struct rockchip_saradc *info = container_of(work, - struct rockchip_saradc, work.work); + struct rockchip_saradc, test_work.work); - rockchip_saradc_start(info, info->chn); + rockchip_saradc_start(info, info->test_chn); } #endif @@ -748,9 +754,9 @@ static int rockchip_saradc_probe(struct platform_device *pdev) return ret; #ifdef CONFIG_ROCKCHIP_SARADC_TEST_CHN - info->wq = create_singlethread_workqueue("adc_wq"); - INIT_DELAYED_WORK(&info->work, rockchip_saradc_test_work); - spin_lock_init(&info->lock); + info->test_wq = create_singlethread_workqueue("adc_wq"); + INIT_DELAYED_WORK(&info->test_work, rockchip_saradc_test_work); + spin_lock_init(&info->test_lock); ret = sysfs_create_group(&pdev->dev.kobj, &rockchip_saradc_attr_group); if (ret) return ret; diff --git a/drivers/media/platform/rockchip/isp/isp_dvbm.c b/drivers/media/platform/rockchip/isp/isp_dvbm.c index 472e6ef96ac0..6cb5569796f3 100644 --- a/drivers/media/platform/rockchip/isp/isp_dvbm.c +++ b/drivers/media/platform/rockchip/isp/isp_dvbm.c @@ -55,9 +55,10 @@ int rkisp_dvbm_init(struct rkisp_stream *stream) dvbm_cfg.cbuf_top = dvbm_cfg.cbuf_bot + (width * wrap_line / 2); dvbm_cfg.cbuf_lstd = width; dvbm_cfg.cbuf_fstd = dvbm_cfg.ybuf_fstd / 2; + dvbm_cfg.chan_id = dev->dev_id; rk_dvbm_ctrl(g_dvbm, DVBM_ISP_SET_CFG, &dvbm_cfg); - rk_dvbm_link(g_dvbm); + rk_dvbm_link(g_dvbm, dev->dev_id); return 0; } @@ -67,7 +68,7 @@ void rkisp_dvbm_deinit(struct rkisp_device *dev) pr_err("g_dvbm %p or devv %p is NULL\n", g_dvbm, dev); return; } - rk_dvbm_unlink(g_dvbm); + rk_dvbm_unlink(g_dvbm, dev->dev_id); } int rkisp_dvbm_event(struct rkisp_device *dev, u32 event) diff --git a/drivers/misc/gpio-detection.c b/drivers/misc/gpio-detection.c deleted file mode 100644 index 69eda8e5e0ef..000000000000 --- a/drivers/misc/gpio-detection.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * gpio detection driver - * - * Copyright (C) 2015 Rockchip Electronics Co., Ltd. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WAKE_LOCK_TIMEOUT_MS (5000) - -struct gpio_data { - struct gpio_detection *parent; - const char *name; - struct device dev; - int notify; - struct gpio_desc *gpio; - int val; - int irq; - struct delayed_work work; - unsigned int debounce_ms; - int wakeup; -}; - -struct gpio_detection { - struct class_attribute cls_attr; - struct device *dev; - int num; - struct gpio_data *data; - struct pinctrl *pinctrl; - struct pinctrl_state *pins_default; - struct notifier_block fb_notifier; - struct wake_lock wake_lock; - int mirror; - int type; - int info; -}; - -static struct class *gpio_detection_class; -static BLOCKING_NOTIFIER_HEAD(gpio_det_notifier_list); -static int system_suspend; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -/* - * gpio_det_notifier_call_chain - notify clients of gpio_det_events - * - */ -int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return blocking_notifier_call_chain(&gpio_det_notifier_list, val, v); -} -EXPORT_SYMBOL_GPL(gpio_det_notifier_call_chain); - -/* - * gpio_det_register_notifier - register a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_register_notifier(struct notifier_block *nb) -{ - int ret = blocking_notifier_chain_register(&gpio_det_notifier_list, nb); - - return ret; -} -EXPORT_SYMBOL(gpio_det_register_notifier); - -/* - * gpio_det_unregister_client - unregister a client notifier - * @nb: notifier block to callback on events - */ -int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&gpio_det_notifier_list, nb); -} -EXPORT_SYMBOL(gpio_det_unregister_notifier); - -#endif - -static void gpio_det_report_event(struct gpio_data *gpiod) -{ - struct gpio_event event; - struct gpio_detection *gpio_det = gpiod->parent; - char *status = NULL; - char *envp[2]; - - event.val = gpiod->val; - event.name = gpiod->name; - status = kasprintf(GFP_KERNEL, "GPIO_NAME=%s GPIO_STATE=%s", - gpiod->name, event.val ? "over" : "on"); - envp[0] = status; - envp[1] = NULL; - wake_lock_timeout(&gpio_det->wake_lock, - msecs_to_jiffies(WAKE_LOCK_TIMEOUT_MS)); - kobject_uevent_env(&gpiod->dev.kobj, KOBJ_CHANGE, envp); - if (gpiod->notify) - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - kfree(status); -} - -static void gpio_det_work_func(struct work_struct *work) -{ - struct gpio_data *gpiod = container_of(work, struct gpio_data, - work.work); - int val = gpiod_get_value(gpiod->gpio); - - if (gpiod->val != val) { - gpiod->val = val; - gpio_det_report_event(gpiod); - if (system_suspend && gpiod->wakeup) { - rk_send_power_key(1); - rk_send_power_key(0); - } - } -} - -static irqreturn_t gpio_det_interrupt(int irq, void *dev_id) -{ - struct gpio_data *gpiod = dev_id; - int val = gpiod_get_raw_value(gpiod->gpio); - unsigned int irqflags = IRQF_ONESHOT; - - if (val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - irq_set_irq_type(gpiod->irq, irqflags); - - mod_delayed_work(system_wq, &gpiod->work, - msecs_to_jiffies(gpiod->debounce_ms)); - - return IRQ_HANDLED; -} - -static int gpio_det_init_status_check(struct gpio_detection *gpio_det) -{ - struct gpio_data *gpiod; - int i; - - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod->val = gpiod_get_value(gpiod->gpio); - if (gpiod->val) - gpio_det_report_event(gpiod); - } - - return 0; -} - -static int gpio_det_fb_notifier_callback(struct notifier_block *self, - unsigned long event, - void *data) -{ - struct gpio_detection *gpio_det; - struct fb_event *evdata = data; - int fb_blank; - - if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK) - return 0; - - gpio_det = container_of(self, struct gpio_detection, fb_notifier); - fb_blank = *(int *)evdata->data; - if (fb_blank == FB_BLANK_UNBLANK) - system_suspend = 0; - else - system_suspend = 1; - - return 0; -} - -static int gpio_det_fb_notifier_register(struct gpio_detection *gpio) -{ - gpio->fb_notifier.notifier_call = gpio_det_fb_notifier_callback; - - return fb_register_client(&gpio->fb_notifier); -} - -static ssize_t gpio_detection_info_show(struct class *class, - struct class_attribute *attr, - char *buf) -{ - struct gpio_detection *gpio_det; - - gpio_det = container_of(attr, struct gpio_detection, cls_attr); - - return sprintf(buf, "%d\n", gpio_det->info); -} - -static ssize_t status_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gpio_data *gpiod = container_of(dev, struct gpio_data, dev); - unsigned int val = gpiod_get_value(gpiod->gpio); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t status_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_data *gpiod; - int val; - int ret; - struct gpio_event event; - - gpiod = container_of(dev, struct gpio_data, dev); - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val >= 0) { - event.val = val; - event.name = gpiod->name; - gpio_det_notifier_call_chain(GPIO_EVENT, &event); - } else { - gpiod->notify = 0; - } - - return count; -} - -static DEVICE_ATTR_RW(status); - -static struct attribute *gpio_detection_attrs[] = { - &dev_attr_status.attr, - NULL, -}; -ATTRIBUTE_GROUPS(gpio_detection); - -static int __init gpio_deteciton_class_init(void) -{ - gpio_detection_class = class_create(THIS_MODULE, "gpio-detection"); - if (IS_ERR(gpio_detection_class)) { - pr_err("create gpio_detection class failed (%ld)\n", - PTR_ERR(gpio_detection_class)); - return PTR_ERR(gpio_detection_class); - } - - return 0; -} - -static int gpio_detection_class_register(struct gpio_detection *gpio_det, - struct gpio_data *gpiod) -{ - int ret; - - gpiod->dev.class = gpio_detection_class; - dev_set_name(&gpiod->dev, "%s", gpiod->name); - dev_set_drvdata(&gpiod->dev, gpio_det); - ret = device_register(&gpiod->dev); - ret = sysfs_create_groups(&gpiod->dev.kobj, gpio_detection_groups); - - return ret; -} - -static int gpio_det_parse_dt(struct gpio_detection *gpio_det, - struct platform_device *pdev) -{ - struct gpio_data *data; - struct device *dev = &pdev->dev; - struct device_node *node; - struct gpio_data *gpiod; - struct fwnode_handle *child; - int count = 0; - int i = 0; - int num = 0; - - num = of_get_child_count(gpio_det->dev->of_node); - count = device_get_child_node_count(dev); - if (!count || !num) - return -ENODEV; - data = devm_kzalloc(gpio_det->dev, num * sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-type", - &gpio_det->type); - of_property_read_u32(gpio_det->dev->of_node, "rockchip,camcap-mirror", - &gpio_det->mirror); - gpio_det->info = (gpio_det->mirror << 4) | gpio_det->type; - device_for_each_child_node(dev, child) { - node = to_of_node(child); - gpiod = &data[i++]; - gpiod->parent = gpio_det; - gpiod->notify = 1; - gpiod->name = of_get_property(node, "label", NULL); - gpiod->wakeup = !!of_get_property(node, "gpio,wakeup", NULL); - of_property_read_u32(node, "linux,debounce-ms", - &gpiod->debounce_ms); - if (!strcmp(gpiod->name, "car-reverse")) - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-reverse", child); - else - gpiod->gpio = devm_get_gpiod_from_child(dev, - "car-acc", child); - } - gpio_det->num = num; - gpio_det->data = data; - - return 0; -} - -static int gpio_det_probe(struct platform_device *pdev) -{ - struct gpio_detection *gpio_det; - struct gpio_data *gpiod; - unsigned long irqflags = IRQF_ONESHOT; - int i; - int ret; - - gpio_det = devm_kzalloc(&pdev->dev, sizeof(*gpio_det), GFP_KERNEL); - if (!gpio_det) - return -ENOMEM; - gpio_det->dev = &pdev->dev; - gpio_det->cls_attr.attr.name = "info"; - gpio_det->cls_attr.attr.mode = S_IRUGO; - gpio_det->cls_attr.show = gpio_detection_info_show; - dev_set_name(gpio_det->dev, "gpio_detection"); - if (!pdev->dev.of_node) - return -EINVAL; - gpio_det->pinctrl = devm_pinctrl_get(&pdev->dev); - if (IS_ERR(gpio_det->pinctrl)) { - dev_err(&pdev->dev, "pinctrl get failed\n"); - return PTR_ERR(gpio_det->pinctrl); - } - gpio_det->pins_default = pinctrl_lookup_state(gpio_det->pinctrl, - PINCTRL_STATE_DEFAULT); - if (IS_ERR(gpio_det->pins_default)) - dev_err(gpio_det->dev, "get default pinstate failed\n"); - else - pinctrl_select_state(gpio_det->pinctrl, gpio_det->pins_default); - if (gpio_det_parse_dt(gpio_det, pdev)) - return -ENODEV; - wake_lock_init(&gpio_det->wake_lock, WAKE_LOCK_SUSPEND, - "gpio_detection"); - for (i = 0; i < gpio_det->num; i++) { - gpiod = &gpio_det->data[i]; - gpiod_direction_input(gpiod->gpio); - - gpiod->irq = gpiod_to_irq(gpiod->gpio); - if (gpiod->irq < 0) { - dev_err(gpio_det->dev, "failed to get irq number for GPIO %s\n", - gpiod->name); - continue; - } - - ret = gpio_detection_class_register(gpio_det, gpiod); - if (ret < 0) - return ret; - INIT_DELAYED_WORK(&gpiod->work, gpio_det_work_func); - gpiod->val = gpiod_get_raw_value(gpiod->gpio); - if (gpiod->val) - irqflags |= IRQ_TYPE_EDGE_FALLING; - else - irqflags |= IRQ_TYPE_EDGE_RISING; - ret = devm_request_threaded_irq(gpio_det->dev, gpiod->irq, - NULL, gpio_det_interrupt, - irqflags | IRQF_ONESHOT, - gpiod->name, gpiod); - if (ret < 0) - dev_err(gpio_det->dev, "request irq(%s) failed:%d\n", - gpiod->name, ret); - else - if (gpiod->wakeup) - enable_irq_wake(gpiod->irq); - } - - if (gpio_det->info) { - ret = class_create_file(gpio_detection_class, - &gpio_det->cls_attr); - if (ret) - dev_warn(gpio_det->dev, "create class file failed:%d\n", - ret); - } - - gpio_det_fb_notifier_register(gpio_det); - gpio_det_init_status_check(gpio_det); - - dev_info(gpio_det->dev, "gpio detection driver probe success\n"); - - return 0; -} - -#if defined(CONFIG_OF) -static const struct of_device_id gpio_det_of_match[] = { - { - .compatible = "gpio-detection" - }, - {}, -}; -#endif - -static struct platform_driver gpio_det_driver = { - .driver = { - .name = "gpio-detection", - .of_match_table = of_match_ptr(gpio_det_of_match), - }, - .probe = gpio_det_probe, -}; - -#ifdef CONFIG_VIDEO_REVERSE_IMAGE -int gpio_det_init(void) -#else -static int __init gpio_det_init(void) -#endif -{ - if (!gpio_deteciton_class_init()) - return platform_driver_register(&gpio_det_driver); - else - return -1; -} - -#ifndef CONFIG_VIDEO_REVERSE_IMAGE -fs_initcall_sync(gpio_det_init); -#endif -static void __exit gpio_det_exit(void) -{ - platform_driver_unregister(&gpio_det_driver); -} - -module_exit(gpio_det_exit); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-detection"); -MODULE_AUTHOR("ROCKCHIP"); diff --git a/drivers/misc/usb_cam_gpio.c b/drivers/misc/usb_cam_gpio.c deleted file mode 100644 index 320c1ed67945..000000000000 --- a/drivers/misc/usb_cam_gpio.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * drivers/misc/usb_cam_gpio.c - * - * Copyright (C) 2012-2016 Rockchip Electronics Co., Ltd. - * Author: Bin Yang - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct class *usb_cam_gpio_class; - -struct usb_cam_gpio { - struct device *dev; - struct device sys_dev; - - struct gpio_desc *gpio_cam_hd; - struct gpio_desc *gpio_cam_ir; -}; - -static ssize_t hd_camera_on_show(struct device *sys_dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, struct usb_cam_gpio, - sys_dev); - - return sprintf(buf, "%d\n", gpiod_get_value(gpiod->gpio_cam_hd)); -} - -static ssize_t hd_camera_on_store(struct device *sys_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, struct usb_cam_gpio, - sys_dev); - int val = 0; - int ret = 0; - - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val) - val = 1; - gpiod_set_value(gpiod->gpio_cam_hd, val); - - return count; -} -static DEVICE_ATTR_RW(hd_camera_on); - -static ssize_t ir_camera_on_show(struct device *sys_dev, - struct device_attribute *attr, - char *buf) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, - struct usb_cam_gpio, sys_dev); - - return sprintf(buf, "%d\n", gpiod_get_value(gpiod->gpio_cam_ir)); -} - -static ssize_t ir_camera_on_store(struct device *sys_dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_cam_gpio *gpiod = container_of(sys_dev, - struct usb_cam_gpio, sys_dev); - int val; - int ret; - - ret = kstrtoint(buf, 0, &val); - if (ret < 0) - return ret; - if (val) - val = 1; - gpiod_set_value(gpiod->gpio_cam_ir, val); - - return count; -} -static DEVICE_ATTR_RW(ir_camera_on); - -static struct attribute *usb_cam_gpio_attrs[] = { - &dev_attr_hd_camera_on.attr, - &dev_attr_ir_camera_on.attr, - NULL, -}; -ATTRIBUTE_GROUPS(usb_cam_gpio); - -static int usb_cam_gpio_device_register(struct usb_cam_gpio *gpiod) -{ - int ret; - struct device *dev = &gpiod->sys_dev; - const char *name = {"usb_camera_on"}; - - dev->class = usb_cam_gpio_class; - dev_set_name(dev, "%s", name); - dev_set_drvdata(dev, gpiod); - ret = device_register(dev); - - return ret; -} - -static int usb_cam_gpio_probe(struct platform_device *pdev) -{ - struct usb_cam_gpio *gpiod; - int ret = 0; - - usb_cam_gpio_class = class_create(THIS_MODULE, "usb_cam_gpio"); - if (IS_ERR(usb_cam_gpio_class)) { - pr_err("create uvc_detection class failed (%ld)\n", - PTR_ERR(usb_cam_gpio_class)); - return PTR_ERR(usb_cam_gpio_class); - } - usb_cam_gpio_class->dev_groups = usb_cam_gpio_groups; - - gpiod = devm_kzalloc(&pdev->dev, sizeof(*gpiod), GFP_KERNEL); - if (!gpiod) - return -ENOMEM; - - gpiod->dev = &pdev->dev; - - gpiod->gpio_cam_hd = devm_gpiod_get_optional(gpiod->dev, - "hd-cam", GPIOD_OUT_LOW); - if (IS_ERR(gpiod->gpio_cam_hd)) { - dev_warn(gpiod->dev, "Could not get hd-cam-gpios!\n"); - gpiod->gpio_cam_hd = NULL; - } - - gpiod->gpio_cam_ir = devm_gpiod_get_optional(gpiod->dev, - "ir-cam", GPIOD_OUT_HIGH); - if (IS_ERR(gpiod->gpio_cam_ir)) { - dev_warn(gpiod->dev, "Could not get ir-cam-gpios!\n"); - gpiod->gpio_cam_ir = NULL; - } - - ret = usb_cam_gpio_device_register(gpiod); - if (ret < 0) { - dev_err(gpiod->dev, "usb_cam_gpio device register fail\n"); - return ret; - } - - dev_info(gpiod->dev, "usb_cam_gpio_probe success\n"); - - return 0; -} - -static const struct of_device_id usb_cam_gpio_match[] = { - { .compatible = "usb-cam-gpio" }, - { /* Sentinel */ } -}; - -static int usb_cam_gpio_remove(struct platform_device *pdev) -{ - if (!IS_ERR(usb_cam_gpio_class)) - class_destroy(usb_cam_gpio_class); - - return 0; -} - -static struct platform_driver usb_cam_gpio_driver = { - .probe = usb_cam_gpio_probe, - .remove = usb_cam_gpio_remove, - .driver = { - .name = "usb_cam_gpio", - .owner = THIS_MODULE, - .of_match_table = usb_cam_gpio_match, - }, -}; - -module_platform_driver(usb_cam_gpio_driver); - -MODULE_ALIAS("platform:usb_cam_gpio"); -MODULE_AUTHOR("Bin Yang "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("usb camera gpio driver"); diff --git a/drivers/power/ec_battery.c b/drivers/power/ec_battery.c deleted file mode 100644 index 38db43507bee..000000000000 --- a/drivers/power/ec_battery.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * ec battery driver - * - * Copyright (C) 2016 Rockchip Electronics Co., Ltd. - * Shunqing Chen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - */ - -#include -#include -#include -#include - -static int dbg_enable; -module_param_named(dbg_level, dbg_enable, int, 0644); - -#define DBG(args...) \ - do { \ - if (dbg_enable) { \ - printk(args); \ - } \ - } while (0) - -struct ec_battery { - struct i2c_client *i2c; - struct device *dev; - struct regmap *regmap; - struct power_supply *bat; - struct workqueue_struct *bat_monitor_wq; - struct delayed_work bat_delay_work; - u32 monitor_sec; - u32 bat_mode; - u16 status; - int current_now; - u16 voltage_now; - u16 rem_capacity; - u16 full_charge_capacity; - u16 design_capacity; - int temperature_now; - int soc; - bool is_charge; - bool dis_charge; - bool is_ctitical; - bool is_battery_low; - bool is_battery_in; - bool is_ac_in; - struct gpio_desc *ec_notify_io; -}; - -enum bat_mode { - MODE_BATTARY = 0, - MODE_VIRTUAL, -}; - -/* virtual params */ -#define VIRTUAL_CURRENT 1000 -#define VIRTUAL_VOLTAGE 3888 -#define VIRTUAL_SOC 66 -#define VIRTUAL_PRESET 1 -#define VIRTUAL_TEMPERATURE 188 -#define VIRTUAL_STATUS POWER_SUPPLY_STATUS_CHARGING - -#define TIMER_MS_COUNTS 1000 -#define DEFAULT_MONITOR_SEC 5 - -#define EC_GET_VERSION_COMMOND 0x10 -#define EC_GET_VERSION_INFO_NUM (5) -#define EC_GET_BATTERY_INFO_COMMOND 0x07 -#define EC_GET_PARAMETER_NUM (13) -#define EC_GET_BATTERY_OTHER_COMMOND 0x08 -#define EC_GET_BATTERYINFO_NUM (7) - -#define EC_GET_BIT(a, b) (((a) & (1 << (b))) ? 1 : 0) -#define EC_DIS_CHARGE(a) EC_GET_BIT(a, 0) -#define EC_IS_CHARGE(a) EC_GET_BIT(a, 1) -#define EC_IS_CRITICAL(a) EC_GET_BIT(a, 2) -#define EC_IS_BATTERY_LOW(a) EC_GET_BIT(a, 3) -#define EC_IS_BATTERY_IN(a) EC_GET_BIT(a, 6) -#define EC_IS_AC_IN(a) EC_GET_BIT(a, 7) - -static int ec_i2c_read(struct ec_battery *bat, u8 cmd, u8 *dest, u16 len) -{ - struct i2c_client *i2c = bat->i2c; - int ret; - struct i2c_msg msg[2]; - u8 buf[2]; - - buf[0] = cmd; /* EC_GET_BATTERY_INFO_COMMOND; */ - msg[0].addr = i2c->addr; - msg[0].flags = i2c->flags & I2C_M_TEN; - msg[0].len = 1; - msg[0].buf = buf; - - msg[1].addr = i2c->addr; - msg[1].flags = i2c->flags & I2C_M_TEN; - msg[1].flags |= I2C_M_RD; - msg[1].len = len; - msg[1].buf = dest; - - ret = i2c_transfer(i2c->adapter, msg, 2); - - return ret; -} - -static void ec_dump_info(struct ec_battery *bat) -{ - int temp; - - DBG("==========================================\n"); - DBG("battery status: %x\n", bat->status); - temp = bat->temperature_now / 10; - DBG("Temp: %d K (%d C))\n", temp, (temp - 272)); - DBG("current_now: %d ma\n", bat->current_now); - DBG("voltage_now: %d mv\n", bat->voltage_now); - DBG("Charge: %d %%\n", bat->soc); - DBG("Remaining: %d mAh\n", bat->rem_capacity); - DBG("Cap-full: %d mAh\n", bat->full_charge_capacity); - DBG("Design: %d mAh\n", bat->design_capacity); - DBG("==========================================\n"); -} - -static int ec_get_battery_info(struct ec_battery *bat) -{ - u8 buf[13] = {0}; - u16 voltage2; - u16 full_charge_capacity_1; - u16 design_capacity; - u16 cur; - int ret; - int soc; - - ret = ec_i2c_read(bat, EC_GET_BATTERY_INFO_COMMOND, buf, - EC_GET_PARAMETER_NUM); - if ((EC_GET_PARAMETER_NUM - 1) == buf[0]) { - bat->status = buf[2] << 8 | buf[1]; - cur = (buf[4] << 8 | buf[3]); - bat->current_now = cur; - if (buf[4] & 0x80) { - bat->current_now = (~cur) & 0xffff; - bat->current_now = -(bat->current_now); - } - - bat->rem_capacity = buf[6] << 8 | buf[5]; - bat->voltage_now = buf[8] << 8 | buf[7]; - bat->full_charge_capacity = buf[10] << 8 | buf[9]; - bat->temperature_now = buf[12] << 8 | buf[11]; - soc = (bat->rem_capacity + bat->full_charge_capacity / 101) * - 100 / bat->full_charge_capacity; - if (soc > 100) - bat->soc = 100; - else if (soc < 0) - bat->soc = 0; - else - bat->soc = soc; - } else { - dev_err(bat->dev, "get battery info from 0x07 erro\n"); - } - - ret = ec_i2c_read(bat, EC_GET_BATTERY_OTHER_COMMOND, buf, - EC_GET_BATTERYINFO_NUM); - if ((EC_GET_BATTERYINFO_NUM - 1) == buf[0]) { - full_charge_capacity_1 = buf[2] << 8 | buf[1]; - voltage2 = buf[4] << 8 | buf[3]; /* the same to uppo */ - design_capacity = buf[6] << 8 | buf[5]; /* the same to uppo */ - bat->design_capacity = design_capacity; - } - - ec_dump_info(bat); - - return 0; -} - -static int ec_get_current(struct ec_battery *bat) -{ - return bat->current_now * 1000; -} - -static int ec_get_voltage(struct ec_battery *bat) -{ - return bat->voltage_now * 1000; -} - -static int is_ec_bat_exist(struct ec_battery *bat) -{ - int is_exist; - - is_exist = EC_IS_BATTERY_IN(bat->status); - return is_exist; -} - -static int ec_get_capacity(struct ec_battery *bat) -{ - return bat->soc; -} - -static int ec_get_temperature(struct ec_battery *bat) -{ - int temp; - - temp = bat->temperature_now - 2722; - return temp; -} - -static int ec_bat_chrg_online(struct ec_battery *bat) -{ - return EC_IS_CHARGE(bat->status); -} - -#ifdef CONFIG_OF -static int ec_bat_parse_dt(struct ec_battery *bat) -{ - int ret; - u32 out_value; - struct device_node *np = bat->dev->of_node; - - bat->bat_mode = MODE_BATTARY; - bat->monitor_sec = DEFAULT_MONITOR_SEC * TIMER_MS_COUNTS; - - ret = of_property_read_u32(np, "virtual_power", &bat->bat_mode); - if (ret < 0) - dev_err(bat->dev, "virtual_power missing!\n"); - - ret = of_property_read_u32(np, "monitor_sec", &out_value); - if (ret < 0) - dev_err(bat->dev, "monitor_sec missing!\n"); - else - bat->monitor_sec = out_value * TIMER_MS_COUNTS; - - bat->ec_notify_io = - devm_gpiod_get_optional(bat->dev, "ec-notify", - GPIOD_IN); - if (!IS_ERR_OR_NULL(bat->ec_notify_io)) - gpiod_direction_output(bat->ec_notify_io, 0); - - return 0; -} -#else -static int ec_bat_parse_dt(struct ec_battery *bat) -{ - return -ENODEV; -} -#endif - -static enum power_supply_property ec_bat_props[] = { - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_CAPACITY, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_STATUS, -}; - -static int ec_battery_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct ec_battery *bat = power_supply_get_drvdata(psy); - - switch (psp) { - case POWER_SUPPLY_PROP_CURRENT_NOW: - val->intval = ec_get_current(bat);/*uA*/ - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_CURRENT * 1000; - break; - case POWER_SUPPLY_PROP_VOLTAGE_NOW: - val->intval = ec_get_voltage(bat);/*uV*/ - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_VOLTAGE * 1000; - break; - case POWER_SUPPLY_PROP_PRESENT: - val->intval = is_ec_bat_exist(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_PRESET; - break; - case POWER_SUPPLY_PROP_CAPACITY: - val->intval = ec_get_capacity(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_SOC; - break; - case POWER_SUPPLY_PROP_HEALTH: - val->intval = POWER_SUPPLY_HEALTH_GOOD; - break; - case POWER_SUPPLY_PROP_TEMP: - val->intval = ec_get_temperature(bat); - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_TEMPERATURE; - break; - case POWER_SUPPLY_PROP_STATUS: - if (bat->bat_mode == MODE_VIRTUAL) - val->intval = VIRTUAL_STATUS; - else if (ec_get_capacity(bat) == 100) - val->intval = POWER_SUPPLY_STATUS_FULL; - else if (ec_bat_chrg_online(bat)) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - break; - default: - return -EINVAL; - } - - return 0; -} - -static const struct power_supply_desc ec_bat_desc = { - .name = "battery", - .type = POWER_SUPPLY_TYPE_BATTERY, - .properties = ec_bat_props, - .num_properties = ARRAY_SIZE(ec_bat_props), - .get_property = ec_battery_get_property, -}; - -static int ec_bat_init_power_supply(struct ec_battery *bat) -{ - struct power_supply_config psy_cfg = { .drv_data = bat, }; - - bat->bat = power_supply_register(bat->dev, &ec_bat_desc, &psy_cfg); - if (IS_ERR(bat->bat)) { - dev_err(bat->dev, "register bat power supply fail\n"); - return PTR_ERR(bat->bat); - } - - return 0; -} - -static void ec_bat_power_supply_changed(struct ec_battery *ec_bat) -{ - bool state_changed; - static int old_cap = -1; - static int old_temperature; - - state_changed = false; - if (ec_get_capacity(ec_bat) != old_cap) - state_changed = true; - else if (ec_get_temperature(ec_bat) != old_temperature) - state_changed = true; - - if (state_changed) { - power_supply_changed(ec_bat->bat); - old_cap = ec_get_capacity(ec_bat); - old_temperature = ec_get_temperature(ec_bat); - } -} - -static void ec_battery_work(struct work_struct *work) -{ - struct ec_battery *ec_bat = - container_of(work, struct ec_battery, bat_delay_work.work); - - ec_get_battery_info(ec_bat); - ec_bat_power_supply_changed(ec_bat); - - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(ec_bat->monitor_sec)); -} - -static int ec_charger_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ec_battery *ec_bat; - int ret; - - ec_bat = devm_kzalloc(&client->dev, sizeof(*ec_bat), GFP_KERNEL); - if (!ec_bat) - return -ENOMEM; - ec_bat->dev = &client->dev; - ec_bat->i2c = client; - i2c_set_clientdata(client, ec_bat); - - ret = ec_bat_parse_dt(ec_bat); - if (ret < 0) { - dev_err(ec_bat->dev, "parse dt failed!\n"); - return ret; - } - - ret = ec_bat_init_power_supply(ec_bat); - if (ret) { - dev_err(ec_bat->dev, "init power supply fail!\n"); - return ret; - } - - ec_bat->bat_monitor_wq = - alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "ec-bat-monitor-wq"); - INIT_DELAYED_WORK(&ec_bat->bat_delay_work, ec_battery_work); - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(TIMER_MS_COUNTS * 5)); - - return ret; -} - -#ifdef CONFIG_PM_SLEEP -static int ec_bat_pm_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ec_battery *ec_bat = i2c_get_clientdata(client); - - cancel_delayed_work_sync(&ec_bat->bat_delay_work); - - if (!IS_ERR_OR_NULL(ec_bat->ec_notify_io)) - gpiod_direction_output(ec_bat->ec_notify_io, 1); - - return 0; -} - -static int ec_bat_pm_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ec_battery *ec_bat = i2c_get_clientdata(client); - - if (!IS_ERR_OR_NULL(ec_bat->ec_notify_io)) - gpiod_direction_output(ec_bat->ec_notify_io, 0); - - queue_delayed_work(ec_bat->bat_monitor_wq, &ec_bat->bat_delay_work, - msecs_to_jiffies(TIMER_MS_COUNTS * 1)); - - return 0; -} -#endif - -static SIMPLE_DEV_PM_OPS(ec_bat_pm_ops, ec_bat_pm_suspend, ec_bat_pm_resume); - -static const struct i2c_device_id ec_battery_i2c_ids[] = { - { "ec_battery" }, - { }, -}; -MODULE_DEVICE_TABLE(i2c, ec_battery_i2c_ids); - -#ifdef CONFIG_OF -static const struct of_device_id ec_of_match[] = { - { .compatible = "rockchip,ec-battery" }, - { }, -}; -MODULE_DEVICE_TABLE(of, ec_of_match); -#else -static const struct of_device_id ec_of_match[] = { - { }, -}; -#endif - -static struct i2c_driver ec_i2c_driver = { - .driver = { - .name = "ec_battery", - .pm = &ec_bat_pm_ops, - .of_match_table = ec_of_match, - }, - .id_table = ec_battery_i2c_ids, - .probe = ec_charger_probe, -}; - -module_i2c_driver(ec_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ec-charger"); -MODULE_AUTHOR("Shunqing Chen"); diff --git a/drivers/power/sy6982c_charger.c b/drivers/power/sy6982c_charger.c deleted file mode 100644 index dfa82c3f8d27..000000000000 --- a/drivers/power/sy6982c_charger.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * sy6982c/sy6982e charger driver - * - * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum charger_t { - USB_TYPE_UNKNOWN_CHARGER, - USB_TYPE_NONE_CHARGER, - USB_TYPE_USB_CHARGER, - USB_TYPE_AC_CHARGER, - USB_TYPE_CDP_CHARGER, - DC_TYPE_DC_CHARGER, - DC_TYPE_NONE_CHARGER, -}; - -struct sy6982c_charger { - struct device *dev; - struct power_supply *usb_psy; - struct workqueue_struct *usb_charger_wq; - struct delayed_work usb_work; - struct workqueue_struct *dc_charger_wq; - struct delayed_work dc_work; - struct delayed_work discnt_work; - struct notifier_block cable_cg_nb; - struct notifier_block cable_discnt_nb; - unsigned int bc_event; - enum charger_t usb_charger; - enum charger_t dc_charger; - bool extcon; - struct extcon_dev *cable_edev; - struct gpio_desc *dc_det_pin; - bool support_dc_det; -}; - -static void sy6982c_cg_bc_evt_worker(struct work_struct *work) -{ - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, usb_work.work); - struct extcon_dev *edev = cg->cable_edev; - enum charger_t charger = USB_TYPE_UNKNOWN_CHARGER; - const char *event[5] = {"UN", "NONE", "USB", "AC", "CDP1.5A"}; - - /* Determine cable/charger type */ - if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) - charger = USB_TYPE_USB_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) - charger = USB_TYPE_AC_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) - charger = USB_TYPE_CDP_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) == 0) - charger = USB_TYPE_NONE_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) == 0) - charger = USB_TYPE_NONE_CHARGER; - - if (charger != USB_TYPE_UNKNOWN_CHARGER) { - dev_info(cg->dev, "receive type-c notifier event: %s...\n", - event[charger]); - cg->usb_charger = charger; - } -} - -static int sy6982c_cg_charger_evt_notifier(struct notifier_block *nb, - unsigned long event, - void *ptr) -{ - struct sy6982c_charger *cg = - container_of(nb, struct sy6982c_charger, cable_cg_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->usb_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static void sy6982c_cg_discnt_evt_worker(struct work_struct *work) -{ - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, discnt_work.work); - - if (extcon_get_cable_state_(cg->cable_edev, EXTCON_USB) == 0) { - dev_info(cg->dev, "receive type-c notifier event: DISCNT...\n"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - } -} - -static int sy6982c_cg_discnt_evt_notfier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct sy6982c_charger *cg = - container_of(nb, struct sy6982c_charger, cable_discnt_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->discnt_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static int sy6982c_cg_init_usb(struct sy6982c_charger *cg) -{ - struct device *dev = cg->dev; - int ret; - struct extcon_dev *edev; - - if (!cg->extcon) - return -1; - - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - if (PTR_ERR(edev) != -EPROBE_DEFER) - dev_err(dev, "Invalid or missing extcon\n"); - return PTR_ERR(edev); - } - - cg->usb_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "sy6982c-usb-wq"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - - /* Register chargers */ - INIT_DELAYED_WORK(&cg->usb_work, sy6982c_cg_bc_evt_worker); - cg->cable_cg_nb.notifier_call = sy6982c_cg_charger_evt_notifier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_SDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for SDP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_DCP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for DCP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_CDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for CDP\n"); - goto __fail; - } - - /* Register discnt usb */ - INIT_DELAYED_WORK(&cg->discnt_work, sy6982c_cg_discnt_evt_worker); - cg->cable_discnt_nb.notifier_call = sy6982c_cg_discnt_evt_notfier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB, - &cg->cable_discnt_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for HOST\n"); - goto __fail; - } - - cg->cable_edev = edev; - schedule_delayed_work(&cg->usb_work, 0); - dev_info(cg->dev, "register extcon evt notifier\n"); - - return 0; - -__fail: - destroy_workqueue(cg->usb_charger_wq); - return ret; -} - -static enum power_supply_property sy6982c_usb_props[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_STATUS, -}; - -static int sy6982c_cg_usb_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct sy6982c_charger *cg = power_supply_get_drvdata(psy); - int online = 0; - int ret = 0; - - if (cg->usb_charger != USB_TYPE_UNKNOWN_CHARGER && - cg->usb_charger != USB_TYPE_NONE_CHARGER) - online = 1; - if (cg->dc_charger != DC_TYPE_NONE_CHARGER) - online = 1; - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = online; - - dev_dbg(cg->dev, "report online: %d\n", val->intval); - break; - case POWER_SUPPLY_PROP_STATUS: - if (online) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - - dev_dbg(cg->dev, "report prop: %d\n", val->intval); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct power_supply_desc sy6982c_usb_desc = { - .name = "sy6982c_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = sy6982c_usb_props, - .num_properties = ARRAY_SIZE(sy6982c_usb_props), - .get_property = sy6982c_cg_usb_get_property, -}; - -static int sy6982c_cg_init_power_supply(struct sy6982c_charger *cg) -{ - struct power_supply_config psy_cfg = { .drv_data = cg, }; - - cg->usb_psy = devm_power_supply_register(cg->dev, &sy6982c_usb_desc, - &psy_cfg); - if (IS_ERR(cg->usb_psy)) { - dev_err(cg->dev, "register usb power supply fail\n"); - return PTR_ERR(cg->usb_psy); - } - - return 0; -} - -#ifdef CONFIG_OF -static int sy6982c_charger_parse_dt(struct sy6982c_charger *cg) -{ - struct device *dev = cg->dev; - - cg->dc_det_pin = devm_gpiod_get_optional(dev, "dc-det", - GPIOD_IN); - if (!IS_ERR_OR_NULL(cg->dc_det_pin)) { - cg->support_dc_det = true; - } else { - dev_err(dev, "invalid dc det gpio!\n"); - cg->support_dc_det = false; - } - - return 0; -} -#else -static int sy6982c_charger_parse_dt(struct sy6982c_charger *cg) -{ - return -ENODEV; -} -#endif - -static enum charger_t sy6982c_charger_get_dc_state(struct sy6982c_charger *cg) -{ - return (gpiod_get_value(cg->dc_det_pin)) ? - DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER; -} - -static void sy6982c_charger_dc_det_worker(struct work_struct *work) -{ - enum charger_t charger; - struct sy6982c_charger *cg = container_of(work, - struct sy6982c_charger, dc_work.work); - - charger = sy6982c_charger_get_dc_state(cg); - if (charger == DC_TYPE_DC_CHARGER) - cg->dc_charger = charger; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - rk_send_wakeup_key(); -} - -static irqreturn_t sy6982c_charger_dc_det_isr(int irq, void *charger) -{ - struct sy6982c_charger *cg = (struct sy6982c_charger *)charger; - - queue_delayed_work(cg->dc_charger_wq, &cg->dc_work, - msecs_to_jiffies(10)); - - return IRQ_HANDLED; -} - -static int sy6982c_charger_init_dc(struct sy6982c_charger *cg) -{ - int ret; - unsigned long irq_flags; - unsigned int dc_det_irq; - - if (!cg->support_dc_det) - return 0; - - cg->dc_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "sy6982c-dc-wq"); - if (!cg->dc_charger_wq) - return -EINVAL; - - INIT_DELAYED_WORK(&cg->dc_work, sy6982c_charger_dc_det_worker); - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - if (gpiod_get_value(cg->dc_det_pin)) - cg->dc_charger = DC_TYPE_DC_CHARGER; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dc_det_irq = gpiod_to_irq(cg->dc_det_pin); - ret = devm_request_irq(cg->dev, dc_det_irq, sy6982c_charger_dc_det_isr, - irq_flags, "sy6982c_dc_det", cg); - if (ret != 0) { - dev_err(cg->dev, "sy6982c_dc_det_irq request failed!\n"); - return ret; - } - - enable_irq_wake(dc_det_irq); - - return 0; -} - -static int sy6982c_charger_probe(struct platform_device *pdev) -{ - struct sy6982c_charger *cg; - int ret; - - cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL); - if (!cg) - return -ENOMEM; - - cg->dev = &pdev->dev; - sy6982c_charger_parse_dt(cg); - sy6982c_charger_init_dc(cg); - cg->extcon = device_property_read_bool(cg->dev, "extcon"); - ret = sy6982c_cg_init_usb(cg); - if (ret) { - dev_err(cg->dev, "init usb failed!\n"); - return ret; - } - - ret = sy6982c_cg_init_power_supply(cg); - if (ret) { - dev_err(cg->dev, "init power supply fail!\n"); - return ret; - } - - dev_info(cg->dev, "driver registered\n"); - - return 0; -} - -static int sy6982c_charger_remove(struct platform_device *pdev) -{ - struct sy6982c_charger *cg = platform_get_drvdata(pdev); - - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); - - return 0; -} - -static const struct of_device_id sy6982c_charger_match[] = { - { - .compatible = "sy6982c-charger", - }, - {}, -}; - -static struct platform_driver sy6982c_charger_driver = { - .probe = sy6982c_charger_probe, - .remove = sy6982c_charger_remove, - .driver = { - .name = "sy6982c-charger", - .of_match_table = sy6982c_charger_match, - }, -}; - -module_platform_driver(sy6982c_charger_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:sy6982c-charger"); -MODULE_AUTHOR("chen Shunqing"); diff --git a/drivers/power/universal_charger.c b/drivers/power/universal_charger.c deleted file mode 100644 index 0f7b4c9e8003..000000000000 --- a/drivers/power/universal_charger.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * universal charger driver - * - * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum charger_t { - USB_TYPE_UNKNOWN_CHARGER, - USB_TYPE_NONE_CHARGER, - USB_TYPE_USB_CHARGER, - USB_TYPE_AC_CHARGER, - USB_TYPE_CDP_CHARGER, - DC_TYPE_DC_CHARGER, - DC_TYPE_NONE_CHARGER, -}; - -struct universal_charger { - struct device *dev; - struct power_supply *usb_psy; - struct workqueue_struct *usb_charger_wq; - struct delayed_work usb_work; - struct workqueue_struct *dc_charger_wq; - struct delayed_work dc_work; - struct delayed_work discnt_work; - struct notifier_block cable_cg_nb; - struct notifier_block cable_discnt_nb; - unsigned int bc_event; - enum charger_t usb_charger; - enum charger_t dc_charger; - bool extcon; - struct extcon_dev *cable_edev; - struct gpio_desc *dc_det_pin; - bool support_dc_det; -}; - -static void universal_cg_bc_evt_worker(struct work_struct *work) -{ - struct universal_charger *cg = - container_of(work, struct universal_charger, usb_work.work); - struct extcon_dev *edev = cg->cable_edev; - enum charger_t charger = USB_TYPE_UNKNOWN_CHARGER; - const char *event[5] = {"UN", "NONE", "USB", "AC", "CDP1.5A"}; - - /* Determine cable/charger type */ - if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_SDP) > 0) - charger = USB_TYPE_USB_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) > 0) - charger = USB_TYPE_AC_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) > 0) - charger = USB_TYPE_CDP_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_DCP) == 0) - charger = USB_TYPE_NONE_CHARGER; - else if (extcon_get_cable_state_(edev, EXTCON_CHG_USB_CDP) == 0) - charger = USB_TYPE_NONE_CHARGER; - - if (charger != USB_TYPE_UNKNOWN_CHARGER) { - dev_info(cg->dev, "receive usb notifier event: %s...\n", - event[charger]); - cg->usb_charger = charger; - } -} - -static int universal_cg_charger_evt_notifier(struct notifier_block *nb, - unsigned long event, - void *ptr) -{ - struct universal_charger *cg = - container_of(nb, struct universal_charger, cable_cg_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->usb_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static void universal_cg_discnt_evt_worker(struct work_struct *work) -{ - struct universal_charger *cg = container_of(work, - struct universal_charger, discnt_work.work); - - if (extcon_get_cable_state_(cg->cable_edev, EXTCON_USB) == 0) { - dev_info(cg->dev, "receive usb notifier event: DISCNT...\n"); - cg->usb_charger = USB_TYPE_NONE_CHARGER; - } -} - -static int universal_cg_discnt_evt_notfier(struct notifier_block *nb, - unsigned long event, void *ptr) -{ - struct universal_charger *cg = - container_of(nb, struct universal_charger, cable_discnt_nb); - - queue_delayed_work(cg->usb_charger_wq, &cg->discnt_work, - msecs_to_jiffies(10)); - - return NOTIFY_DONE; -} - -static int universal_cg_init_usb(struct universal_charger *cg) -{ - struct device *dev = cg->dev; - int ret; - struct extcon_dev *edev; - - if (!cg->extcon) - return 0; - - edev = extcon_get_edev_by_phandle(dev, 0); - if (IS_ERR(edev)) { - if (PTR_ERR(edev) != -EPROBE_DEFER) - dev_err(dev, "Invalid or missing extcon\n"); - return PTR_ERR(edev); - } - - cg->usb_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "universal-usb-wq"); - if (!cg->usb_charger_wq) - return -ENOMEM; - - cg->usb_charger = USB_TYPE_NONE_CHARGER; - - /* Register chargers */ - INIT_DELAYED_WORK(&cg->usb_work, universal_cg_bc_evt_worker); - cg->cable_cg_nb.notifier_call = universal_cg_charger_evt_notifier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_SDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for SDP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_DCP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for DCP\n"); - goto __fail; - } - - ret = devm_extcon_register_notifier(dev, edev, EXTCON_CHG_USB_CDP, - &cg->cable_cg_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for CDP\n"); - goto __fail; - } - - /* Register discnt usb */ - INIT_DELAYED_WORK(&cg->discnt_work, universal_cg_discnt_evt_worker); - cg->cable_discnt_nb.notifier_call = universal_cg_discnt_evt_notfier; - ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB, - &cg->cable_discnt_nb); - if (ret < 0) { - dev_err(dev, "failed to register notifier for HOST\n"); - goto __fail; - } - - cg->cable_edev = edev; - schedule_delayed_work(&cg->usb_work, 0); - dev_info(cg->dev, "register extcon evt notifier\n"); - - return 0; - -__fail: - destroy_workqueue(cg->usb_charger_wq); - return ret; -} - -static enum power_supply_property universal_usb_props[] = { - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_STATUS, -}; - -static int universal_cg_usb_get_property(struct power_supply *psy, - enum power_supply_property psp, - union power_supply_propval *val) -{ - struct universal_charger *cg = power_supply_get_drvdata(psy); - int online = 0; - int ret = 0; - - if (cg->usb_charger != USB_TYPE_UNKNOWN_CHARGER && - cg->usb_charger != USB_TYPE_NONE_CHARGER) - online = 1; - if (cg->dc_charger != DC_TYPE_NONE_CHARGER) - online = 1; - switch (psp) { - case POWER_SUPPLY_PROP_ONLINE: - val->intval = online; - - dev_dbg(cg->dev, "report online: %d\n", val->intval); - break; - case POWER_SUPPLY_PROP_STATUS: - if (online) - val->intval = POWER_SUPPLY_STATUS_CHARGING; - else - val->intval = POWER_SUPPLY_STATUS_DISCHARGING; - - dev_dbg(cg->dev, "report prop: %d\n", val->intval); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static const struct power_supply_desc universal_usb_desc = { - .name = "universal_usb", - .type = POWER_SUPPLY_TYPE_USB, - .properties = universal_usb_props, - .num_properties = ARRAY_SIZE(universal_usb_props), - .get_property = universal_cg_usb_get_property, -}; - -static int universal_cg_init_power_supply(struct universal_charger *cg) -{ - struct power_supply_config psy_cfg = { .drv_data = cg, }; - - cg->usb_psy = devm_power_supply_register(cg->dev, &universal_usb_desc, - &psy_cfg); - if (IS_ERR(cg->usb_psy)) { - dev_err(cg->dev, "register usb power supply fail\n"); - return PTR_ERR(cg->usb_psy); - } - - return 0; -} - -#ifdef CONFIG_OF -static int universal_charger_parse_dt(struct universal_charger *cg) -{ - struct device *dev = cg->dev; - - cg->dc_det_pin = devm_gpiod_get_optional(dev, "dc-det", - GPIOD_IN); - if (!IS_ERR_OR_NULL(cg->dc_det_pin)) { - cg->support_dc_det = true; - } else { - dev_err(dev, "invalid dc det gpio!\n"); - cg->support_dc_det = false; - } - - return 0; -} -#else -static int universal_charger_parse_dt(struct universal_charger *cg) -{ - return -ENODEV; -} -#endif - -static enum -charger_t universal_charger_get_dc_state(struct universal_charger *cg) -{ - return (gpiod_get_value(cg->dc_det_pin)) ? - DC_TYPE_DC_CHARGER : DC_TYPE_NONE_CHARGER; -} - -static void universal_charger_dc_det_worker(struct work_struct *work) -{ - enum charger_t charger; - struct universal_charger *cg = container_of(work, - struct universal_charger, dc_work.work); - - charger = universal_charger_get_dc_state(cg); - if (charger == DC_TYPE_DC_CHARGER) - cg->dc_charger = charger; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; -} - -static irqreturn_t universal_charger_dc_det_isr(int irq, void *charger) -{ - struct universal_charger *cg = (struct universal_charger *)charger; - - queue_delayed_work(cg->dc_charger_wq, &cg->dc_work, - msecs_to_jiffies(10)); - - return IRQ_HANDLED; -} - -static int universal_charger_init_dc(struct universal_charger *cg) -{ - int ret; - unsigned long irq_flags; - unsigned int dc_det_irq; - - if (!cg->support_dc_det) - return 0; - - cg->dc_charger_wq = alloc_ordered_workqueue("%s", - WQ_MEM_RECLAIM | WQ_FREEZABLE, - "universal-dc-wq"); - if (!cg->dc_charger_wq) - return -ENOMEM; - - INIT_DELAYED_WORK(&cg->dc_work, universal_charger_dc_det_worker); - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - if (gpiod_get_value(cg->dc_det_pin)) - cg->dc_charger = DC_TYPE_DC_CHARGER; - else - cg->dc_charger = DC_TYPE_NONE_CHARGER; - - irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - dc_det_irq = gpiod_to_irq(cg->dc_det_pin); - ret = devm_request_irq(cg->dev, dc_det_irq, - universal_charger_dc_det_isr, - irq_flags, "universal_dc_det", cg); - if (ret != 0) { - destroy_workqueue(cg->dc_charger_wq); - dev_err(cg->dev, "universal_dc_det_irq request failed!\n"); - return ret; - } - - enable_irq_wake(dc_det_irq); - - return 0; -} - -static int universal_charger_probe(struct platform_device *pdev) -{ - struct universal_charger *cg; - int ret; - - cg = devm_kzalloc(&pdev->dev, sizeof(*cg), GFP_KERNEL); - if (!cg) - return -ENOMEM; - - cg->dev = &pdev->dev; - universal_charger_parse_dt(cg); - ret = universal_charger_init_dc(cg); - if (ret) { - dev_err(cg->dev, "init dc failed!\n"); - return ret; - } - cg->extcon = device_property_read_bool(cg->dev, "extcon"); - ret = universal_cg_init_usb(cg); - if (ret) { - dev_err(cg->dev, "init usb failed!\n"); - goto __init_usb_fail; - } - - ret = universal_cg_init_power_supply(cg); - if (ret) { - dev_err(cg->dev, "init power supply fail!\n"); - goto ___init_psy_fail; - } - - dev_info(cg->dev, "driver registered\n"); - - return 0; - -___init_psy_fail: - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); -__init_usb_fail: - if (cg->dc_charger_wq) - destroy_workqueue(cg->dc_charger_wq); - - return ret; -} - -static int universal_charger_remove(struct platform_device *pdev) -{ - struct universal_charger *cg = platform_get_drvdata(pdev); - - if (cg->usb_charger_wq) - destroy_workqueue(cg->usb_charger_wq); - if (cg->dc_charger_wq) - destroy_workqueue(cg->dc_charger_wq); - - return 0; -} - -static const struct of_device_id universal_charger_match[] = { - { - .compatible = "universal-charger", - }, - {}, -}; - -static struct platform_driver universal_charger_driver = { - .probe = universal_charger_probe, - .remove = universal_charger_remove, - .driver = { - .name = "universal-charger", - .of_match_table = universal_charger_match, - }, -}; - -module_platform_driver(universal_charger_driver); - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:universal-charger"); -MODULE_AUTHOR("chen Shunqing"); diff --git a/drivers/video/rockchip/dvbm/Kconfig b/drivers/video/rockchip/dvbm/Kconfig index bfbd396b2706..480027e3bd1e 100644 --- a/drivers/video/rockchip/dvbm/Kconfig +++ b/drivers/video/rockchip/dvbm/Kconfig @@ -5,14 +5,3 @@ menuconfig ROCKCHIP_DVBM depends on ARCH_ROCKCHIP help rockchip dvbm module. - -if ROCKCHIP_DVBM - -config ROCKCHIP_DVBM_PROC_FS - bool "enable dvbm procfs" - depends on PROC_FS - default y - help - rockchip dvbm procfs. - -endif diff --git a/drivers/video/rockchip/dvbm/rockchip_dvbm.c b/drivers/video/rockchip/dvbm/rockchip_dvbm.c index 2e40a7e78e78..93760d3f3f48 100644 --- a/drivers/video/rockchip/dvbm/rockchip_dvbm.c +++ b/drivers/video/rockchip/dvbm/rockchip_dvbm.c @@ -7,17 +7,10 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include -#include -#include -#include -#include #include -#include "rockchip_dvbm.h" - #define RK_DVBM "rk_dvbm" unsigned int dvbm_debug; @@ -27,9 +20,6 @@ MODULE_PARM_DESC(dvbm_debug, "bit switch for dvbm debug information"); static struct dvbm_ctx *g_ctx; #define DVBM_DEBUG 0x00000001 -#define DVBM_DEBUG_IRQ 0x00000002 -#define DVBM_DEBUG_REG 0x00000004 -#define DVBM_DEBUG_DUMP 0x00000008 #define DVBM_DEBUG_FRM 0x00000010 #define dvbm_debug(fmt, args...) \ @@ -38,106 +28,45 @@ static struct dvbm_ctx *g_ctx; pr_info(fmt, ##args); \ } while (0) -#define dvbm_debug_reg(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_REG))) \ - pr_info(fmt, ##args); \ - } while (0) - -#define dvbm_debug_irq(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_IRQ))) \ - pr_info(fmt, ##args); \ - } while (0) - -#define dvbm_debug_dump(fmt, args...) \ - do { \ - if (unlikely(dvbm_debug & (DVBM_DEBUG_DUMP))) \ - pr_info(fmt, ##args); \ - } while (0) - #define dvbm_debug_frm(fmt, args...) \ do { \ if (unlikely(dvbm_debug & (DVBM_DEBUG_FRM))) \ pr_info(fmt, ##args); \ } while (0) -#define dvbm_err(fmt, args...) \ - pr_err(fmt, ##args) +#define dvbm_err(fmt, args...) \ + pr_err("%s:%d: " fmt, __func__, __LINE__, ##args) -enum dvbm_flow { - ISP_CFG = 1, - ISP_CONNECT = 2, - VEPU_CFG = 3, - VEPU_CONNECT = 4, -}; -/* dvbm status reg bit value define */ -#define BUF_OVERFLOW BIT(0) -#define RESYNC_FINISH BIT(1) -#define ISP_CNCT_TIMEOUT BIT(2) -#define VEPU_CNCT_TIMEOUT BIT(3) -#define VEPU_HANDSHAKE_TIMEOUT BIT(4) -#define ISP_CNCT BIT(5) -#define ISP_DISCNCT BIT(6) -#define VEPU_CNCT BIT(7) -#define VEPU_DISCNCT BIT(8) - -/* dvbm reg addr define */ -#define DVBM_VERSION 0x0 -#define DVBM_ISP_CNCT 0x4 -#define DVBM_VEPU_CNCT 0x8 -/* cfg regs */ -#define DVBM_CFG 0xC -#define DVBM_WDG_CFG0 0x10 -#define DVBM_WDG_CFG1 0x14 -#define DVBM_WDG_CFG2 0x18 -/* interrupt regs */ -#define DVBM_INT_EN 0x1c -#define DVBM_INT_MSK 0x20 -#define DVBM_INT_CLR 0x24 -#define DVBM_INT_ST 0x28 -/* addr regs */ -#define DVBM_YBUF_BOT 0x2c -#define DVBM_YBUF_TOP 0x30 -#define DVBM_YBUF_SADR 0x34 -#define DVBM_YBUF_LSTD 0x38 -#define DVBM_YBUF_FSTD 0x3c -#define DVBM_CBUF_BOT 0x40 -#define DVBM_CBUF_TOP 0x44 -#define DVBM_CBUF_SADR 0x48 -#define DVBM_CBUF_LSTD 0x4c -#define DVBM_CBUF_FSTD 0x50 -#define DVBM_AFUL_THDY 0x54 -#define DVBM_AFUL_THDC 0x58 -#define DVBM_OVFL_THDY 0x5c -#define DVBM_OVFL_THDC 0x60 -/* status regs */ -#define DVBM_ST 0x80 -#define DVBM_OVFL_ST 0x84 - -#define DVBM_REG_OFFSET 0x2c - -#define SOFT_DVBM 1 #define UPDATE_LINE_CNT 0 -static void rk_dvbm_set_reg(struct dvbm_ctx *ctx, u32 offset, u32 val) -{ - if (!SOFT_DVBM) { - dvbm_debug_reg("write reg[%d] 0x%x = 0x%08x\n", offset >> 2, offset, val); - writel(val, ctx->reg_base + offset); - } -} +#define DVBM_CHANNEL_NUM (3) -static u32 rk_dvbm_read_reg(struct dvbm_ctx *ctx, u32 offset) -{ - u32 val = 0; +struct dvbm_ctx { + struct device *dev; - if (!SOFT_DVBM) { - val = readl(ctx->reg_base + offset); - dvbm_debug_reg("read reg[%d] 0x%x = 0x%08x\n", offset >> 2, offset, val); - } - return val; -} + u32 isp_connet; + u32 vepu_connet; + + /* vepu infos */ + struct dvbm_port port_vepu; + atomic_t vepu_link; + struct dvbm_cb vepu_cb; + struct dvbm_addr_cfg vepu_cfg; + + /* isp infos */ + struct dvbm_port port_isp; + struct dvbm_cb isp_cb; + struct dvbm_isp_cfg_t isp_cfg[DVBM_CHANNEL_NUM]; + struct dvbm_addr_cfg dvbm_addr[DVBM_CHANNEL_NUM]; + u32 chan_id; + struct dvbm_isp_frm_info isp_frm_info; + atomic_t isp_link; + u32 isp_max_lcnt; + u32 isp_frm_start; + u32 isp_frm_end; + ktime_t isp_frm_time; + u32 wrap_line; +}; static struct dvbm_ctx *port_to_ctx(struct dvbm_port *port) { @@ -158,39 +87,12 @@ static void dvbm2enc_callback(struct dvbm_ctx *ctx, enum dvbm_cb_event event, vo struct dvbm_cb *callback = &ctx->vepu_cb; dvbm_callback cb = callback->cb; - if (!ctx->port_vepu.linked) + if (!cb) { + dvbm_err("vepu callback is null\n"); return; - if (cb) - cb(callback->ctx, event, arg); -} + } -static void rk_dvbm_dump_regs(struct dvbm_ctx *ctx) -{ - u32 start = ctx->dump_s;//0x80; - u32 end = ctx->dump_e;//0xb8; - u32 i; - dvbm_debug_dump("=== %s ===\n", __func__); - for (i = start; i <= end; i += 4) - dvbm_debug_dump("reg[0x%0x] = 0x%08x\n", i, readl(ctx->reg_base + i)); - dvbm_debug_dump("=== %s ===\n", __func__); -} - -static int rk_dvbm_clk_on(struct dvbm_ctx *ctx) -{ - int ret = 0; - - if (ctx->clk) - ret = clk_prepare_enable(ctx->clk); - if (ret) - dev_err(ctx->dev, "clk on failed\n"); - return ret; -} - -static int rk_dvbm_clk_off(struct dvbm_ctx *ctx) -{ - if (ctx->clk) - clk_disable_unprepare(ctx->clk); - return 0; + cb(callback->ctx, event, arg); } static void init_isp_infos(struct dvbm_ctx *ctx) @@ -222,84 +124,6 @@ static void rk_dvbm_update_isp_frm_info(struct dvbm_ctx *ctx, u32 line_cnt) #endif } -static int rk_dvbm_setup_iobuf(struct dvbm_ctx *ctx) -{ - u32 *data; - u32 i; - struct rk_dvbm_base *addr_base = &ctx->regs.addr_base; - struct dvbm_isp_cfg_t *cfg = &ctx->isp_cfg; - - addr_base->ybuf_bot = cfg->dma_addr + cfg->ybuf_bot; - addr_base->ybuf_top = cfg->dma_addr + cfg->ybuf_top; - addr_base->ybuf_sadr = cfg->dma_addr + cfg->ybuf_bot; - addr_base->ybuf_fstd = cfg->ybuf_fstd; - addr_base->ybuf_lstd = cfg->ybuf_lstd; - - addr_base->cbuf_bot = cfg->dma_addr + cfg->cbuf_bot; - addr_base->cbuf_top = cfg->dma_addr + cfg->cbuf_top; - addr_base->cbuf_sadr = cfg->dma_addr + cfg->cbuf_bot; - addr_base->cbuf_fstd = cfg->cbuf_fstd; - addr_base->cbuf_lstd = cfg->cbuf_lstd; - - addr_base->aful_thdy = cfg->ybuf_lstd; - addr_base->aful_thdc = cfg->ybuf_lstd; - addr_base->oful_thdy = cfg->ybuf_lstd; - addr_base->oful_thdc = cfg->ybuf_lstd; - - ctx->isp_max_lcnt = cfg->ybuf_fstd / cfg->ybuf_lstd; - ctx->wrap_line = (cfg->ybuf_top - cfg->ybuf_bot) / cfg->ybuf_lstd; - ctx->isp_frm_info.frame_cnt = 0; - ctx->isp_frm_info.line_cnt = 0; - ctx->isp_frm_info.max_line_cnt = ALIGN(ctx->isp_max_lcnt, 32); - ctx->isp_frm_info.wrap_line = ctx->wrap_line; - dvbm_debug("dma_addr %pad y_lstd %d y_fstd %d\n", - &cfg->dma_addr, cfg->ybuf_lstd, cfg->ybuf_fstd); - dvbm_debug("ybot 0x%x top 0x%x cbuf bot 0x%x top 0x%x\n", - addr_base->ybuf_bot, addr_base->ybuf_top, - addr_base->cbuf_bot, addr_base->cbuf_top); - - data = (u32 *)addr_base; - for (i = 0; i < sizeof(struct rk_dvbm_base) / sizeof(u32); i++) - rk_dvbm_set_reg(ctx, i * sizeof(u32) + DVBM_REG_OFFSET, data[i]); - - for (i = 1; i < 65536; i++) - if (!((addr_base->ybuf_fstd * i) % (cfg->ybuf_top - cfg->ybuf_bot))) - break; - ctx->loopcnt = i; - return 0; -} - -static void rk_dvbm_reg_init(struct dvbm_ctx *ctx) -{ - struct rk_dvbm_regs *reg = &ctx->regs; - u32 *val = (u32 *)reg; - - reg->int_en.buf_ovfl = 1; - reg->int_en.isp_cnct = 1; - reg->int_en.vepu_cnct = 1; - reg->int_en.vepu_discnct = 1; - reg->int_en.isp_discnct = 1; - reg->int_en.resync_finish = 1; - reg->int_en.isp_cnct_timeout = 1; - reg->int_en.vepu_cnct_timeout = 1; - reg->int_en.vepu_handshake_timeout = 1; - - reg->dvbm_cfg.fmt = 0; - reg->dvbm_cfg.auto_resyn = 0; - reg->dvbm_cfg.ignore_vepu_cnct_ack = 0; - reg->dvbm_cfg.start_point_after_vepu_cnct = 0; - - reg->wdg_cfg0.wdg_isp_cnct_timeout = 0xfffff; - reg->wdg_cfg1.wdg_vepu_cnct_timeout = 0xfffff; - reg->wdg_cfg2.wdg_vepu_handshake_timeout = 0xfffff; - - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG0, val[DVBM_WDG_CFG0 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG1, val[DVBM_WDG_CFG1 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_WDG_CFG2, val[DVBM_WDG_CFG2 >> 2]); - rk_dvbm_set_reg(ctx, DVBM_CFG, val[DVBM_CFG >> 2]); - rk_dvbm_set_reg(ctx, DVBM_INT_EN, val[DVBM_INT_EN >> 2]); -} - struct dvbm_port *rk_dvbm_get_port(struct platform_device *pdev, enum dvbm_port_dir dir) { @@ -329,18 +153,17 @@ int rk_dvbm_put(struct dvbm_port *port) return -EINVAL; ctx = port_to_ctx(port); - if (!ctx) return -EINVAL; + return 0; } EXPORT_SYMBOL(rk_dvbm_put); -int rk_dvbm_link(struct dvbm_port *port) +int rk_dvbm_link(struct dvbm_port *port, int id) { struct dvbm_ctx *ctx; enum dvbm_port_dir dir; - struct rk_dvbm_regs *reg; int ret = 0; if (WARN_ON(!port)) @@ -348,59 +171,40 @@ int rk_dvbm_link(struct dvbm_port *port) ctx = port_to_ctx(port); dir = port->dir; - reg = &ctx->regs; if (dir == DVBM_ISP_PORT) { - if (port->linked) { - rk_dvbm_unlink(port); - udelay(5); - } - reg->isp_cnct.isp_cnct = 1; - rk_dvbm_set_reg(ctx, DVBM_ISP_CNCT, 0x1); + if (id >= DVBM_CHANNEL_NUM) + dvbm_err("id %d is invalid\n", id); + + dvbm2enc_callback(ctx, DVBM_ISP_REQ_CONNECT, &id); } else if (dir == DVBM_VEPU_PORT) { - if (!port->linked) { - reg->vepu_cnct.vepu_cnct = 1; - rk_dvbm_set_reg(ctx, DVBM_VEPU_CNCT, 0x1); - } - port->linked = 1; - dvbm_debug_dump("=== vepu link ===\n"); - rk_dvbm_dump_regs(ctx); - dvbm_debug_dump("=== vepu link ===\n"); } - dvbm_debug("%s connect frm_cnt[%d : %d]\n", - dir == DVBM_ISP_PORT ? "isp" : "vepu", + dvbm_debug("%s %d connect frm_cnt[%d : %d]\n", + dir == DVBM_ISP_PORT ? "isp" : "vepu", id, ctx->isp_frm_start, ctx->isp_frm_end); return ret; } EXPORT_SYMBOL(rk_dvbm_link); -int rk_dvbm_unlink(struct dvbm_port *port) +int rk_dvbm_unlink(struct dvbm_port *port, int id) { struct dvbm_ctx *ctx; enum dvbm_port_dir dir; - struct rk_dvbm_regs *reg; if (WARN_ON(!port)) return -EINVAL; ctx = port_to_ctx(port); dir = port->dir; - reg = &ctx->regs; if (dir == DVBM_ISP_PORT) { - reg->isp_cnct.isp_cnct = 0; - rk_dvbm_set_reg(ctx, DVBM_ISP_CNCT, 0); - } else if (dir == DVBM_VEPU_PORT) { - reg->vepu_cnct.vepu_cnct = 0; - port->linked = 0; - rk_dvbm_set_reg(ctx, DVBM_VEPU_CNCT, 0); - if (!ctx->regs.dvbm_cfg.auto_resyn) { - u32 connect = 0; + if (id >= DVBM_CHANNEL_NUM) + dvbm_err("id %d is invalid\n", id); - dvbm2enc_callback(ctx, DVBM_VEPU_REQ_CONNECT, &connect); - } + dvbm2enc_callback(ctx, DVBM_ISP_REQ_DISCONNECT, &id); + } else if (dir == DVBM_VEPU_PORT) { } dvbm_debug("%s disconnect\n", dir == DVBM_ISP_PORT ? "isp" : "vepu"); @@ -430,27 +234,9 @@ int rk_dvbm_set_cb(struct dvbm_port *port, struct dvbm_cb *cb) } EXPORT_SYMBOL(rk_dvbm_set_cb); -static void rk_dvbm_update_next_adr(struct dvbm_ctx *ctx) -{ - u32 frame_cnt = ctx->isp_frm_start; - struct dvbm_isp_cfg_t *isp_cfg = &ctx->isp_cfg; - struct dvbm_addr_cfg *vepu_cfg = &ctx->vepu_cfg; - u32 y_wrap_size = isp_cfg->ybuf_top - isp_cfg->ybuf_bot; - u32 c_wrap_size = isp_cfg->cbuf_top - isp_cfg->cbuf_bot; - u32 s_off; - - frame_cnt = (frame_cnt + 1) % (ctx->loopcnt); - s_off = (frame_cnt * isp_cfg->ybuf_fstd) % y_wrap_size; - vepu_cfg->ybuf_sadr = isp_cfg->dma_addr + isp_cfg->ybuf_bot + s_off; - - s_off = (frame_cnt * isp_cfg->cbuf_fstd) % c_wrap_size; - vepu_cfg->cbuf_sadr = isp_cfg->dma_addr + isp_cfg->cbuf_bot + s_off; -} - int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) { struct dvbm_ctx *ctx; - struct rk_dvbm_regs *reg; if ((cmd < DVBM_ISP_CMD_BASE) || (cmd > DVBM_VEPU_CMD_BUTT)) { dvbm_err("%s input cmd invalid\n", __func__); @@ -458,28 +244,43 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } ctx = port_to_ctx(port); - reg = &ctx->regs; switch (cmd) { case DVBM_ISP_SET_CFG: { struct dvbm_isp_cfg_t *cfg = (struct dvbm_isp_cfg_t *)arg; + struct dvbm_addr_cfg *dvbm_adr; + u32 chan_id = cfg->chan_id; - memcpy(&ctx->isp_cfg, cfg, sizeof(struct dvbm_isp_cfg_t)); - rk_dvbm_setup_iobuf(ctx); + if (chan_id >= DVBM_CHANNEL_NUM) { + dvbm_err("%s cmd %d chan id %d is invalid\n", __func__, cmd, chan_id); + return -EINVAL; + } + + memcpy(&ctx->isp_cfg[chan_id], cfg, sizeof(struct dvbm_isp_cfg_t)); init_isp_infos(ctx); - rk_dvbm_update_next_adr(ctx); + + dvbm_adr = &ctx->dvbm_addr[chan_id]; + dvbm_adr->chan_id = chan_id; + dvbm_adr->ybuf_bot = cfg->dma_addr + cfg->ybuf_bot; + dvbm_adr->ybuf_top = cfg->dma_addr + cfg->ybuf_top; + dvbm_adr->ybuf_sadr = cfg->dma_addr + cfg->ybuf_bot; + dvbm_adr->cbuf_bot = cfg->dma_addr + cfg->cbuf_bot; + dvbm_adr->cbuf_top = cfg->dma_addr + cfg->cbuf_top; + dvbm_adr->cbuf_sadr = cfg->dma_addr + cfg->cbuf_bot; + dvbm2enc_callback(ctx, DVBM_ISP_SET_DVBM_CFG, cfg); } break; case DVBM_ISP_FRM_START: { + dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_FRM_STR, arg); rk_dvbm_update_isp_frm_info(ctx, 0); rk_dvbm_show_time(ctx); } break; case DVBM_ISP_FRM_END: { u32 line_cnt = ctx->isp_max_lcnt; + dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_FRM_END, arg); ctx->isp_frm_end = *(u32 *)arg; /* wrap frame_cnt 0 - 255 */ ctx->isp_frm_info.frame_cnt = (ctx->isp_frm_start + 1) % 256; - rk_dvbm_update_next_adr(ctx); rk_dvbm_update_isp_frm_info(ctx, line_cnt); ctx->isp_frm_start++; dvbm_debug("isp frame end[%d : %d]\n", ctx->isp_frm_start, ctx->isp_frm_end); @@ -504,38 +305,14 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } break; case DVBM_VEPU_GET_ADR: { struct dvbm_addr_cfg *dvbm_adr = (struct dvbm_addr_cfg *)arg; - struct rk_dvbm_base *addr_base = ®->addr_base; + u32 chan_id = dvbm_adr->chan_id; - dvbm_adr->ybuf_top = addr_base->ybuf_top; - dvbm_adr->ybuf_bot = addr_base->ybuf_bot; - dvbm_adr->cbuf_top = addr_base->cbuf_top; - dvbm_adr->cbuf_bot = addr_base->cbuf_bot; - dvbm_adr->cbuf_sadr = ctx->vepu_cfg.cbuf_sadr; - dvbm_adr->ybuf_sadr = ctx->vepu_cfg.ybuf_sadr; - dvbm_adr->overflow = ctx->isp_frm_info.line_cnt >= ctx->wrap_line; - dvbm_adr->frame_id = ctx->isp_frm_info.frame_cnt; - dvbm_adr->line_cnt = ctx->isp_frm_info.line_cnt; - } break; - case DVBM_VEPU_GET_FRAME_INFO: { - memcpy(arg, &ctx->isp_frm_info, sizeof(struct dvbm_isp_frm_info)); - } break; - case DVBM_VEPU_SET_RESYNC: { - reg->dvbm_cfg.auto_resyn = *(u32 *)arg; - dev_info(ctx->dev, "change resync %s\n", - reg->dvbm_cfg.auto_resyn ? "auto" : "soft"); - rk_dvbm_set_reg(ctx, DVBM_CFG, ((u32 *)®->dvbm_cfg)[0]); - } break; - case DVBM_VEPU_SET_CFG: { - struct dvbm_vepu_cfg *cfg = (struct dvbm_vepu_cfg *)arg; + if (chan_id >= DVBM_CHANNEL_NUM) { + dvbm_err("%s cmd %d chan id %d is invalid\n", __func__, cmd, chan_id); + return -EINVAL; + } - reg->dvbm_cfg.auto_resyn = cfg->auto_resyn; - reg->dvbm_cfg.ignore_vepu_cnct_ack = cfg->ignore_vepu_cnct_ack; - reg->dvbm_cfg.start_point_after_vepu_cnct = cfg->start_point_after_vepu_cnct; - - rk_dvbm_set_reg(ctx, DVBM_CFG, ((u32 *)®->dvbm_cfg)[0]); - } break; - case DVBM_VEPU_DUMP_REGS: { - rk_dvbm_dump_regs(ctx); + *dvbm_adr = ctx->dvbm_addr[chan_id]; } break; default: { } break; @@ -545,163 +322,27 @@ int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg) } EXPORT_SYMBOL(rk_dvbm_ctrl); -static void dvbm_check_irq(struct dvbm_ctx *ctx) -{ - u32 irq_st = ctx->irq_status; - u32 cur_st = ctx->dvbm_status; - - if (irq_st & ISP_CNCT) { - dvbm_debug_irq("%s isp connect success! st 0x%08x\n", - __func__, cur_st); - ctx->port_isp.linked = 1; - } - if (irq_st & ISP_DISCNCT) { - dvbm_debug_irq("%s isp disconnect success!\n", __func__); - ctx->port_isp.linked = 0; - } - if (irq_st & VEPU_CNCT) { - dvbm_debug_irq("%s vepu connect success! st 0x%08x\n", - __func__, cur_st); - ctx->port_vepu.linked = 1; - } - if (irq_st & VEPU_DISCNCT) { - dvbm_debug_irq("%s vepu disconnect success! st 0x%08x\n", __func__, cur_st); - ctx->port_vepu.linked = 0; - } - if (irq_st & BUF_OVERFLOW) { - dvbm_debug_irq("%s buf overflow st 0x%08x auto_resync %d ignore %d\n", - __func__, cur_st, ctx->regs.dvbm_cfg.auto_resyn, ctx->ignore_ovfl); - - if (!ctx->regs.dvbm_cfg.auto_resyn && !ctx->ignore_ovfl) - rk_dvbm_unlink(&ctx->port_vepu); - } - if (irq_st & (ISP_CNCT_TIMEOUT | VEPU_CNCT_TIMEOUT)) - rk_dvbm_dump_regs(ctx); -} - -static irqreturn_t rk_dvbm_irq(int irq, void *param) -{ - struct dvbm_ctx *ctx = param; - u32 irq_st = 0; - u32 cur_st = 0; - - if (ctx->reg_base) { - /* read irq st */ - irq_st = rk_dvbm_read_reg(ctx, DVBM_INT_ST); - cur_st = rk_dvbm_read_reg(ctx, DVBM_ST); - if (irq_st & BUF_OVERFLOW) { - dvbm_debug_dump("=== dvbm overflow! dump reg st: 0x%08x===\n", irq_st); - rk_dvbm_dump_regs(ctx); - dvbm2enc_callback(ctx, DVBM_VEPU_NOTIFY_DUMP, NULL); - dvbm_debug_dump("=== dvbm overflow! dump reg end===\n"); - } - /* clr irq */ - rk_dvbm_set_reg(ctx, DVBM_INT_CLR, irq_st); - rk_dvbm_set_reg(ctx, DVBM_INT_ST, 0); - } - ctx->irq_status = irq_st; - ctx->dvbm_status = cur_st; - - dvbm_debug_irq("%s irq status 0x%08x\n", __func__, irq_st); - - return IRQ_WAKE_THREAD; -} - -static irqreturn_t rk_dvbm_isr(int irq, void *param) -{ - struct dvbm_ctx *ctx = param; - - dvbm_check_irq(ctx); - - return IRQ_HANDLED; -} - static int rk_dvbm_probe(struct platform_device *pdev) { - int ret; struct dvbm_ctx *ctx = NULL; struct device *dev = &pdev->dev; - struct resource *res = NULL; dev_info(dev, "probe start\n"); ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; - dev_info(dev, "dvbm ctx %p\n", ctx); ctx->dev = dev; - - atomic_set(&ctx->isp_ref, 0); - atomic_set(&ctx->vepu_ref, 0); ctx->port_isp.dir = DVBM_ISP_PORT; ctx->port_vepu.dir = DVBM_VEPU_PORT; platform_set_drvdata(pdev, ctx); - pm_runtime_enable(dev); - - /* get irq */ - ctx->irq = platform_get_irq(pdev, 0); - if (ctx->irq < 0) { - dev_err(&pdev->dev, "no interrupt resource found\n"); - ret = -ENODEV; - goto failed; - } - /* get mem resource */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto failed; - } - - ctx->reg_base = devm_ioremap_resource(dev, res); - if (IS_ERR_OR_NULL(ctx->reg_base)) { - dev_err(dev, "ioremap failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - - ctx->clk = devm_clk_get(ctx->dev, "clk_core"); - if (IS_ERR_OR_NULL(ctx->clk)) { - dev_err(dev, "clk_get failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - ctx->rst = devm_reset_control_get(ctx->dev, "dvbm_rst"); - if (IS_ERR_OR_NULL(ctx->rst)) { - dev_err(dev, "clk_rst failed for resource %pR\n", res); - ret = -ENODEV; - goto failed; - } - if (!SOFT_DVBM) { - ret = pm_runtime_get_sync(dev); - if (ret) - dev_err(dev, "pm get failed!\n"); - ret = rk_dvbm_clk_on(ctx); - if (ret) - goto failed; - } g_ctx = ctx; - rk_dvbm_reg_init(ctx); - ctx->ignore_ovfl = 1; - ctx->dump_s = 0x80; - ctx->dump_e = 0xb8; - ret = devm_request_threaded_irq(dev, ctx->irq, - rk_dvbm_irq, rk_dvbm_isr, - IRQF_ONESHOT, dev_name(dev), ctx); - if (ret) { - dev_err(dev, "register interrupter failed\n"); - goto failed; - } + dev_info(dev, "probe success\n"); return 0; - -failed: - pm_runtime_disable(dev); - - return ret; } static int rk_dvbm_remove(struct platform_device *pdev) @@ -709,11 +350,6 @@ static int rk_dvbm_remove(struct platform_device *pdev) struct device *dev = &pdev->dev; dev_info(dev, "remove device\n"); - if (!SOFT_DVBM) { - rk_dvbm_clk_off(g_ctx); - pm_runtime_put(dev); - } - pm_runtime_disable(dev); return 0; } diff --git a/drivers/video/rockchip/dvbm/rockchip_dvbm.h b/drivers/video/rockchip/dvbm/rockchip_dvbm.h deleted file mode 100644 index 9df38b8cbd58..000000000000 --- a/drivers/video/rockchip/dvbm/rockchip_dvbm.h +++ /dev/null @@ -1,214 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (c) 2022 Rockchip Electronics Co., Ltd. - */ -#ifndef __ROCKCHIP_DVBM_H__ -#define __ROCKCHIP_DVBM_H__ - -#include -#include - -struct rk_dvbm_base { - /* 0x2c */ - u32 ybuf_bot; - /* 0x30 */ - u32 ybuf_top; - /* 0x34 */ - u32 ybuf_sadr; - /* 0x38 */ - u32 ybuf_lstd; - /* 0x3c */ - u32 ybuf_fstd; - /* 0x40 */ - u32 cbuf_bot; - /* 0x44 */ - u32 cbuf_top; - /* 0x48 */ - u32 cbuf_sadr; - /* 0x4c */ - u32 cbuf_lstd; - /* 0x50 */ - u32 cbuf_fstd; - /* 0x54 */ - u32 aful_thdy; - /* 0x58 */ - u32 aful_thdc; - /* 0x5c */ - u32 oful_thdy; - /* 0x60 */ - u32 oful_thdc; -}; - -struct rk_dvbm_regs { - /* 0x0 */ - u32 version; - - /* 0x4 */ - struct { - u32 isp_cnct : 1; - u32 reserved : 31; - } isp_cnct; - - /* 0x8 */ - struct { - u32 vepu_cnct : 1; - u32 reserved : 31; - } vepu_cnct; - - /* 0xc */ - struct { - u32 auto_resyn : 1; - u32 ignore_vepu_cnct_ack : 1; - /* - * 1’b0 : the current ISP frame - * 1’b1 : the next ISP frame - */ - u32 start_point_after_vepu_cnct : 1; - u32 reserved0 : 5; - /* only support yuv420sp 4'h0 */ - u32 fmt : 4; - u32 reserved1 : 20; - } dvbm_cfg; - - /* 0x10 */ - struct { - u32 wdg_isp_cnct_timeout : 22; - u32 reserved : 10; - } wdg_cfg0; - - /* 0x14 */ - struct { - u32 wdg_vepu_cnct_timeout : 22; - u32 reserved : 10; - } wdg_cfg1; - - /* 0x18 */ - struct { - u32 wdg_vepu_handshake_timeout : 22; - u32 reserved : 10; - } wdg_cfg2; - - /* 0x1c */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_en; - - /* 0x20 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_msk; - - /* 0x24 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_clr; - - /* 0x28 */ - struct { - u32 buf_ovfl : 1; - u32 resync_finish : 1; - u32 isp_cnct_timeout : 1; - u32 vepu_cnct_timeout : 1; - - u32 vepu_handshake_timeout : 1; - u32 isp_cnct : 1; - u32 isp_discnct : 1; - u32 vepu_cnct : 1; - - u32 vepu_discnct : 1; - u32 reserved : 23; - } int_st; - struct rk_dvbm_base addr_base; - /* 0x64 - 0x7c */ - u32 reserved[7]; - - /* 0x80 */ - struct { - u32 isp_connection : 1; - u32 vepu_connection : 1; - u32 resynchronization : 1; - u32 y_buf_ovfl : 1; - - u32 c_buf_ovfl : 1; - u32 reserved : 27; - } dvbm_st; - - /* 0x84 */ - u32 ovfl_st; -}; - -struct dvbm_ctx { - struct clk *clk; - struct device *dev; - void __iomem *reg_base; - struct rk_dvbm_regs regs; - struct reset_control *rst; - - u32 isp_connet; - u32 vepu_connet; - u32 buf_overflow; - u32 irq_status; - u32 dvbm_status; - int irq; - - /* vepu infos */ - struct dvbm_port port_vepu; - atomic_t vepu_ref; - atomic_t vepu_link; - struct dvbm_cb vepu_cb; - struct dvbm_addr_cfg vepu_cfg; - - /* isp infos */ - struct dvbm_port port_isp; - struct dvbm_cb isp_cb; - struct dvbm_isp_cfg_t isp_cfg; - struct dvbm_isp_frm_info isp_frm_info; - atomic_t isp_link; - atomic_t isp_ref; - u32 isp_max_lcnt; - u32 isp_frm_start; - u32 isp_frm_end; - ktime_t isp_frm_time; - u32 wrap_line; - - /* debug infos */ - u32 dump_s; - u32 dump_e; - u32 ignore_ovfl; - u32 loopcnt; -}; - -#endif diff --git a/drivers/video/rockchip/mpp/mpp_common.c b/drivers/video/rockchip/mpp/mpp_common.c index ab02cea09f17..80c263ac081e 100644 --- a/drivers/video/rockchip/mpp/mpp_common.c +++ b/drivers/video/rockchip/mpp/mpp_common.c @@ -2239,7 +2239,10 @@ int mpp_dev_probe(struct mpp_dev *mpp, if (IS_ERR(mpp->iommu_info)) { dev_err(dev, "failed to attach iommu\n"); mpp->iommu_info = NULL; + } else { + mpp->iommu_info->queue = mpp->queue; } + if (mpp->hw_ops->init) { ret = mpp->hw_ops->init(mpp); if (ret) diff --git a/drivers/video/rockchip/mpp/mpp_common.h b/drivers/video/rockchip/mpp/mpp_common.h index d60d69970f56..e88243e78617 100644 --- a/drivers/video/rockchip/mpp/mpp_common.h +++ b/drivers/video/rockchip/mpp/mpp_common.h @@ -507,6 +507,9 @@ struct mpp_taskqueue { u32 core_id_max; u32 core_count; unsigned long dev_active_flags; + + /* for devices which share iommu, record last attach device */ + struct mpp_iommu_info *last_iommu_info; }; struct mpp_reset_group { @@ -547,6 +550,9 @@ struct mpp_service { /* global timing record flag */ u32 timing_en; u32 load_interval; + + /* bit mask for iommu shared */ + u32 iommu_shared_mask; }; /* diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 9a3589314e0e..ff93d7f75e6c 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -17,6 +17,7 @@ #include #include #include +#include #ifdef CONFIG_ARM_DMA_USE_IOMMU #include @@ -451,9 +452,19 @@ int mpp_iommu_detach(struct mpp_iommu_info *info) int mpp_iommu_attach(struct mpp_iommu_info *info) { + struct mpp_iommu_info *last_info; + if (!info) return 0; + /* if device changed, detach last first */ + last_info = info->queue->last_iommu_info; + if (info->shared && last_info && last_info->shared + && (info->dev != last_info->dev)) { + iommu_detach_group(last_info->domain, last_info->group); + } + info->queue->last_iommu_info = info; + if (info->domain == iommu_get_domain_for_dev(info->dev)) return 0; @@ -561,6 +572,15 @@ mpp_iommu_probe(struct device *dev) info->irq = platform_get_irq(pdev, 0); info->got_irq = (info->irq < 0) ? false : true; + /* get shared flag, if true detach */ + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { + struct platform_driver *drv = to_platform_driver(dev->driver); + + info->shared = drv->driver_managed_dma; + if (info->shared) + iommu_detach_group(info->domain, info->group); + } + return info; err_put_group: @@ -578,6 +598,10 @@ int mpp_iommu_remove(struct mpp_iommu_info *info) if (!info) return 0; + /* if iommu shared, ensure current device's domain, then remove correctly */ + if (info->shared) + mpp_iommu_attach(info); + iommu_group_put(info->group); platform_device_put(info->pdev); diff --git a/drivers/video/rockchip/mpp/mpp_iommu.h b/drivers/video/rockchip/mpp/mpp_iommu.h index 265f276de281..bf51e0ee4de3 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.h +++ b/drivers/video/rockchip/mpp/mpp_iommu.h @@ -102,6 +102,9 @@ struct mpp_iommu_info { int irq; int got_irq; + /* flag for mark iommu whether shared */ + bool shared; + struct mpp_taskqueue *queue; }; struct mpp_dma_session * diff --git a/drivers/video/rockchip/mpp/mpp_service.c b/drivers/video/rockchip/mpp/mpp_service.c index 882002e20097..4ae409738685 100644 --- a/drivers/video/rockchip/mpp/mpp_service.c +++ b/drivers/video/rockchip/mpp/mpp_service.c @@ -100,6 +100,9 @@ static int mpp_add_driver(struct mpp_service *srv, &srv->grf_infos[type], grf_name); + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) + driver->driver_managed_dma = (srv->iommu_shared_mask & BIT(type)) ? true : false; + ret = platform_driver_register(driver); if (ret) return ret; @@ -444,6 +447,9 @@ static int mpp_service_probe(struct platform_device *pdev) } } + of_property_read_u32(np, "rockchip,iommu-shared-mask", + &srv->iommu_shared_mask); + ret = mpp_register_service(srv, MPP_SERVICE_NAME); if (ret) { dev_err(dev, "register %s device\n", MPP_SERVICE_NAME); diff --git a/drivers/video/rockchip/rga3/include/rga2_reg_info.h b/drivers/video/rockchip/rga3/include/rga2_reg_info.h index 4afac19b0a16..5571c6e40a28 100644 --- a/drivers/video/rockchip/rga3/include/rga2_reg_info.h +++ b/drivers/video/rockchip/rga3/include/rga2_reg_info.h @@ -132,6 +132,14 @@ #define m_RGA2_STATUS1_SW_RGA_STA (0x1 << 0) /*RGA_INT*/ +#define m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR (1 << 24) +#define m_RGA2_INT_FBCIN_DEC_ERROR_EN (1 << 23) +#define m_RGA2_INT_FBCIN_DEC_ERROR (1 << 22) +#define m_RGA2_INT_PREFETCH_TH_INTR (1 << 21) +#define m_RGA2_INT_PRE_TH_CLEAR (1 << 20) +#define m_RGA2_INT_SCL_ERROR_CLEAR (1 << 19) +#define m_RGA2_INT_SCL_ERROR_EN (1 << 18) +#define m_RGA2_INT_SCL_ERROR_INTR (1 << 17) #define m_RGA2_INT_LINE_WR_CLEAR (1 << 16) #define m_RGA2_INT_LINE_RD_CLEAR (1 << 15) #define m_RGA2_INT_LINE_WR_EN (1 << 14) @@ -153,17 +161,23 @@ #define m_RGA2_INT_ERROR_FLAG_MASK \ ( \ m_RGA2_INT_MMU_INT_FLAG | \ - m_RGA2_INT_ERROR_INT_FLAG \ + m_RGA2_INT_ERROR_INT_FLAG | \ + m_RGA2_INT_SCL_ERROR_INTR | \ + m_RGA2_INT_FBCIN_DEC_ERROR \ ) #define m_RGA2_INT_ERROR_CLEAR_MASK \ ( \ - m_RGA2_INT_MMU_INT_CLEAR | \ - m_RGA2_INT_ERROR_INT_CLEAR \ + m_RGA2_INT_MMU_INT_CLEAR | \ + m_RGA2_INT_ERROR_INT_CLEAR | \ + m_RGA2_INT_SCL_ERROR_CLEAR | \ + m_RGA2_INT_FBCIN_DEC_ERROR_CLEAR \ ) #define m_RGA2_INT_ERROR_ENABLE_MASK \ ( \ m_RGA2_INT_MMU_INT_EN | \ - m_RGA2_INT_ERROR_INT_EN \ + m_RGA2_INT_ERROR_INT_EN | \ + m_RGA2_INT_SCL_ERROR_EN | \ + m_RGA2_INT_FBCIN_DEC_ERROR_EN \ ) #define s_RGA2_INT_LINE_WR_CLEAR(x) ((x & 0x1) << 16) diff --git a/drivers/video/rockchip/rga3/include/rga_drv.h b/drivers/video/rockchip/rga3/include/rga_drv.h index e0c34bb4aa7e..334955e73b81 100644 --- a/drivers/video/rockchip/rga3/include/rga_drv.h +++ b/drivers/video/rockchip/rga3/include/rga_drv.h @@ -88,7 +88,7 @@ #define DRIVER_MAJOR_VERISON 1 #define DRIVER_MINOR_VERSION 3 -#define DRIVER_REVISION_VERSION 7 +#define DRIVER_REVISION_VERSION 8 #define DRIVER_PATCH_VERSION #define DRIVER_VERSION (STR(DRIVER_MAJOR_VERISON) "." STR(DRIVER_MINOR_VERSION) \ diff --git a/drivers/video/rockchip/rga3/rga2_reg_info.c b/drivers/video/rockchip/rga3/rga2_reg_info.c index 7a35594e7926..e0bddaaba2af 100644 --- a/drivers/video/rockchip/rga3/rga2_reg_info.c +++ b/drivers/video/rockchip/rga3/rga2_reg_info.c @@ -133,6 +133,22 @@ static void rga2_scale_down_bilinear_protect(u32 *param_fix, u32 *src_fix, *src_fix = final_steps + 1; } +static void rag2_scale_down_average_protect(u32 *param_fix, u32 param, + u32 src, u32 dst) +{ + /* division Loss */ + param = param + 1; + + /* + * Ensure that the (src - 1) drop point is to the left of the last + * point of the dst. + */ + while ((param * (src - 1)) > (dst << 16)) + param--; + + *param_fix = param; +} + static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) { u32 *bRGA_SRC_X_FACTOR; @@ -182,7 +198,8 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH)) | s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_WIDTH((src_fix - 1))); } else { - param_x = ((dw << 16) + (sw / 2)) / sw; + param_x = (dw << 16) / sw; + rag2_scale_down_average_protect(¶m_x, param_x, sw, dw); *bRGA_SRC_X_FACTOR |= ((param_x & 0xffff) << 0); } @@ -219,7 +236,8 @@ static void RGA2_reg_get_param(unsigned char *base, struct rga2_req *msg) ((*bRGA_SRC_ACT_INFO & (~m_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT)) | s_RGA2_SRC_ACT_INFO_SW_SRC_ACT_HEIGHT((src_fix - 1))); } else { - param_y = ((dh << 16) + (sh / 2)) / sh; + param_y = (dh << 16) / sh; + rag2_scale_down_average_protect(¶m_y, param_y, sh, dh); *bRGA_SRC_Y_FACTOR |= ((param_y & 0xffff) << 0); } @@ -3250,6 +3268,12 @@ static int rga2_isr_thread(struct rga_job *job, struct rga_scheduler_t *schedule } else if (job->intr_status & m_RGA2_INT_MMU_INT_FLAG) { rga_job_err(job, "mmu failed, please check size of the buffer or whether the buffer has been freed.\n"); job->ret = -EACCES; + } else if (job->intr_status & m_RGA2_INT_SCL_ERROR_INTR) { + rga_job_err(job, "scale failed, check scale config or formula.\n"); + job->ret = -EACCES; + } else if (job->intr_status & m_RGA2_INT_FBCIN_DEC_ERROR) { + rga_job_err(job, "FBC decode failed, please check if the source data is FBC data.\n"); + job->ret = -EACCES; } if (job->ret == 0) { diff --git a/include/linux/gpio_detection.h b/include/linux/gpio_detection.h deleted file mode 100644 index 57b2ff92bc50..000000000000 --- a/include/linux/gpio_detection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * include/linux/gpio_detection.h - * - * Platform data structure for GPIO detection driver - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ -#ifndef __GPIO_DETECTION_H -#define __GPIO_DETECTION_H - -#define GPIO_EVENT 1 - -/* - * gpio event - * @val: 0 event active, 1 event over - * @name: event name - */ - -struct gpio_event { - int val; - const char *name; -}; - -#if IS_ENABLED(CONFIG_GPIO_DET) - -int gpio_det_register_notifier(struct notifier_block *nb); -int gpio_det_unregister_notifier(struct notifier_block *nb); -int gpio_det_notifier_call_chain(unsigned long val, void *v); - -#else - -static inline int gpio_det_register_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_unregister_notifier(struct notifier_block *nb) -{ - return -EINVAL; -}; - -static inline int gpio_det_notifier_call_chain(unsigned long val, void *v) -{ - return -EINVAL; -}; - -#endif - -#endif diff --git a/include/linux/phy/phy-dp.h b/include/linux/phy/phy-dp.h index 18cad23642cd..9cce5766bc0b 100644 --- a/include/linux/phy/phy-dp.h +++ b/include/linux/phy/phy-dp.h @@ -8,6 +8,9 @@ #include +#define PHY_SUBMODE_DP 0 +#define PHY_SUBMODE_EDP 1 + /** * struct phy_configure_opts_dp - DisplayPort PHY configuration set * diff --git a/include/soc/rockchip/rockchip_dvbm.h b/include/soc/rockchip/rockchip_dvbm.h index dd69047a26d4..07b000f48212 100644 --- a/include/soc/rockchip/rockchip_dvbm.h +++ b/include/soc/rockchip/rockchip_dvbm.h @@ -24,11 +24,7 @@ enum dvbm_cmd { DVBM_ISP_CMD_BUTT, DVBM_VEPU_CMD_BASE = 0x10, - DVBM_VEPU_SET_RESYNC, - DVBM_VEPU_SET_CFG, DVBM_VEPU_GET_ADR, - DVBM_VEPU_GET_FRAME_INFO, - DVBM_VEPU_DUMP_REGS, DVBM_VEPU_CMD_BUTT, }; @@ -42,6 +38,9 @@ enum isp_frame_status { enum dvbm_cb_event { DVBM_ISP_EVENT_BASE = 0, + DVBM_ISP_REQ_CONNECT, + DVBM_ISP_REQ_DISCONNECT, + DVBM_ISP_SET_DVBM_CFG, DVBM_ISP_EVENT_BUTT, DVBM_VEPU_EVENT_BASE = 0x10, @@ -60,9 +59,7 @@ struct dvbm_port { }; struct dvbm_isp_cfg_t { - u32 fmt; - u32 timeout; - + u32 chan_id; struct dmabuf *buf; dma_addr_t dma_addr; u32 ybuf_top; @@ -75,12 +72,6 @@ struct dvbm_isp_cfg_t { u32 cbuf_fstd; }; -struct dvbm_isp_frm_cfg { - s32 frm_idx; - u32 ybuf_start; - u32 cbuf_start; -}; - struct dvbm_isp_frm_info { u32 frame_cnt; u32 line_cnt; @@ -96,14 +87,7 @@ struct dvbm_addr_cfg { u32 cbuf_bot; u32 cbuf_sadr; u32 frame_id; - u32 line_cnt; - u32 overflow; -}; - -struct dvbm_vepu_cfg { - u32 auto_resyn; - u32 ignore_vepu_cnct_ack; - u32 start_point_after_vepu_cnct; + u32 chan_id; }; typedef int (*dvbm_callback)(void *ctx, enum dvbm_cb_event event, void *arg); @@ -119,8 +103,8 @@ struct dvbm_cb { struct dvbm_port *rk_dvbm_get_port(struct platform_device *pdev, enum dvbm_port_dir dir); int rk_dvbm_put(struct dvbm_port *port); -int rk_dvbm_link(struct dvbm_port *port); -int rk_dvbm_unlink(struct dvbm_port *port); +int rk_dvbm_link(struct dvbm_port *port, int id); +int rk_dvbm_unlink(struct dvbm_port *port, int id); int rk_dvbm_set_cb(struct dvbm_port *port, struct dvbm_cb *cb); int rk_dvbm_ctrl(struct dvbm_port *port, enum dvbm_cmd cmd, void *arg); @@ -137,11 +121,11 @@ static inline int rk_dvbm_put(struct dvbm_port *port) return -ENODEV; } -static inline int rk_dvbm_link(struct dvbm_port *port) +static inline int rk_dvbm_link(struct dvbm_port *port, int id) { return -ENODEV; } -static inline int rk_dvbm_unlink(struct dvbm_port *port) +static inline int rk_dvbm_unlink(struct dvbm_port *port, int id) { return -ENODEV; }