diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-07-02 06:43:42 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-09-20 02:05:24 -0400 |
commit | eeb3ca12b4658c569bd60fe60c4c45c627e842a6 (patch) | |
tree | f4e4340e8ec379cf8b8e90fb1df7b4135b1ffefa /drivers/gpu | |
parent | d9f61c2d2847fb2889ed01d2240db38927ab7e18 (diff) |
drm/nvd0/i2c: initial implementation
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.c | 51 |
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index cb389d014326..739c0ac3a9b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -107,6 +107,13 @@ nv4e_i2c_getsda(void *data) | |||
107 | return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); | 107 | return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); |
108 | } | 108 | } |
109 | 109 | ||
110 | static const uint32_t nv50_i2c_port[] = { | ||
111 | 0x00e138, 0x00e150, 0x00e168, 0x00e180, | ||
112 | 0x00e254, 0x00e274, 0x00e764, 0x00e780, | ||
113 | 0x00e79c, 0x00e7b8 | ||
114 | }; | ||
115 | #define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) | ||
116 | |||
110 | static int | 117 | static int |
111 | nv50_i2c_getscl(void *data) | 118 | nv50_i2c_getscl(void *data) |
112 | { | 119 | { |
@@ -130,28 +137,32 @@ static void | |||
130 | nv50_i2c_setscl(void *data, int state) | 137 | nv50_i2c_setscl(void *data, int state) |
131 | { | 138 | { |
132 | struct nouveau_i2c_chan *i2c = data; | 139 | struct nouveau_i2c_chan *i2c = data; |
133 | struct drm_device *dev = i2c->dev; | ||
134 | 140 | ||
135 | nv_wr32(dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); | 141 | nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); |
136 | } | 142 | } |
137 | 143 | ||
138 | static void | 144 | static void |
139 | nv50_i2c_setsda(void *data, int state) | 145 | nv50_i2c_setsda(void *data, int state) |
140 | { | 146 | { |
141 | struct nouveau_i2c_chan *i2c = data; | 147 | struct nouveau_i2c_chan *i2c = data; |
142 | struct drm_device *dev = i2c->dev; | ||
143 | 148 | ||
144 | nv_wr32(dev, i2c->wr, | 149 | nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); |
145 | (nv_rd32(dev, i2c->rd) & 1) | 4 | (state ? 2 : 0)); | ||
146 | i2c->data = state; | 150 | i2c->data = state; |
147 | } | 151 | } |
148 | 152 | ||
149 | static const uint32_t nv50_i2c_port[] = { | 153 | static int |
150 | 0x00e138, 0x00e150, 0x00e168, 0x00e180, | 154 | nvd0_i2c_getscl(void *data) |
151 | 0x00e254, 0x00e274, 0x00e764, 0x00e780, | 155 | { |
152 | 0x00e79c, 0x00e7b8 | 156 | struct nouveau_i2c_chan *i2c = data; |
153 | }; | 157 | return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); |
154 | #define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) | 158 | } |
159 | |||
160 | static int | ||
161 | nvd0_i2c_getsda(void *data) | ||
162 | { | ||
163 | struct nouveau_i2c_chan *i2c = data; | ||
164 | return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); | ||
165 | } | ||
155 | 166 | ||
156 | int | 167 | int |
157 | nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | 168 | nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) |
@@ -163,7 +174,8 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
163 | if (entry->chan) | 174 | if (entry->chan) |
164 | return -EEXIST; | 175 | return -EEXIST; |
165 | 176 | ||
166 | if (dev_priv->card_type >= NV_50 && entry->read >= NV50_I2C_PORTS) { | 177 | if (dev_priv->card_type >= NV_50 && |
178 | dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { | ||
167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); | 179 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); |
168 | return -EINVAL; | 180 | return -EINVAL; |
169 | } | 181 | } |
@@ -192,10 +204,17 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
192 | case 5: | 204 | case 5: |
193 | i2c->bit.setsda = nv50_i2c_setsda; | 205 | i2c->bit.setsda = nv50_i2c_setsda; |
194 | i2c->bit.setscl = nv50_i2c_setscl; | 206 | i2c->bit.setscl = nv50_i2c_setscl; |
195 | i2c->bit.getsda = nv50_i2c_getsda; | 207 | if (dev_priv->card_type < NV_D0) { |
196 | i2c->bit.getscl = nv50_i2c_getscl; | 208 | i2c->bit.getsda = nv50_i2c_getsda; |
197 | i2c->rd = nv50_i2c_port[entry->read]; | 209 | i2c->bit.getscl = nv50_i2c_getscl; |
198 | i2c->wr = i2c->rd; | 210 | i2c->rd = nv50_i2c_port[entry->read]; |
211 | i2c->wr = i2c->rd; | ||
212 | } else { | ||
213 | i2c->bit.getsda = nvd0_i2c_getsda; | ||
214 | i2c->bit.getscl = nvd0_i2c_getscl; | ||
215 | i2c->rd = 0x00d014 + (entry->read * 0x20); | ||
216 | i2c->wr = i2c->rd; | ||
217 | } | ||
199 | break; | 218 | break; |
200 | case 6: | 219 | case 6: |
201 | i2c->rd = entry->read; | 220 | i2c->rd = entry->read; |