diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_dp.c | 87 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.h | 8 |
3 files changed, 72 insertions, 62 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 33742b11188b..8a1b188b4cd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -572,47 +572,64 @@ out: | |||
572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); | 572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); |
573 | } | 573 | } |
574 | 574 | ||
575 | int | 575 | static int |
576 | nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 576 | nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
577 | uint8_t write_byte, uint8_t *read_byte) | ||
578 | { | 577 | { |
579 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | 578 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; |
580 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter; | ||
581 | struct drm_device *dev = auxch->dev; | 579 | struct drm_device *dev = auxch->dev; |
582 | int ret = 0, cmd, addr = algo_data->address; | 580 | struct i2c_msg *msg = msgs; |
583 | uint8_t *buf; | 581 | int ret, mcnt = num; |
584 | |||
585 | if (mode == MODE_I2C_READ) { | ||
586 | cmd = AUX_I2C_READ; | ||
587 | buf = read_byte; | ||
588 | } else { | ||
589 | cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE; | ||
590 | buf = &write_byte; | ||
591 | } | ||
592 | 582 | ||
593 | if (!(mode & MODE_I2C_STOP)) | 583 | while (mcnt--) { |
594 | cmd |= AUX_I2C_MOT; | 584 | u8 remaining = msg->len; |
585 | u8 *ptr = msg->buf; | ||
595 | 586 | ||
596 | if (mode & MODE_I2C_START) | 587 | while (remaining) { |
597 | return 1; | 588 | u8 cnt = (remaining > 16) ? 16 : remaining; |
589 | u8 cmd; | ||
598 | 590 | ||
599 | for (;;) { | 591 | if (msg->flags & I2C_M_RD) |
600 | ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1); | 592 | cmd = AUX_I2C_READ; |
601 | if (ret < 0) | 593 | else |
602 | return ret; | 594 | cmd = AUX_I2C_WRITE; |
603 | 595 | ||
604 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { | 596 | if (mcnt || remaining > 16) |
605 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: | 597 | cmd |= AUX_I2C_MOT; |
606 | return 1; | 598 | |
607 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: | 599 | ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt); |
608 | return -EREMOTEIO; | 600 | if (ret < 0) |
609 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | 601 | return ret; |
610 | udelay(100); | 602 | |
611 | break; | 603 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { |
612 | default: | 604 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: |
613 | NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret); | 605 | break; |
614 | return -EREMOTEIO; | 606 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: |
607 | return -EREMOTEIO; | ||
608 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | ||
609 | udelay(100); | ||
610 | continue; | ||
611 | default: | ||
612 | NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); | ||
613 | return -EREMOTEIO; | ||
614 | } | ||
615 | |||
616 | ptr += cnt; | ||
617 | remaining -= cnt; | ||
615 | } | 618 | } |
619 | |||
620 | msg++; | ||
616 | } | 621 | } |
622 | |||
623 | return num; | ||
624 | } | ||
625 | |||
626 | static u32 | ||
627 | nouveau_dp_i2c_func(struct i2c_adapter *adap) | ||
628 | { | ||
629 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
617 | } | 630 | } |
618 | 631 | ||
632 | const struct i2c_algorithm nouveau_dp_i2c_algo = { | ||
633 | .master_xfer = nouveau_dp_i2c_xfer, | ||
634 | .functionality = nouveau_dp_i2c_func | ||
635 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index cb0cb34440c6..9df711fdbbc5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -174,26 +174,26 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
174 | 174 | ||
175 | switch (entry->port_type) { | 175 | switch (entry->port_type) { |
176 | case 0: | 176 | case 0: |
177 | i2c->algo.bit.setsda = nv04_i2c_setsda; | 177 | i2c->bit.setsda = nv04_i2c_setsda; |
178 | i2c->algo.bit.setscl = nv04_i2c_setscl; | 178 | i2c->bit.setscl = nv04_i2c_setscl; |
179 | i2c->algo.bit.getsda = nv04_i2c_getsda; | 179 | i2c->bit.getsda = nv04_i2c_getsda; |
180 | i2c->algo.bit.getscl = nv04_i2c_getscl; | 180 | i2c->bit.getscl = nv04_i2c_getscl; |
181 | i2c->rd = entry->read; | 181 | i2c->rd = entry->read; |
182 | i2c->wr = entry->write; | 182 | i2c->wr = entry->write; |
183 | break; | 183 | break; |
184 | case 4: | 184 | case 4: |
185 | i2c->algo.bit.setsda = nv4e_i2c_setsda; | 185 | i2c->bit.setsda = nv4e_i2c_setsda; |
186 | i2c->algo.bit.setscl = nv4e_i2c_setscl; | 186 | i2c->bit.setscl = nv4e_i2c_setscl; |
187 | i2c->algo.bit.getsda = nv4e_i2c_getsda; | 187 | i2c->bit.getsda = nv4e_i2c_getsda; |
188 | i2c->algo.bit.getscl = nv4e_i2c_getscl; | 188 | i2c->bit.getscl = nv4e_i2c_getscl; |
189 | i2c->rd = 0x600800 + entry->read; | 189 | i2c->rd = 0x600800 + entry->read; |
190 | i2c->wr = 0x600800 + entry->write; | 190 | i2c->wr = 0x600800 + entry->write; |
191 | break; | 191 | break; |
192 | case 5: | 192 | case 5: |
193 | i2c->algo.bit.setsda = nv50_i2c_setsda; | 193 | i2c->bit.setsda = nv50_i2c_setsda; |
194 | i2c->algo.bit.setscl = nv50_i2c_setscl; | 194 | i2c->bit.setscl = nv50_i2c_setscl; |
195 | i2c->algo.bit.getsda = nv50_i2c_getsda; | 195 | i2c->bit.getsda = nv50_i2c_getsda; |
196 | i2c->algo.bit.getscl = nv50_i2c_getscl; | 196 | i2c->bit.getscl = nv50_i2c_getscl; |
197 | i2c->rd = nv50_i2c_port[entry->read]; | 197 | i2c->rd = nv50_i2c_port[entry->read]; |
198 | i2c->wr = i2c->rd; | 198 | i2c->wr = i2c->rd; |
199 | break; | 199 | break; |
@@ -216,17 +216,14 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
216 | i2c_set_adapdata(&i2c->adapter, i2c); | 216 | i2c_set_adapdata(&i2c->adapter, i2c); |
217 | 217 | ||
218 | if (entry->port_type < 6) { | 218 | if (entry->port_type < 6) { |
219 | i2c->adapter.algo_data = &i2c->algo.bit; | 219 | i2c->adapter.algo_data = &i2c->bit; |
220 | i2c->algo.bit.udelay = 40; | 220 | i2c->bit.udelay = 40; |
221 | i2c->algo.bit.timeout = usecs_to_jiffies(5000); | 221 | i2c->bit.timeout = usecs_to_jiffies(5000); |
222 | i2c->algo.bit.data = i2c; | 222 | i2c->bit.data = i2c; |
223 | ret = i2c_bit_add_bus(&i2c->adapter); | 223 | ret = i2c_bit_add_bus(&i2c->adapter); |
224 | } else { | 224 | } else { |
225 | i2c->adapter.algo_data = &i2c->algo.dp; | 225 | i2c->adapter.algo = &nouveau_dp_i2c_algo; |
226 | i2c->algo.dp.running = false; | 226 | ret = i2c_add_adapter(&i2c->adapter); |
227 | i2c->algo.dp.address = 0; | ||
228 | i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch; | ||
229 | ret = i2c_dp_aux_add_bus(&i2c->adapter); | ||
230 | } | 227 | } |
231 | 228 | ||
232 | if (ret) { | 229 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 6dd2f8713cd1..f71cb32f7571 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -33,10 +33,7 @@ struct dcb_i2c_entry; | |||
33 | struct nouveau_i2c_chan { | 33 | struct nouveau_i2c_chan { |
34 | struct i2c_adapter adapter; | 34 | struct i2c_adapter adapter; |
35 | struct drm_device *dev; | 35 | struct drm_device *dev; |
36 | union { | 36 | struct i2c_algo_bit_data bit; |
37 | struct i2c_algo_bit_data bit; | ||
38 | struct i2c_algo_dp_aux_data dp; | ||
39 | } algo; | ||
40 | unsigned rd; | 37 | unsigned rd; |
41 | unsigned wr; | 38 | unsigned wr; |
42 | unsigned data; | 39 | unsigned data; |
@@ -49,7 +46,6 @@ bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | |||
49 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
50 | struct i2c_board_info *info, int index); | 47 | struct i2c_board_info *info, int index); |
51 | 48 | ||
52 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, | 49 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; |
53 | uint8_t *read_byte); | ||
54 | 50 | ||
55 | #endif /* __NOUVEAU_I2C_H__ */ | 51 | #endif /* __NOUVEAU_I2C_H__ */ |