1 // SPDX-License-Identifier: MIT 2 /* 3 * Permission is hereby granted, free of charge, to any person obtaining a 4 * copy of this software and associated documentation files (the 5 * "Software"), to deal in the Software without restriction, including 6 * without limitation the rights to use, copy, modify, merge, publish, 7 * distribute, sub license, and/or sell copies of the Software, and to 8 * permit persons to whom the Software is furnished to do so, subject to 9 * the following conditions: 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 14 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 17 * USE OR OTHER DEALINGS IN THE SOFTWARE. 18 * 19 * The above copyright notice and this permission notice (including the 20 * next paragraph) shall be included in all copies or substantial portions 21 * of the Software. 22 */ 23 24 #include <linux/i2c-algo-bit.h> 25 #include <linux/i2c.h> 26 27 #include <drm/drm_managed.h> 28 #include <drm/drm_print.h> 29 30 #include "ast_ddc.h" 31 #include "ast_drv.h" 32 33 struct ast_ddc { 34 struct ast_device *ast; 35 36 struct i2c_algo_bit_data bit; 37 struct i2c_adapter adapter; 38 }; 39 40 static void ast_ddc_algo_bit_data_setsda(void *data, int state) 41 { 42 struct ast_ddc *ddc = data; 43 struct ast_device *ast = ddc->ast; 44 int i; 45 u8 ujcrb7, jtemp; 46 47 for (i = 0; i < 0x10000; i++) { 48 ujcrb7 = ((state & 0x01) ? 0 : 1) << 2; 49 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf1, ujcrb7); 50 jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x04); 51 if (ujcrb7 == jtemp) 52 break; 53 } 54 } 55 56 static void ast_ddc_algo_bit_data_setscl(void *data, int state) 57 { 58 struct ast_ddc *ddc = data; 59 struct ast_device *ast = ddc->ast; 60 int i; 61 u8 ujcrb7, jtemp; 62 63 for (i = 0; i < 0x10000; i++) { 64 ujcrb7 = ((state & 0x01) ? 0 : 1); 65 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0xf4, ujcrb7); 66 jtemp = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x01); 67 if (ujcrb7 == jtemp) 68 break; 69 } 70 } 71 72 static int ast_ddc_algo_bit_data_pre_xfer(struct i2c_adapter *adapter) 73 { 74 struct ast_ddc *ddc = i2c_get_adapdata(adapter); 75 struct ast_device *ast = ddc->ast; 76 77 /* 78 * Protect access to I/O registers from concurrent modesetting 79 * by acquiring the I/O-register lock. 80 */ 81 mutex_lock(&ast->modeset_lock); 82 83 return 0; 84 } 85 86 static void ast_ddc_algo_bit_data_post_xfer(struct i2c_adapter *adapter) 87 { 88 struct ast_ddc *ddc = i2c_get_adapdata(adapter); 89 struct ast_device *ast = ddc->ast; 90 91 mutex_unlock(&ast->modeset_lock); 92 } 93 94 static int ast_ddc_algo_bit_data_getsda(void *data) 95 { 96 struct ast_ddc *ddc = data; 97 struct ast_device *ast = ddc->ast; 98 uint32_t val, val2, count, pass; 99 100 count = 0; 101 pass = 0; 102 val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; 103 do { 104 val2 = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; 105 if (val == val2) { 106 pass++; 107 } else { 108 pass = 0; 109 val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x20) >> 5) & 0x01; 110 } 111 } while ((pass < 5) && (count++ < 0x10000)); 112 113 return val & 1 ? 1 : 0; 114 } 115 116 static int ast_ddc_algo_bit_data_getscl(void *data) 117 { 118 struct ast_ddc *ddc = data; 119 struct ast_device *ast = ddc->ast; 120 uint32_t val, val2, count, pass; 121 122 count = 0; 123 pass = 0; 124 val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; 125 do { 126 val2 = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; 127 if (val == val2) { 128 pass++; 129 } else { 130 pass = 0; 131 val = (ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xb7, 0x10) >> 4) & 0x01; 132 } 133 } while ((pass < 5) && (count++ < 0x10000)); 134 135 return val & 1 ? 1 : 0; 136 } 137 138 static void ast_ddc_release(struct drm_device *dev, void *res) 139 { 140 struct ast_ddc *ddc = res; 141 142 i2c_del_adapter(&ddc->adapter); 143 } 144 145 struct i2c_adapter *ast_ddc_create(struct ast_device *ast) 146 { 147 struct drm_device *dev = &ast->base; 148 struct ast_ddc *ddc; 149 struct i2c_adapter *adapter; 150 struct i2c_algo_bit_data *bit; 151 int ret; 152 153 ddc = drmm_kzalloc(dev, sizeof(*ddc), GFP_KERNEL); 154 if (!ddc) 155 return ERR_PTR(-ENOMEM); 156 ddc->ast = ast; 157 158 bit = &ddc->bit; 159 bit->data = ddc; 160 bit->setsda = ast_ddc_algo_bit_data_setsda; 161 bit->setscl = ast_ddc_algo_bit_data_setscl; 162 bit->getsda = ast_ddc_algo_bit_data_getsda; 163 bit->getscl = ast_ddc_algo_bit_data_getscl; 164 bit->pre_xfer = ast_ddc_algo_bit_data_pre_xfer; 165 bit->post_xfer = ast_ddc_algo_bit_data_post_xfer; 166 bit->udelay = 20; 167 bit->timeout = usecs_to_jiffies(2200); 168 169 adapter = &ddc->adapter; 170 adapter->owner = THIS_MODULE; 171 adapter->algo_data = bit; 172 adapter->dev.parent = dev->dev; 173 snprintf(adapter->name, sizeof(adapter->name), "AST DDC bus"); 174 i2c_set_adapdata(adapter, ddc); 175 176 ret = i2c_bit_add_bus(adapter); 177 if (ret) { 178 drm_err(dev, "Failed to register bit i2c\n"); 179 return ERR_PTR(ret); 180 } 181 182 ret = drmm_add_action_or_reset(dev, ast_ddc_release, ddc); 183 if (ret) 184 return ERR_PTR(ret); 185 186 return &ddc->adapter; 187 } 188