mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
media: i2c: rk628: move some function to rk628_mipi_dphy.c
Change-Id: I01a826edaf8c766f616a997d7c83f2009d10adac Signed-off-by: Jianwei Fan <jianwei.fan@rock-chips.com>
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
#
|
||||
# Makefile for the Rockchip RK628 display bridge driver.
|
||||
#
|
||||
video-rk628-objs := rk628.o rk628_cru.o rk628_hdmirx.o rk628_dsi.o rk628_combrxphy.o rk628_combtxphy.o rk628_post_process.o
|
||||
video-rk628-objs := rk628.o rk628_cru.o rk628_hdmirx.o rk628_dsi.o rk628_combrxphy.o \
|
||||
rk628_combtxphy.o rk628_mipi_dphy.o rk628_post_process.o
|
||||
obj-$(CONFIG_VIDEO_RK628) += video-rk628.o
|
||||
|
||||
rk628-csi-objs := rk628_csi_v4l2.o
|
||||
|
||||
@@ -920,7 +920,7 @@ static void rk628_csi_set_csi(struct v4l2_subdev *sd)
|
||||
rk628_csi0_cru_reset(sd);
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
rk628_csi1_cru_reset(sd);
|
||||
mipi_dphy_reset(csi->rk628);
|
||||
rk628_mipi_dphy_reset(csi->rk628);
|
||||
rk628_post_process_setup(sd);
|
||||
|
||||
if (csi->txphy_pwron) {
|
||||
@@ -1347,7 +1347,7 @@ static void rk628_csi_initial_setup(struct v4l2_subdev *sd)
|
||||
|
||||
csi->rk628->dphy_lane_en = 0x1f;
|
||||
if (csi->plat_data->tx_mode == CSI_MODE) {
|
||||
mipi_dphy_reset(csi->rk628);
|
||||
rk628_mipi_dphy_reset(csi->rk628);
|
||||
mipi_dphy_power_on(csi);
|
||||
}
|
||||
csi->txphy_pwron = true;
|
||||
@@ -2058,19 +2058,19 @@ static int mipi_dphy_power_on(struct rk628_csi *csi)
|
||||
rk628_txphy_set_bus_width(csi->rk628, bus_width);
|
||||
rk628_txphy_set_mode(csi->rk628, PHY_MODE_VIDEO_MIPI);
|
||||
|
||||
mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 0);
|
||||
rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 0);
|
||||
if (csi->rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1);
|
||||
rk628_mipi_dphy_init_hsfreqrange(csi->rk628, csi->lane_mbps, 1);
|
||||
|
||||
if (csi->rk628->dual_mipi) {
|
||||
mipi_dphy_init_hsmanual(csi->rk628, true, 0);
|
||||
mipi_dphy_init_hsmanual(csi->rk628, true, 1);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 1);
|
||||
} else if (csi->lane_mbps == MIPI_DATARATE_MBPS_HIGH && !csi->rk628->dual_mipi) {
|
||||
mipi_dphy_init_hsmanual(csi->rk628, true, 0);
|
||||
mipi_dphy_init_hsmanual(csi->rk628, false, 1);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, true, 0);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1);
|
||||
} else {
|
||||
mipi_dphy_init_hsmanual(csi->rk628, false, 0);
|
||||
mipi_dphy_init_hsmanual(csi->rk628, false, 1);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 0);
|
||||
rk628_mipi_dphy_init_hsmanual(csi->rk628, false, 1);
|
||||
}
|
||||
|
||||
usleep_range(1500, 2000);
|
||||
|
||||
@@ -72,7 +72,7 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi)
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_ENABLECLK, 0);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_SHUTDOWNZ, 0);
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ, PHY_RSTZ, 0);
|
||||
testif_testclr_assert(dsi->rk628, 0);
|
||||
rk628_testif_testclr_assert(dsi->rk628, 0);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
@@ -80,9 +80,9 @@ static void mipi_dphy_power_on_dsi(struct rk628_dsi *dsi)
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
|
||||
testif_testclr_deassert(dsi->rk628, 0);
|
||||
rk628_testif_testclr_deassert(dsi->rk628, 0);
|
||||
|
||||
mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps, 0);
|
||||
rk628_mipi_dphy_init_hsfreqrange(dsi->rk628, dsi->lane_mbps, 0);
|
||||
|
||||
dsi_update_bits(rk628, 0, DSI_PHY_RSTZ,
|
||||
PHY_ENABLECLK, PHY_ENABLECLK);
|
||||
|
||||
279
drivers/media/i2c/rk628/rk628_mipi_dphy.c
Normal file
279
drivers/media/i2c/rk628/rk628_mipi_dphy.c
Normal file
@@ -0,0 +1,279 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "rk628_csi.h"
|
||||
#include "rk628_dsi.h"
|
||||
#include "rk628_mipi_dphy.h"
|
||||
|
||||
static inline void testif_testclk_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, PHY_TESTCLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclk_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, PHY_TESTCLR);
|
||||
udelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_testclr_assert);
|
||||
|
||||
void rk628_testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, 0);
|
||||
udelay(1);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_testclr_deassert);
|
||||
|
||||
static inline void testif_testen_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, PHY_TESTEN);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_set_data(struct rk628 *rk628, u8 data, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTDIN_MASK, PHY_TESTDIN(data));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline u8 testif_get_data(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
rk628_i2c_read(rk628, mipi_id ? GRF_DPHY1_STATUS : GRF_DPHY0_STATUS, &data);
|
||||
|
||||
return data >> PHY_TESTDOUT_SHIFT;
|
||||
}
|
||||
|
||||
static void testif_test_code_write(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_code, mipi_id);
|
||||
testif_testen_assert(rk628, mipi_id);
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_testen_deassert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
static void testif_test_data_write(struct rk628 *rk628, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_data, mipi_id);
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
u8 monitor_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
monitor_data = testif_get_data(rk628, mipi_id);
|
||||
|
||||
dev_dbg(rk628->dev, "test_code=0x%02x, mipi dphy%x", test_code, mipi_id);
|
||||
dev_dbg(rk628->dev, "test_data=0x%02x, mipi dphy%x", test_data, mipi_id);
|
||||
dev_dbg(rk628->dev, "monitor_data=0x%02x, mipi dphy%x\n", monitor_data, mipi_id);
|
||||
|
||||
return monitor_data;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_write);
|
||||
|
||||
u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
u8 test_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
test_data = testif_get_data(rk628, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
|
||||
return test_data;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_testif_read);
|
||||
|
||||
static inline void mipi_dphy_enablelane_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, CSI_DPHY_EN(rk628->dphy_lane_en));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enablelane_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ,
|
||||
CSI_PHYSHUTDOWNZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ,
|
||||
CSI_PHYRSTZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id)
|
||||
{
|
||||
const struct {
|
||||
unsigned long max_lane_mbps;
|
||||
u8 hsfreqrange;
|
||||
} hsfreqrange_table[] = {
|
||||
{ 90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
|
||||
{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
|
||||
{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
|
||||
{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
|
||||
{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
|
||||
{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
|
||||
{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
|
||||
{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
|
||||
{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
|
||||
{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
|
||||
};
|
||||
u8 hsfreqrange;
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
|
||||
if (lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(hsfreqrange_table))
|
||||
--index;
|
||||
|
||||
hsfreqrange = hsfreqrange_table[index].hsfreqrange;
|
||||
rk628_testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange), mipi_id);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_init_hsfreqrange);
|
||||
|
||||
void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id)
|
||||
{
|
||||
dev_info(rk628->dev,
|
||||
"mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false");
|
||||
//config mipi timing when mipi freq is 1250Mbps
|
||||
rk628_testif_write(rk628, 0x71,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x72,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x73,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x61,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x62,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x63,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
rk628_testif_write(rk628, 0x65,
|
||||
manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(5)) : 0, mipi_id);
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_init_hsmanual);
|
||||
|
||||
int rk628_mipi_dphy_reset(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, mask;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x1);
|
||||
mipi_dphy_enablelane_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_deassert(rk628, 1);
|
||||
mipi_dphy_shutdownz_assert(rk628);
|
||||
mipi_dphy_rstz_assert(rk628);
|
||||
rk628_testif_testclr_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_testif_testclr_assert(rk628, 1);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX1_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
rk628_testif_testclr_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_testif_testclr_deassert(rk628, 1);
|
||||
mipi_dphy_enablelane_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_assert(rk628, 1);
|
||||
mipi_dphy_shutdownz_deassert(rk628);
|
||||
mipi_dphy_rstz_deassert(rk628);
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x0);
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
mask = STOPSTATE_CLK | STOPSTATE_LANE0;
|
||||
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI],
|
||||
CSITX_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev, "csi0 lane module is not in stop state, val: 0x%x\n", val);
|
||||
|
||||
if (rk628->version >= RK628F_VERSION) {
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI1],
|
||||
CSITX1_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"csi1 lane module is not in stop state, val: 0x%x\n", val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(rk628_mipi_dphy_reset);
|
||||
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2020 Rockchip Electronics Co. Ltd.
|
||||
* Copyright (c) 2023 Rockchip Electronics Co. Ltd.
|
||||
*
|
||||
* Author: Shunqing Chen <csq@rock-chips.com>
|
||||
*/
|
||||
@@ -8,12 +8,6 @@
|
||||
#ifndef _RK628_MIPI_DPHY_H
|
||||
#define _RK628_MIPI_DPHY_H
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include "rk628_csi.h"
|
||||
#include "rk628_dsi.h"
|
||||
#include "rk628.h"
|
||||
|
||||
/* Test Code: 0x44 (HS RX Control of Lane 0) */
|
||||
@@ -23,264 +17,12 @@
|
||||
#define HSPOST(x) UPDATE(x, 4, 0)
|
||||
#define HSEXIT(x) UPDATE(x, 4, 0)
|
||||
|
||||
static inline void testif_testclk_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, PHY_TESTCLK);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclk_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, PHY_TESTCLR);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTCLR, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, PHY_TESTEN);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_testen_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTEN, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void testif_set_data(struct rk628 *rk628, u8 data, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? GRF_MIPI_TX1_CON : GRF_MIPI_TX0_CON,
|
||||
PHY_TESTDIN_MASK, PHY_TESTDIN(data));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline u8 testif_get_data(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
u32 data = 0;
|
||||
|
||||
rk628_i2c_read(rk628, mipi_id ? GRF_DPHY1_STATUS : GRF_DPHY0_STATUS, &data);
|
||||
|
||||
return data >> PHY_TESTDOUT_SHIFT;
|
||||
}
|
||||
|
||||
static void testif_test_code_write(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_code, mipi_id);
|
||||
testif_testen_assert(rk628, mipi_id);
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_testen_deassert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
static void testif_test_data_write(struct rk628 *rk628, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
testif_testclk_deassert(rk628, mipi_id);
|
||||
testif_set_data(rk628, test_data, mipi_id);
|
||||
testif_testclk_assert(rk628, mipi_id);
|
||||
}
|
||||
|
||||
static u8 testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id)
|
||||
{
|
||||
u8 monitor_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
monitor_data = testif_get_data(rk628, mipi_id);
|
||||
|
||||
dev_dbg(rk628->dev, "test_code=0x%02x, mipi dphy%x", test_code, mipi_id);
|
||||
dev_dbg(rk628->dev, "test_data=0x%02x, mipi dphy%x", test_data, mipi_id);
|
||||
dev_dbg(rk628->dev, "monitor_data=0x%02x, mipi dphy%x\n", monitor_data, mipi_id);
|
||||
|
||||
return monitor_data;
|
||||
}
|
||||
|
||||
static inline u8 testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id)
|
||||
{
|
||||
u8 test_data;
|
||||
|
||||
testif_test_code_write(rk628, test_code, mipi_id);
|
||||
test_data = testif_get_data(rk628, mipi_id);
|
||||
testif_test_data_write(rk628, test_data, mipi_id);
|
||||
|
||||
return test_data;
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enablelane_assert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, CSI_DPHY_EN(rk628->dphy_lane_en));
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_enablelane_deassert(struct rk628 *rk628, uint8_t mipi_id)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, mipi_id ? CSITX1_DPHY_CTRL : CSITX_DPHY_CTRL,
|
||||
CSI_DPHY_EN_MASK, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_shutdownz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYSHUTDOWNZ,
|
||||
CSI_PHYSHUTDOWNZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_assert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ, 0);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_rstz_deassert(struct rk628 *rk628)
|
||||
{
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON, CSI_PHYRSTZ,
|
||||
CSI_PHYRSTZ);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
static inline void mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id)
|
||||
{
|
||||
const struct {
|
||||
unsigned long max_lane_mbps;
|
||||
u8 hsfreqrange;
|
||||
} hsfreqrange_table[] = {
|
||||
{ 90, 0x00}, { 100, 0x10}, { 110, 0x20}, { 130, 0x01},
|
||||
{ 140, 0x11}, { 150, 0x21}, { 170, 0x02}, { 180, 0x12},
|
||||
{ 200, 0x22}, { 220, 0x03}, { 240, 0x13}, { 250, 0x23},
|
||||
{ 270, 0x04}, { 300, 0x14}, { 330, 0x05}, { 360, 0x15},
|
||||
{ 400, 0x25}, { 450, 0x06}, { 500, 0x16}, { 550, 0x07},
|
||||
{ 600, 0x17}, { 650, 0x08}, { 700, 0x18}, { 750, 0x09},
|
||||
{ 800, 0x19}, { 850, 0x29}, { 900, 0x39}, { 950, 0x0a},
|
||||
{1000, 0x1a}, {1050, 0x2a}, {1100, 0x3a}, {1150, 0x0b},
|
||||
{1200, 0x1b}, {1250, 0x2b}, {1300, 0x3b}, {1350, 0x0c},
|
||||
{1400, 0x1c}, {1450, 0x2c}, {1500, 0x3c}
|
||||
};
|
||||
u8 hsfreqrange;
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < ARRAY_SIZE(hsfreqrange_table); index++)
|
||||
if (lane_mbps <= hsfreqrange_table[index].max_lane_mbps)
|
||||
break;
|
||||
|
||||
if (index == ARRAY_SIZE(hsfreqrange_table))
|
||||
--index;
|
||||
|
||||
hsfreqrange = hsfreqrange_table[index].hsfreqrange;
|
||||
testif_write(rk628, 0x44, HSFREQRANGE(hsfreqrange), mipi_id);
|
||||
}
|
||||
|
||||
static void __maybe_unused mipi_dphy_init_hsmanual(struct rk628 *rk628,
|
||||
bool manual, uint8_t mipi_id)
|
||||
{
|
||||
dev_info(rk628->dev,
|
||||
"mipi dphy%d hs config, manual: %s\n", mipi_id, manual ? "true" : "false");
|
||||
//config mipi timing when mipi freq is 1250Mbps
|
||||
testif_write(rk628, 0x71,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x72,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].data_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x73,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].data_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x61,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_prepare) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x62,
|
||||
manual ? (HSZERO(rk628->mipi_timing[mipi_id].clk_zero) | BIT(6)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x63,
|
||||
manual ? (HSTX(rk628->mipi_timing[mipi_id].clk_trail) | BIT(7)) : 0, mipi_id);
|
||||
usleep_range(1500, 2000);
|
||||
testif_write(rk628, 0x65,
|
||||
manual ? (HSPOST(rk628->mipi_timing[mipi_id].clk_post) | BIT(5)) : 0, mipi_id);
|
||||
}
|
||||
|
||||
static inline int mipi_dphy_reset(struct rk628 *rk628)
|
||||
{
|
||||
u32 val, mask;
|
||||
int ret;
|
||||
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x1);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x1);
|
||||
mipi_dphy_enablelane_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_deassert(rk628, 1);
|
||||
mipi_dphy_shutdownz_assert(rk628);
|
||||
mipi_dphy_rstz_assert(rk628);
|
||||
testif_testclr_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
testif_testclr_assert(rk628, 1);
|
||||
|
||||
/* Set all REQUEST inputs to zero */
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX0_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_update_bits(rk628, GRF_MIPI_TX1_CON,
|
||||
FORCETXSTOPMODE_MASK | FORCERXMODE_MASK,
|
||||
FORCETXSTOPMODE(0) | FORCERXMODE(0));
|
||||
udelay(1);
|
||||
testif_testclr_deassert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
testif_testclr_deassert(rk628, 1);
|
||||
mipi_dphy_enablelane_assert(rk628, 0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
mipi_dphy_enablelane_assert(rk628, 1);
|
||||
mipi_dphy_shutdownz_deassert(rk628);
|
||||
mipi_dphy_rstz_deassert(rk628);
|
||||
rk628_i2c_write(rk628, CSITX_SYS_CTRL0_IMD, 0x0);
|
||||
if (rk628->version >= RK628F_VERSION)
|
||||
rk628_i2c_write(rk628, CSITX1_SYS_CTRL0_IMD, 0x0);
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
mask = STOPSTATE_CLK | STOPSTATE_LANE0;
|
||||
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI],
|
||||
CSITX_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev, "csi0 lane module is not in stop state, val: 0x%x\n", val);
|
||||
|
||||
if (rk628->version >= RK628F_VERSION) {
|
||||
ret = regmap_read_poll_timeout(rk628->regmap[RK628_DEV_CSI1],
|
||||
CSITX1_CSITX_STATUS1,
|
||||
val, (val & mask) == mask,
|
||||
0, 1000);
|
||||
if (ret < 0)
|
||||
dev_err(rk628->dev,
|
||||
"csi1 lane module is not in stop state, val: 0x%x\n", val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void rk628_testif_testclr_deassert(struct rk628 *rk628, uint8_t mipi_id);
|
||||
void rk628_testif_testclr_assert(struct rk628 *rk628, uint8_t mipi_id);
|
||||
u8 rk628_testif_write(struct rk628 *rk628, u8 test_code, u8 test_data, uint8_t mipi_id);
|
||||
u8 rk628_testif_read(struct rk628 *rk628, u8 test_code, uint8_t mipi_id);
|
||||
void rk628_mipi_dphy_init_hsfreqrange(struct rk628 *rk628, int lane_mbps, uint8_t mipi_id);
|
||||
void rk628_mipi_dphy_init_hsmanual(struct rk628 *rk628, bool manual, uint8_t mipi_id);
|
||||
int rk628_mipi_dphy_reset(struct rk628 *rk628);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user