cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

radeon_i2c.c (4055B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "radeonfb.h"
      3
      4#include <linux/module.h>
      5#include <linux/kernel.h>
      6#include <linux/delay.h>
      7#include <linux/fb.h>
      8
      9
     10#include <linux/i2c.h>
     11#include <linux/i2c-algo-bit.h>
     12
     13#include <asm/io.h>
     14
     15#include <video/radeon.h>
     16#include "../edid.h"
     17
     18static void radeon_gpio_setscl(void* data, int state)
     19{
     20	struct radeon_i2c_chan 	*chan = data;
     21	struct radeonfb_info	*rinfo = chan->rinfo;
     22	u32			val;
     23	
     24	val = INREG(chan->ddc_reg) & ~(VGA_DDC_CLK_OUT_EN);
     25	if (!state)
     26		val |= VGA_DDC_CLK_OUT_EN;
     27
     28	OUTREG(chan->ddc_reg, val);
     29	(void)INREG(chan->ddc_reg);
     30}
     31
     32static void radeon_gpio_setsda(void* data, int state)
     33{
     34	struct radeon_i2c_chan 	*chan = data;
     35	struct radeonfb_info	*rinfo = chan->rinfo;
     36	u32			val;
     37	
     38	val = INREG(chan->ddc_reg) & ~(VGA_DDC_DATA_OUT_EN);
     39	if (!state)
     40		val |= VGA_DDC_DATA_OUT_EN;
     41
     42	OUTREG(chan->ddc_reg, val);
     43	(void)INREG(chan->ddc_reg);
     44}
     45
     46static int radeon_gpio_getscl(void* data)
     47{
     48	struct radeon_i2c_chan 	*chan = data;
     49	struct radeonfb_info	*rinfo = chan->rinfo;
     50	u32			val;
     51	
     52	val = INREG(chan->ddc_reg);
     53
     54	return (val & VGA_DDC_CLK_INPUT) ? 1 : 0;
     55}
     56
     57static int radeon_gpio_getsda(void* data)
     58{
     59	struct radeon_i2c_chan 	*chan = data;
     60	struct radeonfb_info	*rinfo = chan->rinfo;
     61	u32			val;
     62	
     63	val = INREG(chan->ddc_reg);
     64
     65	return (val & VGA_DDC_DATA_INPUT) ? 1 : 0;
     66}
     67
     68static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name)
     69{
     70	int rc;
     71
     72	snprintf(chan->adapter.name, sizeof(chan->adapter.name),
     73		 "radeonfb %s", name);
     74	chan->adapter.owner		= THIS_MODULE;
     75	chan->adapter.algo_data		= &chan->algo;
     76	chan->adapter.dev.parent	= &chan->rinfo->pdev->dev;
     77	chan->algo.setsda		= radeon_gpio_setsda;
     78	chan->algo.setscl		= radeon_gpio_setscl;
     79	chan->algo.getsda		= radeon_gpio_getsda;
     80	chan->algo.getscl		= radeon_gpio_getscl;
     81	chan->algo.udelay		= 10;
     82	chan->algo.timeout		= 20;
     83	chan->algo.data 		= chan;	
     84	
     85	i2c_set_adapdata(&chan->adapter, chan);
     86	
     87	/* Raise SCL and SDA */
     88	radeon_gpio_setsda(chan, 1);
     89	radeon_gpio_setscl(chan, 1);
     90	udelay(20);
     91
     92	rc = i2c_bit_add_bus(&chan->adapter);
     93	if (rc == 0)
     94		dev_dbg(&chan->rinfo->pdev->dev, "I2C bus %s registered.\n", name);
     95	else
     96		dev_warn(&chan->rinfo->pdev->dev, "Failed to register I2C bus %s.\n", name);
     97	return rc;
     98}
     99
    100void radeon_create_i2c_busses(struct radeonfb_info *rinfo)
    101{
    102	rinfo->i2c[0].rinfo	= rinfo;
    103	rinfo->i2c[0].ddc_reg	= GPIO_MONID;
    104#ifndef CONFIG_PPC
    105	rinfo->i2c[0].adapter.class = I2C_CLASS_HWMON;
    106#endif
    107	radeon_setup_i2c_bus(&rinfo->i2c[0], "monid");
    108
    109	rinfo->i2c[1].rinfo	= rinfo;
    110	rinfo->i2c[1].ddc_reg	= GPIO_DVI_DDC;
    111	radeon_setup_i2c_bus(&rinfo->i2c[1], "dvi");
    112
    113	rinfo->i2c[2].rinfo	= rinfo;
    114	rinfo->i2c[2].ddc_reg	= GPIO_VGA_DDC;
    115	radeon_setup_i2c_bus(&rinfo->i2c[2], "vga");
    116
    117	rinfo->i2c[3].rinfo	= rinfo;
    118	rinfo->i2c[3].ddc_reg	= GPIO_CRT2_DDC;
    119	radeon_setup_i2c_bus(&rinfo->i2c[3], "crt2");
    120}
    121
    122void radeon_delete_i2c_busses(struct radeonfb_info *rinfo)
    123{
    124	if (rinfo->i2c[0].rinfo)
    125		i2c_del_adapter(&rinfo->i2c[0].adapter);
    126	rinfo->i2c[0].rinfo = NULL;
    127
    128	if (rinfo->i2c[1].rinfo)
    129		i2c_del_adapter(&rinfo->i2c[1].adapter);
    130	rinfo->i2c[1].rinfo = NULL;
    131
    132	if (rinfo->i2c[2].rinfo)
    133		i2c_del_adapter(&rinfo->i2c[2].adapter);
    134	rinfo->i2c[2].rinfo = NULL;
    135
    136	if (rinfo->i2c[3].rinfo)
    137		i2c_del_adapter(&rinfo->i2c[3].adapter);
    138	rinfo->i2c[3].rinfo = NULL;
    139}
    140
    141int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn,
    142			       u8 **out_edid)
    143{
    144	u8 *edid;
    145
    146	edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter);
    147
    148	if (out_edid)
    149		*out_edid = edid;
    150	if (!edid) {
    151		pr_debug("radeonfb: I2C (port %d) ... not found\n", conn);
    152		return MT_NONE;
    153	}
    154	if (edid[0x14] & 0x80) {
    155		/* Fix detection using BIOS tables */
    156		if (rinfo->is_mobility /*&& conn == ddc_dvi*/ &&
    157		    (INREG(LVDS_GEN_CNTL) & LVDS_ON)) {
    158			pr_debug("radeonfb: I2C (port %d) ... found LVDS panel\n", conn);
    159			return MT_LCD;
    160		} else {
    161			pr_debug("radeonfb: I2C (port %d) ... found TMDS panel\n", conn);
    162			return MT_DFP;
    163		}
    164	}
    165	pr_debug("radeonfb: I2C (port %d) ... found CRT display\n", conn);
    166	return MT_CRT;
    167}
    168