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