mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 12:44:32 -04:00
Merge tag 'exynos-drm-misc-next-for-v6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
New feature - Add DSIM bridge driver support for Exynos7870 . Introduces Exynos7870 DSIM IP block support in the samsung-dsim bridge driver. - Document Exynos7870 DSIM compatible in dt-bindings . Adds exynos7870 compatible string and required clocks in device tree schema. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Inki Dae <inki.dae@samsung.com> Link: https://lore.kernel.org/r/20250915111802.28177-1-inki.dae@samsung.com
This commit is contained in:
@@ -24,6 +24,7 @@ properties:
|
||||
- samsung,exynos5410-mipi-dsi
|
||||
- samsung,exynos5422-mipi-dsi
|
||||
- samsung,exynos5433-mipi-dsi
|
||||
- samsung,exynos7870-mipi-dsi
|
||||
- fsl,imx8mm-mipi-dsim
|
||||
- fsl,imx8mp-mipi-dsim
|
||||
- items:
|
||||
@@ -144,6 +145,32 @@ required:
|
||||
|
||||
allOf:
|
||||
- $ref: ../dsi-controller.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: samsung,exynos7870-mipi-dsi
|
||||
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: pll
|
||||
- const: byte
|
||||
- const: esc
|
||||
|
||||
ports:
|
||||
required:
|
||||
- port@0
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
||||
@@ -31,11 +31,10 @@
|
||||
/* returns true iff both arguments logically differs */
|
||||
#define NEQV(a, b) (!(a) ^ !(b))
|
||||
|
||||
/* DSIM_STATUS */
|
||||
/* DSIM_STATUS or DSIM_DPHY_STATUS */
|
||||
#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
|
||||
#define DSIM_STOP_STATE_CLK BIT(8)
|
||||
#define DSIM_TX_READY_HS_CLK BIT(10)
|
||||
#define DSIM_PLL_STABLE BIT(31)
|
||||
|
||||
/* DSIM_SWRST */
|
||||
#define DSIM_FUNCRST BIT(16)
|
||||
@@ -46,17 +45,13 @@
|
||||
#define DSIM_BTA_TIMEOUT(x) ((x) << 16)
|
||||
|
||||
/* DSIM_CLKCTRL */
|
||||
#define DSIM_ESC_PRESCALER(x) (((x) & 0xffff) << 0)
|
||||
#define DSIM_ESC_PRESCALER_MASK (0xffff << 0)
|
||||
#define DSIM_LANE_ESC_CLK_EN_CLK BIT(19)
|
||||
#define DSIM_LANE_ESC_CLK_EN_DATA(x) (((x) & 0xf) << 20)
|
||||
#define DSIM_LANE_ESC_CLK_EN_DATA_MASK (0xf << 20)
|
||||
#define DSIM_BYTE_CLKEN BIT(24)
|
||||
#define DSIM_BYTE_CLK_SRC(x) (((x) & 0x3) << 25)
|
||||
#define DSIM_BYTE_CLK_SRC_MASK (0x3 << 25)
|
||||
#define DSIM_PLL_BYPASS BIT(27)
|
||||
#define DSIM_ESC_CLKEN BIT(28)
|
||||
#define DSIM_TX_REQUEST_HSCLK BIT(31)
|
||||
#define DSIM_ESC_PRESCALER(x) (((x) & 0xffff) << 0)
|
||||
#define DSIM_ESC_PRESCALER_MASK (0xffff << 0)
|
||||
#define DSIM_LANE_ESC_CLK_EN_DATA(x, offset) (((x) & 0xf) << offset)
|
||||
#define DSIM_LANE_ESC_CLK_EN_DATA_MASK(offset) (0xf << offset)
|
||||
#define DSIM_BYTE_CLK_SRC(x) (((x) & 0x3) << 25)
|
||||
#define DSIM_BYTE_CLK_SRC_MASK (0x3 << 25)
|
||||
#define DSIM_PLL_BYPASS BIT(27)
|
||||
|
||||
/* DSIM_CONFIG */
|
||||
#define DSIM_LANE_EN_CLK BIT(0)
|
||||
@@ -91,7 +86,6 @@
|
||||
*/
|
||||
#define DSIM_HSE_DISABLE_MODE BIT(23)
|
||||
#define DSIM_AUTO_MODE BIT(24)
|
||||
#define DSIM_VIDEO_MODE BIT(25)
|
||||
#define DSIM_BURST_MODE BIT(26)
|
||||
#define DSIM_SYNC_INFORM BIT(27)
|
||||
#define DSIM_EOT_DISABLE BIT(28)
|
||||
@@ -129,9 +123,9 @@
|
||||
#define DSIM_MAIN_HBP_MASK ((0xffff) << 0)
|
||||
|
||||
/* DSIM_MSYNC */
|
||||
#define DSIM_MAIN_VSA(x) ((x) << 22)
|
||||
#define DSIM_MAIN_VSA(x, offset) ((x) << offset)
|
||||
#define DSIM_MAIN_HSA(x) ((x) << 0)
|
||||
#define DSIM_MAIN_VSA_MASK ((0x3ff) << 22)
|
||||
#define DSIM_MAIN_VSA_MASK(offset) ((0x3ff) << offset)
|
||||
#define DSIM_MAIN_HSA_MASK ((0xffff) << 0)
|
||||
|
||||
/* DSIM_SDRESOL */
|
||||
@@ -157,6 +151,11 @@
|
||||
#define DSIM_INT_RX_ECC_ERR BIT(15)
|
||||
#define DSIM_INT_RX_CRC_ERR BIT(14)
|
||||
|
||||
/* DSIM_SFRCTRL */
|
||||
#define DSIM_SFR_CTRL_STAND_BY BIT(4)
|
||||
#define DSIM_SFR_CTRL_SHADOW_UPDATE BIT(1)
|
||||
#define DSIM_SFR_CTRL_SHADOW_EN BIT(0)
|
||||
|
||||
/* DSIM_FIFOCTRL */
|
||||
#define DSIM_RX_DATA_FULL BIT(25)
|
||||
#define DSIM_RX_DATA_EMPTY BIT(24)
|
||||
@@ -191,9 +190,7 @@
|
||||
#define DSIM_PLL_DPDNSWAP_DAT (1 << 24)
|
||||
#define DSIM_FREQ_BAND(x) ((x) << 24)
|
||||
#define DSIM_PLL_EN BIT(23)
|
||||
#define DSIM_PLL_P(x, offset) ((x) << (offset))
|
||||
#define DSIM_PLL_M(x) ((x) << 4)
|
||||
#define DSIM_PLL_S(x) ((x) << 1)
|
||||
#define DSIM_PLL(x, offset) ((x) << (offset))
|
||||
|
||||
/* DSIM_PHYCTRL */
|
||||
#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0)
|
||||
@@ -222,25 +219,42 @@
|
||||
#define DSI_XFER_TIMEOUT_MS 100
|
||||
#define DSI_RX_FIFO_EMPTY 0x30800002
|
||||
|
||||
#define OLD_SCLK_MIPI_CLK_NAME "pll_clk"
|
||||
|
||||
#define PS_TO_CYCLE(ps, hz) DIV64_U64_ROUND_CLOSEST(((ps) * (hz)), 1000000000000ULL)
|
||||
|
||||
static const char *const clk_names[5] = {
|
||||
"bus_clk",
|
||||
"sclk_mipi",
|
||||
"phyclk_mipidphy0_bitclkdiv8",
|
||||
"phyclk_mipidphy0_rxclkesc0",
|
||||
"sclk_rgb_vclk_to_dsim0"
|
||||
};
|
||||
|
||||
enum samsung_dsim_transfer_type {
|
||||
EXYNOS_DSI_TX,
|
||||
EXYNOS_DSI_RX,
|
||||
};
|
||||
|
||||
static struct clk_bulk_data exynos3_clk_bulk_data[] = {
|
||||
{ .id = "bus_clk" },
|
||||
{ .id = "pll_clk" },
|
||||
};
|
||||
|
||||
static struct clk_bulk_data exynos4_clk_bulk_data[] = {
|
||||
{ .id = "bus_clk" },
|
||||
{ .id = "sclk_mipi" },
|
||||
};
|
||||
|
||||
static struct clk_bulk_data exynos5433_clk_bulk_data[] = {
|
||||
{ .id = "bus_clk" },
|
||||
{ .id = "sclk_mipi" },
|
||||
{ .id = "phyclk_mipidphy0_bitclkdiv8" },
|
||||
{ .id = "phyclk_mipidphy0_rxclkesc0" },
|
||||
{ .id = "sclk_rgb_vclk_to_dsim0" },
|
||||
};
|
||||
|
||||
static struct clk_bulk_data exynos7870_clk_bulk_data[] = {
|
||||
{ .id = "bus" },
|
||||
{ .id = "pll" },
|
||||
{ .id = "byte" },
|
||||
{ .id = "esc" },
|
||||
};
|
||||
|
||||
enum reg_idx {
|
||||
DSIM_STATUS_REG, /* Status register */
|
||||
DSIM_STATUS_REG, /* Status register (legacy) */
|
||||
DSIM_LINK_STATUS_REG, /* Link status register */
|
||||
DSIM_DPHY_STATUS_REG, /* D-PHY status register */
|
||||
DSIM_SWRST_REG, /* Software reset register */
|
||||
DSIM_CLKCTRL_REG, /* Clock control register */
|
||||
DSIM_TIMEOUT_REG, /* Time out register */
|
||||
@@ -255,6 +269,7 @@ enum reg_idx {
|
||||
DSIM_PKTHDR_REG, /* Packet Header FIFO register */
|
||||
DSIM_PAYLOAD_REG, /* Payload FIFO register */
|
||||
DSIM_RXFIFO_REG, /* Read FIFO register */
|
||||
DSIM_SFRCTRL_REG, /* SFR standby and shadow control register */
|
||||
DSIM_FIFOCTRL_REG, /* FIFO status and control register */
|
||||
DSIM_PLLCTRL_REG, /* PLL control register */
|
||||
DSIM_PHYCTRL_REG,
|
||||
@@ -312,6 +327,32 @@ static const unsigned int exynos5433_reg_ofs[] = {
|
||||
[DSIM_PHYTIMING2_REG] = 0xBC,
|
||||
};
|
||||
|
||||
static const unsigned int exynos7870_reg_ofs[] = {
|
||||
[DSIM_LINK_STATUS_REG] = 0x04,
|
||||
[DSIM_DPHY_STATUS_REG] = 0x08,
|
||||
[DSIM_SWRST_REG] = 0x0C,
|
||||
[DSIM_CLKCTRL_REG] = 0x10,
|
||||
[DSIM_TIMEOUT_REG] = 0x14,
|
||||
[DSIM_ESCMODE_REG] = 0x1C,
|
||||
[DSIM_MDRESOL_REG] = 0x20,
|
||||
[DSIM_MVPORCH_REG] = 0x24,
|
||||
[DSIM_MHPORCH_REG] = 0x28,
|
||||
[DSIM_MSYNC_REG] = 0x2C,
|
||||
[DSIM_CONFIG_REG] = 0x30,
|
||||
[DSIM_INTSRC_REG] = 0x34,
|
||||
[DSIM_INTMSK_REG] = 0x38,
|
||||
[DSIM_PKTHDR_REG] = 0x3C,
|
||||
[DSIM_PAYLOAD_REG] = 0x40,
|
||||
[DSIM_RXFIFO_REG] = 0x44,
|
||||
[DSIM_SFRCTRL_REG] = 0x48,
|
||||
[DSIM_FIFOCTRL_REG] = 0x4C,
|
||||
[DSIM_PLLCTRL_REG] = 0x94,
|
||||
[DSIM_PHYCTRL_REG] = 0xA4,
|
||||
[DSIM_PHYTIMING_REG] = 0xB4,
|
||||
[DSIM_PHYTIMING1_REG] = 0xB8,
|
||||
[DSIM_PHYTIMING2_REG] = 0xBC,
|
||||
};
|
||||
|
||||
enum reg_value_idx {
|
||||
RESET_TYPE,
|
||||
PLL_TIMER,
|
||||
@@ -384,6 +425,24 @@ static const unsigned int exynos5433_reg_values[] = {
|
||||
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
|
||||
};
|
||||
|
||||
static const unsigned int exynos7870_reg_values[] = {
|
||||
[RESET_TYPE] = DSIM_SWRST,
|
||||
[PLL_TIMER] = 80000,
|
||||
[STOP_STATE_CNT] = 0xa,
|
||||
[PHYCTRL_ULPS_EXIT] = DSIM_PHYCTRL_ULPS_EXIT(0x177),
|
||||
[PHYCTRL_VREG_LP] = 0,
|
||||
[PHYCTRL_SLEW_UP] = 0,
|
||||
[PHYTIMING_LPX] = DSIM_PHYTIMING_LPX(0x07),
|
||||
[PHYTIMING_HS_EXIT] = DSIM_PHYTIMING_HS_EXIT(0x0c),
|
||||
[PHYTIMING_CLK_PREPARE] = DSIM_PHYTIMING1_CLK_PREPARE(0x08),
|
||||
[PHYTIMING_CLK_ZERO] = DSIM_PHYTIMING1_CLK_ZERO(0x2b),
|
||||
[PHYTIMING_CLK_POST] = DSIM_PHYTIMING1_CLK_POST(0x0d),
|
||||
[PHYTIMING_CLK_TRAIL] = DSIM_PHYTIMING1_CLK_TRAIL(0x09),
|
||||
[PHYTIMING_HS_PREPARE] = DSIM_PHYTIMING2_HS_PREPARE(0x09),
|
||||
[PHYTIMING_HS_ZERO] = DSIM_PHYTIMING2_HS_ZERO(0x0f),
|
||||
[PHYTIMING_HS_TRAIL] = DSIM_PHYTIMING2_HS_TRAIL(0x0c),
|
||||
};
|
||||
|
||||
static const unsigned int imx8mm_dsim_reg_values[] = {
|
||||
[RESET_TYPE] = DSIM_SWRST,
|
||||
[PLL_TIMER] = 500,
|
||||
@@ -405,13 +464,26 @@ static const unsigned int imx8mm_dsim_reg_values[] = {
|
||||
static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
|
||||
.reg_ofs = exynos_reg_ofs,
|
||||
.plltmr_reg = 0x50,
|
||||
.has_legacy_status_reg = 1,
|
||||
.has_freqband = 1,
|
||||
.has_clklane_stop = 1,
|
||||
.num_clks = 2,
|
||||
.clk_data = exynos3_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos3_clk_bulk_data),
|
||||
.max_freq = 1000,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 1,
|
||||
.num_bits_resol = 11,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
@@ -424,13 +496,26 @@ static const struct samsung_dsim_driver_data exynos3_dsi_driver_data = {
|
||||
static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
|
||||
.reg_ofs = exynos_reg_ofs,
|
||||
.plltmr_reg = 0x50,
|
||||
.has_legacy_status_reg = 1,
|
||||
.has_freqband = 1,
|
||||
.has_clklane_stop = 1,
|
||||
.num_clks = 2,
|
||||
.clk_data = exynos4_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos4_clk_bulk_data),
|
||||
.max_freq = 1000,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 1,
|
||||
.num_bits_resol = 11,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
@@ -443,11 +528,24 @@ static const struct samsung_dsim_driver_data exynos4_dsi_driver_data = {
|
||||
static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
|
||||
.reg_ofs = exynos_reg_ofs,
|
||||
.plltmr_reg = 0x58,
|
||||
.num_clks = 2,
|
||||
.has_legacy_status_reg = 1,
|
||||
.clk_data = exynos3_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos3_clk_bulk_data),
|
||||
.max_freq = 1000,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 1,
|
||||
.num_bits_resol = 11,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
@@ -459,12 +557,25 @@ static const struct samsung_dsim_driver_data exynos5_dsi_driver_data = {
|
||||
static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
|
||||
.reg_ofs = exynos5433_reg_ofs,
|
||||
.plltmr_reg = 0xa0,
|
||||
.has_legacy_status_reg = 1,
|
||||
.has_clklane_stop = 1,
|
||||
.num_clks = 5,
|
||||
.clk_data = exynos5433_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos5433_clk_bulk_data),
|
||||
.max_freq = 1500,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 0,
|
||||
.num_bits_resol = 12,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = exynos5433_reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
@@ -476,12 +587,25 @@ static const struct samsung_dsim_driver_data exynos5433_dsi_driver_data = {
|
||||
static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
|
||||
.reg_ofs = exynos5433_reg_ofs,
|
||||
.plltmr_reg = 0xa0,
|
||||
.has_legacy_status_reg = 1,
|
||||
.has_clklane_stop = 1,
|
||||
.num_clks = 2,
|
||||
.clk_data = exynos3_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos3_clk_bulk_data),
|
||||
.max_freq = 1500,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 1,
|
||||
.num_bits_resol = 12,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = exynos5422_reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
@@ -490,19 +614,62 @@ static const struct samsung_dsim_driver_data exynos5422_dsi_driver_data = {
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data exynos7870_dsi_driver_data = {
|
||||
.reg_ofs = exynos7870_reg_ofs,
|
||||
.plltmr_reg = 0xa0,
|
||||
.has_clklane_stop = 1,
|
||||
.has_sfrctrl = 1,
|
||||
.clk_data = exynos7870_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos7870_clk_bulk_data),
|
||||
.max_freq = 1500,
|
||||
.wait_for_hdr_fifo = 0,
|
||||
.wait_for_reset = 1,
|
||||
.num_bits_resol = 12,
|
||||
.video_mode_bit = 18,
|
||||
.pll_stable_bit = 24,
|
||||
.esc_clken_bit = 16,
|
||||
.byte_clken_bit = 17,
|
||||
.tx_req_hsclk_bit = 20,
|
||||
.lane_esc_clk_bit = 8,
|
||||
.lane_esc_data_offset = 9,
|
||||
.pll_p_offset = 13,
|
||||
.pll_m_offset = 3,
|
||||
.pll_s_offset = 0,
|
||||
.main_vsa_offset = 16,
|
||||
.reg_values = exynos7870_reg_values,
|
||||
.pll_fin_min = 6,
|
||||
.pll_fin_max = 12,
|
||||
.m_min = 41,
|
||||
.m_max = 125,
|
||||
.min_freq = 500,
|
||||
};
|
||||
|
||||
static const struct samsung_dsim_driver_data imx8mm_dsi_driver_data = {
|
||||
.reg_ofs = exynos5433_reg_ofs,
|
||||
.plltmr_reg = 0xa0,
|
||||
.has_legacy_status_reg = 1,
|
||||
.has_clklane_stop = 1,
|
||||
.num_clks = 2,
|
||||
.clk_data = exynos4_clk_bulk_data,
|
||||
.num_clks = ARRAY_SIZE(exynos4_clk_bulk_data),
|
||||
.max_freq = 2100,
|
||||
.wait_for_hdr_fifo = 1,
|
||||
.wait_for_reset = 0,
|
||||
.num_bits_resol = 12,
|
||||
.video_mode_bit = 25,
|
||||
.pll_stable_bit = 31,
|
||||
.esc_clken_bit = 28,
|
||||
.byte_clken_bit = 24,
|
||||
.tx_req_hsclk_bit = 31,
|
||||
.lane_esc_clk_bit = 19,
|
||||
.lane_esc_data_offset = 20,
|
||||
/*
|
||||
* Unlike Exynos, PLL_P(PMS_P) offset 14 is used in i.MX8M Mini/Nano/Plus
|
||||
* downstream driver - drivers/gpu/drm/bridge/sec-dsim.c
|
||||
*/
|
||||
.pll_p_offset = 14,
|
||||
.pll_m_offset = 4,
|
||||
.pll_s_offset = 1,
|
||||
.main_vsa_offset = 22,
|
||||
.reg_values = imx8mm_dsim_reg_values,
|
||||
.pll_fin_min = 2,
|
||||
.pll_fin_max = 30,
|
||||
@@ -518,6 +685,7 @@ samsung_dsim_types[DSIM_TYPE_COUNT] = {
|
||||
[DSIM_TYPE_EXYNOS5410] = &exynos5_dsi_driver_data,
|
||||
[DSIM_TYPE_EXYNOS5422] = &exynos5422_dsi_driver_data,
|
||||
[DSIM_TYPE_EXYNOS5433] = &exynos5433_dsi_driver_data,
|
||||
[DSIM_TYPE_EXYNOS7870] = &exynos7870_dsi_driver_data,
|
||||
[DSIM_TYPE_IMX8MM] = &imx8mm_dsi_driver_data,
|
||||
[DSIM_TYPE_IMX8MP] = &imx8mm_dsi_driver_data,
|
||||
};
|
||||
@@ -653,8 +821,9 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
|
||||
writel(driver_data->reg_values[PLL_TIMER],
|
||||
dsi->reg_base + driver_data->plltmr_reg);
|
||||
|
||||
reg = DSIM_PLL_EN | DSIM_PLL_P(p, driver_data->pll_p_offset) |
|
||||
DSIM_PLL_M(m) | DSIM_PLL_S(s);
|
||||
reg = DSIM_PLL_EN | DSIM_PLL(p, driver_data->pll_p_offset)
|
||||
| DSIM_PLL(m, driver_data->pll_m_offset)
|
||||
| DSIM_PLL(s, driver_data->pll_s_offset);
|
||||
|
||||
if (driver_data->has_freqband) {
|
||||
static const unsigned long freq_bands[] = {
|
||||
@@ -682,14 +851,17 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
|
||||
|
||||
samsung_dsim_write(dsi, DSIM_PLLCTRL_REG, reg);
|
||||
|
||||
timeout = 1000;
|
||||
timeout = 3000;
|
||||
do {
|
||||
if (timeout-- == 0) {
|
||||
dev_err(dsi->dev, "PLL failed to stabilize\n");
|
||||
return 0;
|
||||
}
|
||||
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
|
||||
} while ((reg & DSIM_PLL_STABLE) == 0);
|
||||
if (driver_data->has_legacy_status_reg)
|
||||
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
|
||||
else
|
||||
reg = samsung_dsim_read(dsi, DSIM_LINK_STATUS_REG);
|
||||
} while ((reg & BIT(driver_data->pll_stable_bit)) == 0);
|
||||
|
||||
dsi->hs_clock = fout;
|
||||
|
||||
@@ -698,6 +870,7 @@ static unsigned long samsung_dsim_set_pll(struct samsung_dsim *dsi,
|
||||
|
||||
static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
|
||||
{
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
unsigned long hs_clk, byte_clk, esc_clk, pix_clk;
|
||||
unsigned long esc_div;
|
||||
u32 reg;
|
||||
@@ -731,15 +904,17 @@ static int samsung_dsim_enable_clock(struct samsung_dsim *dsi)
|
||||
hs_clk, byte_clk, esc_clk);
|
||||
|
||||
reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG);
|
||||
reg &= ~(DSIM_ESC_PRESCALER_MASK | DSIM_LANE_ESC_CLK_EN_CLK
|
||||
| DSIM_LANE_ESC_CLK_EN_DATA_MASK | DSIM_PLL_BYPASS
|
||||
| DSIM_BYTE_CLK_SRC_MASK);
|
||||
reg |= DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN
|
||||
| DSIM_ESC_PRESCALER(esc_div)
|
||||
| DSIM_LANE_ESC_CLK_EN_CLK
|
||||
| DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1)
|
||||
| DSIM_BYTE_CLK_SRC(0)
|
||||
| DSIM_TX_REQUEST_HSCLK;
|
||||
reg &= ~(DSIM_ESC_PRESCALER_MASK | BIT(driver_data->lane_esc_clk_bit)
|
||||
| DSIM_LANE_ESC_CLK_EN_DATA_MASK(driver_data->lane_esc_data_offset)
|
||||
| DSIM_PLL_BYPASS
|
||||
| DSIM_BYTE_CLK_SRC_MASK);
|
||||
reg |= BIT(driver_data->esc_clken_bit) | BIT(driver_data->byte_clken_bit)
|
||||
| DSIM_ESC_PRESCALER(esc_div)
|
||||
| BIT(driver_data->lane_esc_clk_bit)
|
||||
| DSIM_LANE_ESC_CLK_EN_DATA(BIT(dsi->lanes) - 1,
|
||||
driver_data->lane_esc_data_offset)
|
||||
| DSIM_BYTE_CLK_SRC(0)
|
||||
| BIT(driver_data->tx_req_hsclk_bit);
|
||||
samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
|
||||
|
||||
return 0;
|
||||
@@ -843,11 +1018,14 @@ static void samsung_dsim_set_phy_ctrl(struct samsung_dsim *dsi)
|
||||
|
||||
static void samsung_dsim_disable_clock(struct samsung_dsim *dsi)
|
||||
{
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
u32 reg;
|
||||
|
||||
reg = samsung_dsim_read(dsi, DSIM_CLKCTRL_REG);
|
||||
reg &= ~(DSIM_LANE_ESC_CLK_EN_CLK | DSIM_LANE_ESC_CLK_EN_DATA_MASK
|
||||
| DSIM_ESC_CLKEN | DSIM_BYTE_CLKEN);
|
||||
reg &= ~(BIT(driver_data->lane_esc_clk_bit)
|
||||
| DSIM_LANE_ESC_CLK_EN_DATA_MASK(driver_data->lane_esc_data_offset)
|
||||
| BIT(driver_data->esc_clken_bit)
|
||||
| BIT(driver_data->byte_clken_bit));
|
||||
samsung_dsim_write(dsi, DSIM_CLKCTRL_REG, reg);
|
||||
|
||||
reg = samsung_dsim_read(dsi, DSIM_PLLCTRL_REG);
|
||||
@@ -891,7 +1069,7 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
|
||||
* mode, otherwise it will support command mode.
|
||||
*/
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
reg |= DSIM_VIDEO_MODE;
|
||||
reg |= BIT(driver_data->video_mode_bit);
|
||||
|
||||
/*
|
||||
* The user manual describes that following bits are ignored in
|
||||
@@ -962,7 +1140,10 @@ static int samsung_dsim_init_link(struct samsung_dsim *dsi)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
|
||||
if (driver_data->has_legacy_status_reg)
|
||||
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
|
||||
else
|
||||
reg = samsung_dsim_read(dsi, DSIM_DPHY_STATUS_REG);
|
||||
if ((reg & DSIM_STOP_STATE_DAT(lanes_mask))
|
||||
!= DSIM_STOP_STATE_DAT(lanes_mask))
|
||||
continue;
|
||||
@@ -983,6 +1164,7 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
|
||||
{
|
||||
struct drm_display_mode *m = &dsi->mode;
|
||||
unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
|
||||
unsigned int main_vsa_offset = dsi->driver_data->main_vsa_offset;
|
||||
u32 reg;
|
||||
|
||||
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
|
||||
@@ -1009,7 +1191,7 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
|
||||
reg = DSIM_MAIN_HFP(hfp) | DSIM_MAIN_HBP(hbp);
|
||||
samsung_dsim_write(dsi, DSIM_MHPORCH_REG, reg);
|
||||
|
||||
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start)
|
||||
reg = DSIM_MAIN_VSA(m->vsync_end - m->vsync_start, main_vsa_offset)
|
||||
| DSIM_MAIN_HSA(hsa);
|
||||
samsung_dsim_write(dsi, DSIM_MSYNC_REG, reg);
|
||||
}
|
||||
@@ -1023,6 +1205,7 @@ static void samsung_dsim_set_display_mode(struct samsung_dsim *dsi)
|
||||
|
||||
static void samsung_dsim_set_display_enable(struct samsung_dsim *dsi, bool enable)
|
||||
{
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
u32 reg;
|
||||
|
||||
reg = samsung_dsim_read(dsi, DSIM_MDRESOL_REG);
|
||||
@@ -1031,6 +1214,15 @@ static void samsung_dsim_set_display_enable(struct samsung_dsim *dsi, bool enabl
|
||||
else
|
||||
reg &= ~DSIM_MAIN_STAND_BY;
|
||||
samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
|
||||
|
||||
if (driver_data->has_sfrctrl) {
|
||||
reg = samsung_dsim_read(dsi, DSIM_SFRCTRL_REG);
|
||||
if (enable)
|
||||
reg |= DSIM_SFR_CTRL_STAND_BY;
|
||||
else
|
||||
reg &= ~DSIM_SFR_CTRL_STAND_BY;
|
||||
samsung_dsim_write(dsi, DSIM_SFRCTRL_REG, reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int samsung_dsim_wait_for_hdr_fifo(struct samsung_dsim *dsi)
|
||||
@@ -1087,6 +1279,7 @@ static void samsung_dsim_send_to_fifo(struct samsung_dsim *dsi,
|
||||
{
|
||||
struct device *dev = dsi->dev;
|
||||
struct mipi_dsi_packet *pkt = &xfer->packet;
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
const u8 *payload = pkt->payload + xfer->tx_done;
|
||||
u16 length = pkt->payload_length - xfer->tx_done;
|
||||
bool first = !xfer->tx_done;
|
||||
@@ -1127,9 +1320,11 @@ static void samsung_dsim_send_to_fifo(struct samsung_dsim *dsi,
|
||||
return;
|
||||
|
||||
reg = get_unaligned_le32(pkt->header);
|
||||
if (samsung_dsim_wait_for_hdr_fifo(dsi)) {
|
||||
dev_err(dev, "waiting for header FIFO timed out\n");
|
||||
return;
|
||||
if (driver_data->wait_for_hdr_fifo) {
|
||||
if (samsung_dsim_wait_for_hdr_fifo(dsi)) {
|
||||
dev_err(dev, "waiting for header FIFO timed out\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (NEQV(xfer->flags & MIPI_DSI_MSG_USE_LPM,
|
||||
@@ -1922,7 +2117,7 @@ int samsung_dsim_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct samsung_dsim *dsi;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
dsi = devm_drm_bridge_alloc(dev, struct samsung_dsim, bridge, &samsung_dsim_bridge_funcs);
|
||||
if (IS_ERR(dsi))
|
||||
@@ -1946,23 +2141,11 @@ int samsung_dsim_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "failed to get regulators\n");
|
||||
|
||||
dsi->clks = devm_kcalloc(dev, dsi->driver_data->num_clks,
|
||||
sizeof(*dsi->clks), GFP_KERNEL);
|
||||
if (!dsi->clks)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < dsi->driver_data->num_clks; i++) {
|
||||
dsi->clks[i] = devm_clk_get(dev, clk_names[i]);
|
||||
if (IS_ERR(dsi->clks[i])) {
|
||||
if (strcmp(clk_names[i], "sclk_mipi") == 0) {
|
||||
dsi->clks[i] = devm_clk_get(dev, OLD_SCLK_MIPI_CLK_NAME);
|
||||
if (!IS_ERR(dsi->clks[i]))
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_info(dev, "failed to get the clock: %s\n", clk_names[i]);
|
||||
return PTR_ERR(dsi->clks[i]);
|
||||
}
|
||||
ret = devm_clk_bulk_get(dev, dsi->driver_data->num_clks,
|
||||
dsi->driver_data->clk_data);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get clocks in bulk (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dsi->reg_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
@@ -2035,7 +2218,7 @@ static int samsung_dsim_suspend(struct device *dev)
|
||||
{
|
||||
struct samsung_dsim *dsi = dev_get_drvdata(dev);
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
@@ -2051,8 +2234,7 @@ static int samsung_dsim_suspend(struct device *dev)
|
||||
|
||||
phy_power_off(dsi->phy);
|
||||
|
||||
for (i = driver_data->num_clks - 1; i > -1; i--)
|
||||
clk_disable_unprepare(dsi->clks[i]);
|
||||
clk_bulk_disable_unprepare(driver_data->num_clks, driver_data->clk_data);
|
||||
|
||||
ret = regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
||||
if (ret < 0)
|
||||
@@ -2065,7 +2247,7 @@ static int samsung_dsim_resume(struct device *dev)
|
||||
{
|
||||
struct samsung_dsim *dsi = dev_get_drvdata(dev);
|
||||
const struct samsung_dsim_driver_data *driver_data = dsi->driver_data;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
ret = regulator_bulk_enable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
||||
if (ret < 0) {
|
||||
@@ -2073,11 +2255,9 @@ static int samsung_dsim_resume(struct device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < driver_data->num_clks; i++) {
|
||||
ret = clk_prepare_enable(dsi->clks[i]);
|
||||
if (ret < 0)
|
||||
goto err_clk;
|
||||
}
|
||||
ret = clk_bulk_prepare_enable(driver_data->num_clks, driver_data->clk_data);
|
||||
if (ret < 0)
|
||||
goto err_clk;
|
||||
|
||||
ret = phy_power_on(dsi->phy);
|
||||
if (ret < 0) {
|
||||
@@ -2088,8 +2268,7 @@ static int samsung_dsim_resume(struct device *dev)
|
||||
return 0;
|
||||
|
||||
err_clk:
|
||||
while (--i > -1)
|
||||
clk_disable_unprepare(dsi->clks[i]);
|
||||
clk_bulk_disable_unprepare(driver_data->num_clks, driver_data->clk_data);
|
||||
regulator_bulk_disable(ARRAY_SIZE(dsi->supplies), dsi->supplies);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -29,6 +29,7 @@ enum samsung_dsim_type {
|
||||
DSIM_TYPE_EXYNOS5410,
|
||||
DSIM_TYPE_EXYNOS5422,
|
||||
DSIM_TYPE_EXYNOS5433,
|
||||
DSIM_TYPE_EXYNOS7870,
|
||||
DSIM_TYPE_IMX8MM,
|
||||
DSIM_TYPE_IMX8MP,
|
||||
DSIM_TYPE_COUNT,
|
||||
@@ -53,15 +54,29 @@ struct samsung_dsim_transfer {
|
||||
struct samsung_dsim_driver_data {
|
||||
const unsigned int *reg_ofs;
|
||||
unsigned int plltmr_reg;
|
||||
unsigned int has_legacy_status_reg:1;
|
||||
unsigned int has_freqband:1;
|
||||
unsigned int has_clklane_stop:1;
|
||||
unsigned int has_broken_fifoctrl_emptyhdr:1;
|
||||
unsigned int has_sfrctrl:1;
|
||||
struct clk_bulk_data *clk_data;
|
||||
unsigned int num_clks;
|
||||
unsigned int min_freq;
|
||||
unsigned int max_freq;
|
||||
unsigned int wait_for_hdr_fifo;
|
||||
unsigned int wait_for_reset;
|
||||
unsigned int num_bits_resol;
|
||||
unsigned int video_mode_bit;
|
||||
unsigned int pll_stable_bit;
|
||||
unsigned int esc_clken_bit;
|
||||
unsigned int byte_clken_bit;
|
||||
unsigned int tx_req_hsclk_bit;
|
||||
unsigned int lane_esc_clk_bit;
|
||||
unsigned int lane_esc_data_offset;
|
||||
unsigned int pll_p_offset;
|
||||
unsigned int pll_m_offset;
|
||||
unsigned int pll_s_offset;
|
||||
unsigned int main_vsa_offset;
|
||||
const unsigned int *reg_values;
|
||||
unsigned int pll_fin_min;
|
||||
unsigned int pll_fin_max;
|
||||
@@ -91,7 +106,6 @@ struct samsung_dsim {
|
||||
|
||||
void __iomem *reg_base;
|
||||
struct phy *phy;
|
||||
struct clk **clks;
|
||||
struct clk *pll_clk;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
int irq;
|
||||
|
||||
Reference in New Issue
Block a user