mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 21:07:02 +09:00
Merge commit '1ebca99c8f1e959c86646bc3cd72aa22dabb71b0'
* commit '1ebca99c8f1e959c86646bc3cd72aa22dabb71b0': media: i2c: maxim4c: support subscribe hot plug detect event drm/rockchip: dsi2: add support PSR for mipi command mode drm/rockchip: dsi2: set phy mode in .loader_protect helper drm/rockchip: dw-dp: support external bridge drm/rockchip: dw-dp: support fix stream and connector phy: rockchip: mipi-dcphy: optimize signal arm64: dts: rockchip: rk3576-iotest: enable edp sound for edp2dp board drm/rockchip: vop2: resolution bigger than 2560 need high performance drm/rockchip: vop2: recover vop aclk when enter psr and suspend drm/rockchip: vop2: udpate linear 10bit yuv format align role arm64: dts: rockchip: rk3588: enable emmc command queue arm64: dts: rockchip: rk3576: enable emmc command queue mmc: sdhci-of-dwcmshc: add command queue support for rockchip SOCs BACKPORT: mmc: sdhci-of-dwcmshc: Implement SDHCI CQE support BACKPORT: mmc: sdhci-of-dwcmshc: Add error handling in dwcmshc_resume UPSTREAM: mmc: cqhci: Add cqhci set_tran_desc() callback ASoC: rk817: Fix compile warning Change-Id: I1f33e6d6e1b5afed0a25d9bdc979ba78ae1f09bc
This commit is contained in:
@@ -37,6 +37,10 @@
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&edp_sound {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
status = "disabled";
|
||||
};
|
||||
@@ -66,6 +70,10 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
&sai6 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vp0 {
|
||||
assigned-clocks = <&cru DCLK_VP0_SRC>;
|
||||
assigned-clock-parents = <&cru PLL_VPLL>;
|
||||
|
||||
@@ -3993,6 +3993,7 @@
|
||||
<&cru SRST_T_EMMC>;
|
||||
reset-names = "core", "bus", "axi", "block", "timer";
|
||||
max-frequency = <200000000>;
|
||||
supports-cqe;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -5711,6 +5711,7 @@
|
||||
<&cru SRST_T_EMMC>;
|
||||
reset-names = "core", "bus", "axi", "block", "timer";
|
||||
max-frequency = <200000000>;
|
||||
supports-cqe;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -418,12 +418,14 @@ struct dw_dp_mst_enc {
|
||||
struct dw_dp_video video;
|
||||
struct dw_dp_audio *audio;
|
||||
struct device_node *port_node;
|
||||
struct drm_bridge *next_bridge;
|
||||
|
||||
DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
|
||||
|
||||
struct dw_dp_mst_conn *mst_conn;
|
||||
struct dw_dp *dp;
|
||||
int stream_id;
|
||||
int fix_port_num;
|
||||
bool active;
|
||||
};
|
||||
|
||||
@@ -488,6 +490,7 @@ struct dw_dp {
|
||||
bool is_loader_protect;
|
||||
bool support_mst;
|
||||
bool is_mst;
|
||||
bool is_fix_port;
|
||||
int mst_port_num;
|
||||
int active_mst_links;
|
||||
struct drm_dp_mst_topology_mgr mst_mgr;
|
||||
@@ -1306,6 +1309,7 @@ static int dw_dp_mst_info_dump(struct seq_file *s, void *data)
|
||||
struct dw_dp *dp = node->info_ent->data;
|
||||
struct dw_dp_mst_conn *mst_conn;
|
||||
struct drm_property_blob *path_blob;
|
||||
int i;
|
||||
|
||||
if (dp->mst_mgr.cbs) {
|
||||
drm_dp_mst_dump_topology(s, &dp->mst_mgr);
|
||||
@@ -1321,6 +1325,17 @@ static int dw_dp_mst_info_dump(struct seq_file *s, void *data)
|
||||
(char *)path_blob->data);
|
||||
}
|
||||
seq_puts(s, "\n");
|
||||
if (dp->is_fix_port) {
|
||||
seq_puts(s, "\n*** Fix port info ***\n");
|
||||
seq_puts(s, "stream id | port num\n");
|
||||
|
||||
for (i = 0; i < dp->mst_port_num; i++) {
|
||||
if (!dp->mst_enc[i].dp)
|
||||
continue;
|
||||
seq_printf(s, "%-16d %d\n", dp->mst_enc[i].stream_id,
|
||||
dp->mst_enc[i].fix_port_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -3250,14 +3265,39 @@ static const struct drm_connector_funcs dw_dp_mst_connector_funcs = {
|
||||
.early_unregister = dw_dp_mst_connector_early_unregister,
|
||||
};
|
||||
|
||||
static struct drm_bridge *dw_dp_mst_connector_get_bridge(struct dw_dp_mst_conn *mst_conn)
|
||||
{
|
||||
struct dw_dp *dp = mst_conn->dp;
|
||||
int i;
|
||||
|
||||
if (!dp->is_fix_port)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < dp->mst_port_num; i++)
|
||||
if (dp->mst_enc[i].fix_port_num == mst_conn->port->port_num)
|
||||
return dp->mst_enc[i].next_bridge;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int dw_dp_mst_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct dw_dp_mst_conn *mst_conn = container_of(connector,
|
||||
struct dw_dp_mst_conn, connector);
|
||||
struct dw_dp *dp = mst_conn->dp;
|
||||
struct drm_bridge *bridge;
|
||||
struct edid *edid;
|
||||
int num_modes = 0;
|
||||
|
||||
if (dp->is_fix_port) {
|
||||
bridge = dw_dp_mst_connector_get_bridge(mst_conn);
|
||||
if (bridge) {
|
||||
num_modes = drm_bridge_get_modes(bridge, connector);
|
||||
if (num_modes)
|
||||
return num_modes;
|
||||
}
|
||||
}
|
||||
|
||||
edid = drm_dp_mst_get_edid(connector, &dp->mst_mgr, mst_conn->port);
|
||||
if (edid) {
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
@@ -3924,6 +3964,8 @@ dw_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_p
|
||||
for (i = 0; i < dp->mst_port_num; i++) {
|
||||
if (!of_device_is_available(dp->mst_enc[i].port_node))
|
||||
continue;
|
||||
if (dp->is_fix_port && dp->mst_enc[i].fix_port_num != port->port_num)
|
||||
continue;
|
||||
ret = drm_connector_attach_encoder(&mst_conn->connector, &dp->mst_enc[i].encoder);
|
||||
if (ret)
|
||||
goto err;
|
||||
@@ -3979,6 +4021,57 @@ dw_dp_create_fake_mst_encoders(struct dw_dp *dp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dw_dp_mst_get_fix_port(struct dw_dp *dp)
|
||||
{
|
||||
char *prop_name = "rockchip,mst-fixed-ports";
|
||||
int elem_len, ret, i;
|
||||
int elem_data[DPTX_MAX_STREAMS];
|
||||
|
||||
if (!device_property_present(dp->dev, prop_name))
|
||||
return 0;
|
||||
|
||||
elem_len = device_property_count_u32(dp->dev, prop_name);
|
||||
if (dp->mst_port_num != elem_len)
|
||||
return -EINVAL;
|
||||
|
||||
ret = device_property_read_u32_array(dp->dev, prop_name, elem_data, elem_len);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
dp->is_fix_port = true;
|
||||
|
||||
for (i = 0; i < dp->mst_port_num; i++)
|
||||
dp->mst_enc[i].fix_port_num = elem_data[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_dp_mst_find_ext_bridges(struct dw_dp *dp)
|
||||
{
|
||||
struct dw_dp_mst_enc *mst_enc;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < dp->mst_port_num; i++) {
|
||||
mst_enc = &dp->mst_enc[i];
|
||||
if (!of_device_is_available(dp->mst_enc[i].port_node))
|
||||
continue;
|
||||
ret = drm_of_find_panel_or_bridge(mst_enc->port_node, 2, -1, NULL,
|
||||
&mst_enc->next_bridge);
|
||||
if (ret < 0 && ret != -ENODEV)
|
||||
return ret;
|
||||
|
||||
if (mst_enc->next_bridge) {
|
||||
ret = drm_bridge_attach(&mst_enc->encoder, mst_enc->next_bridge, NULL, 0);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dp->dev, "failed to attach next bridge: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dw_dp_mst_encoder_init(struct dw_dp *dp, int conn_base_id)
|
||||
{
|
||||
int ret;
|
||||
@@ -3989,6 +4082,13 @@ static int dw_dp_mst_encoder_init(struct dw_dp *dp, int conn_base_id)
|
||||
INIT_LIST_HEAD(&dp->mst_conn_list);
|
||||
dp->mst_mgr.cbs = &mst_cbs;
|
||||
dw_dp_create_fake_mst_encoders(dp);
|
||||
ret = dw_dp_mst_get_fix_port(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = dw_dp_mst_find_ext_bridges(dp);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = drm_dp_mst_topology_mgr_init(&dp->mst_mgr, dp->encoder.dev,
|
||||
&dp->aux, 16, dp->mst_port_num, conn_base_id);
|
||||
if (ret)
|
||||
@@ -4025,7 +4125,9 @@ static int dw_dp_connector_init(struct dw_dp *dp)
|
||||
|
||||
drm_connector_attach_encoder(connector, bridge->encoder);
|
||||
|
||||
dw_dp_mst_encoder_init(dp, connector->base.id);
|
||||
ret = dw_dp_mst_encoder_init(dp, connector->base.id);
|
||||
if (ret)
|
||||
return ret;
|
||||
prop = drm_property_create_enum(connector->dev, 0, RK_IF_PROP_COLOR_DEPTH,
|
||||
color_depth_enum_list,
|
||||
ARRAY_SIZE(color_depth_enum_list));
|
||||
|
||||
@@ -282,6 +282,9 @@ struct dw_mipi_dsi2 {
|
||||
bool dual_connector_split;
|
||||
bool left_display;
|
||||
u32 split_area;
|
||||
|
||||
bool support_psr;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
static inline struct dw_mipi_dsi2 *host_to_dsi2(struct mipi_dsi_host *host)
|
||||
@@ -318,6 +321,14 @@ static void grf_field_write(struct dw_mipi_dsi2 *dsi2, enum grf_reg_fields index
|
||||
regmap_write(dsi2->grf, reg, (val << lsb) | (GENMASK(msb, lsb) << 16));
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi2_is_cmd_mode(struct dw_mipi_dsi2 *dsi2)
|
||||
{
|
||||
if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int cri_fifos_wait_avail(struct dw_mipi_dsi2 *dsi2)
|
||||
{
|
||||
u32 sts, mask;
|
||||
@@ -432,53 +443,95 @@ static void dw_mipi_dsi2_set_cmd_mode(struct dw_mipi_dsi2 *dsi2)
|
||||
mode, mode & COMMAND_MODE,
|
||||
1000, MODE_STATUS_TIMEOUT_US);
|
||||
if (ret < 0)
|
||||
dev_err(dsi2->dev, "failed to enter data stream mode\n");
|
||||
dev_err(dsi2->dev, "failed to enter command mode\n");
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_disable(struct dw_mipi_dsi2 *dsi2)
|
||||
{
|
||||
if (!dsi2->enabled)
|
||||
goto out;
|
||||
|
||||
regmap_write(dsi2->regmap, DSI2_IPI_PIX_PKT_CFG, 0);
|
||||
dw_mipi_dsi2_set_cmd_mode(dsi2);
|
||||
|
||||
out:
|
||||
if (dsi2->slave)
|
||||
dw_mipi_dsi2_disable(dsi2->slave);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_post_disable(struct dw_mipi_dsi2 *dsi2)
|
||||
{
|
||||
if (!dsi2->enabled)
|
||||
goto out;
|
||||
|
||||
dw_mipi_dsi2_irq_enable(dsi2, 0);
|
||||
regmap_write(dsi2->regmap, DSI2_PWR_UP, RESET);
|
||||
mipi_dcphy_power_off(dsi2);
|
||||
pm_runtime_put(dsi2->dev);
|
||||
|
||||
out:
|
||||
if (dsi2->slave)
|
||||
dw_mipi_dsi2_post_disable(dsi2->slave);
|
||||
}
|
||||
|
||||
static struct drm_crtc *dw_mipi_dsi2_get_new_crtc(struct dw_mipi_dsi2 *dsi2,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_encoder *encoder = &dsi2->encoder;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state, encoder);
|
||||
if (!connector)
|
||||
return NULL;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
if (!conn_state)
|
||||
return NULL;
|
||||
|
||||
return conn_state->crtc;
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi2_encoder_atomic_disable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder);
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
|
||||
struct rockchip_crtc_state *s = to_rockchip_crtc_state(encoder->crtc->state);
|
||||
struct drm_crtc *new_crtc;
|
||||
struct drm_crtc_state *new_crtc_state = NULL;
|
||||
|
||||
if (dsi2->panel)
|
||||
drm_panel_disable(dsi2->panel);
|
||||
new_crtc = dw_mipi_dsi2_get_new_crtc(dsi2, old_state);
|
||||
if (new_crtc)
|
||||
new_crtc_state = drm_atomic_get_new_crtc_state(old_state, new_crtc);
|
||||
|
||||
if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO))
|
||||
if (new_crtc_state && new_crtc_state->self_refresh_active)
|
||||
dev_dbg(dsi2->dev, "%s:%d: psr entry\n", __func__, __LINE__);
|
||||
|
||||
if (!new_crtc_state || !new_crtc_state->self_refresh_active) {
|
||||
if (dsi2->panel)
|
||||
drm_panel_disable(dsi2->panel);
|
||||
}
|
||||
|
||||
if (dw_mipi_dsi2_is_cmd_mode(dsi2))
|
||||
rockchip_drm_crtc_standby(encoder->crtc, 1);
|
||||
|
||||
dw_mipi_dsi2_disable(dsi2);
|
||||
|
||||
if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO))
|
||||
if (dw_mipi_dsi2_is_cmd_mode(dsi2))
|
||||
rockchip_drm_crtc_standby(encoder->crtc, 0);
|
||||
|
||||
if (dsi2->panel)
|
||||
drm_panel_unprepare(dsi2->panel);
|
||||
if (!new_crtc_state || !new_crtc_state->self_refresh_active) {
|
||||
if (dsi2->panel)
|
||||
drm_panel_unprepare(dsi2->panel);
|
||||
}
|
||||
|
||||
dw_mipi_dsi2_post_disable(dsi2);
|
||||
|
||||
if (!crtc->state->active_changed)
|
||||
dsi2->enabled = false;
|
||||
if (dsi2->slave)
|
||||
dsi2->slave->enabled = false;
|
||||
|
||||
if (!encoder->crtc->state->active_changed)
|
||||
return;
|
||||
|
||||
if (dsi2->slave)
|
||||
@@ -749,7 +802,7 @@ static void dw_mipi_dsi2_ipi_set(struct dw_mipi_dsi2 *dsi2)
|
||||
* if the controller is intended to operate in data stream mode,
|
||||
* no more steps are required.
|
||||
*/
|
||||
if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO))
|
||||
if (dw_mipi_dsi2_is_cmd_mode(dsi2))
|
||||
return;
|
||||
|
||||
vact = mode->crtc_vdisplay;
|
||||
@@ -811,6 +864,9 @@ dw_mipi_dsi2_work_mode(struct dw_mipi_dsi2 *dsi2, u32 mode)
|
||||
|
||||
static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2)
|
||||
{
|
||||
if (dsi2->enabled)
|
||||
goto out;
|
||||
|
||||
pm_runtime_get_sync(dsi2->dev);
|
||||
|
||||
dw_mipi_dsi2_host_softrst(dsi2);
|
||||
@@ -827,6 +883,7 @@ static void dw_mipi_dsi2_pre_enable(struct dw_mipi_dsi2 *dsi2)
|
||||
regmap_write(dsi2->regmap, DSI2_PWR_UP, POWER_UP);
|
||||
dw_mipi_dsi2_set_cmd_mode(dsi2);
|
||||
|
||||
out:
|
||||
if (dsi2->slave)
|
||||
dw_mipi_dsi2_pre_enable(dsi2->slave);
|
||||
}
|
||||
@@ -853,6 +910,9 @@ static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2)
|
||||
u32 mode;
|
||||
int ret;
|
||||
|
||||
if (dsi2->enabled)
|
||||
goto out;
|
||||
|
||||
dw_mipi_dsi2_clk_management(dsi2);
|
||||
dw_mipi_dsi2_ipi_set(dsi2);
|
||||
|
||||
@@ -870,6 +930,7 @@ static void dw_mipi_dsi2_enable(struct dw_mipi_dsi2 *dsi2)
|
||||
else
|
||||
dw_mipi_dsi2_set_data_stream_mode(dsi2);
|
||||
|
||||
out:
|
||||
if (dsi2->slave)
|
||||
dw_mipi_dsi2_enable(dsi2->slave);
|
||||
}
|
||||
@@ -943,8 +1004,19 @@ static void dw_mipi_dsi2_encoder_atomic_enable(struct drm_encoder *encoder,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = encoder_to_dsi2(encoder);
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *old_crtc_state = NULL;
|
||||
int ret;
|
||||
|
||||
crtc = dw_mipi_dsi2_get_new_crtc(dsi2, state);
|
||||
if (crtc)
|
||||
old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
|
||||
|
||||
if (old_crtc_state && old_crtc_state->self_refresh_active) {
|
||||
rockchip_drm_crtc_standby(encoder->crtc, 1);
|
||||
dev_dbg(dsi2->dev, "%s:%d: psr exit\n", __func__, __LINE__);
|
||||
}
|
||||
|
||||
ret = dw_mipi_dsi2_encoder_mode_set(dsi2, state);
|
||||
if (ret) {
|
||||
dev_err(dsi2->dev, "failed to set dsi2 mode\n");
|
||||
@@ -961,13 +1033,24 @@ static void dw_mipi_dsi2_encoder_atomic_enable(struct drm_encoder *encoder,
|
||||
|
||||
dw_mipi_dsi2_pre_enable(dsi2);
|
||||
|
||||
if (dsi2->panel)
|
||||
drm_panel_prepare(dsi2->panel);
|
||||
if (!(old_crtc_state && old_crtc_state->self_refresh_active)) {
|
||||
if (dsi2->panel)
|
||||
drm_panel_prepare(dsi2->panel);
|
||||
}
|
||||
|
||||
dw_mipi_dsi2_enable(dsi2);
|
||||
|
||||
if (dsi2->panel)
|
||||
drm_panel_enable(dsi2->panel);
|
||||
if (old_crtc_state && old_crtc_state->self_refresh_active)
|
||||
rockchip_drm_crtc_standby(encoder->crtc, 0);
|
||||
|
||||
dsi2->enabled = true;
|
||||
if (dsi2->slave)
|
||||
dsi2->slave->enabled = true;
|
||||
|
||||
if (!(old_crtc_state && old_crtc_state->self_refresh_active)) {
|
||||
if (dsi2->panel)
|
||||
drm_panel_enable(dsi2->panel);
|
||||
}
|
||||
|
||||
DRM_DEV_INFO(dsi2->dev, "final DSI-Link bandwidth: %u x %d %s\n",
|
||||
dsi2->lane_hs_rate,
|
||||
@@ -1014,7 +1097,7 @@ dw_mipi_dsi2_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
s->color_encoding = DRM_COLOR_YCBCR_BT709;
|
||||
s->color_range = DRM_COLOR_YCBCR_FULL_RANGE;
|
||||
|
||||
if (!(dsi2->mode_flags & MIPI_DSI_MODE_VIDEO)) {
|
||||
if (dw_mipi_dsi2_is_cmd_mode(dsi2)) {
|
||||
s->output_flags |= ROCKCHIP_OUTPUT_MIPI_DS_MODE;
|
||||
s->soft_te = dsi2->te_gpio ? true : false;
|
||||
s->hold_mode = dsi2->disable_hold_mode ? false : true;
|
||||
@@ -1057,18 +1140,26 @@ dw_mipi_dsi2_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
|
||||
static void dw_mipi_dsi2_loader_protect(struct dw_mipi_dsi2 *dsi2, bool on)
|
||||
{
|
||||
if (dsi2->dcphy)
|
||||
if (!dsi2->c_option)
|
||||
phy_set_mode(dsi2->dcphy, PHY_MODE_MIPI_DPHY);
|
||||
|
||||
if (on) {
|
||||
pm_runtime_get_sync(dsi2->dev);
|
||||
phy_init(dsi2->dcphy);
|
||||
dsi2->phy_enabled = true;
|
||||
if (dsi2->dcphy)
|
||||
dsi2->dcphy->power_count++;
|
||||
|
||||
dsi2->enabled = true;
|
||||
} else {
|
||||
pm_runtime_put(dsi2->dev);
|
||||
phy_exit(dsi2->dcphy);
|
||||
dsi2->phy_enabled = false;
|
||||
if (dsi2->dcphy)
|
||||
dsi2->dcphy->power_count--;
|
||||
|
||||
dsi2->enabled = false;
|
||||
}
|
||||
|
||||
if (dsi2->slave)
|
||||
@@ -1152,9 +1243,36 @@ dw_mipi_dsi2_connector_mode_valid(struct drm_connector *connector,
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static int dw_mipi_dsi2_connector_atomic_check(struct drm_connector *connector,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
struct dw_mipi_dsi2 *dsi2 = con_to_dsi2(connector);
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
conn_state = drm_atomic_get_new_connector_state(state, connector);
|
||||
if (WARN_ON(!conn_state))
|
||||
return -ENODEV;
|
||||
|
||||
conn_state->self_refresh_aware = dsi2->support_psr && dw_mipi_dsi2_is_cmd_mode(dsi2);
|
||||
|
||||
if (!conn_state->crtc)
|
||||
return 0;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);
|
||||
if (!crtc_state)
|
||||
return 0;
|
||||
|
||||
if (crtc_state->self_refresh_active && !dw_mipi_dsi2_is_cmd_mode(dsi2))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_connector_helper_funcs dw_mipi_dsi2_connector_helper_funcs = {
|
||||
.get_modes = dw_mipi_dsi2_connector_get_modes,
|
||||
.mode_valid = dw_mipi_dsi2_connector_mode_valid,
|
||||
.atomic_check = dw_mipi_dsi2_connector_atomic_check,
|
||||
};
|
||||
|
||||
static enum drm_connector_status
|
||||
@@ -1257,6 +1375,7 @@ static int dw_mipi_dsi2_dual_channel_probe(struct dw_mipi_dsi2 *dsi2)
|
||||
dsi2->slave->channel = dsi2->channel;
|
||||
dsi2->slave->format = dsi2->format;
|
||||
dsi2->slave->mode_flags = dsi2->mode_flags;
|
||||
dsi2->slave->support_psr = dsi2->support_psr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1668,6 +1787,7 @@ static ssize_t dw_mipi_dsi2_transfer(struct dw_mipi_dsi2 *dsi2,
|
||||
u32 val;
|
||||
u32 mode;
|
||||
|
||||
pm_runtime_get_sync(dsi2->dev);
|
||||
dw_mipi_dsi2_clk_management(dsi2);
|
||||
regmap_update_bits(dsi2->regmap, DSI2_DSI_VID_TX_CFG, LPDT_DISPLAY_CMD_EN,
|
||||
msg->flags & MIPI_DSI_MSG_USE_LPM ? LPDT_DISPLAY_CMD_EN : 0);
|
||||
@@ -1676,12 +1796,12 @@ static ssize_t dw_mipi_dsi2_transfer(struct dw_mipi_dsi2 *dsi2,
|
||||
ret = mipi_dsi_create_packet(&packet, msg);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dsi2->dev, "failed to create packet: %d\n", ret);
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = cri_fifos_wait_avail(dsi2);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
/* Send payload */
|
||||
while (DIV_ROUND_UP(packet.payload_length, 4)) {
|
||||
@@ -1708,18 +1828,24 @@ static ssize_t dw_mipi_dsi2_transfer(struct dw_mipi_dsi2 *dsi2,
|
||||
|
||||
ret = cri_fifos_wait_avail(dsi2);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err;
|
||||
|
||||
if (msg->rx_len) {
|
||||
ret = dw_mipi_dsi2_read_from_fifo(dsi2, msg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pm_runtime_put(dsi2->dev);
|
||||
|
||||
if (dsi2->slave)
|
||||
dw_mipi_dsi2_transfer(dsi2->slave, msg);
|
||||
|
||||
return msg->tx_len;
|
||||
|
||||
err:
|
||||
pm_runtime_put(dsi2->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t dw_mipi_dsi2_host_transfer(struct mipi_dsi_host *host,
|
||||
@@ -1774,6 +1900,12 @@ static int dw_mipi_dsi2_probe(struct platform_device *pdev)
|
||||
if (device_property_read_u32(dev, "split-area", &dsi2->split_area))
|
||||
dsi2->split_area = 0;
|
||||
|
||||
dsi2->support_psr = device_property_read_bool(dev, "support-psr");
|
||||
if (dsi2->support_psr && dsi2->auto_calc_mode) {
|
||||
dsi2->auto_calc_mode = false;
|
||||
dev_info(dev, "disable auto-calculation-mode in PSR mode\n");
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(regs))
|
||||
|
||||
@@ -200,7 +200,8 @@ static int rockchip_drm_aclk_adjust(struct drm_device *dev,
|
||||
funcs = priv->crtc_funcs[drm_crtc_index(crtc)];
|
||||
if (funcs && funcs->set_aclk) {
|
||||
if (vop_bw_info->plane_num_4k || crtc_num > 1 ||
|
||||
crtc->state->adjusted_mode.crtc_hdisplay > 4096) {
|
||||
crtc->state->adjusted_mode.crtc_hdisplay > 2560 ||
|
||||
crtc->state->adjusted_mode.crtc_vdisplay > 2560) {
|
||||
funcs->set_aclk(crtc, ROCKCHIP_VOP_ACLK_ADVANCED_MODE);
|
||||
priv->aclk_adjust_frame_num = 2;
|
||||
} else {
|
||||
|
||||
@@ -28,11 +28,12 @@
|
||||
#define VOP2_MINOR(version) (((version) >> 16) & 0xff)
|
||||
#define VOP2_BUILD(version) ((version) & 0xffff)
|
||||
|
||||
/* The new SOC VOP version is bigger than the old */
|
||||
#define VOP_VERSION_RK3568 VOP2_VERSION(0x40, 0x15, 0x8023)
|
||||
#define VOP_VERSION_RK3588 VOP2_VERSION(0x40, 0x17, 0x6786)
|
||||
#define VOP_VERSION_RK3528 VOP2_VERSION(0x50, 0x17, 0x1263)
|
||||
#define VOP_VERSION_RK3562 VOP2_VERSION(0x50, 0x17, 0x4350)
|
||||
#define VOP_VERSION_RK3568 VOP2_VERSION(0x40, 0x15, 0x8023)
|
||||
#define VOP_VERSION_RK3576 VOP2_VERSION(0x50, 0x19, 0x9765)
|
||||
#define VOP_VERSION_RK3588 VOP2_VERSION(0x40, 0x17, 0x6786)
|
||||
|
||||
/* register one connector */
|
||||
#define ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE BIT(0)
|
||||
|
||||
@@ -4849,6 +4849,17 @@ static void vop2_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Usperspace not commit new frame for long time will triggle driver enter
|
||||
* psr mode, If userspace directly close display at next time and without
|
||||
* any new frame commit, driver will not exit psr, at this case we need to
|
||||
* recover aclk here.
|
||||
*/
|
||||
if (vop2->aclk_rate_reset) {
|
||||
clk_set_rate(vop2->aclk, vop2->aclk_current_freq);
|
||||
vop2->aclk_rate_reset = false;
|
||||
}
|
||||
|
||||
vop2_lock(vop2);
|
||||
DRM_DEV_INFO(vop2->dev, "Crtc atomic disable vp%d\n", vp->id);
|
||||
VOP_MODULE_SET(vop2, vp, almost_full_or_en, 0);
|
||||
@@ -5914,9 +5925,18 @@ static void vop2_win_atomic_update(struct vop2_win *win, struct drm_rect *src, s
|
||||
}
|
||||
}
|
||||
|
||||
if (is_linear_10bit_yuv(fb->format->format) && actual_w & 0x3) {
|
||||
DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when is linear 10 bit yuv format\n", vp->id, win->name, actual_w);
|
||||
actual_w = ALIGN_DOWN(actual_w, 4);
|
||||
/*
|
||||
* At RK356X/RK3588/RK3562/RK3528 linear 10bit yuv format actual_w should align as 4 pixel,
|
||||
* from RK3576 linear 10bit yuv format actual_w should align as 2 pixel.
|
||||
*/
|
||||
if (is_linear_10bit_yuv(fb->format->format)) {
|
||||
if (vop2->version < VOP_VERSION_RK3576 && actual_w & 0x3) {
|
||||
DRM_WARN("vp%d %s actual_w[%d] should align as 4 pixel when is linear 10 bit yuv format\n", vp->id, win->name, actual_w);
|
||||
actual_w = ALIGN_DOWN(actual_w, 4);
|
||||
} else if (vop2->version >= VOP_VERSION_RK3576 && actual_w & 0x1) {
|
||||
DRM_WARN("vp%d %s actual_w[%d] should align as 2 pixel when is linear 10 bit yuv format\n", vp->id, win->name, actual_w);
|
||||
actual_w = ALIGN_DOWN(actual_w, 2);
|
||||
}
|
||||
}
|
||||
|
||||
act_info = (actual_h - 1) << 16 | ((actual_w - 1) & 0xffff);
|
||||
@@ -7700,7 +7720,7 @@ static size_t vop2_crtc_bandwidth(struct drm_crtc *crtc,
|
||||
|
||||
act_w = drm_rect_width(&pstate->src) >> 16;
|
||||
act_h = drm_rect_height(&pstate->src) >> 16;
|
||||
if (pstate->fb->format->is_yuv && (act_w >= 3840 || act_h >= 3840))
|
||||
if (pstate->fb->format->is_yuv && (act_w > 2560 || act_h > 2560))
|
||||
vop_bw_info->plane_num_4k++;
|
||||
|
||||
bpp = rockchip_drm_get_bpp(pstate->fb->format);
|
||||
|
||||
@@ -136,6 +136,20 @@ static int maxim4c_check_local_chipid(maxim4c_t *maxim4c)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void maxim4c_hot_plug_event_report(maxim4c_t *maxim4c, int data)
|
||||
{
|
||||
struct v4l2_subdev *sd = &maxim4c->subdev;
|
||||
struct device *dev = &maxim4c->client->dev;
|
||||
struct v4l2_event evt_hot_plug = {
|
||||
.type = V4L2_EVENT_HOT_PLUG,
|
||||
.u.data[0] = data,
|
||||
};
|
||||
|
||||
dev_dbg(dev, "%s data %d\n", __func__, data);
|
||||
|
||||
v4l2_event_queue(sd->devnode, &evt_hot_plug);
|
||||
}
|
||||
|
||||
static irqreturn_t maxim4c_hot_plug_detect_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
maxim4c_t *maxim4c = dev_id;
|
||||
@@ -223,6 +237,7 @@ static void maxim4c_hot_plug_state_check_work(struct work_struct *work)
|
||||
dev_dbg(dev, "lock state: current = 0x%02x, last = 0x%02x\n",
|
||||
curr_lock_state, last_lock_state);
|
||||
|
||||
maxim4c_hot_plug_event_report(maxim4c, curr_lock_state);
|
||||
maxim4c->link_lock_state = curr_lock_state;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-mux.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
|
||||
@@ -32,6 +34,10 @@
|
||||
/* power supply numbers */
|
||||
#define MAXIM4C_NUM_SUPPLIES 2
|
||||
|
||||
/* Private v4l2 event */
|
||||
#define V4L2_EVENT_HOT_PLUG \
|
||||
(V4L2_EVENT_PRIVATE_START + 0x10)
|
||||
|
||||
enum {
|
||||
MAXIM4C_HOT_PLUG_OUT = 0,
|
||||
MAXIM4C_HOT_PLUG_IN,
|
||||
|
||||
@@ -779,10 +779,7 @@ static int maxim4c_get_fmt(struct v4l2_subdev *sd,
|
||||
fmt->format.height = mode->height;
|
||||
fmt->format.code = mode->bus_fmt;
|
||||
fmt->format.field = V4L2_FIELD_NONE;
|
||||
if (fmt->pad < PAD_MAX && fmt->pad >= PAD0)
|
||||
fmt->reserved[0] = mode->vc[fmt->pad];
|
||||
else
|
||||
fmt->reserved[0] = mode->vc[PAD0];
|
||||
fmt->reserved[0] = mode->vc[fmt->pad];
|
||||
}
|
||||
mutex_unlock(&maxim4c->mutex);
|
||||
|
||||
@@ -925,6 +922,17 @@ static int maxim4c_g_mbus_config(struct v4l2_subdev *sd,
|
||||
}
|
||||
#endif /* LINUX_VERSION_CODE */
|
||||
|
||||
static int maxim4c_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
|
||||
struct v4l2_event_subscription *sub)
|
||||
{
|
||||
switch (sub->type) {
|
||||
case V4L2_EVENT_HOT_PLUG:
|
||||
return v4l2_event_subscribe(fh, sub, 0, NULL);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
|
||||
static const struct v4l2_subdev_internal_ops maxim4c_internal_ops = {
|
||||
.open = maxim4c_open,
|
||||
@@ -933,6 +941,8 @@ static const struct v4l2_subdev_internal_ops maxim4c_internal_ops = {
|
||||
|
||||
static const struct v4l2_subdev_core_ops maxim4c_core_ops = {
|
||||
.s_power = maxim4c_s_power,
|
||||
.subscribe_event = maxim4c_subscribe_event,
|
||||
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
|
||||
.ioctl = maxim4c_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl32 = maxim4c_compat_ioctl32,
|
||||
@@ -1062,7 +1072,7 @@ int maxim4c_v4l2_subdev_init(maxim4c_t *maxim4c)
|
||||
|
||||
#ifdef CONFIG_VIDEO_V4L2_SUBDEV_API
|
||||
sd->internal_ops = &maxim4c_internal_ops;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
|
||||
@@ -225,6 +225,7 @@ config MMC_SDHCI_OF_DWCMSHC
|
||||
depends on OF
|
||||
depends on COMMON_CLK
|
||||
select MMC_HSQ
|
||||
select MMC_CQHCI
|
||||
help
|
||||
This selects Synopsys DesignWare Cores Mobile Storage Controller
|
||||
support.
|
||||
|
||||
@@ -474,8 +474,8 @@ static int cqhci_dma_map(struct mmc_host *host, struct mmc_request *mrq)
|
||||
return sg_count;
|
||||
}
|
||||
|
||||
static void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end,
|
||||
bool dma64)
|
||||
void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end,
|
||||
bool dma64)
|
||||
{
|
||||
__le32 *attr = (__le32 __force *)desc;
|
||||
|
||||
@@ -495,6 +495,7 @@ static void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end,
|
||||
dataddr[0] = cpu_to_le32(addr);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(cqhci_set_tran_desc);
|
||||
|
||||
static int cqhci_prep_tran_desc(struct mmc_request *mrq,
|
||||
struct cqhci_host *cq_host, int tag)
|
||||
@@ -522,7 +523,11 @@ static int cqhci_prep_tran_desc(struct mmc_request *mrq,
|
||||
|
||||
if ((i+1) == sg_count)
|
||||
end = true;
|
||||
cqhci_set_tran_desc(desc, addr, len, end, dma64);
|
||||
if (cq_host->ops->set_tran_desc)
|
||||
cq_host->ops->set_tran_desc(cq_host, &desc, addr, len, end, dma64);
|
||||
else
|
||||
cqhci_set_tran_desc(desc, addr, len, end, dma64);
|
||||
|
||||
desc += cq_host->trans_desc_len;
|
||||
}
|
||||
|
||||
|
||||
@@ -290,6 +290,9 @@ struct cqhci_host_ops {
|
||||
int (*program_key)(struct cqhci_host *cq_host,
|
||||
const union cqhci_crypto_cfg_entry *cfg, int slot);
|
||||
#endif
|
||||
void (*set_tran_desc)(struct cqhci_host *cq_host, u8 **desc,
|
||||
dma_addr_t addr, int len, bool end, bool dma64);
|
||||
|
||||
};
|
||||
|
||||
static inline void cqhci_writel(struct cqhci_host *host, u32 val, int reg)
|
||||
@@ -315,6 +318,7 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error,
|
||||
int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64);
|
||||
struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev);
|
||||
int cqhci_deactivate(struct mmc_host *mmc);
|
||||
void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end, bool dma64);
|
||||
static inline int cqhci_suspend(struct mmc_host *mmc)
|
||||
{
|
||||
return cqhci_deactivate(mmc);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
#include "sdhci-pltfm.h"
|
||||
#include "mmc_hsq.h"
|
||||
#include "cqhci.h"
|
||||
#include "sdhci-cqhci.h"
|
||||
|
||||
#define SDHCI_DWCMSHC_ARG2_STUFF GENMASK(31, 16)
|
||||
|
||||
@@ -38,12 +40,17 @@
|
||||
#define DWCMSHC_ENHANCED_STROBE BIT(8)
|
||||
#define DWCMSHC_EMMC_ATCTRL 0x40
|
||||
|
||||
/* DWC IP vendor area 2 pointer */
|
||||
#define DWCMSHC_P_VENDOR_AREA2 0xea
|
||||
|
||||
/* Rockchip specific Registers */
|
||||
#define DWCMSHC_EMMC_DLL_CTRL 0x800
|
||||
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
|
||||
#define DWCMSHC_EMMC_DLL_TXCLK 0x808
|
||||
#define DWCMSHC_EMMC_DLL_STRBIN 0x80c
|
||||
#define DECMSHC_EMMC_DLL_CMDOUT 0x810
|
||||
#define DECMSHC_EMMC_MISC_CON 0x81C
|
||||
#define MISC_INTCLK_EN BIT(1)
|
||||
#define DWCMSHC_EMMC_DLL_STATUS0 0x840
|
||||
#define DWCMSHC_EMMC_DLL_STATUS1 0x844
|
||||
#define DWCMSHC_EMMC_DLL_START BIT(0)
|
||||
@@ -83,6 +90,10 @@
|
||||
#define BOUNDARY_OK(addr, len) \
|
||||
((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
|
||||
|
||||
#define DWCMSHC_SDHCI_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \
|
||||
SDHCI_TRNS_BLK_CNT_EN | \
|
||||
SDHCI_TRNS_DMA)
|
||||
|
||||
enum dwcmshc_rk_type {
|
||||
DWCMSHC_RK3568,
|
||||
DWCMSHC_RK3588,
|
||||
@@ -117,7 +128,9 @@ struct rk35xx_priv {
|
||||
|
||||
struct dwcmshc_priv {
|
||||
struct clk *bus_clk;
|
||||
int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
|
||||
int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA1 reg */
|
||||
int vendor_specific_area2; /* P_VENDOR_SPECIFIC_AREA2 reg */
|
||||
|
||||
void *priv; /* pointer to SoC private stuff */
|
||||
};
|
||||
|
||||
@@ -230,6 +243,145 @@ static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
|
||||
sdhci_writel(host, vendor, reg);
|
||||
}
|
||||
|
||||
static int dwcmshc_execute_tuning(struct mmc_host *mmc, u32 opcode)
|
||||
{
|
||||
int err = sdhci_execute_tuning(mmc, opcode);
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Tuning can leave the IP in an active state (Buffer Read Enable bit
|
||||
* set) which prevents the entry to low power states (i.e. S0i3). Data
|
||||
* reset will clear it.
|
||||
*/
|
||||
sdhci_reset(host, SDHCI_RESET_DATA);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 dwcmshc_cqe_irq_handler(struct sdhci_host *host, u32 intmask)
|
||||
{
|
||||
int cmd_error = 0;
|
||||
int data_error = 0;
|
||||
|
||||
if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
|
||||
return intmask;
|
||||
|
||||
cqhci_irq(host->mmc, intmask, cmd_error, data_error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwcmshc_sdhci_cqe_enable(struct mmc_host *mmc)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
u8 ctrl;
|
||||
|
||||
sdhci_writew(host, DWCMSHC_SDHCI_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);
|
||||
|
||||
sdhci_cqe_enable(mmc);
|
||||
|
||||
/*
|
||||
* The "DesignWare Cores Mobile Storage Host Controller
|
||||
* DWC_mshc / DWC_mshc_lite Databook" says:
|
||||
* when Host Version 4 Enable" is 1 in Host Control 2 register,
|
||||
* SDHCI_CTRL_ADMA32 bit means ADMA2 is selected.
|
||||
* Selection of 32-bit/64-bit System Addressing:
|
||||
* either 32-bit or 64-bit system addressing is selected by
|
||||
* 64-bit Addressing bit in Host Control 2 register.
|
||||
*
|
||||
* On the other hand the "DesignWare Cores Mobile Storage Host
|
||||
* Controller DWC_mshc / DWC_mshc_lite User Guide" says, that we have to
|
||||
* set DMA_SEL to ADMA2 _only_ mode in the Host Control 2 register.
|
||||
*/
|
||||
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
||||
ctrl &= ~SDHCI_CTRL_DMA_MASK;
|
||||
ctrl |= SDHCI_CTRL_ADMA32;
|
||||
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
|
||||
}
|
||||
|
||||
static void rk35xx_sdhci_cqe_enable(struct mmc_host *mmc)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
u32 reg;
|
||||
|
||||
reg = sdhci_readl(host, dwc_priv->vendor_specific_area2 + CQHCI_CFG);
|
||||
reg |= CQHCI_ENABLE;
|
||||
sdhci_writel(host, reg, dwc_priv->vendor_specific_area2 + CQHCI_CFG);
|
||||
|
||||
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
|
||||
while (reg & SDHCI_DATA_AVAILABLE) {
|
||||
sdhci_readl(host, SDHCI_BUFFER);
|
||||
reg = sdhci_readl(host, SDHCI_PRESENT_STATE);
|
||||
}
|
||||
|
||||
sdhci_writew(host, DWCMSHC_SDHCI_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);
|
||||
|
||||
sdhci_cqe_enable(mmc);
|
||||
|
||||
sdhci_writew(host, DWCMSHC_SDHCI_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE);
|
||||
}
|
||||
|
||||
static void rk35xx_sdhci_cqe_disabled(struct mmc_host *mmc, bool recovery)
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
unsigned long flags;
|
||||
u32 ctrl;
|
||||
|
||||
mmc->cqe_ops->cqe_wait_for_idle(mmc);
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
/*
|
||||
* During CQE command transfers, command complete bit gets latched.
|
||||
* So s/w should clear command complete interrupt status when CQE is
|
||||
* either halted or disabled. Otherwise unexpected SDCHI legacy
|
||||
* interrupt gets triggered when CQE is halted/disabled.
|
||||
*/
|
||||
ctrl = sdhci_readl(host, SDHCI_INT_ENABLE);
|
||||
ctrl |= SDHCI_INT_RESPONSE;
|
||||
sdhci_writel(host, ctrl, SDHCI_INT_ENABLE);
|
||||
sdhci_writel(host, SDHCI_INT_RESPONSE, SDHCI_INT_STATUS);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
sdhci_cqe_disable(mmc, recovery);
|
||||
|
||||
ctrl = sdhci_readl(host, dwc_priv->vendor_specific_area2 + CQHCI_CFG);
|
||||
ctrl &= ~CQHCI_ENABLE;
|
||||
sdhci_writel(host, ctrl, dwc_priv->vendor_specific_area2 + CQHCI_CFG);
|
||||
}
|
||||
|
||||
static void dwcmshc_set_tran_desc(struct cqhci_host *cq_host, u8 **desc,
|
||||
dma_addr_t addr, int len, bool end, bool dma64)
|
||||
{
|
||||
int tmplen, offset;
|
||||
|
||||
if (likely(!len || BOUNDARY_OK(addr, len))) {
|
||||
cqhci_set_tran_desc(*desc, addr, len, end, dma64);
|
||||
return;
|
||||
}
|
||||
|
||||
offset = addr & (SZ_128M - 1);
|
||||
tmplen = SZ_128M - offset;
|
||||
cqhci_set_tran_desc(*desc, addr, tmplen, false, dma64);
|
||||
|
||||
addr += tmplen;
|
||||
len -= tmplen;
|
||||
*desc += cq_host->trans_desc_len;
|
||||
cqhci_set_tran_desc(*desc, addr, len, end, dma64);
|
||||
}
|
||||
|
||||
static void dwcmshc_cqhci_dumpregs(struct mmc_host *mmc)
|
||||
{
|
||||
sdhci_dumpregs(mmc_priv(mmc));
|
||||
}
|
||||
|
||||
static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock)
|
||||
{
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
@@ -375,6 +527,7 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
|
||||
struct rk35xx_priv *priv = dwc_priv->priv;
|
||||
u32 extra = sdhci_readl(host, DECMSHC_EMMC_MISC_CON);
|
||||
|
||||
if (mask & SDHCI_RESET_ALL && priv->reset) {
|
||||
reset_control_assert(priv->reset);
|
||||
@@ -383,12 +536,17 @@ static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
|
||||
}
|
||||
|
||||
sdhci_reset(host, mask);
|
||||
|
||||
/* Enable INTERNAL CLOCK */
|
||||
sdhci_writel(host, MISC_INTCLK_EN | extra, DECMSHC_EMMC_MISC_CON);
|
||||
}
|
||||
|
||||
static void sdhci_dwcmshc_request_done(struct sdhci_host *host, struct mmc_request *mrq)
|
||||
{
|
||||
if (mmc_hsq_finalize_request(host->mmc, mrq))
|
||||
return;
|
||||
if (!(host->mmc->caps2 & MMC_CAP2_CQE)) {
|
||||
if (mmc_hsq_finalize_request(host->mmc, mrq))
|
||||
return;
|
||||
}
|
||||
|
||||
mmc_request_done(host->mmc, mrq);
|
||||
}
|
||||
@@ -400,6 +558,7 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = {
|
||||
.get_max_clock = dwcmshc_get_max_clock,
|
||||
.reset = sdhci_reset,
|
||||
.adma_write_desc = dwcmshc_adma_write_desc,
|
||||
.irq = dwcmshc_cqe_irq_handler,
|
||||
};
|
||||
|
||||
static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
|
||||
@@ -409,6 +568,7 @@ static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
|
||||
.get_max_clock = sdhci_pltfm_clk_get_max_clock,
|
||||
.reset = rk35xx_sdhci_reset,
|
||||
.adma_write_desc = dwcmshc_adma_write_desc,
|
||||
.irq = dwcmshc_cqe_irq_handler,
|
||||
.request_done = sdhci_dwcmshc_request_done,
|
||||
};
|
||||
|
||||
@@ -434,6 +594,84 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
|
||||
SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
|
||||
};
|
||||
|
||||
static const struct cqhci_host_ops dwcmshc_cqhci_ops = {
|
||||
.enable = dwcmshc_sdhci_cqe_enable,
|
||||
.disable = sdhci_cqe_disable,
|
||||
.dumpregs = dwcmshc_cqhci_dumpregs,
|
||||
.set_tran_desc = dwcmshc_set_tran_desc,
|
||||
};
|
||||
|
||||
static const struct cqhci_host_ops rk35xx_cqhci_ops = {
|
||||
.enable = rk35xx_sdhci_cqe_enable,
|
||||
.disable = rk35xx_sdhci_cqe_disabled,
|
||||
.dumpregs = dwcmshc_cqhci_dumpregs,
|
||||
.set_tran_desc = dwcmshc_set_tran_desc,
|
||||
};
|
||||
|
||||
static void dwcmshc_cqhci_init(struct sdhci_host *host, struct platform_device *pdev)
|
||||
{
|
||||
struct cqhci_host *cq_host;
|
||||
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
|
||||
struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
|
||||
struct rk35xx_priv *rk_priv = priv->priv;
|
||||
bool dma64 = false;
|
||||
u16 clk;
|
||||
int err;
|
||||
|
||||
host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
|
||||
cq_host = devm_kzalloc(&pdev->dev, sizeof(*cq_host), GFP_KERNEL);
|
||||
if (!cq_host) {
|
||||
dev_err(mmc_dev(host->mmc), "Unable to setup CQE: not enough memory\n");
|
||||
goto dsbl_cqe_caps;
|
||||
}
|
||||
|
||||
/*
|
||||
* For dwcmshc host controller we have to enable internal clock
|
||||
* before access to some registers from Vendor Specific Area 2.
|
||||
*/
|
||||
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
clk |= SDHCI_CLOCK_INT_EN;
|
||||
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
|
||||
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
if (!(clk & SDHCI_CLOCK_INT_EN)) {
|
||||
dev_err(mmc_dev(host->mmc), "Unable to setup CQE: internal clock enable error\n");
|
||||
goto free_cq_host;
|
||||
}
|
||||
|
||||
cq_host->mmio = host->ioaddr + priv->vendor_specific_area2;
|
||||
if (rk_priv)
|
||||
cq_host->ops = &rk35xx_cqhci_ops;
|
||||
else
|
||||
cq_host->ops = &dwcmshc_cqhci_ops;
|
||||
|
||||
/* Enable using of 128-bit task descriptors */
|
||||
dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
|
||||
if (dma64) {
|
||||
dev_dbg(mmc_dev(host->mmc), "128-bit task descriptors\n");
|
||||
cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
|
||||
}
|
||||
err = cqhci_init(cq_host, host->mmc, dma64);
|
||||
if (err) {
|
||||
dev_err(mmc_dev(host->mmc), "Unable to setup CQE: error %d\n", err);
|
||||
goto int_clock_disable;
|
||||
}
|
||||
|
||||
dev_dbg(mmc_dev(host->mmc), "CQE init done\n");
|
||||
|
||||
return;
|
||||
|
||||
int_clock_disable:
|
||||
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
|
||||
clk &= ~SDHCI_CLOCK_INT_EN;
|
||||
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
|
||||
|
||||
free_cq_host:
|
||||
devm_kfree(&pdev->dev, cq_host);
|
||||
|
||||
dsbl_cqe_caps:
|
||||
host->mmc->caps2 &= ~(MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD);
|
||||
}
|
||||
|
||||
static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
|
||||
{
|
||||
int err;
|
||||
@@ -594,7 +832,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
|
||||
const struct dwcmshc_driver_data *drv_data;
|
||||
struct mmc_hsq *hsq;
|
||||
int err;
|
||||
u32 extra;
|
||||
u32 extra, caps;
|
||||
|
||||
drv_data = device_get_match_data(&pdev->dev);
|
||||
if (!drv_data) {
|
||||
@@ -646,16 +884,7 @@ static int dwcmshc_probe(struct platform_device *pdev)
|
||||
|
||||
host->mmc_host_ops.request = dwcmshc_request;
|
||||
host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe;
|
||||
|
||||
hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL);
|
||||
if (!hsq) {
|
||||
err = -ENOMEM;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
err = mmc_hsq_init(hsq, host->mmc);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
host->mmc_host_ops.execute_tuning = dwcmshc_execute_tuning;
|
||||
|
||||
if (drv_data->flags & RK_PLATFROM) {
|
||||
rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL);
|
||||
@@ -679,12 +908,34 @@ static int dwcmshc_probe(struct platform_device *pdev)
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
caps = sdhci_readl(host, SDHCI_CAPABILITIES);
|
||||
if (caps & SDHCI_CAN_64BIT_V4)
|
||||
sdhci_enable_v4_mode(host);
|
||||
|
||||
host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
|
||||
|
||||
err = sdhci_setup_host(host);
|
||||
if (err)
|
||||
goto err_clk;
|
||||
|
||||
/* Setup Command Queue Engine if enabled */
|
||||
if (device_property_read_bool(&pdev->dev, "supports-cqe")) {
|
||||
priv->vendor_specific_area2 =
|
||||
sdhci_readw(host, DWCMSHC_P_VENDOR_AREA2);
|
||||
|
||||
dwcmshc_cqhci_init(host, pdev);
|
||||
} else {
|
||||
hsq = devm_kzalloc(&pdev->dev, sizeof(*hsq), GFP_KERNEL);
|
||||
if (!hsq) {
|
||||
err = -ENOMEM;
|
||||
goto err_setup_host;
|
||||
}
|
||||
|
||||
err = mmc_hsq_init(hsq, host->mmc);
|
||||
if (err)
|
||||
goto err_setup_host;
|
||||
}
|
||||
|
||||
if (rk_priv)
|
||||
dwcmshc_rk35xx_postinit(host, priv);
|
||||
|
||||
@@ -750,7 +1001,13 @@ static int dwcmshc_suspend(struct device *dev)
|
||||
struct rk35xx_priv *rk_priv = priv->priv;
|
||||
int ret;
|
||||
|
||||
mmc_hsq_suspend(host->mmc);
|
||||
if (host->mmc->caps2 & MMC_CAP2_CQE) {
|
||||
ret = cqhci_suspend(host->mmc);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
mmc_hsq_suspend(host->mmc);
|
||||
}
|
||||
|
||||
ret = sdhci_suspend_host(host);
|
||||
if (ret)
|
||||
@@ -782,21 +1039,40 @@ static int dwcmshc_resume(struct device *dev)
|
||||
if (!IS_ERR(priv->bus_clk)) {
|
||||
ret = clk_prepare_enable(priv->bus_clk);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_clk;
|
||||
}
|
||||
|
||||
if (rk_priv) {
|
||||
ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS,
|
||||
rk_priv->rockchip_clks);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_bus_clk;
|
||||
}
|
||||
|
||||
ret = sdhci_resume_host(host);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto disable_rockchip_clks;
|
||||
|
||||
return mmc_hsq_resume(host->mmc);
|
||||
if (host->mmc->caps2 & MMC_CAP2_CQE) {
|
||||
ret = cqhci_resume(host->mmc);
|
||||
if (ret)
|
||||
goto disable_rockchip_clks;
|
||||
} else {
|
||||
return mmc_hsq_resume(host->mmc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
disable_rockchip_clks:
|
||||
if (rk_priv)
|
||||
clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
|
||||
rk_priv->rockchip_clks);
|
||||
disable_bus_clk:
|
||||
if (!IS_ERR(priv->bus_clk))
|
||||
clk_disable_unprepare(priv->bus_clk);
|
||||
disable_clk:
|
||||
clk_disable_unprepare(pltfm_host->clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dwcmshc_runtime_suspend(struct device *dev)
|
||||
|
||||
@@ -67,6 +67,11 @@
|
||||
#define DPHY_MC_GNR_CON1 0x0304
|
||||
#define T_PHY_READY(x) UPDATE(x, 15, 0)
|
||||
#define DPHY_MC_ANA_CON0 0x0308
|
||||
#define EDGE_CON(x) UPDATE(x, 14, 12)
|
||||
#define EDGE_CON_DIR(x) UPDATE(x, 9, 9)
|
||||
#define EDGE_CON_EN BIT(8)
|
||||
#define RES_UP(x) UPDATE(x, 7, 4)
|
||||
#define RES_DN(x) UPDATE(x, 3, 0)
|
||||
#define DPHY_MC_ANA_CON1 0x030c
|
||||
#define DPHY_MC_ANA_CON2 0x0310
|
||||
#define HS_VREG_AMP_ICON(x) UPDATE(x, 1, 0)
|
||||
@@ -1594,15 +1599,25 @@ samsung_mipi_dphy_clk_lane_timing_init(struct samsung_mipi_dcphy *samsung)
|
||||
{
|
||||
const struct samsung_mipi_dphy_timing *timing;
|
||||
unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
|
||||
u32 val = 0;
|
||||
u32 val, res_up, res_down;
|
||||
|
||||
timing = samsung_mipi_dphy_get_timing(samsung);
|
||||
regmap_write(samsung->regmap, DPHY_MC_GNR_CON0, 0xf000);
|
||||
regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, 0x7133);
|
||||
|
||||
/*
|
||||
* The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the
|
||||
* Driver-Up Resistor and Driver-Down Resistor.
|
||||
*/
|
||||
res_up = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_up_ohm;
|
||||
res_down = samsung->pdata->dphy_hs_drv_res_cfg->clk_hs_drv_down_ohm;
|
||||
val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN |
|
||||
RES_UP(res_up) | RES_DN(res_down);
|
||||
regmap_write(samsung->regmap, DPHY_MC_ANA_CON0, val);
|
||||
|
||||
if (lane_hs_rate >= 4500)
|
||||
regmap_write(samsung->regmap, DPHY_MC_ANA_CON1, 0x0001);
|
||||
|
||||
val = 0;
|
||||
/*
|
||||
* Divide-by-2 Clock from Serial Clock. Use this when data rate is under
|
||||
* 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
|
||||
@@ -1639,14 +1654,22 @@ samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
|
||||
{
|
||||
const struct samsung_mipi_dphy_timing *timing;
|
||||
unsigned int lane_hs_rate = div64_ul(samsung->pll.rate, USEC_PER_SEC);
|
||||
u32 val = 0;
|
||||
u32 val, res_up, res_down;
|
||||
|
||||
timing = samsung_mipi_dphy_get_timing(samsung);
|
||||
|
||||
regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, 0x7133);
|
||||
regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, 0x7133);
|
||||
regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, 0x7133);
|
||||
regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, 0x7133);
|
||||
/*
|
||||
* The Drive-Strength / Voltage-Amplitude is adjusted by adjusting the
|
||||
* Driver-Up Resistor and Driver-Down Resistor.
|
||||
*/
|
||||
res_up = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_up_ohm;
|
||||
res_down = samsung->pdata->dphy_hs_drv_res_cfg->data_hs_drv_down_ohm;
|
||||
val = EDGE_CON(7) | EDGE_CON_DIR(0) | EDGE_CON_EN |
|
||||
RES_UP(res_up) | RES_DN(res_down);
|
||||
regmap_write(samsung->regmap, COMBO_MD0_ANA_CON0, val);
|
||||
regmap_write(samsung->regmap, COMBO_MD1_ANA_CON0, val);
|
||||
regmap_write(samsung->regmap, COMBO_MD2_ANA_CON0, val);
|
||||
regmap_write(samsung->regmap, DPHY_MD3_ANA_CON0, val);
|
||||
|
||||
if (lane_hs_rate >= 4500) {
|
||||
regmap_write(samsung->regmap, COMBO_MD0_ANA_CON1, 0x0001);
|
||||
@@ -1655,6 +1678,7 @@ samsung_mipi_dphy_data_lane_timing_init(struct samsung_mipi_dcphy *samsung)
|
||||
regmap_write(samsung->regmap, DPHY_MD3_ANA_CON1, 0x0001);
|
||||
}
|
||||
|
||||
val = 0;
|
||||
/*
|
||||
* Divide-by-2 Clock from Serial Clock. Use this when data rate is under
|
||||
* 1500Mbps, otherwise divide-by-16 Clock from Serial Clock
|
||||
@@ -2473,12 +2497,28 @@ static const struct dev_pm_ops samsung_mipi_dcphy_pm_ops = {
|
||||
samsung_mipi_dcphy_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct hs_drv_res_cfg rk3576_dphy_hs_drv_res_cfg = {
|
||||
.clk_hs_drv_up_ohm = _52_OHM,
|
||||
.clk_hs_drv_down_ohm = _52_OHM,
|
||||
.data_hs_drv_up_ohm = _39_OHM,
|
||||
.data_hs_drv_down_ohm = _39_OHM,
|
||||
};
|
||||
|
||||
static const struct hs_drv_res_cfg rk3588_dphy_hs_drv_res_cfg = {
|
||||
.clk_hs_drv_up_ohm = _34_OHM,
|
||||
.clk_hs_drv_down_ohm = _34_OHM,
|
||||
.data_hs_drv_up_ohm = _43_OHM,
|
||||
.data_hs_drv_down_ohm = _43_OHM,
|
||||
};
|
||||
|
||||
static const struct samsung_mipi_dcphy_plat_data rk3576_samsung_mipi_dcphy_plat_data = {
|
||||
.dphy_hs_drv_res_cfg = &rk3576_dphy_hs_drv_res_cfg,
|
||||
.dphy_tx_max_kbps_per_lane = 2500000L,
|
||||
.cphy_tx_max_ksps_per_lane = 1700000L,
|
||||
};
|
||||
|
||||
static const struct samsung_mipi_dcphy_plat_data rk3588_samsung_mipi_dcphy_plat_data = {
|
||||
.dphy_hs_drv_res_cfg = &rk3588_dphy_hs_drv_res_cfg,
|
||||
.dphy_tx_max_kbps_per_lane = 4500000L,
|
||||
.cphy_tx_max_ksps_per_lane = 2000000L,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,34 @@
|
||||
|
||||
#define MAX_NUM_CSI2_DPHY (0x2)
|
||||
|
||||
enum hs_drv_res_ohm {
|
||||
_30_OHM = 0x8,
|
||||
_31_2_OHM,
|
||||
_32_5_OHM,
|
||||
_34_OHM,
|
||||
_35_5_OHM,
|
||||
_37_OHM,
|
||||
_39_OHM,
|
||||
_41_OHM,
|
||||
_43_OHM = 0x0,
|
||||
_46_OHM,
|
||||
_49_OHM,
|
||||
_52_OHM,
|
||||
_56_OHM,
|
||||
_60_OHM,
|
||||
_66_OHM,
|
||||
_73_OHM,
|
||||
};
|
||||
|
||||
struct hs_drv_res_cfg {
|
||||
enum hs_drv_res_ohm clk_hs_drv_up_ohm;
|
||||
enum hs_drv_res_ohm clk_hs_drv_down_ohm;
|
||||
enum hs_drv_res_ohm data_hs_drv_up_ohm;
|
||||
enum hs_drv_res_ohm data_hs_drv_down_ohm;
|
||||
};
|
||||
|
||||
struct samsung_mipi_dcphy_plat_data {
|
||||
const struct hs_drv_res_cfg *dphy_hs_drv_res_cfg;
|
||||
u32 dphy_tx_max_kbps_per_lane;
|
||||
u32 cphy_tx_max_ksps_per_lane;
|
||||
};
|
||||
|
||||
@@ -931,7 +931,7 @@ static int rk817_resume_path_get(struct snd_kcontrol *kcontrol,
|
||||
struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
|
||||
struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
|
||||
|
||||
DBG("%s : resume_path %ld\n", __func__, rk817->resume_path);
|
||||
DBG("%s : resume_path %d\n", __func__, rk817->resume_path);
|
||||
|
||||
ucontrol->value.integer.value[0] = rk817->resume_path;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user