.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright(c) 2016, Analogix Semiconductor. |
---|
3 | 4 | * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 and |
---|
6 | | - * only version 2 as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | | - * |
---|
13 | 5 | * Based on anx7808 driver obtained from chromeos with copyright: |
---|
14 | 6 | * Copyright(c) 2013, Google Inc. |
---|
15 | | - * |
---|
16 | 7 | */ |
---|
17 | 8 | #include <linux/delay.h> |
---|
18 | 9 | #include <linux/err.h> |
---|
19 | | -#include <linux/interrupt.h> |
---|
| 10 | +#include <linux/gpio/consumer.h> |
---|
20 | 11 | #include <linux/i2c.h> |
---|
| 12 | +#include <linux/interrupt.h> |
---|
21 | 13 | #include <linux/kernel.h> |
---|
22 | 14 | #include <linux/module.h> |
---|
23 | | -#include <linux/of_gpio.h> |
---|
24 | 15 | #include <linux/of_irq.h> |
---|
25 | 16 | #include <linux/of_platform.h> |
---|
26 | 17 | #include <linux/regmap.h> |
---|
27 | | -#include <linux/types.h> |
---|
28 | | -#include <linux/gpio/consumer.h> |
---|
29 | 18 | #include <linux/regulator/consumer.h> |
---|
| 19 | +#include <linux/types.h> |
---|
30 | 20 | |
---|
31 | | -#include <drm/drmP.h> |
---|
32 | 21 | #include <drm/drm_atomic_helper.h> |
---|
| 22 | +#include <drm/drm_bridge.h> |
---|
33 | 23 | #include <drm/drm_crtc.h> |
---|
34 | | -#include <drm/drm_crtc_helper.h> |
---|
35 | 24 | #include <drm/drm_dp_helper.h> |
---|
36 | 25 | #include <drm/drm_edid.h> |
---|
| 26 | +#include <drm/drm_print.h> |
---|
| 27 | +#include <drm/drm_probe_helper.h> |
---|
37 | 28 | |
---|
38 | 29 | #include "analogix-anx78xx.h" |
---|
39 | 30 | |
---|
.. | .. |
---|
46 | 37 | |
---|
47 | 38 | #define XTAL_CLK 270 /* 27M */ |
---|
48 | 39 | |
---|
49 | | -static const u8 anx78xx_i2c_addresses[] = { |
---|
50 | | - [I2C_IDX_TX_P0] = TX_P0, |
---|
51 | | - [I2C_IDX_TX_P1] = TX_P1, |
---|
52 | | - [I2C_IDX_TX_P2] = TX_P2, |
---|
53 | | - [I2C_IDX_RX_P0] = RX_P0, |
---|
54 | | - [I2C_IDX_RX_P1] = RX_P1, |
---|
| 40 | +static const u8 anx7808_i2c_addresses[] = { |
---|
| 41 | + [I2C_IDX_TX_P0] = 0x78, |
---|
| 42 | + [I2C_IDX_TX_P1] = 0x7a, |
---|
| 43 | + [I2C_IDX_TX_P2] = 0x72, |
---|
| 44 | + [I2C_IDX_RX_P0] = 0x7e, |
---|
| 45 | + [I2C_IDX_RX_P1] = 0x80, |
---|
| 46 | +}; |
---|
| 47 | + |
---|
| 48 | +static const u8 anx781x_i2c_addresses[] = { |
---|
| 49 | + [I2C_IDX_TX_P0] = 0x70, |
---|
| 50 | + [I2C_IDX_TX_P1] = 0x7a, |
---|
| 51 | + [I2C_IDX_TX_P2] = 0x72, |
---|
| 52 | + [I2C_IDX_RX_P0] = 0x7e, |
---|
| 53 | + [I2C_IDX_RX_P1] = 0x80, |
---|
55 | 54 | }; |
---|
56 | 55 | |
---|
57 | 56 | struct anx78xx_platform_data { |
---|
.. | .. |
---|
70 | 69 | struct i2c_client *client; |
---|
71 | 70 | struct edid *edid; |
---|
72 | 71 | struct drm_connector connector; |
---|
73 | | - struct drm_dp_link link; |
---|
74 | 72 | struct anx78xx_platform_data pdata; |
---|
75 | 73 | struct mutex lock; |
---|
76 | 74 | |
---|
.. | .. |
---|
111 | 109 | struct drm_dp_aux_msg *msg) |
---|
112 | 110 | { |
---|
113 | 111 | struct anx78xx *anx78xx = container_of(aux, struct anx78xx, aux); |
---|
114 | | - return anx_aux_transfer(anx78xx->map[I2C_IDX_TX_P0], msg); |
---|
| 112 | + return anx_dp_aux_transfer(anx78xx->map[I2C_IDX_TX_P0], msg); |
---|
115 | 113 | } |
---|
116 | 114 | |
---|
117 | 115 | static int anx78xx_set_hpd(struct anx78xx *anx78xx) |
---|
.. | .. |
---|
581 | 579 | /* 1.0V digital core power regulator */ |
---|
582 | 580 | pdata->dvdd10 = devm_regulator_get(dev, "dvdd10"); |
---|
583 | 581 | if (IS_ERR(pdata->dvdd10)) { |
---|
584 | | - DRM_ERROR("DVDD10 regulator not found\n"); |
---|
| 582 | + if (PTR_ERR(pdata->dvdd10) != -EPROBE_DEFER) |
---|
| 583 | + DRM_ERROR("DVDD10 regulator not found\n"); |
---|
| 584 | + |
---|
585 | 585 | return PTR_ERR(pdata->dvdd10); |
---|
586 | 586 | } |
---|
587 | 587 | |
---|
.. | .. |
---|
603 | 603 | |
---|
604 | 604 | static int anx78xx_dp_link_training(struct anx78xx *anx78xx) |
---|
605 | 605 | { |
---|
606 | | - u8 dp_bw, value; |
---|
| 606 | + u8 dp_bw, dpcd[2]; |
---|
607 | 607 | int err; |
---|
608 | 608 | |
---|
609 | 609 | err = regmap_write(anx78xx->map[I2C_IDX_RX_P0], SP_HDMI_MUTE_CTRL_REG, |
---|
.. | .. |
---|
656 | 656 | if (err) |
---|
657 | 657 | return err; |
---|
658 | 658 | |
---|
659 | | - /* Check link capabilities */ |
---|
660 | | - err = drm_dp_link_probe(&anx78xx->aux, &anx78xx->link); |
---|
661 | | - if (err < 0) { |
---|
662 | | - DRM_ERROR("Failed to probe link capabilities: %d\n", err); |
---|
663 | | - return err; |
---|
664 | | - } |
---|
| 659 | + /* |
---|
| 660 | + * Power up the sink (DP_SET_POWER register is only available on DPCD |
---|
| 661 | + * v1.1 and later). |
---|
| 662 | + */ |
---|
| 663 | + if (anx78xx->dpcd[DP_DPCD_REV] >= 0x11) { |
---|
| 664 | + err = drm_dp_dpcd_readb(&anx78xx->aux, DP_SET_POWER, &dpcd[0]); |
---|
| 665 | + if (err < 0) { |
---|
| 666 | + DRM_ERROR("Failed to read DP_SET_POWER register: %d\n", |
---|
| 667 | + err); |
---|
| 668 | + return err; |
---|
| 669 | + } |
---|
665 | 670 | |
---|
666 | | - /* Power up the sink */ |
---|
667 | | - err = drm_dp_link_power_up(&anx78xx->aux, &anx78xx->link); |
---|
668 | | - if (err < 0) { |
---|
669 | | - DRM_ERROR("Failed to power up DisplayPort link: %d\n", err); |
---|
670 | | - return err; |
---|
| 671 | + dpcd[0] &= ~DP_SET_POWER_MASK; |
---|
| 672 | + dpcd[0] |= DP_SET_POWER_D0; |
---|
| 673 | + |
---|
| 674 | + err = drm_dp_dpcd_writeb(&anx78xx->aux, DP_SET_POWER, dpcd[0]); |
---|
| 675 | + if (err < 0) { |
---|
| 676 | + DRM_ERROR("Failed to power up DisplayPort link: %d\n", |
---|
| 677 | + err); |
---|
| 678 | + return err; |
---|
| 679 | + } |
---|
| 680 | + |
---|
| 681 | + /* |
---|
| 682 | + * According to the DP 1.1 specification, a "Sink Device must |
---|
| 683 | + * exit the power saving state within 1 ms" (Section 2.5.3.1, |
---|
| 684 | + * Table 5-52, "Sink Control Field" (register 0x600). |
---|
| 685 | + */ |
---|
| 686 | + usleep_range(1000, 2000); |
---|
671 | 687 | } |
---|
672 | 688 | |
---|
673 | 689 | /* Possibly enable downspread on the sink */ |
---|
.. | .. |
---|
706 | 722 | if (err) |
---|
707 | 723 | return err; |
---|
708 | 724 | |
---|
709 | | - value = drm_dp_link_rate_to_bw_code(anx78xx->link.rate); |
---|
710 | 725 | err = regmap_write(anx78xx->map[I2C_IDX_TX_P0], |
---|
711 | | - SP_DP_MAIN_LINK_BW_SET_REG, value); |
---|
| 726 | + SP_DP_MAIN_LINK_BW_SET_REG, |
---|
| 727 | + anx78xx->dpcd[DP_MAX_LINK_RATE]); |
---|
712 | 728 | if (err) |
---|
713 | 729 | return err; |
---|
714 | 730 | |
---|
715 | | - err = drm_dp_link_configure(&anx78xx->aux, &anx78xx->link); |
---|
| 731 | + dpcd[1] = drm_dp_max_lane_count(anx78xx->dpcd); |
---|
| 732 | + |
---|
| 733 | + if (drm_dp_enhanced_frame_cap(anx78xx->dpcd)) |
---|
| 734 | + dpcd[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
---|
| 735 | + |
---|
| 736 | + err = drm_dp_dpcd_write(&anx78xx->aux, DP_LINK_BW_SET, dpcd, |
---|
| 737 | + sizeof(dpcd)); |
---|
716 | 738 | if (err < 0) { |
---|
717 | | - DRM_ERROR("Failed to configure DisplayPort link: %d\n", err); |
---|
| 739 | + DRM_ERROR("Failed to configure link: %d\n", err); |
---|
718 | 740 | return err; |
---|
719 | 741 | } |
---|
720 | 742 | |
---|
.. | .. |
---|
825 | 847 | goto unlock; |
---|
826 | 848 | } |
---|
827 | 849 | |
---|
828 | | - err = drm_mode_connector_update_edid_property(connector, |
---|
829 | | - anx78xx->edid); |
---|
| 850 | + err = drm_connector_update_edid_property(connector, |
---|
| 851 | + anx78xx->edid); |
---|
830 | 852 | if (err) { |
---|
831 | 853 | DRM_ERROR("Failed to update EDID property: %d\n", err); |
---|
832 | 854 | goto unlock; |
---|
833 | 855 | } |
---|
834 | 856 | |
---|
835 | 857 | num_modes = drm_add_edid_modes(connector, anx78xx->edid); |
---|
836 | | - /* Store the ELD */ |
---|
837 | | - drm_edid_to_eld(connector, anx78xx->edid); |
---|
838 | 858 | |
---|
839 | 859 | unlock: |
---|
840 | 860 | mutex_unlock(&anx78xx->lock); |
---|
.. | .. |
---|
857 | 877 | return connector_status_connected; |
---|
858 | 878 | } |
---|
859 | 879 | |
---|
860 | | -static void anx78xx_connector_destroy(struct drm_connector *connector) |
---|
861 | | -{ |
---|
862 | | - drm_connector_cleanup(connector); |
---|
863 | | -} |
---|
864 | | - |
---|
865 | 880 | static const struct drm_connector_funcs anx78xx_connector_funcs = { |
---|
866 | | - .dpms = drm_atomic_helper_connector_dpms, |
---|
867 | 881 | .fill_modes = drm_helper_probe_single_connector_modes, |
---|
868 | 882 | .detect = anx78xx_detect, |
---|
869 | | - .destroy = anx78xx_connector_destroy, |
---|
| 883 | + .destroy = drm_connector_cleanup, |
---|
870 | 884 | .reset = drm_atomic_helper_connector_reset, |
---|
871 | 885 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
---|
872 | 886 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
---|
873 | 887 | }; |
---|
874 | 888 | |
---|
875 | | -static int anx78xx_bridge_attach(struct drm_bridge *bridge) |
---|
| 889 | +static int anx78xx_bridge_attach(struct drm_bridge *bridge, |
---|
| 890 | + enum drm_bridge_attach_flags flags) |
---|
876 | 891 | { |
---|
877 | 892 | struct anx78xx *anx78xx = bridge_to_anx78xx(bridge); |
---|
878 | 893 | int err; |
---|
| 894 | + |
---|
| 895 | + if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) { |
---|
| 896 | + DRM_ERROR("Fix bridge driver to make connector optional!"); |
---|
| 897 | + return -EINVAL; |
---|
| 898 | + } |
---|
879 | 899 | |
---|
880 | 900 | if (!bridge->encoder) { |
---|
881 | 901 | DRM_ERROR("Parent encoder object not found"); |
---|
.. | .. |
---|
912 | 932 | |
---|
913 | 933 | anx78xx->connector.polled = DRM_CONNECTOR_POLL_HPD; |
---|
914 | 934 | |
---|
915 | | - err = drm_mode_connector_attach_encoder(&anx78xx->connector, |
---|
916 | | - bridge->encoder); |
---|
| 935 | + err = drm_connector_attach_encoder(&anx78xx->connector, |
---|
| 936 | + bridge->encoder); |
---|
917 | 937 | if (err) { |
---|
918 | 938 | DRM_ERROR("Failed to link up connector to encoder: %d\n", err); |
---|
919 | 939 | return err; |
---|
.. | .. |
---|
924 | 944 | |
---|
925 | 945 | static enum drm_mode_status |
---|
926 | 946 | anx78xx_bridge_mode_valid(struct drm_bridge *bridge, |
---|
| 947 | + const struct drm_display_info *info, |
---|
927 | 948 | const struct drm_display_mode *mode) |
---|
928 | 949 | { |
---|
929 | 950 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
---|
.. | .. |
---|
946 | 967 | } |
---|
947 | 968 | |
---|
948 | 969 | static void anx78xx_bridge_mode_set(struct drm_bridge *bridge, |
---|
949 | | - struct drm_display_mode *mode, |
---|
950 | | - struct drm_display_mode *adjusted_mode) |
---|
| 970 | + const struct drm_display_mode *mode, |
---|
| 971 | + const struct drm_display_mode *adjusted_mode) |
---|
951 | 972 | { |
---|
952 | 973 | struct anx78xx *anx78xx = bridge_to_anx78xx(bridge); |
---|
953 | 974 | struct hdmi_avi_infoframe frame; |
---|
.. | .. |
---|
958 | 979 | |
---|
959 | 980 | mutex_lock(&anx78xx->lock); |
---|
960 | 981 | |
---|
961 | | - err = drm_hdmi_avi_infoframe_from_display_mode(&frame, adjusted_mode); |
---|
| 982 | + err = drm_hdmi_avi_infoframe_from_display_mode(&frame, |
---|
| 983 | + &anx78xx->connector, |
---|
| 984 | + adjusted_mode); |
---|
962 | 985 | if (err) { |
---|
963 | 986 | DRM_ERROR("Failed to setup AVI infoframe: %d\n", err); |
---|
964 | 987 | goto unlock; |
---|
.. | .. |
---|
1173 | 1196 | }; |
---|
1174 | 1197 | |
---|
1175 | 1198 | static const u16 anx78xx_chipid_list[] = { |
---|
| 1199 | + 0x7808, |
---|
1176 | 1200 | 0x7812, |
---|
1177 | 1201 | 0x7814, |
---|
1178 | 1202 | 0x7818, |
---|
.. | .. |
---|
1184 | 1208 | struct anx78xx *anx78xx; |
---|
1185 | 1209 | struct anx78xx_platform_data *pdata; |
---|
1186 | 1210 | unsigned int i, idl, idh, version; |
---|
| 1211 | + const u8 *i2c_addresses; |
---|
1187 | 1212 | bool found = false; |
---|
1188 | 1213 | int err; |
---|
1189 | 1214 | |
---|
.. | .. |
---|
1204 | 1229 | |
---|
1205 | 1230 | err = anx78xx_init_pdata(anx78xx); |
---|
1206 | 1231 | if (err) { |
---|
1207 | | - DRM_ERROR("Failed to initialize pdata: %d\n", err); |
---|
| 1232 | + if (err != -EPROBE_DEFER) |
---|
| 1233 | + DRM_ERROR("Failed to initialize pdata: %d\n", err); |
---|
| 1234 | + |
---|
1208 | 1235 | return err; |
---|
1209 | 1236 | } |
---|
1210 | 1237 | |
---|
.. | .. |
---|
1221 | 1248 | } |
---|
1222 | 1249 | |
---|
1223 | 1250 | /* Map slave addresses of ANX7814 */ |
---|
| 1251 | + i2c_addresses = device_get_match_data(&client->dev); |
---|
1224 | 1252 | for (i = 0; i < I2C_NUM_ADDRESSES; i++) { |
---|
1225 | | - anx78xx->i2c_dummy[i] = i2c_new_dummy(client->adapter, |
---|
1226 | | - anx78xx_i2c_addresses[i] >> 1); |
---|
1227 | | - if (!anx78xx->i2c_dummy[i]) { |
---|
1228 | | - err = -ENOMEM; |
---|
1229 | | - DRM_ERROR("Failed to reserve I2C bus %02x\n", |
---|
1230 | | - anx78xx_i2c_addresses[i]); |
---|
| 1253 | + struct i2c_client *i2c_dummy; |
---|
| 1254 | + |
---|
| 1255 | + i2c_dummy = i2c_new_dummy_device(client->adapter, |
---|
| 1256 | + i2c_addresses[i] >> 1); |
---|
| 1257 | + if (IS_ERR(i2c_dummy)) { |
---|
| 1258 | + err = PTR_ERR(i2c_dummy); |
---|
| 1259 | + DRM_ERROR("Failed to reserve I2C bus %02x: %d\n", |
---|
| 1260 | + i2c_addresses[i], err); |
---|
1231 | 1261 | goto err_unregister_i2c; |
---|
1232 | 1262 | } |
---|
1233 | 1263 | |
---|
| 1264 | + anx78xx->i2c_dummy[i] = i2c_dummy; |
---|
1234 | 1265 | anx78xx->map[i] = devm_regmap_init_i2c(anx78xx->i2c_dummy[i], |
---|
1235 | 1266 | &anx78xx_regmap_config); |
---|
1236 | 1267 | if (IS_ERR(anx78xx->map[i])) { |
---|
1237 | 1268 | err = PTR_ERR(anx78xx->map[i]); |
---|
1238 | 1269 | DRM_ERROR("Failed regmap initialization %02x\n", |
---|
1239 | | - anx78xx_i2c_addresses[i]); |
---|
| 1270 | + i2c_addresses[i]); |
---|
1240 | 1271 | goto err_unregister_i2c; |
---|
1241 | 1272 | } |
---|
1242 | 1273 | } |
---|
.. | .. |
---|
1335 | 1366 | |
---|
1336 | 1367 | #if IS_ENABLED(CONFIG_OF) |
---|
1337 | 1368 | static const struct of_device_id anx78xx_match_table[] = { |
---|
1338 | | - { .compatible = "analogix,anx7814", }, |
---|
| 1369 | + { .compatible = "analogix,anx7808", .data = anx7808_i2c_addresses }, |
---|
| 1370 | + { .compatible = "analogix,anx7812", .data = anx781x_i2c_addresses }, |
---|
| 1371 | + { .compatible = "analogix,anx7814", .data = anx781x_i2c_addresses }, |
---|
| 1372 | + { .compatible = "analogix,anx7818", .data = anx781x_i2c_addresses }, |
---|
1339 | 1373 | { /* sentinel */ }, |
---|
1340 | 1374 | }; |
---|
1341 | 1375 | MODULE_DEVICE_TABLE(of, anx78xx_match_table); |
---|