aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2014-05-08 10:58:04 -0400
committerAlex Deucher <alexander.deucher@amd.com>2014-06-02 10:25:02 -0400
commit831719d62f692e28699a7acd7b441c6f0c01b6f7 (patch)
tree7f9bcfe0d74ae6cae476ab9b597b1a6abfd80446 /drivers
parent182407a6ed5333fc37dd980a8de91a8f826a94f6 (diff)
drm/radeon: add a i2c bus mutex
The i2c and aux buses use the same pads so add a mutex to protect access to the pads. Signed-off-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c18
-rw-r--r--drivers/gpu/drm/radeon/atombios_i2c.c17
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h1
4 files changed, 37 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index bc0119fb6c12..330f8df65b09 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -95,9 +95,12 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
95 int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 95 int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction);
96 unsigned char *base; 96 unsigned char *base;
97 int recv_bytes; 97 int recv_bytes;
98 int r = 0;
98 99
99 memset(&args, 0, sizeof(args)); 100 memset(&args, 0, sizeof(args));
100 101
102 mutex_lock(&chan->mutex);
103
101 base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); 104 base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
102 105
103 radeon_atom_copy_swap(base, send, send_bytes, true); 106 radeon_atom_copy_swap(base, send, send_bytes, true);
@@ -117,19 +120,22 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
117 /* timeout */ 120 /* timeout */
118 if (args.v1.ucReplyStatus == 1) { 121 if (args.v1.ucReplyStatus == 1) {
119 DRM_DEBUG_KMS("dp_aux_ch timeout\n"); 122 DRM_DEBUG_KMS("dp_aux_ch timeout\n");
120 return -ETIMEDOUT; 123 r = -ETIMEDOUT;
124 goto done;
121 } 125 }
122 126
123 /* flags not zero */ 127 /* flags not zero */
124 if (args.v1.ucReplyStatus == 2) { 128 if (args.v1.ucReplyStatus == 2) {
125 DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); 129 DRM_DEBUG_KMS("dp_aux_ch flags not zero\n");
126 return -EBUSY; 130 r = -EBUSY;
131 goto done;
127 } 132 }
128 133
129 /* error */ 134 /* error */
130 if (args.v1.ucReplyStatus == 3) { 135 if (args.v1.ucReplyStatus == 3) {
131 DRM_DEBUG_KMS("dp_aux_ch error\n"); 136 DRM_DEBUG_KMS("dp_aux_ch error\n");
132 return -EIO; 137 r = -EIO;
138 goto done;
133 } 139 }
134 140
135 recv_bytes = args.v1.ucDataOutLen; 141 recv_bytes = args.v1.ucDataOutLen;
@@ -139,7 +145,11 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
139 if (recv && recv_size) 145 if (recv && recv_size)
140 radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); 146 radeon_atom_copy_swap(recv, base + 16, recv_bytes, false);
141 147
142 return recv_bytes; 148 r = recv_bytes;
149done:
150 mutex_unlock(&chan->mutex);
151
152 return r;
143} 153}
144 154
145#define BARE_ADDRESS_SIZE 3 155#define BARE_ADDRESS_SIZE 3
diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c
index b5162c3b6111..9c570fb15b8c 100644
--- a/drivers/gpu/drm/radeon/atombios_i2c.c
+++ b/drivers/gpu/drm/radeon/atombios_i2c.c
@@ -43,15 +43,19 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
43 int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); 43 int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction);
44 unsigned char *base; 44 unsigned char *base;
45 u16 out = cpu_to_le16(0); 45 u16 out = cpu_to_le16(0);
46 int r = 0;
46 47
47 memset(&args, 0, sizeof(args)); 48 memset(&args, 0, sizeof(args));
48 49
50 mutex_lock(&chan->mutex);
51
49 base = (unsigned char *)rdev->mode_info.atom_context->scratch; 52 base = (unsigned char *)rdev->mode_info.atom_context->scratch;
50 53
51 if (flags & HW_I2C_WRITE) { 54 if (flags & HW_I2C_WRITE) {
52 if (num > ATOM_MAX_HW_I2C_WRITE) { 55 if (num > ATOM_MAX_HW_I2C_WRITE) {
53 DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num); 56 DRM_ERROR("hw i2c: tried to write too many bytes (%d vs 3)\n", num);
54 return -EINVAL; 57 r = -EINVAL;
58 goto done;
55 } 59 }
56 if (buf == NULL) 60 if (buf == NULL)
57 args.ucRegIndex = 0; 61 args.ucRegIndex = 0;
@@ -65,7 +69,8 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
65 } else { 69 } else {
66 if (num > ATOM_MAX_HW_I2C_READ) { 70 if (num > ATOM_MAX_HW_I2C_READ) {
67 DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num); 71 DRM_ERROR("hw i2c: tried to read too many bytes (%d vs 255)\n", num);
68 return -EINVAL; 72 r = -EINVAL;
73 goto done;
69 } 74 }
70 args.ucRegIndex = 0; 75 args.ucRegIndex = 0;
71 args.lpI2CDataOut = 0; 76 args.lpI2CDataOut = 0;
@@ -82,13 +87,17 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan,
82 /* error */ 87 /* error */
83 if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) { 88 if (args.ucStatus != HW_ASSISTED_I2C_STATUS_SUCCESS) {
84 DRM_DEBUG_KMS("hw_i2c error\n"); 89 DRM_DEBUG_KMS("hw_i2c error\n");
85 return -EIO; 90 r = -EIO;
91 goto done;
86 } 92 }
87 93
88 if (!(flags & HW_I2C_WRITE)) 94 if (!(flags & HW_I2C_WRITE))
89 radeon_atom_copy_swap(buf, base, num, false); 95 radeon_atom_copy_swap(buf, base, num, false);
90 96
91 return 0; 97done:
98 mutex_unlock(&chan->mutex);
99
100 return r;
92} 101}
93 102
94int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap, 103int radeon_atom_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 7b944142a9fd..427ee4d6d0b5 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -94,6 +94,8 @@ static int pre_xfer(struct i2c_adapter *i2c_adap)
94 struct radeon_i2c_bus_rec *rec = &i2c->rec; 94 struct radeon_i2c_bus_rec *rec = &i2c->rec;
95 uint32_t temp; 95 uint32_t temp;
96 96
97 mutex_lock(&i2c->mutex);
98
97 /* RV410 appears to have a bug where the hw i2c in reset 99 /* RV410 appears to have a bug where the hw i2c in reset
98 * holds the i2c port in a bad state - switch hw i2c away before 100 * holds the i2c port in a bad state - switch hw i2c away before
99 * doing DDC - do this for all r200s/r300s/r400s for safety sake 101 * doing DDC - do this for all r200s/r300s/r400s for safety sake
@@ -170,6 +172,8 @@ static void post_xfer(struct i2c_adapter *i2c_adap)
170 temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask; 172 temp = RREG32(rec->mask_data_reg) & ~rec->mask_data_mask;
171 WREG32(rec->mask_data_reg, temp); 173 WREG32(rec->mask_data_reg, temp);
172 temp = RREG32(rec->mask_data_reg); 174 temp = RREG32(rec->mask_data_reg);
175
176 mutex_unlock(&i2c->mutex);
173} 177}
174 178
175static int get_clock(void *i2c_priv) 179static int get_clock(void *i2c_priv)
@@ -813,6 +817,8 @@ static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
813 struct radeon_i2c_bus_rec *rec = &i2c->rec; 817 struct radeon_i2c_bus_rec *rec = &i2c->rec;
814 int ret = 0; 818 int ret = 0;
815 819
820 mutex_lock(&i2c->mutex);
821
816 switch (rdev->family) { 822 switch (rdev->family) {
817 case CHIP_R100: 823 case CHIP_R100:
818 case CHIP_RV100: 824 case CHIP_RV100:
@@ -879,6 +885,8 @@ static int radeon_hw_i2c_xfer(struct i2c_adapter *i2c_adap,
879 break; 885 break;
880 } 886 }
881 887
888 mutex_unlock(&i2c->mutex);
889
882 return ret; 890 return ret;
883} 891}
884 892
@@ -919,6 +927,7 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
919 i2c->adapter.dev.parent = &dev->pdev->dev; 927 i2c->adapter.dev.parent = &dev->pdev->dev;
920 i2c->dev = dev; 928 i2c->dev = dev;
921 i2c_set_adapdata(&i2c->adapter, i2c); 929 i2c_set_adapdata(&i2c->adapter, i2c);
930 mutex_init(&i2c->mutex);
922 if (rec->mm_i2c || 931 if (rec->mm_i2c ||
923 (rec->hw_capable && 932 (rec->hw_capable &&
924 radeon_hw_i2c && 933 radeon_hw_i2c &&
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 6ddf31a2d34e..b265a8b95fe6 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -191,6 +191,7 @@ struct radeon_i2c_chan {
191 struct radeon_i2c_bus_rec rec; 191 struct radeon_i2c_bus_rec rec;
192 struct drm_dp_aux aux; 192 struct drm_dp_aux aux;
193 bool has_aux; 193 bool has_aux;
194 struct mutex mutex;
194}; 195};
195 196
196/* mostly for macs, but really any system without connector tables */ 197/* mostly for macs, but really any system without connector tables */