diff --git a/arch/arm/boot/dts/rk3506g-demo-display-control.dts b/arch/arm/boot/dts/rk3506g-demo-display-control.dts index ec9438ffc3f8..1688896903ce 100644 --- a/arch/arm/boot/dts/rk3506g-demo-display-control.dts +++ b/arch/arm/boot/dts/rk3506g-demo-display-control.dts @@ -591,6 +591,7 @@ &sai1 { status = "okay"; + rockchip,mclk-no-set; pinctrl-names = "default"; pinctrl-0 = <&rm_io9_sai1_sclk &rm_io10_sai1_lrck @@ -600,6 +601,7 @@ &sai4 { status = "okay"; + rockchip,mclk-no-set; }; &saradc { diff --git a/arch/arm/configs/rv1126-tb.config b/arch/arm/configs/rv1126-tb.config index 729df48a8cb0..49ce46ec1b4e 100644 --- a/arch/arm/configs/rv1126-tb.config +++ b/arch/arm/configs/rv1126-tb.config @@ -54,7 +54,6 @@ CONFIG_USB=m # CONFIG_USB_CONFIGFS_RNDIS is not set CONFIG_USB_DWC3=m CONFIG_USB_DWC3_OF_SIMPLE=m -CONFIG_USB_DWC3_ROCKCHIP_INNO=m CONFIG_USB_EHCI_HCD=m CONFIG_USB_EHCI_HCD_PLATFORM=m CONFIG_USB_HID=m diff --git a/arch/arm64/boot/dts/rockchip/rk3576.dtsi b/arch/arm64/boot/dts/rockchip/rk3576.dtsi index 9dd309efd801..e25899a39eff 100644 --- a/arch/arm64/boot/dts/rockchip/rk3576.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3576.dtsi @@ -3400,6 +3400,12 @@ "dclk_src_vp0", "dclk_src_vp1", "dclk_src_vp2"; + resets = <&cru SRST_D_VP0>, + <&cru SRST_D_VP1>, + <&cru SRST_D_VP2>; + reset-names = "dclk_vp0", + "dclk_vp1", + "dclk_vp2"; rockchip,aclk-normal-mode-rates = <500000000>; rockchip,aclk-reset-mode-rates = <594000000>; rockchip,aclk-advanced-mode-rates = <702000000>; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 36ba988e288a..8dbe50439f84 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -3496,6 +3496,8 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge, extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false); handle_plugged_change(hdmi, false); + if (hdmi->plat_data->crtc_pre_disable) + hdmi->plat_data->crtc_pre_disable(data, bridge->encoder->crtc); mutex_lock(&hdmi->mutex); if (hdmi->dclk_en) { @@ -3570,6 +3572,9 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge, if (link_cfg && link_cfg->frl_mode) queue_work(hdmi->workqueue, &hdmi->flt_work); + if (hdmi->plat_data->crtc_post_enable) + hdmi->plat_data->crtc_post_enable(data, bridge->encoder->crtc); + dw_hdmi_qp_init_audio_infoframe(hdmi); dw_hdmi_qp_audio_enable(hdmi); hdmi_clk_regenerator_update_pixel_clock(hdmi); diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 232d6a60e406..e05b61cea886 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -3200,6 +3200,46 @@ static void dw_hdmi_rockchip_get_mode_color_caps(struct drm_connector *connector hdmi->mode_color_caps, &connector->base, property); } +static void dw_hdmi_rockchip_crtc_post_enable(void *data, struct drm_crtc *crtc) +{ + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + int output_if; + + switch (hdmi->id) { + case 0: + output_if = VOP_OUTPUT_IF_HDMI0; + break; + case 1: + output_if = VOP_OUTPUT_IF_HDMI1; + break; + default: + dev_err(hdmi->dev, "invalid id:%d\n", hdmi->id); + return; + } + + rockchip_drm_crtc_output_post_enable(crtc, output_if); +} + +static void dw_hdmi_rockchip_crtc_pre_disable(void *data, struct drm_crtc *crtc) +{ + struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; + int output_if; + + switch (hdmi->id) { + case 0: + output_if = VOP_OUTPUT_IF_HDMI0; + break; + case 1: + output_if = VOP_OUTPUT_IF_HDMI1; + break; + default: + dev_err(hdmi->dev, "invalid id:%d\n", hdmi->id); + return; + } + + rockchip_drm_crtc_output_pre_disable(crtc, output_if); +} + static const struct drm_prop_enum_list color_depth_enum_list[] = { { 0, "Automatic" }, /* Prefer highest color depth */ { 8, "24bit" }, @@ -4433,6 +4473,10 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, dw_hdmi_rockchip_force_frl_rate; plat_data->get_mode_color_caps = dw_hdmi_rockchip_get_mode_color_caps; + plat_data->crtc_pre_disable = + dw_hdmi_rockchip_crtc_pre_disable; + plat_data->crtc_post_enable = + dw_hdmi_rockchip_crtc_post_enable; plat_data->property_ops = &dw_hdmi_rockchip_property_ops; secondary = rockchip_hdmi_find_by_id(dev->driver, !hdmi->id); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 050e9864a388..22ae57c407c3 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -1070,6 +1070,7 @@ static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list) static inline void vop2_cfg_done(struct drm_crtc *crtc); static void vop2_wait_for_fs_by_done_bit_status(struct vop2_video_port *vp); +static int vop2_clk_reset(struct reset_control *rstc); static inline struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) { @@ -1267,6 +1268,9 @@ static void vop2_crtc_output_post_enable(struct drm_crtc *crtc, int intf) vop2_wait_for_fs_by_done_bit_status(vp); } + if (!vp->loader_protect) + vop2_clk_reset(vp->dclk_rst); + drm_info(vop2, "vop enable intf:%x\n", intf); } @@ -10303,8 +10307,6 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_sta vop3_mcu_mode_setup(crtc); } - if (!vp->loader_protect) - vop2_clk_reset(vp->dclk_rst); if (vcstate->dsc_enable) rk3588_vop2_dsc_cfg_done(crtc); drm_crtc_vblank_on(crtc); diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index 7f1a64f798c7..dfcefbfe25df 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -6494,6 +6494,7 @@ void rkcif_do_stop_stream(struct rkcif_stream *stream, kfifo_free(&stream->dcg_kfifo); } + stream->crop_mask = 0; } if (mode == RKCIF_STREAM_MODE_CAPTURE) { tasklet_disable(&stream->vb_done_tasklet); @@ -11135,6 +11136,10 @@ static void rkcif_line_wake_up_rdbk(struct rkcif_stream *stream, int mipi_id) stream->cur_stream_mode |= RKCIF_STREAM_MODE_TOISP; stream->cifdev->wait_line = 0; stream->is_line_wake_up = false; + v4l2_dbg(3, rkcif_debug, &stream->cifdev->v4l2_dev, + "stream[%d] frame_idx %d, last_rx_buf_idx %d cur dma buf %x, change to online\n", + stream->id, stream->frame_idx, stream->last_rx_buf_idx, + (u32)active_buf->dummy.dma_addr); if (stream->cifdev->hdr.hdr_mode == NO_HDR || (priv->hdr_cfg.hdr_mode == HDR_X2 && stream->id == 1) || (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2)) { @@ -13070,7 +13075,7 @@ static void rkcif_toisp_check_stop_status(struct sditf_priv *priv, (priv->hdr_cfg.hdr_mode == HDR_X3 && stream->id == 2))) sditf_disable_immediately(priv); cur_time = rkcif_time_get_ns(stream->cifdev); - stream->readout.readout_time = cur_time - stream->readout.fs_timestamp; + stream->readout.total_time = cur_time - stream->readout.fs_timestamp; stream->readout.fs_timestamp = cur_time; stream->buf_wake_up_cnt++; if (stream->frame_idx % 2) @@ -13499,8 +13504,6 @@ static void rkcif_sensor_quick_streaming_cb(void *data) RKMODULE_SET_QUICK_STREAM, &on); } -extern void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); - static int rkcif_terminal_sensor_set_stream(struct rkcif_device *cif_dev, int on) { struct rkcif_pipeline *p = &cif_dev->pipe; @@ -14466,7 +14469,10 @@ void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev) } else { spin_lock_irqsave(&stream->fps_lock, flags); stream->readout.fs_timestamp = rkcif_time_get_ns(cif_dev); - stream->frame_idx++; + if (cif_dev->hdr.hdr_mode == HDR_X2 || cif_dev->hdr.hdr_mode == HDR_X3) + stream->frame_idx = cif_dev->stream[0].frame_idx; + else + stream->frame_idx++; if (cif_dev->channels[0].capture_info.mode == RKMODULE_MULTI_CH_TO_MULTI_ISP && cif_dev->sditf[stream->id]) sditf_event_inc_sof(cif_dev->sditf[stream->id]); diff --git a/drivers/media/platform/rockchip/cif/dev.c b/drivers/media/platform/rockchip/cif/dev.c index 70ee9a531acc..319d7527cc17 100644 --- a/drivers/media/platform/rockchip/cif/dev.c +++ b/drivers/media/platform/rockchip/cif/dev.c @@ -2474,7 +2474,7 @@ static void rkcif_init_reset_monitor(struct rkcif_device *dev) INIT_WORK(&dev->reset_work.work, rkcif_reset_work); } -void rkcif_set_sensor_stream(struct work_struct *work) +static void rkcif_set_sensor_stream(struct work_struct *work) { struct rkcif_sensor_work *sensor_work = container_of(work, struct rkcif_sensor_work, diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 8454e21e95e5..baf1582290f8 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -1173,4 +1173,6 @@ void rkcif_reinit_right_half_config(struct rkcif_stream *stream); void rkcif_modify_line_int(struct rkcif_stream *stream, bool en); void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq); + +void rkcif_set_sensor_streamon_in_sync_mode(struct rkcif_device *cif_dev); #endif diff --git a/drivers/media/platform/rockchip/cif/procfs.c b/drivers/media/platform/rockchip/cif/procfs.c index a8022ff7b9cf..badee96a50a7 100644 --- a/drivers/media/platform/rockchip/cif/procfs.c +++ b/drivers/media/platform/rockchip/cif/procfs.c @@ -571,8 +571,11 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) timestamp0 = stream->fps_stats.frm0_timestamp; timestamp1 = stream->fps_stats.frm1_timestamp; spin_unlock_irqrestore(&stream->fps_lock, flags); - fps = timestamp0 > timestamp1 ? - timestamp0 - timestamp1 : timestamp1 - timestamp0; + if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + fps = dev->stream[0].readout.total_time; + else + fps = timestamp0 > timestamp1 ? + timestamp0 - timestamp1 : timestamp1 - timestamp0; fps = div_u64(fps, 1000000); seq_puts(f, "Output Info:\n"); @@ -588,10 +591,16 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f) if (dev->hdr.hdr_mode == NO_HDR || dev->hdr.hdr_mode == HDR_COMPR) { time_val = div_u64(stream->readout.readout_time, 1000000); - seq_printf(f, "\treadout:%u ms\n", time_val); + if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + seq_puts(f, "\tsingle readout:N/A\n"); + else + seq_printf(f, "\tsingle readout:%u ms\n", time_val); } else { time_val = div_u64(stream->readout.readout_time, 1000000); - seq_printf(f, "\tsingle readout:%u ms\n", time_val); + if (dev->sditf[0] && dev->sditf[0]->mode.rdbk_mode < RKISP_VICAP_RDBK_AIQ) + seq_puts(f, "\tsingle readout:N/A\n"); + else + seq_printf(f, "\tsingle readout:%u ms\n", time_val); time_val = div_u64(stream->readout.total_time, 1000000); seq_printf(f, "\ttotal readout:%u ms\n", time_val); diff --git a/drivers/media/platform/rockchip/cif/subdev-itf.c b/drivers/media/platform/rockchip/cif/subdev-itf.c index ce0378e60105..df8d7ca79cfc 100644 --- a/drivers/media/platform/rockchip/cif/subdev-itf.c +++ b/drivers/media/platform/rockchip/cif/subdev-itf.c @@ -1298,8 +1298,8 @@ static int sditf_s_rx_buffer(struct v4l2_subdev *sd, } rx_buf = to_cif_rx_buf(dbufs); - v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "buf back to vicap 0x%x\n", - (u32)rx_buf->dummy.dma_addr); + v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev, "type %d buf back to vicap 0x%x, is_switch %d\n", + dbufs->type, (u32)rx_buf->dummy.dma_addr, dbufs->is_switch); spin_lock_irqsave(&stream->vbq_lock, flags); stream->last_rx_buf_idx = dbufs->sequence + 1; atomic_inc(&stream->buf_cnt); diff --git a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c index 0c7ad151973e..e644a1a0367e 100644 --- a/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c +++ b/drivers/phy/rockchip/phy-rockchip-csi2-dphy-hw.c @@ -659,12 +659,17 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1); if (hw->drv_data->chip_id < CHIP_ID_RK3588) { write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); - if (is_cif) + if (is_cif) { write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_0_1); - else + write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_2_3); + } else { write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, GRF_CSI2PHY_SEL_SPLIT_0_1); + write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_2_3); + } } else if (hw->drv_data->chip_id == CHIP_ID_RK3588) { write_sys_grf_reg(hw, GRF_DPHY_CSIHOST2_SEL, 0x0); write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); @@ -685,12 +690,17 @@ static void csi2_dphy_config_dual_mode(struct csi2_dphy *dphy, write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE1_EN, 0x1); if (hw->drv_data->chip_id < CHIP_ID_RK3588) { write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); - if (is_cif) + if (is_cif) { write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_2_3); - else + GRF_CSI2PHY_SEL_SPLIT_2_3); write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, - GRF_CSI2PHY_SEL_SPLIT_2_3); + GRF_CSI2PHY_SEL_SPLIT_0_1); + } else { + write_grf_reg(hw, GRF_DPHY_ISP_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_2_3); + write_grf_reg(hw, GRF_DPHY_CIF_CSI2PHY_SEL, + GRF_CSI2PHY_SEL_SPLIT_0_1); + } } else if (hw->drv_data->chip_id == CHIP_ID_RK3588) { write_sys_grf_reg(hw, GRF_DPHY_CSIHOST3_SEL, 0x1); write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val); diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 506a42cff11d..864fef540a39 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -118,15 +118,6 @@ config USB_DWC3_OF_SIMPLE Currently supports Xilinx and Qualcomm DWC USB3 IP. Say 'Y' or 'M' if you have one such device. -config USB_DWC3_ROCKCHIP_INNO - bool "Rockchip Platforms with INNO PHY" - depends on OF && COMMON_CLK && (ARCH_ROCKCHIP || COMPILE_TEST) - default USB_DWC3 && PHY_ROCKCHIP_INNO_USB3 && NO_GKI - help - Support of USB2/3 functionality in Rockchip platforms - with INNO USB 3.0 PHY IP inside. - say 'Y' or 'M' if you have one such device. - config USB_DWC3_ST tristate "STMicroelectronics Platforms" depends on (ARCH_STI || COMPILE_TEST) && OF diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index 5dccf31b1b5b..9f66bd82b639 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -50,7 +50,6 @@ obj-$(CONFIG_USB_DWC3_HAPS) += dwc3-haps.o obj-$(CONFIG_USB_DWC3_KEYSTONE) += dwc3-keystone.o obj-$(CONFIG_USB_DWC3_MESON_G12A) += dwc3-meson-g12a.o obj-$(CONFIG_USB_DWC3_OF_SIMPLE) += dwc3-of-simple.o -obj-$(CONFIG_USB_DWC3_ROCKCHIP_INNO) += dwc3-rockchip-inno.o obj-$(CONFIG_USB_DWC3_ST) += dwc3-st.o obj-$(CONFIG_USB_DWC3_QCOM) += dwc3-qcom.o obj-$(CONFIG_USB_DWC3_IMX8MP) += dwc3-imx8mp.o diff --git a/drivers/usb/dwc3/dwc3-rockchip-inno.c b/drivers/usb/dwc3/dwc3-rockchip-inno.c deleted file mode 100644 index 753cf58f68d6..000000000000 --- a/drivers/usb/dwc3/dwc3-rockchip-inno.c +++ /dev/null @@ -1,282 +0,0 @@ -/** - * dwc3-rockchip-inno.c - Rockchip DWC3 Specific Glue layer with INNO PHY - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * - * Authors: William Wu - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * 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 -#include -#include -#include -#include - -#include "core.h" - -#define XHCI_TSTCTRL_MASK (0xf << 28) -struct dwc3_rockchip { - struct device *dev; - struct clk **clks; - int num_clocks; - struct dwc3 *dwc; - struct usb_phy *phy; - struct notifier_block u3phy_nb; - struct work_struct u3_work; - struct mutex lock; -}; - -static int u3phy_disconnect_det_notifier(struct notifier_block *nb, - unsigned long event, void *p) -{ - struct dwc3_rockchip *rockchip = - container_of(nb, struct dwc3_rockchip, u3phy_nb); - - schedule_work(&rockchip->u3_work); - - return NOTIFY_DONE; -} - -static void u3phy_disconnect_det_work(struct work_struct *work) -{ - struct dwc3_rockchip *rockchip = - container_of(work, struct dwc3_rockchip, u3_work); - struct usb_hcd *hcd = dev_get_drvdata(&rockchip->dwc->xhci->dev); - u32 count = 0; - - mutex_lock(&rockchip->lock); - - if (hcd->state != HC_STATE_HALT) - dwc3_host_exit(rockchip->dwc); - - if (rockchip->phy) - usb_phy_shutdown(rockchip->phy); - - while (hcd->state != HC_STATE_HALT) { - if (++count > 1000) { - dev_err(rockchip->dev, - "wait for HCD remove 1s timeout!\n"); - break; - } - usleep_range(1000, 1100); - } - - if (hcd->state == HC_STATE_HALT) - dwc3_host_init(rockchip->dwc); - - if (rockchip->phy) - usb_phy_init(rockchip->phy); - - mutex_unlock(&rockchip->lock); -} - -static int dwc3_rockchip_probe(struct platform_device *pdev) -{ - struct dwc3_rockchip *rockchip; - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node, *child; - struct platform_device *child_pdev; - - unsigned int count; - int ret; - int i; - - rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); - if (!rockchip) - return -ENOMEM; - - child = of_get_child_by_name(np, "dwc3"); - if (!child) { - dev_err(dev, "failed to find dwc3 core node\n"); - return -ENODEV; - } - - count = of_clk_get_parent_count(np); - if (!count) - return -ENOENT; - - rockchip->num_clocks = count; - - rockchip->clks = devm_kcalloc(dev, rockchip->num_clocks, - sizeof(struct clk *), GFP_KERNEL); - if (!rockchip->clks) - return -ENOMEM; - - platform_set_drvdata(pdev, rockchip); - rockchip->dev = dev; - - for (i = 0; i < rockchip->num_clocks; i++) { - struct clk *clk; - - clk = of_clk_get(np, i); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto err0; - } - - ret = clk_prepare_enable(clk); - if (ret < 0) { - clk_put(clk); - goto err0; - } - - rockchip->clks[i] = clk; - } - - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - dev_err(dev, "get_sync failed with err %d\n", ret); - goto err1; - } - - ret = of_platform_populate(np, NULL, NULL, dev); - if (ret) - goto err1; - - child_pdev = of_find_device_by_node(child); - if (!child_pdev) { - dev_err(dev, "failed to find dwc3 core device\n"); - ret = -ENODEV; - goto err2; - } - - rockchip->dwc = platform_get_drvdata(child_pdev); - if (!rockchip->dwc || !rockchip->dwc->xhci) { - dev_dbg(dev, "failed to get drvdata dwc3\n"); - ret = -EPROBE_DEFER; - goto err2; - } - - mutex_init(&rockchip->lock); - - rockchip->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); - if (rockchip->phy) { - INIT_WORK(&rockchip->u3_work, u3phy_disconnect_det_work); - rockchip->u3phy_nb.notifier_call = - u3phy_disconnect_det_notifier; - usb_register_notifier(rockchip->phy, &rockchip->u3phy_nb); - } - - return 0; - -err2: - of_platform_depopulate(dev); -err1: - pm_runtime_put_sync(dev); - pm_runtime_disable(dev); -err0: - for (i = 0; i < rockchip->num_clocks && rockchip->clks[i]; i++) { - if (!pm_runtime_status_suspended(dev)) - clk_disable(rockchip->clks[i]); - clk_unprepare(rockchip->clks[i]); - clk_put(rockchip->clks[i]); - } - - return ret; -} - -static int dwc3_rockchip_remove(struct platform_device *pdev) -{ - struct dwc3_rockchip *rockchip = platform_get_drvdata(pdev); - struct device *dev = &pdev->dev; - int i; - - of_platform_depopulate(dev); - - pm_runtime_put_sync(dev); - pm_runtime_disable(dev); - - for (i = 0; i < rockchip->num_clocks; i++) { - if (!pm_runtime_status_suspended(dev)) - clk_disable(rockchip->clks[i]); - clk_unprepare(rockchip->clks[i]); - clk_put(rockchip->clks[i]); - } - - return 0; -} - -#ifdef CONFIG_PM -static int dwc3_rockchip_runtime_suspend(struct device *dev) -{ - struct dwc3_rockchip *rockchip = dev_get_drvdata(dev); - int i; - - for (i = 0; i < rockchip->num_clocks; i++) - clk_disable(rockchip->clks[i]); - - return 0; -} - -static int dwc3_rockchip_runtime_resume(struct device *dev) -{ - struct dwc3_rockchip *rockchip = dev_get_drvdata(dev); - int ret; - int i; - - for (i = 0; i < rockchip->num_clocks; i++) { - ret = clk_enable(rockchip->clks[i]); - if (ret < 0) { - while (--i >= 0) - clk_disable(rockchip->clks[i]); - return ret; - } - } - - return 0; -} - -static const struct dev_pm_ops dwc3_rockchip_dev_pm_ops = { - SET_RUNTIME_PM_OPS(dwc3_rockchip_runtime_suspend, - dwc3_rockchip_runtime_resume, NULL) -}; - -#define DEV_PM_OPS (&dwc3_rockchip_dev_pm_ops) -#else -#define DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - -static const struct of_device_id rockchip_dwc3_match[] = { - { .compatible = "rockchip,rk3328-dwc3" }, - { /* Sentinel */ } -}; -MODULE_DEVICE_TABLE(of, rockchip_dwc3_match); - -static struct platform_driver dwc3_rockchip_driver = { - .probe = dwc3_rockchip_probe, - .remove = dwc3_rockchip_remove, - .driver = { - .name = "rockchip-inno-dwc3", - .pm = DEV_PM_OPS, - .of_match_table = rockchip_dwc3_match, - }, -}; - -module_platform_driver(dwc3_rockchip_driver); - -MODULE_ALIAS("platform:rockchip-inno-dwc3"); -MODULE_AUTHOR("William Wu "); -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("DesignWare USB3 rockchip-inno Glue Layer"); diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index d02952ceafeb..9580f6e43d3c 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -284,6 +284,8 @@ struct dw_hdmi_plat_data { void (*force_frl_rate)(void *data, u8 rate); void (*get_mode_color_caps)(struct drm_connector *connector, struct drm_display_info *info, void *data); + void (*crtc_pre_disable)(void *data, struct drm_crtc *crtc); + void (*crtc_post_enable)(void *data, struct drm_crtc *crtc); /* Vendor Property support */ const struct dw_hdmi_property_ops *property_ops; diff --git a/sound/soc/codecs/rk730.c b/sound/soc/codecs/rk730.c index 38b941962a35..a3a8f2a29e96 100644 --- a/sound/soc/codecs/rk730.c +++ b/sound/soc/codecs/rk730.c @@ -55,6 +55,7 @@ struct rk730_priv { struct clk *mclk; unsigned int sysclk; atomic_t mix_mode; + bool fixed_mclk_fs; }; /* ADC Digital Volume */ @@ -666,6 +667,16 @@ static const struct _coeff_div coeff_div[] = { {8192000, 32000, 0xe, 0x3, 0x0}, {8192000, 64000, 0xe, 0x3, 0x0}, {8192000, 128000, 0xe, 0x3, 0x0}, + + /* uncommon sample rate groups */ + {12288000, 11025, 0x1, 0x1, 0x0}, + {12288000, 22050, 0x1, 0x1, 0x0}, + {12000000, 11025, 0x4, 0x1, 0x0}, + {12000000, 22050, 0x4, 0x1, 0x0}, + {24000000, 11025, 0xa, 0x1, 0x0}, + {24000000, 22050, 0xa, 0x1, 0x0}, + {11289600, 11025, 0xd, 0x1, 0x0}, + {11289600, 22050, 0xd, 0x1, 0x0}, }; static inline int get_coeff(int mclk, int rate) @@ -679,16 +690,49 @@ static inline int get_coeff(int mclk, int rate) return -EINVAL; } +struct _coeff_clk { + int mclk; + int rate; +}; + +/* codec selects the required mclk and sets it by itself */ +static const struct _coeff_clk coeff_clk[] = { + /* mclks */ + {12288000, 48000}, + {12288000, 96000}, + {12288000, 192000}, + {11289600, 44100}, + {11289600, 88200}, + {11289600, 176000}, + {8192000, 8000}, + {8192000, 16000}, + {8192000, 32000}, + {8192000, 64000}, + {8192000, 128000}, + /* uncommon sample rate groups */ + {11289600, 11025}, + {11289600, 22050}, +}; + +static inline int get_coeff_clk(int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(coeff_clk); i++) { + if (coeff_clk[i].rate == rate) + return coeff_clk[i].mclk; + } + return -EINVAL; +} + static unsigned int samplerate_to_bit(unsigned int samplerate) { switch (samplerate) { case 8000: case 11025: - case 12000: return 0; case 16000: case 22050: - case 24000: return 1; case 32000: case 44100: @@ -716,6 +760,24 @@ static int rk730_dai_hw_params(struct snd_pcm_substream *substream, unsigned int rate; int coeff; + if (!rk730->fixed_mclk_fs) { + rk730->sysclk = get_coeff_clk(params_rate(params)); + if ((int)rk730->sysclk < 0) { + dev_err(component->dev, + "Unable to lookup coeff clk with sample rate %dHz\n", + params_rate(params)); + return -EINVAL; + } + dev_info(component->dev, "%s: Lookup mclk:%d for rate:%d\n", + __func__, rk730->sysclk, params_rate(params)); + + if (clk_set_rate(rk730->mclk, rk730->sysclk) < 0) { + dev_err(component->dev, + "Unable to set mclk %dHz\n", rk730->sysclk); + return -EINVAL; + } + } + coeff = get_coeff(rk730->sysclk, params_rate(params)); if (coeff < 0) coeff = get_coeff(rk730->sysclk / 2, params_rate(params)); @@ -1131,6 +1193,9 @@ static int rk730_i2c_probe(struct i2c_client *i2c, if (IS_ERR(rk730->mclk)) return PTR_ERR(rk730->mclk); + rk730->fixed_mclk_fs = + device_property_read_bool(&i2c->dev, "rockchip,mclk-fs-fixed"); + i2c_set_clientdata(i2c, rk730); ret = devm_snd_soc_register_component(&i2c->dev, diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c index 077a66e8c761..c1d5d23de49d 100644 --- a/sound/soc/rockchip/rockchip_sai.c +++ b/sound/soc/rockchip/rockchip_sai.c @@ -75,6 +75,7 @@ struct rk_sai_dev { bool is_clk_auto; bool is_mclk_calibrate; bool is_tx_auto_gate; /* auto gate clk when TX FIFO empty */ + bool no_set_mclk; }; static const struct sai_of_quirks { @@ -630,7 +631,7 @@ static int rockchip_sai_hw_params(struct snd_pcm_substream *substream, if (sai->is_master_mode) { bclk_rate = sai->fw_ratio * slot_width * ch_per_lane * params_rate(params); - if (sai->is_clk_auto) + if (sai->is_clk_auto && !sai->no_set_mclk) clk_set_rate(sai->mclk, bclk_rate); mclk_rate = clk_get_rate(sai->mclk); @@ -921,9 +922,11 @@ static int rockchip_sai_set_sysclk(struct snd_soc_dai *dai, int clk_id, return ret; } - ret = clk_set_rate(sai->mclk, freq); - if (ret) - dev_err(sai->dev, "Failed to set mclk %d\n", ret); + if (!sai->no_set_mclk) { + ret = clk_set_rate(sai->mclk, freq); + if (ret) + dev_err(sai->dev, "Failed to set mclk %d\n", ret); + } return ret; } @@ -1974,6 +1977,9 @@ static int rockchip_sai_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Have mclk compensation feature\n"); } + sai->no_set_mclk = + device_property_read_bool(&pdev->dev, "rockchip,mclk-no-set"); + sai->mclk = devm_clk_get(&pdev->dev, "mclk"); if (IS_ERR(sai->mclk)) { dev_err(&pdev->dev, "Failed to get mclk\n");