Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/sitronix/st7571-i2c: make probe independent of hw interface

Create an interface independent layer for the probe function. This is to
make it possible to add support for other interfaces.

Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
Link: https://patch.msgid.link/20251215-st7571-split-v3-4-d5f3205c3138@gmail.com
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>

authored by

Marcus Folkesson and committed by
Javier Martinez Canillas
b0c20d82 d93a4354

+127 -91
+126 -67
drivers/gpu/drm/sitronix/st7571-i2c.c
··· 80 80 #define DRIVER_MAJOR 1 81 81 #define DRIVER_MINOR 0 82 82 83 + struct st7571_i2c_transport { 84 + struct i2c_client *client; 85 + 86 + /* 87 + * Depending on the hardware design, the acknowledge signal may be hard to 88 + * recognize as a valid logic "0" level. 89 + * Therefor, ignore NAK if possible to stay compatible with most hardware designs 90 + * and off-the-shelf panels out there. 91 + * 92 + * From section 6.4 MICROPOCESSOR INTERFACE section in the datasheet: 93 + * 94 + * "By connecting SDA_OUT to SDA_IN externally, the SDA line becomes fully 95 + * I2C interface compatible. 96 + * Separating acknowledge-output from serial data 97 + * input is advantageous for chip-on-glass (COG) applications. In COG 98 + * applications, the ITO resistance and the pull-up resistor will form a 99 + * voltage divider, which affects acknowledge-signal level. Larger ITO 100 + * resistance will raise the acknowledged-signal level and system cannot 101 + * recognize this level as a valid logic “0” level. By separating SDA_IN from 102 + * SDA_OUT, the IC can be used in a mode that ignores the acknowledge-bit. 103 + * For applications which check acknowledge-bit, it is necessary to minimize 104 + * the ITO resistance of the SDA_OUT trace to guarantee a valid low level." 105 + * 106 + */ 107 + bool ignore_nak; 108 + }; 109 + 83 110 static inline struct st7571_device *drm_to_st7571(struct drm_device *drm) 84 111 { 85 112 return container_of(drm, struct st7571_device, drm); ··· 114 87 115 88 static int st7571_regmap_write(void *context, const void *data, size_t count) 116 89 { 117 - struct i2c_client *client = context; 118 - struct st7571_device *st7571 = i2c_get_clientdata(client); 90 + struct st7571_i2c_transport *t = context; 119 91 int ret; 120 92 121 93 struct i2c_msg msg = { 122 - .addr = st7571->client->addr, 123 - .flags = st7571->ignore_nak ? I2C_M_IGNORE_NAK : 0, 94 + .addr = t->client->addr, 95 + .flags = t->ignore_nak ? I2C_M_IGNORE_NAK : 0, 124 96 .len = count, 125 97 .buf = (u8 *)data 126 98 }; 127 99 128 - ret = i2c_transfer(st7571->client->adapter, &msg, 1); 100 + ret = i2c_transfer(t->client->adapter, &msg, 1); 129 101 130 102 /* 131 103 * Unfortunately, there is no way to check if the transfer failed because of ··· 132 106 * 133 107 * However, if the transfer fails and ignore_nak is set, we know it is an error. 134 108 */ 135 - if (ret < 0 && st7571->ignore_nak) 109 + if (ret < 0 && t->ignore_nak) 136 110 return ret; 137 111 138 112 return 0; ··· 871 845 return st7571_send_command_list(st7571, commands, ARRAY_SIZE(commands)); 872 846 } 873 847 874 - static int st7571_probe(struct i2c_client *client) 848 + static struct st7571_device *st7571_probe(struct device *dev, 849 + struct regmap *regmap) 875 850 { 876 851 struct st7571_device *st7571; 877 852 struct drm_device *drm; 878 853 int ret; 879 854 880 - st7571 = devm_drm_dev_alloc(&client->dev, &st7571_driver, 855 + st7571 = devm_drm_dev_alloc(dev, &st7571_driver, 881 856 struct st7571_device, drm); 882 857 if (IS_ERR(st7571)) 883 - return PTR_ERR(st7571); 858 + return st7571; 884 859 885 860 drm = &st7571->drm; 886 - st7571->dev = &client->dev; 887 - st7571->client = client; 888 - i2c_set_clientdata(client, st7571); 861 + st7571->dev = dev; 889 862 st7571->pdata = device_get_match_data(st7571->dev); 890 863 891 864 ret = st7571->pdata->parse_dt(st7571); 892 865 if (ret) 893 - return ret; 866 + return ERR_PTR(ret); 894 867 895 868 ret = st7571_validate_parameters(st7571); 896 869 if (ret) 897 - return ret; 870 + return ERR_PTR(ret); 898 871 899 872 st7571->mode = st7571_mode(st7571); 873 + st7571->regmap = regmap; 874 + 875 + 876 + st7571->hwbuf = devm_kzalloc(st7571->dev, 877 + (st7571->nlines * st7571->ncols * st7571->bpp) / 8, 878 + GFP_KERNEL); 879 + if (!st7571->hwbuf) 880 + return ERR_PTR(-ENOMEM); 881 + 882 + st7571->row = devm_kzalloc(st7571->dev, 883 + (st7571->ncols * st7571->bpp), 884 + GFP_KERNEL); 885 + if (!st7571->row) 886 + return ERR_PTR(-ENOMEM); 887 + 888 + ret = st7571_mode_config_init(st7571); 889 + if (ret) { 890 + dev_err(st7571->dev, "Failed to initialize mode config\n"); 891 + return ERR_PTR(ret); 892 + } 893 + 894 + ret = st7571_plane_init(st7571, st7571->pformat); 895 + if (ret) { 896 + dev_err(st7571->dev, "Failed to initialize primary plane\n"); 897 + return ERR_PTR(ret); 898 + } 899 + 900 + ret = st7571_crtc_init(st7571); 901 + if (ret < 0) { 902 + dev_err(st7571->dev, "Failed to initialize CRTC\n"); 903 + return ERR_PTR(ret); 904 + } 905 + 906 + ret = st7571_encoder_init(st7571); 907 + if (ret < 0) { 908 + dev_err(st7571->dev, "Failed to initialize encoder\n"); 909 + return ERR_PTR(ret); 910 + } 911 + 912 + ret = st7571_connector_init(st7571); 913 + if (ret < 0) { 914 + dev_err(st7571->dev, "Failed to initialize connector\n"); 915 + return ERR_PTR(ret); 916 + } 917 + 918 + drm_mode_config_reset(drm); 919 + 920 + ret = drm_dev_register(drm, 0); 921 + if (ret) { 922 + dev_err(st7571->dev, "Failed to register DRM device\n"); 923 + return ERR_PTR(ret); 924 + } 925 + 926 + drm_client_setup(drm, NULL); 927 + return st7571; 928 + } 929 + 930 + static void st7571_remove(struct st7571_device *st7571) 931 + { 932 + drm_dev_unplug(&st7571->drm); 933 + } 934 + 935 + static int st7571_i2c_probe(struct i2c_client *client) 936 + { 937 + struct st7571_device *st7571; 938 + struct st7571_i2c_transport *t; 939 + struct regmap *regmap; 940 + 941 + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); 942 + if (!t) 943 + return -ENOMEM; 944 + 945 + t->client = client; 900 946 901 947 /* 902 948 * The hardware design could make it hard to detect a NAK on the I2C bus. ··· 977 879 * cruft in the logs. 978 880 */ 979 881 if (i2c_check_functionality(client->adapter, I2C_FUNC_PROTOCOL_MANGLING)) 980 - st7571->ignore_nak = true; 882 + t->ignore_nak = true; 981 883 982 - st7571->regmap = devm_regmap_init(st7571->dev, &st7571_regmap_bus, 983 - client, &st7571_regmap_config); 984 - if (IS_ERR(st7571->regmap)) { 985 - return dev_err_probe(st7571->dev, PTR_ERR(st7571->regmap), 884 + regmap = devm_regmap_init(&client->dev, &st7571_regmap_bus, 885 + t, &st7571_regmap_config); 886 + if (IS_ERR(regmap)) { 887 + return dev_err_probe(&client->dev, PTR_ERR(regmap), 986 888 "Failed to initialize regmap\n"); 987 889 } 988 890 989 - st7571->hwbuf = devm_kzalloc(st7571->dev, 990 - (st7571->nlines * st7571->ncols * st7571->bpp) / 8, 991 - GFP_KERNEL); 992 - if (!st7571->hwbuf) 993 - return -ENOMEM; 891 + st7571 = st7571_probe(&client->dev, regmap); 892 + if (IS_ERR(st7571)) 893 + return dev_err_probe(&client->dev, PTR_ERR(st7571), 894 + "Failed to initialize regmap\n"); 994 895 995 - st7571->row = devm_kzalloc(st7571->dev, 996 - (st7571->ncols * st7571->bpp), 997 - GFP_KERNEL); 998 - if (!st7571->row) 999 - return -ENOMEM; 1000 - 1001 - ret = st7571_mode_config_init(st7571); 1002 - if (ret) 1003 - return dev_err_probe(st7571->dev, ret, 1004 - "Failed to initialize mode config\n"); 1005 - 1006 - ret = st7571_plane_init(st7571, st7571->pformat); 1007 - if (ret) 1008 - return dev_err_probe(st7571->dev, ret, 1009 - "Failed to initialize primary plane\n"); 1010 - 1011 - ret = st7571_crtc_init(st7571); 1012 - if (ret < 0) 1013 - return dev_err_probe(st7571->dev, ret, 1014 - "Failed to initialize CRTC\n"); 1015 - 1016 - ret = st7571_encoder_init(st7571); 1017 - if (ret < 0) 1018 - return dev_err_probe(st7571->dev, ret, 1019 - "Failed to initialize encoder\n"); 1020 - 1021 - ret = st7571_connector_init(st7571); 1022 - if (ret < 0) 1023 - return dev_err_probe(st7571->dev, ret, 1024 - "Failed to initialize connector\n"); 1025 - 1026 - drm_mode_config_reset(drm); 1027 - 1028 - ret = drm_dev_register(drm, 0); 1029 - if (ret) 1030 - return dev_err_probe(st7571->dev, ret, 1031 - "Failed to register DRM device\n"); 1032 - 1033 - drm_client_setup(drm, NULL); 896 + i2c_set_clientdata(client, st7571); 1034 897 return 0; 1035 898 } 1036 899 1037 - static void st7571_remove(struct i2c_client *client) 900 + static void st7571_i2c_remove(struct i2c_client *client) 1038 901 { 1039 902 struct st7571_device *st7571 = i2c_get_clientdata(client); 1040 903 1041 - drm_dev_unplug(&st7571->drm); 904 + st7571_remove(st7571); 1042 905 } 1043 906 1044 907 static const struct st7571_panel_data st7567_config = { ··· 1045 986 .name = "st7571", 1046 987 .of_match_table = st7571_of_match, 1047 988 }, 1048 - .probe = st7571_probe, 1049 - .remove = st7571_remove, 989 + .probe = st7571_i2c_probe, 990 + .remove = st7571_i2c_remove, 1050 991 .id_table = st7571_id, 1051 992 }; 1052 993
+1 -24
drivers/gpu/drm/sitronix/st7571.h
··· 13 13 #include <drm/drm_crtc.h> 14 14 #include <drm/drm_drv.h> 15 15 #include <drm/drm_encoder.h> 16 + #include <drm/drm_format_helper.h> 16 17 17 18 #include <linux/regmap.h> 18 19 ··· 63 62 64 63 const struct st7571_panel_format *pformat; 65 64 const struct st7571_panel_data *pdata; 66 - struct i2c_client *client; 67 65 struct gpio_desc *reset; 68 66 struct regmap *regmap; 69 - 70 - /* 71 - * Depending on the hardware design, the acknowledge signal may be hard to 72 - * recognize as a valid logic "0" level. 73 - * Therefor, ignore NAK if possible to stay compatible with most hardware designs 74 - * and off-the-shelf panels out there. 75 - * 76 - * From section 6.4 MICROPOCESSOR INTERFACE section in the datasheet: 77 - * 78 - * "By connecting SDA_OUT to SDA_IN externally, the SDA line becomes fully 79 - * I2C interface compatible. 80 - * Separating acknowledge-output from serial data 81 - * input is advantageous for chip-on-glass (COG) applications. In COG 82 - * applications, the ITO resistance and the pull-up resistor will form a 83 - * voltage divider, which affects acknowledge-signal level. Larger ITO 84 - * resistance will raise the acknowledged-signal level and system cannot 85 - * recognize this level as a valid logic “0” level. By separating SDA_IN from 86 - * SDA_OUT, the IC can be used in a mode that ignores the acknowledge-bit. 87 - * For applications which check acknowledge-bit, it is necessary to minimize 88 - * the ITO resistance of the SDA_OUT trace to guarantee a valid low level." 89 - * 90 - */ 91 - bool ignore_nak; 92 67 93 68 bool grayscale; 94 69 bool inverted;