From 08a7aa1e5be7059d680fedf0a885655a895f638e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:38 -0700 Subject: exynos: video: Move driver files into their own directory Move all the exynos video drivers into one place for ease of maintenance. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/Makefile | 6 +- drivers/video/exynos/Makefile | 12 + drivers/video/exynos/exynos_dp.c | 961 +++++++++++++++++ drivers/video/exynos/exynos_dp_lowlevel.c | 1257 +++++++++++++++++++++++ drivers/video/exynos/exynos_dp_lowlevel.h | 68 ++ drivers/video/exynos/exynos_fb.c | 330 ++++++ drivers/video/exynos/exynos_fb.h | 41 + drivers/video/exynos/exynos_fimd.c | 409 ++++++++ drivers/video/exynos/exynos_mipi_dsi.c | 337 ++++++ drivers/video/exynos/exynos_mipi_dsi_common.c | 620 +++++++++++ drivers/video/exynos/exynos_mipi_dsi_common.h | 35 + drivers/video/exynos/exynos_mipi_dsi_lowlevel.c | 639 ++++++++++++ drivers/video/exynos/exynos_mipi_dsi_lowlevel.h | 98 ++ drivers/video/exynos/exynos_pwm_bl.c | 45 + drivers/video/exynos_dp.c | 961 ----------------- drivers/video/exynos_dp_lowlevel.c | 1257 ----------------------- drivers/video/exynos_dp_lowlevel.h | 68 -- drivers/video/exynos_fb.c | 330 ------ drivers/video/exynos_fb.h | 41 - drivers/video/exynos_fimd.c | 409 -------- drivers/video/exynos_mipi_dsi.c | 337 ------ drivers/video/exynos_mipi_dsi_common.c | 620 ----------- drivers/video/exynos_mipi_dsi_common.h | 35 - drivers/video/exynos_mipi_dsi_lowlevel.c | 639 ------------ drivers/video/exynos_mipi_dsi_lowlevel.h | 98 -- drivers/video/exynos_pwm_bl.c | 45 - drivers/video/s6e8ax0.c | 4 +- 27 files changed, 4855 insertions(+), 4847 deletions(-) create mode 100644 drivers/video/exynos/Makefile create mode 100644 drivers/video/exynos/exynos_dp.c create mode 100644 drivers/video/exynos/exynos_dp_lowlevel.c create mode 100644 drivers/video/exynos/exynos_dp_lowlevel.h create mode 100644 drivers/video/exynos/exynos_fb.c create mode 100644 drivers/video/exynos/exynos_fb.h create mode 100644 drivers/video/exynos/exynos_fimd.c create mode 100644 drivers/video/exynos/exynos_mipi_dsi.c create mode 100644 drivers/video/exynos/exynos_mipi_dsi_common.c create mode 100644 drivers/video/exynos/exynos_mipi_dsi_common.h create mode 100644 drivers/video/exynos/exynos_mipi_dsi_lowlevel.c create mode 100644 drivers/video/exynos/exynos_mipi_dsi_lowlevel.h create mode 100644 drivers/video/exynos/exynos_pwm_bl.c delete mode 100644 drivers/video/exynos_dp.c delete mode 100644 drivers/video/exynos_dp_lowlevel.c delete mode 100644 drivers/video/exynos_dp_lowlevel.h delete mode 100644 drivers/video/exynos_fb.c delete mode 100644 drivers/video/exynos_fb.h delete mode 100644 drivers/video/exynos_fimd.c delete mode 100644 drivers/video/exynos_mipi_dsi.c delete mode 100644 drivers/video/exynos_mipi_dsi_common.c delete mode 100644 drivers/video/exynos_mipi_dsi_common.h delete mode 100644 drivers/video/exynos_mipi_dsi_lowlevel.c delete mode 100644 drivers/video/exynos_mipi_dsi_lowlevel.h delete mode 100644 drivers/video/exynos_pwm_bl.c (limited to 'drivers/video') diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 2fd0891..3f045fe 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -25,11 +25,6 @@ obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o obj-$(CONFIG_ATMEL_LCD) += atmel_lcdfb.o obj-$(CONFIG_CFB_CONSOLE) += cfb_console.o -obj-$(CONFIG_EXYNOS_DP) += exynos_dp.o exynos_dp_lowlevel.o -obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o exynos_fimd.o -obj-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ - exynos_mipi_dsi_lowlevel.o -obj-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o obj-$(CONFIG_FSL_DIU_FB) += fsl_diu_fb.o videomodes.o obj-$(CONFIG_FSL_DCU_FB) += fsl_dcu_fb.o videomodes.o obj-$(CONFIG_L5F31188) += l5f31188.o @@ -68,6 +63,7 @@ obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o obj-${CONFIG_VIDEO_TEGRA124} += tegra124/ +obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-y += bridge/ diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile new file mode 100644 index 0000000..d4bdf32 --- /dev/null +++ b/drivers/video/exynos/Makefile @@ -0,0 +1,12 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_EXYNOS_DP) += exynos_dp.o exynos_dp_lowlevel.o +obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o exynos_fimd.o +obj-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ + exynos_mipi_dsi_lowlevel.o +obj-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c new file mode 100644 index 0000000..0d5d090 --- /dev/null +++ b/drivers/video/exynos/exynos_dp.c @@ -0,0 +1,961 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos_dp_lowlevel.h" + +DECLARE_GLOBAL_DATA_PTR; + +void __exynos_set_dp_phy(unsigned int onoff) +{ +} +void exynos_set_dp_phy(unsigned int onoff) + __attribute__((weak, alias("__exynos_set_dp_phy"))); + +static void exynos_dp_disp_info(struct edp_disp_info *disp_info) +{ + disp_info->h_total = disp_info->h_res + disp_info->h_sync_width + + disp_info->h_back_porch + disp_info->h_front_porch; + disp_info->v_total = disp_info->v_res + disp_info->v_sync_width + + disp_info->v_back_porch + disp_info->v_front_porch; + + return; +} + +static int exynos_dp_init_dp(void) +{ + int ret; + exynos_dp_reset(); + + /* SW defined function Normal operation */ + exynos_dp_enable_sw_func(DP_ENABLE); + + ret = exynos_dp_init_analog_func(); + if (ret != EXYNOS_DP_SUCCESS) + return ret; + + exynos_dp_init_hpd(); + exynos_dp_init_aux(); + + return ret; +} + +static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) +{ + int i; + unsigned char sum = 0; + + for (i = 0; i < EDID_BLOCK_LENGTH; i++) + sum = sum + edid_data[i]; + + return sum; +} + +static unsigned int exynos_dp_read_edid(void) +{ + unsigned char edid[EDID_BLOCK_LENGTH * 2]; + unsigned int extend_block = 0; + unsigned char sum; + unsigned char test_vector; + int retval; + + /* + * EDID device address is 0x50. + * However, if necessary, you must have set upper address + * into E-EDID in I2C device, 0x30. + */ + + /* Read Extension Flag, Number of 128-byte EDID extension blocks */ + exynos_dp_read_byte_from_i2c(I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, + &extend_block); + + if (extend_block > 0) { + printf("DP EDID data includes a single extension!\n"); + + /* Read EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + if (retval != 0) { + printf("DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(edid); + if (sum != 0) { + printf("DP EDID bad checksum!\n"); + return -1; + } + + /* Read additional EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_BLOCK_LENGTH, + EDID_BLOCK_LENGTH, + &edid[EDID_BLOCK_LENGTH]); + if (retval != 0) { + printf("DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); + if (sum != 0) { + printf("DP EDID bad checksum!\n"); + return -1; + } + + exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + &test_vector); + if (test_vector & DPCD_TEST_EDID_READ) { + exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + DPCD_TEST_EDID_CHECKSUM_WRITE); + } + } else { + debug("DP EDID data does not include any extensions.\n"); + + /* Read EDID data */ + retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); + + if (retval != 0) { + printf("DP EDID Read failed!\n"); + return -1; + } + sum = exynos_dp_calc_edid_check_sum(edid); + if (sum != 0) { + printf("DP EDID bad checksum!\n"); + return -1; + } + + exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + &test_vector); + if (test_vector & DPCD_TEST_EDID_READ) { + exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + edid[EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + DPCD_TEST_EDID_CHECKSUM_WRITE); + } + } + + debug("DP EDID Read success!\n"); + + return 0; +} + +static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) +{ + unsigned char buf[12]; + unsigned int ret; + unsigned char temp; + unsigned char retry_cnt; + unsigned char dpcd_rev[16]; + unsigned char lane_bw[16]; + unsigned char lane_cnt[16]; + + memset(dpcd_rev, 0, 16); + memset(lane_bw, 0, 16); + memset(lane_cnt, 0, 16); + memset(buf, 0, 12); + + retry_cnt = 5; + while (retry_cnt) { + /* Read DPCD 0x0000-0x000b */ + ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12, + buf); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printf("DP read_byte_from_dpcd() failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + + /* */ + temp = buf[DPCD_DPCD_REV]; + if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11) + edp_info->dpcd_rev = temp; + else { + printf("DP Wrong DPCD Rev : %x\n", temp); + return -ENODEV; + } + + temp = buf[DPCD_MAX_LINK_RATE]; + if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70) + edp_info->lane_bw = temp; + else { + printf("DP Wrong MAX LINK RATE : %x\n", temp); + return -EINVAL; + } + + /* Refer VESA Display Port Standard Ver1.1a Page 120 */ + if (edp_info->dpcd_rev == DP_DPCD_REV_11) { + temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f; + if (buf[DPCD_MAX_LANE_COUNT] & 0x80) + edp_info->dpcd_efc = 1; + else + edp_info->dpcd_efc = 0; + } else { + temp = buf[DPCD_MAX_LANE_COUNT]; + edp_info->dpcd_efc = 0; + } + + if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 || + temp == DP_LANE_CNT_4) { + edp_info->lane_cnt = temp; + } else { + printf("DP Wrong MAX LANE COUNT : %x\n", temp); + return -EINVAL; + } + + ret = exynos_dp_read_edid(); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP exynos_dp_read_edid() failed\n"); + return -EINVAL; + } + + return ret; +} + +static void exynos_dp_init_training(void) +{ + /* + * MACRO_RST must be applied after the PLL_LOCK to avoid + * the DP inter pair skew issue for at least 10 us + */ + exynos_dp_reset_macro(); + + /* All DP analog module power up */ + exynos_dp_set_analog_power_down(POWER_ALL, 0); +} + +static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) +{ + unsigned char buf[5]; + unsigned int ret = 0; + + debug("DP: %s was called\n", __func__); + + edp_info->lt_info.lt_status = DP_LT_CR; + edp_info->lt_info.ep_loop = 0; + edp_info->lt_info.cr_loop[0] = 0; + edp_info->lt_info.cr_loop[1] = 0; + edp_info->lt_info.cr_loop[2] = 0; + edp_info->lt_info.cr_loop[3] = 0; + + /* Set sink to D0 (Sink Not Ready) mode. */ + ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE, + DPCD_SET_POWER_STATE_D0); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write_dpcd_byte failed\n"); + return ret; + } + + /* Set link rate and count as you want to establish */ + exynos_dp_set_link_bandwidth(edp_info->lane_bw); + exynos_dp_set_lane_count(edp_info->lane_cnt); + + /* Setup RX configuration */ + buf[0] = edp_info->lane_bw; + buf[1] = edp_info->lane_cnt; + + ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2, + buf); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write_dpcd_byte failed\n"); + return ret; + } + + exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0, + edp_info->lane_cnt); + + /* Set training pattern 1 */ + exynos_dp_set_training_pattern(TRAINING_PTN1); + + /* Set RX training pattern */ + buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; + + buf[1] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[2] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[3] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | + DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; + + ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET, + 5, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write_dpcd_byte failed\n"); + return ret; + } + + return ret; +} + +static unsigned int exynos_dp_training_pattern_dis(void) +{ + unsigned int ret = EXYNOS_DP_SUCCESS; + + exynos_dp_set_training_pattern(DP_NONE); + + ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + DPCD_TRAINING_PATTERN_DISABLED); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP request_link_training_req failed\n"); + return -EAGAIN; + } + + return ret; +} + +static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) +{ + unsigned char data; + unsigned int ret = EXYNOS_DP_SUCCESS; + + ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET, + &data); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read_from_dpcd failed\n"); + return -EAGAIN; + } + + if (enable) + data = DPCD_ENHANCED_FRAME_EN | DPCD_LN_COUNT_SET(data); + else + data = DPCD_LN_COUNT_SET(data); + + ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET, + data); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write_to_dpcd failed\n"); + return -EAGAIN; + + } + + return ret; +} + +static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode) +{ + unsigned int ret = EXYNOS_DP_SUCCESS; + + ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP rx_enhance_mode failed\n"); + return -EAGAIN; + } + + exynos_dp_enable_enhanced_mode(enhance_mode); + + return ret; +} + +static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, + unsigned char *status) +{ + unsigned int ret, i; + unsigned char buf[2]; + unsigned char lane_stat[DP_LANE_CNT_4] = {0,}; + unsigned char shift_val[DP_LANE_CNT_4] = {0,}; + + shift_val[0] = 0; + shift_val[1] = 4; + shift_val[2] = 0; + shift_val[3] = 4; + + ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read lane status failed\n"); + return ret; + } + + for (i = 0; i < edp_info->lane_cnt; i++) { + lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f; + if (lane_stat[0] != lane_stat[i]) { + printf("Wrong lane status\n"); + return -EINVAL; + } + } + + *status = lane_stat[0]; + + return ret; +} + +static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, + unsigned char *sw, unsigned char *em) +{ + unsigned int ret = EXYNOS_DP_SUCCESS; + unsigned char buf; + unsigned int dpcd_addr; + unsigned char shift_val[DP_LANE_CNT_4] = {0, 4, 0, 4}; + + /* lane_num value is used as array index, so this range 0 ~ 3 */ + dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); + + ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read adjust request failed\n"); + return -EAGAIN; + } + + *sw = ((buf >> shift_val[lane_num]) & 0x03); + *em = ((buf >> shift_val[lane_num]) & 0x0c) >> 2; + + return ret; +} + +static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) +{ + int ret; + + ret = exynos_dp_training_pattern_dis(); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP training_pattern_disable() failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP set_enhanced_mode() failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + return ret; +} + +static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) +{ + int ret; + + if (edp_info->lane_bw == DP_LANE_BW_2_70) { + edp_info->lane_bw = DP_LANE_BW_1_62; + printf("DP Change lane bw to 1.62Gbps\n"); + edp_info->lt_info.lt_status = DP_LT_START; + ret = EXYNOS_DP_SUCCESS; + } else { + ret = exynos_dp_training_pattern_dis(); + if (ret != EXYNOS_DP_SUCCESS) + printf("DP training_patter_disable() failed\n"); + + ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + if (ret != EXYNOS_DP_SUCCESS) + printf("DP set_enhanced_mode() failed\n"); + + edp_info->lt_info.lt_status = DP_LT_FAIL; + } + + return ret; +} + +static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info + *edp_info) +{ + unsigned int ret = EXYNOS_DP_SUCCESS; + unsigned char lane_stat; + unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0, }; + unsigned int i; + unsigned char adj_req_sw; + unsigned char adj_req_em; + unsigned char buf[5]; + + debug("DP: %s was called\n", __func__); + mdelay(1); + + ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read lane status failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + if (lane_stat & DP_LANE_STAT_CR_DONE) { + debug("DP clock Recovery training succeed\n"); + exynos_dp_set_training_pattern(TRAINING_PTN2); + + for (i = 0; i < edp_info->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw, + &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) + || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | + MAX_PRE_EMPHASIS_REACH_3; + } + exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + } + + buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2; + buf[1] = lt_ctl_val[0]; + buf[2] = lt_ctl_val[1]; + buf[3] = lt_ctl_val[2]; + buf[4] = lt_ctl_val[3]; + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_PATTERN_SET, 5, buf); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write training pattern1 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } else + edp_info->lt_info.lt_status = DP_LT_ET; + } else { + for (i = 0; i < edp_info->lane_cnt; i++) { + lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i); + ret = exynos_dp_read_dpcd_adj_req(i, + &adj_req_sw, &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read adj req failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) + ret = exynos_dp_reduce_link_rate(edp_info); + + if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == + adj_req_sw) && + (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) == + adj_req_em)) { + edp_info->lt_info.cr_loop[i]++; + if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) + ret = exynos_dp_reduce_link_rate( + edp_info); + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | + MAX_PRE_EMPHASIS_REACH_3; + } + exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + } + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP write training pattern2 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + } + + return ret; +} + +static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info + *edp_info) +{ + unsigned int ret = EXYNOS_DP_SUCCESS; + unsigned char lane_stat, adj_req_sw, adj_req_em, i; + unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0,}; + unsigned char interlane_aligned = 0; + unsigned char f_bw; + unsigned char f_lane_cnt; + unsigned char sink_stat; + + mdelay(1); + + ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read lane status failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + return ret; + } + + debug("DP lane stat : %x\n", lane_stat); + + if (lane_stat & DP_LANE_STAT_CR_DONE) { + ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED, + &sink_stat); + if (ret != EXYNOS_DP_SUCCESS) { + edp_info->lt_info.lt_status = DP_LT_FAIL; + + return ret; + } + + interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); + + for (i = 0; i < edp_info->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(i, + &adj_req_sw, &adj_req_em); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP read adj req 1 failed\n"); + edp_info->lt_info.lt_status = DP_LT_FAIL; + + return ret; + } + + lt_ctl_val[i] = 0; + lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; + + if ((adj_req_sw == VOLTAGE_LEVEL_3) || + (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { + lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3; + lt_ctl_val[i] |= MAX_PRE_EMPHASIS_REACH_3; + } + } + + if (((lane_stat&DP_LANE_STAT_CE_DONE) && + (lane_stat&DP_LANE_STAT_SYM_LOCK)) + && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { + debug("DP Equalizer training succeed\n"); + + f_bw = exynos_dp_get_link_bandwidth(); + f_lane_cnt = exynos_dp_get_lane_count(); + + debug("DP final BandWidth : %x\n", f_bw); + debug("DP final Lane Count : %x\n", f_lane_cnt); + + edp_info->lt_info.lt_status = DP_LT_FINISHED; + + exynos_dp_equalizer_err_link(edp_info); + + } else { + edp_info->lt_info.ep_loop++; + + if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { + if (edp_info->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate( + edp_info); + } else { + edp_info->lt_info.lt_status = + DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + } else { + for (i = 0; i < edp_info->lane_cnt; i++) + exynos_dp_set_lanex_pre_emphasis( + lt_ctl_val[i], i); + + ret = exynos_dp_write_bytes_to_dpcd( + DPCD_TRAINING_LANE0_SET, + 4, lt_ctl_val); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP set lt pattern failed\n"); + edp_info->lt_info.lt_status = + DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + } + } + } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate(edp_info); + } else { + edp_info->lt_info.lt_status = DP_LT_FAIL; + exynos_dp_equalizer_err_link(edp_info); + } + + return ret; +} + +static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) +{ + unsigned int ret = 0; + int training_finished; + + /* Turn off unnecessary lane */ + if (edp_info->lane_cnt == 1) + exynos_dp_set_analog_power_down(CH1_BLOCK, 1); + + training_finished = 0; + + edp_info->lt_info.lt_status = DP_LT_START; + + /* Process here */ + while (!training_finished) { + switch (edp_info->lt_info.lt_status) { + case DP_LT_START: + ret = exynos_dp_link_start(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP LT:link start failed\n"); + return ret; + } + break; + case DP_LT_CR: + ret = exynos_dp_process_clock_recovery(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP LT:clock recovery failed\n"); + return ret; + } + break; + case DP_LT_ET: + ret = exynos_dp_process_equalizer_training(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP LT:equalizer training failed\n"); + return ret; + } + break; + case DP_LT_FINISHED: + training_finished = 1; + break; + case DP_LT_FAIL: + return -1; + } + } + + return ret; +} + +static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info) +{ + unsigned int ret; + + exynos_dp_init_training(); + + ret = exynos_dp_sw_link_training(edp_info); + if (ret != EXYNOS_DP_SUCCESS) + printf("DP dp_sw_link_training() failed\n"); + + return ret; +} + +static void exynos_dp_enable_scramble(unsigned int enable) +{ + unsigned char data; + + if (enable) { + exynos_dp_enable_scrambling(DP_ENABLE); + + exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); + } else { + exynos_dp_enable_scrambling(DP_DISABLE); + exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + (u8)(data | DPCD_SCRAMBLING_DISABLED)); + } +} + +static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) +{ + unsigned int ret = 0; + unsigned int retry_cnt; + + mdelay(1); + + if (edp_info->video_info.master_mode) { + printf("DP does not support master mode\n"); + return -ENODEV; + } else { + /* debug slave */ + exynos_dp_config_video_slave_mode(&edp_info->video_info); + } + + exynos_dp_set_video_color_format(&edp_info->video_info); + + if (edp_info->video_info.bist_mode) { + if (exynos_dp_config_video_bist(edp_info) != 0) + return -1; + } + + ret = exynos_dp_get_pll_lock_status(); + if (ret != PLL_LOCKED) { + printf("DP PLL is not locked yet\n"); + return -EIO; + } + + if (edp_info->video_info.master_mode == 0) { + retry_cnt = 10; + while (retry_cnt) { + ret = exynos_dp_is_slave_video_stream_clock_on(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printf("DP stream_clock_on failed\n"); + return ret; + } + retry_cnt--; + mdelay(1); + } else + break; + } + } + + /* Set to use the register calculated M/N video */ + exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0); + + /* For video bist, Video timing must be generated by register */ + exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE); + + /* Enable video bist */ + if (edp_info->video_info.bist_pattern != COLOR_RAMP && + edp_info->video_info.bist_pattern != BALCK_WHITE_V_LINES && + edp_info->video_info.bist_pattern != COLOR_SQUARE) + exynos_dp_enable_video_bist(edp_info->video_info.bist_mode); + else + exynos_dp_enable_video_bist(DP_DISABLE); + + /* Disable video mute */ + exynos_dp_enable_video_mute(DP_DISABLE); + + /* Configure video Master or Slave mode */ + exynos_dp_enable_video_master(edp_info->video_info.master_mode); + + /* Enable video */ + exynos_dp_start_video(); + + if (edp_info->video_info.master_mode == 0) { + retry_cnt = 100; + while (retry_cnt) { + ret = exynos_dp_is_video_stream_on(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printf("DP Timeout of video stream\n"); + return ret; + } + retry_cnt--; + mdelay(5); + } else + break; + } + } + + return ret; +} + +int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) +{ + unsigned int node = fdtdec_next_compatible(blob, 0, + COMPAT_SAMSUNG_EXYNOS5_DP); + if (node <= 0) { + debug("exynos_dp: Can't get device node for dp\n"); + return -ENODEV; + } + + edp_info->disp_info.h_res = fdtdec_get_int(blob, node, + "samsung,h-res", 0); + edp_info->disp_info.h_sync_width = fdtdec_get_int(blob, node, + "samsung,h-sync-width", 0); + edp_info->disp_info.h_back_porch = fdtdec_get_int(blob, node, + "samsung,h-back-porch", 0); + edp_info->disp_info.h_front_porch = fdtdec_get_int(blob, node, + "samsung,h-front-porch", 0); + edp_info->disp_info.v_res = fdtdec_get_int(blob, node, + "samsung,v-res", 0); + edp_info->disp_info.v_sync_width = fdtdec_get_int(blob, node, + "samsung,v-sync-width", 0); + edp_info->disp_info.v_back_porch = fdtdec_get_int(blob, node, + "samsung,v-back-porch", 0); + edp_info->disp_info.v_front_porch = fdtdec_get_int(blob, node, + "samsung,v-front-porch", 0); + edp_info->disp_info.v_sync_rate = fdtdec_get_int(blob, node, + "samsung,v-sync-rate", 0); + + edp_info->lt_info.lt_status = fdtdec_get_int(blob, node, + "samsung,lt-status", 0); + + edp_info->video_info.master_mode = fdtdec_get_int(blob, node, + "samsung,master-mode", 0); + edp_info->video_info.bist_mode = fdtdec_get_int(blob, node, + "samsung,bist-mode", 0); + edp_info->video_info.bist_pattern = fdtdec_get_int(blob, node, + "samsung,bist-pattern", 0); + edp_info->video_info.h_sync_polarity = fdtdec_get_int(blob, node, + "samsung,h-sync-polarity", 0); + edp_info->video_info.v_sync_polarity = fdtdec_get_int(blob, node, + "samsung,v-sync-polarity", 0); + edp_info->video_info.interlaced = fdtdec_get_int(blob, node, + "samsung,interlaced", 0); + edp_info->video_info.color_space = fdtdec_get_int(blob, node, + "samsung,color-space", 0); + edp_info->video_info.dynamic_range = fdtdec_get_int(blob, node, + "samsung,dynamic-range", 0); + edp_info->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, + "samsung,ycbcr-coeff", 0); + edp_info->video_info.color_depth = fdtdec_get_int(blob, node, + "samsung,color-depth", 0); + return 0; +} + +unsigned int exynos_init_dp(void) +{ + unsigned int ret; + struct edp_device_info *edp_info; + + edp_info = kzalloc(sizeof(struct edp_device_info), GFP_KERNEL); + if (!edp_info) { + debug("failed to allocate edp device object.\n"); + return -EFAULT; + } + + if (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) + debug("unable to parse DP DT node\n"); + + exynos_dp_set_base_addr(); + + exynos_dp_disp_info(&edp_info->disp_info); + + exynos_set_dp_phy(1); + + ret = exynos_dp_init_dp(); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP exynos_dp_init_dp() failed\n"); + return ret; + } + + ret = exynos_dp_handle_edid(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("EDP handle_edid fail\n"); + return ret; + } + + ret = exynos_dp_set_link_train(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP link training fail\n"); + return ret; + } + + exynos_dp_enable_scramble(DP_ENABLE); + exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE); + exynos_dp_enable_enhanced_mode(DP_ENABLE); + + exynos_dp_set_link_bandwidth(edp_info->lane_bw); + exynos_dp_set_lane_count(edp_info->lane_cnt); + + exynos_dp_init_video(); + ret = exynos_dp_config_video(edp_info); + if (ret != EXYNOS_DP_SUCCESS) { + printf("Exynos DP init failed\n"); + return ret; + } + + debug("Exynos DP init done\n"); + + return ret; +} diff --git a/drivers/video/exynos/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c new file mode 100644 index 0000000..acb5bc8 --- /dev/null +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -0,0 +1,1257 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Declare global data pointer */ +DECLARE_GLOBAL_DATA_PTR; + +struct exynos_dp *dp_regs; + +void exynos_dp_set_base_addr(void) +{ +#if CONFIG_IS_ENABLED(OF_CONTROL) + unsigned int node = fdtdec_next_compatible(gd->fdt_blob, + 0, COMPAT_SAMSUNG_EXYNOS5_DP); + if (node <= 0) + debug("exynos_dp: Can't get device node for dp\n"); + + dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if (dp_regs == NULL) + debug("Can't get the DP base address\n"); +#else + dp_regs = (struct exynos_dp *)samsung_get_base_dp(); +#endif +} + +static void exynos_dp_enable_video_input(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->video_ctl1); + reg &= ~VIDEO_EN_MASK; + + /* enable video input */ + if (enable) + reg |= VIDEO_EN_MASK; + + writel(reg, &dp_regs->video_ctl1); + + return; +} + +void exynos_dp_enable_video_bist(unsigned int enable) +{ + /* enable video bist */ + unsigned int reg; + + reg = readl(&dp_regs->video_ctl4); + reg &= ~VIDEO_BIST_MASK; + + /* enable video bist */ + if (enable) + reg |= VIDEO_BIST_MASK; + + writel(reg, &dp_regs->video_ctl4); + + return; +} + +void exynos_dp_enable_video_mute(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->video_ctl1); + reg &= ~(VIDEO_MUTE_MASK); + if (enable) + reg |= VIDEO_MUTE_MASK; + + writel(reg, &dp_regs->video_ctl1); + + return; +} + + +static void exynos_dp_init_analog_param(void) +{ + unsigned int reg; + + /* + * Set termination + * Normal bandgap, Normal swing, Tx terminal registor 61 ohm + * 24M Phy clock, TX digital logic power is 100:1.0625V + */ + reg = SEL_BG_NEW_BANDGAP | TX_TERMINAL_CTRL_61_OHM | + SWING_A_30PER_G_NORMAL; + writel(reg, &dp_regs->analog_ctl1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + writel(reg, &dp_regs->analog_ctl2); + + /* + * Set power source for internal clk driver to 1.0625v. + * Select current reference of TX driver current to 00:Ipp/2+Ic/2. + * Set VCO range of PLL +- 0uA + */ + reg = DRIVE_DVDD_BIT_1_0625V | SEL_CURRENT_DEFAULT | VCO_BIT_000_MICRO; + writel(reg, &dp_regs->analog_ctl3); + + /* + * Set AUX TX terminal resistor to 102 ohm + * Set AUX channel amplitude control + */ + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_52_OHM | TX_CUR1_2X | TX_CUR_4_MA; + writel(reg, &dp_regs->pll_filter_ctl1); + + /* + * PLL loop filter bandwidth + * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz + * PLL digital power select: 1.2500V + */ + reg = CH3_AMP_0_MV | CH2_AMP_0_MV | CH1_AMP_0_MV | CH0_AMP_0_MV; + + writel(reg, &dp_regs->amp_tuning_ctl); + + /* + * PLL loop filter bandwidth + * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz + * PLL digital power select: 1.1250V + */ + reg = DP_PLL_LOOP_BIT_DEFAULT | DP_PLL_REF_BIT_1_1250V; + writel(reg, &dp_regs->pll_ctl); +} + +static void exynos_dp_init_interrupt(void) +{ + /* Set interrupt registers to initial states */ + + /* + * Disable interrupt + * INT pin assertion polarity. It must be configured + * correctly according to ICU setting. + * 1 = assert high, 0 = assert low + */ + writel(INT_POL, &dp_regs->int_ctl); + + /* Clear pending registers */ + writel(0xff, &dp_regs->common_int_sta1); + writel(0xff, &dp_regs->common_int_sta2); + writel(0xff, &dp_regs->common_int_sta3); + writel(0xff, &dp_regs->common_int_sta4); + writel(0xff, &dp_regs->int_sta); + + /* 0:mask,1: unmask */ + writel(0x00, &dp_regs->int_sta_mask1); + writel(0x00, &dp_regs->int_sta_mask2); + writel(0x00, &dp_regs->int_sta_mask3); + writel(0x00, &dp_regs->int_sta_mask4); + writel(0x00, &dp_regs->int_sta_mask); +} + +void exynos_dp_reset(void) +{ + unsigned int reg_func_1; + + /* dp tx sw reset */ + writel(RESET_DP_TX, &dp_regs->tx_sw_reset); + + exynos_dp_enable_video_input(DP_DISABLE); + exynos_dp_enable_video_bist(DP_DISABLE); + exynos_dp_enable_video_mute(DP_DISABLE); + + /* software reset */ + reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | + AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | + HDCP_FUNC_EN_N | SW_FUNC_EN_N; + + writel(reg_func_1, &dp_regs->func_en1); + writel(reg_func_1, &dp_regs->func_en2); + + mdelay(1); + + exynos_dp_init_analog_param(); + exynos_dp_init_interrupt(); + + return; +} + +void exynos_dp_enable_sw_func(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->func_en1); + reg &= ~(SW_FUNC_EN_N); + + if (!enable) + reg |= SW_FUNC_EN_N; + + writel(reg, &dp_regs->func_en1); + + return; +} + +unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->phy_pd); + switch (block) { + case AUX_BLOCK: + reg &= ~(AUX_PD); + if (enable) + reg |= AUX_PD; + break; + case CH0_BLOCK: + reg &= ~(CH0_PD); + if (enable) + reg |= CH0_PD; + break; + case CH1_BLOCK: + reg &= ~(CH1_PD); + if (enable) + reg |= CH1_PD; + break; + case CH2_BLOCK: + reg &= ~(CH2_PD); + if (enable) + reg |= CH2_PD; + break; + case CH3_BLOCK: + reg &= ~(CH3_PD); + if (enable) + reg |= CH3_PD; + break; + case ANALOG_TOTAL: + reg &= ~PHY_PD; + if (enable) + reg |= PHY_PD; + break; + case POWER_ALL: + reg &= ~(PHY_PD | AUX_PD | CH0_PD | CH1_PD | CH2_PD | + CH3_PD); + if (enable) + reg |= (PHY_PD | AUX_PD | CH0_PD | CH1_PD | + CH2_PD | CH3_PD); + break; + default: + printf("DP undefined block number : %d\n", block); + return -1; + } + + writel(reg, &dp_regs->phy_pd); + + return 0; +} + +unsigned int exynos_dp_get_pll_lock_status(void) +{ + unsigned int reg; + + reg = readl(&dp_regs->debug_ctl); + + if (reg & PLL_LOCK) + return PLL_LOCKED; + else + return PLL_UNLOCKED; +} + +static void exynos_dp_set_pll_power(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->pll_ctl); + reg &= ~(DP_PLL_PD); + + if (!enable) + reg |= DP_PLL_PD; + + writel(reg, &dp_regs->pll_ctl); +} + +int exynos_dp_init_analog_func(void) +{ + int ret = EXYNOS_DP_SUCCESS; + unsigned int retry_cnt = 10; + unsigned int reg; + + /* Power On All Analog block */ + exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); + + reg = PLL_LOCK_CHG; + writel(reg, &dp_regs->common_int_sta1); + + reg = readl(&dp_regs->debug_ctl); + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); + writel(reg, &dp_regs->debug_ctl); + + /* Assert DP PLL Reset */ + reg = readl(&dp_regs->pll_ctl); + reg |= DP_PLL_RESET; + writel(reg, &dp_regs->pll_ctl); + + mdelay(1); + + /* Deassert DP PLL Reset */ + reg = readl(&dp_regs->pll_ctl); + reg &= ~(DP_PLL_RESET); + writel(reg, &dp_regs->pll_ctl); + + exynos_dp_set_pll_power(DP_ENABLE); + + while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) { + mdelay(1); + retry_cnt--; + if (retry_cnt == 0) { + printf("DP dp's pll lock failed : retry : %d\n", + retry_cnt); + return -EINVAL; + } + } + + debug("dp's pll lock success(%d)\n", retry_cnt); + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + reg = readl(&dp_regs->func_en2); + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N + | AUX_FUNC_EN_N); + writel(reg, &dp_regs->func_en2); + + return ret; +} + +void exynos_dp_init_hpd(void) +{ + unsigned int reg; + + /* Clear interrupts related to Hot Plug Detect */ + reg = HOTPLUG_CHG | HPD_LOST | PLUG; + writel(reg, &dp_regs->common_int_sta4); + + reg = INT_HPD; + writel(reg, &dp_regs->int_sta); + + reg = readl(&dp_regs->sys_ctl3); + reg &= ~(F_HPD | HPD_CTRL); + writel(reg, &dp_regs->sys_ctl3); + + return; +} + +static inline void exynos_dp_reset_aux(void) +{ + unsigned int reg; + + /* Disable AUX channel module */ + reg = readl(&dp_regs->func_en2); + reg |= AUX_FUNC_EN_N; + writel(reg, &dp_regs->func_en2); + + return; +} + +void exynos_dp_init_aux(void) +{ + unsigned int reg; + + /* Clear interrupts related to AUX channel */ + reg = RPLY_RECEIV | AUX_ERR; + writel(reg, &dp_regs->int_sta); + + exynos_dp_reset_aux(); + + /* Disable AUX transaction H/W retry */ + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)| + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + writel(reg, &dp_regs->aux_hw_retry_ctl); + + /* Receive AUX Channel DEFER commands equal to DEFER_COUNT*64 */ + reg = DEFER_CTRL_EN | DEFER_COUNT(1); + writel(reg, &dp_regs->aux_ch_defer_ctl); + + /* Enable AUX channel module */ + reg = readl(&dp_regs->func_en2); + reg &= ~AUX_FUNC_EN_N; + writel(reg, &dp_regs->func_en2); + + return; +} + +void exynos_dp_config_interrupt(void) +{ + unsigned int reg; + + /* 0: mask, 1: unmask */ + reg = COMMON_INT_MASK_1; + writel(reg, &dp_regs->common_int_mask1); + + reg = COMMON_INT_MASK_2; + writel(reg, &dp_regs->common_int_mask2); + + reg = COMMON_INT_MASK_3; + writel(reg, &dp_regs->common_int_mask3); + + reg = COMMON_INT_MASK_4; + writel(reg, &dp_regs->common_int_mask4); + + reg = INT_STA_MASK; + writel(reg, &dp_regs->int_sta_mask); + + return; +} + +unsigned int exynos_dp_get_plug_in_status(void) +{ + unsigned int reg; + + reg = readl(&dp_regs->sys_ctl3); + if (reg & HPD_STATUS) + return 0; + + return -1; +} + +unsigned int exynos_dp_detect_hpd(void) +{ + int timeout_loop = DP_TIMEOUT_LOOP_COUNT; + + mdelay(2); + + while (exynos_dp_get_plug_in_status() != 0) { + if (timeout_loop == 0) + return -EINVAL; + mdelay(10); + timeout_loop--; + } + + return EXYNOS_DP_SUCCESS; +} + +unsigned int exynos_dp_start_aux_transaction(void) +{ + unsigned int reg; + unsigned int ret = 0; + unsigned int retry_cnt; + + /* Enable AUX CH operation */ + reg = readl(&dp_regs->aux_ch_ctl2); + reg |= AUX_EN; + writel(reg, &dp_regs->aux_ch_ctl2); + + retry_cnt = 10; + while (retry_cnt) { + reg = readl(&dp_regs->int_sta); + if (!(reg & RPLY_RECEIV)) { + if (retry_cnt == 0) { + printf("DP Reply Timeout!!\n"); + ret = -EAGAIN; + return ret; + } + mdelay(1); + retry_cnt--; + } else + break; + } + + /* Clear interrupt source for AUX CH command reply */ + writel(reg, &dp_regs->int_sta); + + /* Clear interrupt source for AUX CH access error */ + reg = readl(&dp_regs->int_sta); + if (reg & AUX_ERR) { + printf("DP Aux Access Error\n"); + writel(AUX_ERR, &dp_regs->int_sta); + ret = -EAGAIN; + return ret; + } + + /* Check AUX CH error access status */ + reg = readl(&dp_regs->aux_ch_sta); + if ((reg & AUX_STATUS_MASK) != 0) { + debug("DP AUX CH error happens: %x\n", reg & AUX_STATUS_MASK); + ret = -EAGAIN; + return ret; + } + + return EXYNOS_DP_SUCCESS; +} + +unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, + unsigned char data) +{ + unsigned int reg, ret; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, &dp_regs->aux_addr_19_16); + + /* Write data buffer */ + reg = (unsigned int)data; + writel(reg, &dp_regs->buf_data0); + + /* + * Set DisplayPort transaction and write 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + printf("DP Aux transaction failed\n"); + return ret; + } + + return ret; +} + +unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, + unsigned char *data) +{ + unsigned int reg; + int retval; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, &dp_regs->aux_addr_19_16); + + /* + * Set DisplayPort transaction and read 1 byte + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (!retval) + debug("DP Aux Transaction fail!\n"); + + /* Read data buffer */ + reg = readl(&dp_regs->buf_data0); + *data = (unsigned char)(reg & 0xff); + + return retval; +} + +unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + unsigned int reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + unsigned int retry_cnt; + unsigned int ret = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + retry_cnt = 5; + while (retry_cnt) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_19_16); + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = data[start_offset + cur_data_idx]; + writel(reg, (unsigned int)&dp_regs->buf_data0 + + (4 * cur_data_idx)); + } + /* + * Set DisplayPort transaction and write + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printf("DP Aux Transaction failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + start_offset += cur_data_count; + } + + return ret; +} + +unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + unsigned int reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + unsigned int retry_cnt; + unsigned int ret = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + start_offset = 0; + while (start_offset < count) { + /* Buffer size of AUX CH is 16 * 4bytes */ + if ((count - start_offset) > 16) + cur_data_count = 16; + else + cur_data_count = count - start_offset; + + retry_cnt = 5; + while (retry_cnt) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, &dp_regs->aux_addr_19_16); + /* + * Set DisplayPort transaction and read + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(cur_data_count) | + AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + ret = exynos_dp_start_aux_transaction(); + if (ret != EXYNOS_DP_SUCCESS) { + if (retry_cnt == 0) { + printf("DP Aux Transaction failed\n"); + return ret; + } + retry_cnt--; + } else + break; + } + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = readl((unsigned int)&dp_regs->buf_data0 + + 4 * cur_data_idx); + data[start_offset + cur_data_idx] = (unsigned char)reg; + } + + start_offset += cur_data_count; + } + + return ret; +} + +int exynos_dp_select_i2c_device(unsigned int device_addr, + unsigned int reg_addr) +{ + unsigned int reg; + int retval; + + /* Set EDID device address */ + reg = device_addr; + writel(reg, &dp_regs->aux_addr_7_0); + writel(0x0, &dp_regs->aux_addr_15_8); + writel(0x0, &dp_regs->aux_addr_19_16); + + /* Set offset from base address of EDID device */ + writel(reg_addr, &dp_regs->buf_data0); + + /* + * Set I2C transaction and write address + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | + AUX_TX_COMM_WRITE; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval != 0) + printf("%s: DP Aux Transaction fail!\n", __func__); + + return retval; +} + +int exynos_dp_read_byte_from_i2c(unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data) +{ + unsigned int reg; + int i; + int retval; + + for (i = 0; i < 10; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + /* Select EDID device */ + retval = exynos_dp_select_i2c_device(device_addr, reg_addr); + if (retval != 0) { + printf("DP Select EDID device fail. retry !\n"); + continue; + } + + /* + * Set I2C transaction and read data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval != EXYNOS_DP_SUCCESS) + printf("%s: DP Aux Transaction fail!\n", __func__); + } + + /* Read data */ + if (retval == 0) + *data = readl(&dp_regs->buf_data0); + + return retval; +} + +int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, + unsigned int reg_addr, unsigned int count, unsigned char edid[]) +{ + unsigned int reg; + unsigned int i, j; + unsigned int cur_data_idx; + unsigned int defer = 0; + int retval = 0; + + for (i = 0; i < count; i += 16) { /* use 16 burst */ + for (j = 0; j < 100; j++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, &dp_regs->buffer_data_ctl); + + /* Set normal AUX CH command */ + reg = readl(&dp_regs->aux_ch_ctl2); + reg &= ~ADDR_ONLY; + writel(reg, &dp_regs->aux_ch_ctl2); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending addres + */ + if (!defer) + retval = + exynos_dp_select_i2c_device(device_addr, + reg_addr + i); + else + defer = 0; + + if (retval == EXYNOS_DP_SUCCESS) { + /* + * Set I2C transaction and write data + * If bit 3 is 1, DisplayPort transaction. + * If Bit 3 is 0, I2C transaction. + */ + reg = AUX_LENGTH(16) | + AUX_TX_COMM_I2C_TRANSACTION | + AUX_TX_COMM_READ; + writel(reg, &dp_regs->aux_ch_ctl1); + + /* Start AUX transaction */ + retval = exynos_dp_start_aux_transaction(); + if (retval == 0) + break; + else + printf("DP Aux Transaction fail!\n"); + } + /* Check if Rx sends defer */ + reg = readl(&dp_regs->aux_rx_comm); + if (reg == AUX_RX_COMM_AUX_DEFER || + reg == AUX_RX_COMM_I2C_DEFER) { + printf("DP Defer: %d\n", reg); + defer = 1; + } + } + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + reg = readl((unsigned int)&dp_regs->buf_data0 + + 4 * cur_data_idx); + edid[i + cur_data_idx] = (unsigned char)reg; + } + } + + return retval; +} + +void exynos_dp_reset_macro(void) +{ + unsigned int reg; + + reg = readl(&dp_regs->phy_test); + reg |= MACRO_RST; + writel(reg, &dp_regs->phy_test); + + /* 10 us is the minimum Macro reset time. */ + mdelay(1); + + reg &= ~MACRO_RST; + writel(reg, &dp_regs->phy_test); +} + +void exynos_dp_set_link_bandwidth(unsigned char bwtype) +{ + unsigned int reg; + + reg = (unsigned int)bwtype; + + /* Set bandwidth to 2.7G or 1.62G */ + if ((bwtype == DP_LANE_BW_1_62) || (bwtype == DP_LANE_BW_2_70)) + writel(reg, &dp_regs->link_bw_set); +} + +unsigned char exynos_dp_get_link_bandwidth(void) +{ + unsigned char ret; + unsigned int reg; + + reg = readl(&dp_regs->link_bw_set); + ret = (unsigned char)reg; + + return ret; +} + +void exynos_dp_set_lane_count(unsigned char count) +{ + unsigned int reg; + + reg = (unsigned int)count; + + if ((count == DP_LANE_CNT_1) || (count == DP_LANE_CNT_2) || + (count == DP_LANE_CNT_4)) + writel(reg, &dp_regs->lane_count_set); +} + +unsigned int exynos_dp_get_lane_count(void) +{ + unsigned int reg; + + reg = readl(&dp_regs->lane_count_set); + + return reg; +} + +unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) +{ + unsigned int reg_list[DP_LANE_CNT_4] = { + (unsigned int)&dp_regs->ln0_link_training_ctl, + (unsigned int)&dp_regs->ln1_link_training_ctl, + (unsigned int)&dp_regs->ln2_link_training_ctl, + (unsigned int)&dp_regs->ln3_link_training_ctl, + }; + + return readl(reg_list[lanecnt]); +} + +void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, + unsigned char lanecnt) +{ + unsigned int reg_list[DP_LANE_CNT_4] = { + (unsigned int)&dp_regs->ln0_link_training_ctl, + (unsigned int)&dp_regs->ln1_link_training_ctl, + (unsigned int)&dp_regs->ln2_link_training_ctl, + (unsigned int)&dp_regs->ln3_link_training_ctl, + }; + + writel(request_val, reg_list[lanecnt]); +} + +void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) +{ + unsigned char i; + unsigned int reg; + unsigned int reg_list[DP_LANE_CNT_4] = { + (unsigned int)&dp_regs->ln0_link_training_ctl, + (unsigned int)&dp_regs->ln1_link_training_ctl, + (unsigned int)&dp_regs->ln2_link_training_ctl, + (unsigned int)&dp_regs->ln3_link_training_ctl, + }; + unsigned int reg_shift[DP_LANE_CNT_4] = { + PRE_EMPHASIS_SET_0_SHIFT, + PRE_EMPHASIS_SET_1_SHIFT, + PRE_EMPHASIS_SET_2_SHIFT, + PRE_EMPHASIS_SET_3_SHIFT + }; + + for (i = 0; i < lanecnt; i++) { + reg = level << reg_shift[i]; + writel(reg, reg_list[i]); + } +} + +void exynos_dp_set_training_pattern(unsigned int pattern) +{ + unsigned int reg = 0; + + switch (pattern) { + case PRBS7: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; + break; + case D10_2: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; + break; + case TRAINING_PTN1: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; + break; + case TRAINING_PTN2: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; + break; + case DP_NONE: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_DISABLE | + SW_TRAINING_PATTERN_SET_NORMAL; + break; + default: + break; + } + + writel(reg, &dp_regs->training_ptn_set); +} + +void exynos_dp_enable_enhanced_mode(unsigned char enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->sys_ctl4); + reg &= ~ENHANCED; + + if (enable) + reg |= ENHANCED; + + writel(reg, &dp_regs->sys_ctl4); +} + +void exynos_dp_enable_scrambling(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->training_ptn_set); + reg &= ~(SCRAMBLING_DISABLE); + + if (!enable) + reg |= SCRAMBLING_DISABLE; + + writel(reg, &dp_regs->training_ptn_set); +} + +int exynos_dp_init_video(void) +{ + unsigned int reg; + + /* Clear VID_CLK_CHG[1] and VID_FORMAT_CHG[3] and VSYNC_DET[7] */ + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + writel(reg, &dp_regs->common_int_sta1); + + /* I_STRM__CLK detect : DE_CTL : Auto detect */ + reg &= ~DET_CTRL; + writel(reg, &dp_regs->sys_ctl1); + + return 0; +} + +void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) +{ + unsigned int reg; + + /* Video Slave mode setting */ + reg = readl(&dp_regs->func_en1); + reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N); + reg |= MASTER_VID_FUNC_EN_N; + writel(reg, &dp_regs->func_en1); + + /* Configure Interlaced for slave mode video */ + reg = readl(&dp_regs->video_ctl10); + reg &= ~INTERACE_SCAN_CFG; + reg |= (video_info->interlaced << INTERACE_SCAN_CFG_SHIFT); + writel(reg, &dp_regs->video_ctl10); + + /* Configure V sync polarity for slave mode video */ + reg = readl(&dp_regs->video_ctl10); + reg &= ~VSYNC_POLARITY_CFG; + reg |= (video_info->v_sync_polarity << V_S_POLARITY_CFG_SHIFT); + writel(reg, &dp_regs->video_ctl10); + + /* Configure H sync polarity for slave mode video */ + reg = readl(&dp_regs->video_ctl10); + reg &= ~HSYNC_POLARITY_CFG; + reg |= (video_info->h_sync_polarity << H_S_POLARITY_CFG_SHIFT); + writel(reg, &dp_regs->video_ctl10); + + /* Set video mode to slave mode */ + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; + writel(reg, &dp_regs->soc_general_ctl); +} + +void exynos_dp_set_video_color_format(struct edp_video_info *video_info) +{ + unsigned int reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (video_info->dynamic_range << IN_D_RANGE_SHIFT) | + (video_info->color_depth << IN_BPC_SHIFT) | + (video_info->color_space << IN_COLOR_F_SHIFT); + writel(reg, &dp_regs->video_ctl2); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = readl(&dp_regs->video_ctl3); + reg &= ~IN_YC_COEFFI_MASK; + if (video_info->ycbcr_coeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + writel(reg, &dp_regs->video_ctl3); +} + +int exynos_dp_config_video_bist(struct edp_device_info *edp_info) +{ + unsigned int reg; + unsigned int bist_type = 0; + struct edp_video_info video_info = edp_info->video_info; + + /* For master mode, you don't need to set the video format */ + if (video_info.master_mode == 0) { + writel(TOTAL_LINE_CFG_L(edp_info->disp_info.v_total), + &dp_regs->total_ln_cfg_l); + writel(TOTAL_LINE_CFG_H(edp_info->disp_info.v_total), + &dp_regs->total_ln_cfg_h); + writel(ACTIVE_LINE_CFG_L(edp_info->disp_info.v_res), + &dp_regs->active_ln_cfg_l); + writel(ACTIVE_LINE_CFG_H(edp_info->disp_info.v_res), + &dp_regs->active_ln_cfg_h); + writel(edp_info->disp_info.v_sync_width, + &dp_regs->vsw_cfg); + writel(edp_info->disp_info.v_back_porch, + &dp_regs->vbp_cfg); + writel(edp_info->disp_info.v_front_porch, + &dp_regs->vfp_cfg); + + writel(TOTAL_PIXEL_CFG_L(edp_info->disp_info.h_total), + &dp_regs->total_pix_cfg_l); + writel(TOTAL_PIXEL_CFG_H(edp_info->disp_info.h_total), + &dp_regs->total_pix_cfg_h); + writel(ACTIVE_PIXEL_CFG_L(edp_info->disp_info.h_res), + &dp_regs->active_pix_cfg_l); + writel(ACTIVE_PIXEL_CFG_H(edp_info->disp_info.h_res), + &dp_regs->active_pix_cfg_h); + writel(H_F_PORCH_CFG_L(edp_info->disp_info.h_front_porch), + &dp_regs->hfp_cfg_l); + writel(H_F_PORCH_CFG_H(edp_info->disp_info.h_front_porch), + &dp_regs->hfp_cfg_h); + writel(H_SYNC_PORCH_CFG_L(edp_info->disp_info.h_sync_width), + &dp_regs->hsw_cfg_l); + writel(H_SYNC_PORCH_CFG_H(edp_info->disp_info.h_sync_width), + &dp_regs->hsw_cfg_h); + writel(H_B_PORCH_CFG_L(edp_info->disp_info.h_back_porch), + &dp_regs->hbp_cfg_l); + writel(H_B_PORCH_CFG_H(edp_info->disp_info.h_back_porch), + &dp_regs->hbp_cfg_h); + + /* + * Set SLAVE_I_SCAN_CFG[2], VSYNC_P_CFG[1], + * HSYNC_P_CFG[0] properly + */ + reg = (video_info.interlaced << INTERACE_SCAN_CFG_SHIFT | + video_info.v_sync_polarity << V_S_POLARITY_CFG_SHIFT | + video_info.h_sync_polarity << H_S_POLARITY_CFG_SHIFT); + writel(reg, &dp_regs->video_ctl10); + } + + /* BIST color bar width set--set to each bar is 32 pixel width */ + switch (video_info.bist_pattern) { + case COLORBAR_32: + bist_type = BIST_WIDTH_BAR_32_PIXEL | + BIST_TYPE_COLOR_BAR; + break; + case COLORBAR_64: + bist_type = BIST_WIDTH_BAR_64_PIXEL | + BIST_TYPE_COLOR_BAR; + break; + case WHITE_GRAY_BALCKBAR_32: + bist_type = BIST_WIDTH_BAR_32_PIXEL | + BIST_TYPE_WHITE_GRAY_BLACK_BAR; + break; + case WHITE_GRAY_BALCKBAR_64: + bist_type = BIST_WIDTH_BAR_64_PIXEL | + BIST_TYPE_WHITE_GRAY_BLACK_BAR; + break; + case MOBILE_WHITEBAR_32: + bist_type = BIST_WIDTH_BAR_32_PIXEL | + BIST_TYPE_MOBILE_WHITE_BAR; + break; + case MOBILE_WHITEBAR_64: + bist_type = BIST_WIDTH_BAR_64_PIXEL | + BIST_TYPE_MOBILE_WHITE_BAR; + break; + default: + return -1; + } + + reg = bist_type; + writel(reg, &dp_regs->video_ctl4); + + return 0; +} + +unsigned int exynos_dp_is_slave_video_stream_clock_on(void) +{ + unsigned int reg; + + /* Update Video stream clk detect status */ + reg = readl(&dp_regs->sys_ctl1); + writel(reg, &dp_regs->sys_ctl1); + + reg = readl(&dp_regs->sys_ctl1); + + if (!(reg & DET_STA)) { + debug("DP Input stream clock not detected.\n"); + return -EIO; + } + + return EXYNOS_DP_SUCCESS; +} + +void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, + unsigned int n_value) +{ + unsigned int reg; + + if (type == REGISTER_M) { + reg = readl(&dp_regs->sys_ctl4); + reg |= FIX_M_VID; + writel(reg, &dp_regs->sys_ctl4); + reg = M_VID0_CFG(m_value); + writel(reg, &dp_regs->m_vid0); + reg = M_VID1_CFG(m_value); + writel(reg, &dp_regs->m_vid1); + reg = M_VID2_CFG(m_value); + writel(reg, &dp_regs->m_vid2); + + reg = N_VID0_CFG(n_value); + writel(reg, &dp_regs->n_vid0); + reg = N_VID1_CFG(n_value); + writel(reg, &dp_regs->n_vid1); + reg = N_VID2_CFG(n_value); + writel(reg, &dp_regs->n_vid2); + } else { + reg = readl(&dp_regs->sys_ctl4); + reg &= ~FIX_M_VID; + writel(reg, &dp_regs->sys_ctl4); + } +} + +void exynos_dp_set_video_timing_mode(unsigned int type) +{ + unsigned int reg; + + reg = readl(&dp_regs->video_ctl10); + reg &= ~FORMAT_SEL; + + if (type != VIDEO_TIMING_FROM_CAPTURE) + reg |= FORMAT_SEL; + + writel(reg, &dp_regs->video_ctl10); +} + +void exynos_dp_enable_video_master(unsigned int enable) +{ + unsigned int reg; + + reg = readl(&dp_regs->soc_general_ctl); + if (enable) { + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; + } else { + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MODE_SLAVE_MODE; + } + + writel(reg, &dp_regs->soc_general_ctl); +} + +void exynos_dp_start_video(void) +{ + unsigned int reg; + + /* Enable Video input and disable Mute */ + reg = readl(&dp_regs->video_ctl1); + reg |= VIDEO_EN; + writel(reg, &dp_regs->video_ctl1); +} + +unsigned int exynos_dp_is_video_stream_on(void) +{ + unsigned int reg; + + /* Update STRM_VALID */ + reg = readl(&dp_regs->sys_ctl3); + writel(reg, &dp_regs->sys_ctl3); + + reg = readl(&dp_regs->sys_ctl3); + if (!(reg & STRM_VALID)) + return -EIO; + + return EXYNOS_DP_SUCCESS; +} diff --git a/drivers/video/exynos/exynos_dp_lowlevel.h b/drivers/video/exynos/exynos_dp_lowlevel.h new file mode 100644 index 0000000..8651681 --- /dev/null +++ b/drivers/video/exynos/exynos_dp_lowlevel.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EXYNOS_EDP_LOWLEVEL_H +#define _EXYNOS_EDP_LOWLEVEL_H + +void exynos_dp_enable_video_bist(unsigned int enable); +void exynos_dp_enable_video_mute(unsigned int enable); +void exynos_dp_reset(void); +void exynos_dp_enable_sw_func(unsigned int enable); +unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable); +unsigned int exynos_dp_get_pll_lock_status(void); +int exynos_dp_init_analog_func(void); +void exynos_dp_init_hpd(void); +void exynos_dp_init_aux(void); +void exynos_dp_config_interrupt(void); +unsigned int exynos_dp_get_plug_in_status(void); +unsigned int exynos_dp_detect_hpd(void); +unsigned int exynos_dp_start_aux_transaction(void); +unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, + unsigned char data); +unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, + unsigned char *data); +unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +unsigned int exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int exynos_dp_select_i2c_device( unsigned int device_addr, + unsigned int reg_addr); +int exynos_dp_read_byte_from_i2c(unsigned int device_addr, + unsigned int reg_addr, unsigned int *data); +int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, + unsigned int reg_addr, unsigned int count, + unsigned char edid[]); +void exynos_dp_reset_macro(void); +void exynos_dp_set_link_bandwidth(unsigned char bwtype); +unsigned char exynos_dp_get_link_bandwidth(void); +void exynos_dp_set_lane_count(unsigned char count); +unsigned int exynos_dp_get_lane_count(void); +unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt); +void exynos_dp_set_lane_pre_emphasis(unsigned int level, + unsigned char lanecnt); +void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, + unsigned char lanecnt); +void exynos_dp_set_training_pattern(unsigned int pattern); +void exynos_dp_enable_enhanced_mode(unsigned char enable); +void exynos_dp_enable_scrambling(unsigned int enable); +int exynos_dp_init_video(void); +void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info); +void exynos_dp_set_video_color_format(struct edp_video_info *video_info); +int exynos_dp_config_video_bist(struct edp_device_info *edp_info); +unsigned int exynos_dp_is_slave_video_stream_clock_on(void); +void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, + unsigned int n_value); +void exynos_dp_set_video_timing_mode(unsigned int type); +void exynos_dp_enable_video_master(unsigned int enable); +void exynos_dp_start_video(void); +unsigned int exynos_dp_is_video_stream_on(void); +void exynos_dp_set_base_addr(void); + +#endif /* _EXYNOS_DP_LOWLEVEL_H */ diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c new file mode 100644 index 0000000..69edc3a --- /dev/null +++ b/drivers/video/exynos/exynos_fb.c @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos_fb.h" + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned int panel_width, panel_height; + +#if CONFIG_IS_ENABLED(OF_CONTROL) +vidinfo_t panel_info = { + /* + * Insert a value here so that we don't end up in the BSS + * Reference: drivers/video/tegra.c + */ + .vl_col = -1, +}; +#endif + +ushort *configuration_get_cmap(void) +{ +#if defined(CONFIG_LCD_LOGO) + return bmp_logo_palette; +#else + return NULL; +#endif +} + +static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) +{ + unsigned long palette_size; + unsigned int fb_size; + + fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); + + palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; + + exynos_fimd_lcd_init_mem((unsigned long)lcdbase, + (unsigned long)fb_size, palette_size); +} + +static void exynos_lcd_init(vidinfo_t *vid) +{ + exynos_fimd_lcd_init(vid); + + /* Enable flushing after LCD writes if requested */ + lcd_set_flush_dcache(1); +} + +__weak void exynos_cfg_lcd_gpio(void) +{ +} + +__weak void exynos_backlight_on(unsigned int onoff) +{ +} + +__weak void exynos_reset_lcd(void) +{ +} + +__weak void exynos_lcd_power_on(void) +{ +} + +__weak void exynos_cfg_ldo(void) +{ +} + +__weak void exynos_enable_ldo(unsigned int onoff) +{ +} + +__weak void exynos_backlight_reset(void) +{ +} + +__weak int exynos_lcd_misc_init(vidinfo_t *vid) +{ + return 0; +} + +static void lcd_panel_on(vidinfo_t *vid) +{ + struct gpio_desc pwm_out_gpio; + struct gpio_desc bl_en_gpio; + unsigned int node; + + udelay(vid->init_delay); + + exynos_backlight_reset(); + + exynos_cfg_lcd_gpio(); + + exynos_lcd_power_on(); + + udelay(vid->power_on_delay); + + if (vid->dp_enabled) + exynos_init_dp(); + + exynos_reset_lcd(); + + udelay(vid->reset_delay); + + exynos_backlight_on(1); + +#if CONFIG_IS_ENABLED(OF_CONTROL) + node = fdtdec_next_compatible(gd->fdt_blob, 0, + COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) { + debug("FIMD: Can't get device node for FIMD\n"); + return; + } + gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,pwm-out-gpio", + 0, &pwm_out_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + + gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,bl-en-gpio", 0, + &bl_en_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + +#endif + exynos_cfg_ldo(); + + exynos_enable_ldo(1); + + if (vid->mipi_enabled) + exynos_mipi_dsi_init(); +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +int exynos_lcd_early_init(const void *blob) +{ + unsigned int node; + node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) { + debug("exynos_fb: Can't get device node for fimd\n"); + return -ENODEV; + } + + panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); + if (panel_info.vl_col == 0) { + debug("Can't get XRES\n"); + return -ENXIO; + } + + panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); + if (panel_info.vl_row == 0) { + debug("Can't get YRES\n"); + return -ENXIO; + } + + panel_info.vl_width = fdtdec_get_int(blob, node, + "samsung,vl-width", 0); + + panel_info.vl_height = fdtdec_get_int(blob, node, + "samsung,vl-height", 0); + + panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); + if (panel_info.vl_freq == 0) { + debug("Can't get refresh rate\n"); + return -ENXIO; + } + + if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) + panel_info.vl_clkp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) + panel_info.vl_oep = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) + panel_info.vl_hsp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) + panel_info.vl_vsp = CONFIG_SYS_LOW; + + if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) + panel_info.vl_dp = CONFIG_SYS_LOW; + + panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); + if (panel_info.vl_bpix == 0) { + debug("Can't get bits per pixel\n"); + return -ENXIO; + } + + panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); + if (panel_info.vl_hspw == 0) { + debug("Can't get hsync width\n"); + return -ENXIO; + } + + panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); + if (panel_info.vl_hfpd == 0) { + debug("Can't get right margin\n"); + return -ENXIO; + } + + panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-hbpd", 0); + if (panel_info.vl_hbpd == 0) { + debug("Can't get left margin\n"); + return -ENXIO; + } + + panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, + "samsung,vl-vspw", 0); + if (panel_info.vl_vspw == 0) { + debug("Can't get vsync width\n"); + return -ENXIO; + } + + panel_info.vl_vfpd = fdtdec_get_int(blob, node, + "samsung,vl-vfpd", 0); + if (panel_info.vl_vfpd == 0) { + debug("Can't get lower margin\n"); + return -ENXIO; + } + + panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); + if (panel_info.vl_vbpd == 0) { + debug("Can't get upper margin\n"); + return -ENXIO; + } + + panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, + "samsung,vl-cmd-allow-len", 0); + + panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); + panel_info.init_delay = fdtdec_get_int(blob, node, + "samsung,init-delay", 0); + panel_info.power_on_delay = fdtdec_get_int(blob, node, + "samsung,power-on-delay", 0); + panel_info.reset_delay = fdtdec_get_int(blob, node, + "samsung,reset-delay", 0); + panel_info.interface_mode = fdtdec_get_int(blob, node, + "samsung,interface-mode", 0); + panel_info.mipi_enabled = fdtdec_get_int(blob, node, + "samsung,mipi-enabled", 0); + panel_info.dp_enabled = fdtdec_get_int(blob, node, + "samsung,dp-enabled", 0); + panel_info.cs_setup = fdtdec_get_int(blob, node, + "samsung,cs-setup", 0); + panel_info.wr_setup = fdtdec_get_int(blob, node, + "samsung,wr-setup", 0); + panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); + panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); + + panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); + if (panel_info.logo_on) { + panel_info.logo_width = fdtdec_get_int(blob, node, + "samsung,logo-width", 0); + panel_info.logo_height = fdtdec_get_int(blob, node, + "samsung,logo-height", 0); + panel_info.logo_addr = fdtdec_get_int(blob, node, + "samsung,logo-addr", 0); + } + + panel_info.rgb_mode = fdtdec_get_int(blob, node, + "samsung,rgb-mode", 0); + panel_info.pclk_name = fdtdec_get_int(blob, node, + "samsung,pclk-name", 0); + panel_info.sclk_div = fdtdec_get_int(blob, node, + "samsung,sclk-div", 0); + panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, + "samsung,dual-lcd-enabled", 0); + + return 0; +} +#endif + +void lcd_ctrl_init(void *lcdbase) +{ + set_system_display_ctrl(); + set_lcd_clk(); + +#if CONFIG_IS_ENABLED(OF_CONTROL) +#ifdef CONFIG_EXYNOS_MIPI_DSIM + exynos_init_dsim_platform_data(&panel_info); +#endif + exynos_lcd_misc_init(&panel_info); +#else + /* initialize parameters which is specific to panel. */ + init_panel_info(&panel_info); +#endif + + panel_width = panel_info.vl_width; + panel_height = panel_info.vl_height; + + exynos_lcd_init_mem(lcdbase, &panel_info); + + exynos_lcd_init(&panel_info); +} + +void lcd_enable(void) +{ + if (panel_info.logo_on) { + memset((void *) gd->fb_base, 0, panel_width * panel_height * + (NBITS(panel_info.vl_bpix) >> 3)); + } + + lcd_panel_on(&panel_info); +} + +/* dummy function */ +void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) +{ + return; +} diff --git a/drivers/video/exynos/exynos_fb.h b/drivers/video/exynos/exynos_fb.h new file mode 100644 index 0000000..2c2f94b --- /dev/null +++ b/drivers/video/exynos/exynos_fb.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EXYNOS_FB_H_ +#define _EXYNOS_FB_H_ + +#include + +#define MAX_CLOCK (86 * 1000000) + +enum exynos_cpu_auto_cmd_rate { + DISABLE_AUTO_FRM, + PER_TWO_FRM, + PER_FOUR_FRM, + PER_SIX_FRM, + PER_EIGHT_FRM, + PER_TEN_FRM, + PER_TWELVE_FRM, + PER_FOURTEEN_FRM, + PER_SIXTEEN_FRM, + PER_EIGHTEEN_FRM, + PER_TWENTY_FRM, + PER_TWENTY_TWO_FRM, + PER_TWENTY_FOUR_FRM, + PER_TWENTY_SIX_FRM, + PER_TWENTY_EIGHT_FRM, + PER_THIRTY_FRM, +}; + +void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, + unsigned long palette_size); +void exynos_fimd_lcd_init(vidinfo_t *vid); +unsigned long exynos_fimd_calc_fbsize(void); + +#endif diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c new file mode 100644 index 0000000..ac001a8 --- /dev/null +++ b/drivers/video/exynos/exynos_fimd.c @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "exynos_fb.h" + +DECLARE_GLOBAL_DATA_PTR; + +static unsigned long *lcd_base_addr; +static vidinfo_t *pvid; +static struct exynos_fb *fimd_ctrl; + +void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, + u_long palette_size) +{ + lcd_base_addr = (unsigned long *)screen_base; +} + +static void exynos_fimd_set_dualrgb(unsigned int enabled) +{ + unsigned int cfg = 0; + + if (enabled) { + cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | + EXYNOS_DUALRGB_VDEN_EN_ENABLE; + + /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ + cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | + EXYNOS_DUALRGB_MAIN_CNT(0); + } + + writel(cfg, &fimd_ctrl->dualrgb); +} + +static void exynos_fimd_set_dp_clkcon(unsigned int enabled) +{ + unsigned int cfg = 0; + + if (enabled) + cfg = EXYNOS_DP_CLK_ENABLE; + + writel(cfg, &fimd_ctrl->dp_mie_clkcon); +} + +static void exynos_fimd_set_par(unsigned int win_id) +{ + unsigned int cfg = 0; + + /* set window control */ + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | + EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | + EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | + EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); + + /* DATAPATH is DMA */ + cfg |= EXYNOS_WINCON_DATAPATH_DMA; + + cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; + + /* dma burst is 16 */ + cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; + + switch (pvid->vl_bpix) { + case 4: + cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; + break; + default: + cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; + break; + } + + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + /* set window position to x=0, y=0*/ + cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + + EXYNOS_VIDOSD(win_id)); + + cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | + EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | + EXYNOS_VIDOSD_RIGHT_X_E(1) | + EXYNOS_VIDOSD_BOTTOM_Y_E(0); + + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + + EXYNOS_VIDOSD(win_id)); + + /* set window size for window0*/ + cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + + EXYNOS_VIDOSD(win_id)); +} + +static void exynos_fimd_set_buffer_address(unsigned int win_id) +{ + unsigned long start_addr, end_addr; + + start_addr = (unsigned long)lcd_base_addr; + end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * + pvid->vl_row); + + writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + + EXYNOS_BUFFER_OFFSET(win_id)); + writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + + EXYNOS_BUFFER_OFFSET(win_id)); +} + +static void exynos_fimd_set_clock(vidinfo_t *pvid) +{ + unsigned int cfg = 0, div = 0, remainder, remainder_div; + unsigned long pixel_clock; + unsigned long long src_clock; + + if (pvid->dual_lcd_enabled) { + pixel_clock = pvid->vl_freq * + (pvid->vl_hspw + pvid->vl_hfpd + + pvid->vl_hbpd + pvid->vl_col / 2) * + (pvid->vl_vspw + pvid->vl_vfpd + + pvid->vl_vbpd + pvid->vl_row); + } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { + pixel_clock = pvid->vl_freq * + pvid->vl_width * pvid->vl_height * + (pvid->cs_setup + pvid->wr_setup + + pvid->wr_act + pvid->wr_hold + 1); + } else { + pixel_clock = pvid->vl_freq * + (pvid->vl_hspw + pvid->vl_hfpd + + pvid->vl_hbpd + pvid->vl_col) * + (pvid->vl_vspw + pvid->vl_vfpd + + pvid->vl_vbpd + pvid->vl_row); + } + + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | + EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | + EXYNOS_VIDCON0_CLKDIR_MASK); + cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | + EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); + + src_clock = (unsigned long long) get_lcd_clk(); + + /* get quotient and remainder. */ + remainder = do_div(src_clock, pixel_clock); + div = src_clock; + + remainder *= 10; + remainder_div = remainder / pixel_clock; + + /* round about one places of decimals. */ + if (remainder_div >= 5) + div++; + + /* in case of dual lcd mode. */ + if (pvid->dual_lcd_enabled) + div--; + + cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); + writel(cfg, &fimd_ctrl->vidcon0); +} + +void exynos_set_trigger(void) +{ + unsigned int cfg = 0; + + cfg = readl(&fimd_ctrl->trigcon); + + cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); + + writel(cfg, &fimd_ctrl->trigcon); +} + +int exynos_is_i80_frame_done(void) +{ + unsigned int cfg = 0; + int status; + + cfg = readl(&fimd_ctrl->trigcon); + + /* frame done func is valid only when TRIMODE[0] is set to 1. */ + status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == + EXYNOS_I80STATUS_TRIG_DONE; + + return status; +} + +static void exynos_fimd_lcd_on(void) +{ + unsigned int cfg = 0; + + /* display on */ + cfg = readl(&fimd_ctrl->vidcon0); + cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); + writel(cfg, &fimd_ctrl->vidcon0); +} + +static void exynos_fimd_window_on(unsigned int win_id) +{ + unsigned int cfg = 0; + + /* enable window */ + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + cfg |= EXYNOS_WINCON_ENWIN_ENABLE; + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(&fimd_ctrl->winshmap); + cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); + writel(cfg, &fimd_ctrl->winshmap); +} + +void exynos_fimd_lcd_off(void) +{ + unsigned int cfg = 0; + + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); + writel(cfg, &fimd_ctrl->vidcon0); +} + +void exynos_fimd_window_off(unsigned int win_id) +{ + unsigned int cfg = 0; + + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + cfg &= EXYNOS_WINCON_ENWIN_DISABLE; + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(&fimd_ctrl->winshmap); + cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); + writel(cfg, &fimd_ctrl->winshmap); +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +/* +* The reset value for FIMD SYSMMU register MMU_CTRL is 3 +* on Exynos5420 and newer versions. +* This means FIMD SYSMMU is on by default on Exynos5420 +* and newer versions. +* Since in u-boot we don't use SYSMMU, we should disable +* those FIMD SYSMMU. +* Note that there are 2 SYSMMU for FIMD: m0 and m1. +* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. +* We disable both of them here. +*/ +void exynos_fimd_disable_sysmmu(void) +{ + u32 *sysmmufimd; + unsigned int node; + int node_list[2]; + int count; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", + COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) { + debug("Can't get device node for fimd sysmmu\n"); + return; + } + + sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (!sysmmufimd) { + debug("Can't get base address for sysmmu fimdm0"); + return; + } + + writel(0x0, sysmmufimd); + } +} +#endif + +void exynos_fimd_lcd_init(vidinfo_t *vid) +{ + unsigned int cfg = 0, rgb_mode; + unsigned int offset; +#if CONFIG_IS_ENABLED(OF_CONTROL) + unsigned int node; + + node = fdtdec_next_compatible(gd->fdt_blob, + 0, COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) + debug("exynos_fb: Can't get device node for fimd\n"); + + fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, + node, "reg"); + if (fimd_ctrl == NULL) + debug("Can't get the FIMD base address\n"); + + if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) + exynos_fimd_disable_sysmmu(); + +#else + fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); +#endif + + offset = exynos_fimd_get_base_offset(); + + /* store panel info to global variable */ + pvid = vid; + + rgb_mode = vid->rgb_mode; + + if (vid->interface_mode == FIMD_RGB_INTERFACE) { + cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; + writel(cfg, &fimd_ctrl->vidcon0); + + cfg = readl(&fimd_ctrl->vidcon2); + cfg &= ~(EXYNOS_VIDCON2_WB_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); + cfg |= EXYNOS_VIDCON2_WB_DISABLE; + writel(cfg, &fimd_ctrl->vidcon2); + + /* set polarity */ + cfg = 0; + if (!pvid->vl_clkp) + cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; + if (!pvid->vl_hsp) + cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; + if (!pvid->vl_vsp) + cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; + if (!pvid->vl_dp) + cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; + + writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); + + /* set timing */ + cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); + cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); + cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); + + cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); + cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); + cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); + + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); + + /* set lcd size */ + cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | + EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); + + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); + } + + /* set display mode */ + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; + cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); + writel(cfg, &fimd_ctrl->vidcon0); + + /* set par */ + exynos_fimd_set_par(pvid->win_id); + + /* set memory address */ + exynos_fimd_set_buffer_address(pvid->win_id); + + /* set buffer size */ + cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | + EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | + EXYNOS_VIDADDR_OFFSIZE(0) | + EXYNOS_VIDADDR_OFFSIZE_E(0); + + writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + + EXYNOS_BUFFER_SIZE(pvid->win_id)); + + /* set clock */ + exynos_fimd_set_clock(pvid); + + /* set rgb mode to dual lcd. */ + exynos_fimd_set_dualrgb(pvid->dual_lcd_enabled); + + /* display on */ + exynos_fimd_lcd_on(); + + /* window on */ + exynos_fimd_window_on(pvid->win_id); + + exynos_fimd_set_dp_clkcon(pvid->dp_enabled); +} + +unsigned long exynos_fimd_calc_fbsize(void) +{ + return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); +} diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c new file mode 100644 index 0000000..b597acc --- /dev/null +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "exynos_mipi_dsi_lowlevel.h" +#include "exynos_mipi_dsi_common.h" + +#define master_to_driver(a) (a->dsim_lcd_drv) +#define master_to_device(a) (a->dsim_lcd_dev) + +DECLARE_GLOBAL_DATA_PTR; + +static struct exynos_platform_mipi_dsim *dsim_pd; +#if CONFIG_IS_ENABLED(OF_CONTROL) +static struct mipi_dsim_config dsim_config_dt; +static struct exynos_platform_mipi_dsim dsim_platform_data_dt; +static struct mipi_dsim_lcd_device mipi_lcd_device_dt; +#endif + +struct mipi_dsim_ddi { + int bus_id; + struct list_head list; + struct mipi_dsim_lcd_device *dsim_lcd_dev; + struct mipi_dsim_lcd_driver *dsim_lcd_drv; +}; + +static LIST_HEAD(dsim_ddi_list); +static LIST_HEAD(dsim_lcd_dev_list); + +int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev) +{ + struct mipi_dsim_ddi *dsim_ddi; + + if (!lcd_dev) { + debug("mipi_dsim_lcd_device is NULL.\n"); + return -EFAULT; + } + + if (!lcd_dev->name) { + debug("dsim_lcd_device name is NULL.\n"); + return -EFAULT; + } + + dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL); + if (!dsim_ddi) { + debug("failed to allocate dsim_ddi object.\n"); + return -EFAULT; + } + + dsim_ddi->dsim_lcd_dev = lcd_dev; + + list_add_tail(&dsim_ddi->list, &dsim_ddi_list); + + return 0; +} + +struct mipi_dsim_ddi + *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv) +{ + struct mipi_dsim_ddi *dsim_ddi; + struct mipi_dsim_lcd_device *lcd_dev; + + list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) { + lcd_dev = dsim_ddi->dsim_lcd_dev; + if (!lcd_dev) + continue; + + if (lcd_drv->id >= 0) { + if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 && + lcd_drv->id == lcd_dev->id) { + /** + * bus_id would be used to identify + * connected bus. + */ + dsim_ddi->bus_id = lcd_dev->bus_id; + + return dsim_ddi; + } + } else { + if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) { + /** + * bus_id would be used to identify + * connected bus. + */ + dsim_ddi->bus_id = lcd_dev->bus_id; + + return dsim_ddi; + } + } + + kfree(dsim_ddi); + list_del(&dsim_ddi_list); + } + + return NULL; +} + +int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv) +{ + struct mipi_dsim_ddi *dsim_ddi; + + if (!lcd_drv) { + debug("mipi_dsim_lcd_driver is NULL.\n"); + return -EFAULT; + } + + if (!lcd_drv->name) { + debug("dsim_lcd_driver name is NULL.\n"); + return -EFAULT; + } + + dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv); + if (!dsim_ddi) { + debug("mipi_dsim_ddi object not found.\n"); + return -EFAULT; + } + + dsim_ddi->dsim_lcd_drv = lcd_drv; + + debug("registered panel driver(%s) to mipi-dsi driver.\n", + lcd_drv->name); + + return 0; + +} + +struct mipi_dsim_ddi + *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim, + const char *name) +{ + struct mipi_dsim_ddi *dsim_ddi; + struct mipi_dsim_lcd_driver *lcd_drv; + struct mipi_dsim_lcd_device *lcd_dev; + + list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) { + lcd_drv = dsim_ddi->dsim_lcd_drv; + lcd_dev = dsim_ddi->dsim_lcd_dev; + if (!lcd_drv || !lcd_dev) + continue; + + debug("lcd_drv->id = %d, lcd_dev->id = %d\n", + lcd_drv->id, lcd_dev->id); + + if ((strcmp(lcd_drv->name, name) == 0)) { + lcd_dev->master = dsim; + + dsim->dsim_lcd_dev = lcd_dev; + dsim->dsim_lcd_drv = lcd_drv; + + return dsim_ddi; + } + } + + return NULL; +} + +/* define MIPI-DSI Master operations. */ +static struct mipi_dsim_master_ops master_ops = { + .cmd_write = exynos_mipi_dsi_wr_data, + .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status, + .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, +}; + +int exynos_mipi_dsi_init(void) +{ + struct mipi_dsim_device *dsim; + struct mipi_dsim_config *dsim_config; + struct mipi_dsim_ddi *dsim_ddi; + + dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL); + if (!dsim) { + debug("failed to allocate dsim object.\n"); + return -EFAULT; + } + + /* get mipi_dsim_config. */ + dsim_config = dsim_pd->dsim_config; + if (dsim_config == NULL) { + debug("failed to get dsim config data.\n"); + return -EFAULT; + } + + dsim->pd = dsim_pd; + dsim->dsim_config = dsim_config; + dsim->master_ops = &master_ops; + + /* bind lcd ddi matched with panel name. */ + dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name); + if (!dsim_ddi) { + debug("mipi_dsim_ddi object not found.\n"); + return -ENOSYS; + } + if (dsim_pd->lcd_power) + dsim_pd->lcd_power(); + + if (dsim_pd->mipi_power) + dsim_pd->mipi_power(); + + /* phy_enable(unsigned int dev_index, unsigned int enable) */ + if (dsim_pd->phy_enable) + dsim_pd->phy_enable(0, 1); + + set_mipi_clk(); + + exynos_mipi_dsi_init_dsim(dsim); + exynos_mipi_dsi_init_link(dsim); + exynos_mipi_dsi_set_hs_enable(dsim); + + /* set display timing. */ + exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config); + + /* initialize mipi-dsi client(lcd panel). */ + if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->mipi_panel_init) { + dsim_ddi->dsim_lcd_drv->mipi_panel_init(dsim); + dsim_ddi->dsim_lcd_drv->mipi_display_on(dsim); + } + + debug("mipi-dsi driver(%s mode) has been probed.\n", + (dsim_config->e_interface == DSIM_COMMAND) ? + "CPU" : "RGB"); + + return 0; +} + +void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) +{ + if (pd == NULL) { + debug("pd is NULL\n"); + return; + } + + dsim_pd = pd; +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) +int exynos_dsim_config_parse_dt(const void *blob) +{ + int node; + + node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_MIPI_DSI); + if (node <= 0) { + printf("exynos_mipi_dsi: Can't get device node for mipi dsi\n"); + return -ENODEV; + } + + dsim_config_dt.e_interface = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-interface", 0); + + dsim_config_dt.e_virtual_ch = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-virtual-ch", 0); + + dsim_config_dt.e_pixel_format = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-pixel-format", 0); + + dsim_config_dt.e_burst_mode = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-burst-mode", 0); + + dsim_config_dt.e_no_data_lane = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-no-data-lane", 0); + + dsim_config_dt.e_byte_clk = fdtdec_get_int(blob, node, + "samsung,dsim-config-e-byte-clk", 0); + + dsim_config_dt.hfp = fdtdec_get_int(blob, node, + "samsung,dsim-config-hfp", 0); + + dsim_config_dt.p = fdtdec_get_int(blob, node, + "samsung,dsim-config-p", 0); + dsim_config_dt.m = fdtdec_get_int(blob, node, + "samsung,dsim-config-m", 0); + dsim_config_dt.s = fdtdec_get_int(blob, node, + "samsung,dsim-config-s", 0); + + dsim_config_dt.pll_stable_time = fdtdec_get_int(blob, node, + "samsung,dsim-config-pll-stable-time", 0); + + dsim_config_dt.esc_clk = fdtdec_get_int(blob, node, + "samsung,dsim-config-esc-clk", 0); + + dsim_config_dt.stop_holding_cnt = fdtdec_get_int(blob, node, + "samsung,dsim-config-stop-holding-cnt", 0); + + dsim_config_dt.bta_timeout = fdtdec_get_int(blob, node, + "samsung,dsim-config-bta-timeout", 0); + + dsim_config_dt.rx_timeout = fdtdec_get_int(blob, node, + "samsung,dsim-config-rx-timeout", 0); + + mipi_lcd_device_dt.name = fdtdec_get_config_string(blob, + "samsung,dsim-device-name"); + + mipi_lcd_device_dt.id = fdtdec_get_int(blob, node, + "samsung,dsim-device-id", 0); + + mipi_lcd_device_dt.bus_id = fdtdec_get_int(blob, node, + "samsung,dsim-device-bus_id", 0); + + mipi_lcd_device_dt.reverse_panel = fdtdec_get_int(blob, node, + "samsung,dsim-device-reverse-panel", 0); + + return 0; +} + +void exynos_init_dsim_platform_data(vidinfo_t *vid) +{ + if (exynos_dsim_config_parse_dt(gd->fdt_blob)) + debug("Can't get proper dsim config.\n"); + + strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name); + dsim_platform_data_dt.dsim_config = &dsim_config_dt; + dsim_platform_data_dt.mipi_power = mipi_power; + dsim_platform_data_dt.phy_enable = set_mipi_phy_ctrl; + dsim_platform_data_dt.lcd_panel_info = (void *)vid; + + mipi_lcd_device_dt.platform_data = (void *)&dsim_platform_data_dt; + exynos_mipi_dsi_register_lcd_device(&mipi_lcd_device_dt); + + dsim_pd = &dsim_platform_data_dt; +} +#endif diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c new file mode 100644 index 0000000..925d515 --- /dev/null +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -0,0 +1,620 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include "exynos_mipi_dsi_lowlevel.h" + +#define MHZ (1000 * 1000) +#define FIN_HZ (24 * MHZ) + +#define DFIN_PLL_MIN_HZ (6 * MHZ) +#define DFIN_PLL_MAX_HZ (12 * MHZ) + +#define DFVCO_MIN_HZ (500 * MHZ) +#define DFVCO_MAX_HZ (1000 * MHZ) + +#define TRY_GET_FIFO_TIMEOUT (5000 * 2) + +/* MIPI-DSIM status types. */ +enum { + DSIM_STATE_INIT, /* should be initialized. */ + DSIM_STATE_STOP, /* CPU and LCDC are LP mode. */ + DSIM_STATE_HSCLKEN, /* HS clock was enabled. */ + DSIM_STATE_ULPS +}; + +/* define DSI lane types. */ +enum { + DSIM_LANE_CLOCK = (1 << 0), + DSIM_LANE_DATA0 = (1 << 1), + DSIM_LANE_DATA1 = (1 << 2), + DSIM_LANE_DATA2 = (1 << 3), + DSIM_LANE_DATA3 = (1 << 4) +}; + +static unsigned int dpll_table[15] = { + 100, 120, 170, 220, 270, + 320, 390, 450, 510, 560, + 640, 690, 770, 870, 950 +}; + +static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim, + const unsigned char *data0, unsigned int data1) +{ + unsigned int data_cnt = 0, payload = 0; + + /* in case that data count is more then 4 */ + for (data_cnt = 0; data_cnt < data1; data_cnt += 4) { + /* + * after sending 4bytes per one time, + * send remainder data less then 4. + */ + if ((data1 - data_cnt) < 4) { + if ((data1 - data_cnt) == 3) { + payload = data0[data_cnt] | + data0[data_cnt + 1] << 8 | + data0[data_cnt + 2] << 16; + debug("count = 3 payload = %x, %x %x %x\n", + payload, data0[data_cnt], + data0[data_cnt + 1], + data0[data_cnt + 2]); + } else if ((data1 - data_cnt) == 2) { + payload = data0[data_cnt] | + data0[data_cnt + 1] << 8; + debug("count = 2 payload = %x, %x %x\n", payload, + data0[data_cnt], data0[data_cnt + 1]); + } else if ((data1 - data_cnt) == 1) { + payload = data0[data_cnt]; + } + } else { + /* send 4bytes per one time. */ + payload = data0[data_cnt] | + data0[data_cnt + 1] << 8 | + data0[data_cnt + 2] << 16 | + data0[data_cnt + 3] << 24; + + debug("count = 4 payload = %x, %x %x %x %x\n", + payload, *(u8 *)(data0 + data_cnt), + data0[data_cnt + 1], + data0[data_cnt + 2], + data0[data_cnt + 3]); + } + exynos_mipi_dsi_wr_tx_data(dsim, payload); + } +} + +int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, + const unsigned char *data0, unsigned int data1) +{ + unsigned int timeout = TRY_GET_FIFO_TIMEOUT; + unsigned long delay_val, delay; + unsigned int check_rx_ack = 0; + + if (dsim->state == DSIM_STATE_ULPS) { + debug("state is ULPS.\n"); + + return -EINVAL; + } + + delay_val = MHZ / dsim->dsim_config->esc_clk; + delay = 10 * delay_val; + + mdelay(delay); + + /* only if transfer mode is LPDT, wait SFR becomes empty. */ + if (dsim->state == DSIM_STATE_STOP) { + while (!(exynos_mipi_dsi_get_fifo_state(dsim) & + SFR_HEADER_EMPTY)) { + if ((timeout--) > 0) + mdelay(1); + else { + debug("SRF header fifo is not empty.\n"); + return -EINVAL; + } + } + } + + switch (data_id) { + /* short packet types of packet types for command. */ + case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: + case MIPI_DSI_DCS_SHORT_WRITE: + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: + debug("data0 = %x data1 = %x\n", + data0[0], data0[1]); + exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); + if (check_rx_ack) { + /* process response func should be implemented */ + return 0; + } else { + return -EINVAL; + } + + /* general command */ + case MIPI_DSI_COLOR_MODE_OFF: + case MIPI_DSI_COLOR_MODE_ON: + case MIPI_DSI_SHUTDOWN_PERIPHERAL: + case MIPI_DSI_TURN_ON_PERIPHERAL: + exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); + if (check_rx_ack) { + /* process response func should be implemented. */ + return 0; + } else { + return -EINVAL; + } + + /* packet types for video data */ + case MIPI_DSI_V_SYNC_START: + case MIPI_DSI_V_SYNC_END: + case MIPI_DSI_H_SYNC_START: + case MIPI_DSI_H_SYNC_END: + case MIPI_DSI_END_OF_TRANSMISSION: + return 0; + + /* short and response packet types for command */ + case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: + case MIPI_DSI_DCS_READ: + exynos_mipi_dsi_clear_all_interrupt(dsim); + exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); + /* process response func should be implemented. */ + return 0; + + /* long packet type and null packet */ + case MIPI_DSI_NULL_PACKET: + case MIPI_DSI_BLANKING_PACKET: + return 0; + case MIPI_DSI_GENERIC_LONG_WRITE: + case MIPI_DSI_DCS_LONG_WRITE: + { + unsigned int payload = 0; + + /* if data count is less then 4, then send 3bytes data. */ + if (data1 < 4) { + payload = data0[0] | + data0[1] << 8 | + data0[2] << 16; + + exynos_mipi_dsi_wr_tx_data(dsim, payload); + + debug("count = %d payload = %x,%x %x %x\n", + data1, payload, data0[0], + data0[1], data0[2]); + } else { + /* in case that data count is more then 4 */ + exynos_mipi_dsi_long_data_wr(dsim, data0, data1); + } + + /* put data into header fifo */ + exynos_mipi_dsi_wr_tx_header(dsim, data_id, data1 & 0xff, + (data1 & 0xff00) >> 8); + + } + if (check_rx_ack) + /* process response func should be implemented. */ + return 0; + else + return -EINVAL; + + /* packet typo for video data */ + case MIPI_DSI_PACKED_PIXEL_STREAM_16: + case MIPI_DSI_PACKED_PIXEL_STREAM_18: + case MIPI_DSI_PIXEL_STREAM_3BYTE_18: + case MIPI_DSI_PACKED_PIXEL_STREAM_24: + if (check_rx_ack) { + /* process response func should be implemented. */ + return 0; + } else { + return -EINVAL; + } + default: + debug("data id %x is not supported current DSI spec.\n", + data_id); + + return -EINVAL; + } + + return 0; +} + +int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable) +{ + int sw_timeout; + + if (enable) { + sw_timeout = 1000; + + exynos_mipi_dsi_clear_interrupt(dsim); + exynos_mipi_dsi_enable_pll(dsim, 1); + while (1) { + sw_timeout--; + if (exynos_mipi_dsi_is_pll_stable(dsim)) + return 0; + if (sw_timeout == 0) + return -EINVAL; + } + } else + exynos_mipi_dsi_enable_pll(dsim, 0); + + return 0; +} + +unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim, + unsigned int pre_divider, unsigned int main_divider, + unsigned int scaler) +{ + unsigned long dfin_pll, dfvco, dpll_out; + unsigned int i, freq_band = 0xf; + + dfin_pll = (FIN_HZ / pre_divider); + + /****************************************************** + * Serial Clock(=ByteClk X 8) FreqBand[3:0] * + ****************************************************** + * ~ 99.99 MHz 0000 + * 100 ~ 119.99 MHz 0001 + * 120 ~ 159.99 MHz 0010 + * 160 ~ 199.99 MHz 0011 + * 200 ~ 239.99 MHz 0100 + * 140 ~ 319.99 MHz 0101 + * 320 ~ 389.99 MHz 0110 + * 390 ~ 449.99 MHz 0111 + * 450 ~ 509.99 MHz 1000 + * 510 ~ 559.99 MHz 1001 + * 560 ~ 639.99 MHz 1010 + * 640 ~ 689.99 MHz 1011 + * 690 ~ 769.99 MHz 1100 + * 770 ~ 869.99 MHz 1101 + * 870 ~ 949.99 MHz 1110 + * 950 ~ 1000 MHz 1111 + ******************************************************/ + if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) { + debug("fin_pll range should be 6MHz ~ 12MHz\n"); + exynos_mipi_dsi_enable_afc(dsim, 0, 0); + } else { + if (dfin_pll < 7 * MHZ) + exynos_mipi_dsi_enable_afc(dsim, 1, 0x1); + else if (dfin_pll < 8 * MHZ) + exynos_mipi_dsi_enable_afc(dsim, 1, 0x0); + else if (dfin_pll < 9 * MHZ) + exynos_mipi_dsi_enable_afc(dsim, 1, 0x3); + else if (dfin_pll < 10 * MHZ) + exynos_mipi_dsi_enable_afc(dsim, 1, 0x2); + else if (dfin_pll < 11 * MHZ) + exynos_mipi_dsi_enable_afc(dsim, 1, 0x5); + else + exynos_mipi_dsi_enable_afc(dsim, 1, 0x4); + } + + dfvco = dfin_pll * main_divider; + debug("dfvco = %lu, dfin_pll = %lu, main_divider = %d\n", + dfvco, dfin_pll, main_divider); + if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ) + debug("fvco range should be 500MHz ~ 1000MHz\n"); + + dpll_out = dfvco / (1 << scaler); + debug("dpll_out = %lu, dfvco = %lu, scaler = %d\n", + dpll_out, dfvco, scaler); + + for (i = 0; i < ARRAY_SIZE(dpll_table); i++) { + if (dpll_out < dpll_table[i] * MHZ) { + freq_band = i; + break; + } + } + + debug("freq_band = %d\n", freq_band); + + exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler); + + exynos_mipi_dsi_hs_zero_ctrl(dsim, 0); + exynos_mipi_dsi_prep_ctrl(dsim, 0); + + /* Freq Band */ + exynos_mipi_dsi_pll_freq_band(dsim, freq_band); + + /* Stable time */ + exynos_mipi_dsi_pll_stable_time(dsim, + dsim->dsim_config->pll_stable_time); + + /* Enable PLL */ + debug("FOUT of mipi dphy pll is %luMHz\n", + (dpll_out / MHZ)); + + return dpll_out; +} + +int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim, + unsigned int byte_clk_sel, unsigned int enable) +{ + unsigned int esc_div; + unsigned long esc_clk_error_rate; + unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0; + + if (enable) { + dsim->e_clk_src = byte_clk_sel; + + /* Escape mode clock and byte clock source */ + exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel); + + /* DPHY, DSIM Link : D-PHY clock out */ + if (byte_clk_sel == DSIM_PLL_OUT_DIV8) { + hs_clk = exynos_mipi_dsi_change_pll(dsim, + dsim->dsim_config->p, dsim->dsim_config->m, + dsim->dsim_config->s); + if (hs_clk == 0) { + debug("failed to get hs clock.\n"); + return -EINVAL; + } + + byte_clk = hs_clk / 8; + exynos_mipi_dsi_enable_pll_bypass(dsim, 0); + exynos_mipi_dsi_pll_on(dsim, 1); + /* DPHY : D-PHY clock out, DSIM link : external clock out */ + } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) + debug("not support EXT CLK source for MIPI DSIM\n"); + else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) + debug("not support EXT CLK source for MIPI DSIM\n"); + + /* escape clock divider */ + esc_div = byte_clk / (dsim->dsim_config->esc_clk); + debug("esc_div = %d, byte_clk = %lu, esc_clk = %lu\n", + esc_div, byte_clk, dsim->dsim_config->esc_clk); + if ((byte_clk / esc_div) >= (20 * MHZ) || + (byte_clk / esc_div) > dsim->dsim_config->esc_clk) + esc_div += 1; + + escape_clk = byte_clk / esc_div; + debug("escape_clk = %lu, byte_clk = %lu, esc_div = %d\n", + escape_clk, byte_clk, esc_div); + + /* enable escape clock. */ + exynos_mipi_dsi_enable_byte_clock(dsim, 1); + + /* enable byte clk and escape clock */ + exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div); + /* escape clock on lane */ + exynos_mipi_dsi_enable_esc_clk_on_lane(dsim, + (DSIM_LANE_CLOCK | dsim->data_lane), 1); + + debug("byte clock is %luMHz\n", + (byte_clk / MHZ)); + debug("escape clock that user's need is %lu\n", + (dsim->dsim_config->esc_clk / MHZ)); + debug("escape clock divider is %x\n", esc_div); + debug("escape clock is %luMHz\n", + ((byte_clk / esc_div) / MHZ)); + + if ((byte_clk / esc_div) > escape_clk) { + esc_clk_error_rate = escape_clk / + (byte_clk / esc_div); + debug("error rate is %lu over.\n", + (esc_clk_error_rate / 100)); + } else if ((byte_clk / esc_div) < (escape_clk)) { + esc_clk_error_rate = (byte_clk / esc_div) / + escape_clk; + debug("error rate is %lu under.\n", + (esc_clk_error_rate / 100)); + } + } else { + exynos_mipi_dsi_enable_esc_clk_on_lane(dsim, + (DSIM_LANE_CLOCK | dsim->data_lane), 0); + exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0); + + /* disable escape clock. */ + exynos_mipi_dsi_enable_byte_clock(dsim, 0); + + if (byte_clk_sel == DSIM_PLL_OUT_DIV8) + exynos_mipi_dsi_pll_on(dsim, 0); + } + + return 0; +} + +int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim) +{ + dsim->state = DSIM_STATE_INIT; + + switch (dsim->dsim_config->e_no_data_lane) { + case DSIM_DATA_LANE_1: + dsim->data_lane = DSIM_LANE_DATA0; + break; + case DSIM_DATA_LANE_2: + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; + break; + case DSIM_DATA_LANE_3: + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + DSIM_LANE_DATA2; + break; + case DSIM_DATA_LANE_4: + dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | + DSIM_LANE_DATA2 | DSIM_LANE_DATA3; + break; + default: + debug("data lane is invalid.\n"); + return -EINVAL; + }; + + exynos_mipi_dsi_sw_reset(dsim); + exynos_mipi_dsi_dp_dn_swap(dsim, 0); + + return 0; +} + +int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + /* enable only frame done interrupt */ + exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable); + + return 0; +} + +static void convert_to_fb_videomode(struct fb_videomode *mode1, + vidinfo_t *mode2) +{ + mode1->xres = mode2->vl_width; + mode1->yres = mode2->vl_height; + mode1->upper_margin = mode2->vl_vfpd; + mode1->lower_margin = mode2->vl_vbpd; + mode1->left_margin = mode2->vl_hfpd; + mode1->right_margin = mode2->vl_hbpd; + mode1->vsync_len = mode2->vl_vspw; + mode1->hsync_len = mode2->vl_hspw; +} + +int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, + struct mipi_dsim_config *dsim_config) +{ + struct exynos_platform_mipi_dsim *dsim_pd; + struct fb_videomode lcd_video; + vidinfo_t *vid; + + dsim_pd = (struct exynos_platform_mipi_dsim *)dsim->pd; + vid = (vidinfo_t *)dsim_pd->lcd_panel_info; + + convert_to_fb_videomode(&lcd_video, vid); + + /* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */ + if (dsim->dsim_config->e_interface == (u32) DSIM_VIDEO) { + if (dsim->dsim_config->auto_vertical_cnt == 0) { + exynos_mipi_dsi_set_main_disp_vporch(dsim, + vid->vl_cmd_allow_len, + lcd_video.upper_margin, + lcd_video.lower_margin); + exynos_mipi_dsi_set_main_disp_hporch(dsim, + lcd_video.left_margin, + lcd_video.right_margin); + exynos_mipi_dsi_set_main_disp_sync_area(dsim, + lcd_video.vsync_len, + lcd_video.hsync_len); + } + } + + exynos_mipi_dsi_set_main_disp_resol(dsim, lcd_video.xres, + lcd_video.yres); + + exynos_mipi_dsi_display_config(dsim, dsim->dsim_config); + + debug("lcd panel ==> width = %d, height = %d\n", + lcd_video.xres, lcd_video.yres); + + return 0; +} + +int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim) +{ + unsigned int time_out = 100; + + switch (dsim->state) { + case DSIM_STATE_INIT: + exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f); + + /* dsi configuration */ + exynos_mipi_dsi_init_config(dsim); + exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1); + exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1); + + /* set clock configuration */ + exynos_mipi_dsi_set_clock(dsim, + dsim->dsim_config->e_byte_clk, 1); + + /* check clock and data lane state are stop state */ + while (!(exynos_mipi_dsi_is_lane_state(dsim))) { + time_out--; + if (time_out == 0) { + debug("DSI Master is not stop state.\n"); + debug("Check initialization process\n"); + + return -EINVAL; + } + } + + dsim->state = DSIM_STATE_STOP; + + /* BTA sequence counters */ + exynos_mipi_dsi_set_stop_state_counter(dsim, + dsim->dsim_config->stop_holding_cnt); + exynos_mipi_dsi_set_bta_timeout(dsim, + dsim->dsim_config->bta_timeout); + exynos_mipi_dsi_set_lpdr_timeout(dsim, + dsim->dsim_config->rx_timeout); + + return 0; + default: + debug("DSI Master is already init.\n"); + return 0; + } + + return 0; +} + +int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim) +{ + if (dsim->state == DSIM_STATE_STOP) { + if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) { + dsim->state = DSIM_STATE_HSCLKEN; + + /* set LCDC and CPU transfer mode to HS. */ + exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0); + exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0); + + exynos_mipi_dsi_enable_hs_clock(dsim, 1); + + return 0; + } else + debug("clock source is external bypass.\n"); + } else + debug("DSIM is not stop state.\n"); + + return 0; +} + +int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int mode) +{ + if (mode) { + if (dsim->state != DSIM_STATE_HSCLKEN) { + debug("HS Clock lane is not enabled.\n"); + return -EINVAL; + } + + exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0); + } else { + if (dsim->state == DSIM_STATE_INIT || dsim->state == + DSIM_STATE_ULPS) { + debug("DSI Master is not STOP or HSDT state.\n"); + return -EINVAL; + } + + exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0); + } + + return 0; +} + +int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim) +{ + return _exynos_mipi_dsi_get_frame_done_status(dsim); +} + +int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim) +{ + _exynos_mipi_dsi_clear_frame_done(dsim); + + return 0; +} diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/exynos/exynos_mipi_dsi_common.h new file mode 100644 index 0000000..98eb78e --- /dev/null +++ b/drivers/video/exynos/exynos_mipi_dsi_common.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#ifndef _EXYNOS_MIPI_DSI_COMMON_H +#define _EXYNOS_MIPI_DSI_COMMON_H + +int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, + const unsigned char *data0, unsigned int data1); +int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable); +unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim, + unsigned int pre_divider, unsigned int main_divider, + unsigned int scaler); +int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim, + unsigned int byte_clk_sel, unsigned int enable); +int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim); +int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, + struct mipi_dsim_config *dsim_info); +int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim); +int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim); +int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int mode); +int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, + unsigned int enable); +int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim); +int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim); + +#endif /* _EXYNOS_MIPI_DSI_COMMON_H */ diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c new file mode 100644 index 0000000..fcfdc8d --- /dev/null +++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c @@ -0,0 +1,639 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include "exynos_mipi_dsi_lowlevel.h" +#include "exynos_mipi_dsi_common.h" + +void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim) +{ + unsigned int reg; + + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = readl(&mipi_dsim->swrst); + + reg |= DSIM_FUNCRST; + + writel(reg, &mipi_dsim->swrst); +} + +void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim) +{ + unsigned int reg = 0; + + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = readl(&mipi_dsim->swrst); + + reg |= DSIM_SWRST; + reg |= DSIM_FUNCRST; + + writel(reg, &mipi_dsim->swrst); +} + +void exynos_mipi_dsi_sw_release(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->intsrc); + + reg |= INTSRC_SWRST_RELEASE; + + writel(reg, &mipi_dsim->intsrc); +} + +void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim, + unsigned int mode, unsigned int mask) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->intmsk); + + if (mask) + reg |= mode; + else + reg &= ~mode; + + writel(reg, &mipi_dsim->intmsk); +} + +void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim, + unsigned int cfg) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = readl(&mipi_dsim->fifoctrl); + + writel(reg & ~(cfg), &mipi_dsim->fifoctrl); + udelay(10 * 1000); + reg |= cfg; + + writel(reg, &mipi_dsim->fifoctrl); +} + +/* + * this function set PLL P, M and S value in D-PHY + */ +void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, + unsigned int value) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + writel(DSIM_AFC_CTL(value), &mipi_dsim->phyacchr); +} + +void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim, + unsigned int width_resol, unsigned int height_resol) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + /* standby should be set after configuration so set to not ready*/ + reg = (readl(&mipi_dsim->mdresol)) & ~(DSIM_MAIN_STAND_BY); + writel(reg, &mipi_dsim->mdresol); + + /* reset resolution */ + reg &= ~(DSIM_MAIN_VRESOL(0x7ff) | DSIM_MAIN_HRESOL(0x7ff)); + reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol); + + reg |= DSIM_MAIN_STAND_BY; + writel(reg, &mipi_dsim->mdresol); +} + +void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim, + unsigned int cmd_allow, unsigned int vfront, unsigned int vback) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = (readl(&mipi_dsim->mvporch)) & + ~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) | + (DSIM_MAIN_VBP_MASK)); + + reg |= ((cmd_allow & 0xf) << DSIM_CMD_ALLOW_SHIFT) | + ((vfront & 0x7ff) << DSIM_STABLE_VFP_SHIFT) | + ((vback & 0x7ff) << DSIM_MAIN_VBP_SHIFT); + + writel(reg, &mipi_dsim->mvporch); +} + +void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim, + unsigned int front, unsigned int back) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = (readl(&mipi_dsim->mhporch)) & + ~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK)); + + reg |= (front << DSIM_MAIN_HFP_SHIFT) | (back << DSIM_MAIN_HBP_SHIFT); + + writel(reg, &mipi_dsim->mhporch); +} + +void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim, + unsigned int vert, unsigned int hori) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = (readl(&mipi_dsim->msync)) & + ~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK)); + + reg |= ((vert & 0x3ff) << DSIM_MAIN_VSA_SHIFT) | + (hori << DSIM_MAIN_HSA_SHIFT); + + writel(reg, &mipi_dsim->msync); +} + +void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim, + unsigned int vert, unsigned int hori) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = (readl(&mipi_dsim->sdresol)) & + ~(DSIM_SUB_STANDY_MASK); + + writel(reg, &mipi_dsim->sdresol); + + reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK); + reg |= ((vert & 0x7ff) << DSIM_SUB_VRESOL_SHIFT) | + ((hori & 0x7ff) << DSIM_SUB_HRESOL_SHIFT); + writel(reg, &mipi_dsim->sdresol); + + /* DSIM STANDBY */ + reg |= (1 << DSIM_SUB_STANDY_SHIFT); + writel(reg, &mipi_dsim->sdresol); +} + +void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim) +{ + struct mipi_dsim_config *dsim_config = dsim->dsim_config; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int cfg = (readl(&mipi_dsim->config)) & + ~((1 << DSIM_EOT_PACKET_SHIFT) | + (0x1f << DSIM_HSA_MODE_SHIFT) | + (0x3 << DSIM_NUM_OF_DATALANE_SHIFT)); + + cfg |= (dsim_config->auto_flush << DSIM_AUTO_FLUSH_SHIFT) | + (dsim_config->eot_disable << DSIM_EOT_PACKET_SHIFT) | + (dsim_config->auto_vertical_cnt << DSIM_AUTO_MODE_SHIFT) | + (dsim_config->hse << DSIM_HSE_MODE_SHIFT) | + (dsim_config->hfp << DSIM_HFP_MODE_SHIFT) | + (dsim_config->hbp << DSIM_HBP_MODE_SHIFT) | + (dsim_config->hsa << DSIM_HSA_MODE_SHIFT) | + (dsim_config->e_no_data_lane << DSIM_NUM_OF_DATALANE_SHIFT); + + writel(cfg, &mipi_dsim->config); +} + +void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim, + struct mipi_dsim_config *dsim_config) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + u32 reg = (readl(&mipi_dsim->config)) & + ~((0x3 << DSIM_BURST_MODE_SHIFT) | (1 << DSIM_VIDEO_MODE_SHIFT) + | (0x3 << DSIM_MAINVC_SHIFT) | (0x7 << DSIM_MAINPIX_SHIFT) + | (0x3 << DSIM_SUBVC_SHIFT) | (0x7 << DSIM_SUBPIX_SHIFT)); + + if (dsim_config->e_interface == DSIM_VIDEO) + reg |= (1 << DSIM_VIDEO_MODE_SHIFT); + else if (dsim_config->e_interface == DSIM_COMMAND) + reg &= ~(1 << DSIM_VIDEO_MODE_SHIFT); + else { + printf("unknown lcd type.\n"); + return; + } + + /* main lcd */ + reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << DSIM_BURST_MODE_SHIFT + | ((u8) (dsim_config->e_virtual_ch) & 0x3) << DSIM_MAINVC_SHIFT + | ((u8) (dsim_config->e_pixel_format) & 0x7) << DSIM_MAINPIX_SHIFT; + + writel(reg, &mipi_dsim->config); +} + +void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, + unsigned int lane, unsigned int enable) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = readl(&mipi_dsim->config); + + if (enable) + reg |= DSIM_LANE_ENx(lane); + else + reg &= ~DSIM_LANE_ENx(lane); + + writel(reg, &mipi_dsim->config); +} + +void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, + unsigned int count) +{ + unsigned int cfg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + /* get the data lane number. */ + cfg = DSIM_NUM_OF_DATA_LANE(count); + + writel(cfg, &mipi_dsim->config); +} + +void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, + unsigned int enable, unsigned int afc_code) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->phyacchr); + + reg = 0; + + if (enable) { + reg |= DSIM_AFC_EN; + reg &= ~(0x7 << DSIM_AFC_CTL_SHIFT); + reg |= DSIM_AFC_CTL(afc_code); + } else + reg &= ~DSIM_AFC_EN; + + writel(reg, &mipi_dsim->phyacchr); +} + +void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->clkctrl)) & + ~(DSIM_PLL_BYPASS_EXTERNAL); + + reg |= enable << DSIM_PLL_BYPASS_SHIFT; + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim, + unsigned int freq_band) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->pllctrl)) & + ~(0x1f << DSIM_FREQ_BAND_SHIFT); + + reg |= ((freq_band & 0x1f) << DSIM_FREQ_BAND_SHIFT); + + writel(reg, &mipi_dsim->pllctrl); +} + +void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim, + unsigned int pre_divider, unsigned int main_divider, + unsigned int scaler) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->pllctrl)) & + ~(0x7ffff << 1); + + reg |= ((pre_divider & 0x3f) << DSIM_PREDIV_SHIFT) | + ((main_divider & 0x1ff) << DSIM_MAIN_SHIFT) | + ((scaler & 0x7) << DSIM_SCALER_SHIFT); + + writel(reg, &mipi_dsim->pllctrl); +} + +void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim, + unsigned int lock_time) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + writel(lock_time, &mipi_dsim->plltmr); +} + +void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->pllctrl)) & + ~(0x1 << DSIM_PLL_EN_SHIFT); + + reg |= ((enable & 0x1) << DSIM_PLL_EN_SHIFT); + + writel(reg, &mipi_dsim->pllctrl); +} + +void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim, + unsigned int src) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->clkctrl)) & + ~(0x3 << DSIM_BYTE_CLK_SRC_SHIFT); + + reg |= ((unsigned int) src) << DSIM_BYTE_CLK_SRC_SHIFT; + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->clkctrl)) & + ~(1 << DSIM_BYTE_CLKEN_SHIFT); + + reg |= enable << DSIM_BYTE_CLKEN_SHIFT; + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim, + unsigned int enable, unsigned int prs_val) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->clkctrl)) & + ~((1 << DSIM_ESC_CLKEN_SHIFT) | (0xffff)); + + reg |= enable << DSIM_ESC_CLKEN_SHIFT; + if (enable) + reg |= prs_val; + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim, + unsigned int lane_sel, unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->clkctrl); + + if (enable) + reg |= DSIM_LANE_ESC_CLKEN(lane_sel); + else + reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel); + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->escmode)) & + ~(0x1 << DSIM_FORCE_STOP_STATE_SHIFT); + + reg |= ((enable & 0x1) << DSIM_FORCE_STOP_STATE_SHIFT); + + writel(reg, &mipi_dsim->escmode); +} + +unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->status); + + /** + * check clock and data lane states. + * if MIPI-DSI controller was enabled at bootloader then + * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK. + * so it should be checked for two case. + */ + if ((reg & DSIM_STOP_STATE_DAT(0xf)) && + ((reg & DSIM_STOP_STATE_CLK) || + (reg & DSIM_TX_READY_HS_CLK))) + return 1; + else + return 0; +} + +void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim, + unsigned int cnt_val) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->escmode)) & + ~(0x7ff << DSIM_STOP_STATE_CNT_SHIFT); + + reg |= ((cnt_val & 0x7ff) << DSIM_STOP_STATE_CNT_SHIFT); + + writel(reg, &mipi_dsim->escmode); +} + +void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim, + unsigned int timeout) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->timeout)) & + ~(0xff << DSIM_BTA_TOUT_SHIFT); + + reg |= (timeout << DSIM_BTA_TOUT_SHIFT); + + writel(reg, &mipi_dsim->timeout); +} + +void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim, + unsigned int timeout) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->timeout)) & + ~(0xffff << DSIM_LPDR_TOUT_SHIFT); + + reg |= (timeout << DSIM_LPDR_TOUT_SHIFT); + + writel(reg, &mipi_dsim->timeout); +} + +void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int lp) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->escmode); + + reg &= ~DSIM_CMD_LPDT_LP; + + if (lp) + reg |= DSIM_CMD_LPDT_LP; + + writel(reg, &mipi_dsim->escmode); +} + +void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int lp) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->escmode); + + reg &= ~DSIM_TX_LPDT_LP; + + if (lp) + reg |= DSIM_TX_LPDT_LP; + + writel(reg, &mipi_dsim->escmode); +} + +void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim, + unsigned int enable) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->clkctrl)) & + ~(1 << DSIM_TX_REQUEST_HSCLK_SHIFT); + + reg |= enable << DSIM_TX_REQUEST_HSCLK_SHIFT; + + writel(reg, &mipi_dsim->clkctrl); +} + +void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim, + unsigned int swap_en) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->phyacchr1); + + reg &= ~(0x3 << DSIM_DPDN_SWAP_DATA_SHIFT); + reg |= (swap_en & 0x3) << DSIM_DPDN_SWAP_DATA_SHIFT; + + writel(reg, &mipi_dsim->phyacchr1); +} + +void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim, + unsigned int hs_zero) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->pllctrl)) & + ~(0xf << DSIM_ZEROCTRL_SHIFT); + + reg |= ((hs_zero & 0xf) << DSIM_ZEROCTRL_SHIFT); + + writel(reg, &mipi_dsim->pllctrl); +} + +void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (readl(&mipi_dsim->pllctrl)) & + ~(0x7 << DSIM_PRECTRL_SHIFT); + + reg |= ((prep & 0x7) << DSIM_PRECTRL_SHIFT); + + writel(reg, &mipi_dsim->pllctrl); +} + +void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->intsrc); + + reg |= INTSRC_PLL_STABLE; + + writel(reg, &mipi_dsim->intsrc); +} + +void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + writel(0xffffffff, &mipi_dsim->intsrc); +} + +unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim) +{ + unsigned int reg; + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + reg = readl(&mipi_dsim->status); + + return reg & DSIM_PLL_STABLE ? 1 : 0; +} + +unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + return readl(&mipi_dsim->fifoctrl) & ~(0x1f); +} + +void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, + unsigned int di, const unsigned char data0, const unsigned char data1) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = (DSIM_PKTHDR_DAT1(data1) | DSIM_PKTHDR_DAT0(data0) | + DSIM_PKTHDR_DI(di)); + + writel(reg, &mipi_dsim->pkthdr); +} + +unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device + *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->intsrc); + + return (reg & INTSRC_FRAME_DONE) ? 1 : 0; +} + +void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + unsigned int reg = readl(&mipi_dsim->intsrc); + + writel(reg | INTSRC_FRAME_DONE, &mipi_dsim->intsrc); +} + +void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim, + unsigned int tx_data) +{ + struct exynos_mipi_dsim *mipi_dsim = + (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); + + writel(tx_data, &mipi_dsim->payload); +} diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h new file mode 100644 index 0000000..0bede25 --- /dev/null +++ b/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * Author: InKi Dae + * Author: Donghwa Lee + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H +#define _EXYNOS_MIPI_DSI_LOWLEVEL_H + +void exynos_mipi_dsi_register(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_sw_release(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim, + unsigned int mode, unsigned int mask); +void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, + unsigned int count); +void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim, + unsigned int cfg); +void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, + unsigned int value); +void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, + unsigned int value); +void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim, + unsigned int width_resol, unsigned int height_resol); +void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim, + unsigned int cmd_allow, unsigned int vfront, unsigned int vback); +void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim, + unsigned int front, unsigned int back); +void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim, + unsigned int vert, unsigned int hori); +void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim, + unsigned int vert, unsigned int hori); +void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim, + struct mipi_dsim_config *dsim_config); +void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, + unsigned int count); +void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, + unsigned int lane, unsigned int enable); +void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, + unsigned int enable, unsigned int afc_code); +void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim, + unsigned int enable); +void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim, + unsigned int freq_band); +void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim, + unsigned int pre_divider, unsigned int main_divider, + unsigned int scaler); +void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim, + unsigned int lock_time); +void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, + unsigned int enable); +void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim, + unsigned int src); +void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim, + unsigned int enable); +void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim, + unsigned int enable, unsigned int prs_val); +void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim, + unsigned int lane_sel, unsigned int enable); +void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim, + unsigned int enable); +unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim, + unsigned int cnt_val); +void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim, + unsigned int timeout); +void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim, + unsigned int timeout); +void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int lp); +void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim, + unsigned int lp); +void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim, + unsigned int enable); +void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim, + unsigned int swap_en); +void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim, + unsigned int hs_zero); +void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, + unsigned int prep); +void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim); +unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim); +unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim); +unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device + *dsim); +void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim); +void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, + unsigned int di, const unsigned char data0, const unsigned char data1); +void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim, + unsigned int tx_data); + +#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */ diff --git a/drivers/video/exynos/exynos_pwm_bl.c b/drivers/video/exynos/exynos_pwm_bl.c new file mode 100644 index 0000000..a6890da --- /dev/null +++ b/drivers/video/exynos/exynos_pwm_bl.c @@ -0,0 +1,45 @@ +/* + * PWM BACKLIGHT driver for Board based on EXYNOS. + * + * Author: Donghwa Lee + * + * Derived from linux/drivers/video/backlight/pwm_backlight.c + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct pwm_backlight_data *pwm; + +static int exynos_pwm_backlight_update_status(void) +{ + int brightness = pwm->brightness; + int max = pwm->max_brightness; + + if (brightness == 0) { + pwm_config(pwm->pwm_id, 0, pwm->period); + pwm_disable(pwm->pwm_id); + } else { + pwm_config(pwm->pwm_id, + brightness * pwm->period / max, pwm->period); + pwm_enable(pwm->pwm_id); + } + return 0; +} + +int exynos_pwm_backlight_init(struct pwm_backlight_data *pd) +{ + pwm = pd; + + exynos_pwm_backlight_update_status(); + + return 0; +} diff --git a/drivers/video/exynos_dp.c b/drivers/video/exynos_dp.c deleted file mode 100644 index 0d5d090..0000000 --- a/drivers/video/exynos_dp.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "exynos_dp_lowlevel.h" - -DECLARE_GLOBAL_DATA_PTR; - -void __exynos_set_dp_phy(unsigned int onoff) -{ -} -void exynos_set_dp_phy(unsigned int onoff) - __attribute__((weak, alias("__exynos_set_dp_phy"))); - -static void exynos_dp_disp_info(struct edp_disp_info *disp_info) -{ - disp_info->h_total = disp_info->h_res + disp_info->h_sync_width + - disp_info->h_back_porch + disp_info->h_front_porch; - disp_info->v_total = disp_info->v_res + disp_info->v_sync_width + - disp_info->v_back_porch + disp_info->v_front_porch; - - return; -} - -static int exynos_dp_init_dp(void) -{ - int ret; - exynos_dp_reset(); - - /* SW defined function Normal operation */ - exynos_dp_enable_sw_func(DP_ENABLE); - - ret = exynos_dp_init_analog_func(); - if (ret != EXYNOS_DP_SUCCESS) - return ret; - - exynos_dp_init_hpd(); - exynos_dp_init_aux(); - - return ret; -} - -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) -{ - int i; - unsigned char sum = 0; - - for (i = 0; i < EDID_BLOCK_LENGTH; i++) - sum = sum + edid_data[i]; - - return sum; -} - -static unsigned int exynos_dp_read_edid(void) -{ - unsigned char edid[EDID_BLOCK_LENGTH * 2]; - unsigned int extend_block = 0; - unsigned char sum; - unsigned char test_vector; - int retval; - - /* - * EDID device address is 0x50. - * However, if necessary, you must have set upper address - * into E-EDID in I2C device, 0x30. - */ - - /* Read Extension Flag, Number of 128-byte EDID extension blocks */ - exynos_dp_read_byte_from_i2c(I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, - &extend_block); - - if (extend_block > 0) { - printf("DP EDID data includes a single extension!\n"); - - /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); - if (retval != 0) { - printf("DP EDID Read failed!\n"); - return -1; - } - sum = exynos_dp_calc_edid_check_sum(edid); - if (sum != 0) { - printf("DP EDID bad checksum!\n"); - return -1; - } - - /* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, - EDID_BLOCK_LENGTH, - EDID_BLOCK_LENGTH, - &edid[EDID_BLOCK_LENGTH]); - if (retval != 0) { - printf("DP EDID Read failed!\n"); - return -1; - } - sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); - if (sum != 0) { - printf("DP EDID bad checksum!\n"); - return -1; - } - - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, - &test_vector); - if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, - edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, - DPCD_TEST_EDID_CHECKSUM_WRITE); - } - } else { - debug("DP EDID data does not include any extensions.\n"); - - /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); - - if (retval != 0) { - printf("DP EDID Read failed!\n"); - return -1; - } - sum = exynos_dp_calc_edid_check_sum(edid); - if (sum != 0) { - printf("DP EDID bad checksum!\n"); - return -1; - } - - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, - &test_vector); - if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, - edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, - DPCD_TEST_EDID_CHECKSUM_WRITE); - } - } - - debug("DP EDID Read success!\n"); - - return 0; -} - -static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) -{ - unsigned char buf[12]; - unsigned int ret; - unsigned char temp; - unsigned char retry_cnt; - unsigned char dpcd_rev[16]; - unsigned char lane_bw[16]; - unsigned char lane_cnt[16]; - - memset(dpcd_rev, 0, 16); - memset(lane_bw, 0, 16); - memset(lane_cnt, 0, 16); - memset(buf, 0, 12); - - retry_cnt = 5; - while (retry_cnt) { - /* Read DPCD 0x0000-0x000b */ - ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12, - buf); - if (ret != EXYNOS_DP_SUCCESS) { - if (retry_cnt == 0) { - printf("DP read_byte_from_dpcd() failed\n"); - return ret; - } - retry_cnt--; - } else - break; - } - - /* */ - temp = buf[DPCD_DPCD_REV]; - if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11) - edp_info->dpcd_rev = temp; - else { - printf("DP Wrong DPCD Rev : %x\n", temp); - return -ENODEV; - } - - temp = buf[DPCD_MAX_LINK_RATE]; - if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70) - edp_info->lane_bw = temp; - else { - printf("DP Wrong MAX LINK RATE : %x\n", temp); - return -EINVAL; - } - - /* Refer VESA Display Port Standard Ver1.1a Page 120 */ - if (edp_info->dpcd_rev == DP_DPCD_REV_11) { - temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f; - if (buf[DPCD_MAX_LANE_COUNT] & 0x80) - edp_info->dpcd_efc = 1; - else - edp_info->dpcd_efc = 0; - } else { - temp = buf[DPCD_MAX_LANE_COUNT]; - edp_info->dpcd_efc = 0; - } - - if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 || - temp == DP_LANE_CNT_4) { - edp_info->lane_cnt = temp; - } else { - printf("DP Wrong MAX LANE COUNT : %x\n", temp); - return -EINVAL; - } - - ret = exynos_dp_read_edid(); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP exynos_dp_read_edid() failed\n"); - return -EINVAL; - } - - return ret; -} - -static void exynos_dp_init_training(void) -{ - /* - * MACRO_RST must be applied after the PLL_LOCK to avoid - * the DP inter pair skew issue for at least 10 us - */ - exynos_dp_reset_macro(); - - /* All DP analog module power up */ - exynos_dp_set_analog_power_down(POWER_ALL, 0); -} - -static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) -{ - unsigned char buf[5]; - unsigned int ret = 0; - - debug("DP: %s was called\n", __func__); - - edp_info->lt_info.lt_status = DP_LT_CR; - edp_info->lt_info.ep_loop = 0; - edp_info->lt_info.cr_loop[0] = 0; - edp_info->lt_info.cr_loop[1] = 0; - edp_info->lt_info.cr_loop[2] = 0; - edp_info->lt_info.cr_loop[3] = 0; - - /* Set sink to D0 (Sink Not Ready) mode. */ - ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE, - DPCD_SET_POWER_STATE_D0); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write_dpcd_byte failed\n"); - return ret; - } - - /* Set link rate and count as you want to establish */ - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); - - /* Setup RX configuration */ - buf[0] = edp_info->lane_bw; - buf[1] = edp_info->lane_cnt; - - ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2, - buf); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write_dpcd_byte failed\n"); - return ret; - } - - exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0, - edp_info->lane_cnt); - - /* Set training pattern 1 */ - exynos_dp_set_training_pattern(TRAINING_PTN1); - - /* Set RX training pattern */ - buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; - - buf[1] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | - DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - buf[2] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | - DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - buf[3] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | - DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | - DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - - ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET, - 5, buf); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write_dpcd_byte failed\n"); - return ret; - } - - return ret; -} - -static unsigned int exynos_dp_training_pattern_dis(void) -{ - unsigned int ret = EXYNOS_DP_SUCCESS; - - exynos_dp_set_training_pattern(DP_NONE); - - ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, - DPCD_TRAINING_PATTERN_DISABLED); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP request_link_training_req failed\n"); - return -EAGAIN; - } - - return ret; -} - -static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) -{ - unsigned char data; - unsigned int ret = EXYNOS_DP_SUCCESS; - - ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET, - &data); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read_from_dpcd failed\n"); - return -EAGAIN; - } - - if (enable) - data = DPCD_ENHANCED_FRAME_EN | DPCD_LN_COUNT_SET(data); - else - data = DPCD_LN_COUNT_SET(data); - - ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET, - data); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write_to_dpcd failed\n"); - return -EAGAIN; - - } - - return ret; -} - -static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode) -{ - unsigned int ret = EXYNOS_DP_SUCCESS; - - ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP rx_enhance_mode failed\n"); - return -EAGAIN; - } - - exynos_dp_enable_enhanced_mode(enhance_mode); - - return ret; -} - -static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, - unsigned char *status) -{ - unsigned int ret, i; - unsigned char buf[2]; - unsigned char lane_stat[DP_LANE_CNT_4] = {0,}; - unsigned char shift_val[DP_LANE_CNT_4] = {0,}; - - shift_val[0] = 0; - shift_val[1] = 4; - shift_val[2] = 0; - shift_val[3] = 4; - - ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read lane status failed\n"); - return ret; - } - - for (i = 0; i < edp_info->lane_cnt; i++) { - lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f; - if (lane_stat[0] != lane_stat[i]) { - printf("Wrong lane status\n"); - return -EINVAL; - } - } - - *status = lane_stat[0]; - - return ret; -} - -static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, - unsigned char *sw, unsigned char *em) -{ - unsigned int ret = EXYNOS_DP_SUCCESS; - unsigned char buf; - unsigned int dpcd_addr; - unsigned char shift_val[DP_LANE_CNT_4] = {0, 4, 0, 4}; - - /* lane_num value is used as array index, so this range 0 ~ 3 */ - dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); - - ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read adjust request failed\n"); - return -EAGAIN; - } - - *sw = ((buf >> shift_val[lane_num]) & 0x03); - *em = ((buf >> shift_val[lane_num]) & 0x0c) >> 2; - - return ret; -} - -static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) -{ - int ret; - - ret = exynos_dp_training_pattern_dis(); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP training_pattern_disable() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - } - - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP set_enhanced_mode() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - } - - return ret; -} - -static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) -{ - int ret; - - if (edp_info->lane_bw == DP_LANE_BW_2_70) { - edp_info->lane_bw = DP_LANE_BW_1_62; - printf("DP Change lane bw to 1.62Gbps\n"); - edp_info->lt_info.lt_status = DP_LT_START; - ret = EXYNOS_DP_SUCCESS; - } else { - ret = exynos_dp_training_pattern_dis(); - if (ret != EXYNOS_DP_SUCCESS) - printf("DP training_patter_disable() failed\n"); - - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); - if (ret != EXYNOS_DP_SUCCESS) - printf("DP set_enhanced_mode() failed\n"); - - edp_info->lt_info.lt_status = DP_LT_FAIL; - } - - return ret; -} - -static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info - *edp_info) -{ - unsigned int ret = EXYNOS_DP_SUCCESS; - unsigned char lane_stat; - unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0, }; - unsigned int i; - unsigned char adj_req_sw; - unsigned char adj_req_em; - unsigned char buf[5]; - - debug("DP: %s was called\n", __func__); - mdelay(1); - - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } - - if (lane_stat & DP_LANE_STAT_CR_DONE) { - debug("DP clock Recovery training succeed\n"); - exynos_dp_set_training_pattern(TRAINING_PTN2); - - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw, - &adj_req_em); - if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } - - lt_ctl_val[i] = 0; - lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; - - if ((adj_req_sw == VOLTAGE_LEVEL_3) - || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { - lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | - MAX_PRE_EMPHASIS_REACH_3; - } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); - } - - buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2; - buf[1] = lt_ctl_val[0]; - buf[2] = lt_ctl_val[1]; - buf[3] = lt_ctl_val[2]; - buf[4] = lt_ctl_val[3]; - - ret = exynos_dp_write_bytes_to_dpcd( - DPCD_TRAINING_PATTERN_SET, 5, buf); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write training pattern1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } else - edp_info->lt_info.lt_status = DP_LT_ET; - } else { - for (i = 0; i < edp_info->lane_cnt; i++) { - lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i); - ret = exynos_dp_read_dpcd_adj_req(i, - &adj_req_sw, &adj_req_em); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read adj req failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } - - if ((adj_req_sw == VOLTAGE_LEVEL_3) || - (adj_req_em == PRE_EMPHASIS_LEVEL_3)) - ret = exynos_dp_reduce_link_rate(edp_info); - - if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == - adj_req_sw) && - (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) == - adj_req_em)) { - edp_info->lt_info.cr_loop[i]++; - if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) - ret = exynos_dp_reduce_link_rate( - edp_info); - } - - lt_ctl_val[i] = 0; - lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; - - if ((adj_req_sw == VOLTAGE_LEVEL_3) || - (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { - lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | - MAX_PRE_EMPHASIS_REACH_3; - } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); - } - - ret = exynos_dp_write_bytes_to_dpcd( - DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP write training pattern2 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } - } - - return ret; -} - -static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info - *edp_info) -{ - unsigned int ret = EXYNOS_DP_SUCCESS; - unsigned char lane_stat, adj_req_sw, adj_req_em, i; - unsigned char lt_ctl_val[DP_LANE_CNT_4] = {0,}; - unsigned char interlane_aligned = 0; - unsigned char f_bw; - unsigned char f_lane_cnt; - unsigned char sink_stat; - - mdelay(1); - - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - return ret; - } - - debug("DP lane stat : %x\n", lane_stat); - - if (lane_stat & DP_LANE_STAT_CR_DONE) { - ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED, - &sink_stat); - if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; - - return ret; - } - - interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); - - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, - &adj_req_sw, &adj_req_em); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP read adj req 1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; - - return ret; - } - - lt_ctl_val[i] = 0; - lt_ctl_val[i] = adj_req_em << 3 | adj_req_sw; - - if ((adj_req_sw == VOLTAGE_LEVEL_3) || - (adj_req_em == PRE_EMPHASIS_LEVEL_3)) { - lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3; - lt_ctl_val[i] |= MAX_PRE_EMPHASIS_REACH_3; - } - } - - if (((lane_stat&DP_LANE_STAT_CE_DONE) && - (lane_stat&DP_LANE_STAT_SYM_LOCK)) - && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { - debug("DP Equalizer training succeed\n"); - - f_bw = exynos_dp_get_link_bandwidth(); - f_lane_cnt = exynos_dp_get_lane_count(); - - debug("DP final BandWidth : %x\n", f_bw); - debug("DP final Lane Count : %x\n", f_lane_cnt); - - edp_info->lt_info.lt_status = DP_LT_FINISHED; - - exynos_dp_equalizer_err_link(edp_info); - - } else { - edp_info->lt_info.ep_loop++; - - if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { - if (edp_info->lane_bw == DP_LANE_BW_2_70) { - ret = exynos_dp_reduce_link_rate( - edp_info); - } else { - edp_info->lt_info.lt_status = - DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); - } - } else { - for (i = 0; i < edp_info->lane_cnt; i++) - exynos_dp_set_lanex_pre_emphasis( - lt_ctl_val[i], i); - - ret = exynos_dp_write_bytes_to_dpcd( - DPCD_TRAINING_LANE0_SET, - 4, lt_ctl_val); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP set lt pattern failed\n"); - edp_info->lt_info.lt_status = - DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); - } - } - } - } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { - ret = exynos_dp_reduce_link_rate(edp_info); - } else { - edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); - } - - return ret; -} - -static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) -{ - unsigned int ret = 0; - int training_finished; - - /* Turn off unnecessary lane */ - if (edp_info->lane_cnt == 1) - exynos_dp_set_analog_power_down(CH1_BLOCK, 1); - - training_finished = 0; - - edp_info->lt_info.lt_status = DP_LT_START; - - /* Process here */ - while (!training_finished) { - switch (edp_info->lt_info.lt_status) { - case DP_LT_START: - ret = exynos_dp_link_start(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP LT:link start failed\n"); - return ret; - } - break; - case DP_LT_CR: - ret = exynos_dp_process_clock_recovery(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP LT:clock recovery failed\n"); - return ret; - } - break; - case DP_LT_ET: - ret = exynos_dp_process_equalizer_training(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP LT:equalizer training failed\n"); - return ret; - } - break; - case DP_LT_FINISHED: - training_finished = 1; - break; - case DP_LT_FAIL: - return -1; - } - } - - return ret; -} - -static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info) -{ - unsigned int ret; - - exynos_dp_init_training(); - - ret = exynos_dp_sw_link_training(edp_info); - if (ret != EXYNOS_DP_SUCCESS) - printf("DP dp_sw_link_training() failed\n"); - - return ret; -} - -static void exynos_dp_enable_scramble(unsigned int enable) -{ - unsigned char data; - - if (enable) { - exynos_dp_enable_scrambling(DP_ENABLE); - - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, - (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); - } else { - exynos_dp_enable_scrambling(DP_DISABLE); - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, - (u8)(data | DPCD_SCRAMBLING_DISABLED)); - } -} - -static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) -{ - unsigned int ret = 0; - unsigned int retry_cnt; - - mdelay(1); - - if (edp_info->video_info.master_mode) { - printf("DP does not support master mode\n"); - return -ENODEV; - } else { - /* debug slave */ - exynos_dp_config_video_slave_mode(&edp_info->video_info); - } - - exynos_dp_set_video_color_format(&edp_info->video_info); - - if (edp_info->video_info.bist_mode) { - if (exynos_dp_config_video_bist(edp_info) != 0) - return -1; - } - - ret = exynos_dp_get_pll_lock_status(); - if (ret != PLL_LOCKED) { - printf("DP PLL is not locked yet\n"); - return -EIO; - } - - if (edp_info->video_info.master_mode == 0) { - retry_cnt = 10; - while (retry_cnt) { - ret = exynos_dp_is_slave_video_stream_clock_on(); - if (ret != EXYNOS_DP_SUCCESS) { - if (retry_cnt == 0) { - printf("DP stream_clock_on failed\n"); - return ret; - } - retry_cnt--; - mdelay(1); - } else - break; - } - } - - /* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0); - - /* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE); - - /* Enable video bist */ - if (edp_info->video_info.bist_pattern != COLOR_RAMP && - edp_info->video_info.bist_pattern != BALCK_WHITE_V_LINES && - edp_info->video_info.bist_pattern != COLOR_SQUARE) - exynos_dp_enable_video_bist(edp_info->video_info.bist_mode); - else - exynos_dp_enable_video_bist(DP_DISABLE); - - /* Disable video mute */ - exynos_dp_enable_video_mute(DP_DISABLE); - - /* Configure video Master or Slave mode */ - exynos_dp_enable_video_master(edp_info->video_info.master_mode); - - /* Enable video */ - exynos_dp_start_video(); - - if (edp_info->video_info.master_mode == 0) { - retry_cnt = 100; - while (retry_cnt) { - ret = exynos_dp_is_video_stream_on(); - if (ret != EXYNOS_DP_SUCCESS) { - if (retry_cnt == 0) { - printf("DP Timeout of video stream\n"); - return ret; - } - retry_cnt--; - mdelay(5); - } else - break; - } - } - - return ret; -} - -int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) -{ - unsigned int node = fdtdec_next_compatible(blob, 0, - COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) { - debug("exynos_dp: Can't get device node for dp\n"); - return -ENODEV; - } - - edp_info->disp_info.h_res = fdtdec_get_int(blob, node, - "samsung,h-res", 0); - edp_info->disp_info.h_sync_width = fdtdec_get_int(blob, node, - "samsung,h-sync-width", 0); - edp_info->disp_info.h_back_porch = fdtdec_get_int(blob, node, - "samsung,h-back-porch", 0); - edp_info->disp_info.h_front_porch = fdtdec_get_int(blob, node, - "samsung,h-front-porch", 0); - edp_info->disp_info.v_res = fdtdec_get_int(blob, node, - "samsung,v-res", 0); - edp_info->disp_info.v_sync_width = fdtdec_get_int(blob, node, - "samsung,v-sync-width", 0); - edp_info->disp_info.v_back_porch = fdtdec_get_int(blob, node, - "samsung,v-back-porch", 0); - edp_info->disp_info.v_front_porch = fdtdec_get_int(blob, node, - "samsung,v-front-porch", 0); - edp_info->disp_info.v_sync_rate = fdtdec_get_int(blob, node, - "samsung,v-sync-rate", 0); - - edp_info->lt_info.lt_status = fdtdec_get_int(blob, node, - "samsung,lt-status", 0); - - edp_info->video_info.master_mode = fdtdec_get_int(blob, node, - "samsung,master-mode", 0); - edp_info->video_info.bist_mode = fdtdec_get_int(blob, node, - "samsung,bist-mode", 0); - edp_info->video_info.bist_pattern = fdtdec_get_int(blob, node, - "samsung,bist-pattern", 0); - edp_info->video_info.h_sync_polarity = fdtdec_get_int(blob, node, - "samsung,h-sync-polarity", 0); - edp_info->video_info.v_sync_polarity = fdtdec_get_int(blob, node, - "samsung,v-sync-polarity", 0); - edp_info->video_info.interlaced = fdtdec_get_int(blob, node, - "samsung,interlaced", 0); - edp_info->video_info.color_space = fdtdec_get_int(blob, node, - "samsung,color-space", 0); - edp_info->video_info.dynamic_range = fdtdec_get_int(blob, node, - "samsung,dynamic-range", 0); - edp_info->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, - "samsung,ycbcr-coeff", 0); - edp_info->video_info.color_depth = fdtdec_get_int(blob, node, - "samsung,color-depth", 0); - return 0; -} - -unsigned int exynos_init_dp(void) -{ - unsigned int ret; - struct edp_device_info *edp_info; - - edp_info = kzalloc(sizeof(struct edp_device_info), GFP_KERNEL); - if (!edp_info) { - debug("failed to allocate edp device object.\n"); - return -EFAULT; - } - - if (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) - debug("unable to parse DP DT node\n"); - - exynos_dp_set_base_addr(); - - exynos_dp_disp_info(&edp_info->disp_info); - - exynos_set_dp_phy(1); - - ret = exynos_dp_init_dp(); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP exynos_dp_init_dp() failed\n"); - return ret; - } - - ret = exynos_dp_handle_edid(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("EDP handle_edid fail\n"); - return ret; - } - - ret = exynos_dp_set_link_train(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP link training fail\n"); - return ret; - } - - exynos_dp_enable_scramble(DP_ENABLE); - exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE); - exynos_dp_enable_enhanced_mode(DP_ENABLE); - - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); - - exynos_dp_init_video(); - ret = exynos_dp_config_video(edp_info); - if (ret != EXYNOS_DP_SUCCESS) { - printf("Exynos DP init failed\n"); - return ret; - } - - debug("Exynos DP init done\n"); - - return ret; -} diff --git a/drivers/video/exynos_dp_lowlevel.c b/drivers/video/exynos_dp_lowlevel.c deleted file mode 100644 index acb5bc8..0000000 --- a/drivers/video/exynos_dp_lowlevel.c +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Declare global data pointer */ -DECLARE_GLOBAL_DATA_PTR; - -struct exynos_dp *dp_regs; - -void exynos_dp_set_base_addr(void) -{ -#if CONFIG_IS_ENABLED(OF_CONTROL) - unsigned int node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) - debug("exynos_dp: Can't get device node for dp\n"); - - dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if (dp_regs == NULL) - debug("Can't get the DP base address\n"); -#else - dp_regs = (struct exynos_dp *)samsung_get_base_dp(); -#endif -} - -static void exynos_dp_enable_video_input(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->video_ctl1); - reg &= ~VIDEO_EN_MASK; - - /* enable video input */ - if (enable) - reg |= VIDEO_EN_MASK; - - writel(reg, &dp_regs->video_ctl1); - - return; -} - -void exynos_dp_enable_video_bist(unsigned int enable) -{ - /* enable video bist */ - unsigned int reg; - - reg = readl(&dp_regs->video_ctl4); - reg &= ~VIDEO_BIST_MASK; - - /* enable video bist */ - if (enable) - reg |= VIDEO_BIST_MASK; - - writel(reg, &dp_regs->video_ctl4); - - return; -} - -void exynos_dp_enable_video_mute(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->video_ctl1); - reg &= ~(VIDEO_MUTE_MASK); - if (enable) - reg |= VIDEO_MUTE_MASK; - - writel(reg, &dp_regs->video_ctl1); - - return; -} - - -static void exynos_dp_init_analog_param(void) -{ - unsigned int reg; - - /* - * Set termination - * Normal bandgap, Normal swing, Tx terminal registor 61 ohm - * 24M Phy clock, TX digital logic power is 100:1.0625V - */ - reg = SEL_BG_NEW_BANDGAP | TX_TERMINAL_CTRL_61_OHM | - SWING_A_30PER_G_NORMAL; - writel(reg, &dp_regs->analog_ctl1); - - reg = SEL_24M | TX_DVDD_BIT_1_0625V; - writel(reg, &dp_regs->analog_ctl2); - - /* - * Set power source for internal clk driver to 1.0625v. - * Select current reference of TX driver current to 00:Ipp/2+Ic/2. - * Set VCO range of PLL +- 0uA - */ - reg = DRIVE_DVDD_BIT_1_0625V | SEL_CURRENT_DEFAULT | VCO_BIT_000_MICRO; - writel(reg, &dp_regs->analog_ctl3); - - /* - * Set AUX TX terminal resistor to 102 ohm - * Set AUX channel amplitude control - */ - reg = PD_RING_OSC | AUX_TERMINAL_CTRL_52_OHM | TX_CUR1_2X | TX_CUR_4_MA; - writel(reg, &dp_regs->pll_filter_ctl1); - - /* - * PLL loop filter bandwidth - * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz - * PLL digital power select: 1.2500V - */ - reg = CH3_AMP_0_MV | CH2_AMP_0_MV | CH1_AMP_0_MV | CH0_AMP_0_MV; - - writel(reg, &dp_regs->amp_tuning_ctl); - - /* - * PLL loop filter bandwidth - * For 2.7Gbps: 175KHz, For 1.62Gbps: 234KHz - * PLL digital power select: 1.1250V - */ - reg = DP_PLL_LOOP_BIT_DEFAULT | DP_PLL_REF_BIT_1_1250V; - writel(reg, &dp_regs->pll_ctl); -} - -static void exynos_dp_init_interrupt(void) -{ - /* Set interrupt registers to initial states */ - - /* - * Disable interrupt - * INT pin assertion polarity. It must be configured - * correctly according to ICU setting. - * 1 = assert high, 0 = assert low - */ - writel(INT_POL, &dp_regs->int_ctl); - - /* Clear pending registers */ - writel(0xff, &dp_regs->common_int_sta1); - writel(0xff, &dp_regs->common_int_sta2); - writel(0xff, &dp_regs->common_int_sta3); - writel(0xff, &dp_regs->common_int_sta4); - writel(0xff, &dp_regs->int_sta); - - /* 0:mask,1: unmask */ - writel(0x00, &dp_regs->int_sta_mask1); - writel(0x00, &dp_regs->int_sta_mask2); - writel(0x00, &dp_regs->int_sta_mask3); - writel(0x00, &dp_regs->int_sta_mask4); - writel(0x00, &dp_regs->int_sta_mask); -} - -void exynos_dp_reset(void) -{ - unsigned int reg_func_1; - - /* dp tx sw reset */ - writel(RESET_DP_TX, &dp_regs->tx_sw_reset); - - exynos_dp_enable_video_input(DP_DISABLE); - exynos_dp_enable_video_bist(DP_DISABLE); - exynos_dp_enable_video_mute(DP_DISABLE); - - /* software reset */ - reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | - AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | - HDCP_FUNC_EN_N | SW_FUNC_EN_N; - - writel(reg_func_1, &dp_regs->func_en1); - writel(reg_func_1, &dp_regs->func_en2); - - mdelay(1); - - exynos_dp_init_analog_param(); - exynos_dp_init_interrupt(); - - return; -} - -void exynos_dp_enable_sw_func(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->func_en1); - reg &= ~(SW_FUNC_EN_N); - - if (!enable) - reg |= SW_FUNC_EN_N; - - writel(reg, &dp_regs->func_en1); - - return; -} - -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->phy_pd); - switch (block) { - case AUX_BLOCK: - reg &= ~(AUX_PD); - if (enable) - reg |= AUX_PD; - break; - case CH0_BLOCK: - reg &= ~(CH0_PD); - if (enable) - reg |= CH0_PD; - break; - case CH1_BLOCK: - reg &= ~(CH1_PD); - if (enable) - reg |= CH1_PD; - break; - case CH2_BLOCK: - reg &= ~(CH2_PD); - if (enable) - reg |= CH2_PD; - break; - case CH3_BLOCK: - reg &= ~(CH3_PD); - if (enable) - reg |= CH3_PD; - break; - case ANALOG_TOTAL: - reg &= ~PHY_PD; - if (enable) - reg |= PHY_PD; - break; - case POWER_ALL: - reg &= ~(PHY_PD | AUX_PD | CH0_PD | CH1_PD | CH2_PD | - CH3_PD); - if (enable) - reg |= (PHY_PD | AUX_PD | CH0_PD | CH1_PD | - CH2_PD | CH3_PD); - break; - default: - printf("DP undefined block number : %d\n", block); - return -1; - } - - writel(reg, &dp_regs->phy_pd); - - return 0; -} - -unsigned int exynos_dp_get_pll_lock_status(void) -{ - unsigned int reg; - - reg = readl(&dp_regs->debug_ctl); - - if (reg & PLL_LOCK) - return PLL_LOCKED; - else - return PLL_UNLOCKED; -} - -static void exynos_dp_set_pll_power(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->pll_ctl); - reg &= ~(DP_PLL_PD); - - if (!enable) - reg |= DP_PLL_PD; - - writel(reg, &dp_regs->pll_ctl); -} - -int exynos_dp_init_analog_func(void) -{ - int ret = EXYNOS_DP_SUCCESS; - unsigned int retry_cnt = 10; - unsigned int reg; - - /* Power On All Analog block */ - exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); - - reg = PLL_LOCK_CHG; - writel(reg, &dp_regs->common_int_sta1); - - reg = readl(&dp_regs->debug_ctl); - reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); - writel(reg, &dp_regs->debug_ctl); - - /* Assert DP PLL Reset */ - reg = readl(&dp_regs->pll_ctl); - reg |= DP_PLL_RESET; - writel(reg, &dp_regs->pll_ctl); - - mdelay(1); - - /* Deassert DP PLL Reset */ - reg = readl(&dp_regs->pll_ctl); - reg &= ~(DP_PLL_RESET); - writel(reg, &dp_regs->pll_ctl); - - exynos_dp_set_pll_power(DP_ENABLE); - - while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) { - mdelay(1); - retry_cnt--; - if (retry_cnt == 0) { - printf("DP dp's pll lock failed : retry : %d\n", - retry_cnt); - return -EINVAL; - } - } - - debug("dp's pll lock success(%d)\n", retry_cnt); - - /* Enable Serdes FIFO function and Link symbol clock domain module */ - reg = readl(&dp_regs->func_en2); - reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N - | AUX_FUNC_EN_N); - writel(reg, &dp_regs->func_en2); - - return ret; -} - -void exynos_dp_init_hpd(void) -{ - unsigned int reg; - - /* Clear interrupts related to Hot Plug Detect */ - reg = HOTPLUG_CHG | HPD_LOST | PLUG; - writel(reg, &dp_regs->common_int_sta4); - - reg = INT_HPD; - writel(reg, &dp_regs->int_sta); - - reg = readl(&dp_regs->sys_ctl3); - reg &= ~(F_HPD | HPD_CTRL); - writel(reg, &dp_regs->sys_ctl3); - - return; -} - -static inline void exynos_dp_reset_aux(void) -{ - unsigned int reg; - - /* Disable AUX channel module */ - reg = readl(&dp_regs->func_en2); - reg |= AUX_FUNC_EN_N; - writel(reg, &dp_regs->func_en2); - - return; -} - -void exynos_dp_init_aux(void) -{ - unsigned int reg; - - /* Clear interrupts related to AUX channel */ - reg = RPLY_RECEIV | AUX_ERR; - writel(reg, &dp_regs->int_sta); - - exynos_dp_reset_aux(); - - /* Disable AUX transaction H/W retry */ - reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)| - AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; - writel(reg, &dp_regs->aux_hw_retry_ctl); - - /* Receive AUX Channel DEFER commands equal to DEFER_COUNT*64 */ - reg = DEFER_CTRL_EN | DEFER_COUNT(1); - writel(reg, &dp_regs->aux_ch_defer_ctl); - - /* Enable AUX channel module */ - reg = readl(&dp_regs->func_en2); - reg &= ~AUX_FUNC_EN_N; - writel(reg, &dp_regs->func_en2); - - return; -} - -void exynos_dp_config_interrupt(void) -{ - unsigned int reg; - - /* 0: mask, 1: unmask */ - reg = COMMON_INT_MASK_1; - writel(reg, &dp_regs->common_int_mask1); - - reg = COMMON_INT_MASK_2; - writel(reg, &dp_regs->common_int_mask2); - - reg = COMMON_INT_MASK_3; - writel(reg, &dp_regs->common_int_mask3); - - reg = COMMON_INT_MASK_4; - writel(reg, &dp_regs->common_int_mask4); - - reg = INT_STA_MASK; - writel(reg, &dp_regs->int_sta_mask); - - return; -} - -unsigned int exynos_dp_get_plug_in_status(void) -{ - unsigned int reg; - - reg = readl(&dp_regs->sys_ctl3); - if (reg & HPD_STATUS) - return 0; - - return -1; -} - -unsigned int exynos_dp_detect_hpd(void) -{ - int timeout_loop = DP_TIMEOUT_LOOP_COUNT; - - mdelay(2); - - while (exynos_dp_get_plug_in_status() != 0) { - if (timeout_loop == 0) - return -EINVAL; - mdelay(10); - timeout_loop--; - } - - return EXYNOS_DP_SUCCESS; -} - -unsigned int exynos_dp_start_aux_transaction(void) -{ - unsigned int reg; - unsigned int ret = 0; - unsigned int retry_cnt; - - /* Enable AUX CH operation */ - reg = readl(&dp_regs->aux_ch_ctl2); - reg |= AUX_EN; - writel(reg, &dp_regs->aux_ch_ctl2); - - retry_cnt = 10; - while (retry_cnt) { - reg = readl(&dp_regs->int_sta); - if (!(reg & RPLY_RECEIV)) { - if (retry_cnt == 0) { - printf("DP Reply Timeout!!\n"); - ret = -EAGAIN; - return ret; - } - mdelay(1); - retry_cnt--; - } else - break; - } - - /* Clear interrupt source for AUX CH command reply */ - writel(reg, &dp_regs->int_sta); - - /* Clear interrupt source for AUX CH access error */ - reg = readl(&dp_regs->int_sta); - if (reg & AUX_ERR) { - printf("DP Aux Access Error\n"); - writel(AUX_ERR, &dp_regs->int_sta); - ret = -EAGAIN; - return ret; - } - - /* Check AUX CH error access status */ - reg = readl(&dp_regs->aux_ch_sta); - if ((reg & AUX_STATUS_MASK) != 0) { - debug("DP AUX CH error happens: %x\n", reg & AUX_STATUS_MASK); - ret = -EAGAIN; - return ret; - } - - return EXYNOS_DP_SUCCESS; -} - -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data) -{ - unsigned int reg, ret; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr); - writel(reg, &dp_regs->aux_addr_7_0); - reg = AUX_ADDR_15_8(reg_addr); - writel(reg, &dp_regs->aux_addr_15_8); - reg = AUX_ADDR_19_16(reg_addr); - writel(reg, &dp_regs->aux_addr_19_16); - - /* Write data buffer */ - reg = (unsigned int)data; - writel(reg, &dp_regs->buf_data0); - - /* - * Set DisplayPort transaction and write 1 byte - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); - if (ret != EXYNOS_DP_SUCCESS) { - printf("DP Aux transaction failed\n"); - return ret; - } - - return ret; -} - -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data) -{ - unsigned int reg; - int retval; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr); - writel(reg, &dp_regs->aux_addr_7_0); - reg = AUX_ADDR_15_8(reg_addr); - writel(reg, &dp_regs->aux_addr_15_8); - reg = AUX_ADDR_19_16(reg_addr); - writel(reg, &dp_regs->aux_addr_19_16); - - /* - * Set DisplayPort transaction and read 1 byte - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); - if (!retval) - debug("DP Aux Transaction fail!\n"); - - /* Read data buffer */ - reg = readl(&dp_regs->buf_data0); - *data = (unsigned char)(reg & 0xff); - - return retval; -} - -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) -{ - unsigned int reg; - unsigned int start_offset; - unsigned int cur_data_count; - unsigned int cur_data_idx; - unsigned int retry_cnt; - unsigned int ret = 0; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - start_offset = 0; - while (start_offset < count) { - /* Buffer size of AUX CH is 16 * 4bytes */ - if ((count - start_offset) > 16) - cur_data_count = 16; - else - cur_data_count = count - start_offset; - - retry_cnt = 5; - while (retry_cnt) { - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_7_0); - reg = AUX_ADDR_15_8(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_15_8); - reg = AUX_ADDR_19_16(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_19_16); - - for (cur_data_idx = 0; cur_data_idx < cur_data_count; - cur_data_idx++) { - reg = data[start_offset + cur_data_idx]; - writel(reg, (unsigned int)&dp_regs->buf_data0 + - (4 * cur_data_idx)); - } - /* - * Set DisplayPort transaction and write - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_LENGTH(cur_data_count) | - AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); - if (ret != EXYNOS_DP_SUCCESS) { - if (retry_cnt == 0) { - printf("DP Aux Transaction failed\n"); - return ret; - } - retry_cnt--; - } else - break; - } - start_offset += cur_data_count; - } - - return ret; -} - -unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) -{ - unsigned int reg; - unsigned int start_offset; - unsigned int cur_data_count; - unsigned int cur_data_idx; - unsigned int retry_cnt; - unsigned int ret = 0; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - start_offset = 0; - while (start_offset < count) { - /* Buffer size of AUX CH is 16 * 4bytes */ - if ((count - start_offset) > 16) - cur_data_count = 16; - else - cur_data_count = count - start_offset; - - retry_cnt = 5; - while (retry_cnt) { - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_7_0); - reg = AUX_ADDR_15_8(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_15_8); - reg = AUX_ADDR_19_16(reg_addr + start_offset); - writel(reg, &dp_regs->aux_addr_19_16); - /* - * Set DisplayPort transaction and read - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_LENGTH(cur_data_count) | - AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); - if (ret != EXYNOS_DP_SUCCESS) { - if (retry_cnt == 0) { - printf("DP Aux Transaction failed\n"); - return ret; - } - retry_cnt--; - } else - break; - } - - for (cur_data_idx = 0; cur_data_idx < cur_data_count; - cur_data_idx++) { - reg = readl((unsigned int)&dp_regs->buf_data0 + - 4 * cur_data_idx); - data[start_offset + cur_data_idx] = (unsigned char)reg; - } - - start_offset += cur_data_count; - } - - return ret; -} - -int exynos_dp_select_i2c_device(unsigned int device_addr, - unsigned int reg_addr) -{ - unsigned int reg; - int retval; - - /* Set EDID device address */ - reg = device_addr; - writel(reg, &dp_regs->aux_addr_7_0); - writel(0x0, &dp_regs->aux_addr_15_8); - writel(0x0, &dp_regs->aux_addr_19_16); - - /* Set offset from base address of EDID device */ - writel(reg_addr, &dp_regs->buf_data0); - - /* - * Set I2C transaction and write address - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | - AUX_TX_COMM_WRITE; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); - if (retval != 0) - printf("%s: DP Aux Transaction fail!\n", __func__); - - return retval; -} - -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data) -{ - unsigned int reg; - int i; - int retval; - - for (i = 0; i < 10; i++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - /* Select EDID device */ - retval = exynos_dp_select_i2c_device(device_addr, reg_addr); - if (retval != 0) { - printf("DP Select EDID device fail. retry !\n"); - continue; - } - - /* - * Set I2C transaction and read data - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_TX_COMM_I2C_TRANSACTION | - AUX_TX_COMM_READ; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); - if (retval != EXYNOS_DP_SUCCESS) - printf("%s: DP Aux Transaction fail!\n", __func__); - } - - /* Read data */ - if (retval == 0) - *data = readl(&dp_regs->buf_data0); - - return retval; -} - -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, unsigned char edid[]) -{ - unsigned int reg; - unsigned int i, j; - unsigned int cur_data_idx; - unsigned int defer = 0; - int retval = 0; - - for (i = 0; i < count; i += 16) { /* use 16 burst */ - for (j = 0; j < 100; j++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, &dp_regs->buffer_data_ctl); - - /* Set normal AUX CH command */ - reg = readl(&dp_regs->aux_ch_ctl2); - reg &= ~ADDR_ONLY; - writel(reg, &dp_regs->aux_ch_ctl2); - - /* - * If Rx sends defer, Tx sends only reads - * request without sending addres - */ - if (!defer) - retval = - exynos_dp_select_i2c_device(device_addr, - reg_addr + i); - else - defer = 0; - - if (retval == EXYNOS_DP_SUCCESS) { - /* - * Set I2C transaction and write data - * If bit 3 is 1, DisplayPort transaction. - * If Bit 3 is 0, I2C transaction. - */ - reg = AUX_LENGTH(16) | - AUX_TX_COMM_I2C_TRANSACTION | - AUX_TX_COMM_READ; - writel(reg, &dp_regs->aux_ch_ctl1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); - if (retval == 0) - break; - else - printf("DP Aux Transaction fail!\n"); - } - /* Check if Rx sends defer */ - reg = readl(&dp_regs->aux_rx_comm); - if (reg == AUX_RX_COMM_AUX_DEFER || - reg == AUX_RX_COMM_I2C_DEFER) { - printf("DP Defer: %d\n", reg); - defer = 1; - } - } - - for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { - reg = readl((unsigned int)&dp_regs->buf_data0 - + 4 * cur_data_idx); - edid[i + cur_data_idx] = (unsigned char)reg; - } - } - - return retval; -} - -void exynos_dp_reset_macro(void) -{ - unsigned int reg; - - reg = readl(&dp_regs->phy_test); - reg |= MACRO_RST; - writel(reg, &dp_regs->phy_test); - - /* 10 us is the minimum Macro reset time. */ - mdelay(1); - - reg &= ~MACRO_RST; - writel(reg, &dp_regs->phy_test); -} - -void exynos_dp_set_link_bandwidth(unsigned char bwtype) -{ - unsigned int reg; - - reg = (unsigned int)bwtype; - - /* Set bandwidth to 2.7G or 1.62G */ - if ((bwtype == DP_LANE_BW_1_62) || (bwtype == DP_LANE_BW_2_70)) - writel(reg, &dp_regs->link_bw_set); -} - -unsigned char exynos_dp_get_link_bandwidth(void) -{ - unsigned char ret; - unsigned int reg; - - reg = readl(&dp_regs->link_bw_set); - ret = (unsigned char)reg; - - return ret; -} - -void exynos_dp_set_lane_count(unsigned char count) -{ - unsigned int reg; - - reg = (unsigned int)count; - - if ((count == DP_LANE_CNT_1) || (count == DP_LANE_CNT_2) || - (count == DP_LANE_CNT_4)) - writel(reg, &dp_regs->lane_count_set); -} - -unsigned int exynos_dp_get_lane_count(void) -{ - unsigned int reg; - - reg = readl(&dp_regs->lane_count_set); - - return reg; -} - -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) -{ - unsigned int reg_list[DP_LANE_CNT_4] = { - (unsigned int)&dp_regs->ln0_link_training_ctl, - (unsigned int)&dp_regs->ln1_link_training_ctl, - (unsigned int)&dp_regs->ln2_link_training_ctl, - (unsigned int)&dp_regs->ln3_link_training_ctl, - }; - - return readl(reg_list[lanecnt]); -} - -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt) -{ - unsigned int reg_list[DP_LANE_CNT_4] = { - (unsigned int)&dp_regs->ln0_link_training_ctl, - (unsigned int)&dp_regs->ln1_link_training_ctl, - (unsigned int)&dp_regs->ln2_link_training_ctl, - (unsigned int)&dp_regs->ln3_link_training_ctl, - }; - - writel(request_val, reg_list[lanecnt]); -} - -void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) -{ - unsigned char i; - unsigned int reg; - unsigned int reg_list[DP_LANE_CNT_4] = { - (unsigned int)&dp_regs->ln0_link_training_ctl, - (unsigned int)&dp_regs->ln1_link_training_ctl, - (unsigned int)&dp_regs->ln2_link_training_ctl, - (unsigned int)&dp_regs->ln3_link_training_ctl, - }; - unsigned int reg_shift[DP_LANE_CNT_4] = { - PRE_EMPHASIS_SET_0_SHIFT, - PRE_EMPHASIS_SET_1_SHIFT, - PRE_EMPHASIS_SET_2_SHIFT, - PRE_EMPHASIS_SET_3_SHIFT - }; - - for (i = 0; i < lanecnt; i++) { - reg = level << reg_shift[i]; - writel(reg, reg_list[i]); - } -} - -void exynos_dp_set_training_pattern(unsigned int pattern) -{ - unsigned int reg = 0; - - switch (pattern) { - case PRBS7: - reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; - break; - case D10_2: - reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; - break; - case TRAINING_PTN1: - reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; - break; - case TRAINING_PTN2: - reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; - break; - case DP_NONE: - reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_DISABLE | - SW_TRAINING_PATTERN_SET_NORMAL; - break; - default: - break; - } - - writel(reg, &dp_regs->training_ptn_set); -} - -void exynos_dp_enable_enhanced_mode(unsigned char enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->sys_ctl4); - reg &= ~ENHANCED; - - if (enable) - reg |= ENHANCED; - - writel(reg, &dp_regs->sys_ctl4); -} - -void exynos_dp_enable_scrambling(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->training_ptn_set); - reg &= ~(SCRAMBLING_DISABLE); - - if (!enable) - reg |= SCRAMBLING_DISABLE; - - writel(reg, &dp_regs->training_ptn_set); -} - -int exynos_dp_init_video(void) -{ - unsigned int reg; - - /* Clear VID_CLK_CHG[1] and VID_FORMAT_CHG[3] and VSYNC_DET[7] */ - reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; - writel(reg, &dp_regs->common_int_sta1); - - /* I_STRM__CLK detect : DE_CTL : Auto detect */ - reg &= ~DET_CTRL; - writel(reg, &dp_regs->sys_ctl1); - - return 0; -} - -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) -{ - unsigned int reg; - - /* Video Slave mode setting */ - reg = readl(&dp_regs->func_en1); - reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N); - reg |= MASTER_VID_FUNC_EN_N; - writel(reg, &dp_regs->func_en1); - - /* Configure Interlaced for slave mode video */ - reg = readl(&dp_regs->video_ctl10); - reg &= ~INTERACE_SCAN_CFG; - reg |= (video_info->interlaced << INTERACE_SCAN_CFG_SHIFT); - writel(reg, &dp_regs->video_ctl10); - - /* Configure V sync polarity for slave mode video */ - reg = readl(&dp_regs->video_ctl10); - reg &= ~VSYNC_POLARITY_CFG; - reg |= (video_info->v_sync_polarity << V_S_POLARITY_CFG_SHIFT); - writel(reg, &dp_regs->video_ctl10); - - /* Configure H sync polarity for slave mode video */ - reg = readl(&dp_regs->video_ctl10); - reg &= ~HSYNC_POLARITY_CFG; - reg |= (video_info->h_sync_polarity << H_S_POLARITY_CFG_SHIFT); - writel(reg, &dp_regs->video_ctl10); - - /* Set video mode to slave mode */ - reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; - writel(reg, &dp_regs->soc_general_ctl); -} - -void exynos_dp_set_video_color_format(struct edp_video_info *video_info) -{ - unsigned int reg; - - /* Configure the input color depth, color space, dynamic range */ - reg = (video_info->dynamic_range << IN_D_RANGE_SHIFT) | - (video_info->color_depth << IN_BPC_SHIFT) | - (video_info->color_space << IN_COLOR_F_SHIFT); - writel(reg, &dp_regs->video_ctl2); - - /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ - reg = readl(&dp_regs->video_ctl3); - reg &= ~IN_YC_COEFFI_MASK; - if (video_info->ycbcr_coeff) - reg |= IN_YC_COEFFI_ITU709; - else - reg |= IN_YC_COEFFI_ITU601; - writel(reg, &dp_regs->video_ctl3); -} - -int exynos_dp_config_video_bist(struct edp_device_info *edp_info) -{ - unsigned int reg; - unsigned int bist_type = 0; - struct edp_video_info video_info = edp_info->video_info; - - /* For master mode, you don't need to set the video format */ - if (video_info.master_mode == 0) { - writel(TOTAL_LINE_CFG_L(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_l); - writel(TOTAL_LINE_CFG_H(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_h); - writel(ACTIVE_LINE_CFG_L(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_l); - writel(ACTIVE_LINE_CFG_H(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_h); - writel(edp_info->disp_info.v_sync_width, - &dp_regs->vsw_cfg); - writel(edp_info->disp_info.v_back_porch, - &dp_regs->vbp_cfg); - writel(edp_info->disp_info.v_front_porch, - &dp_regs->vfp_cfg); - - writel(TOTAL_PIXEL_CFG_L(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_l); - writel(TOTAL_PIXEL_CFG_H(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_h); - writel(ACTIVE_PIXEL_CFG_L(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_l); - writel(ACTIVE_PIXEL_CFG_H(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_h); - writel(H_F_PORCH_CFG_L(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_l); - writel(H_F_PORCH_CFG_H(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_h); - writel(H_SYNC_PORCH_CFG_L(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_l); - writel(H_SYNC_PORCH_CFG_H(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_h); - writel(H_B_PORCH_CFG_L(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_l); - writel(H_B_PORCH_CFG_H(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_h); - - /* - * Set SLAVE_I_SCAN_CFG[2], VSYNC_P_CFG[1], - * HSYNC_P_CFG[0] properly - */ - reg = (video_info.interlaced << INTERACE_SCAN_CFG_SHIFT | - video_info.v_sync_polarity << V_S_POLARITY_CFG_SHIFT | - video_info.h_sync_polarity << H_S_POLARITY_CFG_SHIFT); - writel(reg, &dp_regs->video_ctl10); - } - - /* BIST color bar width set--set to each bar is 32 pixel width */ - switch (video_info.bist_pattern) { - case COLORBAR_32: - bist_type = BIST_WIDTH_BAR_32_PIXEL | - BIST_TYPE_COLOR_BAR; - break; - case COLORBAR_64: - bist_type = BIST_WIDTH_BAR_64_PIXEL | - BIST_TYPE_COLOR_BAR; - break; - case WHITE_GRAY_BALCKBAR_32: - bist_type = BIST_WIDTH_BAR_32_PIXEL | - BIST_TYPE_WHITE_GRAY_BLACK_BAR; - break; - case WHITE_GRAY_BALCKBAR_64: - bist_type = BIST_WIDTH_BAR_64_PIXEL | - BIST_TYPE_WHITE_GRAY_BLACK_BAR; - break; - case MOBILE_WHITEBAR_32: - bist_type = BIST_WIDTH_BAR_32_PIXEL | - BIST_TYPE_MOBILE_WHITE_BAR; - break; - case MOBILE_WHITEBAR_64: - bist_type = BIST_WIDTH_BAR_64_PIXEL | - BIST_TYPE_MOBILE_WHITE_BAR; - break; - default: - return -1; - } - - reg = bist_type; - writel(reg, &dp_regs->video_ctl4); - - return 0; -} - -unsigned int exynos_dp_is_slave_video_stream_clock_on(void) -{ - unsigned int reg; - - /* Update Video stream clk detect status */ - reg = readl(&dp_regs->sys_ctl1); - writel(reg, &dp_regs->sys_ctl1); - - reg = readl(&dp_regs->sys_ctl1); - - if (!(reg & DET_STA)) { - debug("DP Input stream clock not detected.\n"); - return -EIO; - } - - return EXYNOS_DP_SUCCESS; -} - -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value) -{ - unsigned int reg; - - if (type == REGISTER_M) { - reg = readl(&dp_regs->sys_ctl4); - reg |= FIX_M_VID; - writel(reg, &dp_regs->sys_ctl4); - reg = M_VID0_CFG(m_value); - writel(reg, &dp_regs->m_vid0); - reg = M_VID1_CFG(m_value); - writel(reg, &dp_regs->m_vid1); - reg = M_VID2_CFG(m_value); - writel(reg, &dp_regs->m_vid2); - - reg = N_VID0_CFG(n_value); - writel(reg, &dp_regs->n_vid0); - reg = N_VID1_CFG(n_value); - writel(reg, &dp_regs->n_vid1); - reg = N_VID2_CFG(n_value); - writel(reg, &dp_regs->n_vid2); - } else { - reg = readl(&dp_regs->sys_ctl4); - reg &= ~FIX_M_VID; - writel(reg, &dp_regs->sys_ctl4); - } -} - -void exynos_dp_set_video_timing_mode(unsigned int type) -{ - unsigned int reg; - - reg = readl(&dp_regs->video_ctl10); - reg &= ~FORMAT_SEL; - - if (type != VIDEO_TIMING_FROM_CAPTURE) - reg |= FORMAT_SEL; - - writel(reg, &dp_regs->video_ctl10); -} - -void exynos_dp_enable_video_master(unsigned int enable) -{ - unsigned int reg; - - reg = readl(&dp_regs->soc_general_ctl); - if (enable) { - reg &= ~VIDEO_MODE_MASK; - reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; - } else { - reg &= ~VIDEO_MODE_MASK; - reg |= VIDEO_MODE_SLAVE_MODE; - } - - writel(reg, &dp_regs->soc_general_ctl); -} - -void exynos_dp_start_video(void) -{ - unsigned int reg; - - /* Enable Video input and disable Mute */ - reg = readl(&dp_regs->video_ctl1); - reg |= VIDEO_EN; - writel(reg, &dp_regs->video_ctl1); -} - -unsigned int exynos_dp_is_video_stream_on(void) -{ - unsigned int reg; - - /* Update STRM_VALID */ - reg = readl(&dp_regs->sys_ctl3); - writel(reg, &dp_regs->sys_ctl3); - - reg = readl(&dp_regs->sys_ctl3); - if (!(reg & STRM_VALID)) - return -EIO; - - return EXYNOS_DP_SUCCESS; -} diff --git a/drivers/video/exynos_dp_lowlevel.h b/drivers/video/exynos_dp_lowlevel.h deleted file mode 100644 index 8651681..0000000 --- a/drivers/video/exynos_dp_lowlevel.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_EDP_LOWLEVEL_H -#define _EXYNOS_EDP_LOWLEVEL_H - -void exynos_dp_enable_video_bist(unsigned int enable); -void exynos_dp_enable_video_mute(unsigned int enable); -void exynos_dp_reset(void); -void exynos_dp_enable_sw_func(unsigned int enable); -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable); -unsigned int exynos_dp_get_pll_lock_status(void); -int exynos_dp_init_analog_func(void); -void exynos_dp_init_hpd(void); -void exynos_dp_init_aux(void); -void exynos_dp_config_interrupt(void); -unsigned int exynos_dp_get_plug_in_status(void); -unsigned int exynos_dp_detect_hpd(void); -unsigned int exynos_dp_start_aux_transaction(void); -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data); -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data); -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -unsigned int exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_select_i2c_device( unsigned int device_addr, - unsigned int reg_addr); -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int *data); -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, - unsigned char edid[]); -void exynos_dp_reset_macro(void); -void exynos_dp_set_link_bandwidth(unsigned char bwtype); -unsigned char exynos_dp_get_link_bandwidth(void); -void exynos_dp_set_lane_count(unsigned char count); -unsigned int exynos_dp_get_lane_count(void); -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt); -void exynos_dp_set_lane_pre_emphasis(unsigned int level, - unsigned char lanecnt); -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt); -void exynos_dp_set_training_pattern(unsigned int pattern); -void exynos_dp_enable_enhanced_mode(unsigned char enable); -void exynos_dp_enable_scrambling(unsigned int enable); -int exynos_dp_init_video(void); -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info); -void exynos_dp_set_video_color_format(struct edp_video_info *video_info); -int exynos_dp_config_video_bist(struct edp_device_info *edp_info); -unsigned int exynos_dp_is_slave_video_stream_clock_on(void); -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value); -void exynos_dp_set_video_timing_mode(unsigned int type); -void exynos_dp_enable_video_master(unsigned int enable); -void exynos_dp_start_video(void); -unsigned int exynos_dp_is_video_stream_on(void); -void exynos_dp_set_base_addr(void); - -#endif /* _EXYNOS_DP_LOWLEVEL_H */ diff --git a/drivers/video/exynos_fb.c b/drivers/video/exynos_fb.c deleted file mode 100644 index 69edc3a..0000000 --- a/drivers/video/exynos_fb.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "exynos_fb.h" - -DECLARE_GLOBAL_DATA_PTR; - -static unsigned int panel_width, panel_height; - -#if CONFIG_IS_ENABLED(OF_CONTROL) -vidinfo_t panel_info = { - /* - * Insert a value here so that we don't end up in the BSS - * Reference: drivers/video/tegra.c - */ - .vl_col = -1, -}; -#endif - -ushort *configuration_get_cmap(void) -{ -#if defined(CONFIG_LCD_LOGO) - return bmp_logo_palette; -#else - return NULL; -#endif -} - -static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) -{ - unsigned long palette_size; - unsigned int fb_size; - - fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); - - palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; - - exynos_fimd_lcd_init_mem((unsigned long)lcdbase, - (unsigned long)fb_size, palette_size); -} - -static void exynos_lcd_init(vidinfo_t *vid) -{ - exynos_fimd_lcd_init(vid); - - /* Enable flushing after LCD writes if requested */ - lcd_set_flush_dcache(1); -} - -__weak void exynos_cfg_lcd_gpio(void) -{ -} - -__weak void exynos_backlight_on(unsigned int onoff) -{ -} - -__weak void exynos_reset_lcd(void) -{ -} - -__weak void exynos_lcd_power_on(void) -{ -} - -__weak void exynos_cfg_ldo(void) -{ -} - -__weak void exynos_enable_ldo(unsigned int onoff) -{ -} - -__weak void exynos_backlight_reset(void) -{ -} - -__weak int exynos_lcd_misc_init(vidinfo_t *vid) -{ - return 0; -} - -static void lcd_panel_on(vidinfo_t *vid) -{ - struct gpio_desc pwm_out_gpio; - struct gpio_desc bl_en_gpio; - unsigned int node; - - udelay(vid->init_delay); - - exynos_backlight_reset(); - - exynos_cfg_lcd_gpio(); - - exynos_lcd_power_on(); - - udelay(vid->power_on_delay); - - if (vid->dp_enabled) - exynos_init_dp(); - - exynos_reset_lcd(); - - udelay(vid->reset_delay); - - exynos_backlight_on(1); - -#if CONFIG_IS_ENABLED(OF_CONTROL) - node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("FIMD: Can't get device node for FIMD\n"); - return; - } - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,pwm-out-gpio", - 0, &pwm_out_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,bl-en-gpio", 0, - &bl_en_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - -#endif - exynos_cfg_ldo(); - - exynos_enable_ldo(1); - - if (vid->mipi_enabled) - exynos_mipi_dsi_init(); -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int exynos_lcd_early_init(const void *blob) -{ - unsigned int node; - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("exynos_fb: Can't get device node for fimd\n"); - return -ENODEV; - } - - panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); - if (panel_info.vl_col == 0) { - debug("Can't get XRES\n"); - return -ENXIO; - } - - panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); - if (panel_info.vl_row == 0) { - debug("Can't get YRES\n"); - return -ENXIO; - } - - panel_info.vl_width = fdtdec_get_int(blob, node, - "samsung,vl-width", 0); - - panel_info.vl_height = fdtdec_get_int(blob, node, - "samsung,vl-height", 0); - - panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); - if (panel_info.vl_freq == 0) { - debug("Can't get refresh rate\n"); - return -ENXIO; - } - - if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) - panel_info.vl_clkp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) - panel_info.vl_oep = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) - panel_info.vl_hsp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) - panel_info.vl_vsp = CONFIG_SYS_LOW; - - if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) - panel_info.vl_dp = CONFIG_SYS_LOW; - - panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); - if (panel_info.vl_bpix == 0) { - debug("Can't get bits per pixel\n"); - return -ENXIO; - } - - panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); - if (panel_info.vl_hspw == 0) { - debug("Can't get hsync width\n"); - return -ENXIO; - } - - panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); - if (panel_info.vl_hfpd == 0) { - debug("Can't get right margin\n"); - return -ENXIO; - } - - panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, - "samsung,vl-hbpd", 0); - if (panel_info.vl_hbpd == 0) { - debug("Can't get left margin\n"); - return -ENXIO; - } - - panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, - "samsung,vl-vspw", 0); - if (panel_info.vl_vspw == 0) { - debug("Can't get vsync width\n"); - return -ENXIO; - } - - panel_info.vl_vfpd = fdtdec_get_int(blob, node, - "samsung,vl-vfpd", 0); - if (panel_info.vl_vfpd == 0) { - debug("Can't get lower margin\n"); - return -ENXIO; - } - - panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); - if (panel_info.vl_vbpd == 0) { - debug("Can't get upper margin\n"); - return -ENXIO; - } - - panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, - "samsung,vl-cmd-allow-len", 0); - - panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); - panel_info.init_delay = fdtdec_get_int(blob, node, - "samsung,init-delay", 0); - panel_info.power_on_delay = fdtdec_get_int(blob, node, - "samsung,power-on-delay", 0); - panel_info.reset_delay = fdtdec_get_int(blob, node, - "samsung,reset-delay", 0); - panel_info.interface_mode = fdtdec_get_int(blob, node, - "samsung,interface-mode", 0); - panel_info.mipi_enabled = fdtdec_get_int(blob, node, - "samsung,mipi-enabled", 0); - panel_info.dp_enabled = fdtdec_get_int(blob, node, - "samsung,dp-enabled", 0); - panel_info.cs_setup = fdtdec_get_int(blob, node, - "samsung,cs-setup", 0); - panel_info.wr_setup = fdtdec_get_int(blob, node, - "samsung,wr-setup", 0); - panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); - panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); - - panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); - if (panel_info.logo_on) { - panel_info.logo_width = fdtdec_get_int(blob, node, - "samsung,logo-width", 0); - panel_info.logo_height = fdtdec_get_int(blob, node, - "samsung,logo-height", 0); - panel_info.logo_addr = fdtdec_get_int(blob, node, - "samsung,logo-addr", 0); - } - - panel_info.rgb_mode = fdtdec_get_int(blob, node, - "samsung,rgb-mode", 0); - panel_info.pclk_name = fdtdec_get_int(blob, node, - "samsung,pclk-name", 0); - panel_info.sclk_div = fdtdec_get_int(blob, node, - "samsung,sclk-div", 0); - panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, - "samsung,dual-lcd-enabled", 0); - - return 0; -} -#endif - -void lcd_ctrl_init(void *lcdbase) -{ - set_system_display_ctrl(); - set_lcd_clk(); - -#if CONFIG_IS_ENABLED(OF_CONTROL) -#ifdef CONFIG_EXYNOS_MIPI_DSIM - exynos_init_dsim_platform_data(&panel_info); -#endif - exynos_lcd_misc_init(&panel_info); -#else - /* initialize parameters which is specific to panel. */ - init_panel_info(&panel_info); -#endif - - panel_width = panel_info.vl_width; - panel_height = panel_info.vl_height; - - exynos_lcd_init_mem(lcdbase, &panel_info); - - exynos_lcd_init(&panel_info); -} - -void lcd_enable(void) -{ - if (panel_info.logo_on) { - memset((void *) gd->fb_base, 0, panel_width * panel_height * - (NBITS(panel_info.vl_bpix) >> 3)); - } - - lcd_panel_on(&panel_info); -} - -/* dummy function */ -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) -{ - return; -} diff --git a/drivers/video/exynos_fb.h b/drivers/video/exynos_fb.h deleted file mode 100644 index 2c2f94b..0000000 --- a/drivers/video/exynos_fb.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_FB_H_ -#define _EXYNOS_FB_H_ - -#include - -#define MAX_CLOCK (86 * 1000000) - -enum exynos_cpu_auto_cmd_rate { - DISABLE_AUTO_FRM, - PER_TWO_FRM, - PER_FOUR_FRM, - PER_SIX_FRM, - PER_EIGHT_FRM, - PER_TEN_FRM, - PER_TWELVE_FRM, - PER_FOURTEEN_FRM, - PER_SIXTEEN_FRM, - PER_EIGHTEEN_FRM, - PER_TWENTY_FRM, - PER_TWENTY_TWO_FRM, - PER_TWENTY_FOUR_FRM, - PER_TWENTY_SIX_FRM, - PER_TWENTY_EIGHT_FRM, - PER_THIRTY_FRM, -}; - -void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, - unsigned long palette_size); -void exynos_fimd_lcd_init(vidinfo_t *vid); -unsigned long exynos_fimd_calc_fbsize(void); - -#endif diff --git a/drivers/video/exynos_fimd.c b/drivers/video/exynos_fimd.c deleted file mode 100644 index ac001a8..0000000 --- a/drivers/video/exynos_fimd.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "exynos_fb.h" - -DECLARE_GLOBAL_DATA_PTR; - -static unsigned long *lcd_base_addr; -static vidinfo_t *pvid; -static struct exynos_fb *fimd_ctrl; - -void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, - u_long palette_size) -{ - lcd_base_addr = (unsigned long *)screen_base; -} - -static void exynos_fimd_set_dualrgb(unsigned int enabled) -{ - unsigned int cfg = 0; - - if (enabled) { - cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | - EXYNOS_DUALRGB_VDEN_EN_ENABLE; - - /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ - cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | - EXYNOS_DUALRGB_MAIN_CNT(0); - } - - writel(cfg, &fimd_ctrl->dualrgb); -} - -static void exynos_fimd_set_dp_clkcon(unsigned int enabled) -{ - unsigned int cfg = 0; - - if (enabled) - cfg = EXYNOS_DP_CLK_ENABLE; - - writel(cfg, &fimd_ctrl->dp_mie_clkcon); -} - -static void exynos_fimd_set_par(unsigned int win_id) -{ - unsigned int cfg = 0; - - /* set window control */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | - EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | - EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | - EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); - - /* DATAPATH is DMA */ - cfg |= EXYNOS_WINCON_DATAPATH_DMA; - - cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; - - /* dma burst is 16 */ - cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; - - switch (pvid->vl_bpix) { - case 4: - cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; - break; - default: - cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; - break; - } - - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - /* set window position to x=0, y=0*/ - cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + - EXYNOS_VIDOSD(win_id)); - - cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | - EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | - EXYNOS_VIDOSD_RIGHT_X_E(1) | - EXYNOS_VIDOSD_BOTTOM_Y_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + - EXYNOS_VIDOSD(win_id)); - - /* set window size for window0*/ - cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + - EXYNOS_VIDOSD(win_id)); -} - -static void exynos_fimd_set_buffer_address(unsigned int win_id) -{ - unsigned long start_addr, end_addr; - - start_addr = (unsigned long)lcd_base_addr; - end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * - pvid->vl_row); - - writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + - EXYNOS_BUFFER_OFFSET(win_id)); - writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + - EXYNOS_BUFFER_OFFSET(win_id)); -} - -static void exynos_fimd_set_clock(vidinfo_t *pvid) -{ - unsigned int cfg = 0, div = 0, remainder, remainder_div; - unsigned long pixel_clock; - unsigned long long src_clock; - - if (pvid->dual_lcd_enabled) { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col / 2) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { - pixel_clock = pvid->vl_freq * - pvid->vl_width * pvid->vl_height * - (pvid->cs_setup + pvid->wr_setup + - pvid->wr_act + pvid->wr_hold + 1); - } else { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | - EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | - EXYNOS_VIDCON0_CLKDIR_MASK); - cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | - EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); - - src_clock = (unsigned long long) get_lcd_clk(); - - /* get quotient and remainder. */ - remainder = do_div(src_clock, pixel_clock); - div = src_clock; - - remainder *= 10; - remainder_div = remainder / pixel_clock; - - /* round about one places of decimals. */ - if (remainder_div >= 5) - div++; - - /* in case of dual lcd mode. */ - if (pvid->dual_lcd_enabled) - div--; - - cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_set_trigger(void) -{ - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->trigcon); - - cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); - - writel(cfg, &fimd_ctrl->trigcon); -} - -int exynos_is_i80_frame_done(void) -{ - unsigned int cfg = 0; - int status; - - cfg = readl(&fimd_ctrl->trigcon); - - /* frame done func is valid only when TRIMODE[0] is set to 1. */ - status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == - EXYNOS_I80STATUS_TRIG_DONE; - - return status; -} - -static void exynos_fimd_lcd_on(void) -{ - unsigned int cfg = 0; - - /* display on */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -static void exynos_fimd_window_on(unsigned int win_id) -{ - unsigned int cfg = 0; - - /* enable window */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg |= EXYNOS_WINCON_ENWIN_ENABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -void exynos_fimd_lcd_off(void) -{ - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_fimd_window_off(unsigned int win_id) -{ - unsigned int cfg = 0; - - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg &= EXYNOS_WINCON_ENWIN_DISABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -/* -* The reset value for FIMD SYSMMU register MMU_CTRL is 3 -* on Exynos5420 and newer versions. -* This means FIMD SYSMMU is on by default on Exynos5420 -* and newer versions. -* Since in u-boot we don't use SYSMMU, we should disable -* those FIMD SYSMMU. -* Note that there are 2 SYSMMU for FIMD: m0 and m1. -* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. -* We disable both of them here. -*/ -void exynos_fimd_disable_sysmmu(void) -{ - u32 *sysmmufimd; - unsigned int node; - int node_list[2]; - int count; - int i; - - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", - COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); - for (i = 0; i < count; i++) { - node = node_list[i]; - if (node <= 0) { - debug("Can't get device node for fimd sysmmu\n"); - return; - } - - sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (!sysmmufimd) { - debug("Can't get base address for sysmmu fimdm0"); - return; - } - - writel(0x0, sysmmufimd); - } -} -#endif - -void exynos_fimd_lcd_init(vidinfo_t *vid) -{ - unsigned int cfg = 0, rgb_mode; - unsigned int offset; -#if CONFIG_IS_ENABLED(OF_CONTROL) - unsigned int node; - - node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) - debug("exynos_fb: Can't get device node for fimd\n"); - - fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if (fimd_ctrl == NULL) - debug("Can't get the FIMD base address\n"); - - if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) - exynos_fimd_disable_sysmmu(); - -#else - fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); -#endif - - offset = exynos_fimd_get_base_offset(); - - /* store panel info to global variable */ - pvid = vid; - - rgb_mode = vid->rgb_mode; - - if (vid->interface_mode == FIMD_RGB_INTERFACE) { - cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; - writel(cfg, &fimd_ctrl->vidcon0); - - cfg = readl(&fimd_ctrl->vidcon2); - cfg &= ~(EXYNOS_VIDCON2_WB_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); - cfg |= EXYNOS_VIDCON2_WB_DISABLE; - writel(cfg, &fimd_ctrl->vidcon2); - - /* set polarity */ - cfg = 0; - if (!pvid->vl_clkp) - cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; - if (!pvid->vl_hsp) - cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; - if (!pvid->vl_vsp) - cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; - if (!pvid->vl_dp) - cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; - - writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); - - /* set timing */ - cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); - cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); - cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); - - cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); - cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); - cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); - - /* set lcd size */ - cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | - EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); - } - - /* set display mode */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; - cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); - writel(cfg, &fimd_ctrl->vidcon0); - - /* set par */ - exynos_fimd_set_par(pvid->win_id); - - /* set memory address */ - exynos_fimd_set_buffer_address(pvid->win_id); - - /* set buffer size */ - cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_OFFSIZE(0) | - EXYNOS_VIDADDR_OFFSIZE_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + - EXYNOS_BUFFER_SIZE(pvid->win_id)); - - /* set clock */ - exynos_fimd_set_clock(pvid); - - /* set rgb mode to dual lcd. */ - exynos_fimd_set_dualrgb(pvid->dual_lcd_enabled); - - /* display on */ - exynos_fimd_lcd_on(); - - /* window on */ - exynos_fimd_window_on(pvid->win_id); - - exynos_fimd_set_dp_clkcon(pvid->dp_enabled); -} - -unsigned long exynos_fimd_calc_fbsize(void) -{ - return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); -} diff --git a/drivers/video/exynos_mipi_dsi.c b/drivers/video/exynos_mipi_dsi.c deleted file mode 100644 index b597acc..0000000 --- a/drivers/video/exynos_mipi_dsi.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "exynos_mipi_dsi_lowlevel.h" -#include "exynos_mipi_dsi_common.h" - -#define master_to_driver(a) (a->dsim_lcd_drv) -#define master_to_device(a) (a->dsim_lcd_dev) - -DECLARE_GLOBAL_DATA_PTR; - -static struct exynos_platform_mipi_dsim *dsim_pd; -#if CONFIG_IS_ENABLED(OF_CONTROL) -static struct mipi_dsim_config dsim_config_dt; -static struct exynos_platform_mipi_dsim dsim_platform_data_dt; -static struct mipi_dsim_lcd_device mipi_lcd_device_dt; -#endif - -struct mipi_dsim_ddi { - int bus_id; - struct list_head list; - struct mipi_dsim_lcd_device *dsim_lcd_dev; - struct mipi_dsim_lcd_driver *dsim_lcd_drv; -}; - -static LIST_HEAD(dsim_ddi_list); -static LIST_HEAD(dsim_lcd_dev_list); - -int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev) -{ - struct mipi_dsim_ddi *dsim_ddi; - - if (!lcd_dev) { - debug("mipi_dsim_lcd_device is NULL.\n"); - return -EFAULT; - } - - if (!lcd_dev->name) { - debug("dsim_lcd_device name is NULL.\n"); - return -EFAULT; - } - - dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL); - if (!dsim_ddi) { - debug("failed to allocate dsim_ddi object.\n"); - return -EFAULT; - } - - dsim_ddi->dsim_lcd_dev = lcd_dev; - - list_add_tail(&dsim_ddi->list, &dsim_ddi_list); - - return 0; -} - -struct mipi_dsim_ddi - *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv) -{ - struct mipi_dsim_ddi *dsim_ddi; - struct mipi_dsim_lcd_device *lcd_dev; - - list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) { - lcd_dev = dsim_ddi->dsim_lcd_dev; - if (!lcd_dev) - continue; - - if (lcd_drv->id >= 0) { - if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 && - lcd_drv->id == lcd_dev->id) { - /** - * bus_id would be used to identify - * connected bus. - */ - dsim_ddi->bus_id = lcd_dev->bus_id; - - return dsim_ddi; - } - } else { - if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) { - /** - * bus_id would be used to identify - * connected bus. - */ - dsim_ddi->bus_id = lcd_dev->bus_id; - - return dsim_ddi; - } - } - - kfree(dsim_ddi); - list_del(&dsim_ddi_list); - } - - return NULL; -} - -int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv) -{ - struct mipi_dsim_ddi *dsim_ddi; - - if (!lcd_drv) { - debug("mipi_dsim_lcd_driver is NULL.\n"); - return -EFAULT; - } - - if (!lcd_drv->name) { - debug("dsim_lcd_driver name is NULL.\n"); - return -EFAULT; - } - - dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv); - if (!dsim_ddi) { - debug("mipi_dsim_ddi object not found.\n"); - return -EFAULT; - } - - dsim_ddi->dsim_lcd_drv = lcd_drv; - - debug("registered panel driver(%s) to mipi-dsi driver.\n", - lcd_drv->name); - - return 0; - -} - -struct mipi_dsim_ddi - *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim, - const char *name) -{ - struct mipi_dsim_ddi *dsim_ddi; - struct mipi_dsim_lcd_driver *lcd_drv; - struct mipi_dsim_lcd_device *lcd_dev; - - list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) { - lcd_drv = dsim_ddi->dsim_lcd_drv; - lcd_dev = dsim_ddi->dsim_lcd_dev; - if (!lcd_drv || !lcd_dev) - continue; - - debug("lcd_drv->id = %d, lcd_dev->id = %d\n", - lcd_drv->id, lcd_dev->id); - - if ((strcmp(lcd_drv->name, name) == 0)) { - lcd_dev->master = dsim; - - dsim->dsim_lcd_dev = lcd_dev; - dsim->dsim_lcd_drv = lcd_drv; - - return dsim_ddi; - } - } - - return NULL; -} - -/* define MIPI-DSI Master operations. */ -static struct mipi_dsim_master_ops master_ops = { - .cmd_write = exynos_mipi_dsi_wr_data, - .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status, - .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, -}; - -int exynos_mipi_dsi_init(void) -{ - struct mipi_dsim_device *dsim; - struct mipi_dsim_config *dsim_config; - struct mipi_dsim_ddi *dsim_ddi; - - dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL); - if (!dsim) { - debug("failed to allocate dsim object.\n"); - return -EFAULT; - } - - /* get mipi_dsim_config. */ - dsim_config = dsim_pd->dsim_config; - if (dsim_config == NULL) { - debug("failed to get dsim config data.\n"); - return -EFAULT; - } - - dsim->pd = dsim_pd; - dsim->dsim_config = dsim_config; - dsim->master_ops = &master_ops; - - /* bind lcd ddi matched with panel name. */ - dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name); - if (!dsim_ddi) { - debug("mipi_dsim_ddi object not found.\n"); - return -ENOSYS; - } - if (dsim_pd->lcd_power) - dsim_pd->lcd_power(); - - if (dsim_pd->mipi_power) - dsim_pd->mipi_power(); - - /* phy_enable(unsigned int dev_index, unsigned int enable) */ - if (dsim_pd->phy_enable) - dsim_pd->phy_enable(0, 1); - - set_mipi_clk(); - - exynos_mipi_dsi_init_dsim(dsim); - exynos_mipi_dsi_init_link(dsim); - exynos_mipi_dsi_set_hs_enable(dsim); - - /* set display timing. */ - exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config); - - /* initialize mipi-dsi client(lcd panel). */ - if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->mipi_panel_init) { - dsim_ddi->dsim_lcd_drv->mipi_panel_init(dsim); - dsim_ddi->dsim_lcd_drv->mipi_display_on(dsim); - } - - debug("mipi-dsi driver(%s mode) has been probed.\n", - (dsim_config->e_interface == DSIM_COMMAND) ? - "CPU" : "RGB"); - - return 0; -} - -void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) -{ - if (pd == NULL) { - debug("pd is NULL\n"); - return; - } - - dsim_pd = pd; -} - -#if CONFIG_IS_ENABLED(OF_CONTROL) -int exynos_dsim_config_parse_dt(const void *blob) -{ - int node; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_MIPI_DSI); - if (node <= 0) { - printf("exynos_mipi_dsi: Can't get device node for mipi dsi\n"); - return -ENODEV; - } - - dsim_config_dt.e_interface = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-interface", 0); - - dsim_config_dt.e_virtual_ch = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-virtual-ch", 0); - - dsim_config_dt.e_pixel_format = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-pixel-format", 0); - - dsim_config_dt.e_burst_mode = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-burst-mode", 0); - - dsim_config_dt.e_no_data_lane = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-no-data-lane", 0); - - dsim_config_dt.e_byte_clk = fdtdec_get_int(blob, node, - "samsung,dsim-config-e-byte-clk", 0); - - dsim_config_dt.hfp = fdtdec_get_int(blob, node, - "samsung,dsim-config-hfp", 0); - - dsim_config_dt.p = fdtdec_get_int(blob, node, - "samsung,dsim-config-p", 0); - dsim_config_dt.m = fdtdec_get_int(blob, node, - "samsung,dsim-config-m", 0); - dsim_config_dt.s = fdtdec_get_int(blob, node, - "samsung,dsim-config-s", 0); - - dsim_config_dt.pll_stable_time = fdtdec_get_int(blob, node, - "samsung,dsim-config-pll-stable-time", 0); - - dsim_config_dt.esc_clk = fdtdec_get_int(blob, node, - "samsung,dsim-config-esc-clk", 0); - - dsim_config_dt.stop_holding_cnt = fdtdec_get_int(blob, node, - "samsung,dsim-config-stop-holding-cnt", 0); - - dsim_config_dt.bta_timeout = fdtdec_get_int(blob, node, - "samsung,dsim-config-bta-timeout", 0); - - dsim_config_dt.rx_timeout = fdtdec_get_int(blob, node, - "samsung,dsim-config-rx-timeout", 0); - - mipi_lcd_device_dt.name = fdtdec_get_config_string(blob, - "samsung,dsim-device-name"); - - mipi_lcd_device_dt.id = fdtdec_get_int(blob, node, - "samsung,dsim-device-id", 0); - - mipi_lcd_device_dt.bus_id = fdtdec_get_int(blob, node, - "samsung,dsim-device-bus_id", 0); - - mipi_lcd_device_dt.reverse_panel = fdtdec_get_int(blob, node, - "samsung,dsim-device-reverse-panel", 0); - - return 0; -} - -void exynos_init_dsim_platform_data(vidinfo_t *vid) -{ - if (exynos_dsim_config_parse_dt(gd->fdt_blob)) - debug("Can't get proper dsim config.\n"); - - strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name); - dsim_platform_data_dt.dsim_config = &dsim_config_dt; - dsim_platform_data_dt.mipi_power = mipi_power; - dsim_platform_data_dt.phy_enable = set_mipi_phy_ctrl; - dsim_platform_data_dt.lcd_panel_info = (void *)vid; - - mipi_lcd_device_dt.platform_data = (void *)&dsim_platform_data_dt; - exynos_mipi_dsi_register_lcd_device(&mipi_lcd_device_dt); - - dsim_pd = &dsim_platform_data_dt; -} -#endif diff --git a/drivers/video/exynos_mipi_dsi_common.c b/drivers/video/exynos_mipi_dsi_common.c deleted file mode 100644 index 925d515..0000000 --- a/drivers/video/exynos_mipi_dsi_common.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#include "exynos_mipi_dsi_lowlevel.h" - -#define MHZ (1000 * 1000) -#define FIN_HZ (24 * MHZ) - -#define DFIN_PLL_MIN_HZ (6 * MHZ) -#define DFIN_PLL_MAX_HZ (12 * MHZ) - -#define DFVCO_MIN_HZ (500 * MHZ) -#define DFVCO_MAX_HZ (1000 * MHZ) - -#define TRY_GET_FIFO_TIMEOUT (5000 * 2) - -/* MIPI-DSIM status types. */ -enum { - DSIM_STATE_INIT, /* should be initialized. */ - DSIM_STATE_STOP, /* CPU and LCDC are LP mode. */ - DSIM_STATE_HSCLKEN, /* HS clock was enabled. */ - DSIM_STATE_ULPS -}; - -/* define DSI lane types. */ -enum { - DSIM_LANE_CLOCK = (1 << 0), - DSIM_LANE_DATA0 = (1 << 1), - DSIM_LANE_DATA1 = (1 << 2), - DSIM_LANE_DATA2 = (1 << 3), - DSIM_LANE_DATA3 = (1 << 4) -}; - -static unsigned int dpll_table[15] = { - 100, 120, 170, 220, 270, - 320, 390, 450, 510, 560, - 640, 690, 770, 870, 950 -}; - -static void exynos_mipi_dsi_long_data_wr(struct mipi_dsim_device *dsim, - const unsigned char *data0, unsigned int data1) -{ - unsigned int data_cnt = 0, payload = 0; - - /* in case that data count is more then 4 */ - for (data_cnt = 0; data_cnt < data1; data_cnt += 4) { - /* - * after sending 4bytes per one time, - * send remainder data less then 4. - */ - if ((data1 - data_cnt) < 4) { - if ((data1 - data_cnt) == 3) { - payload = data0[data_cnt] | - data0[data_cnt + 1] << 8 | - data0[data_cnt + 2] << 16; - debug("count = 3 payload = %x, %x %x %x\n", - payload, data0[data_cnt], - data0[data_cnt + 1], - data0[data_cnt + 2]); - } else if ((data1 - data_cnt) == 2) { - payload = data0[data_cnt] | - data0[data_cnt + 1] << 8; - debug("count = 2 payload = %x, %x %x\n", payload, - data0[data_cnt], data0[data_cnt + 1]); - } else if ((data1 - data_cnt) == 1) { - payload = data0[data_cnt]; - } - } else { - /* send 4bytes per one time. */ - payload = data0[data_cnt] | - data0[data_cnt + 1] << 8 | - data0[data_cnt + 2] << 16 | - data0[data_cnt + 3] << 24; - - debug("count = 4 payload = %x, %x %x %x %x\n", - payload, *(u8 *)(data0 + data_cnt), - data0[data_cnt + 1], - data0[data_cnt + 2], - data0[data_cnt + 3]); - } - exynos_mipi_dsi_wr_tx_data(dsim, payload); - } -} - -int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, - const unsigned char *data0, unsigned int data1) -{ - unsigned int timeout = TRY_GET_FIFO_TIMEOUT; - unsigned long delay_val, delay; - unsigned int check_rx_ack = 0; - - if (dsim->state == DSIM_STATE_ULPS) { - debug("state is ULPS.\n"); - - return -EINVAL; - } - - delay_val = MHZ / dsim->dsim_config->esc_clk; - delay = 10 * delay_val; - - mdelay(delay); - - /* only if transfer mode is LPDT, wait SFR becomes empty. */ - if (dsim->state == DSIM_STATE_STOP) { - while (!(exynos_mipi_dsi_get_fifo_state(dsim) & - SFR_HEADER_EMPTY)) { - if ((timeout--) > 0) - mdelay(1); - else { - debug("SRF header fifo is not empty.\n"); - return -EINVAL; - } - } - } - - switch (data_id) { - /* short packet types of packet types for command. */ - case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: - case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: - case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: - case MIPI_DSI_DCS_SHORT_WRITE: - case MIPI_DSI_DCS_SHORT_WRITE_PARAM: - case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: - debug("data0 = %x data1 = %x\n", - data0[0], data0[1]); - exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); - if (check_rx_ack) { - /* process response func should be implemented */ - return 0; - } else { - return -EINVAL; - } - - /* general command */ - case MIPI_DSI_COLOR_MODE_OFF: - case MIPI_DSI_COLOR_MODE_ON: - case MIPI_DSI_SHUTDOWN_PERIPHERAL: - case MIPI_DSI_TURN_ON_PERIPHERAL: - exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); - if (check_rx_ack) { - /* process response func should be implemented. */ - return 0; - } else { - return -EINVAL; - } - - /* packet types for video data */ - case MIPI_DSI_V_SYNC_START: - case MIPI_DSI_V_SYNC_END: - case MIPI_DSI_H_SYNC_START: - case MIPI_DSI_H_SYNC_END: - case MIPI_DSI_END_OF_TRANSMISSION: - return 0; - - /* short and response packet types for command */ - case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: - case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: - case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: - case MIPI_DSI_DCS_READ: - exynos_mipi_dsi_clear_all_interrupt(dsim); - exynos_mipi_dsi_wr_tx_header(dsim, data_id, data0[0], data0[1]); - /* process response func should be implemented. */ - return 0; - - /* long packet type and null packet */ - case MIPI_DSI_NULL_PACKET: - case MIPI_DSI_BLANKING_PACKET: - return 0; - case MIPI_DSI_GENERIC_LONG_WRITE: - case MIPI_DSI_DCS_LONG_WRITE: - { - unsigned int payload = 0; - - /* if data count is less then 4, then send 3bytes data. */ - if (data1 < 4) { - payload = data0[0] | - data0[1] << 8 | - data0[2] << 16; - - exynos_mipi_dsi_wr_tx_data(dsim, payload); - - debug("count = %d payload = %x,%x %x %x\n", - data1, payload, data0[0], - data0[1], data0[2]); - } else { - /* in case that data count is more then 4 */ - exynos_mipi_dsi_long_data_wr(dsim, data0, data1); - } - - /* put data into header fifo */ - exynos_mipi_dsi_wr_tx_header(dsim, data_id, data1 & 0xff, - (data1 & 0xff00) >> 8); - - } - if (check_rx_ack) - /* process response func should be implemented. */ - return 0; - else - return -EINVAL; - - /* packet typo for video data */ - case MIPI_DSI_PACKED_PIXEL_STREAM_16: - case MIPI_DSI_PACKED_PIXEL_STREAM_18: - case MIPI_DSI_PIXEL_STREAM_3BYTE_18: - case MIPI_DSI_PACKED_PIXEL_STREAM_24: - if (check_rx_ack) { - /* process response func should be implemented. */ - return 0; - } else { - return -EINVAL; - } - default: - debug("data id %x is not supported current DSI spec.\n", - data_id); - - return -EINVAL; - } - - return 0; -} - -int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable) -{ - int sw_timeout; - - if (enable) { - sw_timeout = 1000; - - exynos_mipi_dsi_clear_interrupt(dsim); - exynos_mipi_dsi_enable_pll(dsim, 1); - while (1) { - sw_timeout--; - if (exynos_mipi_dsi_is_pll_stable(dsim)) - return 0; - if (sw_timeout == 0) - return -EINVAL; - } - } else - exynos_mipi_dsi_enable_pll(dsim, 0); - - return 0; -} - -unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim, - unsigned int pre_divider, unsigned int main_divider, - unsigned int scaler) -{ - unsigned long dfin_pll, dfvco, dpll_out; - unsigned int i, freq_band = 0xf; - - dfin_pll = (FIN_HZ / pre_divider); - - /****************************************************** - * Serial Clock(=ByteClk X 8) FreqBand[3:0] * - ****************************************************** - * ~ 99.99 MHz 0000 - * 100 ~ 119.99 MHz 0001 - * 120 ~ 159.99 MHz 0010 - * 160 ~ 199.99 MHz 0011 - * 200 ~ 239.99 MHz 0100 - * 140 ~ 319.99 MHz 0101 - * 320 ~ 389.99 MHz 0110 - * 390 ~ 449.99 MHz 0111 - * 450 ~ 509.99 MHz 1000 - * 510 ~ 559.99 MHz 1001 - * 560 ~ 639.99 MHz 1010 - * 640 ~ 689.99 MHz 1011 - * 690 ~ 769.99 MHz 1100 - * 770 ~ 869.99 MHz 1101 - * 870 ~ 949.99 MHz 1110 - * 950 ~ 1000 MHz 1111 - ******************************************************/ - if (dfin_pll < DFIN_PLL_MIN_HZ || dfin_pll > DFIN_PLL_MAX_HZ) { - debug("fin_pll range should be 6MHz ~ 12MHz\n"); - exynos_mipi_dsi_enable_afc(dsim, 0, 0); - } else { - if (dfin_pll < 7 * MHZ) - exynos_mipi_dsi_enable_afc(dsim, 1, 0x1); - else if (dfin_pll < 8 * MHZ) - exynos_mipi_dsi_enable_afc(dsim, 1, 0x0); - else if (dfin_pll < 9 * MHZ) - exynos_mipi_dsi_enable_afc(dsim, 1, 0x3); - else if (dfin_pll < 10 * MHZ) - exynos_mipi_dsi_enable_afc(dsim, 1, 0x2); - else if (dfin_pll < 11 * MHZ) - exynos_mipi_dsi_enable_afc(dsim, 1, 0x5); - else - exynos_mipi_dsi_enable_afc(dsim, 1, 0x4); - } - - dfvco = dfin_pll * main_divider; - debug("dfvco = %lu, dfin_pll = %lu, main_divider = %d\n", - dfvco, dfin_pll, main_divider); - if (dfvco < DFVCO_MIN_HZ || dfvco > DFVCO_MAX_HZ) - debug("fvco range should be 500MHz ~ 1000MHz\n"); - - dpll_out = dfvco / (1 << scaler); - debug("dpll_out = %lu, dfvco = %lu, scaler = %d\n", - dpll_out, dfvco, scaler); - - for (i = 0; i < ARRAY_SIZE(dpll_table); i++) { - if (dpll_out < dpll_table[i] * MHZ) { - freq_band = i; - break; - } - } - - debug("freq_band = %d\n", freq_band); - - exynos_mipi_dsi_pll_freq(dsim, pre_divider, main_divider, scaler); - - exynos_mipi_dsi_hs_zero_ctrl(dsim, 0); - exynos_mipi_dsi_prep_ctrl(dsim, 0); - - /* Freq Band */ - exynos_mipi_dsi_pll_freq_band(dsim, freq_band); - - /* Stable time */ - exynos_mipi_dsi_pll_stable_time(dsim, - dsim->dsim_config->pll_stable_time); - - /* Enable PLL */ - debug("FOUT of mipi dphy pll is %luMHz\n", - (dpll_out / MHZ)); - - return dpll_out; -} - -int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim, - unsigned int byte_clk_sel, unsigned int enable) -{ - unsigned int esc_div; - unsigned long esc_clk_error_rate; - unsigned long hs_clk = 0, byte_clk = 0, escape_clk = 0; - - if (enable) { - dsim->e_clk_src = byte_clk_sel; - - /* Escape mode clock and byte clock source */ - exynos_mipi_dsi_set_byte_clock_src(dsim, byte_clk_sel); - - /* DPHY, DSIM Link : D-PHY clock out */ - if (byte_clk_sel == DSIM_PLL_OUT_DIV8) { - hs_clk = exynos_mipi_dsi_change_pll(dsim, - dsim->dsim_config->p, dsim->dsim_config->m, - dsim->dsim_config->s); - if (hs_clk == 0) { - debug("failed to get hs clock.\n"); - return -EINVAL; - } - - byte_clk = hs_clk / 8; - exynos_mipi_dsi_enable_pll_bypass(dsim, 0); - exynos_mipi_dsi_pll_on(dsim, 1); - /* DPHY : D-PHY clock out, DSIM link : external clock out */ - } else if (byte_clk_sel == DSIM_EXT_CLK_DIV8) - debug("not support EXT CLK source for MIPI DSIM\n"); - else if (byte_clk_sel == DSIM_EXT_CLK_BYPASS) - debug("not support EXT CLK source for MIPI DSIM\n"); - - /* escape clock divider */ - esc_div = byte_clk / (dsim->dsim_config->esc_clk); - debug("esc_div = %d, byte_clk = %lu, esc_clk = %lu\n", - esc_div, byte_clk, dsim->dsim_config->esc_clk); - if ((byte_clk / esc_div) >= (20 * MHZ) || - (byte_clk / esc_div) > dsim->dsim_config->esc_clk) - esc_div += 1; - - escape_clk = byte_clk / esc_div; - debug("escape_clk = %lu, byte_clk = %lu, esc_div = %d\n", - escape_clk, byte_clk, esc_div); - - /* enable escape clock. */ - exynos_mipi_dsi_enable_byte_clock(dsim, 1); - - /* enable byte clk and escape clock */ - exynos_mipi_dsi_set_esc_clk_prs(dsim, 1, esc_div); - /* escape clock on lane */ - exynos_mipi_dsi_enable_esc_clk_on_lane(dsim, - (DSIM_LANE_CLOCK | dsim->data_lane), 1); - - debug("byte clock is %luMHz\n", - (byte_clk / MHZ)); - debug("escape clock that user's need is %lu\n", - (dsim->dsim_config->esc_clk / MHZ)); - debug("escape clock divider is %x\n", esc_div); - debug("escape clock is %luMHz\n", - ((byte_clk / esc_div) / MHZ)); - - if ((byte_clk / esc_div) > escape_clk) { - esc_clk_error_rate = escape_clk / - (byte_clk / esc_div); - debug("error rate is %lu over.\n", - (esc_clk_error_rate / 100)); - } else if ((byte_clk / esc_div) < (escape_clk)) { - esc_clk_error_rate = (byte_clk / esc_div) / - escape_clk; - debug("error rate is %lu under.\n", - (esc_clk_error_rate / 100)); - } - } else { - exynos_mipi_dsi_enable_esc_clk_on_lane(dsim, - (DSIM_LANE_CLOCK | dsim->data_lane), 0); - exynos_mipi_dsi_set_esc_clk_prs(dsim, 0, 0); - - /* disable escape clock. */ - exynos_mipi_dsi_enable_byte_clock(dsim, 0); - - if (byte_clk_sel == DSIM_PLL_OUT_DIV8) - exynos_mipi_dsi_pll_on(dsim, 0); - } - - return 0; -} - -int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim) -{ - dsim->state = DSIM_STATE_INIT; - - switch (dsim->dsim_config->e_no_data_lane) { - case DSIM_DATA_LANE_1: - dsim->data_lane = DSIM_LANE_DATA0; - break; - case DSIM_DATA_LANE_2: - dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1; - break; - case DSIM_DATA_LANE_3: - dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | - DSIM_LANE_DATA2; - break; - case DSIM_DATA_LANE_4: - dsim->data_lane = DSIM_LANE_DATA0 | DSIM_LANE_DATA1 | - DSIM_LANE_DATA2 | DSIM_LANE_DATA3; - break; - default: - debug("data lane is invalid.\n"); - return -EINVAL; - }; - - exynos_mipi_dsi_sw_reset(dsim); - exynos_mipi_dsi_dp_dn_swap(dsim, 0); - - return 0; -} - -int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - /* enable only frame done interrupt */ - exynos_mipi_dsi_set_interrupt_mask(dsim, INTMSK_FRAME_DONE, enable); - - return 0; -} - -static void convert_to_fb_videomode(struct fb_videomode *mode1, - vidinfo_t *mode2) -{ - mode1->xres = mode2->vl_width; - mode1->yres = mode2->vl_height; - mode1->upper_margin = mode2->vl_vfpd; - mode1->lower_margin = mode2->vl_vbpd; - mode1->left_margin = mode2->vl_hfpd; - mode1->right_margin = mode2->vl_hbpd; - mode1->vsync_len = mode2->vl_vspw; - mode1->hsync_len = mode2->vl_hspw; -} - -int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, - struct mipi_dsim_config *dsim_config) -{ - struct exynos_platform_mipi_dsim *dsim_pd; - struct fb_videomode lcd_video; - vidinfo_t *vid; - - dsim_pd = (struct exynos_platform_mipi_dsim *)dsim->pd; - vid = (vidinfo_t *)dsim_pd->lcd_panel_info; - - convert_to_fb_videomode(&lcd_video, vid); - - /* in case of VIDEO MODE (RGB INTERFACE), it sets polarities. */ - if (dsim->dsim_config->e_interface == (u32) DSIM_VIDEO) { - if (dsim->dsim_config->auto_vertical_cnt == 0) { - exynos_mipi_dsi_set_main_disp_vporch(dsim, - vid->vl_cmd_allow_len, - lcd_video.upper_margin, - lcd_video.lower_margin); - exynos_mipi_dsi_set_main_disp_hporch(dsim, - lcd_video.left_margin, - lcd_video.right_margin); - exynos_mipi_dsi_set_main_disp_sync_area(dsim, - lcd_video.vsync_len, - lcd_video.hsync_len); - } - } - - exynos_mipi_dsi_set_main_disp_resol(dsim, lcd_video.xres, - lcd_video.yres); - - exynos_mipi_dsi_display_config(dsim, dsim->dsim_config); - - debug("lcd panel ==> width = %d, height = %d\n", - lcd_video.xres, lcd_video.yres); - - return 0; -} - -int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim) -{ - unsigned int time_out = 100; - - switch (dsim->state) { - case DSIM_STATE_INIT: - exynos_mipi_dsi_init_fifo_pointer(dsim, 0x1f); - - /* dsi configuration */ - exynos_mipi_dsi_init_config(dsim); - exynos_mipi_dsi_enable_lane(dsim, DSIM_LANE_CLOCK, 1); - exynos_mipi_dsi_enable_lane(dsim, dsim->data_lane, 1); - - /* set clock configuration */ - exynos_mipi_dsi_set_clock(dsim, - dsim->dsim_config->e_byte_clk, 1); - - /* check clock and data lane state are stop state */ - while (!(exynos_mipi_dsi_is_lane_state(dsim))) { - time_out--; - if (time_out == 0) { - debug("DSI Master is not stop state.\n"); - debug("Check initialization process\n"); - - return -EINVAL; - } - } - - dsim->state = DSIM_STATE_STOP; - - /* BTA sequence counters */ - exynos_mipi_dsi_set_stop_state_counter(dsim, - dsim->dsim_config->stop_holding_cnt); - exynos_mipi_dsi_set_bta_timeout(dsim, - dsim->dsim_config->bta_timeout); - exynos_mipi_dsi_set_lpdr_timeout(dsim, - dsim->dsim_config->rx_timeout); - - return 0; - default: - debug("DSI Master is already init.\n"); - return 0; - } - - return 0; -} - -int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim) -{ - if (dsim->state == DSIM_STATE_STOP) { - if (dsim->e_clk_src != DSIM_EXT_CLK_BYPASS) { - dsim->state = DSIM_STATE_HSCLKEN; - - /* set LCDC and CPU transfer mode to HS. */ - exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0); - exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0); - - exynos_mipi_dsi_enable_hs_clock(dsim, 1); - - return 0; - } else - debug("clock source is external bypass.\n"); - } else - debug("DSIM is not stop state.\n"); - - return 0; -} - -int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int mode) -{ - if (mode) { - if (dsim->state != DSIM_STATE_HSCLKEN) { - debug("HS Clock lane is not enabled.\n"); - return -EINVAL; - } - - exynos_mipi_dsi_set_lcdc_transfer_mode(dsim, 0); - } else { - if (dsim->state == DSIM_STATE_INIT || dsim->state == - DSIM_STATE_ULPS) { - debug("DSI Master is not STOP or HSDT state.\n"); - return -EINVAL; - } - - exynos_mipi_dsi_set_cpu_transfer_mode(dsim, 0); - } - - return 0; -} - -int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim) -{ - return _exynos_mipi_dsi_get_frame_done_status(dsim); -} - -int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim) -{ - _exynos_mipi_dsi_clear_frame_done(dsim); - - return 0; -} diff --git a/drivers/video/exynos_mipi_dsi_common.h b/drivers/video/exynos_mipi_dsi_common.h deleted file mode 100644 index 98eb78e..0000000 --- a/drivers/video/exynos_mipi_dsi_common.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include - -#ifndef _EXYNOS_MIPI_DSI_COMMON_H -#define _EXYNOS_MIPI_DSI_COMMON_H - -int exynos_mipi_dsi_wr_data(struct mipi_dsim_device *dsim, unsigned int data_id, - const unsigned char *data0, unsigned int data1); -int exynos_mipi_dsi_pll_on(struct mipi_dsim_device *dsim, unsigned int enable); -unsigned long exynos_mipi_dsi_change_pll(struct mipi_dsim_device *dsim, - unsigned int pre_divider, unsigned int main_divider, - unsigned int scaler); -int exynos_mipi_dsi_set_clock(struct mipi_dsim_device *dsim, - unsigned int byte_clk_sel, unsigned int enable); -int exynos_mipi_dsi_init_dsim(struct mipi_dsim_device *dsim); -int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, - struct mipi_dsim_config *dsim_info); -int exynos_mipi_dsi_init_link(struct mipi_dsim_device *dsim); -int exynos_mipi_dsi_set_hs_enable(struct mipi_dsim_device *dsim); -int exynos_mipi_dsi_set_data_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int mode); -int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, - unsigned int enable); -int exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device *dsim); -int exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim); - -#endif /* _EXYNOS_MIPI_DSI_COMMON_H */ diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.c b/drivers/video/exynos_mipi_dsi_lowlevel.c deleted file mode 100644 index fcfdc8d..0000000 --- a/drivers/video/exynos_mipi_dsi_lowlevel.c +++ /dev/null @@ -1,639 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include - -#include "exynos_mipi_dsi_lowlevel.h" -#include "exynos_mipi_dsi_common.h" - -void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim) -{ - unsigned int reg; - - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = readl(&mipi_dsim->swrst); - - reg |= DSIM_FUNCRST; - - writel(reg, &mipi_dsim->swrst); -} - -void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim) -{ - unsigned int reg = 0; - - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = readl(&mipi_dsim->swrst); - - reg |= DSIM_SWRST; - reg |= DSIM_FUNCRST; - - writel(reg, &mipi_dsim->swrst); -} - -void exynos_mipi_dsi_sw_release(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->intsrc); - - reg |= INTSRC_SWRST_RELEASE; - - writel(reg, &mipi_dsim->intsrc); -} - -void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim, - unsigned int mode, unsigned int mask) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->intmsk); - - if (mask) - reg |= mode; - else - reg &= ~mode; - - writel(reg, &mipi_dsim->intmsk); -} - -void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim, - unsigned int cfg) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = readl(&mipi_dsim->fifoctrl); - - writel(reg & ~(cfg), &mipi_dsim->fifoctrl); - udelay(10 * 1000); - reg |= cfg; - - writel(reg, &mipi_dsim->fifoctrl); -} - -/* - * this function set PLL P, M and S value in D-PHY - */ -void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, - unsigned int value) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - writel(DSIM_AFC_CTL(value), &mipi_dsim->phyacchr); -} - -void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim, - unsigned int width_resol, unsigned int height_resol) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - /* standby should be set after configuration so set to not ready*/ - reg = (readl(&mipi_dsim->mdresol)) & ~(DSIM_MAIN_STAND_BY); - writel(reg, &mipi_dsim->mdresol); - - /* reset resolution */ - reg &= ~(DSIM_MAIN_VRESOL(0x7ff) | DSIM_MAIN_HRESOL(0x7ff)); - reg |= DSIM_MAIN_VRESOL(height_resol) | DSIM_MAIN_HRESOL(width_resol); - - reg |= DSIM_MAIN_STAND_BY; - writel(reg, &mipi_dsim->mdresol); -} - -void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim, - unsigned int cmd_allow, unsigned int vfront, unsigned int vback) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = (readl(&mipi_dsim->mvporch)) & - ~((DSIM_CMD_ALLOW_MASK) | (DSIM_STABLE_VFP_MASK) | - (DSIM_MAIN_VBP_MASK)); - - reg |= ((cmd_allow & 0xf) << DSIM_CMD_ALLOW_SHIFT) | - ((vfront & 0x7ff) << DSIM_STABLE_VFP_SHIFT) | - ((vback & 0x7ff) << DSIM_MAIN_VBP_SHIFT); - - writel(reg, &mipi_dsim->mvporch); -} - -void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim, - unsigned int front, unsigned int back) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = (readl(&mipi_dsim->mhporch)) & - ~((DSIM_MAIN_HFP_MASK) | (DSIM_MAIN_HBP_MASK)); - - reg |= (front << DSIM_MAIN_HFP_SHIFT) | (back << DSIM_MAIN_HBP_SHIFT); - - writel(reg, &mipi_dsim->mhporch); -} - -void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim, - unsigned int vert, unsigned int hori) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = (readl(&mipi_dsim->msync)) & - ~((DSIM_MAIN_VSA_MASK) | (DSIM_MAIN_HSA_MASK)); - - reg |= ((vert & 0x3ff) << DSIM_MAIN_VSA_SHIFT) | - (hori << DSIM_MAIN_HSA_SHIFT); - - writel(reg, &mipi_dsim->msync); -} - -void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim, - unsigned int vert, unsigned int hori) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = (readl(&mipi_dsim->sdresol)) & - ~(DSIM_SUB_STANDY_MASK); - - writel(reg, &mipi_dsim->sdresol); - - reg &= ~(DSIM_SUB_VRESOL_MASK) | ~(DSIM_SUB_HRESOL_MASK); - reg |= ((vert & 0x7ff) << DSIM_SUB_VRESOL_SHIFT) | - ((hori & 0x7ff) << DSIM_SUB_HRESOL_SHIFT); - writel(reg, &mipi_dsim->sdresol); - - /* DSIM STANDBY */ - reg |= (1 << DSIM_SUB_STANDY_SHIFT); - writel(reg, &mipi_dsim->sdresol); -} - -void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim) -{ - struct mipi_dsim_config *dsim_config = dsim->dsim_config; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int cfg = (readl(&mipi_dsim->config)) & - ~((1 << DSIM_EOT_PACKET_SHIFT) | - (0x1f << DSIM_HSA_MODE_SHIFT) | - (0x3 << DSIM_NUM_OF_DATALANE_SHIFT)); - - cfg |= (dsim_config->auto_flush << DSIM_AUTO_FLUSH_SHIFT) | - (dsim_config->eot_disable << DSIM_EOT_PACKET_SHIFT) | - (dsim_config->auto_vertical_cnt << DSIM_AUTO_MODE_SHIFT) | - (dsim_config->hse << DSIM_HSE_MODE_SHIFT) | - (dsim_config->hfp << DSIM_HFP_MODE_SHIFT) | - (dsim_config->hbp << DSIM_HBP_MODE_SHIFT) | - (dsim_config->hsa << DSIM_HSA_MODE_SHIFT) | - (dsim_config->e_no_data_lane << DSIM_NUM_OF_DATALANE_SHIFT); - - writel(cfg, &mipi_dsim->config); -} - -void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim, - struct mipi_dsim_config *dsim_config) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - u32 reg = (readl(&mipi_dsim->config)) & - ~((0x3 << DSIM_BURST_MODE_SHIFT) | (1 << DSIM_VIDEO_MODE_SHIFT) - | (0x3 << DSIM_MAINVC_SHIFT) | (0x7 << DSIM_MAINPIX_SHIFT) - | (0x3 << DSIM_SUBVC_SHIFT) | (0x7 << DSIM_SUBPIX_SHIFT)); - - if (dsim_config->e_interface == DSIM_VIDEO) - reg |= (1 << DSIM_VIDEO_MODE_SHIFT); - else if (dsim_config->e_interface == DSIM_COMMAND) - reg &= ~(1 << DSIM_VIDEO_MODE_SHIFT); - else { - printf("unknown lcd type.\n"); - return; - } - - /* main lcd */ - reg |= ((u8) (dsim_config->e_burst_mode) & 0x3) << DSIM_BURST_MODE_SHIFT - | ((u8) (dsim_config->e_virtual_ch) & 0x3) << DSIM_MAINVC_SHIFT - | ((u8) (dsim_config->e_pixel_format) & 0x7) << DSIM_MAINPIX_SHIFT; - - writel(reg, &mipi_dsim->config); -} - -void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, - unsigned int lane, unsigned int enable) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = readl(&mipi_dsim->config); - - if (enable) - reg |= DSIM_LANE_ENx(lane); - else - reg &= ~DSIM_LANE_ENx(lane); - - writel(reg, &mipi_dsim->config); -} - -void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, - unsigned int count) -{ - unsigned int cfg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - /* get the data lane number. */ - cfg = DSIM_NUM_OF_DATA_LANE(count); - - writel(cfg, &mipi_dsim->config); -} - -void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, - unsigned int enable, unsigned int afc_code) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->phyacchr); - - reg = 0; - - if (enable) { - reg |= DSIM_AFC_EN; - reg &= ~(0x7 << DSIM_AFC_CTL_SHIFT); - reg |= DSIM_AFC_CTL(afc_code); - } else - reg &= ~DSIM_AFC_EN; - - writel(reg, &mipi_dsim->phyacchr); -} - -void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->clkctrl)) & - ~(DSIM_PLL_BYPASS_EXTERNAL); - - reg |= enable << DSIM_PLL_BYPASS_SHIFT; - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim, - unsigned int freq_band) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->pllctrl)) & - ~(0x1f << DSIM_FREQ_BAND_SHIFT); - - reg |= ((freq_band & 0x1f) << DSIM_FREQ_BAND_SHIFT); - - writel(reg, &mipi_dsim->pllctrl); -} - -void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim, - unsigned int pre_divider, unsigned int main_divider, - unsigned int scaler) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->pllctrl)) & - ~(0x7ffff << 1); - - reg |= ((pre_divider & 0x3f) << DSIM_PREDIV_SHIFT) | - ((main_divider & 0x1ff) << DSIM_MAIN_SHIFT) | - ((scaler & 0x7) << DSIM_SCALER_SHIFT); - - writel(reg, &mipi_dsim->pllctrl); -} - -void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim, - unsigned int lock_time) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - writel(lock_time, &mipi_dsim->plltmr); -} - -void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->pllctrl)) & - ~(0x1 << DSIM_PLL_EN_SHIFT); - - reg |= ((enable & 0x1) << DSIM_PLL_EN_SHIFT); - - writel(reg, &mipi_dsim->pllctrl); -} - -void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim, - unsigned int src) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->clkctrl)) & - ~(0x3 << DSIM_BYTE_CLK_SRC_SHIFT); - - reg |= ((unsigned int) src) << DSIM_BYTE_CLK_SRC_SHIFT; - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->clkctrl)) & - ~(1 << DSIM_BYTE_CLKEN_SHIFT); - - reg |= enable << DSIM_BYTE_CLKEN_SHIFT; - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim, - unsigned int enable, unsigned int prs_val) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->clkctrl)) & - ~((1 << DSIM_ESC_CLKEN_SHIFT) | (0xffff)); - - reg |= enable << DSIM_ESC_CLKEN_SHIFT; - if (enable) - reg |= prs_val; - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim, - unsigned int lane_sel, unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->clkctrl); - - if (enable) - reg |= DSIM_LANE_ESC_CLKEN(lane_sel); - else - reg &= ~DSIM_LANE_ESC_CLKEN(lane_sel); - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->escmode)) & - ~(0x1 << DSIM_FORCE_STOP_STATE_SHIFT); - - reg |= ((enable & 0x1) << DSIM_FORCE_STOP_STATE_SHIFT); - - writel(reg, &mipi_dsim->escmode); -} - -unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->status); - - /** - * check clock and data lane states. - * if MIPI-DSI controller was enabled at bootloader then - * TX_READY_HS_CLK is enabled otherwise STOP_STATE_CLK. - * so it should be checked for two case. - */ - if ((reg & DSIM_STOP_STATE_DAT(0xf)) && - ((reg & DSIM_STOP_STATE_CLK) || - (reg & DSIM_TX_READY_HS_CLK))) - return 1; - else - return 0; -} - -void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim, - unsigned int cnt_val) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->escmode)) & - ~(0x7ff << DSIM_STOP_STATE_CNT_SHIFT); - - reg |= ((cnt_val & 0x7ff) << DSIM_STOP_STATE_CNT_SHIFT); - - writel(reg, &mipi_dsim->escmode); -} - -void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim, - unsigned int timeout) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->timeout)) & - ~(0xff << DSIM_BTA_TOUT_SHIFT); - - reg |= (timeout << DSIM_BTA_TOUT_SHIFT); - - writel(reg, &mipi_dsim->timeout); -} - -void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim, - unsigned int timeout) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->timeout)) & - ~(0xffff << DSIM_LPDR_TOUT_SHIFT); - - reg |= (timeout << DSIM_LPDR_TOUT_SHIFT); - - writel(reg, &mipi_dsim->timeout); -} - -void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int lp) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->escmode); - - reg &= ~DSIM_CMD_LPDT_LP; - - if (lp) - reg |= DSIM_CMD_LPDT_LP; - - writel(reg, &mipi_dsim->escmode); -} - -void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int lp) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->escmode); - - reg &= ~DSIM_TX_LPDT_LP; - - if (lp) - reg |= DSIM_TX_LPDT_LP; - - writel(reg, &mipi_dsim->escmode); -} - -void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim, - unsigned int enable) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->clkctrl)) & - ~(1 << DSIM_TX_REQUEST_HSCLK_SHIFT); - - reg |= enable << DSIM_TX_REQUEST_HSCLK_SHIFT; - - writel(reg, &mipi_dsim->clkctrl); -} - -void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim, - unsigned int swap_en) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->phyacchr1); - - reg &= ~(0x3 << DSIM_DPDN_SWAP_DATA_SHIFT); - reg |= (swap_en & 0x3) << DSIM_DPDN_SWAP_DATA_SHIFT; - - writel(reg, &mipi_dsim->phyacchr1); -} - -void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim, - unsigned int hs_zero) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->pllctrl)) & - ~(0xf << DSIM_ZEROCTRL_SHIFT); - - reg |= ((hs_zero & 0xf) << DSIM_ZEROCTRL_SHIFT); - - writel(reg, &mipi_dsim->pllctrl); -} - -void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, unsigned int prep) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (readl(&mipi_dsim->pllctrl)) & - ~(0x7 << DSIM_PRECTRL_SHIFT); - - reg |= ((prep & 0x7) << DSIM_PRECTRL_SHIFT); - - writel(reg, &mipi_dsim->pllctrl); -} - -void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->intsrc); - - reg |= INTSRC_PLL_STABLE; - - writel(reg, &mipi_dsim->intsrc); -} - -void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - writel(0xffffffff, &mipi_dsim->intsrc); -} - -unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim) -{ - unsigned int reg; - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - reg = readl(&mipi_dsim->status); - - return reg & DSIM_PLL_STABLE ? 1 : 0; -} - -unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - return readl(&mipi_dsim->fifoctrl) & ~(0x1f); -} - -void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, - unsigned int di, const unsigned char data0, const unsigned char data1) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = (DSIM_PKTHDR_DAT1(data1) | DSIM_PKTHDR_DAT0(data0) | - DSIM_PKTHDR_DI(di)); - - writel(reg, &mipi_dsim->pkthdr); -} - -unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device - *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->intsrc); - - return (reg & INTSRC_FRAME_DONE) ? 1 : 0; -} - -void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - unsigned int reg = readl(&mipi_dsim->intsrc); - - writel(reg | INTSRC_FRAME_DONE, &mipi_dsim->intsrc); -} - -void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim, - unsigned int tx_data) -{ - struct exynos_mipi_dsim *mipi_dsim = - (struct exynos_mipi_dsim *)samsung_get_base_mipi_dsim(); - - writel(tx_data, &mipi_dsim->payload); -} diff --git a/drivers/video/exynos_mipi_dsi_lowlevel.h b/drivers/video/exynos_mipi_dsi_lowlevel.h deleted file mode 100644 index 0bede25..0000000 --- a/drivers/video/exynos_mipi_dsi_lowlevel.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_MIPI_DSI_LOWLEVEL_H -#define _EXYNOS_MIPI_DSI_LOWLEVEL_H - -void exynos_mipi_dsi_register(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_func_reset(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_sw_reset(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_sw_release(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_set_interrupt_mask(struct mipi_dsim_device *dsim, - unsigned int mode, unsigned int mask); -void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, - unsigned int count); -void exynos_mipi_dsi_init_fifo_pointer(struct mipi_dsim_device *dsim, - unsigned int cfg); -void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, - unsigned int value); -void exynos_mipi_dsi_set_phy_tunning(struct mipi_dsim_device *dsim, - unsigned int value); -void exynos_mipi_dsi_set_main_disp_resol(struct mipi_dsim_device *dsim, - unsigned int width_resol, unsigned int height_resol); -void exynos_mipi_dsi_set_main_disp_vporch(struct mipi_dsim_device *dsim, - unsigned int cmd_allow, unsigned int vfront, unsigned int vback); -void exynos_mipi_dsi_set_main_disp_hporch(struct mipi_dsim_device *dsim, - unsigned int front, unsigned int back); -void exynos_mipi_dsi_set_main_disp_sync_area(struct mipi_dsim_device *dsim, - unsigned int vert, unsigned int hori); -void exynos_mipi_dsi_set_sub_disp_resol(struct mipi_dsim_device *dsim, - unsigned int vert, unsigned int hori); -void exynos_mipi_dsi_init_config(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_display_config(struct mipi_dsim_device *dsim, - struct mipi_dsim_config *dsim_config); -void exynos_mipi_dsi_set_data_lane_number(struct mipi_dsim_device *dsim, - unsigned int count); -void exynos_mipi_dsi_enable_lane(struct mipi_dsim_device *dsim, - unsigned int lane, unsigned int enable); -void exynos_mipi_dsi_enable_afc(struct mipi_dsim_device *dsim, - unsigned int enable, unsigned int afc_code); -void exynos_mipi_dsi_enable_pll_bypass(struct mipi_dsim_device *dsim, - unsigned int enable); -void exynos_mipi_dsi_pll_freq_band(struct mipi_dsim_device *dsim, - unsigned int freq_band); -void exynos_mipi_dsi_pll_freq(struct mipi_dsim_device *dsim, - unsigned int pre_divider, unsigned int main_divider, - unsigned int scaler); -void exynos_mipi_dsi_pll_stable_time(struct mipi_dsim_device *dsim, - unsigned int lock_time); -void exynos_mipi_dsi_enable_pll(struct mipi_dsim_device *dsim, - unsigned int enable); -void exynos_mipi_dsi_set_byte_clock_src(struct mipi_dsim_device *dsim, - unsigned int src); -void exynos_mipi_dsi_enable_byte_clock(struct mipi_dsim_device *dsim, - unsigned int enable); -void exynos_mipi_dsi_set_esc_clk_prs(struct mipi_dsim_device *dsim, - unsigned int enable, unsigned int prs_val); -void exynos_mipi_dsi_enable_esc_clk_on_lane(struct mipi_dsim_device *dsim, - unsigned int lane_sel, unsigned int enable); -void exynos_mipi_dsi_force_dphy_stop_state(struct mipi_dsim_device *dsim, - unsigned int enable); -unsigned int exynos_mipi_dsi_is_lane_state(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_set_stop_state_counter(struct mipi_dsim_device *dsim, - unsigned int cnt_val); -void exynos_mipi_dsi_set_bta_timeout(struct mipi_dsim_device *dsim, - unsigned int timeout); -void exynos_mipi_dsi_set_lpdr_timeout(struct mipi_dsim_device *dsim, - unsigned int timeout); -void exynos_mipi_dsi_set_lcdc_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int lp); -void exynos_mipi_dsi_set_cpu_transfer_mode(struct mipi_dsim_device *dsim, - unsigned int lp); -void exynos_mipi_dsi_enable_hs_clock(struct mipi_dsim_device *dsim, - unsigned int enable); -void exynos_mipi_dsi_dp_dn_swap(struct mipi_dsim_device *dsim, - unsigned int swap_en); -void exynos_mipi_dsi_hs_zero_ctrl(struct mipi_dsim_device *dsim, - unsigned int hs_zero); -void exynos_mipi_dsi_prep_ctrl(struct mipi_dsim_device *dsim, - unsigned int prep); -void exynos_mipi_dsi_clear_interrupt(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_clear_all_interrupt(struct mipi_dsim_device *dsim); -unsigned int exynos_mipi_dsi_is_pll_stable(struct mipi_dsim_device *dsim); -unsigned int exynos_mipi_dsi_get_fifo_state(struct mipi_dsim_device *dsim); -unsigned int _exynos_mipi_dsi_get_frame_done_status(struct mipi_dsim_device - *dsim); -void _exynos_mipi_dsi_clear_frame_done(struct mipi_dsim_device *dsim); -void exynos_mipi_dsi_wr_tx_header(struct mipi_dsim_device *dsim, - unsigned int di, const unsigned char data0, const unsigned char data1); -void exynos_mipi_dsi_wr_tx_data(struct mipi_dsim_device *dsim, - unsigned int tx_data); - -#endif /* _EXYNOS_MIPI_DSI_LOWLEVEL_H */ diff --git a/drivers/video/exynos_pwm_bl.c b/drivers/video/exynos_pwm_bl.c deleted file mode 100644 index a6890da..0000000 --- a/drivers/video/exynos_pwm_bl.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * PWM BACKLIGHT driver for Board based on EXYNOS. - * - * Author: Donghwa Lee - * - * Derived from linux/drivers/video/backlight/pwm_backlight.c - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static struct pwm_backlight_data *pwm; - -static int exynos_pwm_backlight_update_status(void) -{ - int brightness = pwm->brightness; - int max = pwm->max_brightness; - - if (brightness == 0) { - pwm_config(pwm->pwm_id, 0, pwm->period); - pwm_disable(pwm->pwm_id); - } else { - pwm_config(pwm->pwm_id, - brightness * pwm->period / max, pwm->period); - pwm_enable(pwm->pwm_id); - } - return 0; -} - -int exynos_pwm_backlight_init(struct pwm_backlight_data *pd) -{ - pwm = pd; - - exynos_pwm_backlight_update_status(); - - return 0; -} diff --git a/drivers/video/s6e8ax0.c b/drivers/video/s6e8ax0.c index 8494817..1bd49ee 100644 --- a/drivers/video/s6e8ax0.c +++ b/drivers/video/s6e8ax0.c @@ -9,8 +9,8 @@ #include #include -#include "exynos_mipi_dsi_lowlevel.h" -#include "exynos_mipi_dsi_common.h" +#include "exynos/exynos_mipi_dsi_lowlevel.h" +#include "exynos/exynos_mipi_dsi_common.h" static void s6e8ax0_panel_cond(struct mipi_dsim_device *dsim_dev) { -- cgit v1.1 From b6feb2675b75c687b9ddb9e5a493cfe4035e387d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:39 -0700 Subject: exynos: video: Drop dead code We always use device tree with video, so can drop these #ifdefs. Some of the hardware addresses are not needed either. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp_lowlevel.c | 4 ---- drivers/video/exynos/exynos_fb.c | 11 ----------- drivers/video/exynos/exynos_fimd.c | 7 ------- drivers/video/exynos/exynos_mipi_dsi.c | 4 ---- 4 files changed, 26 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c index acb5bc8..e417cf8 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.c +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -22,7 +22,6 @@ struct exynos_dp *dp_regs; void exynos_dp_set_base_addr(void) { -#if CONFIG_IS_ENABLED(OF_CONTROL) unsigned int node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_SAMSUNG_EXYNOS5_DP); if (node <= 0) @@ -32,9 +31,6 @@ void exynos_dp_set_base_addr(void) node, "reg"); if (dp_regs == NULL) debug("Can't get the DP base address\n"); -#else - dp_regs = (struct exynos_dp *)samsung_get_base_dp(); -#endif } static void exynos_dp_enable_video_input(unsigned int enable) diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 69edc3a..39e3ade 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -28,7 +28,6 @@ DECLARE_GLOBAL_DATA_PTR; static unsigned int panel_width, panel_height; -#if CONFIG_IS_ENABLED(OF_CONTROL) vidinfo_t panel_info = { /* * Insert a value here so that we don't end up in the BSS @@ -36,7 +35,6 @@ vidinfo_t panel_info = { */ .vl_col = -1, }; -#endif ushort *configuration_get_cmap(void) { @@ -126,7 +124,6 @@ static void lcd_panel_on(vidinfo_t *vid) exynos_backlight_on(1); -#if CONFIG_IS_ENABLED(OF_CONTROL) node = fdtdec_next_compatible(gd->fdt_blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); if (node <= 0) { @@ -141,7 +138,6 @@ static void lcd_panel_on(vidinfo_t *vid) &bl_en_gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); -#endif exynos_cfg_ldo(); exynos_enable_ldo(1); @@ -150,7 +146,6 @@ static void lcd_panel_on(vidinfo_t *vid) exynos_mipi_dsi_init(); } -#if CONFIG_IS_ENABLED(OF_CONTROL) int exynos_lcd_early_init(const void *blob) { unsigned int node; @@ -288,22 +283,16 @@ int exynos_lcd_early_init(const void *blob) return 0; } -#endif void lcd_ctrl_init(void *lcdbase) { set_system_display_ctrl(); set_lcd_clk(); -#if CONFIG_IS_ENABLED(OF_CONTROL) #ifdef CONFIG_EXYNOS_MIPI_DSIM exynos_init_dsim_platform_data(&panel_info); #endif exynos_lcd_misc_init(&panel_info); -#else - /* initialize parameters which is specific to panel. */ - init_panel_info(&panel_info); -#endif panel_width = panel_info.vl_width; panel_height = panel_info.vl_height; diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c index ac001a8..019d88f 100644 --- a/drivers/video/exynos/exynos_fimd.c +++ b/drivers/video/exynos/exynos_fimd.c @@ -251,7 +251,6 @@ void exynos_fimd_window_off(unsigned int win_id) writel(cfg, &fimd_ctrl->winshmap); } -#if CONFIG_IS_ENABLED(OF_CONTROL) /* * The reset value for FIMD SYSMMU register MMU_CTRL is 3 * on Exynos5420 and newer versions. @@ -289,13 +288,11 @@ void exynos_fimd_disable_sysmmu(void) writel(0x0, sysmmufimd); } } -#endif void exynos_fimd_lcd_init(vidinfo_t *vid) { unsigned int cfg = 0, rgb_mode; unsigned int offset; -#if CONFIG_IS_ENABLED(OF_CONTROL) unsigned int node; node = fdtdec_next_compatible(gd->fdt_blob, @@ -311,10 +308,6 @@ void exynos_fimd_lcd_init(vidinfo_t *vid) if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) exynos_fimd_disable_sysmmu(); -#else - fimd_ctrl = (struct exynos_fb *)samsung_get_base_fimd(); -#endif - offset = exynos_fimd_get_base_offset(); /* store panel info to global variable */ diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index b597acc..5001e16 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -28,11 +28,9 @@ DECLARE_GLOBAL_DATA_PTR; static struct exynos_platform_mipi_dsim *dsim_pd; -#if CONFIG_IS_ENABLED(OF_CONTROL) static struct mipi_dsim_config dsim_config_dt; static struct exynos_platform_mipi_dsim dsim_platform_data_dt; static struct mipi_dsim_lcd_device mipi_lcd_device_dt; -#endif struct mipi_dsim_ddi { int bus_id; @@ -249,7 +247,6 @@ void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) dsim_pd = pd; } -#if CONFIG_IS_ENABLED(OF_CONTROL) int exynos_dsim_config_parse_dt(const void *blob) { int node; @@ -334,4 +331,3 @@ void exynos_init_dsim_platform_data(vidinfo_t *vid) dsim_pd = &dsim_platform_data_dt; } -#endif -- cgit v1.1 From aaca5b1902e1d711d34f2fb741417ec7bae59ad6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:40 -0700 Subject: exynos: video: Remove use of vidinfo_t typedef Use 'struct vidinfo' instead so that we can change this to a struct with a different name in future. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.c | 10 +++++----- drivers/video/exynos/exynos_fimd.c | 6 +++--- drivers/video/exynos/exynos_mipi_dsi_common.c | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 39e3ade..90d2038 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -28,7 +28,7 @@ DECLARE_GLOBAL_DATA_PTR; static unsigned int panel_width, panel_height; -vidinfo_t panel_info = { +struct vidinfo panel_info = { /* * Insert a value here so that we don't end up in the BSS * Reference: drivers/video/tegra.c @@ -45,7 +45,7 @@ ushort *configuration_get_cmap(void) #endif } -static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) +static void exynos_lcd_init_mem(void *lcdbase, struct vidinfo *vid) { unsigned long palette_size; unsigned int fb_size; @@ -58,7 +58,7 @@ static void exynos_lcd_init_mem(void *lcdbase, vidinfo_t *vid) (unsigned long)fb_size, palette_size); } -static void exynos_lcd_init(vidinfo_t *vid) +static void exynos_lcd_init(struct vidinfo *vid) { exynos_fimd_lcd_init(vid); @@ -94,12 +94,12 @@ __weak void exynos_backlight_reset(void) { } -__weak int exynos_lcd_misc_init(vidinfo_t *vid) +__weak int exynos_lcd_misc_init(struct vidinfo *vid) { return 0; } -static void lcd_panel_on(vidinfo_t *vid) +static void lcd_panel_on(struct vidinfo *vid) { struct gpio_desc pwm_out_gpio; struct gpio_desc bl_en_gpio; diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c index 019d88f..e6fb5d1 100644 --- a/drivers/video/exynos/exynos_fimd.c +++ b/drivers/video/exynos/exynos_fimd.c @@ -22,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; static unsigned long *lcd_base_addr; -static vidinfo_t *pvid; +static struct vidinfo *pvid; static struct exynos_fb *fimd_ctrl; void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, @@ -123,7 +123,7 @@ static void exynos_fimd_set_buffer_address(unsigned int win_id) EXYNOS_BUFFER_OFFSET(win_id)); } -static void exynos_fimd_set_clock(vidinfo_t *pvid) +static void exynos_fimd_set_clock(struct vidinfo *pvid) { unsigned int cfg = 0, div = 0, remainder, remainder_div; unsigned long pixel_clock; @@ -289,7 +289,7 @@ void exynos_fimd_disable_sysmmu(void) } } -void exynos_fimd_lcd_init(vidinfo_t *vid) +void exynos_fimd_lcd_init(struct vidinfo *vid) { unsigned int cfg = 0, rgb_mode; unsigned int offset; diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/exynos/exynos_mipi_dsi_common.c index 925d515..85c5e0d 100644 --- a/drivers/video/exynos/exynos_mipi_dsi_common.c +++ b/drivers/video/exynos/exynos_mipi_dsi_common.c @@ -465,7 +465,7 @@ int exynos_mipi_dsi_enable_frame_done_int(struct mipi_dsim_device *dsim, } static void convert_to_fb_videomode(struct fb_videomode *mode1, - vidinfo_t *mode2) + struct vidinfo *mode2) { mode1->xres = mode2->vl_width; mode1->yres = mode2->vl_height; @@ -482,10 +482,10 @@ int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim, { struct exynos_platform_mipi_dsim *dsim_pd; struct fb_videomode lcd_video; - vidinfo_t *vid; + struct vidinfo *vid; dsim_pd = (struct exynos_platform_mipi_dsim *)dsim->pd; - vid = (vidinfo_t *)dsim_pd->lcd_panel_info; + vid = (struct vidinfo *)dsim_pd->lcd_panel_info; convert_to_fb_videomode(&lcd_video, vid); -- cgit v1.1 From 40d500212f74c92ef014ae8df697416e160ee743 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:41 -0700 Subject: exynos: video: Drop the static lcd_base_addr variable Drop this and use parameters instead. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.c | 21 +++------------------ drivers/video/exynos/exynos_fb.h | 2 +- drivers/video/exynos/exynos_fimd.c | 26 +++++++++++--------------- 3 files changed, 15 insertions(+), 34 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 90d2038..a3acdcc 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -45,22 +45,9 @@ ushort *configuration_get_cmap(void) #endif } -static void exynos_lcd_init_mem(void *lcdbase, struct vidinfo *vid) +static void exynos_lcd_init(struct vidinfo *vid, ulong lcd_base) { - unsigned long palette_size; - unsigned int fb_size; - - fb_size = vid->vl_row * vid->vl_col * (NBITS(vid->vl_bpix) >> 3); - - palette_size = NBITS(vid->vl_bpix) == 8 ? 256 : 16; - - exynos_fimd_lcd_init_mem((unsigned long)lcdbase, - (unsigned long)fb_size, palette_size); -} - -static void exynos_lcd_init(struct vidinfo *vid) -{ - exynos_fimd_lcd_init(vid); + exynos_fimd_lcd_init(vid, lcd_base); /* Enable flushing after LCD writes if requested */ lcd_set_flush_dcache(1); @@ -297,9 +284,7 @@ void lcd_ctrl_init(void *lcdbase) panel_width = panel_info.vl_width; panel_height = panel_info.vl_height; - exynos_lcd_init_mem(lcdbase, &panel_info); - - exynos_lcd_init(&panel_info); + exynos_lcd_init(&panel_info, (ulong)lcdbase); } void lcd_enable(void) diff --git a/drivers/video/exynos/exynos_fb.h b/drivers/video/exynos/exynos_fb.h index 2c2f94b..833be6a 100644 --- a/drivers/video/exynos/exynos_fb.h +++ b/drivers/video/exynos/exynos_fb.h @@ -35,7 +35,7 @@ enum exynos_cpu_auto_cmd_rate { void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, unsigned long palette_size); -void exynos_fimd_lcd_init(vidinfo_t *vid); +void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address); unsigned long exynos_fimd_calc_fbsize(void); #endif diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c index e6fb5d1..a1de9ac 100644 --- a/drivers/video/exynos/exynos_fimd.c +++ b/drivers/video/exynos/exynos_fimd.c @@ -21,16 +21,9 @@ DECLARE_GLOBAL_DATA_PTR; -static unsigned long *lcd_base_addr; static struct vidinfo *pvid; static struct exynos_fb *fimd_ctrl; -void exynos_fimd_lcd_init_mem(u_long screen_base, u_long fb_size, - u_long palette_size) -{ - lcd_base_addr = (unsigned long *)screen_base; -} - static void exynos_fimd_set_dualrgb(unsigned int enabled) { unsigned int cfg = 0; @@ -47,7 +40,8 @@ static void exynos_fimd_set_dualrgb(unsigned int enabled) writel(cfg, &fimd_ctrl->dualrgb); } -static void exynos_fimd_set_dp_clkcon(unsigned int enabled) +static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, + unsigned int enabled) { unsigned int cfg = 0; @@ -57,7 +51,7 @@ static void exynos_fimd_set_dp_clkcon(unsigned int enabled) writel(cfg, &fimd_ctrl->dp_mie_clkcon); } -static void exynos_fimd_set_par(unsigned int win_id) +static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) { unsigned int cfg = 0; @@ -109,11 +103,13 @@ static void exynos_fimd_set_par(unsigned int win_id) EXYNOS_VIDOSD(win_id)); } -static void exynos_fimd_set_buffer_address(unsigned int win_id) +static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, + unsigned int win_id, + ulong lcd_base_addr) { unsigned long start_addr, end_addr; - start_addr = (unsigned long)lcd_base_addr; + start_addr = lcd_base_addr; end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * pvid->vl_row); @@ -289,7 +285,7 @@ void exynos_fimd_disable_sysmmu(void) } } -void exynos_fimd_lcd_init(struct vidinfo *vid) +void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address) { unsigned int cfg = 0, rgb_mode; unsigned int offset; @@ -367,10 +363,10 @@ void exynos_fimd_lcd_init(struct vidinfo *vid) writel(cfg, &fimd_ctrl->vidcon0); /* set par */ - exynos_fimd_set_par(pvid->win_id); + exynos_fimd_set_par(pvid, pvid->win_id); /* set memory address */ - exynos_fimd_set_buffer_address(pvid->win_id); + exynos_fimd_set_buffer_address(pvid, pvid->win_id, lcd_base_address); /* set buffer size */ cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | @@ -393,7 +389,7 @@ void exynos_fimd_lcd_init(struct vidinfo *vid) /* window on */ exynos_fimd_window_on(pvid->win_id); - exynos_fimd_set_dp_clkcon(pvid->dp_enabled); + exynos_fimd_set_dp_clkcon(pvid, pvid->dp_enabled); } unsigned long exynos_fimd_calc_fbsize(void) -- cgit v1.1 From 162fa53c8d3c2f832d791d0bb7a72fec1562fba4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:42 -0700 Subject: exynos: video: Drop static variables in exynos_fimd.c Drop these and use parameters instead. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.h | 2 +- drivers/video/exynos/exynos_fimd.c | 51 ++++++++++++++++++++++---------------- 2 files changed, 30 insertions(+), 23 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.h b/drivers/video/exynos/exynos_fb.h index 833be6a..f59cce0 100644 --- a/drivers/video/exynos/exynos_fb.h +++ b/drivers/video/exynos/exynos_fb.h @@ -36,6 +36,6 @@ enum exynos_cpu_auto_cmd_rate { void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, unsigned long palette_size); void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address); -unsigned long exynos_fimd_calc_fbsize(void); +unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid); #endif diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c index a1de9ac..039d4c5 100644 --- a/drivers/video/exynos/exynos_fimd.c +++ b/drivers/video/exynos/exynos_fimd.c @@ -21,11 +21,9 @@ DECLARE_GLOBAL_DATA_PTR; -static struct vidinfo *pvid; -static struct exynos_fb *fimd_ctrl; - -static void exynos_fimd_set_dualrgb(unsigned int enabled) +static void exynos_fimd_set_dualrgb(struct vidinfo *pvid, unsigned int enabled) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; if (enabled) { @@ -43,6 +41,7 @@ static void exynos_fimd_set_dualrgb(unsigned int enabled) static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, unsigned int enabled) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; if (enabled) @@ -53,6 +52,7 @@ static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; /* set window control */ @@ -107,6 +107,7 @@ static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, unsigned int win_id, ulong lcd_base_addr) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned long start_addr, end_addr; start_addr = lcd_base_addr; @@ -121,6 +122,7 @@ static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, static void exynos_fimd_set_clock(struct vidinfo *pvid) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0, div = 0, remainder, remainder_div; unsigned long pixel_clock; unsigned long long src_clock; @@ -172,8 +174,9 @@ static void exynos_fimd_set_clock(struct vidinfo *pvid) writel(cfg, &fimd_ctrl->vidcon0); } -void exynos_set_trigger(void) +void exynos_set_trigger(struct vidinfo *pvid) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; cfg = readl(&fimd_ctrl->trigcon); @@ -183,8 +186,9 @@ void exynos_set_trigger(void) writel(cfg, &fimd_ctrl->trigcon); } -int exynos_is_i80_frame_done(void) +int exynos_is_i80_frame_done(struct vidinfo *pvid) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; int status; @@ -197,8 +201,9 @@ int exynos_is_i80_frame_done(void) return status; } -static void exynos_fimd_lcd_on(void) +static void exynos_fimd_lcd_on(struct vidinfo *pvid) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; /* display on */ @@ -207,8 +212,9 @@ static void exynos_fimd_lcd_on(void) writel(cfg, &fimd_ctrl->vidcon0); } -static void exynos_fimd_window_on(unsigned int win_id) +static void exynos_fimd_window_on(struct vidinfo *pvid, unsigned int win_id) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; /* enable window */ @@ -223,8 +229,9 @@ static void exynos_fimd_window_on(unsigned int win_id) writel(cfg, &fimd_ctrl->winshmap); } -void exynos_fimd_lcd_off(void) +void exynos_fimd_lcd_off(struct vidinfo *pvid) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; cfg = readl(&fimd_ctrl->vidcon0); @@ -232,8 +239,9 @@ void exynos_fimd_lcd_off(void) writel(cfg, &fimd_ctrl->vidcon0); } -void exynos_fimd_window_off(unsigned int win_id) +void exynos_fimd_window_off(struct vidinfo *pvid, unsigned int win_id) { + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; unsigned int cfg = 0; cfg = readl((unsigned int)&fimd_ctrl->wincon0 + @@ -285,8 +293,9 @@ void exynos_fimd_disable_sysmmu(void) } } -void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address) +void exynos_fimd_lcd_init(struct vidinfo *pvid, ulong lcd_base_address) { + struct exynos_fb *fimd_ctrl; unsigned int cfg = 0, rgb_mode; unsigned int offset; unsigned int node; @@ -296,22 +305,20 @@ void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address) if (node <= 0) debug("exynos_fb: Can't get device node for fimd\n"); - fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); + fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, + "reg"); if (fimd_ctrl == NULL) debug("Can't get the FIMD base address\n"); + pvid->fimd_ctrl = fimd_ctrl; if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) exynos_fimd_disable_sysmmu(); offset = exynos_fimd_get_base_offset(); - /* store panel info to global variable */ - pvid = vid; - - rgb_mode = vid->rgb_mode; + rgb_mode = pvid->rgb_mode; - if (vid->interface_mode == FIMD_RGB_INTERFACE) { + if (pvid->interface_mode == FIMD_RGB_INTERFACE) { cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; writel(cfg, &fimd_ctrl->vidcon0); @@ -381,18 +388,18 @@ void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address) exynos_fimd_set_clock(pvid); /* set rgb mode to dual lcd. */ - exynos_fimd_set_dualrgb(pvid->dual_lcd_enabled); + exynos_fimd_set_dualrgb(pvid, pvid->dual_lcd_enabled); /* display on */ - exynos_fimd_lcd_on(); + exynos_fimd_lcd_on(pvid); /* window on */ - exynos_fimd_window_on(pvid->win_id); + exynos_fimd_window_on(pvid, pvid->win_id); exynos_fimd_set_dp_clkcon(pvid, pvid->dp_enabled); } -unsigned long exynos_fimd_calc_fbsize(void) +unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid) { return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); } -- cgit v1.1 From 9c4d440e859c34994689504f1a0d028619042ef3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:43 -0700 Subject: exynos: video: Drop static variables in exynos_fb.c Drop these and use the existing variables instead. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index a3acdcc..abc6091 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -26,8 +26,6 @@ DECLARE_GLOBAL_DATA_PTR; -static unsigned int panel_width, panel_height; - struct vidinfo panel_info = { /* * Insert a value here so that we don't end up in the BSS @@ -281,16 +279,14 @@ void lcd_ctrl_init(void *lcdbase) #endif exynos_lcd_misc_init(&panel_info); - panel_width = panel_info.vl_width; - panel_height = panel_info.vl_height; - exynos_lcd_init(&panel_info, (ulong)lcdbase); } void lcd_enable(void) { if (panel_info.logo_on) { - memset((void *) gd->fb_base, 0, panel_width * panel_height * + memset((void *)gd->fb_base, 0, + panel_info.vl_width * panel_info.vl_height * (NBITS(panel_info.vl_bpix) >> 3)); } -- cgit v1.1 From 8c9b8dc05aec6be390dae8a85da7cb56ed8b4ed9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:44 -0700 Subject: exynos: video: Drop static variables in exynos_dp_lowlevel.c Drop these and use parameters instead. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp.c | 310 +++++++++++++++++------------- drivers/video/exynos/exynos_dp_lowlevel.c | 195 ++++++++++--------- drivers/video/exynos/exynos_dp_lowlevel.h | 131 +++++++------ 3 files changed, 351 insertions(+), 285 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index 0d5d090..9945c4b 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -38,20 +38,20 @@ static void exynos_dp_disp_info(struct edp_disp_info *disp_info) return; } -static int exynos_dp_init_dp(void) +static int exynos_dp_init_dp(struct exynos_dp *dp_regs) { int ret; - exynos_dp_reset(); + exynos_dp_reset(dp_regs); /* SW defined function Normal operation */ - exynos_dp_enable_sw_func(DP_ENABLE); + exynos_dp_enable_sw_func(dp_regs, DP_ENABLE); - ret = exynos_dp_init_analog_func(); + ret = exynos_dp_init_analog_func(dp_regs); if (ret != EXYNOS_DP_SUCCESS) return ret; - exynos_dp_init_hpd(); - exynos_dp_init_aux(); + exynos_dp_init_hpd(dp_regs); + exynos_dp_init_aux(dp_regs); return ret; } @@ -67,7 +67,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) return sum; } -static unsigned int exynos_dp_read_edid(void) +static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) { unsigned char edid[EDID_BLOCK_LENGTH * 2]; unsigned int extend_block = 0; @@ -82,14 +82,15 @@ static unsigned int exynos_dp_read_edid(void) */ /* Read Extension Flag, Number of 128-byte EDID extension blocks */ - exynos_dp_read_byte_from_i2c(I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, - &extend_block); + exynos_dp_read_byte_from_i2c(dp_regs, I2C_EDID_DEVICE_ADDR, + EDID_EXTENSION_FLAG, &extend_block); if (extend_block > 0) { printf("DP EDID data includes a single extension!\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(dp_regs, + I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); @@ -104,7 +105,8 @@ static unsigned int exynos_dp_read_edid(void) } /* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(dp_regs, + I2C_EDID_DEVICE_ADDR, EDID_BLOCK_LENGTH, EDID_BLOCK_LENGTH, &edid[EDID_BLOCK_LENGTH]); @@ -118,19 +120,22 @@ static unsigned int exynos_dp_read_edid(void) return -1; } - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, - &test_vector); + exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_TEST_REQUEST, + &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, + exynos_dp_write_byte_to_dpcd(dp_regs, + DPCD_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + exynos_dp_write_byte_to_dpcd(dp_regs, + DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } } else { debug("DP EDID data does not include any extensions.\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(I2C_EDID_DEVICE_ADDR, + retval = exynos_dp_read_bytes_from_i2c(dp_regs, + I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); @@ -145,12 +150,13 @@ static unsigned int exynos_dp_read_edid(void) return -1; } - exynos_dp_read_byte_from_dpcd(DPCD_TEST_REQUEST, + exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_TEST_REQUEST, &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(DPCD_TEST_EDID_CHECKSUM, - edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(DPCD_TEST_RESPONSE, + exynos_dp_write_byte_to_dpcd(dp_regs, + DPCD_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd(dp_regs, + DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } } @@ -160,7 +166,8 @@ static unsigned int exynos_dp_read_edid(void) return 0; } -static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) +static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned char buf[12]; unsigned int ret; @@ -178,8 +185,8 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) retry_cnt = 5; while (retry_cnt) { /* Read DPCD 0x0000-0x000b */ - ret = exynos_dp_read_bytes_from_dpcd(DPCD_DPCD_REV, 12, - buf); + ret = exynos_dp_read_bytes_from_dpcd(dp_regs, DPCD_DPCD_REV, 12, + buf); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP read_byte_from_dpcd() failed\n"); @@ -227,7 +234,7 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) return -EINVAL; } - ret = exynos_dp_read_edid(); + ret = exynos_dp_read_edid(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_read_edid() failed\n"); return -EINVAL; @@ -236,19 +243,20 @@ static unsigned int exynos_dp_handle_edid(struct edp_device_info *edp_info) return ret; } -static void exynos_dp_init_training(void) +static void exynos_dp_init_training(struct exynos_dp *dp_regs) { /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ - exynos_dp_reset_macro(); + exynos_dp_reset_macro(dp_regs); /* All DP analog module power up */ - exynos_dp_set_analog_power_down(POWER_ALL, 0); + exynos_dp_set_analog_power_down(dp_regs, POWER_ALL, 0); } -static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) +static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned char buf[5]; unsigned int ret = 0; @@ -263,33 +271,32 @@ static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) edp_info->lt_info.cr_loop[3] = 0; /* Set sink to D0 (Sink Not Ready) mode. */ - ret = exynos_dp_write_byte_to_dpcd(DPCD_SINK_POWER_STATE, - DPCD_SET_POWER_STATE_D0); + ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_SINK_POWER_STATE, + DPCD_SET_POWER_STATE_D0); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; } /* Set link rate and count as you want to establish */ - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(dp_regs, edp_info->lane_bw); + exynos_dp_set_lane_count(dp_regs, edp_info->lane_cnt); /* Setup RX configuration */ buf[0] = edp_info->lane_bw; buf[1] = edp_info->lane_cnt; - ret = exynos_dp_write_bytes_to_dpcd(DPCD_LINK_BW_SET, 2, - buf); + ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_LINK_BW_SET, 2, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; } - exynos_dp_set_lane_pre_emphasis(PRE_EMPHASIS_LEVEL_0, + exynos_dp_set_lane_pre_emphasis(dp_regs, PRE_EMPHASIS_LEVEL_0, edp_info->lane_cnt); /* Set training pattern 1 */ - exynos_dp_set_training_pattern(TRAINING_PTN1); + exynos_dp_set_training_pattern(dp_regs, TRAINING_PTN1); /* Set RX training pattern */ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; @@ -303,8 +310,8 @@ static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - ret = exynos_dp_write_bytes_to_dpcd(DPCD_TRAINING_PATTERN_SET, - 5, buf); + ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; @@ -313,14 +320,14 @@ static unsigned int exynos_dp_link_start(struct edp_device_info *edp_info) return ret; } -static unsigned int exynos_dp_training_pattern_dis(void) +static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *dp_regs) { unsigned int ret = EXYNOS_DP_SUCCESS; - exynos_dp_set_training_pattern(DP_NONE); + exynos_dp_set_training_pattern(dp_regs, DP_NONE); - ret = exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, - DPCD_TRAINING_PATTERN_DISABLED); + ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + DPCD_TRAINING_PATTERN_DISABLED); if (ret != EXYNOS_DP_SUCCESS) { printf("DP request_link_training_req failed\n"); return -EAGAIN; @@ -329,13 +336,14 @@ static unsigned int exynos_dp_training_pattern_dis(void) return ret; } -static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) +static unsigned int exynos_dp_enable_rx_to_enhanced_mode( + struct exynos_dp *dp_regs, unsigned char enable) { unsigned char data; unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_read_byte_from_dpcd(DPCD_LANE_COUNT_SET, - &data); + ret = exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_LANE_COUNT_SET, + &data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read_from_dpcd failed\n"); return -EAGAIN; @@ -346,8 +354,7 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) else data = DPCD_LN_COUNT_SET(data); - ret = exynos_dp_write_byte_to_dpcd(DPCD_LANE_COUNT_SET, - data); + ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_LANE_COUNT_SET, data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_to_dpcd failed\n"); return -EAGAIN; @@ -357,23 +364,25 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode(unsigned char enable) return ret; } -static unsigned int exynos_dp_set_enhanced_mode(unsigned char enhance_mode) +static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *dp_regs, + unsigned char enhance_mode) { unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_enable_rx_to_enhanced_mode(enhance_mode); + ret = exynos_dp_enable_rx_to_enhanced_mode(dp_regs, enhance_mode); if (ret != EXYNOS_DP_SUCCESS) { printf("DP rx_enhance_mode failed\n"); return -EAGAIN; } - exynos_dp_enable_enhanced_mode(enhance_mode); + exynos_dp_enable_enhanced_mode(dp_regs, enhance_mode); return ret; } -static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, - unsigned char *status) +static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info, + unsigned char *status) { unsigned int ret, i; unsigned char buf[2]; @@ -385,7 +394,8 @@ static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, shift_val[2] = 0; shift_val[3] = 4; - ret = exynos_dp_read_bytes_from_dpcd(DPCD_LANE0_1_STATUS, 2, buf); + ret = exynos_dp_read_bytes_from_dpcd(dp_regs, DPCD_LANE0_1_STATUS, 2, + buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); return ret; @@ -404,8 +414,8 @@ static int exynos_dp_read_dpcd_lane_stat(struct edp_device_info *edp_info, return ret; } -static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, - unsigned char *sw, unsigned char *em) +static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *dp_regs, + unsigned char lane_num, unsigned char *sw, unsigned char *em) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char buf; @@ -415,7 +425,7 @@ static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, /* lane_num value is used as array index, so this range 0 ~ 3 */ dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); - ret = exynos_dp_read_byte_from_dpcd(dpcd_addr, &buf); + ret = exynos_dp_read_byte_from_dpcd(dp_regs, dpcd_addr, &buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adjust request failed\n"); return -EAGAIN; @@ -427,17 +437,18 @@ static unsigned int exynos_dp_read_dpcd_adj_req(unsigned char lane_num, return ret; } -static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) +static int exynos_dp_equalizer_err_link(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { int ret; - ret = exynos_dp_training_pattern_dis(); + ret = exynos_dp_training_pattern_dis(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP training_pattern_disable() failed\n"); edp_info->lt_info.lt_status = DP_LT_FAIL; } - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(dp_regs, edp_info->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set_enhanced_mode() failed\n"); edp_info->lt_info.lt_status = DP_LT_FAIL; @@ -446,7 +457,8 @@ static int exynos_dp_equalizer_err_link(struct edp_device_info *edp_info) return ret; } -static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) +static int exynos_dp_reduce_link_rate(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { int ret; @@ -456,11 +468,11 @@ static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) edp_info->lt_info.lt_status = DP_LT_START; ret = EXYNOS_DP_SUCCESS; } else { - ret = exynos_dp_training_pattern_dis(); + ret = exynos_dp_training_pattern_dis(dp_regs); if (ret != EXYNOS_DP_SUCCESS) printf("DP training_patter_disable() failed\n"); - ret = exynos_dp_set_enhanced_mode(edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(dp_regs, edp_info->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) printf("DP set_enhanced_mode() failed\n"); @@ -470,8 +482,8 @@ static int exynos_dp_reduce_link_rate(struct edp_device_info *edp_info) return ret; } -static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info - *edp_info) +static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat; @@ -484,7 +496,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info debug("DP: %s was called\n", __func__); mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(dp_regs, edp_info, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); edp_info->lt_info.lt_status = DP_LT_FAIL; @@ -493,11 +505,11 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info if (lane_stat & DP_LANE_STAT_CR_DONE) { debug("DP clock Recovery training succeed\n"); - exynos_dp_set_training_pattern(TRAINING_PTN2); + exynos_dp_set_training_pattern(dp_regs, TRAINING_PTN2); for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, &adj_req_sw, - &adj_req_em); + ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, + &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { edp_info->lt_info.lt_status = DP_LT_FAIL; return ret; @@ -511,7 +523,8 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + exynos_dp_set_lanex_pre_emphasis(dp_regs, + lt_ctl_val[i], i); } buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_2; @@ -520,7 +533,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info buf[3] = lt_ctl_val[2]; buf[4] = lt_ctl_val[3]; - ret = exynos_dp_write_bytes_to_dpcd( + ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern1 failed\n"); @@ -530,8 +543,9 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info edp_info->lt_info.lt_status = DP_LT_ET; } else { for (i = 0; i < edp_info->lane_cnt; i++) { - lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis(i); - ret = exynos_dp_read_dpcd_adj_req(i, + lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis( + dp_regs, i); + ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req failed\n"); @@ -541,7 +555,8 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info if ((adj_req_sw == VOLTAGE_LEVEL_3) || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) - ret = exynos_dp_reduce_link_rate(edp_info); + ret = exynos_dp_reduce_link_rate(dp_regs, + edp_info); if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == adj_req_sw) && @@ -550,7 +565,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info edp_info->lt_info.cr_loop[i]++; if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) ret = exynos_dp_reduce_link_rate( - edp_info); + dp_regs, edp_info); } lt_ctl_val[i] = 0; @@ -561,10 +576,11 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(lt_ctl_val[i], i); + exynos_dp_set_lanex_pre_emphasis(dp_regs, + lt_ctl_val[i], i); } - ret = exynos_dp_write_bytes_to_dpcd( + ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern2 failed\n"); @@ -576,8 +592,8 @@ static unsigned int exynos_dp_process_clock_recovery(struct edp_device_info return ret; } -static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info - *edp_info) +static unsigned int exynos_dp_process_equalizer_training( + struct exynos_dp *dp_regs, struct edp_device_info *edp_info) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat, adj_req_sw, adj_req_em, i; @@ -589,7 +605,7 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(dp_regs, edp_info, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); edp_info->lt_info.lt_status = DP_LT_FAIL; @@ -599,8 +615,9 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info debug("DP lane stat : %x\n", lane_stat); if (lane_stat & DP_LANE_STAT_CR_DONE) { - ret = exynos_dp_read_byte_from_dpcd(DPCD_LN_ALIGN_UPDATED, - &sink_stat); + ret = exynos_dp_read_byte_from_dpcd(dp_regs, + DPCD_LN_ALIGN_UPDATED, + &sink_stat); if (ret != EXYNOS_DP_SUCCESS) { edp_info->lt_info.lt_status = DP_LT_FAIL; @@ -610,7 +627,7 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(i, + ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req 1 failed\n"); @@ -634,15 +651,15 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { debug("DP Equalizer training succeed\n"); - f_bw = exynos_dp_get_link_bandwidth(); - f_lane_cnt = exynos_dp_get_lane_count(); + f_bw = exynos_dp_get_link_bandwidth(dp_regs); + f_lane_cnt = exynos_dp_get_lane_count(dp_regs); debug("DP final BandWidth : %x\n", f_bw); debug("DP final Lane Count : %x\n", f_lane_cnt); edp_info->lt_info.lt_status = DP_LT_FINISHED; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(dp_regs, edp_info); } else { edp_info->lt_info.ep_loop++; @@ -650,46 +667,49 @@ static unsigned int exynos_dp_process_equalizer_training(struct edp_device_info if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { if (edp_info->lane_bw == DP_LANE_BW_2_70) { ret = exynos_dp_reduce_link_rate( - edp_info); + dp_regs, edp_info); } else { edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(dp_regs, + edp_info); } } else { for (i = 0; i < edp_info->lane_cnt; i++) exynos_dp_set_lanex_pre_emphasis( - lt_ctl_val[i], i); + dp_regs, lt_ctl_val[i], i); - ret = exynos_dp_write_bytes_to_dpcd( - DPCD_TRAINING_LANE0_SET, - 4, lt_ctl_val); + ret = exynos_dp_write_bytes_to_dpcd(dp_regs, + DPCD_TRAINING_LANE0_SET, + 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set lt pattern failed\n"); edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(dp_regs, + edp_info); } } } } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { - ret = exynos_dp_reduce_link_rate(edp_info); + ret = exynos_dp_reduce_link_rate(dp_regs, edp_info); } else { edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(edp_info); + exynos_dp_equalizer_err_link(dp_regs, edp_info); } return ret; } -static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) +static unsigned int exynos_dp_sw_link_training(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned int ret = 0; int training_finished; /* Turn off unnecessary lane */ if (edp_info->lane_cnt == 1) - exynos_dp_set_analog_power_down(CH1_BLOCK, 1); + exynos_dp_set_analog_power_down(dp_regs, CH1_BLOCK, 1); training_finished = 0; @@ -699,21 +719,23 @@ static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) while (!training_finished) { switch (edp_info->lt_info.lt_status) { case DP_LT_START: - ret = exynos_dp_link_start(edp_info); + ret = exynos_dp_link_start(dp_regs, edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:link start failed\n"); return ret; } break; case DP_LT_CR: - ret = exynos_dp_process_clock_recovery(edp_info); + ret = exynos_dp_process_clock_recovery(dp_regs, + edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:clock recovery failed\n"); return ret; } break; case DP_LT_ET: - ret = exynos_dp_process_equalizer_training(edp_info); + ret = exynos_dp_process_equalizer_training(dp_regs, + edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:equalizer training failed\n"); return ret; @@ -730,40 +752,43 @@ static unsigned int exynos_dp_sw_link_training(struct edp_device_info *edp_info) return ret; } -static unsigned int exynos_dp_set_link_train(struct edp_device_info *edp_info) +static unsigned int exynos_dp_set_link_train(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned int ret; - exynos_dp_init_training(); + exynos_dp_init_training(dp_regs); - ret = exynos_dp_sw_link_training(edp_info); + ret = exynos_dp_sw_link_training(dp_regs, edp_info); if (ret != EXYNOS_DP_SUCCESS) printf("DP dp_sw_link_training() failed\n"); return ret; } -static void exynos_dp_enable_scramble(unsigned int enable) +static void exynos_dp_enable_scramble(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned char data; if (enable) { - exynos_dp_enable_scrambling(DP_ENABLE); + exynos_dp_enable_scrambling(dp_regs, DP_ENABLE); - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + exynos_dp_read_byte_from_dpcd(dp_regs, + DPCD_TRAINING_PATTERN_SET, &data); + exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); } else { - exynos_dp_enable_scrambling(DP_DISABLE); - exynos_dp_read_byte_from_dpcd(DPCD_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(DPCD_TRAINING_PATTERN_SET, + exynos_dp_enable_scrambling(dp_regs, DP_DISABLE); + exynos_dp_read_byte_from_dpcd(dp_regs, + DPCD_TRAINING_PATTERN_SET, &data); + exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, (u8)(data | DPCD_SCRAMBLING_DISABLED)); } } -static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) +static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned int ret = 0; unsigned int retry_cnt; @@ -775,17 +800,18 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) return -ENODEV; } else { /* debug slave */ - exynos_dp_config_video_slave_mode(&edp_info->video_info); + exynos_dp_config_video_slave_mode(dp_regs, + &edp_info->video_info); } - exynos_dp_set_video_color_format(&edp_info->video_info); + exynos_dp_set_video_color_format(dp_regs, &edp_info->video_info); if (edp_info->video_info.bist_mode) { - if (exynos_dp_config_video_bist(edp_info) != 0) + if (exynos_dp_config_video_bist(dp_regs, edp_info) != 0) return -1; } - ret = exynos_dp_get_pll_lock_status(); + ret = exynos_dp_get_pll_lock_status(dp_regs); if (ret != PLL_LOCKED) { printf("DP PLL is not locked yet\n"); return -EIO; @@ -794,7 +820,7 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) if (edp_info->video_info.master_mode == 0) { retry_cnt = 10; while (retry_cnt) { - ret = exynos_dp_is_slave_video_stream_clock_on(); + ret = exynos_dp_is_slave_video_stream_clock_on(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP stream_clock_on failed\n"); @@ -808,32 +834,34 @@ static unsigned int exynos_dp_config_video(struct edp_device_info *edp_info) } /* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(CALCULATED_M, 0, 0); + exynos_dp_set_video_cr_mn(dp_regs, CALCULATED_M, 0, 0); /* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(VIDEO_TIMING_FROM_CAPTURE); + exynos_dp_set_video_timing_mode(dp_regs, VIDEO_TIMING_FROM_CAPTURE); /* Enable video bist */ if (edp_info->video_info.bist_pattern != COLOR_RAMP && edp_info->video_info.bist_pattern != BALCK_WHITE_V_LINES && edp_info->video_info.bist_pattern != COLOR_SQUARE) - exynos_dp_enable_video_bist(edp_info->video_info.bist_mode); + exynos_dp_enable_video_bist(dp_regs, + edp_info->video_info.bist_mode); else - exynos_dp_enable_video_bist(DP_DISABLE); + exynos_dp_enable_video_bist(dp_regs, DP_DISABLE); /* Disable video mute */ - exynos_dp_enable_video_mute(DP_DISABLE); + exynos_dp_enable_video_mute(dp_regs, DP_DISABLE); /* Configure video Master or Slave mode */ - exynos_dp_enable_video_master(edp_info->video_info.master_mode); + exynos_dp_enable_video_master(dp_regs, + edp_info->video_info.master_mode); /* Enable video */ - exynos_dp_start_video(); + exynos_dp_start_video(dp_regs); if (edp_info->video_info.master_mode == 0) { retry_cnt = 100; while (retry_cnt) { - ret = exynos_dp_is_video_stream_on(); + ret = exynos_dp_is_video_stream_on(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Timeout of video stream\n"); @@ -907,6 +935,8 @@ unsigned int exynos_init_dp(void) { unsigned int ret; struct edp_device_info *edp_info; + struct exynos_dp *dp_regs; + int node; edp_info = kzalloc(sizeof(struct edp_device_info), GFP_KERNEL); if (!edp_info) { @@ -917,39 +947,47 @@ unsigned int exynos_init_dp(void) if (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) debug("unable to parse DP DT node\n"); - exynos_dp_set_base_addr(); + node = fdtdec_next_compatible(gd->fdt_blob, 0, + COMPAT_SAMSUNG_EXYNOS5_DP); + if (node <= 0) + debug("exynos_dp: Can't get device node for dp\n"); + + dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, node, + "reg"); + if (dp_regs == NULL) + debug("Can't get the DP base address\n"); exynos_dp_disp_info(&edp_info->disp_info); exynos_set_dp_phy(1); - ret = exynos_dp_init_dp(); + ret = exynos_dp_init_dp(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_init_dp() failed\n"); return ret; } - ret = exynos_dp_handle_edid(edp_info); + ret = exynos_dp_handle_edid(dp_regs, edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("EDP handle_edid fail\n"); return ret; } - ret = exynos_dp_set_link_train(edp_info); + ret = exynos_dp_set_link_train(dp_regs, edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("DP link training fail\n"); return ret; } - exynos_dp_enable_scramble(DP_ENABLE); - exynos_dp_enable_rx_to_enhanced_mode(DP_ENABLE); - exynos_dp_enable_enhanced_mode(DP_ENABLE); + exynos_dp_enable_scramble(dp_regs, DP_ENABLE); + exynos_dp_enable_rx_to_enhanced_mode(dp_regs, DP_ENABLE); + exynos_dp_enable_enhanced_mode(dp_regs, DP_ENABLE); - exynos_dp_set_link_bandwidth(edp_info->lane_bw); - exynos_dp_set_lane_count(edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(dp_regs, edp_info->lane_bw); + exynos_dp_set_lane_count(dp_regs, edp_info->lane_cnt); - exynos_dp_init_video(); - ret = exynos_dp_config_video(edp_info); + exynos_dp_init_video(dp_regs); + ret = exynos_dp_config_video(dp_regs, edp_info); if (ret != EXYNOS_DP_SUCCESS) { printf("Exynos DP init failed\n"); return ret; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c index e417cf8..153c1c6 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.c +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -14,26 +14,13 @@ #include #include #include +#include "exynos_dp_lowlevel.h" /* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR; -struct exynos_dp *dp_regs; - -void exynos_dp_set_base_addr(void) -{ - unsigned int node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) - debug("exynos_dp: Can't get device node for dp\n"); - - dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, - node, "reg"); - if (dp_regs == NULL) - debug("Can't get the DP base address\n"); -} - -static void exynos_dp_enable_video_input(unsigned int enable) +static void exynos_dp_enable_video_input(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -49,7 +36,7 @@ static void exynos_dp_enable_video_input(unsigned int enable) return; } -void exynos_dp_enable_video_bist(unsigned int enable) +void exynos_dp_enable_video_bist(struct exynos_dp *dp_regs, unsigned int enable) { /* enable video bist */ unsigned int reg; @@ -66,7 +53,7 @@ void exynos_dp_enable_video_bist(unsigned int enable) return; } -void exynos_dp_enable_video_mute(unsigned int enable) +void exynos_dp_enable_video_mute(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -81,7 +68,7 @@ void exynos_dp_enable_video_mute(unsigned int enable) } -static void exynos_dp_init_analog_param(void) +static void exynos_dp_init_analog_param(struct exynos_dp *dp_regs) { unsigned int reg; @@ -130,7 +117,7 @@ static void exynos_dp_init_analog_param(void) writel(reg, &dp_regs->pll_ctl); } -static void exynos_dp_init_interrupt(void) +static void exynos_dp_init_interrupt(struct exynos_dp *dp_regs) { /* Set interrupt registers to initial states */ @@ -157,16 +144,16 @@ static void exynos_dp_init_interrupt(void) writel(0x00, &dp_regs->int_sta_mask); } -void exynos_dp_reset(void) +void exynos_dp_reset(struct exynos_dp *dp_regs) { unsigned int reg_func_1; /* dp tx sw reset */ writel(RESET_DP_TX, &dp_regs->tx_sw_reset); - exynos_dp_enable_video_input(DP_DISABLE); - exynos_dp_enable_video_bist(DP_DISABLE); - exynos_dp_enable_video_mute(DP_DISABLE); + exynos_dp_enable_video_input(dp_regs, DP_DISABLE); + exynos_dp_enable_video_bist(dp_regs, DP_DISABLE); + exynos_dp_enable_video_mute(dp_regs, DP_DISABLE); /* software reset */ reg_func_1 = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | @@ -178,13 +165,13 @@ void exynos_dp_reset(void) mdelay(1); - exynos_dp_init_analog_param(); - exynos_dp_init_interrupt(); + exynos_dp_init_analog_param(dp_regs); + exynos_dp_init_interrupt(dp_regs); return; } -void exynos_dp_enable_sw_func(unsigned int enable) +void exynos_dp_enable_sw_func(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -199,7 +186,8 @@ void exynos_dp_enable_sw_func(unsigned int enable) return; } -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) +unsigned int exynos_dp_set_analog_power_down(struct exynos_dp *dp_regs, + unsigned int block, u32 enable) { unsigned int reg; @@ -252,7 +240,7 @@ unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable) return 0; } -unsigned int exynos_dp_get_pll_lock_status(void) +unsigned int exynos_dp_get_pll_lock_status(struct exynos_dp *dp_regs) { unsigned int reg; @@ -264,7 +252,8 @@ unsigned int exynos_dp_get_pll_lock_status(void) return PLL_UNLOCKED; } -static void exynos_dp_set_pll_power(unsigned int enable) +static void exynos_dp_set_pll_power(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -277,14 +266,14 @@ static void exynos_dp_set_pll_power(unsigned int enable) writel(reg, &dp_regs->pll_ctl); } -int exynos_dp_init_analog_func(void) +int exynos_dp_init_analog_func(struct exynos_dp *dp_regs) { int ret = EXYNOS_DP_SUCCESS; unsigned int retry_cnt = 10; unsigned int reg; /* Power On All Analog block */ - exynos_dp_set_analog_power_down(POWER_ALL, DP_DISABLE); + exynos_dp_set_analog_power_down(dp_regs, POWER_ALL, DP_DISABLE); reg = PLL_LOCK_CHG; writel(reg, &dp_regs->common_int_sta1); @@ -305,9 +294,9 @@ int exynos_dp_init_analog_func(void) reg &= ~(DP_PLL_RESET); writel(reg, &dp_regs->pll_ctl); - exynos_dp_set_pll_power(DP_ENABLE); + exynos_dp_set_pll_power(dp_regs, DP_ENABLE); - while (exynos_dp_get_pll_lock_status() == PLL_UNLOCKED) { + while (exynos_dp_get_pll_lock_status(dp_regs) == PLL_UNLOCKED) { mdelay(1); retry_cnt--; if (retry_cnt == 0) { @@ -328,7 +317,7 @@ int exynos_dp_init_analog_func(void) return ret; } -void exynos_dp_init_hpd(void) +void exynos_dp_init_hpd(struct exynos_dp *dp_regs) { unsigned int reg; @@ -346,7 +335,7 @@ void exynos_dp_init_hpd(void) return; } -static inline void exynos_dp_reset_aux(void) +static inline void exynos_dp_reset_aux(struct exynos_dp *dp_regs) { unsigned int reg; @@ -358,7 +347,7 @@ static inline void exynos_dp_reset_aux(void) return; } -void exynos_dp_init_aux(void) +void exynos_dp_init_aux(struct exynos_dp *dp_regs) { unsigned int reg; @@ -366,7 +355,7 @@ void exynos_dp_init_aux(void) reg = RPLY_RECEIV | AUX_ERR; writel(reg, &dp_regs->int_sta); - exynos_dp_reset_aux(); + exynos_dp_reset_aux(dp_regs); /* Disable AUX transaction H/W retry */ reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(3)| @@ -385,7 +374,7 @@ void exynos_dp_init_aux(void) return; } -void exynos_dp_config_interrupt(void) +void exynos_dp_config_interrupt(struct exynos_dp *dp_regs) { unsigned int reg; @@ -408,7 +397,7 @@ void exynos_dp_config_interrupt(void) return; } -unsigned int exynos_dp_get_plug_in_status(void) +unsigned int exynos_dp_get_plug_in_status(struct exynos_dp *dp_regs) { unsigned int reg; @@ -419,13 +408,13 @@ unsigned int exynos_dp_get_plug_in_status(void) return -1; } -unsigned int exynos_dp_detect_hpd(void) +unsigned int exynos_dp_detect_hpd(struct exynos_dp *dp_regs) { int timeout_loop = DP_TIMEOUT_LOOP_COUNT; mdelay(2); - while (exynos_dp_get_plug_in_status() != 0) { + while (exynos_dp_get_plug_in_status(dp_regs) != 0) { if (timeout_loop == 0) return -EINVAL; mdelay(10); @@ -435,7 +424,7 @@ unsigned int exynos_dp_detect_hpd(void) return EXYNOS_DP_SUCCESS; } -unsigned int exynos_dp_start_aux_transaction(void) +unsigned int exynos_dp_start_aux_transaction(struct exynos_dp *dp_regs) { unsigned int reg; unsigned int ret = 0; @@ -484,8 +473,9 @@ unsigned int exynos_dp_start_aux_transaction(void) return EXYNOS_DP_SUCCESS; } -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data) +unsigned int exynos_dp_write_byte_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char data) { unsigned int reg, ret; @@ -514,7 +504,7 @@ unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP Aux transaction failed\n"); return ret; @@ -523,8 +513,9 @@ unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, return ret; } -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data) +unsigned int exynos_dp_read_byte_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char *data) { unsigned int reg; int retval; @@ -550,7 +541,7 @@ unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (!retval) debug("DP Aux Transaction fail!\n"); @@ -561,9 +552,10 @@ unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, return retval; } -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) +unsigned int exynos_dp_write_bytes_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { unsigned int reg; unsigned int start_offset; @@ -610,7 +602,7 @@ unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Aux Transaction failed\n"); @@ -626,9 +618,10 @@ unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, return ret; } -unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]) +unsigned int exynos_dp_read_bytes_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { unsigned int reg; unsigned int start_offset; @@ -668,7 +661,7 @@ unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - ret = exynos_dp_start_aux_transaction(); + ret = exynos_dp_start_aux_transaction(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Aux Transaction failed\n"); @@ -692,8 +685,8 @@ unsigned int exynos_dp_read_bytes_from_dpcd(unsigned int reg_addr, return ret; } -int exynos_dp_select_i2c_device(unsigned int device_addr, - unsigned int reg_addr) +int exynos_dp_select_i2c_device(struct exynos_dp *dp_regs, + unsigned int device_addr, unsigned int reg_addr) { unsigned int reg; int retval; @@ -717,16 +710,16 @@ int exynos_dp_select_i2c_device(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (retval != 0) printf("%s: DP Aux Transaction fail!\n", __func__); return retval; } -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data) +int exynos_dp_read_byte_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int *data) { unsigned int reg; int i; @@ -738,7 +731,8 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->buffer_data_ctl); /* Select EDID device */ - retval = exynos_dp_select_i2c_device(device_addr, reg_addr); + retval = exynos_dp_select_i2c_device(dp_regs, device_addr, + reg_addr); if (retval != 0) { printf("DP Select EDID device fail. retry !\n"); continue; @@ -754,7 +748,7 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction(dp_regs); if (retval != EXYNOS_DP_SUCCESS) printf("%s: DP Aux Transaction fail!\n", __func__); } @@ -766,8 +760,10 @@ int exynos_dp_read_byte_from_i2c(unsigned int device_addr, return retval; } -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, unsigned char edid[]) +int exynos_dp_read_bytes_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int count, + unsigned char edid[]) { unsigned int reg; unsigned int i, j; @@ -791,9 +787,8 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, * request without sending addres */ if (!defer) - retval = - exynos_dp_select_i2c_device(device_addr, - reg_addr + i); + retval = exynos_dp_select_i2c_device( + dp_regs, device_addr, reg_addr + i); else defer = 0; @@ -809,7 +804,8 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(); + retval = exynos_dp_start_aux_transaction( + dp_regs); if (retval == 0) break; else @@ -834,7 +830,7 @@ int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, return retval; } -void exynos_dp_reset_macro(void) +void exynos_dp_reset_macro(struct exynos_dp *dp_regs) { unsigned int reg; @@ -849,7 +845,8 @@ void exynos_dp_reset_macro(void) writel(reg, &dp_regs->phy_test); } -void exynos_dp_set_link_bandwidth(unsigned char bwtype) +void exynos_dp_set_link_bandwidth(struct exynos_dp *dp_regs, + unsigned char bwtype) { unsigned int reg; @@ -860,7 +857,7 @@ void exynos_dp_set_link_bandwidth(unsigned char bwtype) writel(reg, &dp_regs->link_bw_set); } -unsigned char exynos_dp_get_link_bandwidth(void) +unsigned char exynos_dp_get_link_bandwidth(struct exynos_dp *dp_regs) { unsigned char ret; unsigned int reg; @@ -871,7 +868,7 @@ unsigned char exynos_dp_get_link_bandwidth(void) return ret; } -void exynos_dp_set_lane_count(unsigned char count) +void exynos_dp_set_lane_count(struct exynos_dp *dp_regs, unsigned char count) { unsigned int reg; @@ -882,7 +879,7 @@ void exynos_dp_set_lane_count(unsigned char count) writel(reg, &dp_regs->lane_count_set); } -unsigned int exynos_dp_get_lane_count(void) +unsigned int exynos_dp_get_lane_count(struct exynos_dp *dp_regs) { unsigned int reg; @@ -891,7 +888,8 @@ unsigned int exynos_dp_get_lane_count(void) return reg; } -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) +unsigned char exynos_dp_get_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char lanecnt) { unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, @@ -903,8 +901,9 @@ unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt) return readl(reg_list[lanecnt]); } -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt) +void exynos_dp_set_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char request_val, + unsigned char lanecnt) { unsigned int reg_list[DP_LANE_CNT_4] = { (unsigned int)&dp_regs->ln0_link_training_ctl, @@ -916,7 +915,8 @@ void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, writel(request_val, reg_list[lanecnt]); } -void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) +void exynos_dp_set_lane_pre_emphasis(struct exynos_dp *dp_regs, + unsigned int level, unsigned char lanecnt) { unsigned char i; unsigned int reg; @@ -939,7 +939,8 @@ void exynos_dp_set_lane_pre_emphasis(unsigned int level, unsigned char lanecnt) } } -void exynos_dp_set_training_pattern(unsigned int pattern) +void exynos_dp_set_training_pattern(struct exynos_dp *dp_regs, + unsigned int pattern) { unsigned int reg = 0; @@ -967,7 +968,8 @@ void exynos_dp_set_training_pattern(unsigned int pattern) writel(reg, &dp_regs->training_ptn_set); } -void exynos_dp_enable_enhanced_mode(unsigned char enable) +void exynos_dp_enable_enhanced_mode(struct exynos_dp *dp_regs, + unsigned char enable) { unsigned int reg; @@ -980,7 +982,7 @@ void exynos_dp_enable_enhanced_mode(unsigned char enable) writel(reg, &dp_regs->sys_ctl4); } -void exynos_dp_enable_scrambling(unsigned int enable) +void exynos_dp_enable_scrambling(struct exynos_dp *dp_regs, unsigned int enable) { unsigned int reg; @@ -993,7 +995,7 @@ void exynos_dp_enable_scrambling(unsigned int enable) writel(reg, &dp_regs->training_ptn_set); } -int exynos_dp_init_video(void) +int exynos_dp_init_video(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1008,7 +1010,8 @@ int exynos_dp_init_video(void) return 0; } -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) +void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, + struct edp_video_info *video_info) { unsigned int reg; @@ -1041,7 +1044,8 @@ void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info) writel(reg, &dp_regs->soc_general_ctl); } -void exynos_dp_set_video_color_format(struct edp_video_info *video_info) +void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, + struct edp_video_info *video_info) { unsigned int reg; @@ -1061,7 +1065,8 @@ void exynos_dp_set_video_color_format(struct edp_video_info *video_info) writel(reg, &dp_regs->video_ctl3); } -int exynos_dp_config_video_bist(struct edp_device_info *edp_info) +int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info) { unsigned int reg; unsigned int bist_type = 0; @@ -1151,7 +1156,7 @@ int exynos_dp_config_video_bist(struct edp_device_info *edp_info) return 0; } -unsigned int exynos_dp_is_slave_video_stream_clock_on(void) +unsigned int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1169,8 +1174,8 @@ unsigned int exynos_dp_is_slave_video_stream_clock_on(void) return EXYNOS_DP_SUCCESS; } -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value) +void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, + unsigned int m_value, unsigned int n_value) { unsigned int reg; @@ -1198,7 +1203,8 @@ void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, } } -void exynos_dp_set_video_timing_mode(unsigned int type) +void exynos_dp_set_video_timing_mode(struct exynos_dp *dp_regs, + unsigned int type) { unsigned int reg; @@ -1211,7 +1217,8 @@ void exynos_dp_set_video_timing_mode(unsigned int type) writel(reg, &dp_regs->video_ctl10); } -void exynos_dp_enable_video_master(unsigned int enable) +void exynos_dp_enable_video_master(struct exynos_dp *dp_regs, + unsigned int enable) { unsigned int reg; @@ -1227,7 +1234,7 @@ void exynos_dp_enable_video_master(unsigned int enable) writel(reg, &dp_regs->soc_general_ctl); } -void exynos_dp_start_video(void) +void exynos_dp_start_video(struct exynos_dp *dp_regs) { unsigned int reg; @@ -1237,7 +1244,7 @@ void exynos_dp_start_video(void) writel(reg, &dp_regs->video_ctl1); } -unsigned int exynos_dp_is_video_stream_on(void) +unsigned int exynos_dp_is_video_stream_on(struct exynos_dp *dp_regs) { unsigned int reg; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.h b/drivers/video/exynos/exynos_dp_lowlevel.h index 8651681..85459b5 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.h +++ b/drivers/video/exynos/exynos_dp_lowlevel.h @@ -9,60 +9,81 @@ #ifndef _EXYNOS_EDP_LOWLEVEL_H #define _EXYNOS_EDP_LOWLEVEL_H -void exynos_dp_enable_video_bist(unsigned int enable); -void exynos_dp_enable_video_mute(unsigned int enable); -void exynos_dp_reset(void); -void exynos_dp_enable_sw_func(unsigned int enable); -unsigned int exynos_dp_set_analog_power_down(unsigned int block, u32 enable); -unsigned int exynos_dp_get_pll_lock_status(void); -int exynos_dp_init_analog_func(void); -void exynos_dp_init_hpd(void); -void exynos_dp_init_aux(void); -void exynos_dp_config_interrupt(void); -unsigned int exynos_dp_get_plug_in_status(void); -unsigned int exynos_dp_detect_hpd(void); -unsigned int exynos_dp_start_aux_transaction(void); -unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, - unsigned char data); -unsigned int exynos_dp_read_byte_from_dpcd(unsigned int reg_addr, - unsigned char *data); -unsigned int exynos_dp_write_bytes_to_dpcd(unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -unsigned int exynos_dp_read_bytes_from_dpcd( unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_select_i2c_device( unsigned int device_addr, - unsigned int reg_addr); -int exynos_dp_read_byte_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int *data); -int exynos_dp_read_bytes_from_i2c(unsigned int device_addr, - unsigned int reg_addr, unsigned int count, - unsigned char edid[]); -void exynos_dp_reset_macro(void); -void exynos_dp_set_link_bandwidth(unsigned char bwtype); -unsigned char exynos_dp_get_link_bandwidth(void); -void exynos_dp_set_lane_count(unsigned char count); -unsigned int exynos_dp_get_lane_count(void); -unsigned char exynos_dp_get_lanex_pre_emphasis(unsigned char lanecnt); -void exynos_dp_set_lane_pre_emphasis(unsigned int level, - unsigned char lanecnt); -void exynos_dp_set_lanex_pre_emphasis(unsigned char request_val, - unsigned char lanecnt); -void exynos_dp_set_training_pattern(unsigned int pattern); -void exynos_dp_enable_enhanced_mode(unsigned char enable); -void exynos_dp_enable_scrambling(unsigned int enable); -int exynos_dp_init_video(void); -void exynos_dp_config_video_slave_mode(struct edp_video_info *video_info); -void exynos_dp_set_video_color_format(struct edp_video_info *video_info); -int exynos_dp_config_video_bist(struct edp_device_info *edp_info); -unsigned int exynos_dp_is_slave_video_stream_clock_on(void); -void exynos_dp_set_video_cr_mn(unsigned int type, unsigned int m_value, - unsigned int n_value); -void exynos_dp_set_video_timing_mode(unsigned int type); -void exynos_dp_enable_video_master(unsigned int enable); -void exynos_dp_start_video(void); -unsigned int exynos_dp_is_video_stream_on(void); -void exynos_dp_set_base_addr(void); +void exynos_dp_enable_video_bist(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_enable_video_mute(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_reset(struct exynos_dp *dp_regs); +void exynos_dp_enable_sw_func(struct exynos_dp *dp_regs, unsigned int enable); +unsigned int exynos_dp_set_analog_power_down(struct exynos_dp *dp_regs, + unsigned int block, u32 enable); +unsigned int exynos_dp_get_pll_lock_status(struct exynos_dp *dp_regs); +int exynos_dp_init_analog_func(struct exynos_dp *dp_regs); +void exynos_dp_init_hpd(struct exynos_dp *dp_regs); +void exynos_dp_init_aux(struct exynos_dp *dp_regs); +void exynos_dp_config_interrupt(struct exynos_dp *dp_regs); +unsigned int exynos_dp_get_plug_in_status(struct exynos_dp *dp_regs); +unsigned int exynos_dp_detect_hpd(struct exynos_dp *dp_regs); +unsigned int exynos_dp_start_aux_transaction(struct exynos_dp *dp_regs); +unsigned int exynos_dp_write_byte_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char data); +unsigned int exynos_dp_read_byte_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned char *data); +unsigned int exynos_dp_write_bytes_to_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +unsigned int exynos_dp_read_bytes_from_dpcd(struct exynos_dp *dp_regs, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int exynos_dp_select_i2c_device(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr); +int exynos_dp_read_byte_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int *data); +int exynos_dp_read_bytes_from_i2c(struct exynos_dp *dp_regs, + unsigned int device_addr, + unsigned int reg_addr, unsigned int count, + unsigned char edid[]); +void exynos_dp_reset_macro(struct exynos_dp *dp_regs); +void exynos_dp_set_link_bandwidth(struct exynos_dp *dp_regs, + unsigned char bwtype); +unsigned char exynos_dp_get_link_bandwidth(struct exynos_dp *dp_regs); +void exynos_dp_set_lane_count(struct exynos_dp *dp_regs, unsigned char count); +unsigned int exynos_dp_get_lane_count(struct exynos_dp *dp_regs); +unsigned char exynos_dp_get_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char lanecnt); +void exynos_dp_set_lane_pre_emphasis(struct exynos_dp *dp_regs, + unsigned int level, unsigned char lanecnt); +void exynos_dp_set_lanex_pre_emphasis(struct exynos_dp *dp_regs, + unsigned char request_val, + unsigned char lanecnt); +void exynos_dp_set_training_pattern(struct exynos_dp *dp_regs, + unsigned int pattern); +void exynos_dp_enable_enhanced_mode(struct exynos_dp *dp_regs, + unsigned char enable); +void exynos_dp_enable_scrambling(struct exynos_dp *dp_regs, + unsigned int enable); +int exynos_dp_init_video(struct exynos_dp *dp_regs); +void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, + struct edp_video_info *video_info); +void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, + struct edp_video_info *video_info); +int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, + struct edp_device_info *edp_info); +unsigned int exynos_dp_is_slave_video_stream_clock_on( + struct exynos_dp *dp_regs); +void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, + unsigned int m_value, unsigned int n_value); +void exynos_dp_set_video_timing_mode(struct exynos_dp *dp_regs, + unsigned int type); +void exynos_dp_enable_video_master(struct exynos_dp *dp_regs, + unsigned int enable); +void exynos_dp_start_video(struct exynos_dp *dp_regs); +unsigned int exynos_dp_is_video_stream_on(struct exynos_dp *dp_regs); #endif /* _EXYNOS_DP_LOWLEVEL_H */ -- cgit v1.1 From b04135c998b88b0d7c1f21fef64219c508dfbcad Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:45 -0700 Subject: exynos: video: Move dsim_config_dt into a function In preparation for making this a parameter, move it into the function that sets it up. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_mipi_dsi.c | 37 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index 5001e16..fd96382 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -28,7 +28,6 @@ DECLARE_GLOBAL_DATA_PTR; static struct exynos_platform_mipi_dsim *dsim_pd; -static struct mipi_dsim_config dsim_config_dt; static struct exynos_platform_mipi_dsim dsim_platform_data_dt; static struct mipi_dsim_lcd_device mipi_lcd_device_dt; @@ -247,7 +246,7 @@ void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) dsim_pd = pd; } -int exynos_dsim_config_parse_dt(const void *blob) +int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt) { int node; @@ -257,47 +256,47 @@ int exynos_dsim_config_parse_dt(const void *blob) return -ENODEV; } - dsim_config_dt.e_interface = fdtdec_get_int(blob, node, + dt->e_interface = fdtdec_get_int(blob, node, "samsung,dsim-config-e-interface", 0); - dsim_config_dt.e_virtual_ch = fdtdec_get_int(blob, node, + dt->e_virtual_ch = fdtdec_get_int(blob, node, "samsung,dsim-config-e-virtual-ch", 0); - dsim_config_dt.e_pixel_format = fdtdec_get_int(blob, node, + dt->e_pixel_format = fdtdec_get_int(blob, node, "samsung,dsim-config-e-pixel-format", 0); - dsim_config_dt.e_burst_mode = fdtdec_get_int(blob, node, + dt->e_burst_mode = fdtdec_get_int(blob, node, "samsung,dsim-config-e-burst-mode", 0); - dsim_config_dt.e_no_data_lane = fdtdec_get_int(blob, node, + dt->e_no_data_lane = fdtdec_get_int(blob, node, "samsung,dsim-config-e-no-data-lane", 0); - dsim_config_dt.e_byte_clk = fdtdec_get_int(blob, node, + dt->e_byte_clk = fdtdec_get_int(blob, node, "samsung,dsim-config-e-byte-clk", 0); - dsim_config_dt.hfp = fdtdec_get_int(blob, node, + dt->hfp = fdtdec_get_int(blob, node, "samsung,dsim-config-hfp", 0); - dsim_config_dt.p = fdtdec_get_int(blob, node, + dt->p = fdtdec_get_int(blob, node, "samsung,dsim-config-p", 0); - dsim_config_dt.m = fdtdec_get_int(blob, node, + dt->m = fdtdec_get_int(blob, node, "samsung,dsim-config-m", 0); - dsim_config_dt.s = fdtdec_get_int(blob, node, + dt->s = fdtdec_get_int(blob, node, "samsung,dsim-config-s", 0); - dsim_config_dt.pll_stable_time = fdtdec_get_int(blob, node, + dt->pll_stable_time = fdtdec_get_int(blob, node, "samsung,dsim-config-pll-stable-time", 0); - dsim_config_dt.esc_clk = fdtdec_get_int(blob, node, + dt->esc_clk = fdtdec_get_int(blob, node, "samsung,dsim-config-esc-clk", 0); - dsim_config_dt.stop_holding_cnt = fdtdec_get_int(blob, node, + dt->stop_holding_cnt = fdtdec_get_int(blob, node, "samsung,dsim-config-stop-holding-cnt", 0); - dsim_config_dt.bta_timeout = fdtdec_get_int(blob, node, + dt->bta_timeout = fdtdec_get_int(blob, node, "samsung,dsim-config-bta-timeout", 0); - dsim_config_dt.rx_timeout = fdtdec_get_int(blob, node, + dt->rx_timeout = fdtdec_get_int(blob, node, "samsung,dsim-config-rx-timeout", 0); mipi_lcd_device_dt.name = fdtdec_get_config_string(blob, @@ -317,7 +316,9 @@ int exynos_dsim_config_parse_dt(const void *blob) void exynos_init_dsim_platform_data(vidinfo_t *vid) { - if (exynos_dsim_config_parse_dt(gd->fdt_blob)) + struct mipi_dsim_config dsim_config_dt; + + if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt)) debug("Can't get proper dsim config.\n"); strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name); -- cgit v1.1 From 652d15c06e65ea910bada28925b37483b2a1a0d6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:46 -0700 Subject: exynos: video: Move struct exynos_platform_mipi_dsim into vidinfo Put the pointer to this structure in struct vidinfo so that we can reference it without it being global. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.c | 2 +- drivers/video/exynos/exynos_mipi_dsi.c | 19 ++++--------------- 2 files changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index abc6091..22b9723 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -128,7 +128,7 @@ static void lcd_panel_on(struct vidinfo *vid) exynos_enable_ldo(1); if (vid->mipi_enabled) - exynos_mipi_dsi_init(); + exynos_mipi_dsi_init(panel_info.dsim_platform_data_dt); } int exynos_lcd_early_init(const void *blob) diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index fd96382..b39858a 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -27,8 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct exynos_platform_mipi_dsim *dsim_pd; -static struct exynos_platform_mipi_dsim dsim_platform_data_dt; static struct mipi_dsim_lcd_device mipi_lcd_device_dt; struct mipi_dsim_ddi { @@ -175,7 +173,7 @@ static struct mipi_dsim_master_ops master_ops = { .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done, }; -int exynos_mipi_dsi_init(void) +int exynos_mipi_dsi_init(struct exynos_platform_mipi_dsim *dsim_pd) { struct mipi_dsim_device *dsim; struct mipi_dsim_config *dsim_config; @@ -236,16 +234,6 @@ int exynos_mipi_dsi_init(void) return 0; } -void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd) -{ - if (pd == NULL) { - debug("pd is NULL\n"); - return; - } - - dsim_pd = pd; -} - int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt) { int node; @@ -316,7 +304,8 @@ int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt) void exynos_init_dsim_platform_data(vidinfo_t *vid) { - struct mipi_dsim_config dsim_config_dt; + static struct mipi_dsim_config dsim_config_dt; + static struct exynos_platform_mipi_dsim dsim_platform_data_dt; if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt)) debug("Can't get proper dsim config.\n"); @@ -330,5 +319,5 @@ void exynos_init_dsim_platform_data(vidinfo_t *vid) mipi_lcd_device_dt.platform_data = (void *)&dsim_platform_data_dt; exynos_mipi_dsi_register_lcd_device(&mipi_lcd_device_dt); - dsim_pd = &dsim_platform_data_dt; + vid->dsim_platform_data_dt = &dsim_platform_data_dt; } -- cgit v1.1 From 37ea446b9d7942c0deb5833fede6eb7cabd5bc6d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:47 -0700 Subject: exynos: video: Move mipi_lcd_device_dt into a function In preparation for making this a parameter, move it into the function that sets it up. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_mipi_dsi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c index b39858a..a5d9b59 100644 --- a/drivers/video/exynos/exynos_mipi_dsi.c +++ b/drivers/video/exynos/exynos_mipi_dsi.c @@ -27,8 +27,6 @@ DECLARE_GLOBAL_DATA_PTR; -static struct mipi_dsim_lcd_device mipi_lcd_device_dt; - struct mipi_dsim_ddi { int bus_id; struct list_head list; @@ -234,7 +232,8 @@ int exynos_mipi_dsi_init(struct exynos_platform_mipi_dsim *dsim_pd) return 0; } -int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt) +int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt, + struct mipi_dsim_lcd_device *lcd_dt) { int node; @@ -287,16 +286,16 @@ int exynos_dsim_config_parse_dt(const void *blob, struct mipi_dsim_config *dt) dt->rx_timeout = fdtdec_get_int(blob, node, "samsung,dsim-config-rx-timeout", 0); - mipi_lcd_device_dt.name = fdtdec_get_config_string(blob, + lcd_dt->name = fdtdec_get_config_string(blob, "samsung,dsim-device-name"); - mipi_lcd_device_dt.id = fdtdec_get_int(blob, node, + lcd_dt->id = fdtdec_get_int(blob, node, "samsung,dsim-device-id", 0); - mipi_lcd_device_dt.bus_id = fdtdec_get_int(blob, node, + lcd_dt->bus_id = fdtdec_get_int(blob, node, "samsung,dsim-device-bus_id", 0); - mipi_lcd_device_dt.reverse_panel = fdtdec_get_int(blob, node, + lcd_dt->reverse_panel = fdtdec_get_int(blob, node, "samsung,dsim-device-reverse-panel", 0); return 0; @@ -306,8 +305,10 @@ void exynos_init_dsim_platform_data(vidinfo_t *vid) { static struct mipi_dsim_config dsim_config_dt; static struct exynos_platform_mipi_dsim dsim_platform_data_dt; + static struct mipi_dsim_lcd_device mipi_lcd_device_dt; - if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt)) + if (exynos_dsim_config_parse_dt(gd->fdt_blob, &dsim_config_dt, + &mipi_lcd_device_dt)) debug("Can't get proper dsim config.\n"); strcpy(dsim_platform_data_dt.lcd_panel_name, mipi_lcd_device_dt.name); -- cgit v1.1 From 0c84358cb240953b467034a52fcc2f459ba4029b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:48 -0700 Subject: exynos: video: Combine LCD driver into one file At present exynos_fimd.c is the controller and exynos_fb.c is the U-Boot LCD interface. With driver model we want these in one file, so join them in preparation. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/Makefile | 2 +- drivers/video/exynos/exynos_fb.c | 386 +++++++++++++++++++++++++++++++++++ drivers/video/exynos/exynos_fimd.c | 405 ------------------------------------- 3 files changed, 387 insertions(+), 406 deletions(-) delete mode 100644 drivers/video/exynos/exynos_fimd.c (limited to 'drivers/video') diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile index d4bdf32..001a80f 100644 --- a/drivers/video/exynos/Makefile +++ b/drivers/video/exynos/Makefile @@ -6,7 +6,7 @@ # obj-$(CONFIG_EXYNOS_DP) += exynos_dp.o exynos_dp_lowlevel.o -obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o exynos_fimd.o +obj-$(CONFIG_EXYNOS_FB) += exynos_fb.o obj-$(CONFIG_EXYNOS_MIPI_DSIM) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ exynos_mipi_dsi_lowlevel.o obj-$(CONFIG_EXYNOS_PWM_BL) += exynos_pwm_bl.o diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 22b9723..e13d35a 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,391 @@ struct vidinfo panel_info = { .vl_col = -1, }; +static void exynos_fimd_set_dualrgb(struct vidinfo *pvid, unsigned int enabled) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + if (enabled) { + cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | + EXYNOS_DUALRGB_VDEN_EN_ENABLE; + + /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ + cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | + EXYNOS_DUALRGB_MAIN_CNT(0); + } + + writel(cfg, &fimd_ctrl->dualrgb); +} + +static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, + unsigned int enabled) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + if (enabled) + cfg = EXYNOS_DP_CLK_ENABLE; + + writel(cfg, &fimd_ctrl->dp_mie_clkcon); +} + +static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + /* set window control */ + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | + EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | + EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | + EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); + + /* DATAPATH is DMA */ + cfg |= EXYNOS_WINCON_DATAPATH_DMA; + + cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; + + /* dma burst is 16 */ + cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; + + switch (pvid->vl_bpix) { + case 4: + cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; + break; + default: + cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; + break; + } + + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + /* set window position to x=0, y=0*/ + cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + + EXYNOS_VIDOSD(win_id)); + + cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | + EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | + EXYNOS_VIDOSD_RIGHT_X_E(1) | + EXYNOS_VIDOSD_BOTTOM_Y_E(0); + + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + + EXYNOS_VIDOSD(win_id)); + + /* set window size for window0*/ + cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); + writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + + EXYNOS_VIDOSD(win_id)); +} + +static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, + unsigned int win_id, + ulong lcd_base_addr) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned long start_addr, end_addr; + + start_addr = lcd_base_addr; + end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * + pvid->vl_row); + + writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + + EXYNOS_BUFFER_OFFSET(win_id)); + writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + + EXYNOS_BUFFER_OFFSET(win_id)); +} + +static void exynos_fimd_set_clock(struct vidinfo *pvid) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0, div = 0, remainder, remainder_div; + unsigned long pixel_clock; + unsigned long long src_clock; + + if (pvid->dual_lcd_enabled) { + pixel_clock = pvid->vl_freq * + (pvid->vl_hspw + pvid->vl_hfpd + + pvid->vl_hbpd + pvid->vl_col / 2) * + (pvid->vl_vspw + pvid->vl_vfpd + + pvid->vl_vbpd + pvid->vl_row); + } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { + pixel_clock = pvid->vl_freq * + pvid->vl_width * pvid->vl_height * + (pvid->cs_setup + pvid->wr_setup + + pvid->wr_act + pvid->wr_hold + 1); + } else { + pixel_clock = pvid->vl_freq * + (pvid->vl_hspw + pvid->vl_hfpd + + pvid->vl_hbpd + pvid->vl_col) * + (pvid->vl_vspw + pvid->vl_vfpd + + pvid->vl_vbpd + pvid->vl_row); + } + + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | + EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | + EXYNOS_VIDCON0_CLKDIR_MASK); + cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | + EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); + + src_clock = (unsigned long long) get_lcd_clk(); + + /* get quotient and remainder. */ + remainder = do_div(src_clock, pixel_clock); + div = src_clock; + + remainder *= 10; + remainder_div = remainder / pixel_clock; + + /* round about one places of decimals. */ + if (remainder_div >= 5) + div++; + + /* in case of dual lcd mode. */ + if (pvid->dual_lcd_enabled) + div--; + + cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); + writel(cfg, &fimd_ctrl->vidcon0); +} + +void exynos_set_trigger(struct vidinfo *pvid) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + cfg = readl(&fimd_ctrl->trigcon); + + cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); + + writel(cfg, &fimd_ctrl->trigcon); +} + +int exynos_is_i80_frame_done(struct vidinfo *pvid) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + int status; + + cfg = readl(&fimd_ctrl->trigcon); + + /* frame done func is valid only when TRIMODE[0] is set to 1. */ + status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == + EXYNOS_I80STATUS_TRIG_DONE; + + return status; +} + +static void exynos_fimd_lcd_on(struct vidinfo *pvid) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + /* display on */ + cfg = readl(&fimd_ctrl->vidcon0); + cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); + writel(cfg, &fimd_ctrl->vidcon0); +} + +static void exynos_fimd_window_on(struct vidinfo *pvid, unsigned int win_id) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + /* enable window */ + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + cfg |= EXYNOS_WINCON_ENWIN_ENABLE; + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(&fimd_ctrl->winshmap); + cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); + writel(cfg, &fimd_ctrl->winshmap); +} + +void exynos_fimd_lcd_off(struct vidinfo *pvid) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); + writel(cfg, &fimd_ctrl->vidcon0); +} + +void exynos_fimd_window_off(struct vidinfo *pvid, unsigned int win_id) +{ + struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + unsigned int cfg = 0; + + cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + cfg &= EXYNOS_WINCON_ENWIN_DISABLE; + writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + EXYNOS_WINCON(win_id)); + + cfg = readl(&fimd_ctrl->winshmap); + cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); + writel(cfg, &fimd_ctrl->winshmap); +} + +/* +* The reset value for FIMD SYSMMU register MMU_CTRL is 3 +* on Exynos5420 and newer versions. +* This means FIMD SYSMMU is on by default on Exynos5420 +* and newer versions. +* Since in u-boot we don't use SYSMMU, we should disable +* those FIMD SYSMMU. +* Note that there are 2 SYSMMU for FIMD: m0 and m1. +* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. +* We disable both of them here. +*/ +void exynos_fimd_disable_sysmmu(void) +{ + u32 *sysmmufimd; + unsigned int node; + int node_list[2]; + int count; + int i; + + count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", + COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) { + debug("Can't get device node for fimd sysmmu\n"); + return; + } + + sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (!sysmmufimd) { + debug("Can't get base address for sysmmu fimdm0"); + return; + } + + writel(0x0, sysmmufimd); + } +} + +void exynos_fimd_lcd_init(struct vidinfo *pvid, ulong lcd_base_address) +{ + struct exynos_fb *fimd_ctrl; + unsigned int cfg = 0, rgb_mode; + unsigned int offset; + unsigned int node; + + node = fdtdec_next_compatible(gd->fdt_blob, + 0, COMPAT_SAMSUNG_EXYNOS_FIMD); + if (node <= 0) + debug("exynos_fb: Can't get device node for fimd\n"); + + fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, + "reg"); + if (fimd_ctrl == NULL) + debug("Can't get the FIMD base address\n"); + pvid->fimd_ctrl = fimd_ctrl; + + if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) + exynos_fimd_disable_sysmmu(); + + offset = exynos_fimd_get_base_offset(); + + rgb_mode = pvid->rgb_mode; + + if (pvid->interface_mode == FIMD_RGB_INTERFACE) { + cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; + writel(cfg, &fimd_ctrl->vidcon0); + + cfg = readl(&fimd_ctrl->vidcon2); + cfg &= ~(EXYNOS_VIDCON2_WB_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_MASK | + EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); + cfg |= EXYNOS_VIDCON2_WB_DISABLE; + writel(cfg, &fimd_ctrl->vidcon2); + + /* set polarity */ + cfg = 0; + if (!pvid->vl_clkp) + cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; + if (!pvid->vl_hsp) + cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; + if (!pvid->vl_vsp) + cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; + if (!pvid->vl_dp) + cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; + + writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); + + /* set timing */ + cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); + cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); + cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); + + cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); + cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); + cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); + + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); + + /* set lcd size */ + cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | + EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); + + writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); + } + + /* set display mode */ + cfg = readl(&fimd_ctrl->vidcon0); + cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; + cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); + writel(cfg, &fimd_ctrl->vidcon0); + + /* set par */ + exynos_fimd_set_par(pvid, pvid->win_id); + + /* set memory address */ + exynos_fimd_set_buffer_address(pvid, pvid->win_id, lcd_base_address); + + /* set buffer size */ + cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * + NBITS(pvid->vl_bpix) / 8) | + EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * + NBITS(pvid->vl_bpix) / 8) | + EXYNOS_VIDADDR_OFFSIZE(0) | + EXYNOS_VIDADDR_OFFSIZE_E(0); + + writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + + EXYNOS_BUFFER_SIZE(pvid->win_id)); + + /* set clock */ + exynos_fimd_set_clock(pvid); + + /* set rgb mode to dual lcd. */ + exynos_fimd_set_dualrgb(pvid, pvid->dual_lcd_enabled); + + /* display on */ + exynos_fimd_lcd_on(pvid); + + /* window on */ + exynos_fimd_window_on(pvid, pvid->win_id); + + exynos_fimd_set_dp_clkcon(pvid, pvid->dp_enabled); +} + +unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid) +{ + return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); +} + ushort *configuration_get_cmap(void) { #if defined(CONFIG_LCD_LOGO) diff --git a/drivers/video/exynos/exynos_fimd.c b/drivers/video/exynos/exynos_fimd.c deleted file mode 100644 index 039d4c5..0000000 --- a/drivers/video/exynos/exynos_fimd.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "exynos_fb.h" - -DECLARE_GLOBAL_DATA_PTR; - -static void exynos_fimd_set_dualrgb(struct vidinfo *pvid, unsigned int enabled) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - if (enabled) { - cfg = EXYNOS_DUALRGB_BYPASS_DUAL | EXYNOS_DUALRGB_LINESPLIT | - EXYNOS_DUALRGB_VDEN_EN_ENABLE; - - /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ - cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | - EXYNOS_DUALRGB_MAIN_CNT(0); - } - - writel(cfg, &fimd_ctrl->dualrgb); -} - -static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, - unsigned int enabled) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - if (enabled) - cfg = EXYNOS_DP_CLK_ENABLE; - - writel(cfg, &fimd_ctrl->dp_mie_clkcon); -} - -static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - /* set window control */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | - EXYNOS_WINCON_HAWSWP_ENABLE | EXYNOS_WINCON_WSWP_ENABLE | - EXYNOS_WINCON_BURSTLEN_MASK | EXYNOS_WINCON_BPPMODE_MASK | - EXYNOS_WINCON_INRGB_MASK | EXYNOS_WINCON_DATAPATH_MASK); - - /* DATAPATH is DMA */ - cfg |= EXYNOS_WINCON_DATAPATH_DMA; - - cfg |= EXYNOS_WINCON_HAWSWP_ENABLE; - - /* dma burst is 16 */ - cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; - - switch (pvid->vl_bpix) { - case 4: - cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; - break; - default: - cfg |= EXYNOS_WINCON_BPPMODE_24BPP_888; - break; - } - - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - /* set window position to x=0, y=0*/ - cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + - EXYNOS_VIDOSD(win_id)); - - cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | - EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | - EXYNOS_VIDOSD_RIGHT_X_E(1) | - EXYNOS_VIDOSD_BOTTOM_Y_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + - EXYNOS_VIDOSD(win_id)); - - /* set window size for window0*/ - cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + - EXYNOS_VIDOSD(win_id)); -} - -static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, - unsigned int win_id, - ulong lcd_base_addr) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned long start_addr, end_addr; - - start_addr = lcd_base_addr; - end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * - pvid->vl_row); - - writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + - EXYNOS_BUFFER_OFFSET(win_id)); - writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + - EXYNOS_BUFFER_OFFSET(win_id)); -} - -static void exynos_fimd_set_clock(struct vidinfo *pvid) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0, div = 0, remainder, remainder_div; - unsigned long pixel_clock; - unsigned long long src_clock; - - if (pvid->dual_lcd_enabled) { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col / 2) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { - pixel_clock = pvid->vl_freq * - pvid->vl_width * pvid->vl_height * - (pvid->cs_setup + pvid->wr_setup + - pvid->wr_act + pvid->wr_hold + 1); - } else { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | - EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | - EXYNOS_VIDCON0_CLKDIR_MASK); - cfg |= (EXYNOS_VIDCON0_CLKSEL_SCLK | EXYNOS_VIDCON0_CLKVALUP_ALWAYS | - EXYNOS_VIDCON0_VCLKEN_NORMAL | EXYNOS_VIDCON0_CLKDIR_DIVIDED); - - src_clock = (unsigned long long) get_lcd_clk(); - - /* get quotient and remainder. */ - remainder = do_div(src_clock, pixel_clock); - div = src_clock; - - remainder *= 10; - remainder_div = remainder / pixel_clock; - - /* round about one places of decimals. */ - if (remainder_div >= 5) - div++; - - /* in case of dual lcd mode. */ - if (pvid->dual_lcd_enabled) - div--; - - cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_set_trigger(struct vidinfo *pvid) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->trigcon); - - cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); - - writel(cfg, &fimd_ctrl->trigcon); -} - -int exynos_is_i80_frame_done(struct vidinfo *pvid) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - int status; - - cfg = readl(&fimd_ctrl->trigcon); - - /* frame done func is valid only when TRIMODE[0] is set to 1. */ - status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == - EXYNOS_I80STATUS_TRIG_DONE; - - return status; -} - -static void exynos_fimd_lcd_on(struct vidinfo *pvid) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - /* display on */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -static void exynos_fimd_window_on(struct vidinfo *pvid, unsigned int win_id) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - /* enable window */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg |= EXYNOS_WINCON_ENWIN_ENABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -void exynos_fimd_lcd_off(struct vidinfo *pvid) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); - writel(cfg, &fimd_ctrl->vidcon0); -} - -void exynos_fimd_window_off(struct vidinfo *pvid, unsigned int win_id) -{ - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; - unsigned int cfg = 0; - - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - cfg &= EXYNOS_WINCON_ENWIN_DISABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + - EXYNOS_WINCON(win_id)); - - cfg = readl(&fimd_ctrl->winshmap); - cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); -} - -/* -* The reset value for FIMD SYSMMU register MMU_CTRL is 3 -* on Exynos5420 and newer versions. -* This means FIMD SYSMMU is on by default on Exynos5420 -* and newer versions. -* Since in u-boot we don't use SYSMMU, we should disable -* those FIMD SYSMMU. -* Note that there are 2 SYSMMU for FIMD: m0 and m1. -* m0 handles windows 0 and 4, and m1 handles windows 1, 2 and 3. -* We disable both of them here. -*/ -void exynos_fimd_disable_sysmmu(void) -{ - u32 *sysmmufimd; - unsigned int node; - int node_list[2]; - int count; - int i; - - count = fdtdec_find_aliases_for_id(gd->fdt_blob, "fimd", - COMPAT_SAMSUNG_EXYNOS_SYSMMU, node_list, 2); - for (i = 0; i < count; i++) { - node = node_list[i]; - if (node <= 0) { - debug("Can't get device node for fimd sysmmu\n"); - return; - } - - sysmmufimd = (u32 *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (!sysmmufimd) { - debug("Can't get base address for sysmmu fimdm0"); - return; - } - - writel(0x0, sysmmufimd); - } -} - -void exynos_fimd_lcd_init(struct vidinfo *pvid, ulong lcd_base_address) -{ - struct exynos_fb *fimd_ctrl; - unsigned int cfg = 0, rgb_mode; - unsigned int offset; - unsigned int node; - - node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) - debug("exynos_fb: Can't get device node for fimd\n"); - - fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, - "reg"); - if (fimd_ctrl == NULL) - debug("Can't get the FIMD base address\n"); - pvid->fimd_ctrl = fimd_ctrl; - - if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) - exynos_fimd_disable_sysmmu(); - - offset = exynos_fimd_get_base_offset(); - - rgb_mode = pvid->rgb_mode; - - if (pvid->interface_mode == FIMD_RGB_INTERFACE) { - cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; - writel(cfg, &fimd_ctrl->vidcon0); - - cfg = readl(&fimd_ctrl->vidcon2); - cfg &= ~(EXYNOS_VIDCON2_WB_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_MASK | - EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); - cfg |= EXYNOS_VIDCON2_WB_DISABLE; - writel(cfg, &fimd_ctrl->vidcon2); - - /* set polarity */ - cfg = 0; - if (!pvid->vl_clkp) - cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; - if (!pvid->vl_hsp) - cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; - if (!pvid->vl_vsp) - cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; - if (!pvid->vl_dp) - cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; - - writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); - - /* set timing */ - cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); - cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); - cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); - - cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); - cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); - cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); - - /* set lcd size */ - cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | - EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); - - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); - } - - /* set display mode */ - cfg = readl(&fimd_ctrl->vidcon0); - cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; - cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); - writel(cfg, &fimd_ctrl->vidcon0); - - /* set par */ - exynos_fimd_set_par(pvid, pvid->win_id); - - /* set memory address */ - exynos_fimd_set_buffer_address(pvid, pvid->win_id, lcd_base_address); - - /* set buffer size */ - cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_OFFSIZE(0) | - EXYNOS_VIDADDR_OFFSIZE_E(0); - - writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + - EXYNOS_BUFFER_SIZE(pvid->win_id)); - - /* set clock */ - exynos_fimd_set_clock(pvid); - - /* set rgb mode to dual lcd. */ - exynos_fimd_set_dualrgb(pvid, pvid->dual_lcd_enabled); - - /* display on */ - exynos_fimd_lcd_on(pvid); - - /* window on */ - exynos_fimd_window_on(pvid, pvid->win_id); - - exynos_fimd_set_dp_clkcon(pvid, pvid->dp_enabled); -} - -unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid) -{ - return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); -} -- cgit v1.1 From 7eb860df13ed3e40469eebd407b90c6f9216dd2e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:57 -0700 Subject: exynos: Simplify calling of exynos_dp_phy_ctrl() This function controls enabling the EDP PHY. Rename it and drop the existing weak functions, which are confusing. Signed-off-by: Simon Glass Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index 9945c4b..88926b9 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -22,12 +23,6 @@ DECLARE_GLOBAL_DATA_PTR; -void __exynos_set_dp_phy(unsigned int onoff) -{ -} -void exynos_set_dp_phy(unsigned int onoff) - __attribute__((weak, alias("__exynos_set_dp_phy"))); - static void exynos_dp_disp_info(struct edp_disp_info *disp_info) { disp_info->h_total = disp_info->h_res + disp_info->h_sync_width + @@ -959,7 +954,7 @@ unsigned int exynos_init_dp(void) exynos_dp_disp_info(&edp_info->disp_info); - exynos_set_dp_phy(1); + exynos_dp_phy_ctrl(1); ret = exynos_dp_init_dp(dp_regs); if (ret != EXYNOS_DP_SUCCESS) { -- cgit v1.1 From 21f8f9bb084e276c490454c401fc23dc42c536bc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:08:59 -0700 Subject: exynos: video: Rename edp_device_info to exynos_dp_priv Rename this function to better fit with driver model. It is the private data for the exynos EDP driver. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp.c | 26 +++++++++++++------------- drivers/video/exynos/exynos_dp_lowlevel.c | 2 +- drivers/video/exynos/exynos_dp_lowlevel.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index 88926b9..0d4ceef 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -162,7 +162,7 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) } static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned char buf[12]; unsigned int ret; @@ -251,7 +251,7 @@ static void exynos_dp_init_training(struct exynos_dp *dp_regs) } static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned char buf[5]; unsigned int ret = 0; @@ -376,7 +376,7 @@ static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *dp_regs, } static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info, + struct exynos_dp_priv *edp_info, unsigned char *status) { unsigned int ret, i; @@ -433,7 +433,7 @@ static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *dp_regs, } static int exynos_dp_equalizer_err_link(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { int ret; @@ -453,7 +453,7 @@ static int exynos_dp_equalizer_err_link(struct exynos_dp *dp_regs, } static int exynos_dp_reduce_link_rate(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { int ret; @@ -478,7 +478,7 @@ static int exynos_dp_reduce_link_rate(struct exynos_dp *dp_regs, } static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat; @@ -588,7 +588,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, } static unsigned int exynos_dp_process_equalizer_training( - struct exynos_dp *dp_regs, struct edp_device_info *edp_info) + struct exynos_dp *dp_regs, struct exynos_dp_priv *edp_info) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat, adj_req_sw, adj_req_em, i; @@ -697,7 +697,7 @@ static unsigned int exynos_dp_process_equalizer_training( } static unsigned int exynos_dp_sw_link_training(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned int ret = 0; int training_finished; @@ -748,7 +748,7 @@ static unsigned int exynos_dp_sw_link_training(struct exynos_dp *dp_regs, } static unsigned int exynos_dp_set_link_train(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned int ret; @@ -783,7 +783,7 @@ static void exynos_dp_enable_scramble(struct exynos_dp *dp_regs, } static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned int ret = 0; unsigned int retry_cnt; @@ -872,7 +872,7 @@ static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, return ret; } -int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) +int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *edp_info) { unsigned int node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_DP); @@ -929,11 +929,11 @@ int exynos_dp_parse_dt(const void *blob, struct edp_device_info *edp_info) unsigned int exynos_init_dp(void) { unsigned int ret; - struct edp_device_info *edp_info; + struct exynos_dp_priv *edp_info; struct exynos_dp *dp_regs; int node; - edp_info = kzalloc(sizeof(struct edp_device_info), GFP_KERNEL); + edp_info = kzalloc(sizeof(struct exynos_dp_priv), GFP_KERNEL); if (!edp_info) { debug("failed to allocate edp device object.\n"); return -EFAULT; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c index 153c1c6..00a79ea 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.c +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -1066,7 +1066,7 @@ void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, } int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info) + struct exynos_dp_priv *edp_info) { unsigned int reg; unsigned int bist_type = 0; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.h b/drivers/video/exynos/exynos_dp_lowlevel.h index 85459b5..0a7657e 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.h +++ b/drivers/video/exynos/exynos_dp_lowlevel.h @@ -74,7 +74,7 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, struct edp_video_info *video_info); int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, - struct edp_device_info *edp_info); + struct exynos_dp_priv *edp_info); unsigned int exynos_dp_is_slave_video_stream_clock_on( struct exynos_dp *dp_regs); void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, -- cgit v1.1 From 8b449a6639c6bee1a97c0eba2ab142a7c471d9b1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:09:00 -0700 Subject: exynos: video: Rename variables for driver model Use 'priv' for a private pointer and 'regs' for a register pointer. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp.c | 434 +++++++++++++++--------------- drivers/video/exynos/exynos_dp_lowlevel.c | 71 +++-- drivers/video/exynos/exynos_dp_lowlevel.h | 2 +- drivers/video/exynos/exynos_fb.c | 234 ++++++++-------- 4 files changed, 369 insertions(+), 372 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index 0d4ceef..d7bccc3 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -33,20 +33,20 @@ static void exynos_dp_disp_info(struct edp_disp_info *disp_info) return; } -static int exynos_dp_init_dp(struct exynos_dp *dp_regs) +static int exynos_dp_init_dp(struct exynos_dp *regs) { int ret; - exynos_dp_reset(dp_regs); + exynos_dp_reset(regs); /* SW defined function Normal operation */ - exynos_dp_enable_sw_func(dp_regs, DP_ENABLE); + exynos_dp_enable_sw_func(regs, DP_ENABLE); - ret = exynos_dp_init_analog_func(dp_regs); + ret = exynos_dp_init_analog_func(regs); if (ret != EXYNOS_DP_SUCCESS) return ret; - exynos_dp_init_hpd(dp_regs); - exynos_dp_init_aux(dp_regs); + exynos_dp_init_hpd(regs); + exynos_dp_init_aux(regs); return ret; } @@ -62,7 +62,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) return sum; } -static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) +static unsigned int exynos_dp_read_edid(struct exynos_dp *regs) { unsigned char edid[EDID_BLOCK_LENGTH * 2]; unsigned int extend_block = 0; @@ -77,14 +77,14 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) */ /* Read Extension Flag, Number of 128-byte EDID extension blocks */ - exynos_dp_read_byte_from_i2c(dp_regs, I2C_EDID_DEVICE_ADDR, + exynos_dp_read_byte_from_i2c(regs, I2C_EDID_DEVICE_ADDR, EDID_EXTENSION_FLAG, &extend_block); if (extend_block > 0) { printf("DP EDID data includes a single extension!\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp_regs, + retval = exynos_dp_read_bytes_from_i2c(regs, I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, @@ -100,7 +100,7 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) } /* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp_regs, + retval = exynos_dp_read_bytes_from_i2c(regs, I2C_EDID_DEVICE_ADDR, EDID_BLOCK_LENGTH, EDID_BLOCK_LENGTH, @@ -115,13 +115,13 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) return -1; } - exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_TEST_REQUEST, + exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST, &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(dp_regs, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(dp_regs, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } @@ -129,7 +129,7 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) debug("DP EDID data does not include any extensions.\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp_regs, + retval = exynos_dp_read_bytes_from_i2c(regs, I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, EDID_BLOCK_LENGTH, @@ -145,12 +145,12 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) return -1; } - exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_TEST_REQUEST, + exynos_dp_read_byte_from_dpcd(regs, DPCD_TEST_REQUEST, &test_vector); if (test_vector & DPCD_TEST_EDID_READ) { - exynos_dp_write_byte_to_dpcd(dp_regs, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(dp_regs, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TEST_RESPONSE, DPCD_TEST_EDID_CHECKSUM_WRITE); } @@ -161,8 +161,8 @@ static unsigned int exynos_dp_read_edid(struct exynos_dp *dp_regs) return 0; } -static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_handle_edid(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned char buf[12]; unsigned int ret; @@ -180,7 +180,7 @@ static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, retry_cnt = 5; while (retry_cnt) { /* Read DPCD 0x0000-0x000b */ - ret = exynos_dp_read_bytes_from_dpcd(dp_regs, DPCD_DPCD_REV, 12, + ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_DPCD_REV, 12, buf); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { @@ -195,7 +195,7 @@ static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, /* */ temp = buf[DPCD_DPCD_REV]; if (temp == DP_DPCD_REV_10 || temp == DP_DPCD_REV_11) - edp_info->dpcd_rev = temp; + priv->dpcd_rev = temp; else { printf("DP Wrong DPCD Rev : %x\n", temp); return -ENODEV; @@ -203,33 +203,33 @@ static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, temp = buf[DPCD_MAX_LINK_RATE]; if (temp == DP_LANE_BW_1_62 || temp == DP_LANE_BW_2_70) - edp_info->lane_bw = temp; + priv->lane_bw = temp; else { printf("DP Wrong MAX LINK RATE : %x\n", temp); return -EINVAL; } /* Refer VESA Display Port Standard Ver1.1a Page 120 */ - if (edp_info->dpcd_rev == DP_DPCD_REV_11) { + if (priv->dpcd_rev == DP_DPCD_REV_11) { temp = buf[DPCD_MAX_LANE_COUNT] & 0x1f; if (buf[DPCD_MAX_LANE_COUNT] & 0x80) - edp_info->dpcd_efc = 1; + priv->dpcd_efc = 1; else - edp_info->dpcd_efc = 0; + priv->dpcd_efc = 0; } else { temp = buf[DPCD_MAX_LANE_COUNT]; - edp_info->dpcd_efc = 0; + priv->dpcd_efc = 0; } if (temp == DP_LANE_CNT_1 || temp == DP_LANE_CNT_2 || temp == DP_LANE_CNT_4) { - edp_info->lane_cnt = temp; + priv->lane_cnt = temp; } else { printf("DP Wrong MAX LANE COUNT : %x\n", temp); return -EINVAL; } - ret = exynos_dp_read_edid(dp_regs); + ret = exynos_dp_read_edid(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_read_edid() failed\n"); return -EINVAL; @@ -238,35 +238,35 @@ static unsigned int exynos_dp_handle_edid(struct exynos_dp *dp_regs, return ret; } -static void exynos_dp_init_training(struct exynos_dp *dp_regs) +static void exynos_dp_init_training(struct exynos_dp *regs) { /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ - exynos_dp_reset_macro(dp_regs); + exynos_dp_reset_macro(regs); /* All DP analog module power up */ - exynos_dp_set_analog_power_down(dp_regs, POWER_ALL, 0); + exynos_dp_set_analog_power_down(regs, POWER_ALL, 0); } -static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_link_start(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned char buf[5]; unsigned int ret = 0; debug("DP: %s was called\n", __func__); - edp_info->lt_info.lt_status = DP_LT_CR; - edp_info->lt_info.ep_loop = 0; - edp_info->lt_info.cr_loop[0] = 0; - edp_info->lt_info.cr_loop[1] = 0; - edp_info->lt_info.cr_loop[2] = 0; - edp_info->lt_info.cr_loop[3] = 0; + priv->lt_info.lt_status = DP_LT_CR; + priv->lt_info.ep_loop = 0; + priv->lt_info.cr_loop[0] = 0; + priv->lt_info.cr_loop[1] = 0; + priv->lt_info.cr_loop[2] = 0; + priv->lt_info.cr_loop[3] = 0; /* Set sink to D0 (Sink Not Ready) mode. */ - ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_SINK_POWER_STATE, + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_SINK_POWER_STATE, DPCD_SET_POWER_STATE_D0); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); @@ -274,24 +274,24 @@ static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, } /* Set link rate and count as you want to establish */ - exynos_dp_set_link_bandwidth(dp_regs, edp_info->lane_bw); - exynos_dp_set_lane_count(dp_regs, edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(regs, priv->lane_bw); + exynos_dp_set_lane_count(regs, priv->lane_cnt); /* Setup RX configuration */ - buf[0] = edp_info->lane_bw; - buf[1] = edp_info->lane_cnt; + buf[0] = priv->lane_bw; + buf[1] = priv->lane_cnt; - ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_LINK_BW_SET, 2, buf); + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_LINK_BW_SET, 2, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); return ret; } - exynos_dp_set_lane_pre_emphasis(dp_regs, PRE_EMPHASIS_LEVEL_0, - edp_info->lane_cnt); + exynos_dp_set_lane_pre_emphasis(regs, PRE_EMPHASIS_LEVEL_0, + priv->lane_cnt); /* Set training pattern 1 */ - exynos_dp_set_training_pattern(dp_regs, TRAINING_PTN1); + exynos_dp_set_training_pattern(regs, TRAINING_PTN1); /* Set RX training pattern */ buf[0] = DPCD_SCRAMBLING_DISABLED | DPCD_TRAINING_PATTERN_1; @@ -305,7 +305,7 @@ static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, buf[4] = DPCD_PRE_EMPHASIS_SET_PATTERN_2_LEVEL_0 | DPCD_VOLTAGE_SWING_SET_PATTERN_1_LEVEL_0; - ret = exynos_dp_write_bytes_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_dpcd_byte failed\n"); @@ -315,13 +315,13 @@ static unsigned int exynos_dp_link_start(struct exynos_dp *dp_regs, return ret; } -static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *dp_regs) +static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *regs) { unsigned int ret = EXYNOS_DP_SUCCESS; - exynos_dp_set_training_pattern(dp_regs, DP_NONE); + exynos_dp_set_training_pattern(regs, DP_NONE); - ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, DPCD_TRAINING_PATTERN_DISABLED); if (ret != EXYNOS_DP_SUCCESS) { printf("DP request_link_training_req failed\n"); @@ -332,12 +332,12 @@ static unsigned int exynos_dp_training_pattern_dis(struct exynos_dp *dp_regs) } static unsigned int exynos_dp_enable_rx_to_enhanced_mode( - struct exynos_dp *dp_regs, unsigned char enable) + struct exynos_dp *regs, unsigned char enable) { unsigned char data; unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_read_byte_from_dpcd(dp_regs, DPCD_LANE_COUNT_SET, + ret = exynos_dp_read_byte_from_dpcd(regs, DPCD_LANE_COUNT_SET, &data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read_from_dpcd failed\n"); @@ -349,7 +349,7 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode( else data = DPCD_LN_COUNT_SET(data); - ret = exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_LANE_COUNT_SET, data); + ret = exynos_dp_write_byte_to_dpcd(regs, DPCD_LANE_COUNT_SET, data); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write_to_dpcd failed\n"); return -EAGAIN; @@ -359,24 +359,24 @@ static unsigned int exynos_dp_enable_rx_to_enhanced_mode( return ret; } -static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *dp_regs, +static unsigned int exynos_dp_set_enhanced_mode(struct exynos_dp *regs, unsigned char enhance_mode) { unsigned int ret = EXYNOS_DP_SUCCESS; - ret = exynos_dp_enable_rx_to_enhanced_mode(dp_regs, enhance_mode); + ret = exynos_dp_enable_rx_to_enhanced_mode(regs, enhance_mode); if (ret != EXYNOS_DP_SUCCESS) { printf("DP rx_enhance_mode failed\n"); return -EAGAIN; } - exynos_dp_enable_enhanced_mode(dp_regs, enhance_mode); + exynos_dp_enable_enhanced_mode(regs, enhance_mode); return ret; } -static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info, +static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *regs, + struct exynos_dp_priv *priv, unsigned char *status) { unsigned int ret, i; @@ -389,14 +389,14 @@ static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *dp_regs, shift_val[2] = 0; shift_val[3] = 4; - ret = exynos_dp_read_bytes_from_dpcd(dp_regs, DPCD_LANE0_1_STATUS, 2, + ret = exynos_dp_read_bytes_from_dpcd(regs, DPCD_LANE0_1_STATUS, 2, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); return ret; } - for (i = 0; i < edp_info->lane_cnt; i++) { + for (i = 0; i < priv->lane_cnt; i++) { lane_stat[i] = (buf[(i / 2)] >> shift_val[i]) & 0x0f; if (lane_stat[0] != lane_stat[i]) { printf("Wrong lane status\n"); @@ -409,7 +409,7 @@ static int exynos_dp_read_dpcd_lane_stat(struct exynos_dp *dp_regs, return ret; } -static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *dp_regs, +static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *regs, unsigned char lane_num, unsigned char *sw, unsigned char *em) { unsigned int ret = EXYNOS_DP_SUCCESS; @@ -420,7 +420,7 @@ static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *dp_regs, /* lane_num value is used as array index, so this range 0 ~ 3 */ dpcd_addr = DPCD_ADJUST_REQUEST_LANE0_1 + (lane_num / 2); - ret = exynos_dp_read_byte_from_dpcd(dp_regs, dpcd_addr, &buf); + ret = exynos_dp_read_byte_from_dpcd(regs, dpcd_addr, &buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adjust request failed\n"); return -EAGAIN; @@ -432,53 +432,53 @@ static unsigned int exynos_dp_read_dpcd_adj_req(struct exynos_dp *dp_regs, return ret; } -static int exynos_dp_equalizer_err_link(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static int exynos_dp_equalizer_err_link(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { int ret; - ret = exynos_dp_training_pattern_dis(dp_regs); + ret = exynos_dp_training_pattern_dis(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP training_pattern_disable() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } - ret = exynos_dp_set_enhanced_mode(dp_regs, edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set_enhanced_mode() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } return ret; } -static int exynos_dp_reduce_link_rate(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static int exynos_dp_reduce_link_rate(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { int ret; - if (edp_info->lane_bw == DP_LANE_BW_2_70) { - edp_info->lane_bw = DP_LANE_BW_1_62; + if (priv->lane_bw == DP_LANE_BW_2_70) { + priv->lane_bw = DP_LANE_BW_1_62; printf("DP Change lane bw to 1.62Gbps\n"); - edp_info->lt_info.lt_status = DP_LT_START; + priv->lt_info.lt_status = DP_LT_START; ret = EXYNOS_DP_SUCCESS; } else { - ret = exynos_dp_training_pattern_dis(dp_regs); + ret = exynos_dp_training_pattern_dis(regs); if (ret != EXYNOS_DP_SUCCESS) printf("DP training_patter_disable() failed\n"); - ret = exynos_dp_set_enhanced_mode(dp_regs, edp_info->dpcd_efc); + ret = exynos_dp_set_enhanced_mode(regs, priv->dpcd_efc); if (ret != EXYNOS_DP_SUCCESS) printf("DP set_enhanced_mode() failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; } return ret; } -static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat; @@ -491,22 +491,22 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, debug("DP: %s was called\n", __func__); mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(dp_regs, edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } if (lane_stat & DP_LANE_STAT_CR_DONE) { debug("DP clock Recovery training succeed\n"); - exynos_dp_set_training_pattern(dp_regs, TRAINING_PTN2); + exynos_dp_set_training_pattern(regs, TRAINING_PTN2); - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, + for (i = 0; i < priv->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } @@ -518,7 +518,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(dp_regs, + exynos_dp_set_lanex_pre_emphasis(regs, lt_ctl_val[i], i); } @@ -528,39 +528,39 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, buf[3] = lt_ctl_val[2]; buf[4] = lt_ctl_val[3]; - ret = exynos_dp_write_bytes_to_dpcd(dp_regs, + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, 5, buf); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } else - edp_info->lt_info.lt_status = DP_LT_ET; + priv->lt_info.lt_status = DP_LT_ET; } else { - for (i = 0; i < edp_info->lane_cnt; i++) { + for (i = 0; i < priv->lane_cnt; i++) { lt_ctl_val[i] = exynos_dp_get_lanex_pre_emphasis( - dp_regs, i); - ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, + regs, i); + ret = exynos_dp_read_dpcd_adj_req(regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } if ((adj_req_sw == VOLTAGE_LEVEL_3) || (adj_req_em == PRE_EMPHASIS_LEVEL_3)) - ret = exynos_dp_reduce_link_rate(dp_regs, - edp_info); + ret = exynos_dp_reduce_link_rate(regs, + priv); if ((DRIVE_CURRENT_SET_0_GET(lt_ctl_val[i]) == adj_req_sw) && (PRE_EMPHASIS_SET_0_GET(lt_ctl_val[i]) == adj_req_em)) { - edp_info->lt_info.cr_loop[i]++; - if (edp_info->lt_info.cr_loop[i] == MAX_CR_LOOP) + priv->lt_info.cr_loop[i]++; + if (priv->lt_info.cr_loop[i] == MAX_CR_LOOP) ret = exynos_dp_reduce_link_rate( - dp_regs, edp_info); + regs, priv); } lt_ctl_val[i] = 0; @@ -571,15 +571,15 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, lt_ctl_val[i] |= MAX_DRIVE_CURRENT_REACH_3 | MAX_PRE_EMPHASIS_REACH_3; } - exynos_dp_set_lanex_pre_emphasis(dp_regs, + exynos_dp_set_lanex_pre_emphasis(regs, lt_ctl_val[i], i); } - ret = exynos_dp_write_bytes_to_dpcd(dp_regs, + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP write training pattern2 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } } @@ -588,7 +588,7 @@ static unsigned int exynos_dp_process_clock_recovery(struct exynos_dp *dp_regs, } static unsigned int exynos_dp_process_equalizer_training( - struct exynos_dp *dp_regs, struct exynos_dp_priv *edp_info) + struct exynos_dp *regs, struct exynos_dp_priv *priv) { unsigned int ret = EXYNOS_DP_SUCCESS; unsigned char lane_stat, adj_req_sw, adj_req_em, i; @@ -600,33 +600,33 @@ static unsigned int exynos_dp_process_equalizer_training( mdelay(1); - ret = exynos_dp_read_dpcd_lane_stat(dp_regs, edp_info, &lane_stat); + ret = exynos_dp_read_dpcd_lane_stat(regs, priv, &lane_stat); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read lane status failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } debug("DP lane stat : %x\n", lane_stat); if (lane_stat & DP_LANE_STAT_CR_DONE) { - ret = exynos_dp_read_byte_from_dpcd(dp_regs, + ret = exynos_dp_read_byte_from_dpcd(regs, DPCD_LN_ALIGN_UPDATED, &sink_stat); if (ret != EXYNOS_DP_SUCCESS) { - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } interlane_aligned = (sink_stat & DPCD_INTERLANE_ALIGN_DONE); - for (i = 0; i < edp_info->lane_cnt; i++) { - ret = exynos_dp_read_dpcd_adj_req(dp_regs, i, + for (i = 0; i < priv->lane_cnt; i++) { + ret = exynos_dp_read_dpcd_adj_req(regs, i, &adj_req_sw, &adj_req_em); if (ret != EXYNOS_DP_SUCCESS) { printf("DP read adj req 1 failed\n"); - edp_info->lt_info.lt_status = DP_LT_FAIL; + priv->lt_info.lt_status = DP_LT_FAIL; return ret; } @@ -646,91 +646,91 @@ static unsigned int exynos_dp_process_equalizer_training( && (interlane_aligned == DPCD_INTERLANE_ALIGN_DONE)) { debug("DP Equalizer training succeed\n"); - f_bw = exynos_dp_get_link_bandwidth(dp_regs); - f_lane_cnt = exynos_dp_get_lane_count(dp_regs); + f_bw = exynos_dp_get_link_bandwidth(regs); + f_lane_cnt = exynos_dp_get_lane_count(regs); debug("DP final BandWidth : %x\n", f_bw); debug("DP final Lane Count : %x\n", f_lane_cnt); - edp_info->lt_info.lt_status = DP_LT_FINISHED; + priv->lt_info.lt_status = DP_LT_FINISHED; - exynos_dp_equalizer_err_link(dp_regs, edp_info); + exynos_dp_equalizer_err_link(regs, priv); } else { - edp_info->lt_info.ep_loop++; + priv->lt_info.ep_loop++; - if (edp_info->lt_info.ep_loop > MAX_EQ_LOOP) { - if (edp_info->lane_bw == DP_LANE_BW_2_70) { + if (priv->lt_info.ep_loop > MAX_EQ_LOOP) { + if (priv->lane_bw == DP_LANE_BW_2_70) { ret = exynos_dp_reduce_link_rate( - dp_regs, edp_info); + regs, priv); } else { - edp_info->lt_info.lt_status = + priv->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(dp_regs, - edp_info); + exynos_dp_equalizer_err_link(regs, + priv); } } else { - for (i = 0; i < edp_info->lane_cnt; i++) + for (i = 0; i < priv->lane_cnt; i++) exynos_dp_set_lanex_pre_emphasis( - dp_regs, lt_ctl_val[i], i); + regs, lt_ctl_val[i], i); - ret = exynos_dp_write_bytes_to_dpcd(dp_regs, + ret = exynos_dp_write_bytes_to_dpcd(regs, DPCD_TRAINING_LANE0_SET, 4, lt_ctl_val); if (ret != EXYNOS_DP_SUCCESS) { printf("DP set lt pattern failed\n"); - edp_info->lt_info.lt_status = + priv->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(dp_regs, - edp_info); + exynos_dp_equalizer_err_link(regs, + priv); } } } - } else if (edp_info->lane_bw == DP_LANE_BW_2_70) { - ret = exynos_dp_reduce_link_rate(dp_regs, edp_info); + } else if (priv->lane_bw == DP_LANE_BW_2_70) { + ret = exynos_dp_reduce_link_rate(regs, priv); } else { - edp_info->lt_info.lt_status = DP_LT_FAIL; - exynos_dp_equalizer_err_link(dp_regs, edp_info); + priv->lt_info.lt_status = DP_LT_FAIL; + exynos_dp_equalizer_err_link(regs, priv); } return ret; } -static unsigned int exynos_dp_sw_link_training(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_sw_link_training(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = 0; int training_finished; /* Turn off unnecessary lane */ - if (edp_info->lane_cnt == 1) - exynos_dp_set_analog_power_down(dp_regs, CH1_BLOCK, 1); + if (priv->lane_cnt == 1) + exynos_dp_set_analog_power_down(regs, CH1_BLOCK, 1); training_finished = 0; - edp_info->lt_info.lt_status = DP_LT_START; + priv->lt_info.lt_status = DP_LT_START; /* Process here */ while (!training_finished) { - switch (edp_info->lt_info.lt_status) { + switch (priv->lt_info.lt_status) { case DP_LT_START: - ret = exynos_dp_link_start(dp_regs, edp_info); + ret = exynos_dp_link_start(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:link start failed\n"); return ret; } break; case DP_LT_CR: - ret = exynos_dp_process_clock_recovery(dp_regs, - edp_info); + ret = exynos_dp_process_clock_recovery(regs, + priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:clock recovery failed\n"); return ret; } break; case DP_LT_ET: - ret = exynos_dp_process_equalizer_training(dp_regs, - edp_info); + ret = exynos_dp_process_equalizer_training(regs, + priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP LT:equalizer training failed\n"); return ret; @@ -747,75 +747,75 @@ static unsigned int exynos_dp_sw_link_training(struct exynos_dp *dp_regs, return ret; } -static unsigned int exynos_dp_set_link_train(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_set_link_train(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret; - exynos_dp_init_training(dp_regs); + exynos_dp_init_training(regs); - ret = exynos_dp_sw_link_training(dp_regs, edp_info); + ret = exynos_dp_sw_link_training(regs, priv); if (ret != EXYNOS_DP_SUCCESS) printf("DP dp_sw_link_training() failed\n"); return ret; } -static void exynos_dp_enable_scramble(struct exynos_dp *dp_regs, +static void exynos_dp_enable_scramble(struct exynos_dp *regs, unsigned int enable) { unsigned char data; if (enable) { - exynos_dp_enable_scrambling(dp_regs, DP_ENABLE); + exynos_dp_enable_scrambling(regs, DP_ENABLE); - exynos_dp_read_byte_from_dpcd(dp_regs, + exynos_dp_read_byte_from_dpcd(regs, DPCD_TRAINING_PATTERN_SET, &data); - exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, (u8)(data & ~DPCD_SCRAMBLING_DISABLED)); } else { - exynos_dp_enable_scrambling(dp_regs, DP_DISABLE); - exynos_dp_read_byte_from_dpcd(dp_regs, + exynos_dp_enable_scrambling(regs, DP_DISABLE); + exynos_dp_read_byte_from_dpcd(regs, DPCD_TRAINING_PATTERN_SET, &data); - exynos_dp_write_byte_to_dpcd(dp_regs, DPCD_TRAINING_PATTERN_SET, + exynos_dp_write_byte_to_dpcd(regs, DPCD_TRAINING_PATTERN_SET, (u8)(data | DPCD_SCRAMBLING_DISABLED)); } } -static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) +static unsigned int exynos_dp_config_video(struct exynos_dp *regs, + struct exynos_dp_priv *priv) { unsigned int ret = 0; unsigned int retry_cnt; mdelay(1); - if (edp_info->video_info.master_mode) { + if (priv->video_info.master_mode) { printf("DP does not support master mode\n"); return -ENODEV; } else { /* debug slave */ - exynos_dp_config_video_slave_mode(dp_regs, - &edp_info->video_info); + exynos_dp_config_video_slave_mode(regs, + &priv->video_info); } - exynos_dp_set_video_color_format(dp_regs, &edp_info->video_info); + exynos_dp_set_video_color_format(regs, &priv->video_info); - if (edp_info->video_info.bist_mode) { - if (exynos_dp_config_video_bist(dp_regs, edp_info) != 0) + if (priv->video_info.bist_mode) { + if (exynos_dp_config_video_bist(regs, priv) != 0) return -1; } - ret = exynos_dp_get_pll_lock_status(dp_regs); + ret = exynos_dp_get_pll_lock_status(regs); if (ret != PLL_LOCKED) { printf("DP PLL is not locked yet\n"); return -EIO; } - if (edp_info->video_info.master_mode == 0) { + if (priv->video_info.master_mode == 0) { retry_cnt = 10; while (retry_cnt) { - ret = exynos_dp_is_slave_video_stream_clock_on(dp_regs); + ret = exynos_dp_is_slave_video_stream_clock_on(regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP stream_clock_on failed\n"); @@ -829,34 +829,34 @@ static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, } /* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(dp_regs, CALCULATED_M, 0, 0); + exynos_dp_set_video_cr_mn(regs, CALCULATED_M, 0, 0); /* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(dp_regs, VIDEO_TIMING_FROM_CAPTURE); + exynos_dp_set_video_timing_mode(regs, VIDEO_TIMING_FROM_CAPTURE); /* Enable video bist */ - if (edp_info->video_info.bist_pattern != COLOR_RAMP && - edp_info->video_info.bist_pattern != BALCK_WHITE_V_LINES && - edp_info->video_info.bist_pattern != COLOR_SQUARE) - exynos_dp_enable_video_bist(dp_regs, - edp_info->video_info.bist_mode); + if (priv->video_info.bist_pattern != COLOR_RAMP && + priv->video_info.bist_pattern != BALCK_WHITE_V_LINES && + priv->video_info.bist_pattern != COLOR_SQUARE) + exynos_dp_enable_video_bist(regs, + priv->video_info.bist_mode); else - exynos_dp_enable_video_bist(dp_regs, DP_DISABLE); + exynos_dp_enable_video_bist(regs, DP_DISABLE); /* Disable video mute */ - exynos_dp_enable_video_mute(dp_regs, DP_DISABLE); + exynos_dp_enable_video_mute(regs, DP_DISABLE); /* Configure video Master or Slave mode */ - exynos_dp_enable_video_master(dp_regs, - edp_info->video_info.master_mode); + exynos_dp_enable_video_master(regs, + priv->video_info.master_mode); /* Enable video */ - exynos_dp_start_video(dp_regs); + exynos_dp_start_video(regs); - if (edp_info->video_info.master_mode == 0) { + if (priv->video_info.master_mode == 0) { retry_cnt = 100; while (retry_cnt) { - ret = exynos_dp_is_video_stream_on(dp_regs); + ret = exynos_dp_is_video_stream_on(regs); if (ret != EXYNOS_DP_SUCCESS) { if (retry_cnt == 0) { printf("DP Timeout of video stream\n"); @@ -872,7 +872,7 @@ static unsigned int exynos_dp_config_video(struct exynos_dp *dp_regs, return ret; } -int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *edp_info) +int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *priv) { unsigned int node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_DP); @@ -881,47 +881,47 @@ int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *edp_info) return -ENODEV; } - edp_info->disp_info.h_res = fdtdec_get_int(blob, node, + priv->disp_info.h_res = fdtdec_get_int(blob, node, "samsung,h-res", 0); - edp_info->disp_info.h_sync_width = fdtdec_get_int(blob, node, + priv->disp_info.h_sync_width = fdtdec_get_int(blob, node, "samsung,h-sync-width", 0); - edp_info->disp_info.h_back_porch = fdtdec_get_int(blob, node, + priv->disp_info.h_back_porch = fdtdec_get_int(blob, node, "samsung,h-back-porch", 0); - edp_info->disp_info.h_front_porch = fdtdec_get_int(blob, node, + priv->disp_info.h_front_porch = fdtdec_get_int(blob, node, "samsung,h-front-porch", 0); - edp_info->disp_info.v_res = fdtdec_get_int(blob, node, + priv->disp_info.v_res = fdtdec_get_int(blob, node, "samsung,v-res", 0); - edp_info->disp_info.v_sync_width = fdtdec_get_int(blob, node, + priv->disp_info.v_sync_width = fdtdec_get_int(blob, node, "samsung,v-sync-width", 0); - edp_info->disp_info.v_back_porch = fdtdec_get_int(blob, node, + priv->disp_info.v_back_porch = fdtdec_get_int(blob, node, "samsung,v-back-porch", 0); - edp_info->disp_info.v_front_porch = fdtdec_get_int(blob, node, + priv->disp_info.v_front_porch = fdtdec_get_int(blob, node, "samsung,v-front-porch", 0); - edp_info->disp_info.v_sync_rate = fdtdec_get_int(blob, node, + priv->disp_info.v_sync_rate = fdtdec_get_int(blob, node, "samsung,v-sync-rate", 0); - edp_info->lt_info.lt_status = fdtdec_get_int(blob, node, + priv->lt_info.lt_status = fdtdec_get_int(blob, node, "samsung,lt-status", 0); - edp_info->video_info.master_mode = fdtdec_get_int(blob, node, + priv->video_info.master_mode = fdtdec_get_int(blob, node, "samsung,master-mode", 0); - edp_info->video_info.bist_mode = fdtdec_get_int(blob, node, + priv->video_info.bist_mode = fdtdec_get_int(blob, node, "samsung,bist-mode", 0); - edp_info->video_info.bist_pattern = fdtdec_get_int(blob, node, + priv->video_info.bist_pattern = fdtdec_get_int(blob, node, "samsung,bist-pattern", 0); - edp_info->video_info.h_sync_polarity = fdtdec_get_int(blob, node, + priv->video_info.h_sync_polarity = fdtdec_get_int(blob, node, "samsung,h-sync-polarity", 0); - edp_info->video_info.v_sync_polarity = fdtdec_get_int(blob, node, + priv->video_info.v_sync_polarity = fdtdec_get_int(blob, node, "samsung,v-sync-polarity", 0); - edp_info->video_info.interlaced = fdtdec_get_int(blob, node, + priv->video_info.interlaced = fdtdec_get_int(blob, node, "samsung,interlaced", 0); - edp_info->video_info.color_space = fdtdec_get_int(blob, node, + priv->video_info.color_space = fdtdec_get_int(blob, node, "samsung,color-space", 0); - edp_info->video_info.dynamic_range = fdtdec_get_int(blob, node, + priv->video_info.dynamic_range = fdtdec_get_int(blob, node, "samsung,dynamic-range", 0); - edp_info->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, + priv->video_info.ycbcr_coeff = fdtdec_get_int(blob, node, "samsung,ycbcr-coeff", 0); - edp_info->video_info.color_depth = fdtdec_get_int(blob, node, + priv->video_info.color_depth = fdtdec_get_int(blob, node, "samsung,color-depth", 0); return 0; } @@ -929,17 +929,17 @@ int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *edp_info) unsigned int exynos_init_dp(void) { unsigned int ret; - struct exynos_dp_priv *edp_info; - struct exynos_dp *dp_regs; + struct exynos_dp_priv *priv; + struct exynos_dp *regs; int node; - edp_info = kzalloc(sizeof(struct exynos_dp_priv), GFP_KERNEL); - if (!edp_info) { + priv = kzalloc(sizeof(struct exynos_dp_priv), GFP_KERNEL); + if (!priv) { debug("failed to allocate edp device object.\n"); return -EFAULT; } - if (exynos_dp_parse_dt(gd->fdt_blob, edp_info)) + if (exynos_dp_parse_dt(gd->fdt_blob, priv)) debug("unable to parse DP DT node\n"); node = fdtdec_next_compatible(gd->fdt_blob, 0, @@ -947,42 +947,42 @@ unsigned int exynos_init_dp(void) if (node <= 0) debug("exynos_dp: Can't get device node for dp\n"); - dp_regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, node, + regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (dp_regs == NULL) + if (regs == NULL) debug("Can't get the DP base address\n"); - exynos_dp_disp_info(&edp_info->disp_info); + exynos_dp_disp_info(&priv->disp_info); exynos_dp_phy_ctrl(1); - ret = exynos_dp_init_dp(dp_regs); + ret = exynos_dp_init_dp(regs); if (ret != EXYNOS_DP_SUCCESS) { printf("DP exynos_dp_init_dp() failed\n"); return ret; } - ret = exynos_dp_handle_edid(dp_regs, edp_info); + ret = exynos_dp_handle_edid(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("EDP handle_edid fail\n"); return ret; } - ret = exynos_dp_set_link_train(dp_regs, edp_info); + ret = exynos_dp_set_link_train(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("DP link training fail\n"); return ret; } - exynos_dp_enable_scramble(dp_regs, DP_ENABLE); - exynos_dp_enable_rx_to_enhanced_mode(dp_regs, DP_ENABLE); - exynos_dp_enable_enhanced_mode(dp_regs, DP_ENABLE); + exynos_dp_enable_scramble(regs, DP_ENABLE); + exynos_dp_enable_rx_to_enhanced_mode(regs, DP_ENABLE); + exynos_dp_enable_enhanced_mode(regs, DP_ENABLE); - exynos_dp_set_link_bandwidth(dp_regs, edp_info->lane_bw); - exynos_dp_set_lane_count(dp_regs, edp_info->lane_cnt); + exynos_dp_set_link_bandwidth(regs, priv->lane_bw); + exynos_dp_set_lane_count(regs, priv->lane_cnt); - exynos_dp_init_video(dp_regs); - ret = exynos_dp_config_video(dp_regs, edp_info); + exynos_dp_init_video(regs); + ret = exynos_dp_config_video(regs, priv); if (ret != EXYNOS_DP_SUCCESS) { printf("Exynos DP init failed\n"); return ret; diff --git a/drivers/video/exynos/exynos_dp_lowlevel.c b/drivers/video/exynos/exynos_dp_lowlevel.c index 00a79ea..f978473 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.c +++ b/drivers/video/exynos/exynos_dp_lowlevel.c @@ -1066,49 +1066,46 @@ void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, } int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info) + struct exynos_dp_priv *priv) { unsigned int reg; unsigned int bist_type = 0; - struct edp_video_info video_info = edp_info->video_info; + struct edp_video_info video_info = priv->video_info; /* For master mode, you don't need to set the video format */ if (video_info.master_mode == 0) { - writel(TOTAL_LINE_CFG_L(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_l); - writel(TOTAL_LINE_CFG_H(edp_info->disp_info.v_total), - &dp_regs->total_ln_cfg_h); - writel(ACTIVE_LINE_CFG_L(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_l); - writel(ACTIVE_LINE_CFG_H(edp_info->disp_info.v_res), - &dp_regs->active_ln_cfg_h); - writel(edp_info->disp_info.v_sync_width, - &dp_regs->vsw_cfg); - writel(edp_info->disp_info.v_back_porch, - &dp_regs->vbp_cfg); - writel(edp_info->disp_info.v_front_porch, - &dp_regs->vfp_cfg); - - writel(TOTAL_PIXEL_CFG_L(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_l); - writel(TOTAL_PIXEL_CFG_H(edp_info->disp_info.h_total), - &dp_regs->total_pix_cfg_h); - writel(ACTIVE_PIXEL_CFG_L(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_l); - writel(ACTIVE_PIXEL_CFG_H(edp_info->disp_info.h_res), - &dp_regs->active_pix_cfg_h); - writel(H_F_PORCH_CFG_L(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_l); - writel(H_F_PORCH_CFG_H(edp_info->disp_info.h_front_porch), - &dp_regs->hfp_cfg_h); - writel(H_SYNC_PORCH_CFG_L(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_l); - writel(H_SYNC_PORCH_CFG_H(edp_info->disp_info.h_sync_width), - &dp_regs->hsw_cfg_h); - writel(H_B_PORCH_CFG_L(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_l); - writel(H_B_PORCH_CFG_H(edp_info->disp_info.h_back_porch), - &dp_regs->hbp_cfg_h); + writel(TOTAL_LINE_CFG_L(priv->disp_info.v_total), + &dp_regs->total_ln_cfg_l); + writel(TOTAL_LINE_CFG_H(priv->disp_info.v_total), + &dp_regs->total_ln_cfg_h); + writel(ACTIVE_LINE_CFG_L(priv->disp_info.v_res), + &dp_regs->active_ln_cfg_l); + writel(ACTIVE_LINE_CFG_H(priv->disp_info.v_res), + &dp_regs->active_ln_cfg_h); + writel(priv->disp_info.v_sync_width, &dp_regs->vsw_cfg); + writel(priv->disp_info.v_back_porch, &dp_regs->vbp_cfg); + writel(priv->disp_info.v_front_porch, &dp_regs->vfp_cfg); + + writel(TOTAL_PIXEL_CFG_L(priv->disp_info.h_total), + &dp_regs->total_pix_cfg_l); + writel(TOTAL_PIXEL_CFG_H(priv->disp_info.h_total), + &dp_regs->total_pix_cfg_h); + writel(ACTIVE_PIXEL_CFG_L(priv->disp_info.h_res), + &dp_regs->active_pix_cfg_l); + writel(ACTIVE_PIXEL_CFG_H(priv->disp_info.h_res), + &dp_regs->active_pix_cfg_h); + writel(H_F_PORCH_CFG_L(priv->disp_info.h_front_porch), + &dp_regs->hfp_cfg_l); + writel(H_F_PORCH_CFG_H(priv->disp_info.h_front_porch), + &dp_regs->hfp_cfg_h); + writel(H_SYNC_PORCH_CFG_L(priv->disp_info.h_sync_width), + &dp_regs->hsw_cfg_l); + writel(H_SYNC_PORCH_CFG_H(priv->disp_info.h_sync_width), + &dp_regs->hsw_cfg_h); + writel(H_B_PORCH_CFG_L(priv->disp_info.h_back_porch), + &dp_regs->hbp_cfg_l); + writel(H_B_PORCH_CFG_H(priv->disp_info.h_back_porch), + &dp_regs->hbp_cfg_h); /* * Set SLAVE_I_SCAN_CFG[2], VSYNC_P_CFG[1], diff --git a/drivers/video/exynos/exynos_dp_lowlevel.h b/drivers/video/exynos/exynos_dp_lowlevel.h index 0a7657e..e4c867e 100644 --- a/drivers/video/exynos/exynos_dp_lowlevel.h +++ b/drivers/video/exynos/exynos_dp_lowlevel.h @@ -74,7 +74,7 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp *dp_regs, void exynos_dp_set_video_color_format(struct exynos_dp *dp_regs, struct edp_video_info *video_info); int exynos_dp_config_video_bist(struct exynos_dp *dp_regs, - struct exynos_dp_priv *edp_info); + struct exynos_dp_priv *priv); unsigned int exynos_dp_is_slave_video_stream_clock_on( struct exynos_dp *dp_regs); void exynos_dp_set_video_cr_mn(struct exynos_dp *dp_regs, unsigned int type, diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index e13d35a..83b1187 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -35,9 +35,9 @@ struct vidinfo panel_info = { .vl_col = -1, }; -static void exynos_fimd_set_dualrgb(struct vidinfo *pvid, unsigned int enabled) +static void exynos_fimd_set_dualrgb(struct vidinfo *priv, unsigned int enabled) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; if (enabled) { @@ -45,32 +45,32 @@ static void exynos_fimd_set_dualrgb(struct vidinfo *pvid, unsigned int enabled) EXYNOS_DUALRGB_VDEN_EN_ENABLE; /* in case of Line Split mode, MAIN_CNT doesn't neet to set. */ - cfg |= EXYNOS_DUALRGB_SUB_CNT(pvid->vl_col / 2) | + cfg |= EXYNOS_DUALRGB_SUB_CNT(priv->vl_col / 2) | EXYNOS_DUALRGB_MAIN_CNT(0); } - writel(cfg, &fimd_ctrl->dualrgb); + writel(cfg, ®->dualrgb); } -static void exynos_fimd_set_dp_clkcon(struct vidinfo *pvid, +static void exynos_fimd_set_dp_clkcon(struct vidinfo *priv, unsigned int enabled) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; if (enabled) cfg = EXYNOS_DP_CLK_ENABLE; - writel(cfg, &fimd_ctrl->dp_mie_clkcon); + writel(cfg, ®->dp_mie_clkcon); } -static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) +static void exynos_fimd_set_par(struct vidinfo *priv, unsigned int win_id) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; /* set window control */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + cfg = readl((unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); cfg &= ~(EXYNOS_WINCON_BITSWP_ENABLE | EXYNOS_WINCON_BYTESWP_ENABLE | @@ -86,7 +86,7 @@ static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) /* dma burst is 16 */ cfg |= EXYNOS_WINCON_BURSTLEN_16WORD; - switch (pvid->vl_bpix) { + switch (priv->vl_bpix) { case 4: cfg |= EXYNOS_WINCON_BPPMODE_16BPP_565; break; @@ -95,72 +95,72 @@ static void exynos_fimd_set_par(struct vidinfo *pvid, unsigned int win_id) break; } - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + writel(cfg, (unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); /* set window position to x=0, y=0*/ cfg = EXYNOS_VIDOSD_LEFT_X(0) | EXYNOS_VIDOSD_TOP_Y(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0a + + writel(cfg, (unsigned int)®->vidosd0a + EXYNOS_VIDOSD(win_id)); - cfg = EXYNOS_VIDOSD_RIGHT_X(pvid->vl_col - 1) | - EXYNOS_VIDOSD_BOTTOM_Y(pvid->vl_row - 1) | + cfg = EXYNOS_VIDOSD_RIGHT_X(priv->vl_col - 1) | + EXYNOS_VIDOSD_BOTTOM_Y(priv->vl_row - 1) | EXYNOS_VIDOSD_RIGHT_X_E(1) | EXYNOS_VIDOSD_BOTTOM_Y_E(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0b + + writel(cfg, (unsigned int)®->vidosd0b + EXYNOS_VIDOSD(win_id)); /* set window size for window0*/ - cfg = EXYNOS_VIDOSD_SIZE(pvid->vl_col * pvid->vl_row); - writel(cfg, (unsigned int)&fimd_ctrl->vidosd0c + + cfg = EXYNOS_VIDOSD_SIZE(priv->vl_col * priv->vl_row); + writel(cfg, (unsigned int)®->vidosd0c + EXYNOS_VIDOSD(win_id)); } -static void exynos_fimd_set_buffer_address(struct vidinfo *pvid, +static void exynos_fimd_set_buffer_address(struct vidinfo *priv, unsigned int win_id, ulong lcd_base_addr) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned long start_addr, end_addr; start_addr = lcd_base_addr; - end_addr = start_addr + ((pvid->vl_col * (NBITS(pvid->vl_bpix) / 8)) * - pvid->vl_row); + end_addr = start_addr + ((priv->vl_col * (NBITS(priv->vl_bpix) / 8)) * + priv->vl_row); - writel(start_addr, (unsigned int)&fimd_ctrl->vidw00add0b0 + + writel(start_addr, (unsigned int)®->vidw00add0b0 + EXYNOS_BUFFER_OFFSET(win_id)); - writel(end_addr, (unsigned int)&fimd_ctrl->vidw00add1b0 + + writel(end_addr, (unsigned int)®->vidw00add1b0 + EXYNOS_BUFFER_OFFSET(win_id)); } -static void exynos_fimd_set_clock(struct vidinfo *pvid) +static void exynos_fimd_set_clock(struct vidinfo *priv) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0, div = 0, remainder, remainder_div; unsigned long pixel_clock; unsigned long long src_clock; - if (pvid->dual_lcd_enabled) { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col / 2) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); - } else if (pvid->interface_mode == FIMD_CPU_INTERFACE) { - pixel_clock = pvid->vl_freq * - pvid->vl_width * pvid->vl_height * - (pvid->cs_setup + pvid->wr_setup + - pvid->wr_act + pvid->wr_hold + 1); + if (priv->dual_lcd_enabled) { + pixel_clock = priv->vl_freq * + (priv->vl_hspw + priv->vl_hfpd + + priv->vl_hbpd + priv->vl_col / 2) * + (priv->vl_vspw + priv->vl_vfpd + + priv->vl_vbpd + priv->vl_row); + } else if (priv->interface_mode == FIMD_CPU_INTERFACE) { + pixel_clock = priv->vl_freq * + priv->vl_width * priv->vl_height * + (priv->cs_setup + priv->wr_setup + + priv->wr_act + priv->wr_hold + 1); } else { - pixel_clock = pvid->vl_freq * - (pvid->vl_hspw + pvid->vl_hfpd + - pvid->vl_hbpd + pvid->vl_col) * - (pvid->vl_vspw + pvid->vl_vfpd + - pvid->vl_vbpd + pvid->vl_row); + pixel_clock = priv->vl_freq * + (priv->vl_hspw + priv->vl_hfpd + + priv->vl_hbpd + priv->vl_col) * + (priv->vl_vspw + priv->vl_vfpd + + priv->vl_vbpd + priv->vl_row); } - cfg = readl(&fimd_ctrl->vidcon0); + cfg = readl(®->vidcon0); cfg &= ~(EXYNOS_VIDCON0_CLKSEL_MASK | EXYNOS_VIDCON0_CLKVALUP_MASK | EXYNOS_VIDCON0_CLKVAL_F(0xFF) | EXYNOS_VIDCON0_VCLKEN_MASK | EXYNOS_VIDCON0_CLKDIR_MASK); @@ -181,32 +181,32 @@ static void exynos_fimd_set_clock(struct vidinfo *pvid) div++; /* in case of dual lcd mode. */ - if (pvid->dual_lcd_enabled) + if (priv->dual_lcd_enabled) div--; cfg |= EXYNOS_VIDCON0_CLKVAL_F(div - 1); - writel(cfg, &fimd_ctrl->vidcon0); + writel(cfg, ®->vidcon0); } -void exynos_set_trigger(struct vidinfo *pvid) +void exynos_set_trigger(struct vidinfo *priv) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; - cfg = readl(&fimd_ctrl->trigcon); + cfg = readl(®->trigcon); cfg |= (EXYNOS_I80SOFT_TRIG_EN | EXYNOS_I80START_TRIG); - writel(cfg, &fimd_ctrl->trigcon); + writel(cfg, ®->trigcon); } -int exynos_is_i80_frame_done(struct vidinfo *pvid) +int exynos_is_i80_frame_done(struct vidinfo *priv) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; int status; - cfg = readl(&fimd_ctrl->trigcon); + cfg = readl(®->trigcon); /* frame done func is valid only when TRIMODE[0] is set to 1. */ status = (cfg & EXYNOS_I80STATUS_TRIG_DONE) == @@ -215,58 +215,58 @@ int exynos_is_i80_frame_done(struct vidinfo *pvid) return status; } -static void exynos_fimd_lcd_on(struct vidinfo *pvid) +static void exynos_fimd_lcd_on(struct vidinfo *priv) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; /* display on */ - cfg = readl(&fimd_ctrl->vidcon0); + cfg = readl(®->vidcon0); cfg |= (EXYNOS_VIDCON0_ENVID_ENABLE | EXYNOS_VIDCON0_ENVID_F_ENABLE); - writel(cfg, &fimd_ctrl->vidcon0); + writel(cfg, ®->vidcon0); } -static void exynos_fimd_window_on(struct vidinfo *pvid, unsigned int win_id) +static void exynos_fimd_window_on(struct vidinfo *priv, unsigned int win_id) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; /* enable window */ - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + cfg = readl((unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); cfg |= EXYNOS_WINCON_ENWIN_ENABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + writel(cfg, (unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); - cfg = readl(&fimd_ctrl->winshmap); + cfg = readl(®->winshmap); cfg |= EXYNOS_WINSHMAP_CH_ENABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); + writel(cfg, ®->winshmap); } -void exynos_fimd_lcd_off(struct vidinfo *pvid) +void exynos_fimd_lcd_off(struct vidinfo *priv) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; - cfg = readl(&fimd_ctrl->vidcon0); + cfg = readl(®->vidcon0); cfg &= (EXYNOS_VIDCON0_ENVID_DISABLE | EXYNOS_VIDCON0_ENVID_F_DISABLE); - writel(cfg, &fimd_ctrl->vidcon0); + writel(cfg, ®->vidcon0); } -void exynos_fimd_window_off(struct vidinfo *pvid, unsigned int win_id) +void exynos_fimd_window_off(struct vidinfo *priv, unsigned int win_id) { - struct exynos_fb *fimd_ctrl = pvid->fimd_ctrl; + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; - cfg = readl((unsigned int)&fimd_ctrl->wincon0 + + cfg = readl((unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); cfg &= EXYNOS_WINCON_ENWIN_DISABLE; - writel(cfg, (unsigned int)&fimd_ctrl->wincon0 + + writel(cfg, (unsigned int)®->wincon0 + EXYNOS_WINCON(win_id)); - cfg = readl(&fimd_ctrl->winshmap); + cfg = readl(®->winshmap); cfg &= ~EXYNOS_WINSHMAP_CH_DISABLE(win_id); - writel(cfg, &fimd_ctrl->winshmap); + writel(cfg, ®->winshmap); } /* @@ -307,9 +307,9 @@ void exynos_fimd_disable_sysmmu(void) } } -void exynos_fimd_lcd_init(struct vidinfo *pvid, ulong lcd_base_address) +void exynos_fimd_lcd_init(struct vidinfo *priv, ulong lcd_base_address) { - struct exynos_fb *fimd_ctrl; + struct exynos_fb *reg; unsigned int cfg = 0, rgb_mode; unsigned int offset; unsigned int node; @@ -319,105 +319,105 @@ void exynos_fimd_lcd_init(struct vidinfo *pvid, ulong lcd_base_address) if (node <= 0) debug("exynos_fb: Can't get device node for fimd\n"); - fimd_ctrl = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, + reg = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (fimd_ctrl == NULL) + if (reg == NULL) debug("Can't get the FIMD base address\n"); - pvid->fimd_ctrl = fimd_ctrl; + priv->reg = reg; if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) exynos_fimd_disable_sysmmu(); offset = exynos_fimd_get_base_offset(); - rgb_mode = pvid->rgb_mode; + rgb_mode = priv->rgb_mode; - if (pvid->interface_mode == FIMD_RGB_INTERFACE) { + if (priv->interface_mode == FIMD_RGB_INTERFACE) { cfg |= EXYNOS_VIDCON0_VIDOUT_RGB; - writel(cfg, &fimd_ctrl->vidcon0); + writel(cfg, ®->vidcon0); - cfg = readl(&fimd_ctrl->vidcon2); + cfg = readl(®->vidcon2); cfg &= ~(EXYNOS_VIDCON2_WB_MASK | EXYNOS_VIDCON2_TVFORMATSEL_MASK | EXYNOS_VIDCON2_TVFORMATSEL_YUV_MASK); cfg |= EXYNOS_VIDCON2_WB_DISABLE; - writel(cfg, &fimd_ctrl->vidcon2); + writel(cfg, ®->vidcon2); /* set polarity */ cfg = 0; - if (!pvid->vl_clkp) + if (!priv->vl_clkp) cfg |= EXYNOS_VIDCON1_IVCLK_RISING_EDGE; - if (!pvid->vl_hsp) + if (!priv->vl_hsp) cfg |= EXYNOS_VIDCON1_IHSYNC_INVERT; - if (!pvid->vl_vsp) + if (!priv->vl_vsp) cfg |= EXYNOS_VIDCON1_IVSYNC_INVERT; - if (!pvid->vl_dp) + if (!priv->vl_dp) cfg |= EXYNOS_VIDCON1_IVDEN_INVERT; - writel(cfg, (unsigned int)&fimd_ctrl->vidcon1 + offset); + writel(cfg, (unsigned int)®->vidcon1 + offset); /* set timing */ - cfg = EXYNOS_VIDTCON0_VFPD(pvid->vl_vfpd - 1); - cfg |= EXYNOS_VIDTCON0_VBPD(pvid->vl_vbpd - 1); - cfg |= EXYNOS_VIDTCON0_VSPW(pvid->vl_vspw - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon0 + offset); + cfg = EXYNOS_VIDTCON0_VFPD(priv->vl_vfpd - 1); + cfg |= EXYNOS_VIDTCON0_VBPD(priv->vl_vbpd - 1); + cfg |= EXYNOS_VIDTCON0_VSPW(priv->vl_vspw - 1); + writel(cfg, (unsigned int)®->vidtcon0 + offset); - cfg = EXYNOS_VIDTCON1_HFPD(pvid->vl_hfpd - 1); - cfg |= EXYNOS_VIDTCON1_HBPD(pvid->vl_hbpd - 1); - cfg |= EXYNOS_VIDTCON1_HSPW(pvid->vl_hspw - 1); + cfg = EXYNOS_VIDTCON1_HFPD(priv->vl_hfpd - 1); + cfg |= EXYNOS_VIDTCON1_HBPD(priv->vl_hbpd - 1); + cfg |= EXYNOS_VIDTCON1_HSPW(priv->vl_hspw - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon1 + offset); + writel(cfg, (unsigned int)®->vidtcon1 + offset); /* set lcd size */ - cfg = EXYNOS_VIDTCON2_HOZVAL(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL(pvid->vl_row - 1) | - EXYNOS_VIDTCON2_HOZVAL_E(pvid->vl_col - 1) | - EXYNOS_VIDTCON2_LINEVAL_E(pvid->vl_row - 1); + cfg = EXYNOS_VIDTCON2_HOZVAL(priv->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL(priv->vl_row - 1) | + EXYNOS_VIDTCON2_HOZVAL_E(priv->vl_col - 1) | + EXYNOS_VIDTCON2_LINEVAL_E(priv->vl_row - 1); - writel(cfg, (unsigned int)&fimd_ctrl->vidtcon2 + offset); + writel(cfg, (unsigned int)®->vidtcon2 + offset); } /* set display mode */ - cfg = readl(&fimd_ctrl->vidcon0); + cfg = readl(®->vidcon0); cfg &= ~EXYNOS_VIDCON0_PNRMODE_MASK; cfg |= (rgb_mode << EXYNOS_VIDCON0_PNRMODE_SHIFT); - writel(cfg, &fimd_ctrl->vidcon0); + writel(cfg, ®->vidcon0); /* set par */ - exynos_fimd_set_par(pvid, pvid->win_id); + exynos_fimd_set_par(priv, priv->win_id); /* set memory address */ - exynos_fimd_set_buffer_address(pvid, pvid->win_id, lcd_base_address); + exynos_fimd_set_buffer_address(priv, priv->win_id, lcd_base_address); /* set buffer size */ - cfg = EXYNOS_VIDADDR_PAGEWIDTH(pvid->vl_col * - NBITS(pvid->vl_bpix) / 8) | - EXYNOS_VIDADDR_PAGEWIDTH_E(pvid->vl_col * - NBITS(pvid->vl_bpix) / 8) | + cfg = EXYNOS_VIDADDR_PAGEWIDTH(priv->vl_col * + NBITS(priv->vl_bpix) / 8) | + EXYNOS_VIDADDR_PAGEWIDTH_E(priv->vl_col * + NBITS(priv->vl_bpix) / 8) | EXYNOS_VIDADDR_OFFSIZE(0) | EXYNOS_VIDADDR_OFFSIZE_E(0); - writel(cfg, (unsigned int)&fimd_ctrl->vidw00add2 + - EXYNOS_BUFFER_SIZE(pvid->win_id)); + writel(cfg, (unsigned int)®->vidw00add2 + + EXYNOS_BUFFER_SIZE(priv->win_id)); /* set clock */ - exynos_fimd_set_clock(pvid); + exynos_fimd_set_clock(priv); /* set rgb mode to dual lcd. */ - exynos_fimd_set_dualrgb(pvid, pvid->dual_lcd_enabled); + exynos_fimd_set_dualrgb(priv, priv->dual_lcd_enabled); /* display on */ - exynos_fimd_lcd_on(pvid); + exynos_fimd_lcd_on(priv); /* window on */ - exynos_fimd_window_on(pvid, pvid->win_id); + exynos_fimd_window_on(priv, priv->win_id); - exynos_fimd_set_dp_clkcon(pvid, pvid->dp_enabled); + exynos_fimd_set_dp_clkcon(priv, priv->dp_enabled); } -unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid) +unsigned long exynos_fimd_calc_fbsize(struct vidinfo *priv) { - return pvid->vl_col * pvid->vl_row * (NBITS(pvid->vl_bpix) / 8); + return priv->vl_col * priv->vl_row * (NBITS(priv->vl_bpix) / 8); } ushort *configuration_get_cmap(void) -- cgit v1.1 From bb5930d5c97fa22ed2fe048106fcabb5b7c77c96 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:09:01 -0700 Subject: exynos: video: Convert several boards to driver model for video Update several boards to use driver model for video. This involves changes to the EDP and FIMD (frame buffer) drivers. Existing PWM, simple-panel and pwm-backlight drivers are used. These work without additional configuration since they use the device tree settings in the same way as Linux. Boards converted are: - snow - spring - peach-pit - peach-pi All have been tested. Not converted: - MIPI display driver - s5pc210_universal - smdk5420 - smdk5250 - trats - trats2 Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_dp.c | 146 +++++++++++--- drivers/video/exynos/exynos_fb.c | 407 +++++++++++++++++++++++---------------- drivers/video/simple_panel.c | 2 + 3 files changed, 357 insertions(+), 198 deletions(-) (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index d7bccc3..fc39f2c 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -7,17 +7,21 @@ */ #include +#include #include +#include +#include +#include #include +#include #include #include #include #include #include #include +#include #include -#include -#include #include "exynos_dp_lowlevel.h" @@ -872,15 +876,19 @@ static unsigned int exynos_dp_config_video(struct exynos_dp *regs, return ret; } -int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *priv) +static int exynos_dp_ofdata_to_platdata(struct udevice *dev) { - unsigned int node = fdtdec_next_compatible(blob, 0, - COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) { - debug("exynos_dp: Can't get device node for dp\n"); - return -ENODEV; - } + struct exynos_dp_priv *priv = dev_get_priv(dev); + const void *blob = gd->fdt_blob; + unsigned int node = dev->of_offset; + fdt_addr_t addr; + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) { + debug("Can't get the DP base address\n"); + return -EINVAL; + } + priv->regs = (struct exynos_dp *)addr; priv->disp_info.h_res = fdtdec_get_int(blob, node, "samsung,h-res", 0); priv->disp_info.h_sync_width = fdtdec_get_int(blob, node, @@ -926,34 +934,97 @@ int exynos_dp_parse_dt(const void *blob, struct exynos_dp_priv *priv) return 0; } -unsigned int exynos_init_dp(void) +static int exynos_dp_bridge_init(struct udevice *dev) { - unsigned int ret; - struct exynos_dp_priv *priv; - struct exynos_dp *regs; - int node; + const int max_tries = 10; + int num_tries; + int ret; - priv = kzalloc(sizeof(struct exynos_dp_priv), GFP_KERNEL); - if (!priv) { - debug("failed to allocate edp device object.\n"); - return -EFAULT; + debug("%s\n", __func__); + ret = video_bridge_attach(dev); + if (ret) { + debug("video bridge init failed: %d\n", ret); + return ret; } - if (exynos_dp_parse_dt(gd->fdt_blob, priv)) - debug("unable to parse DP DT node\n"); + /* + * We need to wait for 90ms after bringing up the bridge since there + * is a phantom "high" on the HPD chip during its bootup. The phantom + * high comes within 7ms of de-asserting PD and persists for at least + * 15ms. The real high comes roughly 50ms after PD is de-asserted. The + * phantom high makes it hard for us to know when the NXP chip is up. + */ + mdelay(90); - node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_SAMSUNG_EXYNOS5_DP); - if (node <= 0) - debug("exynos_dp: Can't get device node for dp\n"); + for (num_tries = 0; num_tries < max_tries; num_tries++) { + /* Check HPD. If it's high, or we don't have it, all is well */ + ret = video_bridge_check_attached(dev); + if (!ret || ret == -ENOENT) + return 0; - regs = (struct exynos_dp *)fdtdec_get_addr(gd->fdt_blob, node, - "reg"); - if (regs == NULL) - debug("Can't get the DP base address\n"); + debug("%s: eDP bridge failed to come up; try %d of %d\n", + __func__, num_tries, max_tries); + } + + /* Immediately go into bridge reset if the hp line is not high */ + return -EIO; +} + +static int exynos_dp_bridge_setup(const void *blob) +{ + const int max_tries = 2; + int num_tries; + struct udevice *dev; + int ret; + + /* Configure I2C registers for Parade bridge */ + ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &dev); + if (ret) { + debug("video bridge init failed: %d\n", ret); + return ret; + } + + if (strncmp(dev->driver->name, "parade", 6)) { + /* Mux HPHPD to the special hotplug detect mode */ + exynos_pinmux_config(PERIPH_ID_DPHPD, 0); + } + + for (num_tries = 0; num_tries < max_tries; num_tries++) { + ret = exynos_dp_bridge_init(dev); + if (!ret) + return 0; + if (num_tries == max_tries - 1) + break; + + /* + * If we're here, the bridge chip failed to initialise. + * Power down the bridge in an attempt to reset. + */ + video_bridge_set_active(dev, false); + + /* + * Arbitrarily wait 300ms here with DP_N low. Don't know for + * sure how long we should wait, but we're being paranoid. + */ + mdelay(300); + } + return ret; +} +int exynos_dp_enable(struct udevice *dev, int panel_bpp, + const struct display_timing *timing) +{ + struct exynos_dp_priv *priv = dev_get_priv(dev); + struct exynos_dp *regs = priv->regs; + unsigned int ret; + + debug("%s: start\n", __func__); exynos_dp_disp_info(&priv->disp_info); + ret = exynos_dp_bridge_setup(gd->fdt_blob); + if (ret && ret != -ENODEV) + printf("LCD bridge failed to enable: %d\n", ret); + exynos_dp_phy_ctrl(1); ret = exynos_dp_init_dp(regs); @@ -992,3 +1063,22 @@ unsigned int exynos_init_dp(void) return ret; } + + +static const struct dm_display_ops exynos_dp_ops = { + .enable = exynos_dp_enable, +}; + +static const struct udevice_id exynos_dp_ids[] = { + { .compatible = "samsung,exynos5-dp" }, + { } +}; + +U_BOOT_DRIVER(exynos_dp) = { + .name = "eexynos_dp", + .id = UCLASS_DISPLAY, + .of_match = exynos_dp_ids, + .ops = &exynos_dp_ops, + .ofdata_to_platdata = exynos_dp_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_dp_priv), +}; diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index 83b1187..c8fef63 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -9,33 +9,98 @@ #include #include +#include #include -#include +#include #include #include +#include +#include +#include #include #include #include #include #include #include +#include +#include #include #include #include -#include "exynos_fb.h" - DECLARE_GLOBAL_DATA_PTR; -struct vidinfo panel_info = { - /* - * Insert a value here so that we don't end up in the BSS - * Reference: drivers/video/tegra.c - */ - .vl_col = -1, +enum { + FIMD_RGB_INTERFACE = 1, + FIMD_CPU_INTERFACE = 2, +}; + +enum exynos_fb_rgb_mode_t { + MODE_RGB_P = 0, + MODE_BGR_P = 1, + MODE_RGB_S = 2, + MODE_BGR_S = 3, }; -static void exynos_fimd_set_dualrgb(struct vidinfo *priv, unsigned int enabled) +struct exynos_fb_priv { + ushort vl_col; /* Number of columns (i.e. 640) */ + ushort vl_row; /* Number of rows (i.e. 480) */ + ushort vl_rot; /* Rotation of Display (0, 1, 2, 3) */ + ushort vl_width; /* Width of display area in millimeters */ + ushort vl_height; /* Height of display area in millimeters */ + + /* LCD configuration register */ + u_char vl_freq; /* Frequency */ + u_char vl_clkp; /* Clock polarity */ + u_char vl_oep; /* Output Enable polarity */ + u_char vl_hsp; /* Horizontal Sync polarity */ + u_char vl_vsp; /* Vertical Sync polarity */ + u_char vl_dp; /* Data polarity */ + u_char vl_bpix; /* Bits per pixel */ + + /* Horizontal control register. Timing from data sheet */ + u_char vl_hspw; /* Horz sync pulse width */ + u_char vl_hfpd; /* Wait before of line */ + u_char vl_hbpd; /* Wait end of line */ + + /* Vertical control register. */ + u_char vl_vspw; /* Vertical sync pulse width */ + u_char vl_vfpd; /* Wait before of frame */ + u_char vl_vbpd; /* Wait end of frame */ + u_char vl_cmd_allow_len; /* Wait end of frame */ + + unsigned int win_id; + unsigned int init_delay; + unsigned int power_on_delay; + unsigned int reset_delay; + unsigned int interface_mode; + unsigned int mipi_enabled; + unsigned int dp_enabled; + unsigned int cs_setup; + unsigned int wr_setup; + unsigned int wr_act; + unsigned int wr_hold; + unsigned int logo_on; + unsigned int logo_width; + unsigned int logo_height; + int logo_x_offset; + int logo_y_offset; + unsigned long logo_addr; + unsigned int rgb_mode; + unsigned int resolution; + + /* parent clock name(MPLL, EPLL or VPLL) */ + unsigned int pclk_name; + /* ratio value for source clock from parent clock. */ + unsigned int sclk_div; + + unsigned int dual_lcd_enabled; + struct exynos_fb *reg; + struct exynos_platform_mipi_dsim *dsim_platform_data_dt; +}; + +static void exynos_fimd_set_dualrgb(struct exynos_fb_priv *priv, bool enabled) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -52,7 +117,7 @@ static void exynos_fimd_set_dualrgb(struct vidinfo *priv, unsigned int enabled) writel(cfg, ®->dualrgb); } -static void exynos_fimd_set_dp_clkcon(struct vidinfo *priv, +static void exynos_fimd_set_dp_clkcon(struct exynos_fb_priv *priv, unsigned int enabled) { struct exynos_fb *reg = priv->reg; @@ -64,7 +129,8 @@ static void exynos_fimd_set_dp_clkcon(struct vidinfo *priv, writel(cfg, ®->dp_mie_clkcon); } -static void exynos_fimd_set_par(struct vidinfo *priv, unsigned int win_id) +static void exynos_fimd_set_par(struct exynos_fb_priv *priv, + unsigned int win_id) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -117,7 +183,7 @@ static void exynos_fimd_set_par(struct vidinfo *priv, unsigned int win_id) EXYNOS_VIDOSD(win_id)); } -static void exynos_fimd_set_buffer_address(struct vidinfo *priv, +static void exynos_fimd_set_buffer_address(struct exynos_fb_priv *priv, unsigned int win_id, ulong lcd_base_addr) { @@ -125,7 +191,7 @@ static void exynos_fimd_set_buffer_address(struct vidinfo *priv, unsigned long start_addr, end_addr; start_addr = lcd_base_addr; - end_addr = start_addr + ((priv->vl_col * (NBITS(priv->vl_bpix) / 8)) * + end_addr = start_addr + ((priv->vl_col * (VNBITS(priv->vl_bpix) / 8)) * priv->vl_row); writel(start_addr, (unsigned int)®->vidw00add0b0 + @@ -134,7 +200,7 @@ static void exynos_fimd_set_buffer_address(struct vidinfo *priv, EXYNOS_BUFFER_OFFSET(win_id)); } -static void exynos_fimd_set_clock(struct vidinfo *priv) +static void exynos_fimd_set_clock(struct exynos_fb_priv *priv) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0, div = 0, remainder, remainder_div; @@ -188,7 +254,7 @@ static void exynos_fimd_set_clock(struct vidinfo *priv) writel(cfg, ®->vidcon0); } -void exynos_set_trigger(struct vidinfo *priv) +void exynos_set_trigger(struct exynos_fb_priv *priv) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -200,7 +266,7 @@ void exynos_set_trigger(struct vidinfo *priv) writel(cfg, ®->trigcon); } -int exynos_is_i80_frame_done(struct vidinfo *priv) +int exynos_is_i80_frame_done(struct exynos_fb_priv *priv) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -215,7 +281,7 @@ int exynos_is_i80_frame_done(struct vidinfo *priv) return status; } -static void exynos_fimd_lcd_on(struct vidinfo *priv) +static void exynos_fimd_lcd_on(struct exynos_fb_priv *priv) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -226,7 +292,8 @@ static void exynos_fimd_lcd_on(struct vidinfo *priv) writel(cfg, ®->vidcon0); } -static void exynos_fimd_window_on(struct vidinfo *priv, unsigned int win_id) +static void exynos_fimd_window_on(struct exynos_fb_priv *priv, + unsigned int win_id) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -243,7 +310,7 @@ static void exynos_fimd_window_on(struct vidinfo *priv, unsigned int win_id) writel(cfg, ®->winshmap); } -void exynos_fimd_lcd_off(struct vidinfo *priv) +void exynos_fimd_lcd_off(struct exynos_fb_priv *priv) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -253,7 +320,7 @@ void exynos_fimd_lcd_off(struct vidinfo *priv) writel(cfg, ®->vidcon0); } -void exynos_fimd_window_off(struct vidinfo *priv, unsigned int win_id) +void exynos_fimd_window_off(struct exynos_fb_priv *priv, unsigned int win_id) { struct exynos_fb *reg = priv->reg; unsigned int cfg = 0; @@ -307,24 +374,16 @@ void exynos_fimd_disable_sysmmu(void) } } -void exynos_fimd_lcd_init(struct vidinfo *priv, ulong lcd_base_address) +void exynos_fimd_lcd_init(struct udevice *dev) { - struct exynos_fb *reg; + struct exynos_fb_priv *priv = dev_get_priv(dev); + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct exynos_fb *reg = priv->reg; unsigned int cfg = 0, rgb_mode; unsigned int offset; unsigned int node; - node = fdtdec_next_compatible(gd->fdt_blob, - 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) - debug("exynos_fb: Can't get device node for fimd\n"); - - reg = (struct exynos_fb *)fdtdec_get_addr(gd->fdt_blob, node, - "reg"); - if (reg == NULL) - debug("Can't get the FIMD base address\n"); - priv->reg = reg; - + node = dev->of_offset; if (fdtdec_get_bool(gd->fdt_blob, node, "samsung,disable-sysmmu")) exynos_fimd_disable_sysmmu(); @@ -387,13 +446,13 @@ void exynos_fimd_lcd_init(struct vidinfo *priv, ulong lcd_base_address) exynos_fimd_set_par(priv, priv->win_id); /* set memory address */ - exynos_fimd_set_buffer_address(priv, priv->win_id, lcd_base_address); + exynos_fimd_set_buffer_address(priv, priv->win_id, plat->base); /* set buffer size */ cfg = EXYNOS_VIDADDR_PAGEWIDTH(priv->vl_col * - NBITS(priv->vl_bpix) / 8) | + VNBITS(priv->vl_bpix) / 8) | EXYNOS_VIDADDR_PAGEWIDTH_E(priv->vl_col * - NBITS(priv->vl_bpix) / 8) | + VNBITS(priv->vl_bpix) / 8) | EXYNOS_VIDADDR_OFFSIZE(0) | EXYNOS_VIDADDR_OFFSIZE_E(0); @@ -415,26 +474,9 @@ void exynos_fimd_lcd_init(struct vidinfo *priv, ulong lcd_base_address) exynos_fimd_set_dp_clkcon(priv, priv->dp_enabled); } -unsigned long exynos_fimd_calc_fbsize(struct vidinfo *priv) -{ - return priv->vl_col * priv->vl_row * (NBITS(priv->vl_bpix) / 8); -} - -ushort *configuration_get_cmap(void) -{ -#if defined(CONFIG_LCD_LOGO) - return bmp_logo_palette; -#else - return NULL; -#endif -} - -static void exynos_lcd_init(struct vidinfo *vid, ulong lcd_base) +unsigned long exynos_fimd_calc_fbsize(struct exynos_fb_priv *priv) { - exynos_fimd_lcd_init(vid, lcd_base); - - /* Enable flushing after LCD writes if requested */ - lcd_set_flush_dcache(1); + return priv->vl_col * priv->vl_row * (VNBITS(priv->vl_bpix) / 8); } __weak void exynos_cfg_lcd_gpio(void) @@ -470,217 +512,242 @@ __weak int exynos_lcd_misc_init(struct vidinfo *vid) return 0; } -static void lcd_panel_on(struct vidinfo *vid) +int exynos_fb_ofdata_to_platdata(struct udevice *dev) { - struct gpio_desc pwm_out_gpio; - struct gpio_desc bl_en_gpio; - unsigned int node; - - udelay(vid->init_delay); - - exynos_backlight_reset(); - - exynos_cfg_lcd_gpio(); - - exynos_lcd_power_on(); - - udelay(vid->power_on_delay); - - if (vid->dp_enabled) - exynos_init_dp(); - - exynos_reset_lcd(); - - udelay(vid->reset_delay); - - exynos_backlight_on(1); - - node = fdtdec_next_compatible(gd->fdt_blob, 0, - COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("FIMD: Can't get device node for FIMD\n"); - return; - } - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,pwm-out-gpio", - 0, &pwm_out_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - - gpio_request_by_name_nodev(gd->fdt_blob, node, "samsung,bl-en-gpio", 0, - &bl_en_gpio, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - - exynos_cfg_ldo(); + struct exynos_fb_priv *priv = dev_get_priv(dev); + unsigned int node = dev->of_offset; + const void *blob = gd->fdt_blob; + fdt_addr_t addr; - exynos_enable_ldo(1); - - if (vid->mipi_enabled) - exynos_mipi_dsi_init(panel_info.dsim_platform_data_dt); -} - -int exynos_lcd_early_init(const void *blob) -{ - unsigned int node; - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_FIMD); - if (node <= 0) { - debug("exynos_fb: Can't get device node for fimd\n"); - return -ENODEV; + addr = dev_get_addr(dev); + if (addr == FDT_ADDR_T_NONE) { + debug("Can't get the FIMD base address\n"); + return -EINVAL; } + priv->reg = (struct exynos_fb *)addr; - panel_info.vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); - if (panel_info.vl_col == 0) { + priv->vl_col = fdtdec_get_int(blob, node, "samsung,vl-col", 0); + if (priv->vl_col == 0) { debug("Can't get XRES\n"); return -ENXIO; } - panel_info.vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); - if (panel_info.vl_row == 0) { + priv->vl_row = fdtdec_get_int(blob, node, "samsung,vl-row", 0); + if (priv->vl_row == 0) { debug("Can't get YRES\n"); return -ENXIO; } - panel_info.vl_width = fdtdec_get_int(blob, node, + priv->vl_width = fdtdec_get_int(blob, node, "samsung,vl-width", 0); - panel_info.vl_height = fdtdec_get_int(blob, node, + priv->vl_height = fdtdec_get_int(blob, node, "samsung,vl-height", 0); - panel_info.vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); - if (panel_info.vl_freq == 0) { + priv->vl_freq = fdtdec_get_int(blob, node, "samsung,vl-freq", 0); + if (priv->vl_freq == 0) { debug("Can't get refresh rate\n"); return -ENXIO; } if (fdtdec_get_bool(blob, node, "samsung,vl-clkp")) - panel_info.vl_clkp = CONFIG_SYS_LOW; + priv->vl_clkp = VIDEO_ACTIVE_LOW; if (fdtdec_get_bool(blob, node, "samsung,vl-oep")) - panel_info.vl_oep = CONFIG_SYS_LOW; + priv->vl_oep = VIDEO_ACTIVE_LOW; if (fdtdec_get_bool(blob, node, "samsung,vl-hsp")) - panel_info.vl_hsp = CONFIG_SYS_LOW; + priv->vl_hsp = VIDEO_ACTIVE_LOW; if (fdtdec_get_bool(blob, node, "samsung,vl-vsp")) - panel_info.vl_vsp = CONFIG_SYS_LOW; + priv->vl_vsp = VIDEO_ACTIVE_LOW; if (fdtdec_get_bool(blob, node, "samsung,vl-dp")) - panel_info.vl_dp = CONFIG_SYS_LOW; + priv->vl_dp = VIDEO_ACTIVE_LOW; - panel_info.vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); - if (panel_info.vl_bpix == 0) { + priv->vl_bpix = fdtdec_get_int(blob, node, "samsung,vl-bpix", 0); + if (priv->vl_bpix == 0) { debug("Can't get bits per pixel\n"); return -ENXIO; } - panel_info.vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); - if (panel_info.vl_hspw == 0) { + priv->vl_hspw = fdtdec_get_int(blob, node, "samsung,vl-hspw", 0); + if (priv->vl_hspw == 0) { debug("Can't get hsync width\n"); return -ENXIO; } - panel_info.vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); - if (panel_info.vl_hfpd == 0) { + priv->vl_hfpd = fdtdec_get_int(blob, node, "samsung,vl-hfpd", 0); + if (priv->vl_hfpd == 0) { debug("Can't get right margin\n"); return -ENXIO; } - panel_info.vl_hbpd = (u_char)fdtdec_get_int(blob, node, + priv->vl_hbpd = (u_char)fdtdec_get_int(blob, node, "samsung,vl-hbpd", 0); - if (panel_info.vl_hbpd == 0) { + if (priv->vl_hbpd == 0) { debug("Can't get left margin\n"); return -ENXIO; } - panel_info.vl_vspw = (u_char)fdtdec_get_int(blob, node, + priv->vl_vspw = (u_char)fdtdec_get_int(blob, node, "samsung,vl-vspw", 0); - if (panel_info.vl_vspw == 0) { + if (priv->vl_vspw == 0) { debug("Can't get vsync width\n"); return -ENXIO; } - panel_info.vl_vfpd = fdtdec_get_int(blob, node, + priv->vl_vfpd = fdtdec_get_int(blob, node, "samsung,vl-vfpd", 0); - if (panel_info.vl_vfpd == 0) { + if (priv->vl_vfpd == 0) { debug("Can't get lower margin\n"); return -ENXIO; } - panel_info.vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); - if (panel_info.vl_vbpd == 0) { + priv->vl_vbpd = fdtdec_get_int(blob, node, "samsung,vl-vbpd", 0); + if (priv->vl_vbpd == 0) { debug("Can't get upper margin\n"); return -ENXIO; } - panel_info.vl_cmd_allow_len = fdtdec_get_int(blob, node, + priv->vl_cmd_allow_len = fdtdec_get_int(blob, node, "samsung,vl-cmd-allow-len", 0); - panel_info.win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); - panel_info.init_delay = fdtdec_get_int(blob, node, + priv->win_id = fdtdec_get_int(blob, node, "samsung,winid", 0); + priv->init_delay = fdtdec_get_int(blob, node, "samsung,init-delay", 0); - panel_info.power_on_delay = fdtdec_get_int(blob, node, + priv->power_on_delay = fdtdec_get_int(blob, node, "samsung,power-on-delay", 0); - panel_info.reset_delay = fdtdec_get_int(blob, node, + priv->reset_delay = fdtdec_get_int(blob, node, "samsung,reset-delay", 0); - panel_info.interface_mode = fdtdec_get_int(blob, node, + priv->interface_mode = fdtdec_get_int(blob, node, "samsung,interface-mode", 0); - panel_info.mipi_enabled = fdtdec_get_int(blob, node, + priv->mipi_enabled = fdtdec_get_int(blob, node, "samsung,mipi-enabled", 0); - panel_info.dp_enabled = fdtdec_get_int(blob, node, + priv->dp_enabled = fdtdec_get_int(blob, node, "samsung,dp-enabled", 0); - panel_info.cs_setup = fdtdec_get_int(blob, node, + priv->cs_setup = fdtdec_get_int(blob, node, "samsung,cs-setup", 0); - panel_info.wr_setup = fdtdec_get_int(blob, node, + priv->wr_setup = fdtdec_get_int(blob, node, "samsung,wr-setup", 0); - panel_info.wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); - panel_info.wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); + priv->wr_act = fdtdec_get_int(blob, node, "samsung,wr-act", 0); + priv->wr_hold = fdtdec_get_int(blob, node, "samsung,wr-hold", 0); - panel_info.logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); - if (panel_info.logo_on) { - panel_info.logo_width = fdtdec_get_int(blob, node, + priv->logo_on = fdtdec_get_int(blob, node, "samsung,logo-on", 0); + if (priv->logo_on) { + priv->logo_width = fdtdec_get_int(blob, node, "samsung,logo-width", 0); - panel_info.logo_height = fdtdec_get_int(blob, node, + priv->logo_height = fdtdec_get_int(blob, node, "samsung,logo-height", 0); - panel_info.logo_addr = fdtdec_get_int(blob, node, + priv->logo_addr = fdtdec_get_int(blob, node, "samsung,logo-addr", 0); } - panel_info.rgb_mode = fdtdec_get_int(blob, node, + priv->rgb_mode = fdtdec_get_int(blob, node, "samsung,rgb-mode", 0); - panel_info.pclk_name = fdtdec_get_int(blob, node, + priv->pclk_name = fdtdec_get_int(blob, node, "samsung,pclk-name", 0); - panel_info.sclk_div = fdtdec_get_int(blob, node, + priv->sclk_div = fdtdec_get_int(blob, node, "samsung,sclk-div", 0); - panel_info.dual_lcd_enabled = fdtdec_get_int(blob, node, + priv->dual_lcd_enabled = fdtdec_get_int(blob, node, "samsung,dual-lcd-enabled", 0); return 0; } -void lcd_ctrl_init(void *lcdbase) +static int exynos_fb_probe(struct udevice *dev) { + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct exynos_fb_priv *priv = dev_get_priv(dev); + struct udevice *panel, *bridge; + struct udevice *dp; + int ret; + + debug("%s: start\n", __func__); set_system_display_ctrl(); set_lcd_clk(); #ifdef CONFIG_EXYNOS_MIPI_DSIM exynos_init_dsim_platform_data(&panel_info); #endif - exynos_lcd_misc_init(&panel_info); + exynos_fimd_lcd_init(dev); - exynos_lcd_init(&panel_info, (ulong)lcdbase); -} + ret = uclass_first_device(UCLASS_PANEL, &panel); + if (ret) { + printf("LCD panel failed to probe\n"); + return ret; + } + if (!panel) { + printf("LCD panel not found\n"); + return -ENODEV; + } -void lcd_enable(void) -{ - if (panel_info.logo_on) { - memset((void *)gd->fb_base, 0, - panel_info.vl_width * panel_info.vl_height * - (NBITS(panel_info.vl_bpix) >> 3)); + ret = uclass_first_device(UCLASS_DISPLAY, &dp); + if (ret) { + debug("%s: Display device error %d\n", __func__, ret); + return ret; + } + if (!dev) { + debug("%s: Display device missing\n", __func__); + return -ENODEV; + } + ret = display_enable(dp, 18, NULL); + if (ret) { + debug("%s: Display enable error %d\n", __func__, ret); + return ret; } - lcd_panel_on(&panel_info); + /* backlight / pwm */ + ret = panel_enable_backlight(panel); + if (ret) { + debug("%s: backlight error: %d\n", __func__, ret); + return ret; + } + + ret = uclass_get_device(UCLASS_VIDEO_BRIDGE, 0, &bridge); + if (!ret) + ret = video_bridge_set_backlight(bridge, 80); + if (ret) { + debug("%s: No video bridge, or no backlight on bridge\n", + __func__); + exynos_pinmux_config(PERIPH_ID_PWM0, 0); + } + + uc_priv->xsize = priv->vl_col; + uc_priv->ysize = priv->vl_row; + uc_priv->bpix = priv->vl_bpix; + + /* Enable flushing after LCD writes if requested */ + video_set_flush_dcache(dev, true); + + return 0; } -/* dummy function */ -void lcd_setcolreg(ushort regno, ushort red, ushort green, ushort blue) +static int exynos_fb_bind(struct udevice *dev) { - return; + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + + /* This is the maximum panel size we expect to see */ + plat->size = 1920 * 1080 * 2; + + return 0; } + +static const struct video_ops exynos_fb_ops = { +}; + +static const struct udevice_id exynos_fb_ids[] = { + { .compatible = "samsung,exynos-fimd" }, + { } +}; + +U_BOOT_DRIVER(exynos_fb) = { + .name = "exynos_fb", + .id = UCLASS_VIDEO, + .of_match = exynos_fb_ids, + .ops = &exynos_fb_ops, + .bind = exynos_fb_bind, + .probe = exynos_fb_probe, + .ofdata_to_platdata = exynos_fb_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct exynos_fb_priv), +}; diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index 6219300..b2fe345 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -88,6 +88,8 @@ static const struct panel_ops simple_panel_ops = { static const struct udevice_id simple_panel_ids[] = { { .compatible = "simple-panel" }, { .compatible = "auo,b133xtn01" }, + { .compatible = "auo,b116xw03" }, + { .compatible = "auo,b133htn01" }, { } }; -- cgit v1.1 From f4f2fce70ccf793b10a59e48eb12fd8daa0b1f34 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Feb 2016 21:09:02 -0700 Subject: exynos: video: Drop old unused code Now that we are using driver model, we can drop the weak functions and LCD init in the board file. Signed-off-by: Simon Glass Acked-by: Anatolij Gustschin Signed-off-by: Minkyu Kang --- drivers/video/exynos/exynos_fb.c | 33 -------------------------------- drivers/video/exynos/exynos_fb.h | 41 ---------------------------------------- 2 files changed, 74 deletions(-) delete mode 100644 drivers/video/exynos/exynos_fb.h (limited to 'drivers/video') diff --git a/drivers/video/exynos/exynos_fb.c b/drivers/video/exynos/exynos_fb.c index c8fef63..97228cd 100644 --- a/drivers/video/exynos/exynos_fb.c +++ b/drivers/video/exynos/exynos_fb.c @@ -479,39 +479,6 @@ unsigned long exynos_fimd_calc_fbsize(struct exynos_fb_priv *priv) return priv->vl_col * priv->vl_row * (VNBITS(priv->vl_bpix) / 8); } -__weak void exynos_cfg_lcd_gpio(void) -{ -} - -__weak void exynos_backlight_on(unsigned int onoff) -{ -} - -__weak void exynos_reset_lcd(void) -{ -} - -__weak void exynos_lcd_power_on(void) -{ -} - -__weak void exynos_cfg_ldo(void) -{ -} - -__weak void exynos_enable_ldo(unsigned int onoff) -{ -} - -__weak void exynos_backlight_reset(void) -{ -} - -__weak int exynos_lcd_misc_init(struct vidinfo *vid) -{ - return 0; -} - int exynos_fb_ofdata_to_platdata(struct udevice *dev) { struct exynos_fb_priv *priv = dev_get_priv(dev); diff --git a/drivers/video/exynos/exynos_fb.h b/drivers/video/exynos/exynos_fb.h deleted file mode 100644 index f59cce0..0000000 --- a/drivers/video/exynos/exynos_fb.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 Samsung Electronics - * - * Author: InKi Dae - * Author: Donghwa Lee - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef _EXYNOS_FB_H_ -#define _EXYNOS_FB_H_ - -#include - -#define MAX_CLOCK (86 * 1000000) - -enum exynos_cpu_auto_cmd_rate { - DISABLE_AUTO_FRM, - PER_TWO_FRM, - PER_FOUR_FRM, - PER_SIX_FRM, - PER_EIGHT_FRM, - PER_TEN_FRM, - PER_TWELVE_FRM, - PER_FOURTEEN_FRM, - PER_SIXTEEN_FRM, - PER_EIGHTEEN_FRM, - PER_TWENTY_FRM, - PER_TWENTY_TWO_FRM, - PER_TWENTY_FOUR_FRM, - PER_TWENTY_SIX_FRM, - PER_TWENTY_EIGHT_FRM, - PER_THIRTY_FRM, -}; - -void exynos_fimd_lcd_init_mem(unsigned long screen_base, unsigned long fb_size, - unsigned long palette_size); -void exynos_fimd_lcd_init(struct vidinfo *vid, ulong lcd_base_address); -unsigned long exynos_fimd_calc_fbsize(struct vidinfo *pvid); - -#endif -- cgit v1.1