diff options
Diffstat (limited to 'drivers/video/nexell/soc/s5pxx18_soc_mipi.c')
-rw-r--r-- | drivers/video/nexell/soc/s5pxx18_soc_mipi.c | 580 |
1 files changed, 580 insertions, 0 deletions
diff --git a/drivers/video/nexell/soc/s5pxx18_soc_mipi.c b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c new file mode 100644 index 0000000000..1000ddb642 --- /dev/null +++ b/drivers/video/nexell/soc/s5pxx18_soc_mipi.c @@ -0,0 +1,580 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2016 Nexell Co., Ltd. + * + * Author: junghyun, kim <jhkim@nexell.co.kr> + */ + +#include <linux/types.h> +#include <linux/io.h> + +#include "s5pxx18_soc_disptop.h" +#include "s5pxx18_soc_mipi.h" + +static struct nx_mipi_register_set *__g_pregister[NUMBER_OF_MIPI_MODULE]; + +int nx_mipi_smoke_test(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + + if (pregister->csis_config_ch0 != 0x000000FC) + return false; + + if (pregister->dsim_intmsk != 0xB337FFFF) + return false; + + writel(0xDEADC0DE, &pregister->csis_dphyctrl); + writel(0xFFFFFFFF, &pregister->csis_ctrl2); + writel(0xDEADC0DE, &pregister->dsim_msync); + + if (pregister->csis_dphyctrl != 0xDE80001E) + return false; + + if ((pregister->csis_ctrl2 & (~1)) != 0xEEE00010) + return false; + + if (pregister->dsim_msync != 0xDE80C0DE) + return false; + + return true; +} + +void nx_mipi_set_base_address(u32 module_index, void *base_address) +{ + __g_pregister[module_index] = + (struct nx_mipi_register_set *)base_address; +} + +void *nx_mipi_get_base_address(u32 module_index) +{ + return (void *)__g_pregister[module_index]; +} + +u32 nx_mipi_get_physical_address(u32 module_index) +{ + const u32 physical_addr[] = PHY_BASEADDR_MIPI_LIST; + + return physical_addr[module_index]; +} + +#define __nx_mipi_valid_dsi_intmask__ \ + (~((1 << 26) | (1 << 23) | (1 << 22) | (1 << 19))) + +void nx_mipi_set_interrupt_enable(u32 module_index, u32 int_num, int enable) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + if (int_num < 32) { + regvalue = pregister->csis_intmsk; + regvalue &= ~(1ul << int_num); + regvalue |= (u32)enable << int_num; + writel(regvalue, &pregister->csis_intmsk); + } else { + regvalue = pregister->dsim_intmsk; + regvalue &= ~(1ul << (int_num - 32)); + regvalue |= (u32)enable << (int_num - 32); + writel(regvalue, &pregister->dsim_intmsk); + } +} + +int nx_mipi_get_interrupt_enable(u32 module_index, u32 int_num) +{ + if (int_num < 32) + return (int)((__g_pregister[module_index]->csis_intmsk >> + int_num) & 0x01); + else + return (int)((__g_pregister[module_index]->dsim_intmsk >> + (int_num - 32)) & 0x01); +} + +int nx_mipi_get_interrupt_pending(u32 module_index, u32 int_num) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + int ret; + + pregister = __g_pregister[module_index]; + if (int_num < 32) { + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + ret = (int)((regvalue >> int_num) & 0x01); + } else { + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + ret = (int)((regvalue >> (int_num - 32)) & 0x01); + } + + return ret; +} + +void nx_mipi_clear_interrupt_pending(u32 module_index, u32 int_num) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + if (int_num < 32) + writel(1ul << int_num, &pregister->csis_intsrc); + else + writel(1ul << (int_num - 32), &pregister->dsim_intsrc); +} + +void nx_mipi_set_interrupt_enable_all(u32 module_index, int enable) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + if (enable) + writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intmsk); + else + writel(0, &pregister->dsim_intmsk); +} + +int nx_mipi_get_interrupt_enable_all(u32 module_index) +{ + if (__g_pregister[module_index]->csis_intmsk) + return true; + + if (__g_pregister[module_index]->dsim_intmsk) + return true; + + return false; +} + +int nx_mipi_get_interrupt_pending_all(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + + if (regvalue) + return true; + + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + + if (regvalue) + return true; + + return false; +} + +void nx_mipi_clear_interrupt_pending_all(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(__nx_mipi_valid_dsi_intmask__, &pregister->dsim_intsrc); +} + +int32_t nx_mipi_get_interrupt_pending_number(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + int i; + + pregister = __g_pregister[module_index]; + regvalue = pregister->csis_intmsk; + regvalue &= pregister->csis_intsrc; + if (regvalue != 0) { + for (i = 0; i < 32; i++) { + if (regvalue & 1ul) + return i; + regvalue >>= 1; + } + } + + regvalue = pregister->dsim_intmsk; + regvalue &= pregister->dsim_intsrc; + if (regvalue != 0) { + for (i = 0; i < 32; i++) { + if (regvalue & 1ul) + return i + 32; + regvalue >>= 1; + } + } + return -1; +} + +#define writereg(regname, mask, value) \ + regvalue = pregister->(regname); \ + regvalue = (regvalue & (~(mask))) | (value); \ + writel(regvalue, &pregister->(regname)) + +void nx_mipi_dsi_get_status(u32 module_index, u32 *pulps, u32 *pstop, + u32 *pispllstable, u32 *pisinreset, + u32 *pisbackward, u32 *pishsclockready) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->dsim_status; + if (pulps) { + *pulps = 0; + if (regvalue & (1 << 4)) + *pulps |= (1 << 0); + if (regvalue & (1 << 5)) + *pulps |= (1 << 1); + if (regvalue & (1 << 6)) + *pulps |= (1 << 2); + if (regvalue & (1 << 7)) + *pulps |= (1 << 3); + if (regvalue & (1 << 9)) + *pulps |= (1 << 4); + } + + if (pstop) { + *pstop = 0; + if (regvalue & (1 << 0)) + *pstop |= (1 << 0); + if (regvalue & (1 << 1)) + *pstop |= (1 << 1); + if (regvalue & (1 << 2)) + *pstop |= (1 << 2); + if (regvalue & (1 << 3)) + *pstop |= (1 << 3); + if (regvalue & (1 << 8)) + *pstop |= (1 << 4); + } + + if (pispllstable) + *pispllstable = (regvalue >> 31) & 1; + + if (pisinreset) + *pisinreset = ((regvalue >> 20) & 1) ? 0 : 1; + + if (pisbackward) + *pisbackward = (regvalue >> 16) & 1; + + if (pishsclockready) + *pishsclockready = (regvalue >> 10) & 1; +} + +void nx_mipi_dsi_software_reset(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + + writel(0x00010001, &pregister->dsim_swrst); + + while (0 != (readl(&pregister->dsim_status) & (1 << 20))) + ; + + writel(0x00000000, &pregister->dsim_swrst); +} + +void nx_mipi_dsi_set_clock(u32 module_index, int enable_txhsclock, + int use_external_clock, int enable_byte_clock, + int enable_escclock_clock_lane, + int enable_escclock_data_lane0, + int enable_escclock_data_lane1, + int enable_escclock_data_lane2, + int enable_escclock_data_lane3, + int enable_escprescaler, u32 escprescalervalue) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = 0; + regvalue |= (enable_txhsclock << 31); + regvalue |= (use_external_clock << 27); + regvalue |= (enable_byte_clock << 24); + regvalue |= (enable_escclock_clock_lane << 19); + regvalue |= (enable_escclock_data_lane0 << 20); + regvalue |= (enable_escclock_data_lane1 << 21); + regvalue |= (enable_escclock_data_lane2 << 22); + regvalue |= (enable_escclock_data_lane3 << 23); + regvalue |= (enable_escprescaler << 28); + regvalue |= escprescalervalue; + + writel(regvalue, &pregister->dsim_clkctrl); +} + +void nx_mipi_dsi_set_timeout(u32 module_index, u32 bta_tout, u32 lpdrtout) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = 0; + regvalue |= (bta_tout << 16); + regvalue |= (lpdrtout << 0); + + writel(regvalue, &pregister->dsim_timeout); +} + +void nx_mipi_dsi_set_config_video_mode(u32 module_index, + int enable_auto_flush_main_display_fifo, + int enable_auto_vertical_count, + int enable_burst, + enum nx_mipi_dsi_syncmode sync_mode, + int enable_eo_tpacket, + int enable_hsync_end_packet, + int enable_hfp, int enable_hbp, + int enable_hsa, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format, + u32 number_of_words_in_hfp, + u32 number_of_words_in_hbp, + u32 number_of_words_in_hsync, + u32 number_of_lines_in_vfp, + u32 number_of_lines_in_vbp, + u32 number_of_lines_in_vsync, + u32 number_of_lines_in_command_allow) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (1 << 25); + newvalue |= ((1 - enable_auto_flush_main_display_fifo) << 29); + newvalue |= (enable_auto_vertical_count << 24); + newvalue |= (enable_burst << 26); + newvalue |= (sync_mode << 27); + newvalue |= ((1 - enable_eo_tpacket) << 28); + newvalue |= (enable_hsync_end_packet << 23); + newvalue |= ((1 - enable_hfp) << 22); + newvalue |= ((1 - enable_hbp) << 21); + newvalue |= ((1 - enable_hsa) << 20); + newvalue |= (number_of_virtual_channel << 18); + newvalue |= (format << 12); + + writereg(dsim_config, 0xFFFFFF00, newvalue); + + newvalue = (number_of_lines_in_command_allow << 28); + newvalue |= (number_of_lines_in_vfp << 16); + newvalue |= (number_of_lines_in_vbp << 0); + + writel(newvalue, &pregister->dsim_mvporch); + + newvalue = (number_of_words_in_hfp << 16); + newvalue |= (number_of_words_in_hbp << 0); + + writel(newvalue, &pregister->dsim_mhporch); + + newvalue = (number_of_words_in_hsync << 0); + newvalue |= (number_of_lines_in_vsync << 22); + + writel(newvalue, &pregister->dsim_msync); +} + +void nx_mipi_dsi_set_config_command_mode(u32 module_index, + int + enable_auto_flush_main_display_fifo, + int enable_eo_tpacket, + u32 number_of_virtual_channel, + enum nx_mipi_dsi_format format) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (0 << 25); + newvalue |= (enable_auto_flush_main_display_fifo << 29); + newvalue |= (enable_eo_tpacket << 28); + newvalue |= (number_of_virtual_channel << 18); + newvalue |= (format << 12); + writereg(dsim_config, 0xFFFFFF00, newvalue); +} + +void nx_mipi_dsi_set_escape_mode(u32 module_index, u32 stop_state_count, + int force_stop_state, int force_bta, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (stop_state_count << 21); + newvalue |= (force_stop_state << 20); + newvalue |= (force_bta << 16); + newvalue |= (cmdin_lp << 7); + newvalue |= (txinlp << 6); + writereg(dsim_escmode, 0xFFFFFFC0, newvalue); +} + +void nx_mipi_dsi_set_escape_lp(u32 module_index, + enum nx_mipi_dsi_lpmode cmdin_lp, + enum nx_mipi_dsi_lpmode txinlp) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue = 0; + + pregister = __g_pregister[module_index]; + newvalue |= (cmdin_lp << 7); + newvalue |= (txinlp << 6); + writereg(dsim_escmode, 0xC0, newvalue); +} + +void nx_mipi_dsi_remote_reset_trigger(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (1 << 4); + writereg(dsim_escmode, (1 << 4), newvalue); + + while (readl(&pregister->dsim_escmode) & (1 << 4)) + ; +} + +void nx_mipi_dsi_set_ulps(u32 module_index, int ulpsclocklane, int ulpsdatalane) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + regvalue = pregister->dsim_escmode; + + if (ulpsclocklane) { + regvalue &= ~(1 << 0); + regvalue |= (1 << 1); + } else { + regvalue |= (1 << 0); + } + + if (ulpsdatalane) { + regvalue &= ~(1 << 2); + regvalue |= (1 << 3); + } else { + regvalue |= (1 << 2); + } + + writel(regvalue, &pregister->dsim_escmode); + + if (ulpsclocklane) + while ((1 << 9) == + (readl(&pregister->dsim_status) & (1 << 9))) + ; + else + while (0 != (readl(&pregister->dsim_status) & (1 << 9))) + ; + + if (ulpsdatalane) + while ((15 << 4) == + (readl(&pregister->dsim_status) & (15 << 4))) + ; + else + while (0 != (readl(&pregister->dsim_status) & (15 << 4))) + ; + + if (!ulpsclocklane) + regvalue &= (3 << 0); + + if (!ulpsdatalane) + regvalue |= (3 << 2); + + writel(regvalue, &pregister->dsim_escmode); +} + +void nx_mipi_dsi_set_size(u32 module_index, u32 width, u32 height) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (height << 16); + newvalue |= (width << 0); + writereg(dsim_mdresol, 0x0FFFFFFF, newvalue); +} + +void nx_mipi_dsi_set_enable(u32 module_index, int enable) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + + pregister = __g_pregister[module_index]; + writereg(dsim_mdresol, (1 << 31), (enable << 31)); +} + +void nx_mipi_dsi_set_phy(u32 module_index, u32 number_of_data_lanes, + int enable_clock_lane, int enable_data_lane0, + int enable_data_lane1, int enable_data_lane2, + int enable_data_lane3, int swap_clock_lane, + int swap_data_lane) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + newvalue = (number_of_data_lanes << 5); + newvalue |= (enable_clock_lane << 0); + newvalue |= (enable_data_lane0 << 1); + newvalue |= (enable_data_lane1 << 2); + newvalue |= (enable_data_lane2 << 3); + newvalue |= (enable_data_lane3 << 4); + writereg(dsim_config, 0xFF, newvalue); + newvalue = (swap_clock_lane << 1); + newvalue |= (swap_data_lane << 0); + writereg(dsim_phyacchr1, 0x3, newvalue); +} + +void nx_mipi_dsi_set_pll(u32 module_index, int enable, u32 pllstabletimer, + u32 m_pllpms, u32 m_bandctl, u32 m_dphyctl, + u32 b_dphyctl) +{ + register struct nx_mipi_register_set *pregister; + register u32 regvalue; + u32 newvalue; + + pregister = __g_pregister[module_index]; + if (!enable) { + newvalue = (enable << 23); + newvalue |= (m_pllpms << 1); + newvalue |= (m_bandctl << 24); + writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue); + } + + writel(m_dphyctl, &pregister->dsim_phyacchr); + writel(pllstabletimer, &pregister->dsim_plltmr); + writel((b_dphyctl << 9), &pregister->dsim_phyacchr1); + + if (enable) { + newvalue = (enable << 23); + newvalue |= (m_pllpms << 1); + newvalue |= (m_bandctl << 24); + writereg(dsim_pllctrl, 0x0FFFFFFF, newvalue); + } +} + +void nx_mipi_dsi_write_pkheader(u32 module_index, u32 data) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(data, &pregister->dsim_pkthdr); +} + +void nx_mipi_dsi_write_payload(u32 module_index, u32 data) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + writel(data, &pregister->dsim_payload); +} + +u32 nx_mipi_dsi_read_fifo_status(u32 module_index) +{ + register struct nx_mipi_register_set *pregister; + + pregister = __g_pregister[module_index]; + return readl(&pregister->dsim_fifoctrl); +} |