diff options
Diffstat (limited to 'drivers/video/nvidia/nv_i2c.c')
-rw-r--r-- | drivers/video/nvidia/nv_i2c.c | 94 |
1 files changed, 22 insertions, 72 deletions
diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c index b8588973e400..afe4567e1ff4 100644 --- a/drivers/video/nvidia/nv_i2c.c +++ b/drivers/video/nvidia/nv_i2c.c | |||
@@ -30,16 +30,14 @@ static void nvidia_gpio_setscl(void *data, int state) | |||
30 | struct nvidia_par *par = chan->par; | 30 | struct nvidia_par *par = chan->par; |
31 | u32 val; | 31 | u32 val; |
32 | 32 | ||
33 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); | 33 | val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; |
34 | val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; | ||
35 | 34 | ||
36 | if (state) | 35 | if (state) |
37 | val |= 0x20; | 36 | val |= 0x20; |
38 | else | 37 | else |
39 | val &= ~0x20; | 38 | val &= ~0x20; |
40 | 39 | ||
41 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); | 40 | NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); |
42 | VGA_WR08(par->PCIO, 0x3d5, val | 0x1); | ||
43 | } | 41 | } |
44 | 42 | ||
45 | static void nvidia_gpio_setsda(void *data, int state) | 43 | static void nvidia_gpio_setsda(void *data, int state) |
@@ -48,16 +46,14 @@ static void nvidia_gpio_setsda(void *data, int state) | |||
48 | struct nvidia_par *par = chan->par; | 46 | struct nvidia_par *par = chan->par; |
49 | u32 val; | 47 | u32 val; |
50 | 48 | ||
51 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); | 49 | val = NVReadCrtc(par, chan->ddc_base + 1) & 0xf0; |
52 | val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0; | ||
53 | 50 | ||
54 | if (state) | 51 | if (state) |
55 | val |= 0x10; | 52 | val |= 0x10; |
56 | else | 53 | else |
57 | val &= ~0x10; | 54 | val &= ~0x10; |
58 | 55 | ||
59 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1); | 56 | NVWriteCrtc(par, chan->ddc_base + 1, val | 0x01); |
60 | VGA_WR08(par->PCIO, 0x3d5, val | 0x1); | ||
61 | } | 57 | } |
62 | 58 | ||
63 | static int nvidia_gpio_getscl(void *data) | 59 | static int nvidia_gpio_getscl(void *data) |
@@ -66,12 +62,9 @@ static int nvidia_gpio_getscl(void *data) | |||
66 | struct nvidia_par *par = chan->par; | 62 | struct nvidia_par *par = chan->par; |
67 | u32 val = 0; | 63 | u32 val = 0; |
68 | 64 | ||
69 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); | 65 | if (NVReadCrtc(par, chan->ddc_base) & 0x04) |
70 | if (VGA_RD08(par->PCIO, 0x3d5) & 0x04) | ||
71 | val = 1; | 66 | val = 1; |
72 | 67 | ||
73 | val = VGA_RD08(par->PCIO, 0x3d5); | ||
74 | |||
75 | return val; | 68 | return val; |
76 | } | 69 | } |
77 | 70 | ||
@@ -81,20 +74,21 @@ static int nvidia_gpio_getsda(void *data) | |||
81 | struct nvidia_par *par = chan->par; | 74 | struct nvidia_par *par = chan->par; |
82 | u32 val = 0; | 75 | u32 val = 0; |
83 | 76 | ||
84 | VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base); | 77 | if (NVReadCrtc(par, chan->ddc_base) & 0x08) |
85 | if (VGA_RD08(par->PCIO, 0x3d5) & 0x08) | ||
86 | val = 1; | 78 | val = 1; |
87 | 79 | ||
88 | return val; | 80 | return val; |
89 | } | 81 | } |
90 | 82 | ||
91 | static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name) | 83 | static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name, |
84 | unsigned int i2c_class) | ||
92 | { | 85 | { |
93 | int rc; | 86 | int rc; |
94 | 87 | ||
95 | strcpy(chan->adapter.name, name); | 88 | strcpy(chan->adapter.name, name); |
96 | chan->adapter.owner = THIS_MODULE; | 89 | chan->adapter.owner = THIS_MODULE; |
97 | chan->adapter.id = I2C_HW_B_NVIDIA; | 90 | chan->adapter.id = I2C_HW_B_NVIDIA; |
91 | chan->adapter.class = i2c_class; | ||
98 | chan->adapter.algo_data = &chan->algo; | 92 | chan->adapter.algo_data = &chan->algo; |
99 | chan->adapter.dev.parent = &chan->par->pci_dev->dev; | 93 | chan->adapter.dev.parent = &chan->par->pci_dev->dev; |
100 | chan->algo.setsda = nvidia_gpio_setsda; | 94 | chan->algo.setsda = nvidia_gpio_setsda; |
@@ -127,83 +121,39 @@ static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name) | |||
127 | 121 | ||
128 | void nvidia_create_i2c_busses(struct nvidia_par *par) | 122 | void nvidia_create_i2c_busses(struct nvidia_par *par) |
129 | { | 123 | { |
130 | par->bus = 3; | ||
131 | |||
132 | par->chan[0].par = par; | 124 | par->chan[0].par = par; |
133 | par->chan[1].par = par; | 125 | par->chan[1].par = par; |
134 | par->chan[2].par = par; | 126 | par->chan[2].par = par; |
135 | 127 | ||
136 | par->chan[0].ddc_base = 0x3e; | 128 | par->chan[0].ddc_base = 0x36; |
137 | nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0"); | 129 | nvidia_setup_i2c_bus(&par->chan[0], "nvidia #0", I2C_CLASS_HWMON); |
138 | 130 | ||
139 | par->chan[1].ddc_base = 0x36; | 131 | par->chan[1].ddc_base = 0x3e; |
140 | nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1"); | 132 | nvidia_setup_i2c_bus(&par->chan[1], "nvidia #1", 0); |
141 | 133 | ||
142 | par->chan[2].ddc_base = 0x50; | 134 | par->chan[2].ddc_base = 0x50; |
143 | nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2"); | 135 | nvidia_setup_i2c_bus(&par->chan[2], "nvidia #2", 0); |
144 | } | 136 | } |
145 | 137 | ||
146 | void nvidia_delete_i2c_busses(struct nvidia_par *par) | 138 | void nvidia_delete_i2c_busses(struct nvidia_par *par) |
147 | { | 139 | { |
148 | if (par->chan[0].par) | 140 | int i; |
149 | i2c_del_adapter(&par->chan[0].adapter); | ||
150 | par->chan[0].par = NULL; | ||
151 | |||
152 | if (par->chan[1].par) | ||
153 | i2c_del_adapter(&par->chan[1].adapter); | ||
154 | par->chan[1].par = NULL; | ||
155 | |||
156 | if (par->chan[2].par) | ||
157 | i2c_del_adapter(&par->chan[2].adapter); | ||
158 | par->chan[2].par = NULL; | ||
159 | |||
160 | } | ||
161 | 141 | ||
162 | static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan) | 142 | for (i = 0; i < 3; i++) { |
163 | { | 143 | if (!par->chan[i].par) |
164 | u8 start = 0x0; | 144 | continue; |
165 | struct i2c_msg msgs[] = { | 145 | i2c_del_adapter(&par->chan[i].adapter); |
166 | { | 146 | par->chan[i].par = NULL; |
167 | .addr = 0x50, | ||
168 | .len = 1, | ||
169 | .buf = &start, | ||
170 | }, { | ||
171 | .addr = 0x50, | ||
172 | .flags = I2C_M_RD, | ||
173 | .len = EDID_LENGTH, | ||
174 | }, | ||
175 | }; | ||
176 | u8 *buf; | ||
177 | |||
178 | if (!chan->par) | ||
179 | return NULL; | ||
180 | |||
181 | buf = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
182 | if (!buf) { | ||
183 | dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n"); | ||
184 | return NULL; | ||
185 | } | 147 | } |
186 | msgs[1].buf = buf; | ||
187 | |||
188 | if (i2c_transfer(&chan->adapter, msgs, 2) == 2) | ||
189 | return buf; | ||
190 | dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n"); | ||
191 | kfree(buf); | ||
192 | return NULL; | ||
193 | } | 148 | } |
194 | 149 | ||
195 | int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) | 150 | int nvidia_probe_i2c_connector(struct fb_info *info, int conn, u8 **out_edid) |
196 | { | 151 | { |
197 | struct nvidia_par *par = info->par; | 152 | struct nvidia_par *par = info->par; |
198 | u8 *edid = NULL; | 153 | u8 *edid = NULL; |
199 | int i; | ||
200 | 154 | ||
201 | for (i = 0; i < 3; i++) { | 155 | if (par->chan[conn - 1].par) |
202 | /* Do the real work */ | 156 | edid = fb_ddc_read(&par->chan[conn - 1].adapter); |
203 | edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]); | ||
204 | if (edid) | ||
205 | break; | ||
206 | } | ||
207 | 157 | ||
208 | if (!edid && conn == 1) { | 158 | if (!edid && conn == 1) { |
209 | /* try to get from firmware */ | 159 | /* try to get from firmware */ |