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 | |
18 | static 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 | |
32 | static 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 | |
46 | static 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 | |
57 | static 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 | |
68 | static int radeon_setup_i2c_bus(struct radeon_i2c_chan *chan, const char *name) |
69 | { |
70 | int rc; |
71 | |
72 | snprintf(buf: chan->adapter.name, size: sizeof(chan->adapter.name), |
73 | fmt: "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(adap: &chan->adapter, data: chan); |
86 | |
87 | /* Raise SCL and SDA */ |
88 | radeon_gpio_setsda(data: chan, state: 1); |
89 | radeon_gpio_setscl(data: chan, state: 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 | |
100 | void 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(chan: &rinfo->i2c[0], name: "monid" ); |
108 | |
109 | rinfo->i2c[1].rinfo = rinfo; |
110 | rinfo->i2c[1].ddc_reg = GPIO_DVI_DDC; |
111 | radeon_setup_i2c_bus(chan: &rinfo->i2c[1], name: "dvi" ); |
112 | |
113 | rinfo->i2c[2].rinfo = rinfo; |
114 | rinfo->i2c[2].ddc_reg = GPIO_VGA_DDC; |
115 | radeon_setup_i2c_bus(chan: &rinfo->i2c[2], name: "vga" ); |
116 | |
117 | rinfo->i2c[3].rinfo = rinfo; |
118 | rinfo->i2c[3].ddc_reg = GPIO_CRT2_DDC; |
119 | radeon_setup_i2c_bus(chan: &rinfo->i2c[3], name: "crt2" ); |
120 | } |
121 | |
122 | void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) |
123 | { |
124 | if (rinfo->i2c[0].rinfo) |
125 | i2c_del_adapter(adap: &rinfo->i2c[0].adapter); |
126 | rinfo->i2c[0].rinfo = NULL; |
127 | |
128 | if (rinfo->i2c[1].rinfo) |
129 | i2c_del_adapter(adap: &rinfo->i2c[1].adapter); |
130 | rinfo->i2c[1].rinfo = NULL; |
131 | |
132 | if (rinfo->i2c[2].rinfo) |
133 | i2c_del_adapter(adap: &rinfo->i2c[2].adapter); |
134 | rinfo->i2c[2].rinfo = NULL; |
135 | |
136 | if (rinfo->i2c[3].rinfo) |
137 | i2c_del_adapter(adap: &rinfo->i2c[3].adapter); |
138 | rinfo->i2c[3].rinfo = NULL; |
139 | } |
140 | |
141 | int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, |
142 | u8 **out_edid) |
143 | { |
144 | u8 *edid; |
145 | |
146 | edid = fb_ddc_read(adapter: &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 | |
169 | |