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