Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288. 1. RK3288 have five special pll resigters which not indicata in exynos dp controller. 2. The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos. 3. Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks, - Yakir
Changes in v3: - Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data. - Take Heiko suggest, rename some "samsung*" dts propery to "analogix*". - Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info. - Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4". - Take Heiko suggest, add devicetree binding documents. - Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding. - Update the exist exynos dtsi file with the latest DP DT properies. - Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk". - Take Heiko suggest, add devicetree binding document. - Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node. - Add the new function point analogix_dp_platdata.get_modes init. - Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control. - Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed. - move dp hpd detect to connector detect function. - Add edid modes parse support
Changes in v2: - Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow: - retval = exynos_dp_read_bytes_from_i2c(... ...) + retval = + exynos_dp_read_bytes_from_i2c(......); - Take Jingoo Han suggest, just remove my name from author list. - Take Jingoo Han suggest, remove new copyright - Fix compiled failed dut to analogix_dp_device misspell - Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver. - Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver. - Add GNU license v2 declared and samsung copyright - Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (62%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c create mode 100644 drivers/phy/phy-rockchip-dp.c create mode 100644 include/drm/bridge/analogix_dp.h
After run "checkpatch.pl -f --subjective" command, I see there are lots of alignment problem in exynos_dp driver, so let just fix them.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: None Changes in v2: - Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow: - retval = exynos_dp_read_bytes_from_i2c(... ...) + retval = + exynos_dp_read_bytes_from_i2c(......);
drivers/gpu/drm/exynos/exynos_dp_core.c | 219 ++++++++++++++++---------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 53 ++++---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 100 +++++++-------- 3 files changed, 182 insertions(+), 190 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 172b800..562f4a8 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -114,8 +114,8 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp)
/* Read Extension Flag, Number of 128-byte EDID extension blocks */ retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_EXTENSION_FLAG, - &extend_block); + EDID_EXTENSION_FLAG, + &extend_block); if (retval) return retval;
@@ -123,10 +123,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) dev_dbg(dp->dev, "EDID data includes a single extension!\n");
/* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); + retval = exynos_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; @@ -138,11 +139,11 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) }
/* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp, - I2C_EDID_DEVICE_ADDR, - EDID_BLOCK_LENGTH, - EDID_BLOCK_LENGTH, - &edid[EDID_BLOCK_LENGTH]); + retval = exynos_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, + EDID_BLOCK_LENGTH, + EDID_BLOCK_LENGTH, + &edid[EDID_BLOCK_LENGTH]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; @@ -154,24 +155,22 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) }
exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, - &test_vector); + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd(dp, - DP_TEST_EDID_CHECKSUM, + exynos_dp_write_byte_to_dpcd( + dp, DP_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(dp, - DP_TEST_RESPONSE, + exynos_dp_write_byte_to_dpcd( + dp, DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE); } } else { dev_info(dp->dev, "EDID data does not include any extensions.\n");
/* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c(dp, - I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); + retval = exynos_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; @@ -182,16 +181,15 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) return -EIO; }
- exynos_dp_read_byte_from_dpcd(dp, - DP_TEST_REQUEST, - &test_vector); + exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd(dp, - DP_TEST_EDID_CHECKSUM, - edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd(dp, - DP_TEST_RESPONSE, - DP_TEST_EDID_CHECKSUM_WRITE); + exynos_dp_write_byte_to_dpcd( + dp, DP_TEST_EDID_CHECKSUM, + edid[EDID_CHECKSUM]); + exynos_dp_write_byte_to_dpcd( + dp, DP_TEST_RESPONSE, + DP_TEST_EDID_CHECKSUM_WRITE); } }
@@ -206,8 +204,7 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) int retval;
/* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */ - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, - 12, buf); + retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); if (retval) return retval;
@@ -222,19 +219,21 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) }
static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp, - bool enable) + bool enable) { u8 data;
exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
if (enable) - exynos_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET, - DP_LANE_COUNT_ENHANCED_FRAME_EN | - DPCD_LANE_COUNT_SET(data)); + exynos_dp_write_byte_to_dpcd( + dp, DP_LANE_COUNT_SET, + DP_LANE_COUNT_ENHANCED_FRAME_EN | + DPCD_LANE_COUNT_SET(data)); else - exynos_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET, - DPCD_LANE_COUNT_SET(data)); + exynos_dp_write_byte_to_dpcd( + dp, DP_LANE_COUNT_SET, + DPCD_LANE_COUNT_SET(data)); }
static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp) @@ -261,13 +260,12 @@ static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp) { exynos_dp_set_training_pattern(dp, DP_NONE);
- exynos_dp_write_byte_to_dpcd(dp, - DP_TRAINING_PATTERN_SET, - DP_TRAINING_PATTERN_DISABLE); + exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); }
static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, - int pre_emphasis, int lane) + int pre_emphasis, int lane) { switch (lane) { case 0: @@ -307,15 +305,14 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) /* Setup RX configuration */ buf[0] = dp->link_train.link_rate; buf[1] = dp->link_train.lane_count; - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, - 2, buf); + retval = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); if (retval) return retval;
/* Set TX pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_lane_pre_emphasis(dp, - PRE_EMPHASIS_LEVEL_0, lane); + exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, + lane);
/* Wait for PLL lock */ pll_tries = 0; @@ -333,9 +330,9 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
/* Set RX training pattern */ - retval = exynos_dp_write_byte_to_dpcd(dp, - DP_TRAINING_PATTERN_SET, - DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1); + retval = exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_1); if (retval) return retval;
@@ -344,7 +341,7 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, buf); + lane_count, buf);
return retval; } @@ -352,7 +349,7 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) { int shift = (lane & 1) * 4; - u8 link_value = link_status[lane>>1]; + u8 link_value = link_status[lane >> 1];
return (link_value >> shift) & 0xf; } @@ -371,7 +368,7 @@ static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) }
static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, - int lane_count) + int lane_count) { int lane; u8 lane_status; @@ -390,10 +387,10 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, }
static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], - int lane) + int lane) { int shift = (lane & 1) * 4; - u8 link_value = adjust_request[lane>>1]; + u8 link_value = adjust_request[lane >> 1];
return (link_value >> shift) & 0x3; } @@ -403,13 +400,13 @@ static unsigned char exynos_dp_get_adjust_request_pre_emphasis( int lane) { int shift = (lane & 1) * 4; - u8 link_value = adjust_request[lane>>1]; + u8 link_value = adjust_request[lane >> 1];
return ((link_value >> shift) & 0xc) >> 2; }
static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp, - u8 training_lane_set, int lane) + u8 training_lane_set, int lane) { switch (lane) { case 0: @@ -465,7 +462,7 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) }
static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, - u8 adjust_request[2]) + u8 adjust_request[2]) { int lane, lane_count; u8 voltage_swing, pre_emphasis, training_lane; @@ -498,13 +495,13 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
lane_count = dp->link_train.lane_count;
- retval = exynos_dp_read_bytes_from_dpcd(dp, - DP_LANE0_1_STATUS, 2, link_status); + retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, + 2, link_status); if (retval) return retval;
- retval = exynos_dp_read_bytes_from_dpcd(dp, - DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); + retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, + 2, adjust_request); if (retval) return retval;
@@ -512,8 +509,8 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) /* set training pattern 2 for EQ */ exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
- retval = exynos_dp_write_byte_to_dpcd(dp, - DP_TRAINING_PATTERN_SET, + retval = exynos_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_2); if (retval) @@ -551,11 +548,11 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) exynos_dp_get_adjust_training_lane(dp, adjust_request);
for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + exynos_dp_set_lane_link_training( + dp, dp->link_train.training_lane[lane], lane);
- retval = exynos_dp_write_bytes_to_dpcd(dp, - DP_TRAINING_LANE0_SET, lane_count, + retval = exynos_dp_write_bytes_to_dpcd( + dp, DP_TRAINING_LANE0_SET, lane_count, dp->link_train.training_lane); if (retval) return retval; @@ -573,8 +570,8 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
lane_count = dp->link_train.lane_count;
- retval = exynos_dp_read_bytes_from_dpcd(dp, - DP_LANE0_1_STATUS, 2, link_status); + retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, + 2, link_status); if (retval) return retval;
@@ -583,13 +580,13 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) return -EIO; }
- retval = exynos_dp_read_bytes_from_dpcd(dp, - DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); + retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, + 2, adjust_request); if (retval) return retval;
- retval = exynos_dp_read_byte_from_dpcd(dp, - DP_LANE_ALIGN_STATUS_UPDATED, &link_align); + retval = exynos_dp_read_byte_from_dpcd( + dp, DP_LANE_ALIGN_STATUS_UPDATED, &link_align); if (retval) return retval;
@@ -628,17 +625,18 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) }
for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + exynos_dp_set_lane_link_training( + dp, dp->link_train.training_lane[lane], lane);
retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, dp->link_train.training_lane); + lane_count, + dp->link_train.training_lane);
return retval; }
static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, - u8 *bandwidth) + u8 *bandwidth) { u8 data;
@@ -651,7 +649,7 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, }
static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, - u8 *lane_count) + u8 *lane_count) { u8 data;
@@ -664,8 +662,8 @@ static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, }
static void exynos_dp_init_training(struct exynos_dp_device *dp, - enum link_lane_count_type max_lane, - enum link_rate_type max_rate) + enum link_lane_count_type max_lane, + enum link_rate_type max_rate) { /* * MACRO_RST must be applied after the PLL_LOCK to avoid @@ -678,7 +676,7 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && - (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { + (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS; @@ -738,8 +736,7 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) }
static int exynos_dp_set_link_train(struct exynos_dp_device *dp, - u32 count, - u32 bwtype) + u32 count, u32 bwtype) { int i; int retval; @@ -830,21 +827,19 @@ static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable) if (enable) { exynos_dp_enable_scrambling(dp);
- exynos_dp_read_byte_from_dpcd(dp, - DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(dp, - DP_TRAINING_PATTERN_SET, + exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); } else { exynos_dp_disable_scrambling(dp);
- exynos_dp_read_byte_from_dpcd(dp, - DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd(dp, - DP_TRAINING_PATTERN_SET, - (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); + exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, + &data); + exynos_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, + (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); } }
@@ -915,7 +910,7 @@ static void exynos_dp_commit(struct exynos_drm_display *display) }
ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, - dp->video_info->link_rate); + dp->video_info->link_rate); if (ret) { dev_err(dp->dev, "unable to do link train\n"); return; @@ -1004,7 +999,7 @@ static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = {
/* returns the number of bridges attached */ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, - struct drm_encoder *encoder) + struct drm_encoder *encoder) { int ret;
@@ -1020,7 +1015,7 @@ static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, }
static int exynos_dp_create_connector(struct exynos_drm_display *display, - struct drm_encoder *encoder) + struct drm_encoder *encoder) { struct exynos_dp_device *dp = display_to_dp(display); struct drm_connector *connector = &dp->connector; @@ -1038,7 +1033,8 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, connector->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(dp->drm_dev, connector, - &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); + &exynos_dp_connector_funcs, + DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; @@ -1148,8 +1144,8 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) struct device_node *dp_node = dev->of_node; struct video_info *dp_video_config;
- dp_video_config = devm_kzalloc(dev, - sizeof(*dp_video_config), GFP_KERNEL); + dp_video_config = devm_kzalloc(dev, sizeof(*dp_video_config), + GFP_KERNEL); if (!dp_video_config) return ERR_PTR(-ENOMEM);
@@ -1163,37 +1159,37 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) of_property_read_bool(dp_node, "interlaced");
if (of_property_read_u32(dp_node, "samsung,color-space", - &dp_video_config->color_space)) { + &dp_video_config->color_space)) { dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "samsung,dynamic-range", - &dp_video_config->dynamic_range)) { + &dp_video_config->dynamic_range)) { dev_err(dev, "failed to get dynamic-range\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff", - &dp_video_config->ycbcr_coeff)) { + &dp_video_config->ycbcr_coeff)) { dev_err(dev, "failed to get ycbcr-coeff\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "samsung,color-depth", - &dp_video_config->color_depth)) { + &dp_video_config->color_depth)) { dev_err(dev, "failed to get color-depth\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "samsung,link-rate", - &dp_video_config->link_rate)) { + &dp_video_config->link_rate)) { dev_err(dev, "failed to get link-rate\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "samsung,lane-count", - &dp_video_config->lane_count)) { + &dp_video_config->lane_count)) { dev_err(dev, "failed to get lane-count\n"); return ERR_PTR(-EINVAL); } @@ -1206,7 +1202,7 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) int ret;
ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm, - OF_USE_NATIVE_MODE); + OF_USE_NATIVE_MODE); if (ret) { DRM_ERROR("failed: of_get_videomode() : %d\n", ret); return ret; @@ -1302,7 +1298,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) exynos_dp_init_dp(dp);
ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, - irq_flags, "exynos-dp", dp); + irq_flags, "exynos-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; @@ -1315,7 +1311,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) }
static void exynos_dp_unbind(struct device *dev, struct device *master, - void *data) + void *data) { struct exynos_dp_device *dp = dev_get_drvdata(dev);
@@ -1334,7 +1330,7 @@ static int exynos_dp_probe(struct platform_device *pdev) struct exynos_dp_device *dp;
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), - GFP_KERNEL); + GFP_KERNEL); if (!dp) return -ENOMEM;
@@ -1358,8 +1354,9 @@ static int exynos_dp_probe(struct platform_device *pdev) of_node_put(bridge_node); if (!dp->bridge) return -EPROBE_DEFER; - } else + } else { return -EPROBE_DEFER; + } }
return component_add(&pdev->dev, &exynos_dp_ops); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index a4e7996..c321ad5 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h @@ -180,8 +180,8 @@ void exynos_dp_config_interrupt(struct exynos_dp_device *dp); enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, - enum analog_power_block block, - bool enable); + enum analog_power_block block, + bool enable); void exynos_dp_init_analog_func(struct exynos_dp_device *dp); void exynos_dp_init_hpd(struct exynos_dp_device *dp); enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp); @@ -192,50 +192,50 @@ int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); void exynos_dp_enable_sw_function(struct exynos_dp_device *dp); int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp); int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char data); + unsigned int reg_addr, + unsigned char data); int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char *data); + unsigned int reg_addr, + unsigned char *data); int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, unsigned int device_addr, unsigned int reg_addr); int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data); + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data); int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int count, - unsigned char edid[]); + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]); void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype); void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype); void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count); void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count); void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable); void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, - enum pattern_set pattern); + enum pattern_set pattern); void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level); void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level); void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level); void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level); void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, - u32 training_lane); + u32 training_lane); void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, - u32 training_lane); + u32 training_lane); void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, - u32 training_lane); + u32 training_lane); void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, - u32 training_lane); + u32 training_lane); u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp); u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp); u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); @@ -246,9 +246,8 @@ void exynos_dp_init_video(struct exynos_dp_device *dp); void exynos_dp_set_video_color_format(struct exynos_dp_device *dp); int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, - enum clock_recovery_m_value_type type, - u32 m_value, - u32 n_value); + enum clock_recovery_m_value_type type, + u32 m_value, u32 n_value); void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type); void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); void exynos_dp_start_video(struct exynos_dp_device *dp); diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c index c1f87a2..9aa483d 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_reg.c +++ b/drivers/gpu/drm/exynos/exynos_dp_reg.c @@ -202,8 +202,8 @@ void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable) }
void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, - enum analog_power_block block, - bool enable) + enum analog_power_block block, + bool enable) { u32 reg;
@@ -399,8 +399,8 @@ void exynos_dp_init_aux(struct exynos_dp_device *dp) exynos_dp_reset_aux(dp);
/* Disable AUX transaction H/W retry */ - reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)| - AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL);
/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ @@ -483,8 +483,8 @@ int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp) }
int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char data) + unsigned int reg_addr, + unsigned char data) { u32 reg; int i; @@ -519,17 +519,16 @@ int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); }
return retval; }
int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char *data) + unsigned int reg_addr, + unsigned char *data) { u32 reg; int i; @@ -560,9 +559,8 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); }
/* Read data buffer */ @@ -573,9 +571,9 @@ int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, }
int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]) + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { u32 reg; unsigned int start_offset; @@ -625,9 +623,9 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); }
start_offset += cur_data_count; @@ -637,9 +635,9 @@ int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, }
int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]) + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) { u32 reg; unsigned int start_offset; @@ -683,9 +681,9 @@ int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); }
for (cur_data_idx = 0; cur_data_idx < cur_data_count; @@ -736,9 +734,9 @@ int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, }
int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data) + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data) { u32 reg; int i; @@ -767,9 +765,8 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); }
/* Read data */ @@ -780,10 +777,10 @@ int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, }
int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int count, - unsigned char edid[]) + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]) { u32 reg; unsigned int i, j; @@ -807,8 +804,8 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, * request without sending address */ if (!defer) - retval = exynos_dp_select_i2c_device(dp, - device_addr, reg_addr + i); + retval = exynos_dp_select_i2c_device( + dp, device_addr, reg_addr + i); else defer = 0;
@@ -828,15 +825,14 @@ int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, retval = exynos_dp_start_aux_transaction(dp); if (retval == 0) break; - else - dev_dbg(dp->dev, - "%s: Aux Transaction fail!\n", - __func__); + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); } /* Check if Rx sends defer */ reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM); if (reg == AUX_RX_COMM_AUX_DEFER || - reg == AUX_RX_COMM_I2C_DEFER) { + reg == AUX_RX_COMM_I2C_DEFER) { dev_err(dp->dev, "Defer: %d\n\n", reg); defer = 1; } @@ -901,7 +897,7 @@ void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable) }
void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, - enum pattern_set pattern) + enum pattern_set pattern) { u32 reg;
@@ -974,7 +970,7 @@ void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level) }
void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, - u32 training_lane) + u32 training_lane) { u32 reg;
@@ -983,7 +979,7 @@ void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, }
void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, - u32 training_lane) + u32 training_lane) { u32 reg;
@@ -992,7 +988,7 @@ void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, }
void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, - u32 training_lane) + u32 training_lane) { u32 reg;
@@ -1001,7 +997,7 @@ void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, }
void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, - u32 training_lane) + u32 training_lane) { u32 reg;
@@ -1125,9 +1121,9 @@ int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp) }
void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, - enum clock_recovery_m_value_type type, - u32 m_value, - u32 n_value) + enum clock_recovery_m_value_type type, + u32 m_value, + u32 n_value) { u32 reg;
@@ -1221,7 +1217,7 @@ void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp) u32 reg;
reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1); - reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N); + reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); reg |= MASTER_VID_FUNC_EN_N; writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
In order to move exynos dp code to bridge directory, we need to convert driver drm bridge mode first. As dp driver already have a ptn3460 bridge, so we need to move ptn bridge to the next bridge of dp bridge.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: None Changes in v2: - Take Jingoo Han suggest, just remove my name from author list.
drivers/gpu/drm/exynos/exynos_dp_core.c | 194 ++++++++++++++++++++------------ drivers/gpu/drm/exynos/exynos_dp_core.h | 1 + 2 files changed, 123 insertions(+), 72 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c index 562f4a8..2b87406 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c @@ -997,59 +997,6 @@ static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { .best_encoder = exynos_dp_best_encoder, };
-/* returns the number of bridges attached */ -static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, - struct drm_encoder *encoder) -{ - int ret; - - encoder->bridge = dp->bridge; - dp->bridge->encoder = encoder; - ret = drm_bridge_attach(encoder->dev, dp->bridge); - if (ret) { - DRM_ERROR("Failed to attach bridge to drm\n"); - return ret; - } - - return 0; -} - -static int exynos_dp_create_connector(struct exynos_drm_display *display, - struct drm_encoder *encoder) -{ - struct exynos_dp_device *dp = display_to_dp(display); - struct drm_connector *connector = &dp->connector; - int ret; - - dp->encoder = encoder; - - /* Pre-empt DP connector creation if there's a bridge */ - if (dp->bridge) { - ret = exynos_drm_attach_lcd_bridge(dp, encoder); - if (!ret) - return 0; - } - - connector->polled = DRM_CONNECTOR_POLL_HPD; - - ret = drm_connector_init(dp->drm_dev, connector, - &exynos_dp_connector_funcs, - DRM_MODE_CONNECTOR_eDP); - if (ret) { - DRM_ERROR("Failed to initialize connector with drm\n"); - return ret; - } - - drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); - drm_connector_register(connector); - drm_mode_connector_attach_encoder(connector, encoder); - - if (dp->panel) - ret = drm_panel_attach(dp->panel, &dp->connector); - - return ret; -} - static void exynos_dp_phy_init(struct exynos_dp_device *dp) { if (dp->phy) @@ -1114,23 +1061,126 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) } }
-static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) +/* returns the number of bridges attached */ +static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, + struct drm_encoder *encoder) +{ + int ret; + + dp->bridge->next = dp->ptn_bridge; + dp->bridge->encoder = encoder; + ret = drm_bridge_attach(encoder->dev, dp->bridge); + if (ret) { + DRM_ERROR("Failed to attach ptn bridge to drm\n"); + return ret; + } + + return 0; +} + +static int exynos_dp_bridge_attach(struct drm_bridge *bridge) +{ + + struct exynos_dp_device *dp = bridge->driver_private; + struct drm_encoder *encoder = dp->encoder; + struct drm_connector *connector = &dp->connector; + int ret; + + if (!bridge->encoder) { + DRM_ERROR("Parent encoder object not found"); + return -ENODEV; + } + + encoder->bridge = bridge; + + /* Pre-empt DP connector creation if there's a bridge */ + if (dp->ptn_bridge) { + ret = exynos_drm_attach_lcd_bridge(dp, encoder); + if (ret) + return -ENODEV; + } + + connector->polled = DRM_CONNECTOR_POLL_HPD; + + ret = drm_connector_init(dp->drm_dev, connector, + &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); + if (ret) { + DRM_ERROR("Failed to initialize connector with drm\n"); + return ret; + } + + drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); + drm_connector_register(connector); + drm_mode_connector_attach_encoder(connector, encoder); + + if (dp->panel) + ret = drm_panel_attach(dp->panel, &dp->connector); + + return ret; +} + +static void exynos_dp_bridge_nop(struct drm_bridge *bridge) +{ + /* do nothing */ +} + +static void exynos_dp_bridge_enable(struct drm_bridge *bridge) +{ + struct exynos_dp_device *dp = bridge->driver_private; + + exynos_dp_poweron(dp); + dp->dpms_mode = DRM_MODE_DPMS_ON; +} + +static void exynos_dp_bridge_disable(struct drm_bridge *bridge) +{ + struct exynos_dp_device *dp = bridge->driver_private; + + exynos_dp_poweroff(dp); + dp->dpms_mode = DRM_MODE_DPMS_OFF; +} + +static const struct drm_bridge_funcs exynos_dp_bridge_funcs = { + .enable = exynos_dp_bridge_enable, + .disable = exynos_dp_bridge_disable, + .pre_enable = exynos_dp_bridge_nop, + .post_disable = exynos_dp_bridge_nop, + .attach = exynos_dp_bridge_attach, +}; + +static int exynos_dp_create_connector(struct exynos_drm_display *display, + struct drm_encoder *encoder) { struct exynos_dp_device *dp = display_to_dp(display); + struct drm_device *drm_dev = dp->drm_dev; + struct drm_bridge *bridge; + int ret;
- switch (mode) { - case DRM_MODE_DPMS_ON: - exynos_dp_poweron(dp); - break; - case DRM_MODE_DPMS_STANDBY: - case DRM_MODE_DPMS_SUSPEND: - case DRM_MODE_DPMS_OFF: - exynos_dp_poweroff(dp); - break; - default: - break; + bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL); + if (!bridge) { + DRM_ERROR("failed to allocate for drm bridge\n"); + return -ENOMEM; } - dp->dpms_mode = mode; + + dp->bridge = bridge; + dp->encoder = encoder; + + bridge->driver_private = dp; + bridge->encoder = dp->encoder; + bridge->funcs = &exynos_dp_bridge_funcs; + + ret = drm_bridge_attach(drm_dev, bridge); + if (ret) { + DRM_ERROR("failed to attach drm bridge\n"); + return -EINVAL; + } + + return 0; +} + +static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) +{ + /* do nothing */ }
static struct exynos_drm_display_ops exynos_dp_display_ops = { @@ -1242,7 +1292,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) } }
- if (!dp->panel && !dp->bridge) { + if (!dp->panel && !dp->ptn_bridge) { ret = exynos_dp_dt_parse_panel(dp); if (ret) return ret; @@ -1315,7 +1365,7 @@ static void exynos_dp_unbind(struct device *dev, struct device *master, { struct exynos_dp_device *dp = dev_get_drvdata(dev);
- exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF); + exynos_dp_bridge_disable(dp->bridge); }
static const struct component_ops exynos_dp_ops = { @@ -1350,9 +1400,9 @@ static int exynos_dp_probe(struct platform_device *pdev) if (endpoint) { bridge_node = of_graph_get_remote_port_parent(endpoint); if (bridge_node) { - dp->bridge = of_drm_find_bridge(bridge_node); + dp->ptn_bridge = of_drm_find_bridge(bridge_node); of_node_put(bridge_node); - if (!dp->bridge) + if (!dp->ptn_bridge) return -EPROBE_DEFER; } else { return -EPROBE_DEFER; @@ -1374,7 +1424,7 @@ static int exynos_dp_suspend(struct device *dev) { struct exynos_dp_device *dp = dev_get_drvdata(dev);
- exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_OFF); + exynos_dp_bridge_disable(dp->bridge); return 0; }
@@ -1382,7 +1432,7 @@ static int exynos_dp_resume(struct device *dev) { struct exynos_dp_device *dp = dev_get_drvdata(dev);
- exynos_dp_dpms(&dp->display, DRM_MODE_DPMS_ON); + exynos_dp_bridge_enable(dp->bridge); return 0; } #endif diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h index c321ad5..29bd56e 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ b/drivers/gpu/drm/exynos/exynos_dp_core.h @@ -154,6 +154,7 @@ struct exynos_dp_device { struct drm_encoder *encoder; struct drm_panel *panel; struct drm_bridge *bridge; + struct drm_bridge *ptn_bridge; struct clk *clock; unsigned int irq; void __iomem *reg_base;
Split the dp core driver from exynos directory to bridge directory, and rename the core driver to analogix_dp_*, leave the platform code to analogix_dp-exynos.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data. - Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
Changes in v2: - Take Jingoo Han suggest, remove new copyright - Fix compiled failed dut to analogix_dp_device misspell
drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + .../exynos_dp_core.c => bridge/analogix_dp_core.c} | 816 ++++++------- drivers/gpu/drm/bridge/analogix_dp_core.h | 282 +++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1265 ++++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 258 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 291 +++++ drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ----- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1259 ------------------- include/drm/bridge/analogix_dp.h | 24 + 12 files changed, 2350 insertions(+), 2140 deletions(-) rename drivers/gpu/drm/{exynos/exynos_dp_core.c => bridge/analogix_dp_core.c} (50%) create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (64%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 include/drm/bridge/analogix_dp.h
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index acef322..c7638b5 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -3,6 +3,11 @@ config DRM_DW_HDMI depends on DRM select DRM_KMS_HELPER
+config DRM_ANALOGIX_DP + tristate + depends on DRM + select DRM_KMS_HELPER + config DRM_PTN3460 tristate "PTN3460 DP/LVDS bridge" depends on DRM diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 8dfebd9..a7ee559 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_PS8622) += ps8622.o obj-$(CONFIG_DRM_PTN3460) += ptn3460.o obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp_core.o analogix_dp_reg.o diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c similarity index 50% rename from drivers/gpu/drm/exynos/exynos_dp_core.c rename to drivers/gpu/drm/bridge/analogix_dp_core.c index 2b87406..6c15e20 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -1,5 +1,5 @@ /* - * Samsung SoC DP (Display Port) interface driver. + * Analogix Core DP (Display Port) interface driver. * * Copyright (C) 2012 Samsung Electronics Co., Ltd. * Author: Jingoo Han jg1.han@samsung.com @@ -18,12 +18,9 @@ #include <linux/interrupt.h> #include <linux/of.h> #include <linux/of_gpio.h> -#include <linux/of_graph.h> #include <linux/gpio.h> #include <linux/component.h> #include <linux/phy/phy.h> -#include <video/of_display_timing.h> -#include <video/of_videomode.h>
#include <drm/drmP.h> #include <drm/drm_crtc.h> @@ -31,51 +28,42 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_panel.h>
-#include "exynos_dp_core.h" +#include <drm/bridge/analogix_dp.h>
-#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ - connector) +#include "analogix_dp_core.h"
-static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) -{ - return to_exynos_crtc(dp->encoder->crtc); -} - -static inline struct exynos_dp_device * -display_to_dp(struct exynos_drm_display *d) -{ - return container_of(d, struct exynos_dp_device, display); -} +#define connector_to_dp(c) \ + container_of(c, struct analogix_dp_device, connector)
struct bridge_init { struct i2c_client *client; struct device_node *node; };
-static void exynos_dp_init_dp(struct exynos_dp_device *dp) +static void analogix_dp_init_dp(struct analogix_dp_device *dp) { - exynos_dp_reset(dp); + analogix_dp_reset(dp);
- exynos_dp_swreset(dp); + analogix_dp_swreset(dp);
- exynos_dp_init_analog_param(dp); - exynos_dp_init_interrupt(dp); + analogix_dp_init_analog_param(dp); + analogix_dp_init_interrupt(dp);
/* SW defined function Normal operation */ - exynos_dp_enable_sw_function(dp); + analogix_dp_enable_sw_function(dp);
- exynos_dp_config_interrupt(dp); - exynos_dp_init_analog_func(dp); + analogix_dp_config_interrupt(dp); + analogix_dp_init_analog_func(dp);
- exynos_dp_init_hpd(dp); - exynos_dp_init_aux(dp); + analogix_dp_init_hpd(dp); + analogix_dp_init_aux(dp); }
-static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) +static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) { int timeout_loop = 0;
- while (exynos_dp_get_plug_in_status(dp) != 0) { + while (analogix_dp_get_plug_in_status(dp) != 0) { timeout_loop++; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "failed to get hpd plug status\n"); @@ -87,7 +75,7 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) return 0; }
-static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) +static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) { int i; unsigned char sum = 0; @@ -98,7 +86,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) return sum; }
-static int exynos_dp_read_edid(struct exynos_dp_device *dp) +static int analogix_dp_read_edid(struct analogix_dp_device *dp) { unsigned char edid[EDID_BLOCK_LENGTH * 2]; unsigned int extend_block = 0; @@ -113,9 +101,9 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) */
/* Read Extension Flag, Number of 128-byte EDID extension blocks */ - retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_EXTENSION_FLAG, - &extend_block); + retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, + EDID_EXTENSION_FLAG, + &extend_block); if (retval) return retval;
@@ -123,44 +111,44 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) dev_dbg(dp->dev, "EDID data includes a single extension!\n");
/* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c( - dp, I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); + retval = analogix_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; } - sum = exynos_dp_calc_edid_check_sum(edid); + sum = analogix_dp_calc_edid_check_sum(edid); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; }
/* Read additional EDID data */ - retval = exynos_dp_read_bytes_from_i2c( - dp, I2C_EDID_DEVICE_ADDR, - EDID_BLOCK_LENGTH, - EDID_BLOCK_LENGTH, - &edid[EDID_BLOCK_LENGTH]); + retval = analogix_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, + EDID_BLOCK_LENGTH, + EDID_BLOCK_LENGTH, + &edid[EDID_BLOCK_LENGTH]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; } - sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); + sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; }
- exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, - &test_vector); + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE); } @@ -168,26 +156,28 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) dev_info(dp->dev, "EDID data does not include any extensions.\n");
/* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c( - dp, I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]); + retval = analogix_dp_read_bytes_from_i2c( + dp, I2C_EDID_DEVICE_ADDR, + EDID_HEADER_PATTERN, + EDID_BLOCK_LENGTH, + &edid[EDID_HEADER_PATTERN]); if (retval != 0) { dev_err(dp->dev, "EDID Read failed!\n"); return -EIO; } - sum = exynos_dp_calc_edid_check_sum(edid); + sum = analogix_dp_calc_edid_check_sum(edid); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; }
- exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, - &test_vector); + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE); } @@ -197,20 +187,20 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) return 0; }
-static int exynos_dp_handle_edid(struct exynos_dp_device *dp) +static int analogix_dp_handle_edid(struct analogix_dp_device *dp) { u8 buf[12]; int i; int retval;
/* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */ - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); if (retval) return retval;
/* Read EDID */ for (i = 0; i < 3; i++) { - retval = exynos_dp_read_edid(dp); + retval = analogix_dp_read_edid(dp); if (!retval) break; } @@ -218,74 +208,76 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) return retval; }
-static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp, - bool enable) +static void +analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp, + bool enable) { u8 data;
- exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
if (enable) - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_LANE_COUNT_SET, DP_LANE_COUNT_ENHANCED_FRAME_EN | DPCD_LANE_COUNT_SET(data)); else - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_LANE_COUNT_SET, DPCD_LANE_COUNT_SET(data)); }
-static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp) +static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp) { u8 data; int retval;
- exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); retval = DPCD_ENHANCED_FRAME_CAP(data);
return retval; }
-static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp) +static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp) { u8 data;
- data = exynos_dp_is_enhanced_mode_available(dp); - exynos_dp_enable_rx_to_enhanced_mode(dp, data); - exynos_dp_enable_enhanced_mode(dp, data); + data = analogix_dp_is_enhanced_mode_available(dp); + analogix_dp_enable_rx_to_enhanced_mode(dp, data); + analogix_dp_enable_enhanced_mode(dp, data); }
-static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp) +static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) { - exynos_dp_set_training_pattern(dp, DP_NONE); + analogix_dp_set_training_pattern(dp, DP_NONE);
- exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, - DP_TRAINING_PATTERN_DISABLE); + analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); }
-static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, - int pre_emphasis, int lane) +static void +analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp, + int pre_emphasis, int lane) { switch (lane) { case 0: - exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); break; case 1: - exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); break;
case 2: - exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); break;
case 3: - exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); break; } }
-static int exynos_dp_link_start(struct exynos_dp_device *dp) +static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; int lane, lane_count, pll_tries, retval; @@ -299,24 +291,24 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) dp->link_train.cr_loop[lane] = 0;
/* Set link rate and count as you want to establish*/ - exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); - exynos_dp_set_lane_count(dp, dp->link_train.lane_count); + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
/* Setup RX configuration */ buf[0] = dp->link_train.link_rate; buf[1] = dp->link_train.lane_count; - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); if (retval) return retval;
/* Set TX pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, - lane); + analogix_dp_set_lane_lane_pre_emphasis( + dp, PRE_EMPHASIS_LEVEL_0, lane);
/* Wait for PLL lock */ pll_tries = 0; - while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { dev_err(dp->dev, "Wait for PLL lock timed out\n"); return -ETIMEDOUT; @@ -327,12 +319,12 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) }
/* Set training pattern 1 */ - exynos_dp_set_training_pattern(dp, TRAINING_PTN1); + analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
/* Set RX training pattern */ - retval = exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, - DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_1); + retval = analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_1); if (retval) return retval;
@@ -340,13 +332,13 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
- retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, buf); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, buf);
return retval; }
-static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) +static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) { int shift = (lane & 1) * 4; u8 link_value = link_status[lane >> 1]; @@ -354,21 +346,21 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) return (link_value >> shift) & 0xf; }
-static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) +static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) { int lane; u8 lane_status;
for (lane = 0; lane < lane_count; lane++) { - lane_status = exynos_dp_get_lane_status(link_status, lane); + lane_status = analogix_dp_get_lane_status(link_status, lane); if ((lane_status & DP_LANE_CR_DONE) == 0) return -EINVAL; } return 0; }
-static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, - int lane_count) +static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, + int lane_count) { int lane; u8 lane_status; @@ -377,7 +369,7 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, return -EINVAL;
for (lane = 0; lane < lane_count; lane++) { - lane_status = exynos_dp_get_lane_status(link_status, lane); + lane_status = analogix_dp_get_lane_status(link_status, lane); lane_status &= DP_CHANNEL_EQ_BITS; if (lane_status != DP_CHANNEL_EQ_BITS) return -EINVAL; @@ -386,8 +378,8 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, return 0; }
-static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], - int lane) +static unsigned char +analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane) { int shift = (lane & 1) * 4; u8 link_value = adjust_request[lane >> 1]; @@ -395,7 +387,7 @@ static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], return (link_value >> shift) & 0x3; }
-static unsigned char exynos_dp_get_adjust_request_pre_emphasis( +static unsigned char analogix_dp_get_adjust_request_pre_emphasis( u8 adjust_request[2], int lane) { @@ -405,45 +397,45 @@ static unsigned char exynos_dp_get_adjust_request_pre_emphasis( return ((link_value >> shift) & 0xc) >> 2; }
-static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp, - u8 training_lane_set, int lane) +static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp, + u8 training_lane_set, int lane) { switch (lane) { case 0: - exynos_dp_set_lane0_link_training(dp, training_lane_set); + analogix_dp_set_lane0_link_training(dp, training_lane_set); break; case 1: - exynos_dp_set_lane1_link_training(dp, training_lane_set); + analogix_dp_set_lane1_link_training(dp, training_lane_set); break;
case 2: - exynos_dp_set_lane2_link_training(dp, training_lane_set); + analogix_dp_set_lane2_link_training(dp, training_lane_set); break;
case 3: - exynos_dp_set_lane3_link_training(dp, training_lane_set); + analogix_dp_set_lane3_link_training(dp, training_lane_set); break; } }
-static unsigned int exynos_dp_get_lane_link_training( - struct exynos_dp_device *dp, +static unsigned int analogix_dp_get_lane_link_training( + struct analogix_dp_device *dp, int lane) { u32 reg;
switch (lane) { case 0: - reg = exynos_dp_get_lane0_link_training(dp); + reg = analogix_dp_get_lane0_link_training(dp); break; case 1: - reg = exynos_dp_get_lane1_link_training(dp); + reg = analogix_dp_get_lane1_link_training(dp); break; case 2: - reg = exynos_dp_get_lane2_link_training(dp); + reg = analogix_dp_get_lane2_link_training(dp); break; case 3: - reg = exynos_dp_get_lane3_link_training(dp); + reg = analogix_dp_get_lane3_link_training(dp); break; default: WARN_ON(1); @@ -453,25 +445,25 @@ static unsigned int exynos_dp_get_lane_link_training( return reg; }
-static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) +static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) { - exynos_dp_training_pattern_dis(dp); - exynos_dp_set_enhanced_mode(dp); + analogix_dp_training_pattern_dis(dp); + analogix_dp_set_enhanced_mode(dp);
dp->link_train.lt_state = FAILED; }
-static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, - u8 adjust_request[2]) +static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp, + u8 adjust_request[2]) { int lane, lane_count; u8 voltage_swing, pre_emphasis, training_lane;
lane_count = dp->link_train.lane_count; for (lane = 0; lane < lane_count; lane++) { - voltage_swing = exynos_dp_get_adjust_request_voltage( + voltage_swing = analogix_dp_get_adjust_request_voltage( adjust_request, lane); - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( adjust_request, lane); training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | DPCD_PRE_EMPHASIS_SET(pre_emphasis); @@ -485,7 +477,7 @@ static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, } }
-static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) +static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) { int lane, lane_count, retval; u8 voltage_swing, pre_emphasis, training_lane; @@ -495,24 +487,24 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
lane_count = dp->link_train.lane_count;
- retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, - 2, link_status); + retval = analogix_dp_read_bytes_from_dpcd( + dp, DP_LANE0_1_STATUS, 2, link_status); if (retval) return retval;
- retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); + retval = analogix_dp_read_bytes_from_dpcd( + dp, DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); if (retval) return retval;
- if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { + if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { /* set training pattern 2 for EQ */ - exynos_dp_set_training_pattern(dp, TRAINING_PTN2); + analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
- retval = exynos_dp_write_byte_to_dpcd( - dp, DP_TRAINING_PATTERN_SET, - DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_2); + retval = analogix_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_2); if (retval) return retval;
@@ -520,12 +512,12 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) dp->link_train.lt_state = EQUALIZER_TRAINING; } else { for (lane = 0; lane < lane_count; lane++) { - training_lane = exynos_dp_get_lane_link_training( + training_lane = analogix_dp_get_lane_link_training( dp, lane); - voltage_swing = exynos_dp_get_adjust_request_voltage( - adjust_request, lane); - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( + voltage_swing = analogix_dp_get_adjust_request_voltage( adjust_request, lane); + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( + adjust_request, lane);
if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing && @@ -539,19 +531,19 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", dp->link_train.cr_loop[lane], voltage_swing, pre_emphasis); - exynos_dp_reduce_link_rate(dp); + analogix_dp_reduce_link_rate(dp); return -EIO; } } }
- exynos_dp_get_adjust_training_lane(dp, adjust_request); + analogix_dp_get_adjust_training_lane(dp, adjust_request);
for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training( + analogix_dp_set_lane_link_training( dp, dp->link_train.training_lane[lane], lane);
- retval = exynos_dp_write_bytes_to_dpcd( + retval = analogix_dp_write_bytes_to_dpcd( dp, DP_TRAINING_LANE0_SET, lane_count, dp->link_train.training_lane); if (retval) @@ -560,7 +552,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) return retval; }
-static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) +static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { int lane, lane_count, retval; u32 reg; @@ -570,46 +562,46 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
lane_count = dp->link_train.lane_count;
- retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, - 2, link_status); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, + 2, link_status); if (retval) return retval;
- if (exynos_dp_clock_recovery_ok(link_status, lane_count)) { - exynos_dp_reduce_link_rate(dp); + if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { + analogix_dp_reduce_link_rate(dp); return -EIO; }
- retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, + 2, adjust_request); if (retval) return retval;
- retval = exynos_dp_read_byte_from_dpcd( + retval = analogix_dp_read_byte_from_dpcd( dp, DP_LANE_ALIGN_STATUS_UPDATED, &link_align); if (retval) return retval;
- exynos_dp_get_adjust_training_lane(dp, adjust_request); + analogix_dp_get_adjust_training_lane(dp, adjust_request);
- if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) { + if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { /* traing pattern Set to Normal */ - exynos_dp_training_pattern_dis(dp); + analogix_dp_training_pattern_dis(dp);
dev_info(dp->dev, "Link Training success!\n");
- exynos_dp_get_link_bandwidth(dp, ®); + analogix_dp_get_link_bandwidth(dp, ®); dp->link_train.link_rate = reg; dev_dbg(dp->dev, "final bandwidth = %.2x\n", dp->link_train.link_rate);
- exynos_dp_get_lane_count(dp, ®); + analogix_dp_get_lane_count(dp, ®); dp->link_train.lane_count = reg; dev_dbg(dp->dev, "final lane count = %.2x\n", dp->link_train.lane_count);
/* set enhanced mode if available */ - exynos_dp_set_enhanced_mode(dp); + analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FINISHED;
return 0; @@ -620,23 +612,23 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
if (dp->link_train.eq_loop > MAX_EQ_LOOP) { dev_err(dp->dev, "EQ Max loop\n"); - exynos_dp_reduce_link_rate(dp); + analogix_dp_reduce_link_rate(dp); return -EIO; }
for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training( + analogix_dp_set_lane_link_training( dp, dp->link_train.training_lane[lane], lane);
- retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, - dp->link_train.training_lane); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, + dp->link_train.training_lane);
return retval; }
-static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, - u8 *bandwidth) +static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, + u8 *bandwidth) { u8 data;
@@ -644,12 +636,12 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, * For DP rev.1.1, Maximum link rate of Main Link lanes * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps */ - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); *bandwidth = data; }
-static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, - u8 *lane_count) +static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp, + u8 *lane_count) { u8 data;
@@ -657,23 +649,23 @@ static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, * For DP rev.1.1, Maximum number of Main Link lanes * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes */ - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); *lane_count = DPCD_MAX_LANE_COUNT(data); }
-static void exynos_dp_init_training(struct exynos_dp_device *dp, - enum link_lane_count_type max_lane, - enum link_rate_type max_rate) +static void analogix_dp_init_training(struct analogix_dp_device *dp, + enum link_lane_count_type max_lane, + enum link_rate_type max_rate) { /* * 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); + analogix_dp_reset_macro(dp);
/* Initialize by reading RX's DPCD */ - exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); - exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); + analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); + analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { @@ -695,10 +687,10 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, dp->link_train.link_rate = max_rate;
/* All DP analog module power up */ - exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); }
-static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) +static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) { int retval = 0, training_finished = 0;
@@ -708,17 +700,17 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) while (!retval && !training_finished) { switch (dp->link_train.lt_state) { case START: - retval = exynos_dp_link_start(dp); + retval = analogix_dp_link_start(dp); if (retval) dev_err(dp->dev, "LT link start failed!\n"); break; case CLOCK_RECOVERY: - retval = exynos_dp_process_clock_recovery(dp); + retval = analogix_dp_process_clock_recovery(dp); if (retval) dev_err(dp->dev, "LT CR failed!\n"); break; case EQUALIZER_TRAINING: - retval = exynos_dp_process_equalizer_training(dp); + retval = analogix_dp_process_equalizer_training(dp); if (retval) dev_err(dp->dev, "LT EQ failed!\n"); break; @@ -735,15 +727,15 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) return retval; }
-static int exynos_dp_set_link_train(struct exynos_dp_device *dp, - u32 count, u32 bwtype) +static int analogix_dp_set_link_train(struct analogix_dp_device *dp, + u32 count, u32 bwtype) { int i; int retval;
for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { - exynos_dp_init_training(dp, count, bwtype); - retval = exynos_dp_sw_link_training(dp); + analogix_dp_init_training(dp, count, bwtype); + retval = analogix_dp_sw_link_training(dp); if (retval == 0) break;
@@ -753,24 +745,24 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp, return retval; }
-static int exynos_dp_config_video(struct exynos_dp_device *dp) +static int analogix_dp_config_video(struct analogix_dp_device *dp) { int retval = 0; int timeout_loop = 0; int done_count = 0;
- exynos_dp_config_video_slave_mode(dp); + analogix_dp_config_video_slave_mode(dp);
- exynos_dp_set_video_color_format(dp); + analogix_dp_set_video_color_format(dp);
- if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { dev_err(dp->dev, "PLL is not locked yet.\n"); return -EINVAL; }
for (;;) { timeout_loop++; - if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0) + if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) break; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "Timeout of video streamclk ok\n"); @@ -781,25 +773,25 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) }
/* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); + analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
/* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); + analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
/* Disable video mute */ - exynos_dp_enable_video_mute(dp, 0); + analogix_dp_enable_video_mute(dp, 0);
/* Configure video slave mode */ - exynos_dp_enable_video_master(dp, 0); + analogix_dp_enable_video_master(dp, 0);
/* Enable video */ - exynos_dp_start_video(dp); + analogix_dp_start_video(dp);
timeout_loop = 0;
for (;;) { timeout_loop++; - if (exynos_dp_is_video_stream_on(dp) == 0) { + if (analogix_dp_is_video_stream_on(dp) == 0) { done_count++; if (done_count > 10) break; @@ -820,45 +812,46 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) return retval; }
-static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable) +static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, + bool enable) { u8 data;
if (enable) { - exynos_dp_enable_scrambling(dp); + analogix_dp_enable_scrambling(dp);
- exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd( - dp, DP_TRAINING_PATTERN_SET, - (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); + analogix_dp_read_byte_from_dpcd( + dp, DP_TRAINING_PATTERN_SET, &data); + analogix_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, + (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); } else { - exynos_dp_disable_scrambling(dp); + analogix_dp_disable_scrambling(dp);
- exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd( + analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, + &data); + analogix_dp_write_byte_to_dpcd( dp, DP_TRAINING_PATTERN_SET, (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); } }
-static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) +static irqreturn_t analogix_dp_irq_handler(int irq, void *arg) { - struct exynos_dp_device *dp = arg; + struct analogix_dp_device *dp = arg;
enum dp_irq_type irq_type;
- irq_type = exynos_dp_get_irq_type(dp); + irq_type = analogix_dp_get_irq_type(dp); switch (irq_type) { case DP_IRQ_TYPE_HP_CABLE_IN: dev_dbg(dp->dev, "Received irq - cable in\n"); schedule_work(&dp->hotplug_work); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; case DP_IRQ_TYPE_HP_CABLE_OUT: dev_dbg(dp->dev, "Received irq - cable out\n"); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; case DP_IRQ_TYPE_HP_CHANGE: /* @@ -867,7 +860,7 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) * only handle cable changes. */ dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n"); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; default: dev_err(dp->dev, "Received irq - unknown type!\n"); @@ -876,172 +869,155 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) return IRQ_HANDLED; }
-static void exynos_dp_hotplug(struct work_struct *work) +static void analogix_dp_hotplug(struct work_struct *work) { - struct exynos_dp_device *dp; + struct analogix_dp_device *dp;
- dp = container_of(work, struct exynos_dp_device, hotplug_work); + dp = container_of(work, struct analogix_dp_device, hotplug_work);
if (dp->drm_dev) drm_helper_hpd_irq_event(dp->drm_dev); }
-static void exynos_dp_commit(struct exynos_drm_display *display) +static void analogix_dp_commit(struct analogix_dp_device *dp) { - struct exynos_dp_device *dp = display_to_dp(display); int ret;
/* Keep the panel disabled while we configure video */ - if (dp->panel) { - if (drm_panel_disable(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) DRM_ERROR("failed to disable the panel\n"); }
- ret = exynos_dp_detect_hpd(dp); + ret = analogix_dp_detect_hpd(dp); if (ret) { /* Cable has been disconnected, we're done */ return; }
- ret = exynos_dp_handle_edid(dp); + ret = analogix_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n"); return; }
- ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, - dp->video_info->link_rate); + ret = analogix_dp_set_link_train(dp, dp->video_info->lane_count, + dp->video_info->link_rate); if (ret) { dev_err(dp->dev, "unable to do link train\n"); return; }
- exynos_dp_enable_scramble(dp, 1); - exynos_dp_enable_rx_to_enhanced_mode(dp, 1); - exynos_dp_enable_enhanced_mode(dp, 1); + analogix_dp_enable_scramble(dp, 1); + analogix_dp_enable_rx_to_enhanced_mode(dp, 1); + analogix_dp_enable_enhanced_mode(dp, 1);
- exynos_dp_set_lane_count(dp, dp->video_info->lane_count); - exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); + analogix_dp_set_lane_count(dp, dp->video_info->lane_count); + analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
- exynos_dp_init_video(dp); - ret = exynos_dp_config_video(dp); + analogix_dp_init_video(dp); + ret = analogix_dp_config_video(dp); if (ret) dev_err(dp->dev, "unable to config video\n");
/* Safe to enable the panel now */ - if (dp->panel) { - if (drm_panel_enable(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_enable(dp->plat_data->panel)) DRM_ERROR("failed to enable the panel\n"); } }
-static enum drm_connector_status exynos_dp_detect( +static enum drm_connector_status analogix_dp_detect( struct drm_connector *connector, bool force) { return connector_status_connected; }
-static void exynos_dp_connector_destroy(struct drm_connector *connector) +static void analogix_dp_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); drm_connector_cleanup(connector); }
-static struct drm_connector_funcs exynos_dp_connector_funcs = { +static struct drm_connector_funcs analogix_dp_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = exynos_dp_detect, - .destroy = exynos_dp_connector_destroy, + .detect = analogix_dp_detect, + .destroy = analogix_dp_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, };
-static int exynos_dp_get_modes(struct drm_connector *connector) +static int analogix_dp_get_modes(struct drm_connector *connector) { - struct exynos_dp_device *dp = ctx_from_connector(connector); - struct drm_display_mode *mode; + struct analogix_dp_device *dp = connector_to_dp(connector); + struct analogix_dp_plat_data *plat_data = dp->plat_data; + int num_modes = 0;
- if (dp->panel) - return drm_panel_get_modes(dp->panel); - - mode = drm_mode_create(connector->dev); - if (!mode) { - DRM_ERROR("failed to create a new display mode.\n"); - return 0; - } + if (plat_data && plat_data->panel) + num_modes += drm_panel_get_modes(plat_data->panel);
- drm_display_mode_from_videomode(&dp->priv.vm, mode); - mode->width_mm = dp->priv.width_mm; - mode->height_mm = dp->priv.height_mm; - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; + if (plat_data && plat_data->get_modes) + num_modes += plat_data->get_modes(plat_data, connector);
- mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; - drm_mode_set_name(mode); - drm_mode_probed_add(connector, mode); - - return 1; + return num_modes; }
-static struct drm_encoder *exynos_dp_best_encoder( +static struct drm_encoder *analogix_dp_best_encoder( struct drm_connector *connector) { - struct exynos_dp_device *dp = ctx_from_connector(connector); + struct analogix_dp_device *dp = connector_to_dp(connector);
return dp->encoder; }
-static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { - .get_modes = exynos_dp_get_modes, - .best_encoder = exynos_dp_best_encoder, +static struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { + .get_modes = analogix_dp_get_modes, + .best_encoder = analogix_dp_best_encoder, };
-static void exynos_dp_phy_init(struct exynos_dp_device *dp) +static void analogix_dp_phy_init(struct analogix_dp_device *dp) { if (dp->phy) phy_power_on(dp->phy); }
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp) +static void analogix_dp_phy_exit(struct analogix_dp_device *dp) { if (dp->phy) phy_power_off(dp->phy); }
-static void exynos_dp_poweron(struct exynos_dp_device *dp) +static void analogix_dp_poweron(struct analogix_dp_device *dp) { - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); - if (dp->dpms_mode == DRM_MODE_DPMS_ON) return;
- if (dp->panel) { - if (drm_panel_prepare(dp->panel)) { + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_prepare(dp->plat_data->panel)) { DRM_ERROR("failed to setup the panel\n"); return; } }
- if (crtc->ops->clock_enable) - crtc->ops->clock_enable(dp_to_crtc(dp), true); + if (dp->plat_data && dp->plat_data->power_on) + dp->plat_data->power_on(dp->plat_data);
clk_prepare_enable(dp->clock); - exynos_dp_phy_init(dp); - exynos_dp_init_dp(dp); + analogix_dp_phy_init(dp); + analogix_dp_init_dp(dp); enable_irq(dp->irq); - exynos_dp_commit(&dp->display); + analogix_dp_commit(dp); }
-static void exynos_dp_poweroff(struct exynos_dp_device *dp) +static void analogix_dp_poweroff(struct analogix_dp_device *dp) { - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); - if (dp->dpms_mode != DRM_MODE_DPMS_ON) return;
- if (dp->panel) { - if (drm_panel_disable(dp->panel)) { + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) { DRM_ERROR("failed to disable the panel\n"); return; } @@ -1049,39 +1025,21 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp)
disable_irq(dp->irq); flush_work(&dp->hotplug_work); - exynos_dp_phy_exit(dp); + analogix_dp_phy_exit(dp); clk_disable_unprepare(dp->clock);
- if (crtc->ops->clock_enable) - crtc->ops->clock_enable(dp_to_crtc(dp), false); + if (dp->plat_data && dp->plat_data->power_off) + dp->plat_data->power_off(dp->plat_data);
- if (dp->panel) { - if (drm_panel_unprepare(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); } }
-/* returns the number of bridges attached */ -static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, - struct drm_encoder *encoder) +static int analogix_dp_bridge_attach(struct drm_bridge *bridge) { - int ret; - - dp->bridge->next = dp->ptn_bridge; - dp->bridge->encoder = encoder; - ret = drm_bridge_attach(encoder->dev, dp->bridge); - if (ret) { - DRM_ERROR("Failed to attach ptn bridge to drm\n"); - return ret; - } - - return 0; -} - -static int exynos_dp_bridge_attach(struct drm_bridge *bridge) -{ - - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private; struct drm_encoder *encoder = dp->encoder; struct drm_connector *connector = &dp->connector; int ret; @@ -1093,66 +1051,77 @@ static int exynos_dp_bridge_attach(struct drm_bridge *bridge)
encoder->bridge = bridge;
- /* Pre-empt DP connector creation if there's a bridge */ - if (dp->ptn_bridge) { - ret = exynos_drm_attach_lcd_bridge(dp, encoder); - if (ret) - return -ENODEV; - } - connector->polled = DRM_CONNECTOR_POLL_HPD;
ret = drm_connector_init(dp->drm_dev, connector, - &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); + &analogix_dp_connector_funcs, + DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; }
- drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); + drm_connector_helper_add(connector, + &analogix_dp_connector_helper_funcs); drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder);
- if (dp->panel) - ret = drm_panel_attach(dp->panel, &dp->connector); + if (dp->plat_data && dp->plat_data->panel) { + ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); + if (ret) { + DRM_ERROR("Failed to attach panel\n"); + return ret; + } + } + + /* + * This should be the end of attach function, caused + * we should ensure dp bridge could attach first. + */ + if (dp->plat_data && dp->plat_data->attach) { + ret = dp->plat_data->attach(dp->plat_data, bridge); + if (ret) { + DRM_ERROR("Failed at platform attch func\n"); + return ret; + } + }
- return ret; + return 0; }
-static void exynos_dp_bridge_nop(struct drm_bridge *bridge) +static void analogix_dp_bridge_nop(struct drm_bridge *bridge) { /* do nothing */ }
-static void exynos_dp_bridge_enable(struct drm_bridge *bridge) +static void analogix_dp_bridge_enable(struct drm_bridge *bridge) { - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private;
- exynos_dp_poweron(dp); + analogix_dp_poweron(dp); dp->dpms_mode = DRM_MODE_DPMS_ON; }
-static void exynos_dp_bridge_disable(struct drm_bridge *bridge) +static void analogix_dp_bridge_disable(struct drm_bridge *bridge) { - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private;
- exynos_dp_poweroff(dp); + analogix_dp_poweroff(dp); dp->dpms_mode = DRM_MODE_DPMS_OFF; }
-static const struct drm_bridge_funcs exynos_dp_bridge_funcs = { - .enable = exynos_dp_bridge_enable, - .disable = exynos_dp_bridge_disable, - .pre_enable = exynos_dp_bridge_nop, - .post_disable = exynos_dp_bridge_nop, - .attach = exynos_dp_bridge_attach, +static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { + .enable = analogix_dp_bridge_enable, + .disable = analogix_dp_bridge_disable, + .pre_enable = analogix_dp_bridge_nop, + .post_disable = analogix_dp_bridge_nop, + .attach = analogix_dp_bridge_attach, };
-static int exynos_dp_create_connector(struct exynos_drm_display *display, - struct drm_encoder *encoder) +static int analogix_dp_bridge_register(struct drm_device *drm_dev, + struct analogix_dp_device *dp) + { - struct exynos_dp_device *dp = display_to_dp(display); - struct drm_device *drm_dev = dp->drm_dev; struct drm_bridge *bridge; int ret;
@@ -1163,11 +1132,10 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, }
dp->bridge = bridge; - dp->encoder = encoder;
bridge->driver_private = dp; bridge->encoder = dp->encoder; - bridge->funcs = &exynos_dp_bridge_funcs; + bridge->funcs = &analogix_dp_bridge_funcs;
ret = drm_bridge_attach(drm_dev, bridge); if (ret) { @@ -1178,18 +1146,7 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, return 0; }
-static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) -{ - /* do nothing */ -} - -static struct exynos_drm_display_ops exynos_dp_display_ops = { - .create_connector = exynos_dp_create_connector, - .dpms = exynos_dp_dpms, - .commit = exynos_dp_commit, -}; - -static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) +static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) { struct device_node *dp_node = dev->of_node; struct video_info *dp_video_config; @@ -1208,37 +1165,37 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) dp_video_config->interlaced = of_property_read_bool(dp_node, "interlaced");
- if (of_property_read_u32(dp_node, "samsung,color-space", + if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) { dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "samsung,dynamic-range", + if (of_property_read_u32(dp_node, "analogix,dynamic-range", &dp_video_config->dynamic_range)) { dev_err(dev, "failed to get dynamic-range\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff", + if (of_property_read_u32(dp_node, "analogix,ycbcr-coeff", &dp_video_config->ycbcr_coeff)) { dev_err(dev, "failed to get ycbcr-coeff\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "samsung,color-depth", + if (of_property_read_u32(dp_node, "analogix,color-depth", &dp_video_config->color_depth)) { dev_err(dev, "failed to get color-depth\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "samsung,link-rate", + if (of_property_read_u32(dp_node, "analogix,link-rate", &dp_video_config->link_rate)) { dev_err(dev, "failed to get link-rate\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "samsung,lane-count", + if (of_property_read_u32(dp_node, "analogix,lane-count", &dp_video_config->lane_count)) { dev_err(dev, "failed to get lane-count\n"); return ERR_PTR(-EINVAL); @@ -1247,32 +1204,33 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) return dp_video_config; }
-static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, + struct drm_encoder *encoder, + struct analogix_dp_plat_data *plat_data) { - int ret; - - ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm, - OF_USE_NATIVE_MODE); - if (ret) { - DRM_ERROR("failed: of_get_videomode() : %d\n", ret); - return ret; - } - return 0; -} - -static int exynos_dp_bind(struct device *dev, struct device *master, void *data) -{ - struct exynos_dp_device *dp = dev_get_drvdata(dev); struct platform_device *pdev = to_platform_device(dev); - struct drm_device *drm_dev = data; + struct analogix_dp_device *dp; struct resource *res; unsigned int irq_flags; int ret = 0;
+ dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + dev_set_drvdata(dev, dp); + dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF;
- dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); + /* + * platform dp driver need containor_of the plat_data to get + * the driver private data, so we need to store the point of + * plat_data, not the context of plat_data. + */ + dp->plat_data = plat_data; + + dp->video_info = analogix_dp_dt_parse_pdata(&pdev->dev); if (IS_ERR(dp->video_info)) return PTR_ERR(dp->video_info);
@@ -1292,12 +1250,6 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) } }
- if (!dp->panel && !dp->ptn_bridge) { - ret = exynos_dp_dt_parse_panel(dp); - if (ret) - return ret; - } - dp->clock = devm_clk_get(&pdev->dev, "dp"); if (IS_ERR(dp->clock)) { dev_err(&pdev->dev, "failed to get clock\n"); @@ -1312,7 +1264,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) if (IS_ERR(dp->reg_base)) return PTR_ERR(dp->reg_base);
- dp->hpd_gpio = of_get_named_gpio(dev->of_node, "samsung,hpd-gpio", 0); + dp->hpd_gpio = of_get_named_gpio(dev->of_node, "analogix,hpd-gpio", 0);
if (gpio_is_valid(dp->hpd_gpio)) { /* @@ -1341,14 +1293,14 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) return -ENODEV; }
- INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); + INIT_WORK(&dp->hotplug_work, analogix_dp_hotplug);
- exynos_dp_phy_init(dp); + analogix_dp_phy_init(dp);
- exynos_dp_init_dp(dp); + analogix_dp_init_dp(dp);
- ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, - irq_flags, "exynos-dp", dp); + ret = devm_request_irq(&pdev->dev, dp->irq, analogix_dp_irq_handler, + irq_flags, "analogix-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; @@ -1356,108 +1308,38 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) disable_irq(dp->irq);
dp->drm_dev = drm_dev; + dp->encoder = encoder;
- return exynos_drm_create_enc_conn(drm_dev, &dp->display); -} - -static void exynos_dp_unbind(struct device *dev, struct device *master, - void *data) -{ - struct exynos_dp_device *dp = dev_get_drvdata(dev); - - exynos_dp_bridge_disable(dp->bridge); -} - -static const struct component_ops exynos_dp_ops = { - .bind = exynos_dp_bind, - .unbind = exynos_dp_unbind, -}; - -static int exynos_dp_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *panel_node, *bridge_node, *endpoint; - struct exynos_dp_device *dp; - - dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), - GFP_KERNEL); - if (!dp) - return -ENOMEM; - - dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; - dp->display.ops = &exynos_dp_display_ops; - platform_set_drvdata(pdev, dp); - - panel_node = of_parse_phandle(dev->of_node, "panel", 0); - if (panel_node) { - dp->panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (!dp->panel) - return -EPROBE_DEFER; - } - - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); - if (endpoint) { - bridge_node = of_graph_get_remote_port_parent(endpoint); - if (bridge_node) { - dp->ptn_bridge = of_drm_find_bridge(bridge_node); - of_node_put(bridge_node); - if (!dp->ptn_bridge) - return -EPROBE_DEFER; - } else { - return -EPROBE_DEFER; - } - } - - return component_add(&pdev->dev, &exynos_dp_ops); + return analogix_dp_bridge_register(drm_dev, dp); } +EXPORT_SYMBOL_GPL(analogix_dp_bind);
-static int exynos_dp_remove(struct platform_device *pdev) +void analogix_dp_unbind(struct device *dev, struct device *master, void *data) { - component_del(&pdev->dev, &exynos_dp_ops); + struct analogix_dp_device *dp = dev_get_drvdata(dev);
- return 0; + analogix_dp_bridge_disable(dp->bridge); } +EXPORT_SYMBOL_GPL(analogix_dp_unbind);
-#ifdef CONFIG_PM_SLEEP -static int exynos_dp_suspend(struct device *dev) +int analogix_dp_suspend(struct device *dev) { - struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct analogix_dp_device *dp = dev_get_drvdata(dev);
- exynos_dp_bridge_disable(dp->bridge); + analogix_dp_bridge_disable(dp->bridge); return 0; } +EXPORT_SYMBOL_GPL(analogix_dp_suspend);
-static int exynos_dp_resume(struct device *dev) +int analogix_dp_resume(struct device *dev) { - struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct analogix_dp_device *dp = dev_get_drvdata(dev);
- exynos_dp_bridge_enable(dp->bridge); + analogix_dp_bridge_enable(dp->bridge); return 0; } -#endif - -static const struct dev_pm_ops exynos_dp_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) -}; - -static const struct of_device_id exynos_dp_match[] = { - { .compatible = "samsung,exynos5-dp" }, - {}, -}; -MODULE_DEVICE_TABLE(of, exynos_dp_match); - -struct platform_driver dp_driver = { - .probe = exynos_dp_probe, - .remove = exynos_dp_remove, - .driver = { - .name = "exynos-dp", - .owner = THIS_MODULE, - .pm = &exynos_dp_pm_ops, - .of_match_table = exynos_dp_match, - }, -}; +EXPORT_SYMBOL_GPL(analogix_dp_resume);
MODULE_AUTHOR("Jingoo Han jg1.han@samsung.com"); -MODULE_DESCRIPTION("Samsung SoC DP Driver"); +MODULE_DESCRIPTION("Analogix Core DP Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h new file mode 100644 index 0000000..2cefde9 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -0,0 +1,282 @@ +/* + * Header file for Samsung DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han jg1.han@samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _ANALOGIX_DP_CORE_H +#define _ANALOGIX_DP_CORE_H + +#include <drm/drm_crtc.h> +#include <drm/drm_dp_helper.h> + +#define DP_TIMEOUT_LOOP_COUNT 100 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum link_training_state { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + PLL_UNLOCKED, + PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + +enum dp_irq_type { + DP_IRQ_TYPE_HP_CABLE_IN, + DP_IRQ_TYPE_HP_CABLE_OUT, + DP_IRQ_TYPE_HP_CHANGE, + DP_IRQ_TYPE_UNKNOWN, +}; + +struct video_info { + char *name; + + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; + + enum color_space color_space; + enum dynamic_range dynamic_range; + enum color_coefficient ycbcr_coeff; + enum color_depth color_depth; + + enum link_rate_type link_rate; + enum link_lane_count_type lane_count; +}; + +struct link_train { + int eq_loop; + int cr_loop[4]; + + u8 link_rate; + u8 lane_count; + u8 training_lane[4]; + + enum link_training_state lt_state; +}; + +struct analogix_dp_device { + struct device *dev; + struct drm_device *drm_dev; + struct drm_connector connector; + struct drm_encoder *encoder; + struct drm_bridge *bridge; + struct clk *clock; + unsigned int irq; + void __iomem *reg_base; + + struct video_info *video_info; + struct link_train link_train; + struct work_struct hotplug_work; + struct phy *phy; + int dpms_mode; + int hpd_gpio; + + struct analogix_dp_plat_data *plat_data; +}; + +/* analogix_dp_reg.c */ +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable); +void analogix_dp_stop_video(struct analogix_dp_device *dp); +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable); +void analogix_dp_init_analog_param(struct analogix_dp_device *dp); +void analogix_dp_init_interrupt(struct analogix_dp_device *dp); +void analogix_dp_reset(struct analogix_dp_device *dp); +void analogix_dp_swreset(struct analogix_dp_device *dp); +void analogix_dp_config_interrupt(struct analogix_dp_device *dp); +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable); +void analogix_dp_init_analog_func(struct analogix_dp_device *dp); +void analogix_dp_init_hpd(struct analogix_dp_device *dp); +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp); +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp); +void analogix_dp_reset_aux(struct analogix_dp_device *dp); +void analogix_dp_init_aux(struct analogix_dp_device *dp); +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp); +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp); +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp); +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data); +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data); +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr); +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data); +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]); +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype); +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype); +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count); +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count); +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, + bool enable); +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern); +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane); +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); +void analogix_dp_reset_macro(struct analogix_dp_device *dp); +void analogix_dp_init_video(struct analogix_dp_device *dp); + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp); +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp); +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, u32 n_value); +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type); +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, + bool enable); +void analogix_dp_start_video(struct analogix_dp_device *dp); +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp); +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); + +/* I2C EDID Chip ID, Slave Address */ +#define I2C_EDID_DEVICE_ADDR 0x50 +#define I2C_E_EDID_DEVICE_ADDR 0x30 + +#define EDID_BLOCK_LENGTH 0x80 +#define EDID_HEADER_PATTERN 0x00 +#define EDID_EXTENSION_FLAG 0x7e +#define EDID_CHECKSUM 0x7f + +/* DP_MAX_LANE_COUNT */ +#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) +#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) + +/* DP_LANE_COUNT_SET */ +#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) + +/* DP_TRAINING_LANE0_SET */ +#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) +#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) +#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) +#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) + +#endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix_dp_reg.c new file mode 100644 index 0000000..cc5cdbf --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.c @@ -0,0 +1,1265 @@ +/* + * Samsung DP (Display port) register interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han jg1.han@samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/device.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/gpio.h> + +#include "analogix_dp_core.h" +#include "analogix_dp_reg.h" + +#define COMMON_INT_MASK_1 0 +#define COMMON_INT_MASK_2 0 +#define COMMON_INT_MASK_3 0 +#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) +#define INT_STA_MASK INT_HPD + +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg |= HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg &= ~HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + } +} + +void analogix_dp_stop_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg &= ~VIDEO_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); +} + +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) + reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | + LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; + else + reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | + LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; + + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP); +} + +void analogix_dp_init_analog_param(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = TX_TERMINAL_CTRL_50_OHM; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); + + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3); + + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | + TX_CUR1_2X | TX_CUR_16_MA; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1); + + reg = CH3_AMP_400_MV | CH2_AMP_400_MV | + CH1_AMP_400_MV | CH0_AMP_400_MV; + writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL); +} + +void analogix_dp_init_interrupt(struct analogix_dp_device *dp) +{ + /* Set interrupt pin assertion polarity as high */ + writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL); + + /* Clear pending regisers */ + writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2); + writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3); + writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA); + + /* 0:mask,1: unmask */ + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); + writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); +} + +void analogix_dp_reset(struct analogix_dp_device *dp) +{ + u32 reg; + + analogix_dp_stop_video(dp); + analogix_dp_enable_video_mute(dp, 0); + + reg = 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, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + + reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | + SERDES_FIFO_FUNC_EN_N | + LS_CLK_DOMAIN_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + + usleep_range(20, 30); + + analogix_dp_lane_swap(dp, 0); + + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + + writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); + writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL); + + writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L); + writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H); + + writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL); + + writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST); + + writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD); + writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN); + + writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH); + writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH); + + writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_swreset(struct analogix_dp_device *dp) +{ + writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET); +} + +void analogix_dp_config_interrupt(struct analogix_dp_device *dp) +{ + u32 reg; + + /* 0: mask, 1: unmask */ + reg = COMMON_INT_MASK_1; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); + + reg = COMMON_INT_MASK_2; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); + + reg = COMMON_INT_MASK_3; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); + + reg = COMMON_INT_MASK_4; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); + + reg = INT_STA_MASK; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); +} + +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + if (reg & PLL_LOCK) + return PLL_LOCKED; + else + return PLL_UNLOCKED; +} + +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); + reg |= DP_PLL_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); + reg &= ~DP_PLL_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); + } +} + +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable) +{ + u32 reg; + + switch (block) { + case AUX_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= AUX_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~AUX_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH0_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH1_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH1_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH1_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH2_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH2_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH2_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH3_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH3_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH3_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case ANALOG_TOTAL: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= DP_PHY_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~DP_PHY_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case POWER_ALL: + if (enable) { + reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | + CH1_PD | CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + writel(0x00, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + default: + break; + } +} + +void analogix_dp_init_analog_func(struct analogix_dp_device *dp) +{ + u32 reg; + int timeout_loop = 0; + + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); + + reg = PLL_LOCK_CHG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); + writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + + /* Power up PLL */ + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + analogix_dp_set_pll_power_down(dp, 0); + + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "failed to get pll lock status\n"); + return; + } + usleep_range(10, 20); + } + } + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N + | AUX_FUNC_EN_N); + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + reg = HOTPLUG_CHG | HPD_LOST | PLUG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + + reg = INT_HPD; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); +} + +void analogix_dp_init_hpd(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + analogix_dp_clear_hotplug_interrupts(dp); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + reg &= ~(F_HPD | HPD_CTRL); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); +} + +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + reg = gpio_get_value(dp->hpd_gpio); + if (reg) + return DP_IRQ_TYPE_HP_CABLE_IN; + else + return DP_IRQ_TYPE_HP_CABLE_OUT; + } else { + /* Parse hotplug interrupt status register */ + reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + + if (reg & PLUG) + return DP_IRQ_TYPE_HP_CABLE_IN; + + if (reg & HPD_LOST) + return DP_IRQ_TYPE_HP_CABLE_OUT; + + if (reg & HOTPLUG_CHG) + return DP_IRQ_TYPE_HP_CHANGE; + + return DP_IRQ_TYPE_UNKNOWN; + } +} + +void analogix_dp_reset_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Disable AUX channel module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg |= AUX_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +void analogix_dp_init_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Clear inerrupts related to AUX channel */ + reg = RPLY_RECEIV | AUX_ERR; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); + + analogix_dp_reset_aux(dp); + + /* Disable AUX transaction H/W retry */ + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL); + + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ + reg = DEFER_CTRL_EN | DEFER_COUNT(1); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL); + + /* Enable AUX channel module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg &= ~AUX_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + if (gpio_get_value(dp->hpd_gpio)) + return 0; + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + if (reg & HPD_STATUS) + return 0; + } + + return -EINVAL; +} + +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + reg &= ~SW_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); +} + +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) +{ + int reg; + int retval = 0; + int timeout_loop = 0; + + /* Enable AUX CH operation */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + reg |= AUX_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + + /* Is AUX CH command reply received? */ + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + while (!(reg & RPLY_RECEIV)) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "AUX CH command reply failed!\n"); + return -ETIMEDOUT; + } + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + usleep_range(10, 11); + } + + /* Clear interrupt source for AUX CH command reply */ + writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA); + + /* Clear interrupt source for AUX CH access error */ + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + if (reg & AUX_ERR) { + writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); + return -EREMOTEIO; + } + + /* Check AUX CH error access status */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); + if ((reg & AUX_STATUS_MASK) != 0) { + dev_err(dp->dev, "AUX CH error happens: %d\n\n", + reg & AUX_STATUS_MASK); + return -EREMOTEIO; + } + + return retval; +} + +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); + + /* Write data buffer */ + reg = (unsigned int)data; + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + /* + * 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + return retval; +} + +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + /* Read data buffer */ + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + *data = (unsigned char)(reg & 0xff); + + return retval; +} + +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_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; + + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_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, dp->reg_base + + ANALOGIX_DP_BUF_DATA_0 + + 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_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; + + /* AUX CH Request Transaction process */ + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * cur_data_idx); + data[start_offset + cur_data_idx] = + (unsigned char)reg; + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr) +{ + u32 reg; + int retval; + + /* Set EDID device address */ + reg = device_addr; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); + + /* Set offset from base address of EDID device */ + writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + /* + * 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval != 0) + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + + return retval; +} + +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select EDID device */ + retval = analogix_dp_select_i2c_device(dp, device_addr, + reg_addr); + if (retval != 0) + 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + /* Read data */ + if (retval == 0) + *data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + return retval; +} + +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]) +{ + u32 reg; + unsigned int i, j; + unsigned int cur_data_idx; + unsigned int defer = 0; + int retval = 0; + + for (i = 0; i < count; i += 16) { + for (j = 0; j < 3; j++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Set normal AUX CH command */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + reg &= ~ADDR_ONLY; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending address + */ + if (!defer) + retval = analogix_dp_select_i2c_device( + dp, device_addr, reg_addr + i); + else + defer = 0; + + if (retval == 0) { + /* + * 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->reg_base + + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + /* Check if Rx sends defer */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM); + if (reg == AUX_RX_COMM_AUX_DEFER || + reg == AUX_RX_COMM_I2C_DEFER) { + dev_err(dp->dev, "Defer: %d\n\n", reg); + defer = 1; + } + } + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * cur_data_idx); + edid[i + cur_data_idx] = (unsigned char)reg; + } + } + + return retval; +} + +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) +{ + u32 reg; + + reg = bwtype; + if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS)) + writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET); +} + +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET); + *bwtype = reg; +} + +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count) +{ + u32 reg; + + reg = count; + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); +} + +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); + *count = reg; +} + +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, + bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg |= ENHANCED; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg &= ~ENHANCED; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + } +} + +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern) +{ + u32 reg; + + switch (pattern) { + case PRBS7: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case D10_2: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN1: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN2: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case DP_NONE: + reg = SCRAMBLING_ENABLE | + LINK_QUAL_PATTERN_SET_DISABLE | + SW_TRAINING_PATTERN_SET_NORMAL; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + default: + break; + } +} + +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); +} + +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); + return reg; +} + +void analogix_dp_reset_macro(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST); + reg |= MACRO_RST; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); + + /* 10 us is the minimum reset time. */ + usleep_range(10, 20); + + reg &= ~MACRO_RST; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); +} + +void analogix_dp_init_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + + reg = 0x0; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + reg = CHA_CRI(4) | CHA_CTRL; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + + reg = 0x0; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + + reg = VID_HRES_TH(2) | VID_VRES_TH(0); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8); +} + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | + (dp->video_info->color_depth << IN_BPC_SHIFT) | + (dp->video_info->color_space << IN_COLOR_F_SHIFT); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); + reg &= ~IN_YC_COEFFI_MASK; + if (dp->video_info->ycbcr_coeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); +} + +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + if (!(reg & DET_STA)) { + dev_dbg(dp->dev, "Input stream clock not detected.\n"); + return -EINVAL; + } + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); + + if (reg & CHA_STA) { + dev_dbg(dp->dev, "Input stream clk is changing\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, u32 n_value) +{ + u32 reg; + + if (type == REGISTER_M) { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg |= FIX_M_VID; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg = m_value & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0); + reg = (m_value >> 8) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1); + reg = (m_value >> 16) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2); + + reg = n_value & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0); + reg = (n_value >> 8) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1); + reg = (n_value >> 16) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg &= ~FIX_M_VID; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0); + writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1); + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2); + } +} + +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type) +{ + u32 reg; + + if (type == VIDEO_TIMING_FROM_CAPTURE) { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~FORMAT_SEL; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg |= FORMAT_SEL; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + } +} + +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + } +} + +void analogix_dp_start_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg |= VIDEO_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); +} + +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + if (!(reg & STRM_VALID)) { + dev_dbg(dp->dev, "Input video stream is not detected.\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); + reg |= MASTER_VID_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~INTERACE_SCAN_CFG; + reg |= (dp->video_info->interlaced << 2); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~VSYNC_POLARITY_CFG; + reg |= (dp->video_info->v_sync_polarity << 1); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~HSYNC_POLARITY_CFG; + reg |= (dp->video_info->h_sync_polarity << 0); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + reg &= ~SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); +} + +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + reg |= SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); +} diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h b/drivers/gpu/drm/bridge/analogix_dp_reg.h similarity index 64% rename from drivers/gpu/drm/exynos/exynos_dp_reg.h rename to drivers/gpu/drm/bridge/analogix_dp_reg.h index 2e9bd0e..bed226f 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.h @@ -1,5 +1,5 @@ /* - * Register definition file for Samsung DP driver + * Register definition file for Analogix Core DP driver * * Copyright (C) 2012 Samsung Electronics Co., Ltd. * Author: Jingoo Han jg1.han@samsung.com @@ -9,96 +9,96 @@ * published by the Free Software Foundation. */
-#ifndef _EXYNOS_DP_REG_H -#define _EXYNOS_DP_REG_H - -#define EXYNOS_DP_TX_SW_RESET 0x14 -#define EXYNOS_DP_FUNC_EN_1 0x18 -#define EXYNOS_DP_FUNC_EN_2 0x1C -#define EXYNOS_DP_VIDEO_CTL_1 0x20 -#define EXYNOS_DP_VIDEO_CTL_2 0x24 -#define EXYNOS_DP_VIDEO_CTL_3 0x28 - -#define EXYNOS_DP_VIDEO_CTL_8 0x3C -#define EXYNOS_DP_VIDEO_CTL_10 0x44 - -#define EXYNOS_DP_LANE_MAP 0x35C - -#define EXYNOS_DP_ANALOG_CTL_1 0x370 -#define EXYNOS_DP_ANALOG_CTL_2 0x374 -#define EXYNOS_DP_ANALOG_CTL_3 0x378 -#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C -#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 - -#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 - -#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 -#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8 -#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC -#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0 -#define EXYNOS_DP_INT_STA 0x3DC -#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0 -#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4 -#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8 -#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC -#define EXYNOS_DP_INT_STA_MASK 0x3F8 -#define EXYNOS_DP_INT_CTL 0x3FC - -#define EXYNOS_DP_SYS_CTL_1 0x600 -#define EXYNOS_DP_SYS_CTL_2 0x604 -#define EXYNOS_DP_SYS_CTL_3 0x608 -#define EXYNOS_DP_SYS_CTL_4 0x60C - -#define EXYNOS_DP_PKT_SEND_CTL 0x640 -#define EXYNOS_DP_HDCP_CTL 0x648 - -#define EXYNOS_DP_LINK_BW_SET 0x680 -#define EXYNOS_DP_LANE_COUNT_SET 0x684 -#define EXYNOS_DP_TRAINING_PTN_SET 0x688 -#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C -#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690 -#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694 -#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698 - -#define EXYNOS_DP_DEBUG_CTL 0x6C0 -#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4 -#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8 -#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0 - -#define EXYNOS_DP_M_VID_0 0x700 -#define EXYNOS_DP_M_VID_1 0x704 -#define EXYNOS_DP_M_VID_2 0x708 -#define EXYNOS_DP_N_VID_0 0x70C -#define EXYNOS_DP_N_VID_1 0x710 -#define EXYNOS_DP_N_VID_2 0x714 - -#define EXYNOS_DP_PLL_CTL 0x71C -#define EXYNOS_DP_PHY_PD 0x720 -#define EXYNOS_DP_PHY_TEST 0x724 - -#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730 -#define EXYNOS_DP_AUDIO_MARGIN 0x73C - -#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764 -#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778 -#define EXYNOS_DP_AUX_CH_STA 0x780 -#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788 -#define EXYNOS_DP_AUX_RX_COMM 0x78C -#define EXYNOS_DP_BUFFER_DATA_CTL 0x790 -#define EXYNOS_DP_AUX_CH_CTL_1 0x794 -#define EXYNOS_DP_AUX_ADDR_7_0 0x798 -#define EXYNOS_DP_AUX_ADDR_15_8 0x79C -#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0 -#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4 - -#define EXYNOS_DP_BUF_DATA_0 0x7C0 - -#define EXYNOS_DP_SOC_GENERAL_CTL 0x800 - -/* EXYNOS_DP_TX_SW_RESET */ +#ifndef _ANALOGIX_DP_REG_H +#define _ANALOGIX_DP_REG_H + +#define ANALOGIX_DP_TX_SW_RESET 0x14 +#define ANALOGIX_DP_FUNC_EN_1 0x18 +#define ANALOGIX_DP_FUNC_EN_2 0x1C +#define ANALOGIX_DP_VIDEO_CTL_1 0x20 +#define ANALOGIX_DP_VIDEO_CTL_2 0x24 +#define ANALOGIX_DP_VIDEO_CTL_3 0x28 + +#define ANALOGIX_DP_VIDEO_CTL_8 0x3C +#define ANALOGIX_DP_VIDEO_CTL_10 0x44 + +#define ANALOGIX_DP_LANE_MAP 0x35C + +#define ANALOGIX_DP_ANALOG_CTL_1 0x370 +#define ANALOGIX_DP_ANALOG_CTL_2 0x374 +#define ANALOGIX_DP_ANALOG_CTL_3 0x378 +#define ANALOGIX_DP_PLL_FILTER_CTL_1 0x37C +#define ANALOGIX_DP_TX_AMP_TUNING_CTL 0x380 + +#define ANALOGIX_DP_AUX_HW_RETRY_CTL 0x390 + +#define ANALOGIX_DP_COMMON_INT_STA_1 0x3C4 +#define ANALOGIX_DP_COMMON_INT_STA_2 0x3C8 +#define ANALOGIX_DP_COMMON_INT_STA_3 0x3CC +#define ANALOGIX_DP_COMMON_INT_STA_4 0x3D0 +#define ANALOGIX_DP_INT_STA 0x3DC +#define ANALOGIX_DP_COMMON_INT_MASK_1 0x3E0 +#define ANALOGIX_DP_COMMON_INT_MASK_2 0x3E4 +#define ANALOGIX_DP_COMMON_INT_MASK_3 0x3E8 +#define ANALOGIX_DP_COMMON_INT_MASK_4 0x3EC +#define ANALOGIX_DP_INT_STA_MASK 0x3F8 +#define ANALOGIX_DP_INT_CTL 0x3FC + +#define ANALOGIX_DP_SYS_CTL_1 0x600 +#define ANALOGIX_DP_SYS_CTL_2 0x604 +#define ANALOGIX_DP_SYS_CTL_3 0x608 +#define ANALOGIX_DP_SYS_CTL_4 0x60C + +#define ANALOGIX_DP_PKT_SEND_CTL 0x640 +#define ANALOGIX_DP_HDCP_CTL 0x648 + +#define ANALOGIX_DP_LINK_BW_SET 0x680 +#define ANALOGIX_DP_LANE_COUNT_SET 0x684 +#define ANALOGIX_DP_TRAINING_PTN_SET 0x688 +#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL 0x68C +#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL 0x690 +#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL 0x694 +#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL 0x698 + +#define ANALOGIX_DP_DEBUG_CTL 0x6C0 +#define ANALOGIX_DP_HPD_DEGLITCH_L 0x6C4 +#define ANALOGIX_DP_HPD_DEGLITCH_H 0x6C8 +#define ANALOGIX_DP_LINK_DEBUG_CTL 0x6E0 + +#define ANALOGIX_DP_M_VID_0 0x700 +#define ANALOGIX_DP_M_VID_1 0x704 +#define ANALOGIX_DP_M_VID_2 0x708 +#define ANALOGIX_DP_N_VID_0 0x70C +#define ANALOGIX_DP_N_VID_1 0x710 +#define ANALOGIX_DP_N_VID_2 0x714 + +#define ANALOGIX_DP_PLL_CTL 0x71C +#define ANALOGIX_DP_PHY_PD 0x720 +#define ANALOGIX_DP_PHY_TEST 0x724 + +#define ANALOGIX_DP_VIDEO_FIFO_THRD 0x730 +#define ANALOGIX_DP_AUDIO_MARGIN 0x73C + +#define ANALOGIX_DP_M_VID_GEN_FILTER_TH 0x764 +#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH 0x778 +#define ANALOGIX_DP_AUX_CH_STA 0x780 +#define ANALOGIX_DP_AUX_CH_DEFER_CTL 0x788 +#define ANALOGIX_DP_AUX_RX_COMM 0x78C +#define ANALOGIX_DP_BUFFER_DATA_CTL 0x790 +#define ANALOGIX_DP_AUX_CH_CTL_1 0x794 +#define ANALOGIX_DP_AUX_ADDR_7_0 0x798 +#define ANALOGIX_DP_AUX_ADDR_15_8 0x79C +#define ANALOGIX_DP_AUX_ADDR_19_16 0x7A0 +#define ANALOGIX_DP_AUX_CH_CTL_2 0x7A4 + +#define ANALOGIX_DP_BUF_DATA_0 0x7C0 + +#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 + +/* ANALOGIX_DP_TX_SW_RESET */ #define RESET_DP_TX (0x1 << 0)
-/* EXYNOS_DP_FUNC_EN_1 */ +/* ANALOGIX_DP_FUNC_EN_1 */ #define MASTER_VID_FUNC_EN_N (0x1 << 7) #define SLAVE_VID_FUNC_EN_N (0x1 << 5) #define AUD_FIFO_FUNC_EN_N (0x1 << 4) @@ -107,17 +107,17 @@ #define CRC_FUNC_EN_N (0x1 << 1) #define SW_FUNC_EN_N (0x1 << 0)
-/* EXYNOS_DP_FUNC_EN_2 */ +/* ANALOGIX_DP_FUNC_EN_2 */ #define SSC_FUNC_EN_N (0x1 << 7) #define AUX_FUNC_EN_N (0x1 << 2) #define SERDES_FIFO_FUNC_EN_N (0x1 << 1) #define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
-/* EXYNOS_DP_VIDEO_CTL_1 */ +/* ANALOGIX_DP_VIDEO_CTL_1 */ #define VIDEO_EN (0x1 << 7) #define HDCP_VIDEO_MUTE (0x1 << 6)
-/* EXYNOS_DP_VIDEO_CTL_1 */ +/* ANALOGIX_DP_VIDEO_CTL_1 */ #define IN_D_RANGE_MASK (0x1 << 7) #define IN_D_RANGE_SHIFT (7) #define IN_D_RANGE_CEA (0x1 << 7) @@ -134,7 +134,7 @@ #define IN_COLOR_F_YCBCR422 (0x1 << 0) #define IN_COLOR_F_RGB (0x0 << 0)
-/* EXYNOS_DP_VIDEO_CTL_3 */ +/* ANALOGIX_DP_VIDEO_CTL_3 */ #define IN_YC_COEFFI_MASK (0x1 << 7) #define IN_YC_COEFFI_SHIFT (7) #define IN_YC_COEFFI_ITU709 (0x1 << 7) @@ -144,17 +144,17 @@ #define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) #define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
-/* EXYNOS_DP_VIDEO_CTL_8 */ +/* ANALOGIX_DP_VIDEO_CTL_8 */ #define VID_HRES_TH(x) (((x) & 0xf) << 4) #define VID_VRES_TH(x) (((x) & 0xf) << 0)
-/* EXYNOS_DP_VIDEO_CTL_10 */ +/* ANALOGIX_DP_VIDEO_CTL_10 */ #define FORMAT_SEL (0x1 << 4) #define INTERACE_SCAN_CFG (0x1 << 2) #define VSYNC_POLARITY_CFG (0x1 << 1) #define HSYNC_POLARITY_CFG (0x1 << 0)
-/* EXYNOS_DP_LANE_MAP */ +/* ANALOGIX_DP_LANE_MAP */ #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) #define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) #define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) @@ -172,30 +172,30 @@ #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
-/* EXYNOS_DP_ANALOG_CTL_1 */ +/* ANALOGIX_DP_ANALOG_CTL_1 */ #define TX_TERMINAL_CTRL_50_OHM (0x1 << 4)
-/* EXYNOS_DP_ANALOG_CTL_2 */ +/* ANALOGIX_DP_ANALOG_CTL_2 */ #define SEL_24M (0x1 << 3) #define TX_DVDD_BIT_1_0625V (0x4 << 0)
-/* EXYNOS_DP_ANALOG_CTL_3 */ +/* ANALOGIX_DP_ANALOG_CTL_3 */ #define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) #define VCO_BIT_600_MICRO (0x5 << 0)
-/* EXYNOS_DP_PLL_FILTER_CTL_1 */ +/* ANALOGIX_DP_PLL_FILTER_CTL_1 */ #define PD_RING_OSC (0x1 << 6) #define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) #define TX_CUR1_2X (0x1 << 2) #define TX_CUR_16_MA (0x3 << 0)
-/* EXYNOS_DP_TX_AMP_TUNING_CTL */ +/* ANALOGIX_DP_TX_AMP_TUNING_CTL */ #define CH3_AMP_400_MV (0x0 << 24) #define CH2_AMP_400_MV (0x0 << 16) #define CH1_AMP_400_MV (0x0 << 8) #define CH0_AMP_400_MV (0x0 << 0)
-/* EXYNOS_DP_AUX_HW_RETRY_CTL */ +/* ANALOGIX_DP_AUX_HW_RETRY_CTL */ #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) #define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) @@ -204,7 +204,7 @@ #define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) #define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
-/* EXYNOS_DP_COMMON_INT_STA_1 */ +/* ANALOGIX_DP_COMMON_INT_STA_1 */ #define VSYNC_DET (0x1 << 7) #define PLL_LOCK_CHG (0x1 << 6) #define SPDIF_ERR (0x1 << 5) @@ -214,19 +214,19 @@ #define VID_CLK_CHG (0x1 << 1) #define SW_INT (0x1 << 0)
-/* EXYNOS_DP_COMMON_INT_STA_2 */ +/* ANALOGIX_DP_COMMON_INT_STA_2 */ #define ENC_EN_CHG (0x1 << 6) #define HW_BKSV_RDY (0x1 << 3) #define HW_SHA_DONE (0x1 << 2) #define HW_AUTH_STATE_CHG (0x1 << 1) #define HW_AUTH_DONE (0x1 << 0)
-/* EXYNOS_DP_COMMON_INT_STA_3 */ +/* ANALOGIX_DP_COMMON_INT_STA_3 */ #define AFIFO_UNDER (0x1 << 7) #define AFIFO_OVER (0x1 << 6) #define R0_CHK_FLAG (0x1 << 5)
-/* EXYNOS_DP_COMMON_INT_STA_4 */ +/* ANALOGIX_DP_COMMON_INT_STA_4 */ #define PSR_ACTIVE (0x1 << 7) #define PSR_INACTIVE (0x1 << 6) #define SPDIF_BI_PHASE_ERR (0x1 << 5) @@ -234,29 +234,29 @@ #define HPD_LOST (0x1 << 1) #define PLUG (0x1 << 0)
-/* EXYNOS_DP_INT_STA */ +/* ANALOGIX_DP_INT_STA */ #define INT_HPD (0x1 << 6) #define HW_TRAINING_FINISH (0x1 << 5) #define RPLY_RECEIV (0x1 << 1) #define AUX_ERR (0x1 << 0)
-/* EXYNOS_DP_INT_CTL */ +/* ANALOGIX_DP_INT_CTL */ #define SOFT_INT_CTRL (0x1 << 2) #define INT_POL1 (0x1 << 1) #define INT_POL0 (0x1 << 0)
-/* EXYNOS_DP_SYS_CTL_1 */ +/* ANALOGIX_DP_SYS_CTL_1 */ #define DET_STA (0x1 << 2) #define FORCE_DET (0x1 << 1) #define DET_CTRL (0x1 << 0)
-/* EXYNOS_DP_SYS_CTL_2 */ +/* ANALOGIX_DP_SYS_CTL_2 */ #define CHA_CRI(x) (((x) & 0xf) << 4) #define CHA_STA (0x1 << 2) #define FORCE_CHA (0x1 << 1) #define CHA_CTRL (0x1 << 0)
-/* EXYNOS_DP_SYS_CTL_3 */ +/* ANALOGIX_DP_SYS_CTL_3 */ #define HPD_STATUS (0x1 << 6) #define F_HPD (0x1 << 5) #define HPD_CTRL (0x1 << 4) @@ -265,13 +265,13 @@ #define F_VALID (0x1 << 1) #define VALID_CTRL (0x1 << 0)
-/* EXYNOS_DP_SYS_CTL_4 */ +/* ANALOGIX_DP_SYS_CTL_4 */ #define FIX_M_AUD (0x1 << 4) #define ENHANCED (0x1 << 3) #define FIX_M_VID (0x1 << 2) #define M_VID_UPDATE_CTRL (0x3 << 0)
-/* EXYNOS_DP_TRAINING_PTN_SET */ +/* ANALOGIX_DP_TRAINING_PTN_SET */ #define SCRAMBLER_TYPE (0x1 << 9) #define HW_LINK_TRAINING_PATTERN (0x1 << 8) #define SCRAMBLING_DISABLE (0x1 << 5) @@ -285,24 +285,24 @@ #define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) #define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
-/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ +/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */ #define PRE_EMPHASIS_SET_MASK (0x3 << 3) #define PRE_EMPHASIS_SET_SHIFT (3)
-/* EXYNOS_DP_DEBUG_CTL */ +/* ANALOGIX_DP_DEBUG_CTL */ #define PLL_LOCK (0x1 << 4) #define F_PLL_LOCK (0x1 << 3) #define PLL_LOCK_CTRL (0x1 << 2) #define PN_INV (0x1 << 0)
-/* EXYNOS_DP_PLL_CTL */ +/* ANALOGIX_DP_PLL_CTL */ #define DP_PLL_PD (0x1 << 7) #define DP_PLL_RESET (0x1 << 6) #define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) #define DP_PLL_REF_BIT_1_1250V (0x5 << 0) #define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
-/* EXYNOS_DP_PHY_PD */ +/* ANALOGIX_DP_PHY_PD */ #define DP_PHY_PD (0x1 << 5) #define AUX_PD (0x1 << 4) #define CH3_PD (0x1 << 3) @@ -310,28 +310,28 @@ #define CH1_PD (0x1 << 1) #define CH0_PD (0x1 << 0)
-/* EXYNOS_DP_PHY_TEST */ +/* ANALOGIX_DP_PHY_TEST */ #define MACRO_RST (0x1 << 5) #define CH1_TEST (0x1 << 1) #define CH0_TEST (0x1 << 0)
-/* EXYNOS_DP_AUX_CH_STA */ +/* ANALOGIX_DP_AUX_CH_STA */ #define AUX_BUSY (0x1 << 4) #define AUX_STATUS_MASK (0xf << 0)
-/* EXYNOS_DP_AUX_CH_DEFER_CTL */ +/* ANALOGIX_DP_AUX_CH_DEFER_CTL */ #define DEFER_CTRL_EN (0x1 << 7) #define DEFER_COUNT(x) (((x) & 0x7f) << 0)
-/* EXYNOS_DP_AUX_RX_COMM */ +/* ANALOGIX_DP_AUX_RX_COMM */ #define AUX_RX_COMM_I2C_DEFER (0x2 << 2) #define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
-/* EXYNOS_DP_BUFFER_DATA_CTL */ +/* ANALOGIX_DP_BUFFER_DATA_CTL */ #define BUF_CLR (0x1 << 7) #define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
-/* EXYNOS_DP_AUX_CH_CTL_1 */ +/* ANALOGIX_DP_AUX_CH_CTL_1 */ #define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) #define AUX_TX_COMM_MASK (0xf << 0) #define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) @@ -340,20 +340,20 @@ #define AUX_TX_COMM_WRITE (0x0 << 0) #define AUX_TX_COMM_READ (0x1 << 0)
-/* EXYNOS_DP_AUX_ADDR_7_0 */ +/* ANALOGIX_DP_AUX_ADDR_7_0 */ #define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
-/* EXYNOS_DP_AUX_ADDR_15_8 */ +/* ANALOGIX_DP_AUX_ADDR_15_8 */ #define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
-/* EXYNOS_DP_AUX_ADDR_19_16 */ +/* ANALOGIX_DP_AUX_ADDR_19_16 */ #define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
-/* EXYNOS_DP_AUX_CH_CTL_2 */ +/* ANALOGIX_DP_AUX_CH_CTL_2 */ #define ADDR_ONLY (0x1 << 1) #define AUX_EN (0x1 << 0)
-/* EXYNOS_DP_SOC_GENERAL_CTL */ +/* ANALOGIX_DP_SOC_GENERAL_CTL */ #define AUDIO_MODE_SPDIF_MODE (0x1 << 8) #define AUDIO_MODE_MASTER_MODE (0x0 << 8) #define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) @@ -363,4 +363,4 @@ #define VIDEO_MODE_SLAVE_MODE (0x1 << 0) #define VIDEO_MODE_MASTER_MODE (0x0 << 0)
-#endif /* _EXYNOS_DP_REG_H */ +#endif /* _ANALOGIX_DP_REG_H */ diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 43003c4..b33549c 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -54,9 +54,10 @@ config DRM_EXYNOS_DSI help This enables support for Exynos MIPI-DSI device.
-config DRM_EXYNOS_DP - bool "EXYNOS DRM DP driver support" +config DRM_EXYNOS_ANALOGIX_DP + bool "EXYNOS specific extensions for Analogix DP driver" depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) + select DRM_ANALOGIX_DP default DRM_EXYNOS select DRM_PANEL help diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 7de0b10..cda4d26 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -14,7 +14,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o +exynosdrm-$(CONFIG_DRM_EXYNOS_ANALOGIX_DP) += analogix_dp-exynos.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o diff --git a/drivers/gpu/drm/exynos/analogix_dp-exynos.c b/drivers/gpu/drm/exynos/analogix_dp-exynos.c new file mode 100644 index 0000000..d5631c2 --- /dev/null +++ b/drivers/gpu/drm/exynos/analogix_dp-exynos.c @@ -0,0 +1,291 @@ +/* + * Samsung SoC DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han jg1.han@samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/component.h> +#include <linux/of_graph.h> +#include <video/of_display_timing.h> +#include <video/of_videomode.h> + +#include <drm/drmP.h> +#include <drm/drm_panel.h> +#include <drm/bridge/ptn3460.h> +#include <drm/bridge/analogix_dp.h> + +#include <drm/exynos_drm.h> +#include "exynos_drm_drv.h" + +#define plat_data_to_dp(pd) \ + container_of(pd, struct exynos_dp_device, plat_data) + +struct exynos_dp_device { + struct exynos_drm_display display; + struct drm_bridge *ptn_bridge; + struct drm_device *drm_dev; + struct device *dev; + + struct exynos_drm_panel_info priv; + struct analogix_dp_plat_data plat_data; +}; + +int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data, + bool enable) +{ + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct drm_encoder *encoder = dp->display.encoder; + struct exynos_drm_crtc *crtc; + + if (!encoder) + return -1; + + crtc = to_exynos_crtc(encoder->crtc); + if (crtc && crtc->ops && crtc->ops->clock_enable) + crtc->ops->clock_enable(crtc, enable); + + return 0; +} + +static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data) +{ + return exynos_dp_crtc_clock_enable(plat_data, true); +} + +static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) +{ + return exynos_dp_crtc_clock_enable(plat_data, false); +} + +static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data, + struct drm_connector *connector) +{ + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct drm_display_mode *mode; + + if (dp->plat_data.panel) + return 0; + + mode = drm_mode_create(connector->dev); + if (!mode) { + DRM_ERROR("failed to create a new display mode.\n"); + return 0; + } + + drm_display_mode_from_videomode(&dp->priv.vm, mode); + mode->width_mm = dp->priv.width_mm; + mode->height_mm = dp->priv.height_mm; + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_set_name(mode); + drm_mode_probed_add(connector, mode); + + return 1; +} + +static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, + struct drm_bridge *bridge) +{ + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct drm_encoder *encoder = dp->display.encoder; + int ret; + + /* Pre-empt DP connector creation if there's a bridge */ + if (dp->ptn_bridge) { + bridge->next = dp->ptn_bridge; + dp->ptn_bridge->encoder = encoder; + ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge); + if (ret) { + DRM_ERROR("Failed to attach bridge to drm\n"); + bridge->next = NULL; + return ret; + } + } + + return 0; +} + +static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) +{ + /* do nothing */ +} + +static int exynos_dp_create_connector(struct exynos_drm_display *display, + struct drm_encoder *encoder) +{ + /* do nothing */ + return 0; +} + +static void exynos_dp_commit(struct exynos_drm_display *display) +{ + /* do nothing */ +} + +static struct exynos_drm_display_ops exynos_dp_display_ops = { + .create_connector = exynos_dp_create_connector, + .dpms = exynos_dp_dpms, + .commit = exynos_dp_commit, +}; + +static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +{ + int ret; + + ret = of_get_videomode(dp->dev->of_node, &dp->priv.vm, + OF_USE_NATIVE_MODE); + if (ret) { + DRM_ERROR("failed: of_get_videomode() : %d\n", ret); + return ret; + } + + return 0; +} + +static int exynos_dp_bind(struct device *dev, struct device *master, void *data) +{ + struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + int ret; + + /* + * Just like the probe function said, we don't need the + * device drvrate anymore, we should leave the charge to + * analogix dp driver, set the device drvdata to NULL. + */ + dev_set_drvdata(dev, NULL); + + dp->dev = dev; + dp->drm_dev = drm_dev; + + dp->plat_data.power_on = exynos_dp_poweron; + dp->plat_data.power_off = exynos_dp_poweroff; + dp->plat_data.get_modes = exynos_dp_get_modes; + dp->plat_data.attach = exynos_dp_bridge_attach; + + if (!dp->plat_data.panel || !dp->ptn_bridge) { + ret = exynos_dp_dt_parse_panel(dp); + if (ret) + return ret; + } + + ret = exynos_drm_create_enc_conn(dp->drm_dev, &dp->display); + if (ret) { + DRM_ERROR("exynos dp create enc_conn failed\n"); + return ret; + } + + return analogix_dp_bind(dev, dp->drm_dev, dp->display.encoder, + &dp->plat_data); +} + +static void exynos_dp_unbind(struct device *dev, struct device *master, + void *data) +{ + return analogix_dp_unbind(dev, master, data); +} + +static const struct component_ops exynos_dp_ops = { + .bind = exynos_dp_bind, + .unbind = exynos_dp_unbind, +}; + +static int exynos_dp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *panel_node, *bridge_node, *endpoint; + struct exynos_dp_device *dp; + + dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), + GFP_KERNEL); + if (!dp) + return -ENOMEM; + + /* + * We just use the drvdata until driver run into component + * add function, and then we would set drvdata to null, so + * that analogix dp driver would take charge of the drvdata. + */ + platform_set_drvdata(pdev, dp); + + dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; + dp->display.ops = &exynos_dp_display_ops; + + panel_node = of_parse_phandle(dev->of_node, "panel", 0); + if (panel_node) { + dp->plat_data.panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (!dp->plat_data.panel) + return -EPROBE_DEFER; + } + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (endpoint) { + bridge_node = of_graph_get_remote_port_parent(endpoint); + if (bridge_node) { + dp->ptn_bridge = of_drm_find_bridge(bridge_node); + of_node_put(bridge_node); + if (!dp->ptn_bridge) + return -EPROBE_DEFER; + } else { + return -EPROBE_DEFER; + } + } + + return component_add(&pdev->dev, &exynos_dp_ops); +} + +static int exynos_dp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &exynos_dp_ops); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int exynos_dp_suspend(struct device *dev) +{ + return analogix_dp_suspend(dev); +} + +static int exynos_dp_resume(struct device *dev) +{ + return analogix_dp_resume(dev); +} +#endif + +static const struct dev_pm_ops exynos_dp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) +}; + +static const struct of_device_id exynos_dp_match[] = { + { .compatible = "samsung,exynos5-dp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_dp_match); + +struct platform_driver dp_driver = { + .probe = exynos_dp_probe, + .remove = exynos_dp_remove, + .driver = { + .name = "exynos-dp", + .owner = THIS_MODULE, + .pm = &exynos_dp_pm_ops, + .of_match_table = exynos_dp_match, + }, +}; + +MODULE_AUTHOR("Jingoo Han jg1.han@samsung.com"); +MODULE_DESCRIPTION("Samsung Specific Analogix-DP Driver Extension"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h deleted file mode 100644 index 29bd56e..0000000 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Header file for Samsung DP (Display Port) interface driver. - * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Jingoo Han jg1.han@samsung.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef _EXYNOS_DP_CORE_H -#define _EXYNOS_DP_CORE_H - -#include <drm/drm_crtc.h> -#include <drm/drm_dp_helper.h> -#include <drm/exynos_drm.h> - -#include "exynos_drm_drv.h" - -#define DP_TIMEOUT_LOOP_COUNT 100 -#define MAX_CR_LOOP 5 -#define MAX_EQ_LOOP 5 - -enum link_rate_type { - LINK_RATE_1_62GBPS = 0x06, - LINK_RATE_2_70GBPS = 0x0a -}; - -enum link_lane_count_type { - LANE_COUNT1 = 1, - LANE_COUNT2 = 2, - LANE_COUNT4 = 4 -}; - -enum link_training_state { - START, - CLOCK_RECOVERY, - EQUALIZER_TRAINING, - FINISHED, - FAILED -}; - -enum voltage_swing_level { - VOLTAGE_LEVEL_0, - VOLTAGE_LEVEL_1, - VOLTAGE_LEVEL_2, - VOLTAGE_LEVEL_3, -}; - -enum pre_emphasis_level { - PRE_EMPHASIS_LEVEL_0, - PRE_EMPHASIS_LEVEL_1, - PRE_EMPHASIS_LEVEL_2, - PRE_EMPHASIS_LEVEL_3, -}; - -enum pattern_set { - PRBS7, - D10_2, - TRAINING_PTN1, - TRAINING_PTN2, - DP_NONE -}; - -enum color_space { - COLOR_RGB, - COLOR_YCBCR422, - COLOR_YCBCR444 -}; - -enum color_depth { - COLOR_6, - COLOR_8, - COLOR_10, - COLOR_12 -}; - -enum color_coefficient { - COLOR_YCBCR601, - COLOR_YCBCR709 -}; - -enum dynamic_range { - VESA, - CEA -}; - -enum pll_status { - PLL_UNLOCKED, - PLL_LOCKED -}; - -enum clock_recovery_m_value_type { - CALCULATED_M, - REGISTER_M -}; - -enum video_timing_recognition_type { - VIDEO_TIMING_FROM_CAPTURE, - VIDEO_TIMING_FROM_REGISTER -}; - -enum analog_power_block { - AUX_BLOCK, - CH0_BLOCK, - CH1_BLOCK, - CH2_BLOCK, - CH3_BLOCK, - ANALOG_TOTAL, - POWER_ALL -}; - -enum dp_irq_type { - DP_IRQ_TYPE_HP_CABLE_IN, - DP_IRQ_TYPE_HP_CABLE_OUT, - DP_IRQ_TYPE_HP_CHANGE, - DP_IRQ_TYPE_UNKNOWN, -}; - -struct video_info { - char *name; - - bool h_sync_polarity; - bool v_sync_polarity; - bool interlaced; - - enum color_space color_space; - enum dynamic_range dynamic_range; - enum color_coefficient ycbcr_coeff; - enum color_depth color_depth; - - enum link_rate_type link_rate; - enum link_lane_count_type lane_count; -}; - -struct link_train { - int eq_loop; - int cr_loop[4]; - - u8 link_rate; - u8 lane_count; - u8 training_lane[4]; - - enum link_training_state lt_state; -}; - -struct exynos_dp_device { - struct exynos_drm_display display; - struct device *dev; - struct drm_device *drm_dev; - struct drm_connector connector; - struct drm_encoder *encoder; - struct drm_panel *panel; - struct drm_bridge *bridge; - struct drm_bridge *ptn_bridge; - struct clk *clock; - unsigned int irq; - void __iomem *reg_base; - - struct video_info *video_info; - struct link_train link_train; - struct work_struct hotplug_work; - struct phy *phy; - int dpms_mode; - int hpd_gpio; - - struct exynos_drm_panel_info priv; -}; - -/* exynos_dp_reg.c */ -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); -void exynos_dp_stop_video(struct exynos_dp_device *dp); -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); -void exynos_dp_init_analog_param(struct exynos_dp_device *dp); -void exynos_dp_init_interrupt(struct exynos_dp_device *dp); -void exynos_dp_reset(struct exynos_dp_device *dp); -void exynos_dp_swreset(struct exynos_dp_device *dp); -void exynos_dp_config_interrupt(struct exynos_dp_device *dp); -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, - enum analog_power_block block, - bool enable); -void exynos_dp_init_analog_func(struct exynos_dp_device *dp); -void exynos_dp_init_hpd(struct exynos_dp_device *dp); -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp); -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp); -void exynos_dp_reset_aux(struct exynos_dp_device *dp); -void exynos_dp_init_aux(struct exynos_dp_device *dp); -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp); -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp); -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char data); -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char *data); -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr); -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data); -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int count, - unsigned char edid[]); -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype); -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype); -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count); -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count); -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable); -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, - enum pattern_set pattern); -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, - u32 training_lane); -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); -void exynos_dp_reset_macro(struct exynos_dp_device *dp); -void exynos_dp_init_video(struct exynos_dp_device *dp); - -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp); -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, - enum clock_recovery_m_value_type type, - u32 m_value, u32 n_value); -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type); -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); -void exynos_dp_start_video(struct exynos_dp_device *dp); -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp); -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp); -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp); -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp); - -/* I2C EDID Chip ID, Slave Address */ -#define I2C_EDID_DEVICE_ADDR 0x50 -#define I2C_E_EDID_DEVICE_ADDR 0x30 - -#define EDID_BLOCK_LENGTH 0x80 -#define EDID_HEADER_PATTERN 0x00 -#define EDID_EXTENSION_FLAG 0x7e -#define EDID_CHECKSUM 0x7f - -/* DP_MAX_LANE_COUNT */ -#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) -#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) - -/* DP_LANE_COUNT_SET */ -#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) - -/* DP_TRAINING_LANE0_SET */ -#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) -#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) -#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) -#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) - -#endif /* _EXYNOS_DP_CORE_H */ diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.c b/drivers/gpu/drm/exynos/exynos_dp_reg.c deleted file mode 100644 index 9aa483d..0000000 --- a/drivers/gpu/drm/exynos/exynos_dp_reg.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* - * Samsung DP (Display port) register interface driver. - * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Jingoo Han jg1.han@samsung.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include <linux/device.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/gpio.h> - -#include "exynos_dp_core.h" -#include "exynos_dp_reg.h" - -#define COMMON_INT_MASK_1 0 -#define COMMON_INT_MASK_2 0 -#define COMMON_INT_MASK_3 0 -#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) -#define INT_STA_MASK INT_HPD - -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable) -{ - u32 reg; - - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - reg |= HDCP_VIDEO_MUTE; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - reg &= ~HDCP_VIDEO_MUTE; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - } -} - -void exynos_dp_stop_video(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - reg &= ~VIDEO_EN; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); -} - -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable) -{ - u32 reg; - - if (enable) - reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | - LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; - else - reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | - LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; - - writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP); -} - -void exynos_dp_init_analog_param(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = TX_TERMINAL_CTRL_50_OHM; - writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1); - - reg = SEL_24M | TX_DVDD_BIT_1_0625V; - writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2); - - reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; - writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3); - - reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | - TX_CUR1_2X | TX_CUR_16_MA; - writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1); - - reg = CH3_AMP_400_MV | CH2_AMP_400_MV | - CH1_AMP_400_MV | CH0_AMP_400_MV; - writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL); -} - -void exynos_dp_init_interrupt(struct exynos_dp_device *dp) -{ - /* Set interrupt pin assertion polarity as high */ - writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL); - - /* Clear pending regisers */ - writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); - writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2); - writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3); - writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); - writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA); - - /* 0:mask,1: unmask */ - writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1); - writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2); - writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3); - writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4); - writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK); -} - -void exynos_dp_reset(struct exynos_dp_device *dp) -{ - u32 reg; - - exynos_dp_stop_video(dp); - exynos_dp_enable_video_mute(dp, 0); - - reg = 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, dp->reg_base + EXYNOS_DP_FUNC_EN_1); - - reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | - SERDES_FIFO_FUNC_EN_N | - LS_CLK_DOMAIN_FUNC_EN_N; - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); - - usleep_range(20, 30); - - exynos_dp_lane_swap(dp, 0); - - writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1); - writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2); - writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3); - writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4); - - writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL); - writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL); - - writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L); - writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H); - - writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL); - - writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST); - - writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD); - writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN); - - writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH); - writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH); - - writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); -} - -void exynos_dp_swreset(struct exynos_dp_device *dp) -{ - writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET); -} - -void exynos_dp_config_interrupt(struct exynos_dp_device *dp) -{ - u32 reg; - - /* 0: mask, 1: unmask */ - reg = COMMON_INT_MASK_1; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1); - - reg = COMMON_INT_MASK_2; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2); - - reg = COMMON_INT_MASK_3; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3); - - reg = COMMON_INT_MASK_4; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4); - - reg = INT_STA_MASK; - writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK); -} - -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL); - if (reg & PLL_LOCK) - return PLL_LOCKED; - else - return PLL_UNLOCKED; -} - -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable) -{ - u32 reg; - - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL); - reg |= DP_PLL_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL); - reg &= ~DP_PLL_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL); - } -} - -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, - enum analog_power_block block, - bool enable) -{ - u32 reg; - - switch (block) { - case AUX_BLOCK: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= AUX_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~AUX_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case CH0_BLOCK: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= CH0_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~CH0_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case CH1_BLOCK: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= CH1_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~CH1_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case CH2_BLOCK: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= CH2_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~CH2_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case CH3_BLOCK: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= CH3_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~CH3_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case ANALOG_TOTAL: - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg |= DP_PHY_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD); - reg &= ~DP_PHY_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - case POWER_ALL: - if (enable) { - reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | - CH1_PD | CH0_PD; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD); - } else { - writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD); - } - break; - default: - break; - } -} - -void exynos_dp_init_analog_func(struct exynos_dp_device *dp) -{ - u32 reg; - int timeout_loop = 0; - - exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); - - reg = PLL_LOCK_CHG; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); - - reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL); - reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); - writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL); - - /* Power up PLL */ - if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - exynos_dp_set_pll_power_down(dp, 0); - - while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { - timeout_loop++; - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { - dev_err(dp->dev, "failed to get pll lock status\n"); - return; - } - usleep_range(10, 20); - } - } - - /* Enable Serdes FIFO function and Link symbol clock domain module */ - reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); - reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N - | AUX_FUNC_EN_N); - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); -} - -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp) -{ - u32 reg; - - if (gpio_is_valid(dp->hpd_gpio)) - return; - - reg = HOTPLUG_CHG | HPD_LOST | PLUG; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); - - reg = INT_HPD; - writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); -} - -void exynos_dp_init_hpd(struct exynos_dp_device *dp) -{ - u32 reg; - - if (gpio_is_valid(dp->hpd_gpio)) - return; - - exynos_dp_clear_hotplug_interrupts(dp); - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); - reg &= ~(F_HPD | HPD_CTRL); - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); -} - -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp) -{ - u32 reg; - - if (gpio_is_valid(dp->hpd_gpio)) { - reg = gpio_get_value(dp->hpd_gpio); - if (reg) - return DP_IRQ_TYPE_HP_CABLE_IN; - else - return DP_IRQ_TYPE_HP_CABLE_OUT; - } else { - /* Parse hotplug interrupt status register */ - reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4); - - if (reg & PLUG) - return DP_IRQ_TYPE_HP_CABLE_IN; - - if (reg & HPD_LOST) - return DP_IRQ_TYPE_HP_CABLE_OUT; - - if (reg & HOTPLUG_CHG) - return DP_IRQ_TYPE_HP_CHANGE; - - return DP_IRQ_TYPE_UNKNOWN; - } -} - -void exynos_dp_reset_aux(struct exynos_dp_device *dp) -{ - u32 reg; - - /* Disable AUX channel module */ - reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); - reg |= AUX_FUNC_EN_N; - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); -} - -void exynos_dp_init_aux(struct exynos_dp_device *dp) -{ - u32 reg; - - /* Clear inerrupts related to AUX channel */ - reg = RPLY_RECEIV | AUX_ERR; - writel(reg, dp->reg_base + EXYNOS_DP_INT_STA); - - exynos_dp_reset_aux(dp); - - /* Disable AUX transaction H/W retry */ - reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | - AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; - writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL); - - /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ - reg = DEFER_CTRL_EN | DEFER_COUNT(1); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL); - - /* Enable AUX channel module */ - reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2); - reg &= ~AUX_FUNC_EN_N; - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2); -} - -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp) -{ - u32 reg; - - if (gpio_is_valid(dp->hpd_gpio)) { - if (gpio_get_value(dp->hpd_gpio)) - return 0; - } else { - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); - if (reg & HPD_STATUS) - return 0; - } - - return -EINVAL; -} - -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1); - reg &= ~SW_FUNC_EN_N; - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1); -} - -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp) -{ - int reg; - int retval = 0; - int timeout_loop = 0; - - /* Enable AUX CH operation */ - reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); - reg |= AUX_EN; - writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); - - /* Is AUX CH command reply received? */ - reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); - while (!(reg & RPLY_RECEIV)) { - timeout_loop++; - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { - dev_err(dp->dev, "AUX CH command reply failed!\n"); - return -ETIMEDOUT; - } - reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); - usleep_range(10, 11); - } - - /* Clear interrupt source for AUX CH command reply */ - writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA); - - /* Clear interrupt source for AUX CH access error */ - reg = readl(dp->reg_base + EXYNOS_DP_INT_STA); - if (reg & AUX_ERR) { - writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA); - return -EREMOTEIO; - } - - /* Check AUX CH error access status */ - reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA); - if ((reg & AUX_STATUS_MASK) != 0) { - dev_err(dp->dev, "AUX CH error happens: %d\n\n", - reg & AUX_STATUS_MASK); - return -EREMOTEIO; - } - - return retval; -} - -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char data) -{ - u32 reg; - int i; - int retval; - - for (i = 0; i < 3; i++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); - - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); - reg = AUX_ADDR_15_8(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); - reg = AUX_ADDR_19_16(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); - - /* Write data buffer */ - reg = (unsigned int)data; - writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0); - - /* - * 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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); - } - - return retval; -} - -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char *data) -{ - u32 reg; - int i; - int retval; - - for (i = 0; i < 3; i++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); - - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); - reg = AUX_ADDR_15_8(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); - reg = AUX_ADDR_19_16(reg_addr); - writel(reg, dp->reg_base + EXYNOS_DP_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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); - } - - /* Read data buffer */ - reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0); - *data = (unsigned char)(reg & 0xff); - - return retval; -} - -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]) -{ - u32 reg; - unsigned int start_offset; - unsigned int cur_data_count; - unsigned int cur_data_idx; - int i; - int retval = 0; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_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; - - for (i = 0; i < 3; i++) { - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); - reg = AUX_ADDR_15_8(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); - reg = AUX_ADDR_19_16(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_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, dp->reg_base + EXYNOS_DP_BUF_DATA_0 - + 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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); - } - - start_offset += cur_data_count; - } - - return retval; -} - -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]) -{ - u32 reg; - unsigned int start_offset; - unsigned int cur_data_count; - unsigned int cur_data_idx; - int i; - int retval = 0; - - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_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; - - /* AUX CH Request Transaction process */ - for (i = 0; i < 3; i++) { - /* Select DPCD device address */ - reg = AUX_ADDR_7_0(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); - reg = AUX_ADDR_15_8(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); - reg = AUX_ADDR_19_16(reg_addr + start_offset); - writel(reg, dp->reg_base + EXYNOS_DP_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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); - } - - for (cur_data_idx = 0; cur_data_idx < cur_data_count; - cur_data_idx++) { - reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0 - + 4 * cur_data_idx); - data[start_offset + cur_data_idx] = - (unsigned char)reg; - } - - start_offset += cur_data_count; - } - - return retval; -} - -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr) -{ - u32 reg; - int retval; - - /* Set EDID device address */ - reg = device_addr; - writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0); - writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8); - writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16); - - /* Set offset from base address of EDID device */ - writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0); - - /* - * 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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval != 0) - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); - - return retval; -} - -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data) -{ - u32 reg; - int i; - int retval; - - for (i = 0; i < 3; i++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); - - /* Select EDID device */ - retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr); - if (retval != 0) - 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->reg_base + EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); - } - - /* Read data */ - if (retval == 0) - *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0); - - return retval; -} - -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int count, - unsigned char edid[]) -{ - u32 reg; - unsigned int i, j; - unsigned int cur_data_idx; - unsigned int defer = 0; - int retval = 0; - - for (i = 0; i < count; i += 16) { - for (j = 0; j < 3; j++) { - /* Clear AUX CH data buffer */ - reg = BUF_CLR; - writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL); - - /* Set normal AUX CH command */ - reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); - reg &= ~ADDR_ONLY; - writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2); - - /* - * If Rx sends defer, Tx sends only reads - * request without sending address - */ - if (!defer) - retval = exynos_dp_select_i2c_device( - dp, device_addr, reg_addr + i); - else - defer = 0; - - if (retval == 0) { - /* - * 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->reg_base + - EXYNOS_DP_AUX_CH_CTL_1); - - /* Start AUX transaction */ - retval = exynos_dp_start_aux_transaction(dp); - if (retval == 0) - break; - - dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", - __func__); - } - /* Check if Rx sends defer */ - reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM); - if (reg == AUX_RX_COMM_AUX_DEFER || - reg == AUX_RX_COMM_I2C_DEFER) { - dev_err(dp->dev, "Defer: %d\n\n", reg); - defer = 1; - } - } - - for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { - reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0 - + 4 * cur_data_idx); - edid[i + cur_data_idx] = (unsigned char)reg; - } - } - - return retval; -} - -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype) -{ - u32 reg; - - reg = bwtype; - if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS)) - writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET); -} - -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET); - *bwtype = reg; -} - -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count) -{ - u32 reg; - - reg = count; - writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET); -} - -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET); - *count = reg; -} - -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable) -{ - u32 reg; - - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); - reg |= ENHANCED; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); - reg &= ~ENHANCED; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); - } -} - -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, - enum pattern_set pattern) -{ - u32 reg; - - switch (pattern) { - case PRBS7: - reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - break; - case D10_2: - reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - break; - case TRAINING_PTN1: - reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - break; - case TRAINING_PTN2: - reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - break; - case DP_NONE: - reg = SCRAMBLING_ENABLE | - LINK_QUAL_PATTERN_SET_DISABLE | - SW_TRAINING_PATTERN_SET_NORMAL; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - break; - default: - break; - } -} - -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); -} - -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); -} - -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL); - return reg; -} - -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL); - return reg; -} - -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL); - return reg; -} - -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL); - return reg; -} - -void exynos_dp_reset_macro(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST); - reg |= MACRO_RST; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST); - - /* 10 us is the minimum reset time. */ - usleep_range(10, 20); - - reg &= ~MACRO_RST; - writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST); -} - -void exynos_dp_init_video(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; - writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1); - - reg = 0x0; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1); - - reg = CHA_CRI(4) | CHA_CTRL; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2); - - reg = 0x0; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); - - reg = VID_HRES_TH(2) | VID_VRES_TH(0); - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8); -} - -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp) -{ - u32 reg; - - /* Configure the input color depth, color space, dynamic range */ - reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | - (dp->video_info->color_depth << IN_BPC_SHIFT) | - (dp->video_info->color_space << IN_COLOR_F_SHIFT); - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2); - - /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); - reg &= ~IN_YC_COEFFI_MASK; - if (dp->video_info->ycbcr_coeff) - reg |= IN_YC_COEFFI_ITU709; - else - reg |= IN_YC_COEFFI_ITU601; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3); -} - -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1); - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1); - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1); - - if (!(reg & DET_STA)) { - dev_dbg(dp->dev, "Input stream clock not detected.\n"); - return -EINVAL; - } - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2); - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2); - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2); - dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); - - if (reg & CHA_STA) { - dev_dbg(dp->dev, "Input stream clk is changing\n"); - return -EINVAL; - } - - return 0; -} - -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, - enum clock_recovery_m_value_type type, - u32 m_value, - u32 n_value) -{ - u32 reg; - - if (type == REGISTER_M) { - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); - reg |= FIX_M_VID; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); - reg = m_value & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0); - reg = (m_value >> 8) & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1); - reg = (m_value >> 16) & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2); - - reg = n_value & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0); - reg = (n_value >> 8) & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1); - reg = (n_value >> 16) & 0xff; - writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4); - reg &= ~FIX_M_VID; - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4); - - writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0); - writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1); - writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2); - } -} - -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type) -{ - u32 reg; - - if (type == VIDEO_TIMING_FROM_CAPTURE) { - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - reg &= ~FORMAT_SEL; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - reg |= FORMAT_SEL; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - } -} - -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable) -{ - u32 reg; - - if (enable) { - reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); - reg &= ~VIDEO_MODE_MASK; - reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; - writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); - } else { - reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); - reg &= ~VIDEO_MODE_MASK; - reg |= VIDEO_MODE_SLAVE_MODE; - writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); - } -} - -void exynos_dp_start_video(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); - reg |= VIDEO_EN; - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1); -} - -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); - writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3); - - reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3); - if (!(reg & STRM_VALID)) { - dev_dbg(dp->dev, "Input video stream is not detected.\n"); - return -EINVAL; - } - - return 0; -} - -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1); - reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); - reg |= MASTER_VID_FUNC_EN_N; - writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1); - - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - reg &= ~INTERACE_SCAN_CFG; - reg |= (dp->video_info->interlaced << 2); - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - reg &= ~VSYNC_POLARITY_CFG; - reg |= (dp->video_info->v_sync_polarity << 1); - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - - reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - reg &= ~HSYNC_POLARITY_CFG; - reg |= (dp->video_info->h_sync_polarity << 0); - writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10); - - reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; - writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL); -} - -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - reg &= ~SCRAMBLING_DISABLE; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); -} - -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp) -{ - u32 reg; - - reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); - reg |= SCRAMBLING_DISABLE; - writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET); -} diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h new file mode 100644 index 0000000..8b4ffad --- /dev/null +++ b/include/drm/bridge/analogix_dp.h @@ -0,0 +1,24 @@ +#ifndef _ANALOGIX_DP_H_ +#define _ANALOGIX_DP_H_ + +#include <drm/drm_crtc.h> + +struct analogix_dp_plat_data { + struct drm_panel *panel; + + int (*power_on)(struct analogix_dp_plat_data *); + int (*power_off)(struct analogix_dp_plat_data *); + int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *); + int (*get_modes)(struct analogix_dp_plat_data *, + struct drm_connector *); +}; + +int analogix_dp_resume(struct device *dev); +int analogix_dp_suspend(struct device *dev); + +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, + struct drm_encoder *encoder, + struct analogix_dp_plat_data *plat_data); +void analogix_dp_unbind(struct device *dev, struct device *master, void *data); + +#endif /* _ANALOGIX_DP_H_ */
Both hsync/vsync polarity and interlace mode can be parsed from drm display mode, and dynamic_range and ycbcr_coeff can be judge by the video code.
But presumably Exynos still relaies on the DT properties, so take good use of mode_fixup() in to achieve the compatibility hacks.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 50 ++++++++++++---------- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 65 ++++++++++++++++++++++++++--- 2 files changed, 89 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 6c15e20..480cc13 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -1110,11 +1110,40 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) dp->dpms_mode = DRM_MODE_DPMS_OFF; }
+static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, + struct drm_display_mode *orig_mode, + struct drm_display_mode *mode) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct video_info *video_info = dp->video_info; + int vic; + + /* interlaces & hsync pol & vsync pol */ + video_info->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + video_info->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + video_info->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + + /* dynamic_range & colorimetry */ + vic = drm_match_cea_mode(mode); + if ((vic == 6) || (vic == 7) || (vic == 21) || (vic == 22) || + (vic == 2) || (vic == 3) || (vic == 17) || (vic == 18)) { + video_info->dynamic_range = CEA; + video_info->ycbcr_coeff = COLOR_YCBCR601; + } else if (vic) { + video_info->dynamic_range = CEA; + video_info->ycbcr_coeff = COLOR_YCBCR709; + } else { + video_info->dynamic_range = VESA; + video_info->ycbcr_coeff = COLOR_YCBCR709; + } +} + static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { .enable = analogix_dp_bridge_enable, .disable = analogix_dp_bridge_disable, .pre_enable = analogix_dp_bridge_nop, .post_disable = analogix_dp_bridge_nop, + .mode_set = analogix_dp_bridge_mode_set, .attach = analogix_dp_bridge_attach, };
@@ -1156,33 +1185,12 @@ static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) if (!dp_video_config) return ERR_PTR(-ENOMEM);
- dp_video_config->h_sync_polarity = - of_property_read_bool(dp_node, "hsync-active-high"); - - dp_video_config->v_sync_polarity = - of_property_read_bool(dp_node, "vsync-active-high"); - - dp_video_config->interlaced = - of_property_read_bool(dp_node, "interlaced"); - if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) { dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
- if (of_property_read_u32(dp_node, "analogix,dynamic-range", - &dp_video_config->dynamic_range)) { - dev_err(dev, "failed to get dynamic-range\n"); - return ERR_PTR(-EINVAL); - } - - if (of_property_read_u32(dp_node, "analogix,ycbcr-coeff", - &dp_video_config->ycbcr_coeff)) { - dev_err(dev, "failed to get ycbcr-coeff\n"); - return ERR_PTR(-EINVAL); - } - if (of_property_read_u32(dp_node, "analogix,color-depth", &dp_video_config->color_depth)) { dev_err(dev, "failed to get color-depth\n"); diff --git a/drivers/gpu/drm/exynos/analogix_dp-exynos.c b/drivers/gpu/drm/exynos/analogix_dp-exynos.c index d5631c2..17da2c8 100644 --- a/drivers/gpu/drm/exynos/analogix_dp-exynos.c +++ b/drivers/gpu/drm/exynos/analogix_dp-exynos.c @@ -26,11 +26,17 @@ #include <drm/exynos_drm.h> #include "exynos_drm_drv.h"
-#define plat_data_to_dp(pd) \ - container_of(pd, struct exynos_dp_device, plat_data) +#define to_dp(nm) container_of(nm, struct exynos_dp_device, nm) + +struct video_info { + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; +};
struct exynos_dp_device { struct exynos_drm_display display; + struct video_info video_info; struct drm_bridge *ptn_bridge; struct drm_device *drm_dev; struct device *dev; @@ -42,7 +48,7 @@ struct exynos_dp_device { int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data, bool enable) { - struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct exynos_dp_device *dp = to_dp(plat_data); struct drm_encoder *encoder = dp->display.encoder; struct exynos_drm_crtc *crtc;
@@ -69,7 +75,7 @@ static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data, struct drm_connector *connector) { - struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct exynos_dp_device *dp = to_dp(plat_data); struct drm_display_mode *mode;
if (dp->plat_data.panel) @@ -97,7 +103,7 @@ static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data, static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, struct drm_bridge *bridge) { - struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct exynos_dp_device *dp = to_dp(plat_data); struct drm_encoder *encoder = dp->display.encoder; int ret;
@@ -116,6 +122,34 @@ static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, return 0; }
+static void exynos_dp_mode_fixup(struct exynos_drm_display *display, + struct drm_connector *connector, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct exynos_dp_device *dp = to_dp(display); + int flags = adjusted_mode->flags; + + flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC | + DRM_MODE_FLAG_INTERLACE); + + if (dp->video_info.h_sync_polarity) + flags |= DRM_MODE_FLAG_PHSYNC; + else + flags |= DRM_MODE_FLAG_NHSYNC; + + if (dp->video_info.v_sync_polarity) + flags |= DRM_MODE_FLAG_PVSYNC; + else + flags |= DRM_MODE_FLAG_NVSYNC; + + if (dp->video_info.interlaced) + flags |= DRM_MODE_FLAG_INTERLACE; + + adjusted_mode->flags = flags; +} + static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) { /* do nothing */ @@ -137,6 +171,7 @@ static struct exynos_drm_display_ops exynos_dp_display_ops = { .create_connector = exynos_dp_create_connector, .dpms = exynos_dp_dpms, .commit = exynos_dp_commit, + .mode_fixup = exynos_dp_mode_fixup, };
static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) @@ -153,6 +188,22 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) return 0; }
+static int exynos_dp_dt_parse_video_info(struct exynos_dp_device *dp) +{ + struct device_node *dp_node = dp->dev->of_node; + + dp->video_info.h_sync_polarity = + of_property_read_bool(dp_node, "hsync-active-high"); + + dp->video_info.v_sync_polarity = + of_property_read_bool(dp_node, "vsync-active-high"); + + dp->video_info.interlaced = + of_property_read_bool(dp_node, "interlaced"); + + return 0; +} + static int exynos_dp_bind(struct device *dev, struct device *master, void *data) { struct exynos_dp_device *dp = dev_get_drvdata(dev); @@ -180,6 +231,10 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) return ret; }
+ ret = exynos_dp_dt_parse_video_info(dp); + if (ret) + return ret; + ret = exynos_drm_create_enc_conn(dp->drm_dev, &dp->display); if (ret) { DRM_ERROR("exynos dp create enc_conn failed\n");
link_rate and lane_count already configed in analogix_dp_set_link_train(), so we don't need to config those repeatly after training finished, just remove them out.
Beside Display Port 1.2 already support 5.4Gbps link rate, the maximum sets would change from {1.62Gbps, 2.7Gbps} to {1.62Gbps, 2.7Gbps, 5.4Gbps}.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 16 ++++++++-------- drivers/gpu/drm/bridge/analogix_dp_core.h | 9 +++++---- 2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 480cc13..1778e0a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -635,6 +635,8 @@ static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, /* * For DP rev.1.1, Maximum link rate of Main Link lanes * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps + * For DP rev.1.2, Maximum link rate of Main Link lanes + * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps */ analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); *bandwidth = data; @@ -668,7 +670,8 @@ static void analogix_dp_init_training(struct analogix_dp_device *dp, analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && - (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { + (dp->link_train.link_rate != LINK_RATE_2_70GBPS) && + (dp->link_train.link_rate != LINK_RATE_5_40GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS; @@ -901,8 +904,8 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) return; }
- ret = analogix_dp_set_link_train(dp, dp->video_info->lane_count, - dp->video_info->link_rate); + ret = analogix_dp_set_link_train(dp, dp->video_info->max_lane_count, + dp->video_info->max_link_rate); if (ret) { dev_err(dp->dev, "unable to do link train\n"); return; @@ -912,9 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_rx_to_enhanced_mode(dp, 1); analogix_dp_enable_enhanced_mode(dp, 1);
- analogix_dp_set_lane_count(dp, dp->video_info->lane_count); - analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate); - analogix_dp_init_video(dp); ret = analogix_dp_config_video(dp); if (ret) @@ -1198,13 +1198,13 @@ static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) }
if (of_property_read_u32(dp_node, "analogix,link-rate", - &dp_video_config->link_rate)) { + &dp_video_config->max_link_rate)) { dev_err(dev, "failed to get link-rate\n"); return ERR_PTR(-EINVAL); }
if (of_property_read_u32(dp_node, "analogix,lane-count", - &dp_video_config->lane_count)) { + &dp_video_config->max_lane_count)) { dev_err(dev, "failed to get lane-count\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h index 2cefde9..941b34f 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -21,8 +21,9 @@ #define MAX_EQ_LOOP 5
enum link_rate_type { - LINK_RATE_1_62GBPS = 0x06, - LINK_RATE_2_70GBPS = 0x0a + LINK_RATE_1_62GBPS = DP_LINK_BW_1_62, + LINK_RATE_2_70GBPS = DP_LINK_BW_2_7, + LINK_RATE_5_40GBPS = DP_LINK_BW_5_4, };
enum link_lane_count_type { @@ -128,8 +129,8 @@ struct video_info { enum color_coefficient ycbcr_coeff; enum color_depth color_depth;
- enum link_rate_type link_rate; - enum link_lane_count_type lane_count; + enum link_rate_type max_link_rate; + enum link_lane_count_type max_lane_count; };
struct link_train {
On 2015. 8. 19., at PM 11:50, Yakir Yang ykk@rock-chips.com wrote:
link_rate and lane_count already configed in analogix_dp_set_link_train(),
s/configed/configured
Also, the commit name such as "fix ... bug" is not good. How about following?
drm: bridge/analogix_dp: remove duplicate configuration of link rate and link count
Best regards, Jingoo Han
so we don't need to config those repeatly after training finished, just remove them out.
Beside Display Port 1.2 already support 5.4Gbps link rate, the maximum sets would change from {1.62Gbps, 2.7Gbps} to {1.62Gbps, 2.7Gbps, 5.4Gbps}.
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to
the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 16 ++++++++-------- drivers/gpu/drm/bridge/analogix_dp_core.h | 9 +++++---- 2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 480cc13..1778e0a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -635,6 +635,8 @@ static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, /* * For DP rev.1.1, Maximum link rate of Main Link lanes * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
* For DP rev.1.2, Maximum link rate of Main Link lanes
*/ analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); *bandwidth = data;* 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps
@@ -668,7 +670,8 @@ static void analogix_dp_init_training(struct analogix_dp_device *dp, analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
(dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
(dp->link_train.link_rate != LINK_RATE_2_70GBPS) &&
(dp->link_train.link_rate != LINK_RATE_5_40GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS;
@@ -901,8 +904,8 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) return; }
- ret = analogix_dp_set_link_train(dp, dp->video_info->lane_count,
dp->video_info->link_rate);
- ret = analogix_dp_set_link_train(dp, dp->video_info->max_lane_count,
if (ret) { dev_err(dp->dev, "unable to do link train\n"); return;dp->video_info->max_link_rate);
@@ -912,9 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_rx_to_enhanced_mode(dp, 1); analogix_dp_enable_enhanced_mode(dp, 1);
- analogix_dp_set_lane_count(dp, dp->video_info->lane_count);
- analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
- analogix_dp_init_video(dp); ret = analogix_dp_config_video(dp); if (ret)
@@ -1198,13 +1198,13 @@ static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) }
if (of_property_read_u32(dp_node, "analogix,link-rate",
&dp_video_config->link_rate)) {
&dp_video_config->max_link_rate)) { dev_err(dev, "failed to get link-rate\n"); return ERR_PTR(-EINVAL);
}
if (of_property_read_u32(dp_node, "analogix,lane-count",
&dp_video_config->lane_count)) {
}&dp_video_config->max_lane_count)) { dev_err(dev, "failed to get lane-count\n"); return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h index 2cefde9..941b34f 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -21,8 +21,9 @@ #define MAX_EQ_LOOP 5
enum link_rate_type {
- LINK_RATE_1_62GBPS = 0x06,
- LINK_RATE_2_70GBPS = 0x0a
- LINK_RATE_1_62GBPS = DP_LINK_BW_1_62,
- LINK_RATE_2_70GBPS = DP_LINK_BW_2_7,
- LINK_RATE_5_40GBPS = DP_LINK_BW_5_4,
};
enum link_lane_count_type { @@ -128,8 +129,8 @@ struct video_info { enum color_coefficient ycbcr_coeff; enum color_depth color_depth;
- enum link_rate_type link_rate;
- enum link_lane_count_type lane_count;
- enum link_rate_type max_link_rate;
- enum link_lane_count_type max_lane_count;
};
struct link_train {
1.9.1
Hi Jingoo,
On 08/20/2015 02:22 AM, Jingoo Han wrote:
On 2015. 8. 19., at PM 11:50, Yakir Yang ykk@rock-chips.com wrote:
link_rate and lane_count already configed in analogix_dp_set_link_train(),
s/configed/configured
Also, the commit name such as "fix ... bug" is not good. How about following?
drm: bridge/analogix_dp: remove duplicate configuration of link rate and link count
Thanks, done, it's more readable.
- Yakir
Best regards, Jingoo Han
so we don't need to config those repeatly after training finished, just remove them out.
Beside Display Port 1.2 already support 5.4Gbps link rate, the maximum sets would change from {1.62Gbps, 2.7Gbps} to {1.62Gbps, 2.7Gbps, 5.4Gbps}.
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 16 ++++++++-------- drivers/gpu/drm/bridge/analogix_dp_core.h | 9 +++++---- 2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 480cc13..1778e0a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -635,6 +635,8 @@ static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp, /* * For DP rev.1.1, Maximum link rate of Main Link lanes * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
* For DP rev.1.2, Maximum link rate of Main Link lanes
*/ analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); *bandwidth = data;* 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps
@@ -668,7 +670,8 @@ static void analogix_dp_init_training(struct analogix_dp_device *dp, analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
(dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
(dp->link_train.link_rate != LINK_RATE_2_70GBPS) &&
(dp->link_train.link_rate != LINK_RATE_5_40GBPS)) { dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n", dp->link_train.link_rate); dp->link_train.link_rate = LINK_RATE_1_62GBPS;
@@ -901,8 +904,8 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) return; }
- ret = analogix_dp_set_link_train(dp, dp->video_info->lane_count,
dp->video_info->link_rate);
- ret = analogix_dp_set_link_train(dp, dp->video_info->max_lane_count,
if (ret) { dev_err(dp->dev, "unable to do link train\n"); return;dp->video_info->max_link_rate);
@@ -912,9 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_rx_to_enhanced_mode(dp, 1); analogix_dp_enable_enhanced_mode(dp, 1);
- analogix_dp_set_lane_count(dp, dp->video_info->lane_count);
- analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
- analogix_dp_init_video(dp); ret = analogix_dp_config_video(dp); if (ret)
@@ -1198,13 +1198,13 @@ static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) }
if (of_property_read_u32(dp_node, "analogix,link-rate",
&dp_video_config->link_rate)) {
&dp_video_config->max_link_rate)) { dev_err(dev, "failed to get link-rate\n"); return ERR_PTR(-EINVAL);
}
if (of_property_read_u32(dp_node, "analogix,lane-count",
&dp_video_config->lane_count)) {
}&dp_video_config->max_lane_count)) { dev_err(dev, "failed to get lane-count\n"); return ERR_PTR(-EINVAL);
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h index 2cefde9..941b34f 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -21,8 +21,9 @@ #define MAX_EQ_LOOP 5
enum link_rate_type {
- LINK_RATE_1_62GBPS = 0x06,
- LINK_RATE_2_70GBPS = 0x0a
- LINK_RATE_1_62GBPS = DP_LINK_BW_1_62,
- LINK_RATE_2_70GBPS = DP_LINK_BW_2_7,
- LINK_RATE_5_40GBPS = DP_LINK_BW_5_4,
};
enum link_lane_count_type { @@ -128,8 +129,8 @@ struct video_info { enum color_coefficient ycbcr_coeff; enum color_depth color_depth;
- enum link_rate_type link_rate;
- enum link_lane_count_type lane_count;
- enum link_rate_type max_link_rate;
- enum link_lane_count_type max_lane_count;
};
struct link_train {
1.9.1
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Heiko suggest, add devicetree binding documents. - Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding. - Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings + +Required properties for dp-controller: + -compatible: + platform specific such as: + * "samsung,exynos5-dp" + * "rockchip,rk3288-dp" + -reg: + physical base address of the controller and length + of memory mapped region. + -interrupts: + interrupt combiner values. + -clocks: + from common clock binding: handle to dp clock. + -clock-names: + from common clock binding: Shall be "dp". + -interrupt-parent: + phandle to Interrupt combiner node. + -phys: + from general PHY binding: the phandle for the PHY device. + -phy-names: + from general PHY binding: Should be "dp". + -analogix,color-space: + input video data format. + COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2 + -analogix,color-depth: + number of bits per colour component. + COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3 + -analogix,link-rate: + max link rate supported by the eDP controller. + LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A, + LINK_RATE_5_40GBPS = 0x14 + -analogix,lane-count: + max number of lanes supported by the eDP contoller. + LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 + -port@[X]: SoC specific port nodes with endpoint definitions as defined + in Documentation/devicetree/bindings/media/video-interfaces.txt, + please refer to the SoC specific binding document: + * Documentation/devicetree/bindings/video/exynos_dp.txt + * Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt + +Optional properties for dp-controller: + -analogix,hpd-gpio: + Hotplug detect GPIO. + Indicates which GPIO should be used for hotplug + detection + -video interfaces: Device node can contain video interface port + nodes according to [1]. + +[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +------------------------------------------------------------------------------- + +Example: + + dp-controller { + compatible = "samsung,exynos5-dp"; + reg = <0x145b0000 0x10000>; + interrupts = <10 3>; + interrupt-parent = <&combiner>; + clocks = <&clock 342>; + clock-names = "dp"; + + phys = <&dp_phy>; + phy-names = "dp"; + + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>; + }; diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp". - -samsung,color-space: - input video data format. - COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2 - -samsung,dynamic-range: - dynamic range for input video data. - VESA = 0, CEA = 1 - -samsung,ycbcr-coeff: - YCbCr co-efficients for input video. - COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1 - -samsung,color-depth: - number of bits per colour component. - COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3 - -samsung,link-rate: - link rate supported by the panel. - LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A - -samsung,lane-count: - number of lanes supported by the panel. - LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4 - - display-timings: timings for the connected panel as described by - Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller: + - display-timings: timings for the connected panel as described by + Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined @@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined - -samsung,hpd-gpio: - Hotplug detect GPIO. - Indicates which GPIO should be used for hotplug - detection - -video interfaces: Device node can contain video interface port - nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document: + * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt + -phys (required) + -phy-names (required) + -analogix,color-space (required) + -analogix,color-depth (required) + -analogix,link-rate (required) + -analogix,lane-count (required) + -analogix,hpd-gpio (optional) + -video interfaces (optional) +-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller { - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <4>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>;
display-timings { native-mode = <&lcd_timing>; diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay"; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <4>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>; };
&fimd { diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp { - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <4>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>;
pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>; diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <2>; - samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <2>; + analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
ports { port@0 { diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <1>; - samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <1>; + analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>; };
&ehci { diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x06>; - samsung,lane-count = <2>; - samsung,hpd-gpio = <&gpx2 6 0>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x06>; + analogix,lane-count = <2>; + analogix,hpd-gpio = <&gpx2 6 0>;
ports { port@0 { diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <4>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>; status = "okay"; };
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>; - samsung,color-space = <0>; - samsung,dynamic-range = <0>; - samsung,ycbcr-coeff = <0>; - samsung,color-depth = <1>; - samsung,link-rate = <0x0a>; - samsung,lane-count = <2>; - samsung,hpd-gpio = <&gpx2 6 0>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <2>; + analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>; };
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd { diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci { diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
};
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers. Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please: 1. Provide backward compatibility. Mark old properties as deprecated but still support them. 2. Separate all DTS changes to a separate patch, unless bisectability would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability. 3. Use proper subject for the patch changing DTS. This is not documentation change! 4. Please use script get_maintainers to obtain list of valid maintainers and CC-them with at least cover letter and patches requiring their attention.
Best regards, Krzysztof
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd { diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci { diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
};
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag. Let me show same examples, make me understand your suggest rightly.
1. "samsung,ycbcr-coeff" is abandoned in latest analogix-dp driver, absolutely I should not carry this to analogix-dp.txt document. But I should keep this in exynos-dp.txt document, and mark them with an little "deprecated" flag.
[Documentation/devicetree/bindings/video/exynos_dp.txt] Required properties for dp-controller: [...] -samsung,ycbcr-coeff (DEPRECATED): YCbCr co-efficients for input video. COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
Is it right ?
- Separate all DTS changes to a separate patch, unless bisectability
would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability.
So I should separate this patch into two parts, one is name "Document:", the other is "ARM: dts: ".
Honestly, I don't understand what the "bisectability" means in this case.
- Use proper subject for the patch changing DTS. This is not
documentation change!
Hmm... when I separate this patch into two parts, I though I can keep "Documentation" proper subject in this patch, and the other is the "ARM: dts" proper subject. Am I right ?
- Please use script get_maintainers to obtain list of valid
maintainers and CC-them with at least cover letter and patches requiring their attention.
Yeah, thanks.
Thanks a lot, - Yakir
Best regards, Krzysztof
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd {
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci {
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
};analogix,lane-count = <4>; status = "okay";
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
};analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
- if (of_property_read_u32(dp_node, "samsung,color-space", + if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Let me show same examples, make me understand your suggest rightly.
exynos-dp already contains deprecated properties. Other ways of doing this would be: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt Documentation/devicetree/bindings/rtc/s3c-rtc.txt
It depends up to you. The "touchscreen" looks good because it organizes old properties in a common section. In case of exynos-dp.txt you can add at beginning of file information about new bindings and mark everything deprecated.
- "samsung,ycbcr-coeff" is abandoned in latest analogix-dp driver,
absolutely I should not carry this to analogix-dp.txt document. But I should keep this in exynos-dp.txt document, and mark them with an little "deprecated" flag.
[Documentation/devicetree/bindings/video/exynos_dp.txt] Required properties for dp-controller: [...] -samsung,ycbcr-coeff (DEPRECATED): YCbCr co-efficients for input video. COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
Is it right ?
Yes, this is right.
- Separate all DTS changes to a separate patch, unless bisectability
would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability.
So I should separate this patch into two parts, one is name "Document:", the other is "ARM: dts: ".
Yes.
Honestly, I don't understand what the "bisectability" means in this case.
I was referring to bisectability in general. The patchset should be fully bisectable which means that it does not introduce any issues during "git bisect". This effectively means that at each intermediate step (after applying each patch, one by one) every existing stuff works the same as previously without any regression. Including booting with old DTB.
- Use proper subject for the patch changing DTS. This is not
documentation change!
Hmm... when I separate this patch into two parts, I though I can keep "Documentation" proper subject in this patch, and the other is the "ARM: dts" proper subject. Am I right ?
Yes, you're right.
- Please use script get_maintainers to obtain list of valid
maintainers and CC-them with at least cover letter and patches requiring their attention.
Yeah, thanks.
Sure. Now I found older versions of the patchset but previously there were no changes to the bindings. Again the prefix in subject is important to easily filter out and find necessary emails.
BTW, I like the patchset because I like in general works which merge code and reduce duplicate stuff.
Best regards, Krzysztof
Hi Krzysztof,
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop. If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
But from your follow suggest, I think you agree to update driver code, and just mark old prop with deprecated flag. If so I think such code would not be wrong
- if (of_property_read_u32(dp_node, "samsung,color-space", + if (of_property_read_u32(dp_node, "analogix,color-space",
And actually @Rob have suggest me to remove the prefix, just use "color-space" here.
Let me show same examples, make me understand your suggest rightly.
exynos-dp already contains deprecated properties. Other ways of doing this would be: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt Documentation/devicetree/bindings/rtc/s3c-rtc.txt
It depends up to you. The "touchscreen" looks good because it organizes old properties in a common section. In case of exynos-dp.txt you can add at beginning of file information about new bindings and mark everything deprecated.
Whoops, thanks for your remind, I prefer the "touchscreen" style.
- "samsung,ycbcr-coeff" is abandoned in latest analogix-dp driver,
absolutely I should not carry this to analogix-dp.txt document. But I should keep this in exynos-dp.txt document, and mark them with an little "deprecated" flag.
[Documentation/devicetree/bindings/video/exynos_dp.txt] Required properties for dp-controller: [...] -samsung,ycbcr-coeff (DEPRECATED): YCbCr co-efficients for input video. COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
Is it right ?
Yes, this is right.
- Separate all DTS changes to a separate patch, unless bisectability
would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability.
So I should separate this patch into two parts, one is name "Document:", the other is "ARM: dts: ".
Yes.
Honestly, I don't understand what the "bisectability" means in this case.
I was referring to bisectability in general. The patchset should be fully bisectable which means that it does not introduce any issues during "git bisect". This effectively means that at each intermediate step (after applying each patch, one by one) every existing stuff works the same as previously without any regression. Including booting with old DTB.
Oh, thanks for your careful explain, so I guess your first comment is talking about the "bisectability" that if I only apply the 01 - 05 patches, kernel could not bootup normally, cause driver need "analogix,color-space" but DTB only have "samsung,color-space".
- Use proper subject for the patch changing DTS. This is not
documentation change!
Hmm... when I separate this patch into two parts, I though I can keep "Documentation" proper subject in this patch, and the other is the "ARM: dts" proper subject. Am I right ?
Yes, you're right.
- Please use script get_maintainers to obtain list of valid
maintainers and CC-them with at least cover letter and patches requiring their attention.
Yeah, thanks.
Sure. Now I found older versions of the patchset but previously there were no changes to the bindings. Again the prefix in subject is important to easily filter out and find necessary emails.
BTW, I like the patchset because I like in general works which merge code and reduce duplicate stuff.
Aha, thanks :-D
Best regards, - Yakir
Best regards, Krzysztof
Hi Yakir,
Am Montag, 24. August 2015, 20:48:01 schrieb Yakir Yang:
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop. If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
But from your follow suggest, I think you agree to update driver code, and just mark old prop with deprecated flag. If so I think such code would not be wrong
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
In a generic driver, the property should have either none, or the analogix prefix. But DT-properties need to be backwards compatible, meaning an older Exynos devicetree should run unmodified with a newer kernel.
So the common course of action is to mark the old one as deprecated but still test for both, so something like:
if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) if (of_property_read_u32(dp_node, "samsung,color-space", &dp_video_config->color_space)) {
dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
Hi Heiko,
在 2015/8/24 21:03, Heiko Stuebner 写道:
Hi Yakir,
Am Montag, 24. August 2015, 20:48:01 schrieb Yakir Yang:
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote: > Analogix dp driver is split from exynos dp driver, so we just > make an copy of exynos_dp.txt, and then simplify exynos_dp.txt > > Beside update some exynos dtsi file with the latest change > according to the devicetree binding documents. You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop. If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
But from your follow suggest, I think you agree to update driver code, and just mark old prop with deprecated flag. If so I think such code would not be wrong
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
In a generic driver, the property should have either none, or the analogix prefix. But DT-properties need to be backwards compatible, meaning an older Exynos devicetree should run unmodified with a newer kernel.
So the common course of action is to mark the old one as deprecated but still test for both, so something like:
if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) if (of_property_read_u32(dp_node, "samsung,color-space", &dp_video_config->color_space)) { dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
Wow, thanks a lot for your explain and code, it do help me to understand this suggest rightly :-)
Thanks, - Yakir
On 24.08.2015 21:48, Yakir Yang wrote:
Hi Krzysztof,
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop.
Right, the focus is on the driver.
If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
If you are replacing a binding/property then it should be marked deprecated. This means that the old property is still working but new users of it should not be added.
But from your follow suggest, I think you agree to update driver code, and just mark old prop with deprecated flag. If so I think such code would not be wrong
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
It looks wrong because it breaks backward compatibility with existing DTB. As I said before:
- Provide backward compatibility. Mark old properties
as deprecated but still support them.
And actually @Rob have suggest me to remove the prefix, just use "color-space" here.
For new bindings I don't mind. But please remember about existing users, existing DTB and bisectability.
Let me show same examples, make me understand your suggest rightly.
exynos-dp already contains deprecated properties. Other ways of doing this would be: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt Documentation/devicetree/bindings/rtc/s3c-rtc.txt
It depends up to you. The "touchscreen" looks good because it organizes old properties in a common section. In case of exynos-dp.txt you can add at beginning of file information about new bindings and mark everything deprecated.
Whoops, thanks for your remind, I prefer the "touchscreen" style.
- "samsung,ycbcr-coeff" is abandoned in latest analogix-dp driver,
absolutely I should not carry this to analogix-dp.txt document. But I should keep this in exynos-dp.txt document, and mark them with an little "deprecated" flag.
[Documentation/devicetree/bindings/video/exynos_dp.txt] Required properties for dp-controller: [...] -samsung,ycbcr-coeff (DEPRECATED): YCbCr co-efficients for input video. COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
Is it right ?
Yes, this is right.
- Separate all DTS changes to a separate patch, unless bisectability
would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability.
So I should separate this patch into two parts, one is name "Document:", the other is "ARM: dts: ".
Yes.
Honestly, I don't understand what the "bisectability" means in this case.
I was referring to bisectability in general. The patchset should be fully bisectable which means that it does not introduce any issues during "git bisect". This effectively means that at each intermediate step (after applying each patch, one by one) every existing stuff works the same as previously without any regression. Including booting with old DTB.
Oh, thanks for your careful explain, so I guess your first comment is talking about the "bisectability" that if I only apply the 01 - 05 patches, kernel could not bootup normally, cause driver need "analogix,color-space" but DTB only have "samsung,color-space".
Right. In the same time please remember that kernel may be booted with old DTB.
Best regards, Krzysztof
Hi Krzysztof,
在 2015/8/25 7:49, Krzysztof Kozlowski 写道:
On 24.08.2015 21:48, Yakir Yang wrote:
Hi Krzysztof,
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote: > Analogix dp driver is split from exynos dp driver, so we just > make an copy of exynos_dp.txt, and then simplify exynos_dp.txt > > Beside update some exynos dtsi file with the latest change > according to the devicetree binding documents. You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop.
Right, the focus is on the driver.
If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
If you are replacing a binding/property then it should be marked deprecated. This means that the old property is still working but new users of it should not be added.
Okay, so just quote Heiko's reply, such code would be need in analogix dp driver.
if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) if (of_property_read_u32(dp_node, "samsung,color-space", &dp_video_config->color_space)) {
dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
But from your follow suggest, I think you agree to update driver code, and just mark old prop with deprecated flag. If so I think such code would not be wrong
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
It looks wrong because it breaks backward compatibility with existing DTB. As I said before:
- Provide backward compatibility. Mark old properties
as deprecated but still support them.
And actually @Rob have suggest me to remove the prefix, just use "color-space" here.
For new bindings I don't mind. But please remember about existing users, existing DTB and bisectability.
Let me show same examples, make me understand your suggest rightly.
exynos-dp already contains deprecated properties. Other ways of doing this would be: Documentation/devicetree/bindings/input/touchscreen/touchscreen.txt Documentation/devicetree/bindings/rtc/s3c-rtc.txt
It depends up to you. The "touchscreen" looks good because it organizes old properties in a common section. In case of exynos-dp.txt you can add at beginning of file information about new bindings and mark everything deprecated.
Whoops, thanks for your remind, I prefer the "touchscreen" style.
- "samsung,ycbcr-coeff" is abandoned in latest analogix-dp driver,
absolutely I should not carry this to analogix-dp.txt document. But I should keep this in exynos-dp.txt document, and mark them with an little "deprecated" flag.
[Documentation/devicetree/bindings/video/exynos_dp.txt] Required properties for dp-controller: [...] -samsung,ycbcr-coeff (DEPRECATED): YCbCr co-efficients for input video. COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
Is it right ?
Yes, this is right.
- Separate all DTS changes to a separate patch, unless bisectability
would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability.
So I should separate this patch into two parts, one is name "Document:", the other is "ARM: dts: ".
Yes.
Honestly, I don't understand what the "bisectability" means in this case.
I was referring to bisectability in general. The patchset should be fully bisectable which means that it does not introduce any issues during "git bisect". This effectively means that at each intermediate step (after applying each patch, one by one) every existing stuff works the same as previously without any regression. Including booting with old DTB.
Oh, thanks for your careful explain, so I guess your first comment is talking about the "bisectability" that if I only apply the 01 - 05 patches, kernel could not bootup normally, cause driver need "analogix,color-space" but DTB only have "samsung,color-space".
Right. In the same time please remember that kernel may be booted with old DTB.
Okay, thanks a lot ;)
- Yakir
Best regards, Krzysztof
On 25.08.2015 10:33, Yakir Yang wrote:
Hi Krzysztof,
在 2015/8/25 7:49, Krzysztof Kozlowski 写道:
On 24.08.2015 21:48, Yakir Yang wrote:
Hi Krzysztof,
在 08/24/2015 12:20 PM, Krzysztof Kozlowski 写道:
On 24.08.2015 11:42, Yakir Yang wrote:
Hi Krzysztof,
在 08/23/2015 07:43 PM, Krzysztof Kozlowski 写道:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com: > On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com > wrote: >> Analogix dp driver is split from exynos dp driver, so we just >> make an copy of exynos_dp.txt, and then simplify exynos_dp.txt >> >> Beside update some exynos dtsi file with the latest change >> according to the devicetree binding documents. > You can't just change the exynos bindings and break > compatibility. Is > there some agreement with exynos folks to do this? No, there is no agreement. This wasn't even sent to Exynos maintainers.
Sorry about this one, actually I have add Exynos maintainers in version 1 & version 2, but lose some maintainers in version 3, I would fix it in bellow versions.
Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them.
Do you mean that I should keep the old properties declare in exynos-dp.txt, but just mark them as deprecated flag.
That is one of ways how to do this. However more important is that driver should still support old bindings so such code:
if (of_property_read_u32(dp_node, "samsung,color-space",
if (of_property_read_u32(dp_node, "analogix,color-space",
is probably wrong. Will the driver support old DTB in the same way as it was supporting before the change?
Okay, I got your means. So document is not the focus, the most important is that driver should support the old dts prop.
Right, the focus is on the driver.
If so the new analogix dp driver should keep the "samsung,color-space", rather then just mark it with [DEPRECATED] flag.
If you are replacing a binding/property then it should be marked deprecated. This means that the old property is still working but new users of it should not be added.
Okay, so just quote Heiko's reply, such code would be need in analogix dp driver.
if (of_property_read_u32(dp_node, "analogix,color-space", &dp_video_config->color_space)) if (of_property_read_u32(dp_node, "samsung,color-space", &dp_video_config->color_space)) { dev_err(dev, "failed to get color-space\n"); return ERR_PTR(-EINVAL); }
Yes. It does not look pretty but something like this is needed.
Best regards, Krzysztof
On 2015. 8. 24., at AM 9:43, Krzysztof Kozlowski k.kozlowski@samsung.com wrote:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote: Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers. Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them. 2. Separate all DTS changes to a separate patch, unless bisectability would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability. 3. Use proper subject for the patch changing DTS. This is not documentation change! 4. Please use script get_maintainers to obtain list of valid maintainers and CC-them with at least cover letter and patches requiring their attention.
To Yakir Yang,
Please be careful when you CC people.
I don't find the reason why you CC'ed the following people. Of course, they look to be one of the talented developers. However, they look to be unrelated to your patchset.
Takashi Iwai Vincent Palatin Fabio Estevam Philipp Zabel
Also, please add Exynos Architecture maintainers to CC list. I don't understand why you removed them from CC list. Kukjin Kim Krzysztof Kozlowski
Without their Ack, you will not change the codes of ARM Exynos Architecture.
Best regards, Jingoo Han
Best regards, Krzysztof
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies
from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd { diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci { diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
};
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hi Jingoo,
在 08/24/2015 03:40 PM, Jingoo Han 写道:
On 2015. 8. 24., at AM 9:43, Krzysztof Kozlowski k.kozlowski@samsung.com wrote:
2015-08-24 8:23 GMT+09:00 Rob Herring robherring2@gmail.com:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote: Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
No, there is no agreement. This wasn't even sent to Exynos maintainers. Additionally the patchset did not look interesting to me because of misleading subject - Documentation instead of "ARM: dts:".
Yakir, please:
- Provide backward compatibility. Mark old properties as deprecated
but still support them. 2. Separate all DTS changes to a separate patch, unless bisectability would be hurt. Anyway you should prepare it in a such way that separation would be possible without breaking bisectability. 3. Use proper subject for the patch changing DTS. This is not documentation change! 4. Please use script get_maintainers to obtain list of valid maintainers and CC-them with at least cover letter and patches requiring their attention.
To Yakir Yang,
Please be careful when you CC people.
I don't find the reason why you CC'ed the following people. Of course, they look to be one of the talented developers. However, they look to be unrelated to your patchset.
Takashi Iwai Vincent Palatin Fabio Estevam Philipp Zabel
Yeah, actually I just got those people from patman tools. Thanks for your remind, I would pay more attention in next version :-)
Also, please add Exynos Architecture maintainers to CC list. I don't understand why you removed them from CC list. Kukjin Kim Krzysztof Kozlowski
Without their Ack, you will not change the codes of ARM Exynos Architecture.
Wow, thanks a lot, it's a serious mistaken ;)
Thanks, - Yakir
Best regards, Jingoo Han
Best regards, Krzysztof
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd { diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci { diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; status = "okay";
};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
};
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Hi Rob,
在 08/23/2015 06:23 PM, Rob Herring 写道:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
Analogix dp driver is split from exynos dp driver, so we just make an copy of exynos_dp.txt, and then simplify exynos_dp.txt
Beside update some exynos dtsi file with the latest change according to the devicetree binding documents.
You can't just change the exynos bindings and break compatibility. Is there some agreement with exynos folks to do this?
Yeah, this change only start to introduce in version 3 series, so there is no agreement or discuss before.
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 70 ++++++++++++++++++++++ .../devicetree/bindings/video/exynos_dp.txt | 50 ++++++---------- arch/arm/boot/dts/exynos5250-arndale.dts | 10 ++-- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 ++-- arch/arm/boot/dts/exynos5250-snow.dts | 12 ++-- arch/arm/boot/dts/exynos5250-spring.dts | 12 ++-- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 ++-- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 ++-- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 ++-- 9 files changed, 119 insertions(+), 79 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt new file mode 100644 index 0000000..6127018 --- /dev/null +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -0,0 +1,70 @@ +Analogix Display Port bridge bindings
+Required properties for dp-controller:
-compatible:
platform specific such as:
* "samsung,exynos5-dp"
* "rockchip,rk3288-dp"
-reg:
physical base address of the controller and length
of memory mapped region.
-interrupts:
interrupt combiner values.
-clocks:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-phys:
from general PHY binding: the phandle for the PHY device.
-phy-names:
from general PHY binding: Should be "dp".
-analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Okay, thanks
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
Like "link-rate-mbps = 162000", so I need of_property_read_u32() for this prop.
Okay, done.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
Done
-port@[X]: SoC specific port nodes with endpoint definitions as defined
in Documentation/devicetree/bindings/media/video-interfaces.txt,
please refer to the SoC specific binding document:
* Documentation/devicetree/bindings/video/exynos_dp.txt
* Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
Hmm... I don't understand how the HDMI connector binding works, there are no driver that name with "hdmi-connector" compatible, does it just an sample case for all HDMI dts node?
But I'm okay with your suggest here, change "analogix,hpd-gpio" to "hpd-gpios" ;)
-video interfaces: Device node can contain video interface port
nodes according to [1].
Isn't this the same as ports above? How are they optional? 0 ports would be pretty useless.
I though I make an mistaken here, "-video interfaces" is the same as previous "ports".
And "ports" is an required property in rockchip case, cause we use it to bind "dp" driver to crtc "vop" driver. But I thinks "ports" in not an required property in exynos case, they only use when there are a dp/lvds application scenarios.
Here are example (./arch/arm/boot/dts/exynos5420-peach-pit.dts): &dp { [...] ports { port@0 { dp_out: endpoint { remote-endpoint = <&bridge_in>; }; }; }; };
ps8625: lvds-bridge@48 { [...] ports { port@0 { bridge_out: endpoint { remote-endpoint = <&panel_in>; }; };
port@1 { bridge_in: endpoint { remote-endpoint = <&dp_out>; }; }; };
};
So I would rather to remove "ports" to analogix_dp-rockchip.txt with "required" flag, and keep "video-port" in analogox-dp.txt with "optional" flag.
+[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +-------------------------------------------------------------------------------
+Example:
dp-controller {
compatible = "samsung,exynos5-dp";
reg = <0x145b0000 0x10000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 7a3a9cd..177506f 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -31,28 +31,10 @@ Required properties for dp-controller: from general PHY binding: the phandle for the PHY device. -phy-names: from general PHY binding: Should be "dp".
-samsung,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
-samsung,dynamic-range:
dynamic range for input video data.
VESA = 0, CEA = 1
-samsung,ycbcr-coeff:
YCbCr co-efficients for input video.
COLOR_YCBCR601 = 0, COLOR_YCBCR709 = 1
-samsung,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
-samsung,link-rate:
link rate supported by the panel.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A
-samsung,lane-count:
number of lanes supported by the panel.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt
Optional properties for dp-controller:
- display-timings: timings for the connected panel as described by
Documentation/devicetree/bindings/video/display-timing.txt -interlaced: interlace scan mode. Progressive if defined, Interlaced if not defined
@@ -62,14 +44,18 @@ Optional properties for dp-controller: -hsync-active-high: HSYNC polarity configuration. High if defined, Low if not defined
-samsung,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
-video interfaces: Device node can contain video interface port
nodes according to [1].
-[1]: Documentation/devicetree/bindings/media/video-interfaces.txt +For the below properties, please refer to Analogix DP binding document:
- Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt
-phys (required)
-phy-names (required)
-analogix,color-space (required)
-analogix,color-depth (required)
-analogix,link-rate (required)
-analogix,lane-count (required)
-analogix,hpd-gpio (optional)
-video interfaces (optional)
+-------------------------------------------------------------------------------
Example:
@@ -88,12 +74,10 @@ SOC specific portion:
Board Specific portion: dp-controller {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; display-timings { native-mode = <&lcd_timing>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts index 7e728a1..e48798d 100644 --- a/arch/arm/boot/dts/exynos5250-arndale.dts +++ b/arch/arm/boot/dts/exynos5250-arndale.dts @@ -119,12 +119,10 @@
&dp { status = "okay";
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>;
};
&fimd {
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts index 4fe186d..b8c6b8b 100644 --- a/arch/arm/boot/dts/exynos5250-smdk5250.dts +++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts @@ -75,12 +75,10 @@ };
&dp {
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <4>; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
diff --git a/arch/arm/boot/dts/exynos5250-snow.dts b/arch/arm/boot/dts/exynos5250-snow.dts index b7f4122..9ce2b89 100644 --- a/arch/arm/boot/dts/exynos5250-snow.dts +++ b/arch/arm/boot/dts/exynos5250-snow.dts @@ -239,13 +239,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx0 7 GPIO_ACTIVE_HIGH>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index d03f9b8..9288ae6 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -69,13 +69,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <1>;
samsung,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <1>;
analogix,hpd-gpio = <&gpc3 0 GPIO_ACTIVE_HIGH>;
};
&ehci {
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts index 8f4d76c..695a380 100644 --- a/arch/arm/boot/dts/exynos5420-peach-pit.dts +++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts @@ -147,13 +147,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x06>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x06>;
analogix,lane-count = <2>;
analogix,hpd-gpio = <&gpx2 6 0>; ports { port@0 {
diff --git a/arch/arm/boot/dts/exynos5420-smdk5420.dts b/arch/arm/boot/dts/exynos5420-smdk5420.dts index 98871f9..fd46714 100644 --- a/arch/arm/boot/dts/exynos5420-smdk5420.dts +++ b/arch/arm/boot/dts/exynos5420-smdk5420.dts @@ -91,12 +91,10 @@ &dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hpd>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <4>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
};analogix,lane-count = <4>; status = "okay";
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts index 7d5b386..54b4c63 100644 --- a/arch/arm/boot/dts/exynos5800-peach-pi.dts +++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts @@ -141,13 +141,11 @@ status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hpd_gpio>;
samsung,color-space = <0>;
samsung,dynamic-range = <0>;
samsung,ycbcr-coeff = <0>;
samsung,color-depth = <1>;
samsung,link-rate = <0x0a>;
samsung,lane-count = <2>;
samsung,hpd-gpio = <&gpx2 6 0>;
analogix,color-space = <0>;
analogix,color-depth = <1>;
analogix,link-rate = <0x0a>;
analogix,lane-count = <2>;
};analogix,hpd-gpio = <&gpx2 6 0>; panel = <&panel>;
-- 1.9.1
linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
I'm not surprised one iota that DRM bindings are a mess. There's no one overlooking the adoption of DRM bindings, so surprise surprise, everyone does their own thing. This is exactly what happens every time in that scenario. It's not a new problem.
When we adopted the graph bindings for iMX DRM, I thought exactly at that time "it would be nice if this could become the standard for binding DRM components together" but I don't have the authority from either the DT perspective or the DRM perspective to mandate that. Neither does anyone else. That's the _real_ problem here.
I've seen several DRM bindings go by which don't use the of-graph stuff, which means that they'll never be compatible with generic components which do use the of-graph stuff.
Like you say, it's a mess, but it's a mess of our own making, because no one has the authority to regulate this.
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
+Optional properties for dp-controller:
-analogix,hpd-gpio:
Hotplug detect GPIO.
Indicates which GPIO should be used for hotplug
detection
We should align with "hpd-gpios" used by HDMI connector binding. Or do we need a DP connector binding that this should be defined in? Probably so.
The DRM related bindings are such a cluster f*ck with everyone picking their own way to do things. Just grep hpd in bindings for starters. That is just the tip.
I'm not surprised one iota that DRM bindings are a mess. There's no one overlooking the adoption of DRM bindings, so surprise surprise, everyone does their own thing. This is exactly what happens every time in that scenario. It's not a new problem.
True.
When we adopted the graph bindings for iMX DRM, I thought exactly at that time "it would be nice if this could become the standard for binding DRM components together" but I don't have the authority from either the DT perspective or the DRM perspective to mandate that. Neither does anyone else. That's the _real_ problem here.
I've seen several DRM bindings go by which don't use the of-graph stuff, which means that they'll never be compatible with generic components which do use the of-graph stuff.
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
Like you say, it's a mess, but it's a mess of our own making, because no one has the authority to regulate this.
Certainly, and I will take some blame here. We deferred a lot of binding review to subsystem maintainers with the directive to ask for help when needed. The latter has not happened. We need to improve the situation here before we end up with a bigger mess. The momentum to use DRM on Android is growing, so the problem is only going to get worse if we do nothing.
Rob
Am Montag, 24. August 2015, 09:48:27 schrieb Rob Herring:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux
When we adopted the graph bindings for iMX DRM, I thought exactly at that time "it would be nice if this could become the standard for binding DRM components together" but I don't have the authority from either the DT perspective or the DRM perspective to mandate that. Neither does anyone else. That's the _real_ problem here.
I've seen several DRM bindings go by which don't use the of-graph stuff, which means that they'll never be compatible with generic components which do use the of-graph stuff.
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
but that is then simply implementation specific. Panels and bridges can very well be part of and created from an of_graph description without needing to be a (linux-)component - see patch 7.
在 2015/8/24 22:48, Rob Herring 写道:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
Actually this "color-bpp" should come from crtc driver, maybe should come from "struct drm_crtc {".
Like rockchip stuffs, analogix_dp-rockchip call an mode_config from rockchip_drm_vop driver and set output mode to RGB[10:10:10], then vop driver just store the output mode type to the private struct "vop->connecot_out_mode". do think that this outmode should store into crtc, not just come from DT prop.
- Yakir
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
There should be no need to have this in DT at all. The BPC is a property of the attached panel and it should come from the panel (either the panel driver or parsed from EDID if available).
When we adopted the graph bindings for iMX DRM, I thought exactly at that time "it would be nice if this could become the standard for binding DRM components together" but I don't have the authority from either the DT perspective or the DRM perspective to mandate that. Neither does anyone else. That's the _real_ problem here.
I've seen several DRM bindings go by which don't use the of-graph stuff, which means that they'll never be compatible with generic components which do use the of-graph stuff.
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
I certainly support unification, but it needs to be reasonable. There are cases where a different structure for the binding work better than another and I think this always needs to be evaluated on a case by case basis.
Because of that I think it makes sense to make all these framework bits opt-in, otherwise we could easily end up in a situation where drivers have to be rearchitected (or even DT bindings altered!) in order to be able to reuse code.
Thierry
On Tue, Aug 25, 2015 at 11:12:48AM +0200, Thierry Reding wrote:
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
I certainly support unification, but it needs to be reasonable. There are cases where a different structure for the binding work better than another and I think this always needs to be evaluated on a case by case basis.
It can't be a case-by-case basis.
The TDA998x encoder/connector is going to be component only. This is a generic chip, which can be attached to the output of any parallel RGB+sync+clock bus. In other words, it could appear anywhere.
Are you really saying that we need to support multiple schemes of attaching the driver to DRM? That's totally insane IMHO.
The problem with the drm_encoder_slave stuff is that you can't sanely attach of-nodes to the drm-created i2c device. Yes, you can parse them from the DT file as a sub-node of the upper device, but that then goes against the principle of the I2C bindings, which is to list the I2C devices as a child below the I2C adapter node. If you try and put the DT node there, then the OF code will create the I2C device for you, and the drm_encoder_slave stuff won't have the control it needs to communicate through the wrapped i2c_driver stuff.
So, tda998x is going component-only, as that's the _only_ sane solution for it.
Now, what happens when some other DRM driver wants to use the tda998x driver, and its bindings are not compatible with the component helpers? They're pretty much stuck up the creek without a paddle.
Case by case doesn't work unless you're talking about truely isolated hardware where no one shares anything.
On Tue, Aug 25, 2015 at 10:29:39AM +0100, Russell King - ARM Linux wrote:
On Tue, Aug 25, 2015 at 11:12:48AM +0200, Thierry Reding wrote:
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
I certainly support unification, but it needs to be reasonable. There are cases where a different structure for the binding work better than another and I think this always needs to be evaluated on a case by case basis.
It can't be a case-by-case basis.
The TDA998x encoder/connector is going to be component only. This is a generic chip, which can be attached to the output of any parallel RGB+sync+clock bus. In other words, it could appear anywhere.
Are you really saying that we need to support multiple schemes of attaching the driver to DRM? That's totally insane IMHO.
No, what I'm saying is that we should have a single scheme, but one that doesn't put any restrictions on what kind of DT binding you use or how your driver is architected.
The problem with the drm_encoder_slave stuff is that you can't sanely attach of-nodes to the drm-created i2c device. Yes, you can parse them from the DT file as a sub-node of the upper device, but that then goes against the principle of the I2C bindings, which is to list the I2C devices as a child below the I2C adapter node. If you try and put the DT node there, then the OF code will create the I2C device for you, and the drm_encoder_slave stuff won't have the control it needs to communicate through the wrapped i2c_driver stuff.
So, tda998x is going component-only, as that's the _only_ sane solution for it.
Has anyone ever considered turning it into a DRM bridge driver? I had always envisioned component/master to be primarily useful to glue together various SoC components to form one componentized device. Now if tda998x is an I2C slave it is external to the SoC (auxiliary), so in my opinion much better off as a bridge driver.
Bridge drivers don't come with any of the disadvantages that the drm_encoder_slave stuff has. They are regular drivers that are probed via their parent busses (I2C, platform, SPI, ...) and hook into DRM via an abstract interface. The DT aspect is taken care of automatically because they get instantiated by their parent bus like any other device.
Now, what happens when some other DRM driver wants to use the tda998x driver, and its bindings are not compatible with the component helpers? They're pretty much stuck up the creek without a paddle.
I'm sure that will be very helpful response for whoever's going to end up having to deal with that situation.
Case by case doesn't work unless you're talking about truely isolated hardware where no one shares anything.
There are two different things here. The inter-driver interface, which, in my opinion, it makes a lot of sense to standardize. Like I mentioned above I think it unwise to make this interface depend upon a framework or the firmware description such as DT in order to avoid unnecessary restrictions. The second, orthogonal, issue, is the DT bindings. Those I think should absolutely be designed case by case and select whatever most accurately describes the hardware.
Thierry
On Tue, Aug 25, 2015 at 12:40:01PM +0200, Thierry Reding wrote:
On Tue, Aug 25, 2015 at 10:29:39AM +0100, Russell King - ARM Linux wrote:
Now, what happens when some other DRM driver wants to use the tda998x driver, and its bindings are not compatible with the component helpers? They're pretty much stuck up the creek without a paddle.
I'm sure that will be very helpful response for whoever's going to end up having to deal with that situation.
Thank you for that comment, it's very constructive and much appreciated. I can see it's well worth me continuing to spend time on this thread.
Hi Thierry,
在 2015/8/25 17:12, Thierry Reding 写道:
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
There should be no need to have this in DT at all. The BPC is a property of the attached panel and it should come from the panel (either the panel driver or parsed from EDID if available).
Actually I have send an email about this one to you in version 2, just past from that email:
"samsung,color_space" and "samsung,color-depth"
The drm_display_info's color_formats and bpc indicate the monitor display ability, but the edp driver could not take it as input video format directly.
For example, with my DP TV I would found "RGB444 & YCRCB422 & & YCRCB444" support in drm_display_info.color_formats and 16bit bpc support, but RK3288 crtc driver could only output RGB & ITU formats, so finally analogix_dp-rockchip driver config crtc to RGBaaa 10bpc mode.
In this sutiation, the analogix_dp core driver would pazzled by the drm_display_info, can't chose the right color_space and bpc.
And this is the place that confused me, wish you could give some ideas about this one :-)
- Yakir
When we adopted the graph bindings for iMX DRM, I thought exactly at that time "it would be nice if this could become the standard for binding DRM components together" but I don't have the authority from either the DT perspective or the DRM perspective to mandate that. Neither does anyone else. That's the _real_ problem here.
I've seen several DRM bindings go by which don't use the of-graph stuff, which means that they'll never be compatible with generic components which do use the of-graph stuff.
It goes beyond bindings IMO. The use of the component framework or not has been at the whim of driver writers as well. It is either used or private APIs are created. I'm using components and my need for it boils down to passing the struct drm_device pointer to the encoder. Other components like panels and bridges have different ways to attach to the DRM driver.
I certainly support unification, but it needs to be reasonable. There are cases where a different structure for the binding work better than another and I think this always needs to be evaluated on a case by case basis.
Because of that I think it makes sense to make all these framework bits opt-in, otherwise we could easily end up in a situation where drivers have to be rearchitected (or even DT bindings altered!) in order to be able to reuse code.
Thierry
On Tue, Aug 25, 2015 at 05:41:19PM +0800, Yakir Yang wrote:
Hi Thierry,
在 2015/8/25 17:12, Thierry Reding 写道:
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
-analogix,color-depth:
number of bits per colour component.
COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3
This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
There should be no need to have this in DT at all. The BPC is a property of the attached panel and it should come from the panel (either the panel driver or parsed from EDID if available).
Actually I have send an email about this one to you in version 2, just past from that email:
"samsung,color_space" and "samsung,color-depth"
The drm_display_info's color_formats and bpc indicate the monitor display ability, but the edp driver could not take it as input video format directly.
For example, with my DP TV I would found "RGB444 & YCRCB422 & & YCRCB444" support in drm_display_info.color_formats and 16bit bpc support, but RK3288 crtc driver could only output RGB & ITU formats, so finally analogix_dp-rockchip driver config crtc to RGBaaa 10bpc mode.
In this sutiation, the analogix_dp core driver would pazzled by the drm_display_info, can't chose the right color_space and bpc.
And this is the place that confused me, wish you could give some ideas about this one :-)
Your display driver should choose whatever it is capable of outputting. If the display reports that it can do 16 bits-per-color, but your display driver can't do it, then it should choose a configuration that it supports. Similarily for the color encodings. If you can't generate YCrCb444 with your hardware, then it's the driver's job to know about that and select the next appropriate configuration.
But hard-coding this is not the right solution because the value in DT may end up conflicting with what the display reports.
Thierry
Hi Thierry,
在 2015/8/25 18:06, Thierry Reding 写道:
On Tue, Aug 25, 2015 at 05:41:19PM +0800, Yakir Yang wrote:
Hi Thierry,
在 2015/8/25 17:12, Thierry Reding 写道:
On Mon, Aug 24, 2015 at 09:48:27AM -0500, Rob Herring wrote:
On Mon, Aug 24, 2015 at 7:57 AM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote: > + -analogix,color-depth: > + number of bits per colour component. > + COLOR_6 = 0, COLOR_8 = 1, COLOR_10 = 2, COLOR_12 = 3 This seems pretty generic. Just use 6, 8, 10, or 12 for values. And drop the vendor prefix.
Please think about this some more. What does "color-depth" mean? Does it mean the number of bits per colour _component_, or does it mean the total number of bits to represent a particular colour. It's confusing as it stands.
Then "component-color-bpp" perhaps?
There should be no need to have this in DT at all. The BPC is a property of the attached panel and it should come from the panel (either the panel driver or parsed from EDID if available).
Actually I have send an email about this one to you in version 2, just past from that email:
"samsung,color_space" and "samsung,color-depth"
The drm_display_info's color_formats and bpc indicate the monitor display ability, but the edp driver could not take it as input video format directly.
For example, with my DP TV I would found "RGB444 & YCRCB422 & & YCRCB444" support in drm_display_info.color_formats and 16bit bpc support, but RK3288 crtc driver could only output RGB & ITU formats, so finally analogix_dp-rockchip driver config crtc to RGBaaa 10bpc mode.
In this sutiation, the analogix_dp core driver would pazzled by the drm_display_info, can't chose the right color_space and bpc.
And this is the place that confused me, wish you could give some ideas about this one :-)
Your display driver should choose whatever it is capable of outputting. If the display reports that it can do 16 bits-per-color, but your display driver can't do it, then it should choose a configuration that it supports. Similarily for the color encodings. If you can't generate YCrCb444 with your hardware, then it's the driver's job to know about that and select the next appropriate configuration.
But hard-coding this is not the right solution because the value in DT may end up conflicting with what the display reports.
Yeah, thanks for your explain, you are right. It's the best way to get "color-depth" and "color-space" from display driver, not to hard-code in DT prop.
But if the common analogix-dp driver want to get those values, then those values should come from the common drm struct data. Personally I think "struct drm_crtc" is the best place that should indicate the output ability of SoC vop/lcdc.
But I haven't find out there are some place to store those message for now (I don't think it's good to modify the original color-space and color-bpc which parsed from monitor edid).
So could you share sme ideas about this, and I would rather to talk with Mark (Author of rockchip drm driver) to find out the better way to fix this one.
Besides, I would appreciate very much if you can share some ideas about how Exynos handler with this problem ;)
Thanks, - Yakir
Thierry
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
Same as for the link rate.
Thierry
Hi Thierry,
在 2015/8/25 17:15, Thierry Reding 写道:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
Hmm... could you share more about this :-)
I only find that drm_dp_link_probe() could get the panel link-rate and num-lanes by reading the DP_DPCD_REV messag.
I don't found there are some guidance to help select the approriate one. Beside this DT prop just indicate the max eDP controller link-rate & lanes support, how could eDP detect them automatically?
- Yakir
-analogix,lane-count:
max number of lanes supported by the eDP contoller.
LANE_COUNT1 = 1, LANE_COUNT2 = 2, LANE_COUNT4 = 4
And drop the vendor prefix here.
Same as for the link rate.
Thierry
On Tue, Aug 25, 2015 at 4:15 AM, Thierry Reding treding@nvidia.com wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
Good, even better.
Rob
Hi Thierry & Rob,
在 2015/8/25 21:27, Rob Herring 写道:
On Tue, Aug 25, 2015 at 4:15 AM, Thierry Reding treding@nvidia.com wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
Good, even better.
I do think we still need keep this DT prop yet.
I think drm_dp_help.c could get the "panel" max link-rate and lane-count, but it's not enough, we still need knew the "eDP controller" max link-rate and lane-count.
Let me show the exact example that happened in my side. When I connect my board to my 2K DP-1.2 TV. Analogix dp driver would get the max link-rate from dpcd, and the max link-rate is 5.4Gbps. So if I just set eDP controller link-rate to 5.4Gbps, the DP TV just broken, do not light up normally.
This reason why TV broken is the max link-rate which support by RK3288 eDP controller is 2.7Gbps. Here are the exact words that RK3288 eDP TRM said:
*Compliant with DisplayPortTM Specification, Version 1.2. Compliant with eDPTM Specification, Version 1.3. HDCP v1.3 amendment for DisplayPortTM Revision 1.0. Main link containing 4 physical lanes of 2.7/1.62 Gbps/lane * **
Beside I haven't found there are some registers would indicate the eDP controller max link-rate and lane-count, so this is why I still instance that we need this DT prop to indicata "Max rate controller support".
So, I wish you could agree with me on this point.
Thanks, - Yakir
Rob
On Tue, Aug 25, 2015 at 09:48:01PM +0800, Yakir Yang wrote:
Hi Thierry & Rob,
在 2015/8/25 21:27, Rob Herring 写道:
On Tue, Aug 25, 2015 at 4:15 AM, Thierry Reding treding@nvidia.com wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
Good, even better.
I do think we still need keep this DT prop yet.
I think drm_dp_help.c could get the "panel" max link-rate and lane-count, but it's not enough, we still need knew the "eDP controller" max link-rate and lane-count.
Let me show the exact example that happened in my side. When I connect my board to my 2K DP-1.2 TV. Analogix dp driver would get the max link-rate from dpcd, and the max link-rate is 5.4Gbps. So if I just set eDP controller link-rate to 5.4Gbps, the DP TV just broken, do not light up normally.
This reason why TV broken is the max link-rate which support by RK3288 eDP controller is 2.7Gbps. Here are the exact words that RK3288 eDP TRM said:
*Compliant with DisplayPortTM Specification, Version 1.2. Compliant with eDPTM Specification, Version 1.3. HDCP v1.3 amendment for DisplayPortTM Revision 1.0. Main link containing 4 physical lanes of 2.7/1.62 Gbps/lane
**
Beside I haven't found there are some registers would indicate the eDP controller max link-rate and lane-count, so this is why I still instance that we need this DT prop to indicata "Max rate controller support".
So, I wish you could agree with me on this point.
Your driver should know what link rates it supports and restrict itself to use those. This is implied by the compatible string and doesn't need to be duplicated into device tree.
Thierry
Hi Thierry,
在 2015/8/25 22:16, Thierry Reding 写道:
On Tue, Aug 25, 2015 at 09:48:01PM +0800, Yakir Yang wrote:
Hi Thierry & Rob,
在 2015/8/25 21:27, Rob Herring 写道:
On Tue, Aug 25, 2015 at 4:15 AM, Thierry Reding treding@nvidia.com wrote:
On Sun, Aug 23, 2015 at 06:23:14PM -0500, Rob Herring wrote:
On Wed, Aug 19, 2015 at 9:50 AM, Yakir Yang ykk@rock-chips.com wrote:
[...]
-analogix,link-rate:
max link rate supported by the eDP controller.
LINK_RATE_1_62GBPS = 0x6, LINK_RATE_2_70GBPS = 0x0A,
LINK_RATE_5_40GBPS = 0x14
Same here. I'd rather see something like "link-rate-mbps" and use the actual rate.
There is no need whatsoever to hard-code this in DT. (e)DP provides the means to detect what rate the link supports and the specification provides guidance on how to select an appropriate one.
Good, even better.
I do think we still need keep this DT prop yet.
I think drm_dp_help.c could get the "panel" max link-rate and lane-count, but it's not enough, we still need knew the "eDP controller" max link-rate and lane-count.
Let me show the exact example that happened in my side. When I connect my board to my 2K DP-1.2 TV. Analogix dp driver would get the max link-rate from dpcd, and the max link-rate is 5.4Gbps. So if I just set eDP controller link-rate to 5.4Gbps, the DP TV just broken, do not light up normally.
This reason why TV broken is the max link-rate which support by RK3288 eDP controller is 2.7Gbps. Here are the exact words that RK3288 eDP TRM said:
*Compliant with DisplayPortTM Specification, Version 1.2. Compliant with eDPTM Specification, Version 1.3. HDCP v1.3 amendment for DisplayPortTM Revision 1.0. Main link containing 4 physical lanes of 2.7/1.62 Gbps/lane
**
Beside I haven't found there are some registers would indicate the eDP controller max link-rate and lane-count, so this is why I still instance that we need this DT prop to indicata "Max rate controller support".
So, I wish you could agree with me on this point.
Your driver should know what link rates it supports and restrict itself to use those. This is implied by the compatible string and doesn't need to be duplicated into device tree.
Oh, yeah, good idea :-D Thanks for your point out.
- Yakir
Thierry
On Wed, Aug 19, 2015 at 09:50:34AM -0500, Yakir Yang wrote: [...]
- -analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
I don't think DT is an appropriate place to set this. To my knowledge this depends on the display and/or mode, so I don't think hard-coding it here is the right thing to do.
Thierry
Hi Thierry,
在 2015/8/25 17:58, Thierry Reding 写道:
On Wed, Aug 19, 2015 at 09:50:34AM -0500, Yakir Yang wrote: [...]
- -analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
I don't think DT is an appropriate place to set this. To my knowledge this depends on the display and/or mode, so I don't think hard-coding it here is the right thing to do.
Yeah, same question with my previous reply ;)
Thanks, - Yakir
Thierry
On Tue, Aug 25, 2015 at 10:03:52PM +0800, Yakir Yang wrote:
Hi Thierry,
在 2015/8/25 17:58, Thierry Reding 写道:
On Wed, Aug 19, 2015 at 09:50:34AM -0500, Yakir Yang wrote: [...]
- -analogix,color-space:
input video data format.
COLOR_RGB = 0, COLOR_YCBCR422 = 1, COLOR_YCBCR444 = 2
I don't think DT is an appropriate place to set this. To my knowledge this depends on the display and/or mode, so I don't think hard-coding it here is the right thing to do.
Yeah, same question with my previous reply ;)
I don't have an answer for you, unfortunately. But like I said, hard-coding isn't going to work. What if, for example, you set this to a fixed value and then you connect a monitor that doesn't support the specific one you set?
You cited code from dw_hdmi.c earlier, it looks like it might be correct even though it doesn't cite a reference for why this was done. Perhaps someone on this thread, or someone involved with dw_hdmi can answer where that code came from.
Thierry
On Tue, Aug 25, 2015 at 04:21:51PM +0200, Thierry Reding wrote:
You cited code from dw_hdmi.c earlier, it looks like it might be correct even though it doesn't cite a reference for why this was done. Perhaps someone on this thread, or someone involved with dw_hdmi can answer where that code came from.
dw_hdmi doesn't do any format conversion - it's hard coded to RGB, 8 bits per colour component. That's a requirement for all HDMI sinks.
The reason it's hard-coded in dw_hdmi is that (a) no one has yet decided its worth the effort to get the dw_hdmi hardware to do the colourspace conversion to the YUV spaces and verify that it works, and (b) I really don't see the point when we're talking about computer like devices which work primerily with RGB and RGB is always supported by the sink.
As far as greater colour depths go, the driver came from the Freescale iMX6 code base, and the hardware which feeds dw_hdmi can't do more than 8 bits per component - so going to 10, 12 or 16 bits per component is beyond what iMX6 can cope with. Hence, no one on the iMX6 side has a need for the deep colour stuff.
In any case, I view this as a very low priority issue - it would be nice to have audio support on HDMI for iMX6 at some point in the next 20 years, preferably before the hardware becomes obsolete. I've been maintaining patches for this for 1.5 years now... how much longer is it going to take? My pull request to David from 15th July was ignored. My re-send of that after he returned was ignored. My reminder of it has been ignored. What's going on in DRM land? It would be nice to get _some_ kind of feedback so I know why they're not being taken, so I can fix whatever the issue is.
Rockchip have three clocks for dp controller, we leave pclk_edp to analogix_dp driver control, and keep the sclk_edp_24m and sclk_edp in platform driver.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk". - Take Heiko suggest, add devicetree binding document. - Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node. - Add the new function point analogix_dp_platdata.get_modes init.
Changes in v2: - Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver. - Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
.../bindings/video/analogix_dp-rockchip.txt | 82 +++++ drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 389 +++++++++++++++++++++ 4 files changed, 481 insertions(+) create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
diff --git a/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt b/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt new file mode 100644 index 0000000..99fd421 --- /dev/null +++ b/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt @@ -0,0 +1,82 @@ +Rockchip RK3288 specific extensions to the Analogix Display Port +================================ + +Required properties: +- compatible: "rockchip,rk3288-edp"; + +- reg: physical base address of the controller and length +- clocks: from common clock binding: handle to dp clock. + of memory mapped region. +- clock-names: from common clock binding: + Required elements: "dp" "pclk" +- resets: Must contain an entry for each entry in reset-names. + See ../reset/reset.txt for details. +- reset-names: Must include the name "dp" + +- rockchip,grf: this soc should set GRF regs, so need get grf here. + +- ports: contain a port node with endpoint definitions as defined in + Documentation/devicetree/bindings/media/video-interfaces.txt. + + +For the below properties, please refer to Analogix DP binding document: + * Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt +- phys (required) +- phy-names (required) +- analogix,color-space (required) +- analogix,color-depth (required) +- analogix,link-rate (required) +- analogix,lane-count (required) +- analogix,hpd-gpio (optional) +- video interfaces (optional) +------------------------------------------------------------------------------- + +Example: + dp-controller: dp@ff970000 { + compatible = "rockchip,rk3288-dp"; + reg = <0xff970000 0x4000>; + interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>; + clock-names = "dp", "pclk"; + phys = <&dp_phy>; + phy-names = "dp"; + + rockchip,grf = <&grf>; + resets = <&cru 111>; + reset-names = "dp"; + + hsync-active-high = <0>; + vsync-active-high = <0>; + interlaced = <0>; + analogix,color-space = <0>; + analogix,color-depth = <1>; + analogix,link-rate = <0x0a>; + analogix,lane-count = <4>; + status = "disabled"; + + ports { + edp_in: port { + #address-cells = <1>; + #size-cells = <0>; + edp_in_vopb: endpoint@0 { + reg = <0>; + remote-endpoint = <&vopb_out_edp>; + }; + edp_in_vopl: endpoint@1 { + reg = <1>; + remote-endpoint = <&vopl_out_edp>; + }; + }; + + edp_out: port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + edp_out_panel: endpoint { + reg = <0>; + remote-endpoint = <&panel_in_edp> + }; + }; + }; + }; + diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 35215f6..c2ba945 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -25,3 +25,12 @@ config ROCKCHIP_DW_HDMI for the Synopsys DesignWare HDMI driver. If you want to enable HDMI on RK3288 based SoC, you should selet this option. + +config ROCKCHIP_ANALOGIX_DP + tristate "Rockchip specific extensions for Analogix DP driver" + depends on DRM_ROCKCHIP + select DRM_ANALOGIX_DP + help + This selects support for Rockchip SoC specific extensions + for the Analogix Core DP driver. If you want to enable DP + on RK3288 based SoC, you should selet this option. diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index f3d8a19..8ad01fb 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -6,5 +6,6 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \ rockchip_drm_gem.o
obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o +obj-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c new file mode 100644 index 0000000..cebff9e --- /dev/null +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -0,0 +1,389 @@ +/* + * Rockchip SoC DP (Display Port) interface driver. + * + * Copyright (C) Fuzhou Rockchip Electronics Co., Ltd. + * Author: Andy Yan andy.yan@rock-chips.com + * Yakir Yang ykk@rock-chips.com + * Jeff Chen jeff.chen@rock-chips.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <drm/drmP.h> +#include <drm/drm_crtc_helper.h> +#include <drm/drm_panel.h> +#include <drm/drm_of.h> +#include <drm/drm_dp_helper.h> + +#include <linux/component.h> +#include <linux/mfd/syscon.h> +#include <linux/of_graph.h> +#include <linux/regmap.h> +#include <linux/reset.h> +#include <linux/clk.h> + +#include <video/of_videomode.h> +#include <video/videomode.h> + +#include <drm/bridge/analogix_dp.h> + +#include "rockchip_drm_drv.h" +#include "rockchip_drm_vop.h" + +#define encoder_to_dp(c) \ + container_of(c, struct rockchip_dp_device, encoder) + +#define plat_data_to_dp(pd) \ + container_of(pd, struct rockchip_dp_device, plat_data) + +/* dp grf register offset */ +#define GRF_GPIO7B_IOMUX 0x0070 +#define GPIO7B3_SEL_MASK (0x03 << 6) +#define GPIO7B3_SEL_EDP_HOTPLUG BIT(7) + +#define GRF_SOC_CON6 0x025c +#define GRF_EDP_LCD_SEL_MASK BIT(5) +#define GRF_EDP_SEL_VOP_LIT BIT(5) +#define GRF_EDP_SEL_VOP_BIG 0 + +struct rockchip_dp_device { + struct drm_device *drm_dev; + struct device *dev; + struct drm_encoder encoder; + struct drm_display_mode mode; + + struct clk *pclk; + struct regmap *grf; + struct reset_control *rst; + + struct analogix_dp_plat_data plat_data; +}; + +static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) +{ + u32 val; + int ret; + + val = GPIO7B3_SEL_EDP_HOTPLUG | (GPIO7B3_SEL_MASK << 16); + ret = regmap_write(dp->grf, GRF_GPIO7B_IOMUX, val); + if (ret != 0) { + dev_err(dp->dev, "Could not config GRF edp hpd: %d\n", ret); + return ret; + } + + reset_control_assert(dp->rst); + usleep_range(10, 20); + reset_control_deassert(dp->rst); + + return 0; +} + +static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) +{ + struct rockchip_dp_device *dp = plat_data_to_dp(plat_data); + int ret; + + ret = clk_prepare_enable(dp->pclk); + if (ret < 0) { + dev_err(dp->dev, "failed to enable pclk %d\n", ret); + return ret; + } + + ret = rockchip_dp_pre_init(dp); + if (ret < 0) { + dev_err(dp->dev, "failed to dp pre init %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) +{ + struct rockchip_dp_device *dp = plat_data_to_dp(plat_data); + + clk_disable_unprepare(dp->pclk); + + return 0; +} + +static bool +rockchip_dp_drm_encoder_mode_fixup(struct drm_encoder *encoder, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* do nothing */ + return true; +} + +static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted) +{ + /* do nothing */ +} + +static void rockchip_dp_drm_encoder_prepare(struct drm_encoder *encoder) +{ + struct rockchip_dp_device *dp = encoder_to_dp(encoder); + u32 val; + int ret; + + ret = rockchip_drm_crtc_mode_config(encoder->crtc, + DRM_MODE_CONNECTOR_eDP, + ROCKCHIP_OUT_MODE_AAAA); + if (ret < 0) { + dev_err(dp->dev, "Could not set crtc mode config: %d.\n", ret); + return; + } + + ret = rockchip_drm_encoder_get_mux_id(dp->dev->of_node, encoder); + if (ret < 0) + return; + + if (ret) + val = GRF_EDP_SEL_VOP_LIT | (GRF_EDP_LCD_SEL_MASK << 16); + else + val = GRF_EDP_SEL_VOP_BIG | (GRF_EDP_LCD_SEL_MASK << 16); + + dev_dbg(dp->dev, "vop %s output to dp\n", (ret) ? "LIT" : "BIG"); + + ret = regmap_write(dp->grf, GRF_SOC_CON6, val); + if (ret != 0) { + dev_err(dp->dev, "Could not write to GRF: %d\n", ret); + return; + } +} + +static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) +{ + /* do nothing */ +} + +static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { + .mode_fixup = rockchip_dp_drm_encoder_mode_fixup, + .mode_set = rockchip_dp_drm_encoder_mode_set, + .prepare = rockchip_dp_drm_encoder_prepare, + .commit = rockchip_dp_drm_encoder_nop, + .disable = rockchip_dp_drm_encoder_nop, +}; + +static void rockchip_dp_drm_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static struct drm_encoder_funcs rockchip_dp_encoder_funcs = { + .destroy = rockchip_dp_drm_encoder_destroy, +}; + +static int rockchip_dp_init(struct rockchip_dp_device *dp) +{ + struct device *dev = dp->dev; + struct device_node *np = dev->of_node; + int ret; + + dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(dp->grf)) { + dev_err(dev, "failed to get rockchip,grf property\n"); + return PTR_ERR(dp->grf); + } + + dp->pclk = devm_clk_get(dev, "pclk"); + if (IS_ERR(dp->pclk)) { + dev_err(dev, "failed to get pclk property\n"); + return PTR_ERR(dp->pclk); + } + + dp->rst = devm_reset_control_get(dev, "dp"); + if (IS_ERR(dp->rst)) { + dev_err(dev, "failed to get dp reset control\n"); + return PTR_ERR(dp->rst); + } + + ret = clk_prepare_enable(dp->pclk); + if (ret < 0) { + dev_err(dp->dev, "failed to enable pclk %d\n", ret); + return ret; + } + + ret = rockchip_dp_pre_init(dp); + if (ret < 0) { + dev_err(dp->dev, "failed to pre init %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_dp_drm_create_encoder(struct rockchip_dp_device *dp) +{ + struct drm_encoder *encoder = &dp->encoder; + struct drm_device *drm_dev = dp->drm_dev; + struct device *dev = dp->dev; + int ret; + + encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, + dev->of_node); + DRM_DEBUG_KMS("possible_crtcs = 0x%x\n", encoder->possible_crtcs); + + ret = drm_encoder_init(drm_dev, encoder, &rockchip_dp_encoder_funcs, + DRM_MODE_ENCODER_TMDS); + if (ret) { + DRM_ERROR("failed to initialize encoder with drm\n"); + return ret; + } + + drm_encoder_helper_add(encoder, &rockchip_dp_encoder_helper_funcs); + + return 0; +} + +static int rockchip_dp_bind(struct device *dev, struct device *master, + void *data) +{ + struct rockchip_dp_device *dp = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + int ret; + + /* + * Just like the probe function said, we don't need the + * device drvrate anymore, we should leave the charge to + * analogix dp driver, set the device drvdata to NULL. + */ + dev_set_drvdata(dev, NULL); + + ret = rockchip_dp_init(dp); + if (ret < 0) + return ret; + + dp->drm_dev = drm_dev; + + ret = rockchip_dp_drm_create_encoder(dp); + if (ret) { + DRM_ERROR("failed to create drm encoder\n"); + return ret; + } + + dp->plat_data.attach = NULL; + dp->plat_data.get_modes = NULL; + dp->plat_data.power_on = rockchip_dp_poweron; + dp->plat_data.power_off = rockchip_dp_powerdown; + + return analogix_dp_bind(dev, dp->drm_dev, &dp->encoder, + &dp->plat_data); +} + +static void rockchip_dp_unbind(struct device *dev, struct device *master, + void *data) +{ + return analogix_dp_unbind(dev, master, data); +} + +static const struct component_ops rockchip_dp_component_ops = { + .bind = rockchip_dp_bind, + .unbind = rockchip_dp_unbind, +}; + +static int rockchip_dp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *panel_node, *port, *endpoint; + struct rockchip_dp_device *dp; + struct drm_panel *panel; + + port = of_graph_get_port_by_id(dev->of_node, 1); + if (!port) { + dev_err(dev, "can't find output port\n"); + return -EINVAL; + } + + endpoint = of_get_child_by_name(port, "endpoint"); + of_node_put(port); + if (!endpoint) { + dev_err(dev, "no output endpoint found\n"); + return -EINVAL; + } + + panel_node = of_graph_get_remote_port_parent(endpoint); + of_node_put(endpoint); + if (!panel_node) { + dev_err(dev, "no output node found\n"); + return -EINVAL; + } + + panel = of_drm_find_panel(panel_node); + if (!panel) { + DRM_ERROR("failed to find panel\n"); + of_node_put(panel_node); + return -EPROBE_DEFER; + } + + of_node_put(panel_node); + + dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + dp->dev = dev; + + dp->plat_data.panel = panel; + + /* + * We just use the drvdata until driver run into component + * add function, and then we would set drvdata to null, so + * that analogix dp driver could take charge of the drvdata. + */ + platform_set_drvdata(pdev, dp); + + return component_add(dev, &rockchip_dp_component_ops); +} + +static int rockchip_dp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &rockchip_dp_component_ops); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int rockchip_dp_suspend(struct device *dev) +{ + return analogix_dp_suspend(dev); +} + +static int rockchip_dp_resume(struct device *dev) +{ + return analogix_dp_resume(dev); +} +#endif + +static const struct dev_pm_ops rockchip_dp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(rockchip_dp_suspend, rockchip_dp_resume) +}; + +static const struct of_device_id rockchip_dp_dt_ids[] = { + {.compatible = "rockchip,rk3288-dp",}, + {} +}; +MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids); + +static struct platform_driver rockchip_dp_driver = { + .probe = rockchip_dp_probe, + .remove = rockchip_dp_remove, + .driver = { + .name = "rockchip-dp", + .owner = THIS_MODULE, + .pm = &rockchip_dp_pm_ops, + .of_match_table = of_match_ptr(rockchip_dp_dt_ids), + }, +}; + +module_platform_driver(rockchip_dp_driver); + +MODULE_AUTHOR("Yakir Yang ykk@rock-chips.com"); +MODULE_AUTHOR("Jeff chen jeff.chen@rock-chips.com"); +MODULE_DESCRIPTION("Rockchip Specific Analogix-DP Driver Extension"); +MODULE_LICENSE("GPL v2");
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
Changes in v2: None
.../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 +++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 drivers/phy/phy-rockchip-dp.c
diff --git a/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt new file mode 100644 index 0000000..5de1088 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt @@ -0,0 +1,26 @@ +Rockchip Soc Seroes Display Port PHY +------------------------------------ + +Required properties: +- compatible : should be one of the following supported values: + - "rockchip.rk3288-dp-phy" + +- reg : a list of registers used by phy driver +- clocks: from common clock binding: handle to dp clock. + of memory mapped region. +- clock-names: from common clock binding: + Required elements: "sclk_dp" "sclk_dp_24m" + +- rockchip,grf: this soc should set GRF regs, so need get grf here. +- #phy-cells : from the generic PHY bindings, must be 0; + +Example: + +edp_phy: phy@ff770274 { + compatilble = "rockchip,rk3288-dp-phy"; + reg = <0xff770274 4>; + rockchip,grf = <&grf>; + clocks = <&cru SCLK_EDP_24M>; + clock-names = "24m"; + #phy-cells = <0>; +} diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 6b8dd16..da00440 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -297,6 +297,13 @@ config PHY_ROCKCHIP_USB help Enable this to support the Rockchip USB 2.0 PHY.
+config PHY_ROCKCHIP_DP + tristate "Rockchip Display Port PHY Driver" + depends on ARCH_ROCKCHIP && OF + select GENERIC_PHY + help + Enable this to support the Rockchip Display Port PHY. + config PHY_ST_SPEAR1310_MIPHY tristate "ST SPEAR1310-MIPHY driver" select GENERIC_PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f344e1b..35e3ce6 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -33,6 +33,7 @@ phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/phy-rockchip-dp.c new file mode 100644 index 0000000..4759111 --- /dev/null +++ b/drivers/phy/phy-rockchip-dp.c @@ -0,0 +1,185 @@ +/* + * Rockchip DP PHY driver + * + * Copyright (C) 2015 FuZhou Rockchip Co., Ltd. + * Author: Yakir Yang <ykk@@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License. + */ + +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/platform_device.h> + +#define GRF_SOC_CON12 0x0274 +#define GRF_EDP_REF_CLK_SEL_INTER BIT(4) + +#define DP_PHY_SIDDQ_WRITE_EN BIT(21) +#define DP_PHY_SIDDQ_ON 0 +#define DP_PHY_SIDDQ_OFF BIT(5) + +struct rockchip_dp_phy { + struct device *dev; + struct regmap *grf; + void __iomem *regs; + struct clk *phy_24m; +}; + +static int rockchip_dp_phy_clk_enable(struct rockchip_dp_phy *dp) +{ + int ret = 0; + + ret = clk_set_rate(dp->phy_24m, 24000000); + if (ret < 0) { + dev_err(dp->dev, "cannot set clock phy_24m %d\n", ret); + return ret; + } + + ret = clk_prepare_enable(dp->phy_24m); + if (ret < 0) { + dev_err(dp->dev, "cannot enable clock phy_24m %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_dp_phy_clk_disable(struct rockchip_dp_phy *dp) +{ + clk_disable_unprepare(dp->phy_24m); + + return 0; +} + +static int rockchip_set_phy_state(struct phy *phy, bool enable) +{ + struct rockchip_dp_phy *dp = phy_get_drvdata(phy); + + if (enable) { + rockchip_dp_phy_clk_enable(dp); + writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_ON, dp->regs); + } else { + rockchip_dp_phy_clk_disable(dp); + writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_OFF, dp->regs); + } + + return 0; +} + +static int rockchip_dp_phy_power_on(struct phy *phy) +{ + return rockchip_set_phy_state(phy, true); +} + +static int rockchip_dp_phy_power_off(struct phy *phy) +{ + return rockchip_set_phy_state(phy, false); +} + +static struct phy_ops rockchip_dp_phy_ops = { + .power_on = rockchip_dp_phy_power_on, + .power_off = rockchip_dp_phy_power_off, + .owner = THIS_MODULE, +}; + +static int rockchip_dp_phy_init(struct rockchip_dp_phy *dp) +{ + struct device *dev = dp->dev; + struct device_node *np = dev->of_node; + int ret; + + dp->phy_24m = devm_clk_get(dev, "24m"); + if (IS_ERR(dp->phy_24m)) { + dev_err(dev, "cannot get clock 24m\n"); + return PTR_ERR(dp->phy_24m); + } + + ret = rockchip_dp_phy_clk_enable(dp); + if (ret < 0) { + dev_err(dp->dev, "cannot enable dp phy clk %d\n", ret); + return ret; + } + + dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(dp->grf)) { + dev_err(dev, "rk3288-dp needs rockchip,grf property\n"); + return PTR_ERR(dp->grf); + } + + ret = regmap_write(dp->grf, GRF_SOC_CON12, + GRF_EDP_REF_CLK_SEL_INTER | + (GRF_EDP_REF_CLK_SEL_INTER << 16)); + if (ret != 0) { + dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_dp_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct phy_provider *phy_provider; + struct rockchip_dp_phy *dp; + struct resource *res; + struct phy *phy; + int ret; + + dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL); + if (IS_ERR(dp)) + return -ENOMEM; + + dp->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + dp->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(dp->regs)) + return PTR_ERR(dp->regs); + + ret = rockchip_dp_phy_init(dp); + if (ret) + return ret; + + phy = devm_phy_create(dev, NULL, &rockchip_dp_phy_ops, NULL); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + phy_set_drvdata(phy, dp); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id rockchip_dp_phy_dt_ids[] = { + { .compatible = "rockchip,rk3288-dp-phy" }, + {} +}; + +MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids); + +static struct platform_driver rockchip_dp_phy_driver = { + .probe = rockchip_dp_phy_probe, + .driver = { + .name = "rockchip-dp-phy", + .owner = THIS_MODULE, + .of_match_table = rockchip_dp_phy_dt_ids, + }, +}; + +module_platform_driver(rockchip_dp_phy_driver); + +MODULE_AUTHOR("Yakir Yang ykk@rock-chips.com"); +MODULE_DESCRIPTION("Rockchip DP PHY driver"); +MODULE_LICENSE("GPL v2");
Hi,
On Wednesday 19 August 2015 08:21 PM, Yakir Yang wrote:
Signed-off-by: Yakir Yang ykk@rock-chips.com
where's the commit message?
Changes in v3:
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
Changes in v2: None
.../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 +++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 drivers/phy/phy-rockchip-dp.c
diff --git a/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt new file mode 100644 index 0000000..5de1088 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt @@ -0,0 +1,26 @@ +Rockchip Soc Seroes Display Port PHY +------------------------------------
+Required properties: +- compatible : should be one of the following supported values:
- "rockchip.rk3288-dp-phy"
+- reg : a list of registers used by phy driver +- clocks: from common clock binding: handle to dp clock.
- of memory mapped region.
+- clock-names: from common clock binding:
- Required elements: "sclk_dp" "sclk_dp_24m"
+- rockchip,grf: this soc should set GRF regs, so need get grf here. +- #phy-cells : from the generic PHY bindings, must be 0;
+Example:
+edp_phy: phy@ff770274 {
- compatilble = "rockchip,rk3288-dp-phy";
- reg = <0xff770274 4>;
- rockchip,grf = <&grf>;
- clocks = <&cru SCLK_EDP_24M>;
- clock-names = "24m";
- #phy-cells = <0>;
+} diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 6b8dd16..da00440 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -297,6 +297,13 @@ config PHY_ROCKCHIP_USB help Enable this to support the Rockchip USB 2.0 PHY.
+config PHY_ROCKCHIP_DP
- tristate "Rockchip Display Port PHY Driver"
- depends on ARCH_ROCKCHIP && OF
- select GENERIC_PHY
- help
Enable this to support the Rockchip Display Port PHY.
config PHY_ST_SPEAR1310_MIPHY tristate "ST SPEAR1310-MIPHY driver" select GENERIC_PHY diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f344e1b..35e3ce6 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -33,6 +33,7 @@ phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/phy-rockchip-dp.c new file mode 100644 index 0000000..4759111 --- /dev/null +++ b/drivers/phy/phy-rockchip-dp.c @@ -0,0 +1,185 @@ +/*
- Rockchip DP PHY driver
- Copyright (C) 2015 FuZhou Rockchip Co., Ltd.
- Author: Yakir Yang <ykk@@rock-chips.com>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License.
- */
+#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/platform_device.h>
+#define GRF_SOC_CON12 0x0274 +#define GRF_EDP_REF_CLK_SEL_INTER BIT(4)
+#define DP_PHY_SIDDQ_WRITE_EN BIT(21) +#define DP_PHY_SIDDQ_ON 0 +#define DP_PHY_SIDDQ_OFF BIT(5)
+struct rockchip_dp_phy {
- struct device *dev;
- struct regmap *grf;
- void __iomem *regs;
- struct clk *phy_24m;
+};
+static int rockchip_dp_phy_clk_enable(struct rockchip_dp_phy *dp) +{
- int ret = 0;
- ret = clk_set_rate(dp->phy_24m, 24000000);
- if (ret < 0) {
dev_err(dp->dev, "cannot set clock phy_24m %d\n", ret);
return ret;
- }
- ret = clk_prepare_enable(dp->phy_24m);
- if (ret < 0) {
dev_err(dp->dev, "cannot enable clock phy_24m %d\n", ret);
return ret;
- }
- return 0;
+}
+static int rockchip_dp_phy_clk_disable(struct rockchip_dp_phy *dp) +{
- clk_disable_unprepare(dp->phy_24m);
- return 0;
+}
+static int rockchip_set_phy_state(struct phy *phy, bool enable) +{
- struct rockchip_dp_phy *dp = phy_get_drvdata(phy);
- if (enable) {
rockchip_dp_phy_clk_enable(dp);
writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_ON, dp->regs);
- } else {
rockchip_dp_phy_clk_disable(dp);
writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_OFF, dp->regs);
- }
- return 0;
+}
+static int rockchip_dp_phy_power_on(struct phy *phy) +{
- return rockchip_set_phy_state(phy, true);
+}
+static int rockchip_dp_phy_power_off(struct phy *phy) +{
- return rockchip_set_phy_state(phy, false);
+}
+static struct phy_ops rockchip_dp_phy_ops = {
- .power_on = rockchip_dp_phy_power_on,
- .power_off = rockchip_dp_phy_power_off,
- .owner = THIS_MODULE,
+};
+static int rockchip_dp_phy_init(struct rockchip_dp_phy *dp) +{
- struct device *dev = dp->dev;
- struct device_node *np = dev->of_node;
- int ret;
- dp->phy_24m = devm_clk_get(dev, "24m");
- if (IS_ERR(dp->phy_24m)) {
dev_err(dev, "cannot get clock 24m\n");
return PTR_ERR(dp->phy_24m);
- }
- ret = rockchip_dp_phy_clk_enable(dp);
- if (ret < 0) {
dev_err(dp->dev, "cannot enable dp phy clk %d\n", ret);
return ret;
- }
- dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
- if (IS_ERR(dp->grf)) {
dev_err(dev, "rk3288-dp needs rockchip,grf property\n");
return PTR_ERR(dp->grf);
- }
- ret = regmap_write(dp->grf, GRF_SOC_CON12,
GRF_EDP_REF_CLK_SEL_INTER |
(GRF_EDP_REF_CLK_SEL_INTER << 16));
- if (ret != 0) {
dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret);
return ret;
- }
This function can be split to do only clk_get and syscon_regmap_lookup in probe, clk_enable and regmap_write in phy_init?
- return 0;
+}
+static int rockchip_dp_phy_probe(struct platform_device *pdev) +{
- struct device *dev = &pdev->dev;
- struct phy_provider *phy_provider;
- struct rockchip_dp_phy *dp;
- struct resource *res;
- struct phy *phy;
- int ret;
- dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
- if (IS_ERR(dp))
return -ENOMEM;
- dp->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dp->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(dp->regs))
return PTR_ERR(dp->regs);
- ret = rockchip_dp_phy_init(dp);
- if (ret)
return ret;
- phy = devm_phy_create(dev, NULL, &rockchip_dp_phy_ops, NULL);
- if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
return PTR_ERR(phy);
- }
- phy_set_drvdata(phy, dp);
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- return PTR_ERR_OR_ZERO(phy_provider);
+}
+static const struct of_device_id rockchip_dp_phy_dt_ids[] = {
- { .compatible = "rockchip,rk3288-dp-phy" },
- {}
+};
+MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids);
+static struct platform_driver rockchip_dp_phy_driver = {
- .probe = rockchip_dp_phy_probe,
- .driver = {
.name = "rockchip-dp-phy",
.owner = THIS_MODULE,
owner is not required here.
Thanks Kishon
Hi Kishon,
On 08/19/2015 11:40 PM, Kishon Vijay Abraham I wrote:
Hi,
On Wednesday 19 August 2015 08:21 PM, Yakir Yang wrote:
Signed-off-by: Yakir Yang ykk@rock-chips.com
where's the commit message?
Actually I have no detail words for this, so leave this empty :-)
If you think I should add some words here, I may want to declare the relationship of this driver and remote analogix dp driver.
Changes in v3:
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
Changes in v2: None
.../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 +++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 drivers/phy/phy-rockchip-dp.c
diff --git a/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt new file mode 100644 index 0000000..5de1088 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt @@ -0,0 +1,26 @@ +Rockchip Soc Seroes Display Port PHY +------------------------------------
+Required properties: +- compatible : should be one of the following supported values:
- "rockchip.rk3288-dp-phy"
+- reg : a list of registers used by phy driver +- clocks: from common clock binding: handle to dp clock.
- of memory mapped region.
+- clock-names: from common clock binding:
- Required elements: "sclk_dp" "sclk_dp_24m"
+- rockchip,grf: this soc should set GRF regs, so need get grf here. +- #phy-cells : from the generic PHY bindings, must be 0;
+Example:
+edp_phy: phy@ff770274 {
- compatilble = "rockchip,rk3288-dp-phy";
- reg = <0xff770274 4>;
- rockchip,grf = <&grf>;
- clocks = <&cru SCLK_EDP_24M>;
- clock-names = "24m";
- #phy-cells = <0>;
+} diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 6b8dd16..da00440 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -297,6 +297,13 @@ config PHY_ROCKCHIP_USB help Enable this to support the Rockchip USB 2.0 PHY.
+config PHY_ROCKCHIP_DP
- tristate "Rockchip Display Port PHY Driver"
- depends on ARCH_ROCKCHIP && OF
- select GENERIC_PHY
- help
Enable this to support the Rockchip Display Port PHY.
- config PHY_ST_SPEAR1310_MIPHY tristate "ST SPEAR1310-MIPHY driver" select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index f344e1b..35e3ce6 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -33,6 +33,7 @@ phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o +obj-$(CONFIG_PHY_ROCKCHIP_DP) += phy-rockchip-dp.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o diff --git a/drivers/phy/phy-rockchip-dp.c b/drivers/phy/phy-rockchip-dp.c new file mode 100644 index 0000000..4759111 --- /dev/null +++ b/drivers/phy/phy-rockchip-dp.c @@ -0,0 +1,185 @@ +/*
- Rockchip DP PHY driver
- Copyright (C) 2015 FuZhou Rockchip Co., Ltd.
- Author: Yakir Yang <ykk@@rock-chips.com>
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License.
- */
+#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> +#include <linux/platform_device.h>
+#define GRF_SOC_CON12 0x0274 +#define GRF_EDP_REF_CLK_SEL_INTER BIT(4)
+#define DP_PHY_SIDDQ_WRITE_EN BIT(21) +#define DP_PHY_SIDDQ_ON 0 +#define DP_PHY_SIDDQ_OFF BIT(5)
+struct rockchip_dp_phy {
- struct device *dev;
- struct regmap *grf;
- void __iomem *regs;
- struct clk *phy_24m;
+};
+static int rockchip_dp_phy_clk_enable(struct rockchip_dp_phy *dp) +{
- int ret = 0;
- ret = clk_set_rate(dp->phy_24m, 24000000);
- if (ret < 0) {
dev_err(dp->dev, "cannot set clock phy_24m %d\n", ret);
return ret;
- }
- ret = clk_prepare_enable(dp->phy_24m);
- if (ret < 0) {
dev_err(dp->dev, "cannot enable clock phy_24m %d\n", ret);
return ret;
- }
- return 0;
+}
+static int rockchip_dp_phy_clk_disable(struct rockchip_dp_phy *dp) +{
- clk_disable_unprepare(dp->phy_24m);
- return 0;
+}
+static int rockchip_set_phy_state(struct phy *phy, bool enable) +{
- struct rockchip_dp_phy *dp = phy_get_drvdata(phy);
- if (enable) {
rockchip_dp_phy_clk_enable(dp);
writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_ON, dp->regs);
- } else {
rockchip_dp_phy_clk_disable(dp);
writel(DP_PHY_SIDDQ_WRITE_EN | DP_PHY_SIDDQ_OFF, dp->regs);
- }
- return 0;
+}
+static int rockchip_dp_phy_power_on(struct phy *phy) +{
- return rockchip_set_phy_state(phy, true);
+}
+static int rockchip_dp_phy_power_off(struct phy *phy) +{
- return rockchip_set_phy_state(phy, false);
+}
+static struct phy_ops rockchip_dp_phy_ops = {
- .power_on = rockchip_dp_phy_power_on,
- .power_off = rockchip_dp_phy_power_off,
- .owner = THIS_MODULE,
+};
+static int rockchip_dp_phy_init(struct rockchip_dp_phy *dp) +{
- struct device *dev = dp->dev;
- struct device_node *np = dev->of_node;
- int ret;
- dp->phy_24m = devm_clk_get(dev, "24m");
- if (IS_ERR(dp->phy_24m)) {
dev_err(dev, "cannot get clock 24m\n");
return PTR_ERR(dp->phy_24m);
- }
- ret = rockchip_dp_phy_clk_enable(dp);
- if (ret < 0) {
dev_err(dp->dev, "cannot enable dp phy clk %d\n", ret);
return ret;
- }
- dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
- if (IS_ERR(dp->grf)) {
dev_err(dev, "rk3288-dp needs rockchip,grf property\n");
return PTR_ERR(dp->grf);
- }
- ret = regmap_write(dp->grf, GRF_SOC_CON12,
GRF_EDP_REF_CLK_SEL_INTER |
(GRF_EDP_REF_CLK_SEL_INTER << 16));
- if (ret != 0) {
dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret);
return ret;
- }
This function can be split to do only clk_get and syscon_regmap_lookup in probe, clk_enable and regmap_write in phy_init?
Yeah, I agree with you to move DT property code to probe function, and I do find a bug that clk_enable should be remove from probe/phy_init function.
If clock have been enabled in probe function, then the reference count of this clock would never reach zero, cause phy_power_on always corresponding to phy_power_off.
So phy_init function would only have one expression regmap_write, it's redundant, let's just delete phy_init function, move all code to probe.
Thanks, - Yakir
------------------------------------------------------------------------------------------------ static int rockchip_dp_phy_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct phy_provider *phy_provider; struct rockchip_dp_phy *dp; struct resource *res; @@ -146,15 +112,31 @@ static int rockchip_dp_phy_probe(struct platform_device *pdev) if (IS_ERR(dp->regs)) return PTR_ERR(dp->regs);
- ret = rockchip_dp_phy_init(dp); - if (ret) + dp->phy_24m = devm_clk_get(dev, "24m"); + if (IS_ERR(dp->phy_24m)) { + dev_err(dev, "cannot get clock 24m\n"); + return PTR_ERR(dp->phy_24m); + } + + dp->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(dp->grf)) { + dev_err(dev, "rk3288-dp needs rockchip,grf property\n"); + return PTR_ERR(dp->grf); + } + + ret = regmap_write(dp->grf, GRF_SOC_CON12, GRF_EDP_REF_CLK_SEL_INTER | + (GRF_EDP_REF_CLK_SEL_INTER << 16)); + if (ret) { + dev_err(dp->dev, "Could not config GRF edp ref clk: %d\n", ret); return ret; + }
phy = devm_phy_create(dev, NULL, &rockchip_dp_phy_ops, NULL); if (IS_ERR(phy)) { dev_err(dev, "failed to create phy\n"); return PTR_ERR(phy); }
- return 0;
+}
+static int rockchip_dp_phy_probe(struct platform_device *pdev) +{
- struct device *dev = &pdev->dev;
- struct phy_provider *phy_provider;
- struct rockchip_dp_phy *dp;
- struct resource *res;
- struct phy *phy;
- int ret;
- dp = devm_kzalloc(dev, sizeof(*dp), GFP_KERNEL);
- if (IS_ERR(dp))
return -ENOMEM;
- dp->dev = dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dp->regs = devm_ioremap_resource(dev, res);
- if (IS_ERR(dp->regs))
return PTR_ERR(dp->regs);
- ret = rockchip_dp_phy_init(dp);
- if (ret)
return ret;
- phy = devm_phy_create(dev, NULL, &rockchip_dp_phy_ops, NULL);
- if (IS_ERR(phy)) {
dev_err(dev, "failed to create phy\n");
return PTR_ERR(phy);
- }
- phy_set_drvdata(phy, dp);
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- return PTR_ERR_OR_ZERO(phy_provider);
+}
+static const struct of_device_id rockchip_dp_phy_dt_ids[] = {
- { .compatible = "rockchip,rk3288-dp-phy" },
- {}
+};
+MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids);
+static struct platform_driver rockchip_dp_phy_driver = {
- .probe = rockchip_dp_phy_probe,
- .driver = {
.name = "rockchip-dp-phy",
.owner = THIS_MODULE,
owner is not required here.
Thanks Kishon
Hi Kishon,
On 08/20/2015 01:56 AM, Yakir Yang wrote:
Hi Kishon,
On 08/19/2015 11:40 PM, Kishon Vijay Abraham I wrote: [...]
[...] +MODULE_DEVICE_TABLE(of, rockchip_dp_phy_dt_ids);
+static struct platform_driver rockchip_dp_phy_driver = {
- .probe = rockchip_dp_phy_probe,
- .driver = {
.name = "rockchip-dp-phy",
.owner = THIS_MODULE,
owner is not required here.
Whoops, forget to reply this one.
Done.
- Yakir
Thanks Kishon
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: None Changes in v2: - Add GNU license v2 declared and samsung copyright
drivers/gpu/drm/exynos/analogix_dp-exynos.c | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 1 + include/drm/bridge/analogix_dp.h | 16 ++++++++++++++++ 3 files changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/exynos/analogix_dp-exynos.c b/drivers/gpu/drm/exynos/analogix_dp-exynos.c index 17da2c8..b160159 100644 --- a/drivers/gpu/drm/exynos/analogix_dp-exynos.c +++ b/drivers/gpu/drm/exynos/analogix_dp-exynos.c @@ -220,6 +220,7 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) dp->dev = dev; dp->drm_dev = drm_dev;
+ dp->plat_data.dev_type = EXYNOS_DP; dp->plat_data.power_on = exynos_dp_poweron; dp->plat_data.power_off = exynos_dp_poweroff; dp->plat_data.get_modes = exynos_dp_get_modes; diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index cebff9e..f2c5c26 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -267,6 +267,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, return ret; }
+ dp->plat_data.dev_type = RK3288_DP; dp->plat_data.attach = NULL; dp->plat_data.get_modes = NULL; dp->plat_data.power_on = rockchip_dp_poweron; diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index 8b4ffad..7209a64 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h @@ -1,9 +1,25 @@ +/* + * Analogix Core DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ #ifndef _ANALOGIX_DP_H_ #define _ANALOGIX_DP_H_
#include <drm/drm_crtc.h>
+enum analogix_dp_devtype { + EXYNOS_DP, + RK3288_DP, +}; + struct analogix_dp_plat_data { + enum analogix_dp_devtype dev_type; struct drm_panel *panel;
int (*power_on)(struct analogix_dp_plat_data *);
RK3288 need some special registers setting, we can separate them out by the dev_type of plat_data.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: None Changes in v2: - Fix compile failed dut to phy_pd_addr variable misspell error
drivers/gpu/drm/bridge/analogix_dp_reg.c | 76 ++++++++++++++++++++------------ drivers/gpu/drm/bridge/analogix_dp_reg.h | 12 +++++ 2 files changed, 60 insertions(+), 28 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix_dp_reg.c index cc5cdbf..a0fc1fb 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.c @@ -15,6 +15,8 @@ #include <linux/delay.h> #include <linux/gpio.h>
+#include <drm/bridge/analogix_dp.h> + #include "analogix_dp_core.h" #include "analogix_dp_reg.h"
@@ -72,6 +74,14 @@ void analogix_dp_init_analog_param(struct analogix_dp_device *dp) reg = SEL_24M | TX_DVDD_BIT_1_0625V; writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2);
+ if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) { + writel(REF_CLK_24M, dp->reg_base + ANALOGIX_DP_PLL_REG_1); + writel(0x95, dp->reg_base + ANALOGIX_DP_PLL_REG_2); + writel(0x40, dp->reg_base + ANALOGIX_DP_PLL_REG_3); + writel(0x58, dp->reg_base + ANALOGIX_DP_PLL_REG_4); + writel(0x22, dp->reg_base + ANALOGIX_DP_PLL_REG_5); + } + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3);
@@ -206,81 +216,85 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, bool enable) { u32 reg; + u32 phy_pd_addr = ANALOGIX_DP_PHY_PD; + + if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) + phy_pd_addr = ANALOGIX_DP_PD;
switch (block) { case AUX_BLOCK: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= AUX_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~AUX_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case CH0_BLOCK: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= CH0_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~CH0_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case CH1_BLOCK: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= CH1_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~CH1_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case CH2_BLOCK: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= CH2_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~CH2_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case CH3_BLOCK: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= CH3_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~CH3_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case ANALOG_TOTAL: if (enable) { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg |= DP_PHY_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg = readl(dp->reg_base + phy_pd_addr); reg &= ~DP_PHY_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } break; case POWER_ALL: if (enable) { reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | CH1_PD | CH0_PD; - writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(reg, dp->reg_base + phy_pd_addr); } else { - writel(0x00, dp->reg_base + ANALOGIX_DP_PHY_PD); + writel(0x00, dp->reg_base + phy_pd_addr); } break; default: @@ -399,8 +413,14 @@ void analogix_dp_init_aux(struct analogix_dp_device *dp) analogix_dp_reset_aux(dp);
/* Disable AUX transaction H/W retry */ - reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | - AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + if (dp->plat_data && (dp->plat_data->dev_type == RK3288_DP)) + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(0) | + AUX_HW_RETRY_COUNT_SEL(3) | + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + else + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | + AUX_HW_RETRY_COUNT_SEL(0) | + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL);
/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix_dp_reg.h index bed226f..e38af21 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.h @@ -22,6 +22,14 @@ #define ANALOGIX_DP_VIDEO_CTL_8 0x3C #define ANALOGIX_DP_VIDEO_CTL_10 0x44
+#define ANALOGIX_DP_PLL_REG_1 0xfc +#define ANALOGIX_DP_PLL_REG_2 0x9e4 +#define ANALOGIX_DP_PLL_REG_3 0x9e8 +#define ANALOGIX_DP_PLL_REG_4 0x9ec +#define ANALOGIX_DP_PLL_REG_5 0xa00 + +#define ANALOGIX_DP_PD 0x12c + #define ANALOGIX_DP_LANE_MAP 0x35C
#define ANALOGIX_DP_ANALOG_CTL_1 0x370 @@ -154,6 +162,10 @@ #define VSYNC_POLARITY_CFG (0x1 << 1) #define HSYNC_POLARITY_CFG (0x1 << 0)
+/* ANALOGIX_DP_PLL_REG_1 */ +#define REF_CLK_24M (0x1 << 1) +#define REF_CLK_27M (0x0 << 1) + /* ANALOGIX_DP_LANE_MAP */ #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) #define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
Some edp screen do not have hpd signal, so we can't just return failed when hpd plug in detect failed.
This is an hardware property, so we need add a devicetree property "analogix,need-force-hpd" to indicate this sutiation.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
Changes in v2: None
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 3 ++ .../bindings/video/analogix_dp-rockchip.txt | 1 + .../devicetree/bindings/video/exynos_dp.txt | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 36 +++++++++++++++++++--- drivers/gpu/drm/bridge/analogix_dp_core.h | 2 ++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 9 ++++++ 6 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt index 6127018..b043200 100644 --- a/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt +++ b/Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt @@ -40,6 +40,9 @@ Required properties for dp-controller: * Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt
Optional properties for dp-controller: + -analogix,need-force-hpd: + Indicate driver need force hpd when hpd detect failed, this + is used for some eDP screen which don't have hpd signal. -analogix,hpd-gpio: Hotplug detect GPIO. Indicates which GPIO should be used for hotplug diff --git a/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt b/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt index 99fd421..752005e 100644 --- a/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt +++ b/Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt @@ -27,6 +27,7 @@ For the below properties, please refer to Analogix DP binding document: - analogix,color-depth (required) - analogix,link-rate (required) - analogix,lane-count (required) +- analogix,need-force-hpd (optional) - analogix,hpd-gpio (optional) - video interfaces (optional) ------------------------------------------------------------------------------- diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt index 177506f..ba20416 100644 --- a/Documentation/devicetree/bindings/video/exynos_dp.txt +++ b/Documentation/devicetree/bindings/video/exynos_dp.txt @@ -53,6 +53,7 @@ For the below properties, please refer to Analogix DP binding document: -analogix,color-depth (required) -analogix,link-rate (required) -analogix,lane-count (required) + -analogix,need-force-hpd (optional) -analogix,hpd-gpio (optional) -video interfaces (optional) ------------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 1778e0a..99870f7 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -63,15 +63,38 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) { int timeout_loop = 0;
- while (analogix_dp_get_plug_in_status(dp) != 0) { + while (timeout_loop < DP_TIMEOUT_LOOP_COUNT) { + if (analogix_dp_get_plug_in_status(dp) == 0) + return 0; + timeout_loop++; - if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { - dev_err(dp->dev, "failed to get hpd plug status\n"); - return -ETIMEDOUT; - } usleep_range(10, 11); }
+ /* + * Some edp screen do not have hpd signal, so we can't just + * return failed when hpd plug in detect failed, DT property + * "need-force-hpd" would indicate whether driver need this. + */ + if (!dp->need_force_hpd) + return -ETIMEDOUT; + + /* + * The eDP TRM indicate that if HPD_STATUS(RO) is 0, AUX CH + * will not work, so we need to give a force hpd action to + * set HPD_STATUS manually. + */ + dev_dbg(dp->dev, "failed to get hpd plug status, try to force hpd\n"); + + analogix_dp_force_hpd(dp); + + if (analogix_dp_get_plug_in_status(dp) != 0) { + dev_err(dp->dev, "failed to get hpd plug in status\n"); + return -EINVAL; + } + + dev_dbg(dp->dev, "success to get plug in status after force hpd\n"); + return 0; }
@@ -1272,6 +1295,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, if (IS_ERR(dp->reg_base)) return PTR_ERR(dp->reg_base);
+ dp->need_force_hpd = + of_property_read_bool(dev->of_node, "analogix,need-force-hpd"); + dp->hpd_gpio = of_get_named_gpio(dev->of_node, "analogix,hpd-gpio", 0);
if (gpio_is_valid(dp->hpd_gpio)) { diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h index 941b34f..2405155 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -160,6 +160,7 @@ struct analogix_dp_device { struct phy *phy; int dpms_mode; int hpd_gpio; + bool need_force_hpd;
struct analogix_dp_plat_data *plat_data; }; @@ -180,6 +181,7 @@ void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, bool enable); void analogix_dp_init_analog_func(struct analogix_dp_device *dp); void analogix_dp_init_hpd(struct analogix_dp_device *dp); +void analogix_dp_force_hpd(struct analogix_dp_device *dp); enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp); void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp); void analogix_dp_reset_aux(struct analogix_dp_device *dp); diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix_dp_reg.c index a0fc1fb..bf7cee1 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.c @@ -365,6 +365,15 @@ void analogix_dp_init_hpd(struct analogix_dp_device *dp) writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); }
+void analogix_dp_force_hpd(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + reg = (F_HPD | HPD_CTRL); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); +} + enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) { u32 reg;
Some edp screen with no hpd signal would need some delay time to ensure that screen would be ready for work, so we can expand the delay time in hpd detect function, it works prefectly on my rk3288 sdk board.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: None Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 99870f7..75dd44a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -68,7 +68,7 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0;
timeout_loop++; - usleep_range(10, 11); + usleep_range(100, 110); }
/*
On 2015. 8. 19., at PM 11:52, Yakir Yang ykk@rock-chips.com wrote:
Some edp screen with no hpd signal would need some delay time to ensure that screen would be ready for work, so we can expand the delay time in hpd detect function, it works prefectly on my rk3288 sdk board.
Then, this delay has a dependency on the "rk3288 sdk" board. Also, if the delay time is expanded, the booting time of some Exybos boards will be increased unnecessarily. :-(
So, please add new DT property such as 'hpd-delay' that can be added to board DT files.
If there is not that DT property in DT files, the default value '10' will written to a variable such as 'unsigned int hpd_delay'. If there is the DT property in DT files, the delay value will written to the variable when parsing DT values and will be used in analogix_dp_detect_hpd().
What I want to say is that there should not be harmful effect on the existing Exynos boards, due to unrelated reasons.
Best regards, Jingoo Han
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3: None Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 99870f7..75dd44a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -68,7 +68,7 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0;
timeout_loop++;
usleep_range(10, 11);
usleep_range(100, 110);
}
/*
-- 1.9.1
Hi Jingoo,
On 08/20/2015 01:11 AM, Jingoo Han wrote:
On 2015. 8. 19., at PM 11:52, Yakir Yang ykk@rock-chips.com wrote:
Some edp screen with no hpd signal would need some delay time to ensure that screen would be ready for work, so we can expand the delay time in hpd detect function, it works prefectly on my rk3288 sdk board.
Then, this delay has a dependency on the "rk3288 sdk" board. Also, if the delay time is expanded, the booting time of some Exybos boards will be increased unnecessarily. :-(
So, please add new DT property such as 'hpd-delay' that can be added to board DT files.
If there is not that DT property in DT files, the default value '10' will written to a variable such as 'unsigned int hpd_delay'. If there is the DT property in DT files, the delay value will written to the variable when parsing DT values and will be used in analogix_dp_detect_hpd().
What I want to say is that there should not be harmful effect on the existing Exynos boards, due to unrelated reasons.
Yeah, you are right, I made an mistake here.
And I want to put this delay to "need-force-hpd" code, cause this property is for the no-hpd-signal eDP screen.
But strangely, with my this series, I don't need the expand delay any more, I am not sure which change improved this, I guess those delay time should come from drm core ?
Whatever seems we don't need this delay for now, and if I can find the exact reason and realize I still need this delay, I prefer to add those delay in "need-force-hpd" code.
Thanks, - Yakir
Best regards, Jingoo Han
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3: None Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 99870f7..75dd44a 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -68,7 +68,7 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0;
timeout_loop++;
usleep_range(10, 11);
usleep_range(100, 110);
}
/*
-- 1.9.1
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - move dp hpd detect to connector detect function.
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 75dd44a..052b9b3 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -915,12 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) DRM_ERROR("failed to disable the panel\n"); }
- ret = analogix_dp_detect_hpd(dp); - if (ret) { - /* Cable has been disconnected, we're done */ - return; - } - ret = analogix_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n"); @@ -953,6 +947,12 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) static enum drm_connector_status analogix_dp_detect( struct drm_connector *connector, bool force) { + struct analogix_dp_device *dp = connector_to_dp(connector); + + if (analogix_dp_detect_hpd(dp)) + /* Cable has been disconnected, we're done */ + return connector_status_disconnected; + return connector_status_connected; }
On 2015. 8. 19., at PM 11:52, Yakir Yang ykk@rock-chips.com wrote:
What is the reason to make this patch?
Please make commit message including the reason.
Best regards, Jingoo Han
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- move dp hpd detect to connector detect function.
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 75dd44a..052b9b3 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -915,12 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) DRM_ERROR("failed to disable the panel\n"); }
- ret = analogix_dp_detect_hpd(dp);
- if (ret) {
/* Cable has been disconnected, we're done */
return;
- }
- ret = analogix_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n");
@@ -953,6 +947,12 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) static enum drm_connector_status analogix_dp_detect( struct drm_connector *connector, bool force) {
- struct analogix_dp_device *dp = connector_to_dp(connector);
- if (analogix_dp_detect_hpd(dp))
/* Cable has been disconnected, we're done */
return connector_status_disconnected;
- return connector_status_connected;
}
-- 1.9.1
Hi Jingoo,
On 08/20/2015 02:49 AM, Jingoo Han wrote:
On 2015. 8. 19., at PM 11:52, Yakir Yang ykk@rock-chips.com wrote:
What is the reason to make this patch?
Please make commit message including the reason.
Okay, I think the below words would be okay :)
"This change just make a little clean to make code more like drm core expect, move hdp detect code from bridge->enable(), and place them into connector->detect()."
Thanks, - Yakir
Best regards, Jingoo Han
Signed-off-by: Yakir Yang ykk@rock-chips.com
Changes in v3:
- move dp hpd detect to connector detect function.
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 75dd44a..052b9b3 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -915,12 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) DRM_ERROR("failed to disable the panel\n"); }
- ret = analogix_dp_detect_hpd(dp);
- if (ret) {
/* Cable has been disconnected, we're done */
return;
- }
- ret = analogix_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n");
@@ -953,6 +947,12 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) static enum drm_connector_status analogix_dp_detect( struct drm_connector *connector, bool force) {
- struct analogix_dp_device *dp = connector_to_dp(connector);
- if (analogix_dp_detect_hpd(dp))
/* Cable has been disconnected, we're done */
return connector_status_disconnected;
- return connector_status_connected;
}
-- 1.9.1
Display Port monitor could support kinds of mode which indicate in monitor edid, not just one single display resolution which defined in panel or devivetree property display timing.
Signed-off-by: Yakir Yang ykk@rock-chips.com --- Changes in v3: - Add edid modes parse support
Changes in v2: None
drivers/gpu/drm/bridge/analogix_dp_core.c | 17 +++++++----- drivers/gpu/drm/bridge/analogix_dp_core.h | 45 ++++++++++++++++--------------- 2 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c index 052b9b3..83698c6 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -111,7 +111,7 @@ static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
static int analogix_dp_read_edid(struct analogix_dp_device *dp) { - unsigned char edid[EDID_BLOCK_LENGTH * 2]; + unsigned char *edid = dp->edid; unsigned int extend_block = 0; unsigned char sum; unsigned char test_vector; @@ -915,12 +915,6 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) DRM_ERROR("failed to disable the panel\n"); }
- ret = analogix_dp_handle_edid(dp); - if (ret) { - dev_err(dp->dev, "unable to handle edid\n"); - return; - } - ret = analogix_dp_set_link_train(dp, dp->video_info->max_lane_count, dp->video_info->max_link_rate); if (ret) { @@ -976,8 +970,17 @@ static int analogix_dp_get_modes(struct drm_connector *connector) { struct analogix_dp_device *dp = connector_to_dp(connector); struct analogix_dp_plat_data *plat_data = dp->plat_data; + struct edid *edid = (struct edid *)dp->edid; int num_modes = 0;
+ if (analogix_dp_handle_edid(dp)) { + dev_err(dp->dev, "unable to handle edid\n"); + return -EINVAL; + } + + drm_mode_connector_update_edid_property(connector, edid); + num_modes += drm_add_edid_modes(connector, edid); + if (plat_data && plat_data->panel) num_modes += drm_panel_get_modes(plat_data->panel);
diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h index 2405155..950b6ca 100644 --- a/drivers/gpu/drm/bridge/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -20,6 +20,28 @@ #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5
+/* I2C EDID Chip ID, Slave Address */ +#define I2C_EDID_DEVICE_ADDR 0x50 +#define I2C_E_EDID_DEVICE_ADDR 0x30 + +#define EDID_BLOCK_LENGTH 0x80 +#define EDID_HEADER_PATTERN 0x00 +#define EDID_EXTENSION_FLAG 0x7e +#define EDID_CHECKSUM 0x7f + +/* DP_MAX_LANE_COUNT */ +#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) +#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) + +/* DP_LANE_COUNT_SET */ +#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) + +/* DP_TRAINING_LANE0_SET */ +#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) +#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) +#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) +#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) + enum link_rate_type { LINK_RATE_1_62GBPS = DP_LINK_BW_1_62, LINK_RATE_2_70GBPS = DP_LINK_BW_2_7, @@ -161,6 +183,7 @@ struct analogix_dp_device { int dpms_mode; int hpd_gpio; bool need_force_hpd; + unsigned char edid[EDID_BLOCK_LENGTH * 2];
struct analogix_dp_plat_data *plat_data; }; @@ -260,26 +283,4 @@ void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
-/* I2C EDID Chip ID, Slave Address */ -#define I2C_EDID_DEVICE_ADDR 0x50 -#define I2C_E_EDID_DEVICE_ADDR 0x30 - -#define EDID_BLOCK_LENGTH 0x80 -#define EDID_HEADER_PATTERN 0x00 -#define EDID_EXTENSION_FLAG 0x7e -#define EDID_CHECKSUM 0x7f - -/* DP_MAX_LANE_COUNT */ -#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) -#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) - -/* DP_LANE_COUNT_SET */ -#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) - -/* DP_TRAINING_LANE0_SET */ -#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) -#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) -#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) -#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) - #endif /* _ANALOGIX_DP_CORE_H */
On 20 August 2015 at 00:48, Yakir Yang ykk@rock-chips.com wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
I'd like to pull this in, but it probably needs an ack from Samsung,
Inki can you guys find some time to test this?
Dave.
Hi Dave,
On 08/19/2015 06:54 PM, Dave Airlie wrote:
On 20 August 2015 at 00:48, Yakir Yang ykk@rock-chips.com wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
I'd like to pull this in, but it probably needs an ack from Samsung,
Inki can you guys find some time to test this?
Dave.
Wow, thanks a lots :-)
Still waiting for some reviews and acks.
Best regards, - Yakir
Hi,
On 08/19/2015 08:18 PM, Yakir Yang wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks,
- Yakir
Changes in v3:
- Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data.
- Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
- Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
- Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk".
- Take Heiko suggest, add devicetree binding document.
- Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node.
- Add the new function point analogix_dp_platdata.get_modes init.
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
- Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
- move dp hpd detect to connector detect function.
- Add edid modes parse support
Changes in v2:
- Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow:
- retval = exynos_dp_read_bytes_from_i2c(... ...)
- retval =
- exynos_dp_read_bytes_from_i2c(......);
- Take Jingoo Han suggest, just remove my name from author list.
- Take Jingoo Han suggest, remove new copyright
- Fix compiled failed dut to analogix_dp_device misspell
- Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver.
- Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
- Add GNU license v2 declared and samsung copyright
- Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c
Minor comment: Since there are a few files required for the driver, could you create a separate folder within drivers/gpu/drm/bridge?
Thanks, Archit
On 2015. 8. 20., at PM 1:29, Archit Taneja architt@codeaurora.org wrote:
Hi,
On 08/19/2015 08:18 PM, Yakir Yang wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks,
- Yakir
Changes in v3:
- Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data.
- Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
- Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
- Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk".
- Take Heiko suggest, add devicetree binding document.
- Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node.
- Add the new function point analogix_dp_platdata.get_modes init.
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
- Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
- move dp hpd detect to connector detect function.
- Add edid modes parse support
Changes in v2:
- Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow:
- retval = exynos_dp_read_bytes_from_i2c(... ...)
- retval =
- exynos_dp_read_bytes_from_i2c(......);
- Take Jingoo Han suggest, just remove my name from author list.
- Take Jingoo Han suggest, remove new copyright
- Fix compiled failed dut to analogix_dp_device misspell
- Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver.
- Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
- Add GNU license v2 declared and samsung copyright
- Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c
Minor comment: Since there are a few files required for the driver, could you create a separate folder within drivers/gpu/drm/bridge?
I agree on this opinion. Thank you.
Best regards, Jingoo Han
Thanks, Archit
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Hi Jingoo & Archit,
On 08/20/2015 12:54 AM, Jingoo Han wrote:
On 2015. 8. 20., at PM 1:29, Archit Taneja architt@codeaurora.org wrote:
Hi,
On 08/19/2015 08:18 PM, Yakir Yang wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks,
- Yakir
Changes in v3:
- Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data.
- Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
- Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
- Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk".
- Take Heiko suggest, add devicetree binding document.
- Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node.
- Add the new function point analogix_dp_platdata.get_modes init.
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
- Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
- move dp hpd detect to connector detect function.
- Add edid modes parse support
Changes in v2:
- Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow:
- retval = exynos_dp_read_bytes_from_i2c(... ...)
- retval =
- exynos_dp_read_bytes_from_i2c(......);
- Take Jingoo Han suggest, just remove my name from author list.
- Take Jingoo Han suggest, remove new copyright
- Fix compiled failed dut to analogix_dp_device misspell
- Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver.
- Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
- Add GNU license v2 declared and samsung copyright
- Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c
Minor comment: Since there are a few files required for the driver, could you create a separate folder within drivers/gpu/drm/bridge?
I agree on this opinion. Thank you.
Thanks for your comment ;)
Yeah, bridge/ have been add four new files for this driver, it would be better to collect into a separate folder.
I'm wondering should I just name the folder with "analogix_dp/", or we can make it more common (like "analogix/")? (personally I do like the last one)
Thanks, - Yakir
Best regards, Jingoo Han
Thanks, Archit
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
On 2015. 8. 20., at PM 3:23, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo & Archit,
On 08/20/2015 12:54 AM, Jingoo Han wrote:
On 2015. 8. 20., at PM 1:29, Archit Taneja architt@codeaurora.org wrote: Hi,
On 08/19/2015 08:18 PM, Yakir Yang wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks,
- Yakir
Changes in v3:
- Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data.
- Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
- Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
- Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk".
- Take Heiko suggest, add devicetree binding document.
- Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node.
- Add the new function point analogix_dp_platdata.get_modes init.
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
- Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
- move dp hpd detect to connector detect function.
- Add edid modes parse support
Changes in v2:
- Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow:
- retval = exynos_dp_read_bytes_from_i2c(... ...)
- retval =
- exynos_dp_read_bytes_from_i2c(......);
- Take Jingoo Han suggest, just remove my name from author list.
- Take Jingoo Han suggest, remove new copyright
- Fix compiled failed dut to analogix_dp_device misspell
- Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver.
- Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
- Add GNU license v2 declared and samsung copyright
- Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c
Minor comment: Since there are a few files required for the driver, could you create a separate folder within drivers/gpu/drm/bridge?
I agree on this opinion. Thank you.
Thanks for your comment ;)
Yeah, bridge/ have been add four new files for this driver, it would be better to collect into a separate folder.
I'm wondering should I just name the folder with "analogix_dp/", or we can make it more common (like "analogix/")? (personally I do like the last one)
I prefer "analogix".
Best regards, Jingoo Han
Thanks,
- Yakir
Best regards, Jingoo Han
Thanks, Archit
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Hi Jingoo,
On 08/20/2015 01:55 AM, Jingoo Han wrote:
On 2015. 8. 20., at PM 3:23, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo & Archit,
On 08/20/2015 12:54 AM, Jingoo Han wrote:
On 2015. 8. 20., at PM 1:29, Archit Taneja architt@codeaurora.org wrote: Hi,
On 08/19/2015 08:18 PM, Yakir Yang wrote:
Hi all, The Samsung Exynos eDP controller and Rockchip RK3288 eDP controller share the same IP, so a lot of parts can be re-used. I split the common code into bridge directory, then rk3288 and exynos only need to keep some platform code. Cause I can't find the exact IP name of exynos dp controller, so I decide to name dp core driver with "analogix" which I find in rk3288 eDP TRM ;)
Beyond that, there are three light registers setting differents bewteen exynos and rk3288.
- RK3288 have five special pll resigters which not indicata in exynos dp controller.
- The address of DP_PHY_PD(dp phy power manager register) are different between rk3288 and exynos.
- Rk3288 and exynos have different setting with AUX_HW_RETRY_CTL(dp debug register).
I have verified this series on two kinds of rockchip platform board, one is rk3288 sdk board which connect with a 2K display port monitor, the other is google jerry chromebook which connect with a eDP screen "cnm,n116bgeea2", both of them works rightlly.
I haven't verified the dp function on samsung platform, cause I haven't got exynos boards. I can only ensure that there are no build error on samsung platform, wish some samsung guys help to test. ;)
Thanks,
- Yakir
Changes in v3:
- Take Thierry Reding suggest, move exynos's video_timing code to analogix_dp-exynos platform driver, add get_modes method to struct analogix_dp_plat_data.
- Take Heiko suggest, rename some "samsung*" dts propery to "analogix*".
- Take Thierry Reding suggest, dynamic parse video timing info from struct drm_display_mode and struct drm_display_info.
- Take Thierry Reding suggest, link_rate and lane_count shouldn't config to the DT property value directly, but we can take those as hardware limite. For example, RK3288 only support 4 physical lanes of 2.7/1.62 Gbps/lane, so DT property would like "link-rate = 0x0a" "lane-count = 4".
- Take Heiko suggest, add devicetree binding documents.
- Take Thierry Reding suggest, remove sync pol & colorimetry properies from the new analogix dp driver devicetree binding.
- Update the exist exynos dtsi file with the latest DP DT properies.
- Take Thierry Reding and Heiko suggest, leave "sclk_edp_24m" to rockchip dp phy driver which name to "24m", and leave "sclk_edp" to analogix dp core driver which name to "dp", and leave "pclk_edp" to rockchip dp platform driver which name to "pclk".
- Take Heiko suggest, add devicetree binding document.
- Take Heiko suggest, remove "rockchip,panel" DT property, take use of remote point to get panel node.
- Add the new function point analogix_dp_platdata.get_modes init.
- Take Heiko suggest, add rockchip dp phy driver, collect the phy clocks and power control.
- Add "analogix,need-force-hpd" to indicate whether driver need foce hpd when hpd detect failed.
- move dp hpd detect to connector detect function.
- Add edid modes parse support
Changes in v2:
- Take Joe Preches advise, improved commit message more readable, and avoid using some uncommon style like bellow:
- retval = exynos_dp_read_bytes_from_i2c(... ...)
- retval =
- exynos_dp_read_bytes_from_i2c(......);
- Take Jingoo Han suggest, just remove my name from author list.
- Take Jingoo Han suggest, remove new copyright
- Fix compiled failed dut to analogix_dp_device misspell
- Take Heiko suggest, get panel node with remote-endpoint method, and create devicetree binding for driver.
- Remove the clock enable/disbale with "sclk_edp" & "sclk_edp_24m", leave those clock to rockchip dp phy driver.
- Add GNU license v2 declared and samsung copyright
- Fix compile failed dut to phy_pd_addr variable misspell error
Yakir Yang (14): drm: exynos/dp: fix code style drm: exynos/dp: convert to drm bridge mode drm: bridge: analogix_dp: split exynos dp driver to bridge dir drm: bridge/analogix_dp: dynamic parse sync_pol & interlace & colorimetry drm: bridge/analogix_dp: fix link_rate & lane_count bug Documentation: drm/bridge: add document for analogix_dp drm: rockchip/dp: add rockchip platform dp driver phy: Add driver for rockchip Display Port PHY drm: bridge/analogix_dp: add platform device type support drm: bridge: analogix_dp: add some rk3288 special registers setting drm: bridge: analogix_dp: try force hpd after plug in lookup failed drm: bridge/analogix_dp: expand the delay time for hpd detect drm: bridge/analogix_dp: move hpd detect to connector detect function drm: bridge/analogix_dp: add edid modes parse in get_modes method
.../devicetree/bindings/drm/bridge/analogix_dp.txt | 73 + .../devicetree/bindings/phy/rockchip-dp-phy.txt | 26 + .../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++ drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c
Minor comment: Since there are a few files required for the driver, could you create a separate folder within drivers/gpu/drm/bridge?
I agree on this opinion. Thank you.
Thanks for your comment ;)
Yeah, bridge/ have been add four new files for this driver, it would be better to collect into a separate folder.
I'm wondering should I just name the folder with "analogix_dp/", or we can make it more common (like "analogix/")? (personally I do like the last one)
I prefer "analogix".
Okay :)
- Yakir
Best regards, Jingoo Han
Thanks,
- Yakir
Best regards, Jingoo Han
Thanks, Archit
-- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Best regards, Jingoo Han
drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (62%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c create mode 100644 drivers/phy/phy-rockchip-dp.c create mode 100644 include/drm/bridge/analogix_dp.h
-- 1.9.1
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case. Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ls drivers/gpu/drm/imx/ dw_hdmi-imx.c imx-drm.h imx-tve.c ipuv3-plane.c Kconfig parallel-display.c
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ls drivers/mmc/host/dw_mmc* drivers/mmc/host/dw_mmc.c drivers/mmc/host/dw_mmc.h drivers/mmc/host/dw_mmc-pci.c drivers/mmc/host/dw_mmc-pltfm.h drivers/mmc/host/dw_mmc-exynos.c drivers/mmc/host/dw_mmc-k3.c drivers/mmc/host/dw_mmc-pltfm.c drivers/mmc/host/dw_mmc-rockchip.c
Thanks, - Yakir
Best regards, Jingoo Han
drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (62%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c create mode 100644 drivers/phy/phy-rockchip-dp.c create mode 100644 include/drm/bridge/analogix_dp.h
-- 1.9.1
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use "IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Best regards, Jingoo Han
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ ls drivers/gpu/drm/imx/ dw_hdmi-imx.c imx-drm.h imx-tve.c ipuv3-plane.c Kconfig parallel-display.c
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ ls drivers/mmc/host/dw_mmc* drivers/mmc/host/dw_mmc.c drivers/mmc/host/dw_mmc.h drivers/mmc/host/dw_mmc-pci.c drivers/mmc/host/dw_mmc-pltfm.h drivers/mmc/host/dw_mmc-exynos.c drivers/mmc/host/dw_mmc-k3.c drivers/mmc/host/dw_mmc-pltfm.c drivers/mmc/host/dw_mmc-rockchip.c
Thanks,
- Yakir
Best regards, Jingoo Han
drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (62%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c create mode 100644 drivers/phy/phy-rockchip-dp.c create mode 100644 include/drm/bridge/analogix_dp.h
-- 1.9.1
On Fri, Aug 21, 2015 at 08:24:16PM +0900, Jingoo Han wrote:
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use "IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Exynos DRM maintainers get to pick their filenames, so Yakir, please rename as Jingoo suggested.
Even if you didn't the first thing that would go into the Exynos DRM driver tree after this is merged is a rename patch anyway.
Thierry
Hi Thierry,
2015-08-21 9:16 GMT-04:00 Thierry Reding treding@nvidia.com:
On Fri, Aug 21, 2015 at 08:24:16PM +0900, Jingoo Han wrote:
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382
+++++++++++++++++++
drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294
++++++++++++++++++
.../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as
dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use
"IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Exynos DRM maintainers get to pick their filenames, so Yakir, please rename as Jingoo suggested.
Even if you didn't the first thing that would go into the Exynos DRM driver tree after this is merged is a rename patch anyway.
Okay, thanks for your remind ;)
- Yakir
Thierry
Linux-rockchip mailing list Linux-rockchip@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-rockchip
Hi,
Could you rebase your serie onto linux-next or 4.2-rc8 ? it does not apply here...
Regards, Romain
2015-08-21 15:16 GMT+02:00 Thierry Reding treding@nvidia.com:
On Fri, Aug 21, 2015 at 08:24:16PM +0900, Jingoo Han wrote:
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use "IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Exynos DRM maintainers get to pick their filenames, so Yakir, please rename as Jingoo suggested.
Even if you didn't the first thing that would go into the Exynos DRM driver tree after this is merged is a rename patch anyway.
Thierry
Hi Romain,
在 08/30/2015 08:16 PM, Romain Perier 写道:
Hi,
Could you rebase your serie onto linux-next or 4.2-rc8 ? it does not apply here...
Thanks for try to applied, and feel sorry for that failed.
This v3 series was rebased on github.com/torvalds/linux.git, so I should rebase on kernel/next/linux-next.git when I'm preparing v4 series.
Thanks, - Yakir
Regards, Romain
2015-08-21 15:16 GMT+02:00 Thierry Reding treding@nvidia.com:
On Fri, Aug 21, 2015 at 08:24:16PM +0900, Jingoo Han wrote:
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use "IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Exynos DRM maintainers get to pick their filenames, so Yakir, please rename as Jingoo suggested.
Even if you didn't the first thing that would go into the Exynos DRM driver tree after this is merged is a rename patch anyway.
Thierry
Hi Jingoo,
2015-08-21 7:24 GMT-04:00 Jingoo Han jingoohan1@gmail.com:
On 2015. 8. 21., at PM 7:01, Yakir Yang ykk@rock-chips.com wrote:
Hi Jingoo,
在 2015/8/21 16:20, Jingoo Han 写道:
On 2015. 8. 19., at PM 11:48, Yakir Yang ykk@rock-chips.com ykk@rock-chips.com wrote:
.....
.../bindings/video/analogix_dp-rockchip.txt | 83 ++ .../devicetree/bindings/video/exynos_dp.txt | 51 +- arch/arm/boot/dts/exynos5250-arndale.dts | 10 +- arch/arm/boot/dts/exynos5250-smdk5250.dts | 10 +- arch/arm/boot/dts/exynos5250-snow.dts | 12 +- arch/arm/boot/dts/exynos5250-spring.dts | 12 +- arch/arm/boot/dts/exynos5420-peach-pit.dts | 12 +- arch/arm/boot/dts/exynos5420-smdk5420.dts | 10 +- arch/arm/boot/dts/exynos5800-peach-pi.dts | 12 +- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + drivers/gpu/drm/bridge/analogix_dp_core.c | 1382 +++++++++++++++++++ drivers/gpu/drm/bridge/analogix_dp_core.h | 286 ++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1294 ++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 270 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 347 +++++
Would you change this file name to "exynos_dp.c"?
Sorry, I don't think so ;(
I think IP_name+Soc_name would be better in this re-use case.
So? Is there the naming rule such as "IP_name+SoC_name"?
Beside I see there are lots of driver named with this format in kernel, such as dw_hdmi & dw_mmc
Please look at other dw cases. For example, look at dw_pcie.
drivers/pci/host/ pcie-designware.c pci-spear13xx.c pci-exynos.c
In this case, pci-spear13xx.c and pci-exynos.c do not use "IP_name+SoC_name", even though these are dw IPs.
Also, naming consistency is more important. Now, Exynos DRM files are using "exynos_drm_" prefix.
drivers/gpu/drm/exynos/ exynos_drm_buf.c exynos_drm_core.c ....
However, "analogix_dp-exynos.c" looks very inconsistent.
If there is no strict naming rule, please use "exynos_dp.c" or "exynos_drm_dp.c".
Sorry for the delay :-)
Okay, it is little bit inconsistent, but I just want to make the IP name more clearly.
Anyway I should follow your suggest with “exynos_*” style for now, so done, I would change the filename to "exynos_dp.c" ;)
Thanks, - Yakir
Best regards, Jingoo Han
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ ls drivers/gpu/drm/imx/ dw_hdmi-imx.c imx-drm.h imx-tve.c ipuv3-plane.c Kconfig parallel-display.c
(cr) (chromeos-3.14) yakir@server ~/trunk/src/third_party/kernel/v3.14 $ ls drivers/mmc/host/dw_mmc* drivers/mmc/host/dw_mmc.c drivers/mmc/host/dw_mmc.h drivers/mmc/host/dw_mmc-pci.c drivers/mmc/host/dw_mmc-pltfm.h drivers/mmc/host/dw_mmc-exynos.c drivers/mmc/host/dw_mmc-k3.c drivers/mmc/host/dw_mmc-pltfm.c drivers/mmc/host/dw_mmc-rockchip.c
Thanks,
- Yakir
Best regards, Jingoo Han
drivers/gpu/drm/exynos/exynos_dp_core.c | 1416 -------------------- drivers/gpu/drm/exynos/exynos_dp_core.h | 282 ---- drivers/gpu/drm/exynos/exynos_dp_reg.c | 1263 ----------------- drivers/gpu/drm/rockchip/Kconfig | 9 + drivers/gpu/drm/rockchip/Makefile | 1 + drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 390 ++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-rockchip-dp.c | 185 +++ include/drm/bridge/analogix_dp.h | 40 + 30 files changed, 4325 insertions(+), 3172 deletions(-) create mode 100644 Documentation/devicetree/bindings/drm/bridge/analogix_dp.txt create mode 100644 Documentation/devicetree/bindings/phy/rockchip-dp-phy.txt create mode 100644 Documentation/devicetree/bindings/video/analogix_dp-rockchip.txt create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.c create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (62%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c create mode 100644 drivers/gpu/drm/rockchip/analogix_dp-rockchip.c create mode 100644 drivers/phy/phy-rockchip-dp.c create mode 100644 include/drm/bridge/analogix_dp.h
-- 1.9.1
dri-devel@lists.freedesktop.org