mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 04:10:18 +09:00
phy: rockchip: mipi-rx: distinguish control object for txrx
txrx can be linked with isp or csi-host, so separate it Change-Id: I41d81770c53008bdf9703f92834cc41d9724a563 Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
This commit is contained in:
@@ -77,6 +77,8 @@
|
||||
#define RK3288_PHY_TEST_CTRL1 0x34
|
||||
#define RK3288_PHY_SHUTDOWNZ 0x08
|
||||
#define RK3288_PHY_RSTZ 0x0c
|
||||
#define RK3288_PHY_N_LANES 0x04
|
||||
#define RK3288_PHY_RESETN 0x10
|
||||
|
||||
#define RK3399_PHY_TEST_CTRL0 0xb4
|
||||
#define RK3399_PHY_TEST_CTRL1 0xb8
|
||||
@@ -261,6 +263,9 @@ enum txrx_reg_id {
|
||||
TXRX_PHY_TEST_CTRL1,
|
||||
TXRX_PHY_SHUTDOWNZ,
|
||||
TXRX_PHY_RSTZ,
|
||||
TXRX_PHY_N_LANES,
|
||||
TXRX_PHY_ENABLECLK,
|
||||
TXRX_PHY_RESETN
|
||||
};
|
||||
|
||||
struct dphy_reg {
|
||||
@@ -370,6 +375,8 @@ static const struct txrx_reg rk3288_txrx_regs[] = {
|
||||
[TXRX_PHY_TEST_CTRL1] = TXRX_REG(RK3288_PHY_TEST_CTRL1),
|
||||
[TXRX_PHY_SHUTDOWNZ] = TXRX_REG(RK3288_PHY_SHUTDOWNZ),
|
||||
[TXRX_PHY_RSTZ] = TXRX_REG(RK3288_PHY_RSTZ),
|
||||
[TXRX_PHY_N_LANES] = TXRX_REG(RK3288_PHY_N_LANES),
|
||||
[TXRX_PHY_RESETN] = TXRX_REG(RK3288_PHY_RESETN),
|
||||
};
|
||||
|
||||
static const struct txrx_reg rk3399_txrx_regs[] = {
|
||||
@@ -548,7 +555,7 @@ static inline void write_csiphy_reg(struct mipidphy_priv *priv,
|
||||
}
|
||||
|
||||
static inline void read_csiphy_reg(struct mipidphy_priv *priv,
|
||||
int index, u32 *value)
|
||||
int index, u32 *value)
|
||||
{
|
||||
const struct csiphy_reg *reg = &priv->csiphy_regs[index];
|
||||
|
||||
@@ -587,6 +594,24 @@ static void csi_mipidphy_wr_ths_settle(struct mipidphy_priv *priv, int hsfreq,
|
||||
write_csiphy_reg(priv, offset, val);
|
||||
}
|
||||
|
||||
static struct v4l2_subdev *get_remote_sink_dev(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct media_pad *local, *remote;
|
||||
struct media_entity *sink_me;
|
||||
|
||||
local = &sd->entity.pads[MIPI_DPHY_RX_PAD_SOURCE];
|
||||
remote = media_entity_remote_pad(local);
|
||||
if (!remote) {
|
||||
v4l2_warn(sd, "No link between dphy and cif or isp\n");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sink_me = media_entity_remote_pad(local)->entity;
|
||||
|
||||
return media_entity_to_v4l2_subdev(sink_me);
|
||||
}
|
||||
|
||||
static struct v4l2_subdev *get_remote_sensor(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct media_pad *local, *remote;
|
||||
@@ -608,9 +633,10 @@ static struct mipidphy_sensor *sd_to_sensor(struct mipidphy_priv *priv,
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_sensors; ++i)
|
||||
for (i = 0; i < priv->num_sensors; ++i) {
|
||||
if (priv->sensors[i].sd == sd)
|
||||
return &priv->sensors[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -1007,11 +1033,18 @@ static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
|
||||
struct v4l2_subdev *sd)
|
||||
{
|
||||
struct v4l2_subdev *sensor_sd = get_remote_sensor(sd);
|
||||
struct v4l2_subdev *sink_sd = get_remote_sink_dev(sd);
|
||||
struct mipidphy_sensor *sensor = sd_to_sensor(priv, sensor_sd);
|
||||
const struct dphy_drv_data *drv_data = priv->drv_data;
|
||||
const struct hsfreq_range *hsfreq_ranges = drv_data->hsfreq_ranges;
|
||||
int num_hsfreq_ranges = drv_data->num_hsfreq_ranges;
|
||||
int i, hsfreq = 0;
|
||||
bool is_linked_isp;
|
||||
|
||||
if (strstr(sink_sd->name, "csi2"))
|
||||
is_linked_isp = false;
|
||||
else
|
||||
is_linked_isp = true;
|
||||
|
||||
for (i = 0; i < num_hsfreq_ranges; i++) {
|
||||
if (hsfreq_ranges[i].range_h >= priv->data_rate_mbps) {
|
||||
@@ -1035,7 +1068,10 @@ static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
|
||||
*/
|
||||
write_grf_reg(priv, GRF_CON_ISP_DPHY_SEL, 1);
|
||||
write_grf_reg(priv, GRF_DSI_CSI_TESTBUS_SEL, 1);
|
||||
write_grf_reg(priv, GRF_DPHY_RX1_SRC_SEL, 1);
|
||||
if (is_linked_isp)
|
||||
write_grf_reg(priv, GRF_DPHY_RX1_SRC_SEL, 1);
|
||||
else
|
||||
write_grf_reg(priv, GRF_DPHY_RX1_SRC_SEL, 0);
|
||||
|
||||
/*
|
||||
* Config rk3399:
|
||||
@@ -1047,6 +1083,10 @@ static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
|
||||
/* Step1: set RSTZ = 1'b0, phy1-rx controlled by isp */
|
||||
|
||||
/* Step2: set SHUTDOWNZ = 1'b0, phy1-rx controlled by isp */
|
||||
if (!is_linked_isp) {
|
||||
write_txrx_reg(priv, TXRX_PHY_RSTZ, 0);
|
||||
write_txrx_reg(priv, TXRX_PHY_SHUTDOWNZ, 0);
|
||||
}
|
||||
|
||||
/* Step3: set TESTCLR= 1'b1,TESTCLK=1'b1 */
|
||||
write_txrx_reg(priv, TXRX_PHY_TEST_CTRL0, PHY_TESTCLR | PHY_TESTCLK);
|
||||
@@ -1102,8 +1142,13 @@ static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
|
||||
* is set by isp1,
|
||||
* if run 3399 here operates grf_soc_con23[0:3]
|
||||
*/
|
||||
write_grf_reg(priv, GRF_DPHY_TX1RX1_ENABLE,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
if (is_linked_isp) {
|
||||
write_grf_reg(priv, GRF_DPHY_TX1RX1_ENABLE,
|
||||
GENMASK(sensor->lanes - 1, 0));
|
||||
} else {
|
||||
write_grf_reg(priv, GRF_DPHY_TX1RX1_ENABLECLK, 1);
|
||||
write_txrx_reg(priv, TXRX_PHY_N_LANES, sensor->lanes - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step13:Set SHUTDOWNZ=1'b1, phy1-rx controlled by isp,
|
||||
@@ -1111,6 +1156,12 @@ static int mipidphy_txrx_stream_on(struct mipidphy_priv *priv,
|
||||
*/
|
||||
|
||||
/* Step14:Set RSTZ=1'b1, phy1-rx controlled by isp*/
|
||||
if (!is_linked_isp) {
|
||||
write_txrx_reg(priv, TXRX_PHY_SHUTDOWNZ, 1);
|
||||
usleep_range(100, 150);
|
||||
write_txrx_reg(priv, TXRX_PHY_RSTZ, 1);
|
||||
write_txrx_reg(priv, TXRX_PHY_RESETN, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Step15:Wait until STOPSTATEDATA_N & STOPSTATECLK
|
||||
@@ -1139,8 +1190,9 @@ static int csi_mipidphy_stream_on(struct mipidphy_priv *priv,
|
||||
|
||||
/* set data lane num and enable clock lane */
|
||||
write_csiphy_reg(priv, CSIPHY_CTRL_LANE_ENABLE,
|
||||
((GENMASK(sensor->lanes - 1, 0) << MIPI_CSI_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
|
||||
(0x1 << MIPI_CSI_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT) | 0x1));
|
||||
((GENMASK(sensor->lanes - 1, 0) <<
|
||||
MIPI_CSI_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
|
||||
(0x1 << MIPI_CSI_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT) | 0x1));
|
||||
|
||||
/* Reset dphy analog part */
|
||||
write_csiphy_reg(priv, CSIPHY_CTRL_PWRCTL, 0xe0);
|
||||
@@ -1325,10 +1377,11 @@ rockchip_mipidphy_notifier_bound(struct v4l2_async_notifier *notifier,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = media_entity_create_link(
|
||||
&sensor->sd->entity, pad,
|
||||
&priv->sd.entity, MIPI_DPHY_RX_PAD_SINK,
|
||||
priv->num_sensors != 1 ? 0 : MEDIA_LNK_FL_ENABLED);
|
||||
ret = media_entity_create_link(&sensor->sd->entity, pad,
|
||||
&priv->sd.entity,
|
||||
MIPI_DPHY_RX_PAD_SINK,
|
||||
priv->num_sensors != 1 ? 0 :
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret) {
|
||||
dev_err(priv->dev,
|
||||
"failed to create link for %s\n",
|
||||
@@ -1415,10 +1468,11 @@ static int rockchip_mipidphy_media_init(struct mipidphy_priv *priv)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
|
||||
priv->dev, &priv->notifier,
|
||||
sizeof(struct sensor_async_subdev), 0,
|
||||
rockchip_mipidphy_fwnode_parse);
|
||||
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(priv->dev,
|
||||
&priv->notifier,
|
||||
sizeof(struct sensor_async_subdev),
|
||||
0,
|
||||
rockchip_mipidphy_fwnode_parse);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -1490,9 +1544,15 @@ static int rockchip_mipidphy_probe(struct platform_device *pdev)
|
||||
priv->stream_on = mipidphy_txrx_stream_on;
|
||||
priv->txrx_base_addr = NULL;
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->txrx_base_addr = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->txrx_base_addr))
|
||||
if (res) {
|
||||
priv->txrx_base_addr = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->txrx_base_addr)) {
|
||||
dev_err(dev, "Failed to ioremap resource\n");
|
||||
return PTR_ERR(priv->txrx_base_addr);
|
||||
}
|
||||
} else {
|
||||
priv->stream_on = mipidphy_rx_stream_on;
|
||||
}
|
||||
priv->stream_off = NULL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user