From patchwork Fri Jun 24 20:26:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin Brace X-Patchwork-Id: 12895058 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 5073EC43334 for ; Fri, 24 Jun 2022 20:33:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 90A3610F3F8; Fri, 24 Jun 2022 20:33:33 +0000 (UTC) Received: from mout.gmx.net (mout.gmx.net [212.227.15.19]) by gabe.freedesktop.org (Postfix) with ESMTPS id C32EA10F2DA for ; Fri, 24 Jun 2022 20:33:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1656102804; bh=FTS0WBHVw5mYjOegRVw3nfhyqrC1r3khqrbIVBtc0Ps=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=luyOJqzhUma2sNyYPZTMiOBoRVdviwzL7UX8Iy9LNnF+GznDv2rkpYiK8iWAnlh// pZuvRTzobN+wXt5M6Rf+fGxZLjYA0iJHlvwLtyxfwqHr4Wi+VvNl4yxzoFSaDKvYXK fWxdY0r+bhXoujR7Cn/qUyoFM1Up3Nh+WUhypzBg= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from localhost.localdomain ([174.250.50.5]) by mail.gmx.net (mrgmx004 [212.227.17.184]) with ESMTPSA (Nemesis) id 1N0G1d-1nheAG47ip-00xLFl; Fri, 24 Jun 2022 22:28:21 +0200 From: Kevin Brace To: dri-devel@lists.freedesktop.org Subject: [PATCH 14/28] drm/via: Add via_i2c.c Date: Fri, 24 Jun 2022 15:26:19 -0500 Message-Id: <20220624202633.3978-15-kevinbrace@gmx.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220624202633.3978-1-kevinbrace@gmx.com> References: <20220624202633.3978-1-kevinbrace@gmx.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:qmJNG5z7aPY2Bo/YWuB6lDUn1d1l9RnN+CTUFZ8EOn6tCistoKv wOf/ZRp/hlKii6jw6fND5e335bTjwTgfmOqB7T3felc1dvs4UyQYnsbUWquP13T9AalNg0R GcdBucM4+f7ggin+LTjFrHMiUrYGBxGONwwP++zug8vdQsduwv8w6+c11qwJbaUDPrCGmCw mUuTAuMC2jb3u7n5sUKYQ== X-UI-Out-Filterresults: notjunk:1;V03:K0:hfxH1X2xJeA=:fq0ykxOsgO9tJ9gOYNCeR3 iBF3sWiZ8Fum/fCe9VPkFp6MQ8OGXh1vqYEmTga0pIH376WluihQIw1Ph1FObNwDNtNmABDUg HeNDCF2+ylayYnPcwXjFJaeTV061f0SBYFBQaDpy30iwbz9fQATbpF1w6PyZKPrCmPsnrWD05 iULuXBLld34GbAzBQ9oYsSqCp8MzevbbM5iRtzMmptU8ajfAid8HrKZccR1iFBSW8YImj4GYg 6ggecnH9/DrbIqHSqSD14M8YR+0XqnhqF2p+LNjpE8HWr83Q0NV91ciNrhmNQIlruaQTL9bfK 8PIq2vFZkOqVdqn8k5c1Mg70A06ut8S2yG5ndcZkkI7XSsr7C1TDWQXELL3RboZpKyeWlCuPB 9eekSQRL37qeo2fsIPw57dbuPYqgoPpP2U+mjJ+knvG6HeiDr6UV9gzHBMwjAt4bbOOjC/U2E dBB7Zz4uJjev2ypIsOAYvtWwNV2x4kUxOTUGV3gOlrKJRE/xJi1RzuC091qjTh8jZDj+ZEh9K Fqk4cHzHBS6EOTCUxr/xgKDKRlvxOXiM0eVxamiRDoCSviZsSLRLCaGTT70oBqhknknLZskLS imRMAUrPLaIKml+C1WjhowelAHaZQ+5z9Gab5D7w2ZKXBgNfF3aAlLXGoeSNNghg5w9dM7vdS LMmSViAAm5wezA48MRhXrZphyTdhPeHwVRTUoDqQQ49z/EJivJTaUZz/t+fozcwxVCMVMv5z3 mOR5XRS1Gx4sYLY4j2dGqlHVvmYQlPx9sEH9VRmwux5IvuubHPLzwMoXdGVCE7XpJoLuuSpje qvAfy4xEzUtqwHHvdt9OxJc2FMazGt38f1k5uxlQOkAARdtOp3JkiQ/u8bOr3alGkWhS1RQTb 2yGBW9nskTzMVJK9iN/71Qhw/GcdNfwukztjsgzxe9RpVS9PR1BfhlnZPfl6MLKDAuLdcYzFs wBY4sOxmGiMjYkRSXzaXHY4yvRqPN50MCrJMVah4sb/P5qWvE4D+78Ax3i+iQ9wxzgx8DKzN5 CLZy24XCJjD+Gv28p8lYx/aH70GwtTxPCod5/dHu9U6lUt4h/pFvrQ7Fm5lQfSTjL1Lx+yzY2 4Ir7yZuTcsLn43r9VOd3jzKW9+Jed78RxPbhMpxCZW14KGlDebLpT5vCA== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Brace Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Kevin Brace Note that the code here is GPL based. Signed-off-by: Kevin Brace --- drivers/gpu/drm/via/via_i2c.c | 209 ++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 drivers/gpu/drm/via/via_i2c.c -- 2.35.1 diff --git a/drivers/gpu/drm/via/via_i2c.c b/drivers/gpu/drm/via/via_i2c.c new file mode 100644 index 000000000000..f2e8b118754e --- /dev/null +++ b/drivers/gpu/drm/via/via_i2c.c @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright 2012 James Simmons. All Rights Reserved. + * Copyright 1998-2009 VIA Technologies, Inc. All Rights Reserved. + * Copyright 2001-2008 S3 Graphics, Inc. All Rights Reserved. + * + * Author(s): + * James Simmons + */ + +#include + +#include "via_drv.h" + +enum viafb_i2c_adap; + +#include + +#define SERIAL 0 +#define GPIO 1 + +static struct via_i2c_stuff via_i2c_par[5]; + +static void via_i2c_setsda(void *data, int state) +{ + struct via_i2c_stuff *i2c = data; + struct drm_device *dev = i2c_get_adapdata(&i2c->adapter); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + u8 value, mask; + + if (i2c->is_active == GPIO) { + mask = state ? BIT(6) : BIT(6) | BIT(4); + value = state ? 0x00 : BIT(6); + } else { + value = state ? BIT(4) | BIT(0) : BIT(0); + mask = BIT(4) | BIT(0); + } + + svga_wseq_mask(VGABASE, i2c->i2c_port, value, mask); +} + +static void via_i2c_setscl(void *data, int state) +{ + struct via_i2c_stuff *i2c = data; + struct drm_device *dev = i2c_get_adapdata(&i2c->adapter); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + u8 value, mask; + + if (i2c->is_active == GPIO) { + mask = state ? BIT(7) : BIT(7) | BIT(5); + value = state ? 0x00 : BIT(7); + } else { + value = state ? BIT(5) | BIT(0) : BIT(0); + mask = BIT(5) | BIT(0); + } + + svga_wseq_mask(VGABASE, i2c->i2c_port, value, mask); +} + +static int via_i2c_getsda(void *data) +{ + struct via_i2c_stuff *i2c = data; + struct drm_device *dev = i2c_get_adapdata(&i2c->adapter); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + + return vga_rseq(VGABASE, i2c->i2c_port) & BIT(2); +} + +static int via_i2c_getscl(void *data) +{ + struct via_i2c_stuff *i2c = data; + struct drm_device *dev = i2c_get_adapdata(&i2c->adapter); + struct via_drm_priv *dev_priv = to_via_drm_priv(dev); + + return vga_rseq(VGABASE, i2c->i2c_port) & BIT(3); +} + +struct i2c_adapter *via_find_ddc_bus(int port) +{ + struct i2c_adapter *adapter = NULL; + int i; + + for (i = 0; i < ARRAY_SIZE(via_i2c_par); i++) { + struct via_i2c_stuff *i2c = &via_i2c_par[i]; + + if (i2c->i2c_port == port) { + adapter = &i2c->adapter; + break; + } + } + return adapter; +} + +static int create_i2c_bus(struct drm_device *dev, + struct via_i2c_stuff *i2c_par) +{ + struct i2c_adapter *adapter = &i2c_par->adapter; + struct i2c_algo_bit_data *algo = &i2c_par->algo; + + algo->setsda = via_i2c_setsda; + algo->setscl = via_i2c_setscl; + algo->getsda = via_i2c_getsda; + algo->getscl = via_i2c_getscl; + algo->udelay = 15; + algo->timeout = usecs_to_jiffies(2200); /* from VESA */ + algo->data = i2c_par; + + sprintf(adapter->name, "via i2c bit bus 0x%02x", i2c_par->i2c_port); + adapter->owner = THIS_MODULE; + adapter->class = I2C_CLASS_DDC; + adapter->algo_data = algo; + i2c_set_adapdata(adapter, dev); + + /* Raise SCL and SDA */ + via_i2c_setsda(i2c_par, 1); + via_i2c_setscl(i2c_par, 1); + udelay(20); + + return i2c_bit_add_bus(adapter); +} + +void via_i2c_readbytes(struct i2c_adapter *adapter, + u8 slave_addr, char offset, + u8 *buffer, unsigned int size) +{ + u8 out_buf[2]; + u8 in_buf[2]; + struct i2c_msg msgs[] = { + { + .addr = slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = slave_addr, + .flags = I2C_M_RD, + .len = size, + .buf = in_buf, + } + }; + + out_buf[0] = offset; + out_buf[1] = 0; + + if (i2c_transfer(adapter, msgs, 2) != 2) + printk(KERN_WARNING "%s failed\n", __func__); + else + *buffer = in_buf[0]; +} + +void via_i2c_writebytes(struct i2c_adapter *adapter, + u8 slave_addr, char offset, + u8 *data, unsigned int size) +{ + struct i2c_msg msg = { 0 }; + u8 *out_buf; + + out_buf = kzalloc(size + 1, GFP_KERNEL); + out_buf[0] = offset; + memcpy(&out_buf[1], data, size); + msg.addr = slave_addr; + msg.flags = 0; + msg.len = size + 1; + msg.buf = out_buf; + + if (i2c_transfer(adapter, &msg, 1) != 1) + printk(KERN_WARNING "%s failed\n", __func__); + + kfree(out_buf); +} + +void via_i2c_reg_init(struct via_drm_priv *dev_priv) +{ + svga_wseq_mask(VGABASE, 0x31, 0x30, 0x30); + svga_wseq_mask(VGABASE, 0x26, 0x30, 0x30); + vga_wseq(VGABASE, 0x2C, 0xc2); + vga_wseq(VGABASE, 0x3D, 0xc0); + svga_wseq_mask(VGABASE, 0x2C, 0x30, 0x30); + svga_wseq_mask(VGABASE, 0x3D, 0x30, 0x30); +} + +int via_i2c_init(struct drm_device *dev) +{ + int types[] = { SERIAL, SERIAL, GPIO, GPIO, GPIO }; + int ports[] = { 0x26, 0x31, 0x25, 0x2C, 0x3D }; + int count = ARRAY_SIZE(via_i2c_par), ret, i; + struct via_i2c_stuff *i2c = via_i2c_par; + + for (i = 0; i < count; i++) { + i2c->is_active = types[i]; + i2c->i2c_port = ports[i]; + + ret = create_i2c_bus(dev, i2c); + if (ret < 0) + DRM_ERROR("cannot create i2c bus %x:%d\n", + ports[i], ret); + i2c++; + } + return 0; +} + +void via_i2c_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(via_i2c_par); i++) + i2c_del_adapter(&via_i2c_par->adapter); +}