Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Permission is hereby granted, free of charge, to any person obtaining a
0004  * copy of this software and associated documentation files (the
0005  * "Software"), to deal in the Software without restriction, including
0006  * without limitation the rights to use, copy, modify, merge, publish,
0007  * distribute, sub license, and/or sell copies of the Software, and to
0008  * permit persons to whom the Software is furnished to do so, subject to
0009  * the following conditions:
0010  *
0011  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0012  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0013  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
0014  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
0015  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
0016  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
0017  * USE OR OTHER DEALINGS IN THE SOFTWARE.
0018  *
0019  * The above copyright notice and this permission notice (including the
0020  * next paragraph) shall be included in all copies or substantial portions
0021  * of the Software.
0022  */
0023 
0024 #include <drm/drm_managed.h>
0025 #include <drm/drm_print.h>
0026 
0027 #include "ast_drv.h"
0028 
0029 static void ast_i2c_setsda(void *i2c_priv, int data)
0030 {
0031     struct ast_i2c_chan *i2c = i2c_priv;
0032     struct ast_private *ast = to_ast_private(i2c->dev);
0033     int i;
0034     u8 ujcrb7, jtemp;
0035 
0036     for (i = 0; i < 0x10000; i++) {
0037         ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
0038         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
0039         jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
0040         if (ujcrb7 == jtemp)
0041             break;
0042     }
0043 }
0044 
0045 static void ast_i2c_setscl(void *i2c_priv, int clock)
0046 {
0047     struct ast_i2c_chan *i2c = i2c_priv;
0048     struct ast_private *ast = to_ast_private(i2c->dev);
0049     int i;
0050     u8 ujcrb7, jtemp;
0051 
0052     for (i = 0; i < 0x10000; i++) {
0053         ujcrb7 = ((clock & 0x01) ? 0 : 1);
0054         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
0055         jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
0056         if (ujcrb7 == jtemp)
0057             break;
0058     }
0059 }
0060 
0061 static int ast_i2c_getsda(void *i2c_priv)
0062 {
0063     struct ast_i2c_chan *i2c = i2c_priv;
0064     struct ast_private *ast = to_ast_private(i2c->dev);
0065     uint32_t val, val2, count, pass;
0066 
0067     count = 0;
0068     pass = 0;
0069     val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
0070     do {
0071         val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
0072         if (val == val2) {
0073             pass++;
0074         } else {
0075             pass = 0;
0076             val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
0077         }
0078     } while ((pass < 5) && (count++ < 0x10000));
0079 
0080     return val & 1 ? 1 : 0;
0081 }
0082 
0083 static int ast_i2c_getscl(void *i2c_priv)
0084 {
0085     struct ast_i2c_chan *i2c = i2c_priv;
0086     struct ast_private *ast = to_ast_private(i2c->dev);
0087     uint32_t val, val2, count, pass;
0088 
0089     count = 0;
0090     pass = 0;
0091     val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
0092     do {
0093         val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
0094         if (val == val2) {
0095             pass++;
0096         } else {
0097             pass = 0;
0098             val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
0099         }
0100     } while ((pass < 5) && (count++ < 0x10000));
0101 
0102     return val & 1 ? 1 : 0;
0103 }
0104 
0105 static void ast_i2c_release(struct drm_device *dev, void *res)
0106 {
0107     struct ast_i2c_chan *i2c = res;
0108 
0109     i2c_del_adapter(&i2c->adapter);
0110     kfree(i2c);
0111 }
0112 
0113 struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev)
0114 {
0115     struct ast_i2c_chan *i2c;
0116     int ret;
0117 
0118     i2c = kzalloc(sizeof(struct ast_i2c_chan), GFP_KERNEL);
0119     if (!i2c)
0120         return NULL;
0121 
0122     i2c->adapter.owner = THIS_MODULE;
0123     i2c->adapter.class = I2C_CLASS_DDC;
0124     i2c->adapter.dev.parent = dev->dev;
0125     i2c->dev = dev;
0126     i2c_set_adapdata(&i2c->adapter, i2c);
0127     snprintf(i2c->adapter.name, sizeof(i2c->adapter.name),
0128          "AST i2c bit bus");
0129     i2c->adapter.algo_data = &i2c->bit;
0130 
0131     i2c->bit.udelay = 20;
0132     i2c->bit.timeout = 2;
0133     i2c->bit.data = i2c;
0134     i2c->bit.setsda = ast_i2c_setsda;
0135     i2c->bit.setscl = ast_i2c_setscl;
0136     i2c->bit.getsda = ast_i2c_getsda;
0137     i2c->bit.getscl = ast_i2c_getscl;
0138     ret = i2c_bit_add_bus(&i2c->adapter);
0139     if (ret) {
0140         drm_err(dev, "Failed to register bit i2c\n");
0141         goto out_kfree;
0142     }
0143 
0144     ret = drmm_add_action_or_reset(dev, ast_i2c_release, i2c);
0145     if (ret)
0146         return NULL;
0147     return i2c;
0148 
0149 out_kfree:
0150     kfree(i2c);
0151     return NULL;
0152 }