mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
Merge commit 'ce6e1b95ba555d78ea1f4ca5653a1c8a074c1745'
* commit 'ce6e1b95ba555d78ea1f4ca5653a1c8a074c1745': arm64: dts: rockchip: rk3576-android: enabled wdt usb: typec: tcpci_husb311: Disable IRQ before unregistering TCPCI port misc: rk628: hdmitx: supplement valid modes misc: rk628: bt1120rx: rk628d adjust cpll frequency to support more frequencies misc: rk628: bt1120rx: rk628f adjust cpll frequency to support more frequencies misc: rk628: cru: clock adjustment logic optimization misc: rk628: cru: add clk_summary for debugging misc: rk628: hdmitx: fix rk628d display anomaly when clock frequency is below 40MHz phy: rockchip: inno-usb2: Add refclock freq setting media: rockchip: vpss: fix offline device id out of range phy: rockchip: usbdp: amend ssc modulation deviation media: i2c: lontium driver: remove judge timing valid drm/rockchip: analogix_dp: fix the log to indicate edp data source video: rockchip: mpp: rk3576: fix enc err when rec_fbc_dis=1 media: rockchip: vpss: offline support 8k drm/rockchip: dw-hdmi-qp: Enable/disable hdcp without hdmi enable/disable arm64: dts: rockchip: rk3576: fix apb clk to PCLK_HDPTX_APB for edp media: rockchip: hdmirx: fix low_latency NULL pointer err. ASoC: es8323: add support 'ADC Data Select' control node Change-Id: I3c5237b5d3c98957a1d02b563ea8ee5c1e3d45b6
This commit is contained in:
@@ -81,3 +81,7 @@
|
||||
&vop {
|
||||
support-multi-area;
|
||||
};
|
||||
|
||||
&wdt {
|
||||
status= "okay";
|
||||
};
|
||||
|
||||
@@ -5186,7 +5186,7 @@
|
||||
hdptxphy: phy@2b000000 {
|
||||
compatible = "rockchip,rk3576-hdptx-phy", "rockchip,rk3588-hdptx-phy";
|
||||
reg = <0x0 0x2b000000 0x0 0x2000>;
|
||||
clocks = <&cru CLK_PHY_REF_SRC>, <&cru PCLK_PMUPHY_ROOT>;
|
||||
clocks = <&cru CLK_PHY_REF_SRC>, <&cru PCLK_HDPTX_APB>;
|
||||
clock-names = "ref", "apb";
|
||||
resets = <&cru SRST_P_HDPTX_APB>, <&cru SRST_HDPTX_INIT>,
|
||||
<&cru SRST_HDPTX_CMN>, <&cru SRST_HDPTX_LANE>;
|
||||
|
||||
@@ -2075,9 +2075,8 @@ static u8 dw_hdmi_qp_hdcp_capable(struct dw_hdmi_qp *hdmi)
|
||||
}
|
||||
|
||||
static void dw_hdmi_qp_hdcp_enable(struct dw_hdmi_qp *hdmi,
|
||||
struct drm_connector *connector)
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
const struct drm_connector_state *conn_state = connector->state;
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
|
||||
hdmi_writel(hdmi, 0, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
@@ -2715,8 +2714,31 @@ static bool check_hdr_color_change(struct drm_connector_state *old_state,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool check_dw_hdcp_state_changed(struct drm_connector *conn,
|
||||
struct drm_atomic_state *state)
|
||||
static void dw_hdmi_qp_hdcp_disable(struct dw_hdmi_qp *hdmi,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
void *data = hdmi->plat_data->phy_data;
|
||||
|
||||
hdmi_writel(hdmi, 0, AVP_1_INT_MASK_N);
|
||||
hdmi_writel(hdmi, 0, AVP_3_INT_MASK_N);
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_stop)
|
||||
hdmi->hdcp->hdcp_stop(hdmi->hdcp);
|
||||
|
||||
hdmi_writel(hdmi, 0x34, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||
|
||||
if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
drm_hdcp_update_content_protection(hdmi->curr_conn,
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED);
|
||||
|
||||
hdmi->hdcp_status = 0;
|
||||
if (hdmi->plat_data->set_hdcp_status)
|
||||
hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
|
||||
}
|
||||
|
||||
static void set_dw_hdmi_hdcp_enable(struct dw_hdmi_qp *hdmi,
|
||||
struct drm_connector *conn,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *old_state, *new_state;
|
||||
u64 old_cp, new_cp;
|
||||
@@ -2726,24 +2748,14 @@ static bool check_dw_hdcp_state_changed(struct drm_connector *conn,
|
||||
old_cp = old_state->content_protection;
|
||||
new_cp = new_state->content_protection;
|
||||
|
||||
if (old_state->hdcp_content_type != new_state->hdcp_content_type &&
|
||||
new_cp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return true;
|
||||
if (old_cp != new_cp) {
|
||||
if (new_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
|
||||
old_cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
dw_hdmi_qp_hdcp_enable(hdmi, new_state);
|
||||
else if (new_cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED &&
|
||||
old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED)
|
||||
dw_hdmi_qp_hdcp_disable(hdmi, new_state);
|
||||
}
|
||||
|
||||
if (!new_state->crtc) {
|
||||
if (old_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)
|
||||
new_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (old_cp == new_cp ||
|
||||
(old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED &&
|
||||
new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
@@ -2890,9 +2902,6 @@ static int dw_hdmi_connector_atomic_check(struct drm_connector *connector,
|
||||
}
|
||||
}
|
||||
|
||||
if (check_dw_hdcp_state_changed(connector, state))
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2908,6 +2917,8 @@ static void dw_hdmi_connector_atomic_commit(struct drm_connector *connector,
|
||||
hdmi_writel(hdmi, 2, PKTSCHED_PKT_CONTROL0);
|
||||
hdmi->update = false;
|
||||
}
|
||||
|
||||
set_dw_hdmi_hdcp_enable(hdmi, connector, state);
|
||||
}
|
||||
|
||||
void dw_hdmi_qp_set_output_type(struct dw_hdmi_qp *hdmi, u64 val)
|
||||
@@ -3078,21 +3089,7 @@ static void dw_hdmi_qp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
hdmi_writel(hdmi, 1, PKTSCHED_PKT_CONTROL0);
|
||||
mdelay(50);
|
||||
|
||||
hdmi_writel(hdmi, 0, AVP_1_INT_MASK_N);
|
||||
hdmi_writel(hdmi, 0, AVP_3_INT_MASK_N);
|
||||
if (hdmi->hdcp && hdmi->hdcp->hdcp_stop)
|
||||
hdmi->hdcp->hdcp_stop(hdmi->hdcp);
|
||||
|
||||
hdmi_writel(hdmi, 0x34, HDCP2LOGIC_ESM_GPIO_IN);
|
||||
hdmi_modb(hdmi, HDCP2_BYPASS, HDCP2_BYPASS, HDCP2LOGIC_CONFIG0);
|
||||
|
||||
if (conn_state->content_protection != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)
|
||||
drm_hdcp_update_content_protection(hdmi->curr_conn,
|
||||
DRM_MODE_CONTENT_PROTECTION_DESIRED);
|
||||
|
||||
hdmi->hdcp_status = 0;
|
||||
if (hdmi->plat_data->set_hdcp_status)
|
||||
hdmi->plat_data->set_hdcp_status(data, hdmi->hdcp_status);
|
||||
dw_hdmi_qp_hdcp_disable(hdmi, conn_state);
|
||||
|
||||
extcon_set_state_sync(hdmi->extcon, EXTCON_DISP_HDMI, false);
|
||||
handle_plugged_change(hdmi, false);
|
||||
@@ -3165,7 +3162,7 @@ static void dw_hdmi_qp_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
if (hdmi->panel)
|
||||
drm_panel_enable(hdmi->panel);
|
||||
|
||||
dw_hdmi_qp_hdcp_enable(hdmi, hdmi->curr_conn);
|
||||
dw_hdmi_qp_hdcp_enable(hdmi, hdmi->curr_conn->state);
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dw_hdmi_bridge_funcs = {
|
||||
|
||||
@@ -383,6 +383,9 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
|
||||
struct rockchip_dp_device *dp = encoder_to_dp(encoder);
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state;
|
||||
struct of_endpoint endpoint;
|
||||
struct device_node *remote_port_parent;
|
||||
char name[32];
|
||||
int ret;
|
||||
|
||||
crtc = rockchip_dp_drm_get_new_crtc(encoder, state);
|
||||
@@ -398,11 +401,21 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder,
|
||||
if (ret != 0)
|
||||
DRM_DEV_ERROR(dp->dev, "Could not write to GRF reg mem_clk_auto_gating: %d\n", ret);
|
||||
|
||||
ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder);
|
||||
ret = drm_of_encoder_active_endpoint(dp->dev->of_node, encoder, &endpoint);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
DRM_DEV_DEBUG(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG");
|
||||
remote_port_parent = of_graph_get_remote_port_parent(endpoint.local_node);
|
||||
if (remote_port_parent) {
|
||||
if (of_get_child_by_name(remote_port_parent, "ports"))
|
||||
sprintf(name, "%s vp%d", remote_port_parent->full_name, endpoint.id);
|
||||
else
|
||||
sprintf(name, "%s %s",
|
||||
remote_port_parent->full_name, endpoint.id ? "vopl" : "vopb");
|
||||
of_node_put(remote_port_parent);
|
||||
|
||||
DRM_DEV_DEBUG(dp->dev, "%s output to edp\n", name);
|
||||
}
|
||||
|
||||
ret = rockchip_grf_field_write(dp->grf, &dp->data->lcdc_sel, ret);
|
||||
if (ret != 0)
|
||||
|
||||
@@ -739,12 +739,6 @@ static int lt6911uxc_s_dv_timings(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!v4l2_valid_dv_timings(timings,
|
||||
<6911uxc_timings_cap, NULL, NULL)) {
|
||||
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
lt6911uxc->timings = *timings;
|
||||
enable_stream(sd, false);
|
||||
|
||||
|
||||
@@ -654,12 +654,6 @@ static int lt7911d_s_dv_timings(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!v4l2_valid_dv_timings(timings,
|
||||
<7911d_timings_cap, NULL, NULL)) {
|
||||
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
lt7911d->timings = *timings;
|
||||
|
||||
enable_stream(sd, false);
|
||||
|
||||
@@ -925,12 +925,6 @@ static int lt7911uxc_s_dv_timings(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!v4l2_valid_dv_timings(timings,
|
||||
<7911uxc_timings_cap, NULL, NULL)) {
|
||||
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
lt7911uxc->timings = *timings;
|
||||
|
||||
enable_stream(sd, false);
|
||||
|
||||
@@ -892,12 +892,6 @@ static int lt8668sx_s_dv_timings(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!v4l2_valid_dv_timings(timings,
|
||||
<8668sx_timings_cap, NULL, NULL)) {
|
||||
v4l2_dbg(1, debug, sd, "%s: timings out of range\n", __func__);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
lt8668sx->timings = *timings;
|
||||
lt8668sx->last_framerate = lt8668sx->cur_framerate;
|
||||
|
||||
|
||||
@@ -2195,6 +2195,7 @@ static void hdmirx_free_fence(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
unsigned long lock_flags = 0;
|
||||
struct hdmirx_fence *vb_fence, *done_fence;
|
||||
struct v4l2_device *v4l2_dev = &hdmirx_dev->v4l2_dev;
|
||||
struct files_struct *files = current->files;
|
||||
LIST_HEAD(local_list);
|
||||
|
||||
spin_lock_irqsave(&hdmirx_dev->fence_lock, lock_flags);
|
||||
@@ -2216,7 +2217,8 @@ static void hdmirx_free_fence(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
v4l2_dbg(2, debug, v4l2_dev, "%s: free qbuf_fence fd:%d\n",
|
||||
__func__, vb_fence->fence_fd);
|
||||
dma_fence_put(vb_fence->fence);
|
||||
put_unused_fd(vb_fence->fence_fd);
|
||||
if (files)
|
||||
put_unused_fd(vb_fence->fence_fd);
|
||||
kfree(vb_fence);
|
||||
}
|
||||
|
||||
@@ -2229,7 +2231,8 @@ static void hdmirx_free_fence(struct rk_hdmirx_dev *hdmirx_dev)
|
||||
v4l2_dbg(2, debug, v4l2_dev, "%s: free done_fence fd:%d\n",
|
||||
__func__, done_fence->fence_fd);
|
||||
dma_fence_put(done_fence->fence);
|
||||
put_unused_fd(done_fence->fence_fd);
|
||||
if (files)
|
||||
put_unused_fd(done_fence->fence_fd);
|
||||
kfree(done_fence);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
|
||||
#define RKVPSS_DEFAULT_WIDTH 1920
|
||||
#define RKVPSS_DEFAULT_HEIGHT 1080
|
||||
|
||||
#define RKVPSS_MAX_WIDTH 4672
|
||||
#define RKVPSS_MAX_HEIGHT 3504
|
||||
#define RKVPSS_MIN_WIDTH 32
|
||||
#define RKVPSS_MIN_HEIGHT 32
|
||||
#define RKVPSS_UNITE_MAX_WIDTH 8192
|
||||
#define RKVPSS_UNITE_MAX_HEIGHT 6144
|
||||
#define RKVPSS_VIDEO_NAME_LEN 16
|
||||
|
||||
#define RKVPSS_REG_CACHE_SYNC 0xeeeeeeee
|
||||
@@ -43,6 +44,13 @@ enum rkvpss_fmt_pix_type {
|
||||
FMT_RGB,
|
||||
};
|
||||
|
||||
enum rkvpss_rotate {
|
||||
ROTATE_0 = 0,
|
||||
ROTATE_90,
|
||||
ROTATE_180,
|
||||
ROTATE_270,
|
||||
};
|
||||
|
||||
/* One structure per video node */
|
||||
struct rkvpss_vdev_node {
|
||||
struct vb2_queue buf_queue;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,9 @@
|
||||
|
||||
#ifndef _RKVPSS_OFFLINE_H
|
||||
#define _RKVPSS_OFFLINE_H
|
||||
#define DEV_NUM_MAX 10
|
||||
#define DEV_NUM_MAX 256
|
||||
#define UNITE_ENLARGE 16
|
||||
#define UNITE_LEFT_ENLARGE 16
|
||||
|
||||
#include "hw.h"
|
||||
|
||||
@@ -45,6 +47,20 @@ struct rkvpss_dev_rate {
|
||||
u32 delay;
|
||||
};
|
||||
|
||||
struct rkvpss_unite_scl_params {
|
||||
u32 y_w_fac;
|
||||
u32 c_w_fac;
|
||||
u32 y_h_fac;
|
||||
u32 c_h_fac;
|
||||
u32 y_w_phase;
|
||||
u32 c_w_phase;
|
||||
u32 quad_crop_w;
|
||||
u32 scl_in_crop_w_y;
|
||||
u32 scl_in_crop_w_c;
|
||||
u32 right_scl_need_size_y;
|
||||
u32 right_scl_need_size_c;
|
||||
};
|
||||
|
||||
struct rkvpss_offline_dev {
|
||||
struct rkvpss_hw_dev *hw;
|
||||
struct v4l2_device v4l2_dev;
|
||||
@@ -56,6 +72,8 @@ struct rkvpss_offline_dev {
|
||||
struct list_head cfginfo_list;
|
||||
struct mutex ofl_lock;
|
||||
struct rkvpss_dev_rate dev_rate[DEV_NUM_MAX];
|
||||
struct rkvpss_unite_scl_params unite_params[RKVPSS_OUTPUT_MAX];
|
||||
u32 unite_right_enlarge;
|
||||
bool mode_sel_en;
|
||||
};
|
||||
|
||||
|
||||
@@ -1321,6 +1321,7 @@ static void rk628_debugfs_create(struct rk628 *rk628)
|
||||
|
||||
rk628_debugfs_register_create(rk628);
|
||||
|
||||
rk628_cru_create_debugfs_file(rk628);
|
||||
rk628_rgb_decoder_create_debugfs_file(rk628);
|
||||
rk628_post_process_create_debugfs_file(rk628);
|
||||
rk628_mipi_dsi_create_debugfs_file(rk628);
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
|
||||
#include "asm-generic/errno-base.h"
|
||||
#include "rk628.h"
|
||||
#include "rk628_cru.h"
|
||||
@@ -273,19 +275,85 @@ static unsigned long rk628_cru_clk_set_rate_pll(struct rk628 *rk628,
|
||||
return (unsigned long)foutpostdiv;
|
||||
}
|
||||
|
||||
static int rk628_cru_clk_get_parent_rate(struct rk628 *rk628, unsigned int id,
|
||||
unsigned int *parent_id,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
u32 val;
|
||||
int parent = -1;
|
||||
|
||||
switch (id) {
|
||||
case CGU_CLK_RX_READ:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
|
||||
val &= CLK_RX_READ_SEL_MASK;
|
||||
val >>= CLK_RX_READ_SEL_SHIFT;
|
||||
parent = val == CLK_RX_READ_SEL_GPLL ? CGU_CLK_GPLL : CGU_CLK_CPLL;
|
||||
break;
|
||||
case CGU_SCLK_VOP:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
|
||||
val &= CLK_UART_SRC_SEL_MASK;
|
||||
val >>= SCLK_VOP_SEL_SHIFT;
|
||||
parent = val == SCLK_VOP_SEL_GPLL ? CGU_CLK_GPLL : CGU_CLK_CPLL;
|
||||
break;
|
||||
case CGU_CLK_UART_SRC:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &val);
|
||||
val &= SCLK_VOP_SEL_MASK;
|
||||
parent = val == CLK_UART_SRC_SEL_GPLL ? CGU_CLK_GPLL : CGU_CLK_CPLL;
|
||||
break;
|
||||
case CGU_BT1120DEC:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
|
||||
val &= CLK_BT1120DEC_SEL_MASK;
|
||||
parent = val == CLK_BT1120DEC_SEL_GPLL ? CGU_CLK_GPLL : CGU_CLK_CPLL;
|
||||
break;
|
||||
case CGU_CLK_HDMIRX_AUD:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V2) >> 14;
|
||||
else
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V1) >> 15;
|
||||
switch (val) {
|
||||
case 0:
|
||||
parent = CGU_CLK_CPLL;
|
||||
break;
|
||||
case 1:
|
||||
parent = CGU_CLK_GPLL;
|
||||
break;
|
||||
case 2:
|
||||
parent = CGU_CLK_APLL;
|
||||
}
|
||||
break;
|
||||
case CGU_CLK_IMODET:
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
|
||||
val &= CLK_IMODET_SEL_MASK;
|
||||
val >>= CLK_IMODET_SEL_SHIFT;
|
||||
parent = val == SCLK_VOP_SEL_GPLL ? CGU_CLK_GPLL : CGU_CLK_CPLL;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (parent < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (parent_id)
|
||||
*parent_id = parent;
|
||||
|
||||
if (parent_rate)
|
||||
*parent_rate = rk628_cru_clk_get_rate(rk628, parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long m, n, parent_rate;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
|
||||
val &= SCLK_VOP_SEL_MASK;
|
||||
val >>= SCLK_VOP_SEL_SHIFT;
|
||||
if (val == SCLK_VOP_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_SCLK_VOP,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rational_best_approximation(rate, parent_rate,
|
||||
GENMASK(15, 0), GENMASK(15, 0),
|
||||
@@ -298,15 +366,13 @@ static unsigned long rk628_cru_clk_set_rate_sclk_vop(struct rk628 *rk628,
|
||||
static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate, parent_rate, m, n;
|
||||
u32 mux, div;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux);
|
||||
mux &= CLK_UART_SRC_SEL_MASK;
|
||||
mux >>= SCLK_VOP_SEL_SHIFT;
|
||||
if (mux == SCLK_VOP_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_SCLK_VOP,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON13, &div);
|
||||
m = div >> 16 & 0xffff;
|
||||
@@ -319,15 +385,13 @@ static unsigned long rk628_cru_clk_get_rate_sclk_vop(struct rk628 *rk628)
|
||||
static unsigned long rk628_cru_clk_get_rate_clk_imodet(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate, parent_rate, n;
|
||||
u32 mux, div;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &mux);
|
||||
mux &= CLK_IMODET_SEL_MASK;
|
||||
mux >>= CLK_IMODET_SEL_SHIFT;
|
||||
if (mux == SCLK_VOP_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_CLK_IMODET,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &div);
|
||||
n = div & 0x1f;
|
||||
@@ -340,15 +404,12 @@ static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long m, n, parent_rate;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &val);
|
||||
val &= CLK_RX_READ_SEL_MASK;
|
||||
val >>= CLK_RX_READ_SEL_SHIFT;
|
||||
if (val == CLK_RX_READ_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_CLK_RX_READ,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rational_best_approximation(rate, parent_rate,
|
||||
GENMASK(15, 0), GENMASK(15, 0),
|
||||
@@ -358,17 +419,35 @@ static unsigned long rk628_cru_clk_set_rate_rx_read(struct rk628 *rk628,
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_get_rate_rx_read(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate, m, n, parent_rate;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_CLK_RX_READ,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON14, &div);
|
||||
m = div >> 16 & 0xffff;
|
||||
n = div & 0xffff;
|
||||
rate = parent_rate * m / n;
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_get_rate_uart_src(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate, parent_rate;
|
||||
u32 mux, div;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &mux);
|
||||
mux &= SCLK_VOP_SEL_MASK;
|
||||
if (mux == CLK_UART_SRC_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_CLK_UART_SRC,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON21, &div);
|
||||
div &= CLK_UART_SRC_DIV_MASK;
|
||||
@@ -429,51 +508,34 @@ static unsigned long rk628_cru_clk_set_rate_sclk_hdmirx_aud(struct rk628 *rk628,
|
||||
|
||||
static unsigned long rk628_cru_clk_get_rate_sclk_hdmirx_aud(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long rate;
|
||||
u64 parent_rate;
|
||||
u8 div;
|
||||
u32 val;
|
||||
unsigned long rate, parent_rate;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_CLK_HDMIRX_AUD,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &div);
|
||||
div = ((div & CLK_HDMIRX_AUD_DIV_MASK) >> 6) + 1;
|
||||
rate = parent_rate / div;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON05, &val);
|
||||
div = ((val & CLK_HDMIRX_AUD_DIV_MASK) >> 6) + 1;
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V2) >> 14;
|
||||
else
|
||||
val = (val & CLK_HDMIRX_AUD_SEL_MASK_V1) >> 15;
|
||||
if (!val)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
else if (val == 2)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_APLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
do_div(parent_rate, div);
|
||||
rate = parent_rate;
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
rk628_cru_clk_get_rate_bt1120_dec_parent(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long parent_rate;
|
||||
u32 mux;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &mux);
|
||||
mux &= CLK_BT1120DEC_SEL_MASK;
|
||||
if (mux == CLK_BT1120DEC_SEL_GPLL)
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_GPLL);
|
||||
else
|
||||
parent_rate = rk628_cru_clk_get_rate_pll(rk628, CGU_CLK_CPLL);
|
||||
|
||||
return parent_rate;
|
||||
}
|
||||
|
||||
static unsigned long rk628_cru_clk_set_rate_bt1120_dec(struct rk628 *rk628,
|
||||
unsigned long rate)
|
||||
{
|
||||
unsigned long parent_rate;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_BT1120DEC,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
parent_rate = rk628_cru_clk_get_rate_bt1120_dec_parent(rk628);
|
||||
div = DIV_ROUND_UP(parent_rate, rate);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON02, CLK_BT1120DEC_DIV(div-1));
|
||||
|
||||
@@ -484,8 +546,12 @@ static unsigned long rk628_cru_clk_get_rate_bt1120_dec(struct rk628 *rk628)
|
||||
{
|
||||
unsigned long parent_rate;
|
||||
u32 div;
|
||||
int ret;
|
||||
|
||||
parent_rate = rk628_cru_clk_get_rate_bt1120_dec_parent(rk628);
|
||||
ret = rk628_cru_clk_get_parent_rate(rk628, CGU_BT1120DEC,
|
||||
NULL, &parent_rate);
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
rk628_i2c_read(rk628, CRU_CLKSEL_CON02, &div);
|
||||
div = (div & 0x1f) + 1;
|
||||
@@ -540,6 +606,9 @@ unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id)
|
||||
case CGU_CLK_GPLL:
|
||||
rate = rk628_cru_clk_get_rate_pll(rk628, id);
|
||||
break;
|
||||
case CGU_CLK_RX_READ:
|
||||
rate = rk628_cru_clk_get_rate_rx_read(rk628);
|
||||
break;
|
||||
case CGU_SCLK_VOP:
|
||||
rate = rk628_cru_clk_get_rate_sclk_vop(rk628);
|
||||
break;
|
||||
@@ -559,32 +628,201 @@ unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id)
|
||||
return rate;
|
||||
}
|
||||
|
||||
static void rk628_cru_show_pll_tree(struct seq_file *s, unsigned int parent_id,
|
||||
const char *parent_name)
|
||||
{
|
||||
struct rk628 *rk628 = s->private;
|
||||
unsigned long rate;
|
||||
unsigned int parent, i;
|
||||
unsigned int id_list[] = {
|
||||
CGU_CLK_RX_READ,
|
||||
CGU_SCLK_VOP,
|
||||
CGU_BT1120DEC,
|
||||
CGU_CLK_HDMIRX_AUD,
|
||||
CGU_CLK_IMODET
|
||||
};
|
||||
char const *id_name[] = {
|
||||
"clk_rx_read",
|
||||
"clk_sclk_vop",
|
||||
"clk_bt1120dec",
|
||||
"clk_hdmirx_aud",
|
||||
"clk_imodet"
|
||||
};
|
||||
|
||||
if (rk628->version < RK628F_VERSION && parent_id == CGU_CLK_APLL)
|
||||
return;
|
||||
|
||||
rate = rk628_cru_clk_get_rate(rk628, parent_id);
|
||||
seq_printf(s, "%-22s %10lu\n", parent_name, rate);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(id_list); ++i) {
|
||||
rk628_cru_clk_get_parent_rate(rk628, id_list[i], &parent, NULL);
|
||||
if (parent != parent_id)
|
||||
continue;
|
||||
rate = rk628_cru_clk_get_rate(rk628, id_list[i]);
|
||||
seq_printf(s, " %-18s %10lu\n", id_name[i], rate);
|
||||
}
|
||||
}
|
||||
|
||||
static int rk628_cru_show_clk_tree(struct seq_file *s, void *data)
|
||||
{
|
||||
unsigned int pll_list[] = {CGU_CLK_CPLL, CGU_CLK_GPLL, CGU_CLK_APLL};
|
||||
char const *pll_name[] = {"cpll", "gpll", "apll"};
|
||||
unsigned int i;
|
||||
|
||||
seq_printf(s, "%-22s %10s\n", " clock", "rate ");
|
||||
seq_puts(s, "---------------------------------\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pll_list); ++i)
|
||||
rk628_cru_show_pll_tree(s, pll_list[i], pll_name[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk628_clk_summary_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct rk628 *rk628 = inode->i_private;
|
||||
|
||||
return single_open(file, rk628_cru_show_clk_tree, rk628);
|
||||
}
|
||||
|
||||
static const struct file_operations rk628_clk_summary_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = rk628_clk_summary_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
void rk628_cru_create_debugfs_file(struct rk628 *rk628)
|
||||
{
|
||||
debugfs_create_file("clk_summary", 0400, rk628->debug_dir, rk628,
|
||||
&rk628_clk_summary_fops);
|
||||
}
|
||||
|
||||
void rk628_cru_init(struct rk628 *rk628)
|
||||
{
|
||||
u32 val;
|
||||
u8 mcu_mode;
|
||||
|
||||
/*
|
||||
* In rk628d application, if you need to dynamically tune the cpll
|
||||
* frequency, you need to mount pclk under gpll, otherwise it will
|
||||
* affect the i2c use. The bt1120rx only supports 5bit integer crossover
|
||||
* frequency, in order to crossover frequency accurately, you need to
|
||||
* adjust the cpll frequency dynamically, so in the scenario of rk628d
|
||||
* bt1120rx, mount the pclk under gpll.
|
||||
*/
|
||||
rk628_i2c_read(rk628, GRF_SYSTEM_STATUS0, &val);
|
||||
mcu_mode = (val & I2C_ONLY_FLAG) ? 0 : 1;
|
||||
if (mcu_mode || rk628->version >= RK628F_VERSION) {
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, HIWORD_UPDATE(1, 4, 4));
|
||||
/*
|
||||
* rk628d pclk use cpll by default, and frequency is 99MHz
|
||||
* rk628f pclk use gpll by default, and frequency is 98.304MHz
|
||||
*/
|
||||
if (rk628_input_is_bt1120(rk628)) {
|
||||
/* set pclk use gpll, and set pclk 98.304Hz */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0089);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* clock switch and first set gpll almost 99MHz */
|
||||
rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff701d);
|
||||
mdelay(1);
|
||||
/* set clk_gpll_mux from gpll */
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0004);
|
||||
mdelay(1);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0080);
|
||||
/* set pclk use gpll, now div is 4 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0083);
|
||||
/* set cpll almost 400MHz */
|
||||
rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff3063);
|
||||
mdelay(1);
|
||||
/* set clk_cpll_mux from clk_cpll */
|
||||
rk628_i2c_write(rk628, CRU_MODE_CON00, 0xffff0005);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
|
||||
rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028);
|
||||
mdelay(1);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b);
|
||||
rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063);
|
||||
mdelay(1);
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
|
||||
if (rk628_input_is_bt1120(rk628)) {
|
||||
/* set pclk use cpll, now div is 4 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003);
|
||||
/* set pclk use cpll, now div is 10 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0009);
|
||||
/* set gpll 983.04Hz */
|
||||
rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028);
|
||||
mdelay(1);
|
||||
/* set pclk use gpll, now div is 10 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0089);
|
||||
/* set cpll 1188MHz */
|
||||
rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063);
|
||||
/* final: cpll 1188MHz, gpll 983.04Hz, pclk (use gpll) 98.304Hz */
|
||||
} else {
|
||||
/* set pclk use cpll, now div is 4 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff0003);
|
||||
/* set pclk use cpll, now div is 12 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
|
||||
/* set gpll 983.04Hz */
|
||||
rk628_i2c_write(rk628, CRU_GPLL_CON0, 0xffff1028);
|
||||
mdelay(1);
|
||||
/* set pclk use gpll, now div is 12 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff008b);
|
||||
/* set cpll 1188MHz */
|
||||
rk628_i2c_write(rk628, CRU_CPLL_CON0, 0xffff1063);
|
||||
mdelay(1);
|
||||
/* set pclk use cpll, now div is 12 */
|
||||
rk628_i2c_write(rk628, CRU_CLKSEL_CON00, 0x00ff000b);
|
||||
/* final: cpll 1188MHz, gpll 983.04Hz, pclk (use cpll) 99Hz */
|
||||
}
|
||||
}
|
||||
|
||||
void rk628_cru_clk_adjust(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_display_mode *src = &rk628->src_mode;
|
||||
const struct rk628_display_mode *dst = &rk628->dst_mode;
|
||||
u64 dst_rate, src_rate;
|
||||
unsigned long dec_clk_rate;
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
* Try to keep cpll frequency close to 1188m (Tested bt1120rx and rk628f
|
||||
* hdmirx scenarios)
|
||||
*/
|
||||
if ((rk628_input_is_hdmi(rk628) && rk628->version != RK628D_VERSION) ||
|
||||
rk628_input_is_bt1120(rk628)) {
|
||||
val = 1188000000UL / (src->clock * 1000);
|
||||
if (rk628_input_is_bt1120(rk628) && val > (CLK_BT1120DEC_DIV_MAX + 1))
|
||||
val = CLK_BT1120DEC_DIV_MAX + 1;
|
||||
val *= src->clock * 1000;
|
||||
rk628_cru_clk_set_rate(rk628, CGU_CLK_CPLL, val);
|
||||
msleep(50);
|
||||
dev_info(rk628->dev, "adjust cpll to %uHz", val);
|
||||
}
|
||||
|
||||
/*
|
||||
* BT1120 dec clk is a 5-bit integer division, which is inaccurate in
|
||||
* most resolutions. So if the frequency division is not accurate, apply
|
||||
* for a fault tolerance of up 2% in frequency setting, so that the
|
||||
* obtained frequency is slightly higher than the actual required clk,
|
||||
* so that the deviation between the actual clk and the required clk
|
||||
* frequency is not significant.
|
||||
*/
|
||||
if (rk628_input_is_bt1120(rk628)) {
|
||||
rk628_cru_clk_set_rate(rk628, CGU_BT1120DEC, src->clock * 1000);
|
||||
dec_clk_rate = rk628_cru_clk_get_rate(rk628, CGU_BT1120DEC);
|
||||
if (dec_clk_rate < src->clock * 1000)
|
||||
rk628_cru_clk_set_rate(rk628, CGU_BT1120DEC, src->clock * 1020);
|
||||
}
|
||||
|
||||
src_rate = src->clock * 1000;
|
||||
dst_rate = src_rate * dst->vtotal * dst->htotal;
|
||||
do_div(dst_rate, (src->vtotal * src->htotal));
|
||||
do_div(dst_rate, 1000);
|
||||
dev_info(rk628->dev, "src %dx%d clock:%d\n",
|
||||
src->hdisplay, src->vdisplay, src->clock);
|
||||
|
||||
dev_info(rk628->dev, "dst %dx%d clock:%llu\n",
|
||||
dst->hdisplay, dst->vdisplay, dst_rate);
|
||||
|
||||
rk628_cru_clk_set_rate(rk628, CGU_CLK_RX_READ, src->clock * 1000);
|
||||
rk628_cru_clk_set_rate(rk628, CGU_SCLK_VOP, dst_rate * 1000);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
#define CLK_BT1120DEC_SEL_GPLL 1
|
||||
#define CLK_BT1120DEC_SEL_CPLL 0
|
||||
#define CLK_BT1120DEC_DIV(x) HIWORD_UPDATE(x, 4, 0)
|
||||
#define CLK_BT1120DEC_DIV_MAX GENMASK(4, 0)
|
||||
#define CRU_CLKSEL_CON03 CRU_REG(0x008c)
|
||||
#define CRU_CLKSEL_CON04 CRU_REG(0x0090)
|
||||
#define CLK_HDMIRX_AUD_DIV_MASK GENMASK(13, 6)
|
||||
@@ -172,10 +173,13 @@
|
||||
#define CGU_BT1120DEC 37
|
||||
#define CGU_SCLK_UART 38
|
||||
#define CGU_CLK_APLL 39
|
||||
#define CGU_CLK_UART_SRC 40
|
||||
|
||||
unsigned long rk628_cru_clk_get_rate(struct rk628 *rk628, unsigned int id);
|
||||
int rk628_cru_clk_set_rate(struct rk628 *rk628, unsigned int id,
|
||||
unsigned long rate);
|
||||
void rk628_cru_init(struct rk628 *rk628);
|
||||
void rk628_cru_create_debugfs_file(struct rk628 *rk628);
|
||||
void rk628_cru_clk_adjust(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1227,14 +1227,7 @@ int rk628_hdmirx_enable(struct rk628 *rk628)
|
||||
return HDMIRX_PLUGIN | HDMIRX_NOSIGNAL;
|
||||
|
||||
dev_info(rk628->dev, "hdmirx success\n");
|
||||
if (rk628->version != RK628D_VERSION) {
|
||||
/* Try to keep pll frequency close to 1188m */
|
||||
val = DIV_ROUND_CLOSEST_ULL(1188000000, (src_mode->clock * 1000));
|
||||
val *= src_mode->clock * 1000;
|
||||
/* set pll rate according hdmirx tmds clk */
|
||||
rk628_cru_clk_set_rate(rk628, CGU_CLK_CPLL, val);
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
rk628_hdmirx_video_unmute(rk628, 1);
|
||||
|
||||
return HDMIRX_PLUGIN;
|
||||
|
||||
@@ -630,6 +630,33 @@ static enum drm_mode_status
|
||||
rk628_hdmi_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct rk628_hdmi *hdmi = connector_to_hdmi(connector);
|
||||
struct rk628 *rk628 = hdmi->rk628;
|
||||
|
||||
/* rk628 hdmitx supports up to 148.5MHz frequency */
|
||||
if (mode->clock > 148500)
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
/*
|
||||
* rk628d hdmitx below (including) 40MHz clock frequency (800x600@60Hz),
|
||||
* hsync and vsync can only output negative polarity
|
||||
*/
|
||||
if (rk628->version == RK628D_VERSION && mode->clock <= 40000 &&
|
||||
(mode->flags & DRM_MODE_FLAG_PHSYNC ||
|
||||
mode->flags & DRM_MODE_FLAG_PVSYNC))
|
||||
return MODE_BAD;
|
||||
|
||||
if (rk628_input_is_bt1120(rk628) || rk628_input_is_rgb(rk628)) {
|
||||
/* rk628 bt1120rx cannot be displayed at frequencies below 40MHz. */
|
||||
if (rk628_input_is_bt1120(rk628) && mode->clock < 40000)
|
||||
return MODE_CLOCK_LOW;
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unverified pathway retains only 1080p and 720p resolutions
|
||||
*/
|
||||
if ((mode->hdisplay == 1920 && mode->vdisplay == 1080) ||
|
||||
(mode->hdisplay == 1280 && mode->vdisplay == 720))
|
||||
return MODE_OK;
|
||||
@@ -677,8 +704,19 @@ static void rk628_hdmi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
struct rk628_display_mode *src = rk628_display_get_src_mode(rk628);
|
||||
struct rk628_display_mode *dst = rk628_display_get_dst_mode(rk628);
|
||||
|
||||
/* Store the display mode for plugin/DPMS poweron events */
|
||||
/*
|
||||
* Store the display mode for plugin/DPMS poweron events. rk628d hdmitx
|
||||
* below (including) 40MHz clock frequency (800x600@60Hz), hsync and
|
||||
* vsync can only output negative polarity
|
||||
*/
|
||||
memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode));
|
||||
if (rk628->version == RK628D_VERSION && mode->clock <= 40000) {
|
||||
hdmi->previous_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
|
||||
DRM_MODE_FLAG_PVSYNC);
|
||||
hdmi->previous_mode.flags |= (DRM_MODE_FLAG_NHSYNC |
|
||||
DRM_MODE_FLAG_NVSYNC);
|
||||
}
|
||||
|
||||
dst->clock = mode->clock;
|
||||
dst->hdisplay = mode->hdisplay;
|
||||
dst->hsync_start = mode->hsync_start;
|
||||
|
||||
@@ -1502,20 +1502,6 @@ void rk628_post_process_init(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_display_mode *src = &rk628->src_mode;
|
||||
const struct rk628_display_mode *dst = &rk628->dst_mode;
|
||||
u64 dst_rate, src_rate;
|
||||
|
||||
src_rate = src->clock * 1000;
|
||||
dst_rate = src_rate * dst->vtotal * dst->htotal;
|
||||
do_div(dst_rate, (src->vtotal * src->htotal));
|
||||
do_div(dst_rate, 1000);
|
||||
dev_info(rk628->dev, "src %dx%d clock:%d\n",
|
||||
src->hdisplay, src->vdisplay, src->clock);
|
||||
|
||||
dev_info(rk628->dev, "dst %dx%d clock:%llu\n",
|
||||
dst->hdisplay, dst->vdisplay, dst_rate);
|
||||
|
||||
rk628_cru_clk_set_rate(rk628, CGU_CLK_RX_READ, src->clock * 1000);
|
||||
rk628_cru_clk_set_rate(rk628, CGU_SCLK_VOP, dst_rate * 1000);
|
||||
|
||||
if (rk628_output_is_hdmi(rk628)) {
|
||||
rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_VSYNC_POL_MASK,
|
||||
@@ -1602,6 +1588,7 @@ static void rk628_post_process_csc(struct rk628 *rk628)
|
||||
|
||||
void rk628_post_process_enable(struct rk628 *rk628)
|
||||
{
|
||||
rk628_cru_clk_adjust(rk628);
|
||||
/*
|
||||
* bt1120 needs to configure the timing register, but hdmitx will modify
|
||||
* the timing as needed, so the bt1120 enable process is moved here.
|
||||
|
||||
@@ -269,7 +269,6 @@ static void rk628_bt1120_decoder_timing_cfg(struct rk628 *rk628)
|
||||
static void rk628_bt1120_decoder_enable(struct rk628 *rk628)
|
||||
{
|
||||
struct rk628_display_mode *mode = rk628_display_get_src_mode(rk628);
|
||||
unsigned long dec_clk_rate;
|
||||
|
||||
rk628_set_input_bus_format(rk628, BUS_FMT_YUV422);
|
||||
|
||||
@@ -289,19 +288,6 @@ static void rk628_bt1120_decoder_enable(struct rk628 *rk628)
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON00, 0x10001000);
|
||||
rk628_i2c_write(rk628, CRU_SOFTRST_CON00, 0x10000000);
|
||||
|
||||
/*
|
||||
* BT1120 dec clk is a 4-bit integer division, which is inaccurate in
|
||||
* most resolutions. So if the frequency division is not accurate, apply
|
||||
* for a fault tolerance of up 2% in frequency setting, so that the
|
||||
* obtained frequency is slightly higher than the actual required clk,
|
||||
* so that the deviation between the actual clk and the required clk
|
||||
* frequency is not significant.
|
||||
*/
|
||||
rk628_cru_clk_set_rate(rk628, CGU_BT1120DEC, mode->clock * 1000);
|
||||
dec_clk_rate = rk628_cru_clk_get_rate(rk628, CGU_BT1120DEC);
|
||||
if (dec_clk_rate < mode->clock * 1000)
|
||||
rk628_cru_clk_set_rate(rk628, CGU_BT1120DEC, mode->clock * 1020);
|
||||
|
||||
if (rk628->rgb.bt1120_dual_edge) {
|
||||
rk628_i2c_update_bits(rk628, GRF_RGB_DEC_CON0,
|
||||
DEC_DUALEDGE_EN, DEC_DUALEDGE_EN);
|
||||
|
||||
@@ -217,6 +217,9 @@ struct rockchip_usb2phy_port_cfg {
|
||||
* @ls_filter_con: set linestate filter time.
|
||||
* @port_cfgs: usb-phy port configurations.
|
||||
* @ls_filter_con: set linestate filter time.
|
||||
* @refclk_fsel: reference clock frequency select,
|
||||
* true - select 24 MHz
|
||||
* false - select 26 MHz
|
||||
* @chg_det: charger detection registers.
|
||||
*/
|
||||
struct rockchip_usb2phy_cfg {
|
||||
@@ -229,6 +232,7 @@ struct rockchip_usb2phy_cfg {
|
||||
struct usb2phy_reg clkout_ctl;
|
||||
struct usb2phy_reg clkout_ctl_phy;
|
||||
struct usb2phy_reg ls_filter_con;
|
||||
struct usb2phy_reg refclk_fsel;
|
||||
const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
|
||||
const struct rockchip_chg_det_reg chg_det;
|
||||
};
|
||||
@@ -580,6 +584,31 @@ err_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_usb2phy_refclk_set(struct rockchip_usb2phy *rphy)
|
||||
{
|
||||
struct regmap *base = get_reg_base(rphy);
|
||||
struct clk *refclk = of_clk_get_by_name(rphy->dev->of_node, "phyclk");
|
||||
unsigned long rate;
|
||||
|
||||
/* get phy reference clock */
|
||||
rate = clk_get_rate(refclk);
|
||||
dev_info(rphy->dev, "refclk freq %ld\n", rate);
|
||||
|
||||
switch (rate) {
|
||||
case 24000000:
|
||||
property_enable(base, &rphy->phy_cfg->refclk_fsel, true);
|
||||
break;
|
||||
case 26000000:
|
||||
property_enable(base, &rphy->phy_cfg->refclk_fsel, false);
|
||||
break;
|
||||
default:
|
||||
dev_err(rphy->dev, "unsupported refclk freq %ld\n", rate);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_usb2phy_extcon_register(struct rockchip_usb2phy *rphy)
|
||||
{
|
||||
int ret;
|
||||
@@ -2382,6 +2411,13 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
||||
else
|
||||
rphy->num_clks = ret;
|
||||
|
||||
/* Set phy Reference clock frequency */
|
||||
if (rphy->phy_cfg->refclk_fsel.enable) {
|
||||
ret = rockchip_usb2phy_refclk_set(rphy);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_bulk_prepare_enable(rphy->num_clks, rphy->clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -4009,6 +4045,7 @@ static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
|
||||
.phy_tuning = rk3576_usb2phy_tuning,
|
||||
.clkout_ctl = { 0x0008, 0, 0, 1, 0 },
|
||||
.ls_filter_con = { 0x0020, 19, 0, 0x30100, 0x00020 },
|
||||
.refclk_fsel = { 0x0004, 2, 0, 0x6, 0x2 },
|
||||
.port_cfgs = {
|
||||
[USB2PHY_PORT_OTG] = {
|
||||
.phy_sus = { 0x0000, 8, 0, 0, 0x1d1 },
|
||||
@@ -4063,6 +4100,7 @@ static const struct rockchip_usb2phy_cfg rk3576_phy_cfgs[] = {
|
||||
.phy_tuning = rk3576_usb2phy_tuning,
|
||||
.clkout_ctl = { 0x2008, 0, 0, 1, 0 },
|
||||
.ls_filter_con = { 0x2020, 19, 0, 0x30100, 0x00020 },
|
||||
.refclk_fsel = { 0x2004, 2, 0, 0x6, 0x2 },
|
||||
.port_cfgs = {
|
||||
[USB2PHY_PORT_OTG] = {
|
||||
.phy_sus = { 0x2000, 8, 0, 0, 0x1d1 },
|
||||
|
||||
@@ -336,7 +336,8 @@ static const struct reg_sequence udphy_24m_refclk_cfg[] = {
|
||||
{0x0a64, 0xa8}, {0x1a3c, 0xd0},
|
||||
{0x1a44, 0xd0}, {0x1a48, 0x01},
|
||||
{0x1a4c, 0x0d}, {0x1a54, 0xe0},
|
||||
{0x1a5c, 0xe0}, {0x1a64, 0xa8}
|
||||
{0x1a5c, 0xe0}, {0x1a64, 0xa8},
|
||||
{0x00D4, 0x30}
|
||||
};
|
||||
|
||||
static const struct reg_sequence udphy_26m_refclk_cfg[] = {
|
||||
@@ -363,7 +364,7 @@ static const struct reg_sequence udphy_26m_refclk_cfg[] = {
|
||||
{0x0c30, 0x0E}, {0x0C48, 0x06},
|
||||
{0x1C30, 0x0E}, {0x1C48, 0x06},
|
||||
{0x028C, 0x18}, {0x0AF0, 0x00},
|
||||
{0x1AF0, 0x00}
|
||||
{0x1AF0, 0x00}, {0x00D4, 0x33}
|
||||
};
|
||||
|
||||
static const struct reg_sequence udphy_init_sequence[] = {
|
||||
@@ -398,8 +399,7 @@ static const struct reg_sequence udphy_init_sequence[] = {
|
||||
{0x0070, 0x7D}, {0x0074, 0x68},
|
||||
{0x0AF4, 0x1A}, {0x1AF4, 0x1A},
|
||||
{0x0440, 0x3F}, {0x10D4, 0x08},
|
||||
{0x20D4, 0x08}, {0x00D4, 0x30},
|
||||
{0x0024, 0x6e},
|
||||
{0x20D4, 0x08}, {0x0024, 0x6e}
|
||||
};
|
||||
|
||||
static inline int grfreg_write(struct regmap *base,
|
||||
|
||||
@@ -307,6 +307,7 @@ static void husb311_remove(struct i2c_client *client)
|
||||
struct husb311_chip *chip = i2c_get_clientdata(client);
|
||||
|
||||
device_init_wakeup(chip->dev, false);
|
||||
disable_irq(client->irq);
|
||||
cancel_delayed_work_sync(&chip->pm_work);
|
||||
tcpci_unregister_port(chip->tcpci);
|
||||
}
|
||||
@@ -317,6 +318,7 @@ static void husb311_shutdown(struct i2c_client *client)
|
||||
|
||||
husb311_set_vbus(chip->tcpci, &chip->data, false, false);
|
||||
|
||||
disable_irq(client->irq);
|
||||
cancel_delayed_work_sync(&chip->pm_work);
|
||||
tcpci_unregister_port(chip->tcpci);
|
||||
}
|
||||
|
||||
@@ -189,6 +189,7 @@ union rkvenc2_dual_core_handshake_id {
|
||||
#define RKVENC2_BIT_VAL_H264 0
|
||||
#define RKVENC2_BIT_VAL_H265 1
|
||||
#define RKVENC2_BIT_SLEN_FIFO BIT(30)
|
||||
#define RKVENC2_BIT_REC_FBC_DIS BIT(31)
|
||||
|
||||
#define RKVENC2_REG_SLI_SPLIT (56)
|
||||
#define RKVENC510_REG_SLI_SPLIT (60)
|
||||
@@ -270,6 +271,7 @@ struct rkvenc_task {
|
||||
/* jpege bitstream */
|
||||
struct mpp_dma_buffer *bs_buf;
|
||||
u32 offset_bs;
|
||||
u32 rec_fbc_dis;
|
||||
};
|
||||
|
||||
#define RKVENC_MAX_RCB_NUM (4)
|
||||
@@ -1112,6 +1114,16 @@ static void *rkvenc_alloc_task(struct mpp_session *session,
|
||||
task->clk_mode = CLK_MODE_NORMAL;
|
||||
rkvenc2_check_split_task(mpp, task);
|
||||
|
||||
/* check whether the current task is rec_fbc_dis = 1 */
|
||||
if (task->hw_info->vepu_type == RKVENC_VEPU_510) {
|
||||
if (task->reg[RKVENC_CLASS_PIC].valid) {
|
||||
u32 *reg = task->reg[RKVENC_CLASS_PIC].data;
|
||||
|
||||
task->rec_fbc_dis = reg[RKVENC510_REG_ENC_PIC] & RKVENC2_BIT_REC_FBC_DIS;
|
||||
reg[RKVENC510_REG_ENC_PIC] &= ~(RKVENC2_BIT_REC_FBC_DIS);
|
||||
}
|
||||
}
|
||||
|
||||
mpp_debug_leave();
|
||||
|
||||
return mpp_task;
|
||||
@@ -1423,6 +1435,9 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task)
|
||||
mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY);
|
||||
|
||||
if (hw->vepu_type == RKVENC_VEPU_510) {
|
||||
u32 rec_fbc_dis = task->rec_fbc_dis;
|
||||
u32 enc_pic = mpp_read(mpp, 0x300);
|
||||
|
||||
/*
|
||||
* Config dvbm special reg to expected that
|
||||
* vepu will hold when the encoding finish.
|
||||
@@ -1431,7 +1446,20 @@ static int rkvenc_run(struct mpp_dev *mpp, struct mpp_task *mpp_task)
|
||||
mpp_write(mpp, 0x308, BIT(18) | BIT(16));
|
||||
/* Enable slice done interrupt and slice fifo info. */
|
||||
mpp_write(mpp, 0x20, mpp_read(mpp, 0x20) | BIT(3));
|
||||
mpp_write(mpp, 0x300, mpp_read(mpp, 0x300) | BIT(30));
|
||||
/*
|
||||
* Fix bug:
|
||||
* Writing reg 0x300 BIT(31) may cause the DMA module to falsely
|
||||
* trigger writing data. It will case enc err.
|
||||
* So we need to disable the core clock before writing reg 0x300,
|
||||
* and re-enable the core clock after writing reg 0x300.
|
||||
*/
|
||||
if (rec_fbc_dis) {
|
||||
mpp_clk_safe_disable(enc->core_clk_info.clk);
|
||||
mpp_write(mpp, 0x300, enc_pic | BIT(30) | BIT(31));
|
||||
mpp_clk_safe_enable(enc->core_clk_info.clk);
|
||||
} else {
|
||||
mpp_write(mpp, 0x300, enc_pic | BIT(30));
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush the register before the start the device */
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
#define RKVPSS_CMD_MODULE_GET \
|
||||
_IOR('V', BASE_VIDIOC_PRIVATE + 54, struct rkvpss_module_sel)
|
||||
|
||||
#define RKVPSS_CMD_CHECKPARAMS \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 55, struct rkvpss_frame_cfg)
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/* struct rkvpss_mirror_flip
|
||||
|
||||
@@ -144,6 +144,10 @@ static const char * const es8323_diff_sel[] = {
|
||||
"Line 1", "Line 2"
|
||||
};
|
||||
|
||||
static const char * const es8323_adc_data_sel[] = {
|
||||
"Left Right", "Left Left", "Right Right", "Right Left"
|
||||
};
|
||||
|
||||
SOC_VALUE_ENUM_SINGLE_DECL(es8323_left_dac_enum, ES8323_ADCCONTROL2, 6, 3, es8323_pga_sell, es8323_line_values);
|
||||
SOC_VALUE_ENUM_SINGLE_DECL(es8323_right_dac_enum, ES8323_ADCCONTROL2, 4, 3, es8323_pga_selr, es8323_line_values);
|
||||
static SOC_ENUM_SINGLE_DECL(es8323_diff_enum, ES8323_ADCCONTROL3, 7, es8323_diff_sel);
|
||||
@@ -163,6 +167,7 @@ static const struct soc_enum es8323_enum[] = {
|
||||
SOC_ENUM_SINGLE(ES8323_ADCCONTROL6, 6, 4, adcpol_txt),
|
||||
SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 3, 3, es8323_mono_mux),
|
||||
SOC_ENUM_SINGLE(ES8323_ADCCONTROL3, 7, 2, es8323_diff_sel),
|
||||
SOC_ENUM_SINGLE(ES8323_ADCCONTROL4, 6, 4, es8323_adc_data_sel),
|
||||
};
|
||||
|
||||
static const DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 50, 1);
|
||||
@@ -208,6 +213,7 @@ static const struct snd_kcontrol_new es8323_snd_controls[] = {
|
||||
ES8323_DACCONTROL25, 0, 33, 0, out_tlv),
|
||||
SOC_DOUBLE_R_TLV("Output 2 Playback Volume", ES8323_DACCONTROL26,
|
||||
ES8323_DACCONTROL27, 0, 33, 0, out_tlv),
|
||||
SOC_ENUM("ADC Data Select", es8323_enum[11]),
|
||||
};
|
||||
|
||||
static const struct snd_kcontrol_new es8323_left_line_controls =
|
||||
|
||||
Reference in New Issue
Block a user