Subject | Hash | Author | Date (UTC) |
---|---|---|---|
page flip fix | e51d9d4b1788c17633b0cdffd7a50309d51f8d0f | Sylvain BERTRAND | 2014-08-30 14:08:35 |
ack-ing the DCE irqs at the right time | a12ec7f4781872de8d155e4e1d90b07df3e44c34 | Sylvain BERTRAND | 2014-08-28 15:23:29 |
normal programs use normal syscalls then ioctl | 37589b6856d941efdc763eed41b237f4f62cb960 | Sylvain BERTRAND | 2014-07-08 19:01:52 |
new firware breaks the 3D pipeline | 13db71ba4522d7266d68a21f43f25ee3781d0b92 | Sylvain BERTRAND | 2014-07-03 22:54:30 |
closed src or gnu gpl *not* v2 drivers are illegal | dc1de426b639ffee863b0a211e9cf0e349f855f0 | Sylvain BERTRAND | 2014-07-03 17:59:46 |
compiling with 3.16 rc2 new mc fw code | e00afdaeef8513da35c82cc82dcfee0745aa9129 | Sylvain BERTRAND | 2014-06-29 01:54:40 |
untested handling of new mc fw | eb89a71b0af7781d1fc9ee226c1269b6d5183749 | Sylvain BERTRAND | 2014-06-29 01:26:15 |
become legal | ef922b67f25aaf0c4f8cff5be572e53fb53bdfe5 | Sylvain BERTRAND | 2014-06-28 23:33:40 |
use usleep_range and fix a dp 1.1 time out | d4183ce73e6ec7d7f3baf9d710dd2ba015b4a6a9 | Sylvain BERTRAND | 2014-02-19 20:09:44 |
fix dac | a864ba601253674b679b07e4b1ddc00fb83a8cb6 | Sylvain BERTRAND | 2014-02-19 19:17:08 |
clear atombias dpm state and warn for instability | 28b598d81f6a873f90d1a9325e3e1002743487a5 | Sylvain BERTRAND | 2014-02-19 19:10:43 |
CFG_MEM_SZ upper 16bits may have garbage | f08f2e3471989e448d6d76ba02565fd9efc3293f | Sylvain BERTRAND | 2014-02-19 17:55:38 |
fix ena rbs mask performance critical bug | 289497449dd0f2acb09e03f65988e22e45948fb6 | Sylvain BERTRAND | 2014-02-19 17:15:18 |
upstream confirm bug, fixed | e2142c3fdfc01d51e7fec7687ec4d02f548ce763 | Sylvain BERTRAND | 2014-02-18 16:10:14 |
mainly bug fixing | 1650d6a6e13bd81a4df9bfaa84a5daef2989ccdf | Sylvain BERTRAND | 2014-02-18 12:46:40 |
dump smc sw regs | 5b42263039c858624ff411d94318f6ef5171a864 | Sylvain BERTRAND | 2014-02-17 12:22:26 |
disable switch to low power when no display | 69f94e04ea89c1fe9ccaef153da5f5ade232c2a1 | Sylvain BERTRAND | 2014-02-17 09:59:28 |
finish smc switch to driver power state | 6f99d0a01491dd671174919d842a771ac4a81a4b | Sylvain BERTRAND | 2014-02-17 09:47:02 |
pcie things and follow upstream for dyn pm init | f4fb120597276a3badc08eec30783b10d111f756 | Sylvain BERTRAND | 2014-02-17 09:00:00 |
dump performance state tbls | 06a22756b504ecf4523c86f657104e0b970195de | Sylvain BERTRAND | 2014-02-14 17:02:23 |
File drivers/gpu/alga/amd/atombios/dce.c changed (mode: 100644) (index 223ea69..da79a81) | |||
... | ... | unlock_mutex: | |
1304 | 1304 | } | } |
1305 | 1305 | EXPORT_SYMBOL_GPL(atb_crtc_lock); | EXPORT_SYMBOL_GPL(atb_crtc_lock); |
1306 | 1306 | ||
1307 | /* | ||
1308 | * The DCE vertical timings seems to: | ||
1309 | * - the vblank is cut in 2 parts: a top one and a bottom one | ||
1310 | * - the bottom vblank size (number of lines) seems to be the sync pulse | ||
1311 | * +-------------------------+ | ||
1312 | * | vblank top | | ||
1313 | * +-------------------------+ | ||
1314 | * | | | ||
1315 | * | frame | | ||
1316 | * | | | ||
1317 | * +-------------------------+ | ||
1318 | * | vblank bot = sync pulse | | ||
1319 | * +-------------------------+ | ||
1320 | */ | ||
1307 | 1321 | long atb_crtc_timing(struct atombios *atb, u8 i, struct alga_timing *t) | long atb_crtc_timing(struct atombios *atb, u8 i, struct alga_timing *t) |
1308 | 1322 | { | { |
1309 | 1323 | u16 of; | u16 of; |
File drivers/gpu/alga/amd/dce6/crtc.c changed (mode: 100644) (index 5508ab8..69c3638) | |||
... | ... | long crtc_fb(struct dce6 *dce, u8 i, struct sink_db_fb *db_fb) | |
29 | 29 | u32 fb_swap; | u32 fb_swap; |
30 | 30 | u32 viewport_h; | u32 viewport_h; |
31 | 31 | u32 viewport_v; | u32 viewport_v; |
32 | u32 tmp; | ||
32 | u32 grph_flip_ctl; | ||
33 | 33 | ||
34 | 34 | fb_swap = set(GSC_ENDIAN_SWAP, GSC_ENDIAN_NONE); | fb_swap = set(GSC_ENDIAN_SWAP, GSC_ENDIAN_NONE); |
35 | 35 | switch (db_fb->pixel_fmt) { | switch (db_fb->pixel_fmt) { |
... | ... | long crtc_fb(struct dce6 *dce, u8 i, struct sink_db_fb *db_fb) | |
87 | 87 | ||
88 | 88 | /* XXX: obsolete pageflip setup */ | /* XXX: obsolete pageflip setup */ |
89 | 89 | /* make sure flip is at vb rather than hb */ | /* make sure flip is at vb rather than hb */ |
90 | tmp = dce->ddev.rr32(dce->ddev.dev, regs_grph_flip_ctl[i]); | ||
91 | tmp &= ~GFC_SURF_UPDATE_H_RETRACE_ENA; | ||
92 | WR32(tmp, regs_grph_flip_ctl[i]); | ||
90 | grph_flip_ctl = dce->ddev.rr32(dce->ddev.dev, regs_grph_flip_ctl[i]); | ||
91 | grph_flip_ctl &= ~GFC_SURF_UPDATE_H_RETRACE_ENA; | ||
92 | WR32(grph_flip_ctl, regs_grph_flip_ctl[i]); | ||
93 | 93 | ||
94 | 94 | /* set pageflip to happen anywhere in vblank interval */ | /* set pageflip to happen anywhere in vblank interval */ |
95 | 95 | WR32(0, regs_master_update_mode[i]); | WR32(0, regs_master_update_mode[i]); |
... | ... | long dce6_crtcs_shutdown(struct dce6 *dce) | |
190 | 190 | } | } |
191 | 191 | EXPORT_SYMBOL_GPL(dce6_crtcs_shutdown); | EXPORT_SYMBOL_GPL(dce6_crtcs_shutdown); |
192 | 192 | ||
193 | static void page_flip(struct dce6 *dce, u8 i) | ||
193 | static long page_flip(struct dce6 *dce, u8 i) | ||
194 | 194 | { | { |
195 | u32 tmp; | ||
195 | u32 grph_update; | ||
196 | 196 | u64 swap; | u64 swap; |
197 | 197 | struct crtc_surfs *css; | struct crtc_surfs *css; |
198 | 198 | u32 j; | u32 j; |
199 | long r; | ||
200 | |||
201 | r = 0; | ||
199 | 202 | ||
200 | 203 | css = &dce->dps[i].pf.crtc_surfs; | css = &dce->dps[i].pf.crtc_surfs; |
201 | 204 | ||
... | ... | static void page_flip(struct dce6 *dce, u8 i) | |
203 | 206 | css->secondary = css->primary; | css->secondary = css->primary; |
204 | 207 | css->primary = swap; | css->primary = swap; |
205 | 208 | ||
206 | tmp = RR32(regs_grph_update[i]); | ||
207 | tmp |= GU_UPDATE_LOCK; | ||
208 | WR32(tmp, regs_grph_update[i]); | ||
209 | grph_update = RR32(regs_grph_update[i]); | ||
210 | grph_update |= GU_UPDATE_LOCK; | ||
211 | WR32(grph_update, regs_grph_update[i]); | ||
209 | 212 | ||
210 | 213 | WR32(upper_32_bits(css->primary), regs_grph_primary_surf_addr_high[i]); | WR32(upper_32_bits(css->primary), regs_grph_primary_surf_addr_high[i]); |
211 | 214 | WR32(upper_32_bits(css->secondary), | WR32(upper_32_bits(css->secondary), |
... | ... | static void page_flip(struct dce6 *dce, u8 i) | |
215 | 218 | WR32((u32)(css->secondary) & GSSA_SURF_ADDR_MASK, | WR32((u32)(css->secondary) & GSSA_SURF_ADDR_MASK, |
216 | 219 | regs_grph_secondary_surf_addr[i]); | regs_grph_secondary_surf_addr[i]); |
217 | 220 | ||
221 | /* wait for the notification to go high */ | ||
218 | 222 | for (j = 0; j < USEC_TIMEOUT; ++j) { | for (j = 0; j < USEC_TIMEOUT; ++j) { |
219 | 223 | if (RR32(regs_grph_update[i]) & GU_SURF_UPDATE_PENDING) | if (RR32(regs_grph_update[i]) & GU_SURF_UPDATE_PENDING) |
220 | 224 | break; | break; |
221 | 225 | udelay(1); | udelay(1); |
222 | 226 | } | } |
223 | if (j == USEC_TIMEOUT) | ||
224 | dev_warn(dce->ddev.dev, "dce6: page flip %u timed out\n", i); | ||
227 | if (j == USEC_TIMEOUT) { | ||
228 | dev_err(dce->ddev.dev, "dce6: page flip on %u timed out\n", i); | ||
229 | r = -DCE6_ERR; | ||
230 | } | ||
225 | 231 | ||
226 | tmp &= ~GU_UPDATE_LOCK; | ||
227 | WR32(tmp, regs_grph_update[i]); | ||
232 | grph_update &= ~GU_UPDATE_LOCK; | ||
233 | WR32(grph_update, regs_grph_update[i]); | ||
234 | return r; | ||
228 | 235 | } | } |
229 | 236 | ||
230 | 237 | /* | /* |
... | ... | static void page_flip(struct dce6 *dce, u8 i) | |
233 | 240 | */ | */ |
234 | 241 | void dce6_pf_irq(struct dce6 *dce, u8 i, struct timespec monotonic_raw_tp) | void dce6_pf_irq(struct dce6 *dce, u8 i, struct timespec monotonic_raw_tp) |
235 | 242 | { | { |
236 | u32 tmp; | ||
237 | u32 vblanks_n; | ||
243 | u32 crtc_int_mask; | ||
244 | u32 vblank_n; | ||
245 | |||
246 | vblank_n = RR32(regs_crtc_status_frame_cnt[i]); | ||
247 | |||
248 | /* | ||
249 | * XXX: we can be in the vblank handler only to notify a page flip | ||
250 | * completion. | ||
251 | * There are 2 things to keep in mind: | ||
252 | * - the vblank interrupt can happen a bit *before* the real vblank. | ||
253 | * (was told it's an hardware bug). | ||
254 | * - the page flip will be done in hardware during the vblank, you | ||
255 | * don't know when (insanity since they have the specs). | ||
256 | * It is supposed *not* to matter since, in vblank, the pixel of the | ||
257 | * visible frame buffer are supposed to be sent already to the display | ||
258 | * device. | ||
259 | * Meaning, starting to draw the next frame into the "maybe" not yet | ||
260 | * flipped visible framebuffer should have very little chance/no chance to | ||
261 | * glitch what's actually on screen. | ||
262 | * If it does glitch for whatever reason in some cases, will | ||
263 | * wait for the update pending bit to go low, hard way. | ||
264 | */ | ||
238 | 265 | ||
239 | /* disabling page flip is disabling the vblank interrupt */ | ||
240 | tmp = RR32(regs_crtc_int_mask[i]); | ||
241 | tmp &= ~IM_VBLANK_INT_MASK; | ||
242 | WR32(tmp, regs_crtc_int_mask[i]); | ||
266 | /* page flip is done */ | ||
243 | 267 | ||
244 | page_flip(dce, i); | ||
268 | /* we don't need the vblank interupt anymore */ | ||
269 | crtc_int_mask = RR32(regs_crtc_int_mask[i]); | ||
270 | crtc_int_mask &= ~IM_VBLANK_INT_MASK; | ||
271 | WR32(crtc_int_mask, regs_crtc_int_mask[i]); | ||
245 | 272 | ||
246 | vblanks_n = RR32(regs_crtc_status_frame_cnt[i]); | ||
247 | |||
248 | 273 | spin_lock(&dce->dps[i].pf.lock); | spin_lock(&dce->dps[i].pf.lock); |
249 | if (dce->dps[i].pf.notify) | ||
250 | dce->dps[i].pf.notify(i, vblanks_n, monotonic_raw_tp, | ||
274 | dce->dps[i].pf.notify(i, vblank_n, monotonic_raw_tp, | ||
251 | 275 | dce->dps[i].pf.data); | dce->dps[i].pf.data); |
252 | 276 | dce->dps[i].pf.notify = NULL; | dce->dps[i].pf.notify = NULL; |
253 | 277 | dce->dps[i].pf.data = NULL; | dce->dps[i].pf.data = NULL; |
... | ... | void dce6_pf_irq(struct dce6 *dce, u8 i, struct timespec monotonic_raw_tp) | |
255 | 279 | } | } |
256 | 280 | EXPORT_SYMBOL_GPL(dce6_pf_irq); | EXPORT_SYMBOL_GPL(dce6_pf_irq); |
257 | 281 | ||
258 | /* XXX: the notify function will be run in hard irq context */ | ||
259 | 282 | long dce6_pf(struct dce6 *dce, u8 i, | long dce6_pf(struct dce6 *dce, u8 i, |
260 | 283 | void (*notify)(u8 i, u32 vblanks_n, struct timespec monotonic_raw_tp, | void (*notify)(u8 i, u32 vblanks_n, struct timespec monotonic_raw_tp, |
261 | 284 | void *data), void *data) | void *data), void *data) |
262 | 285 | { | { |
263 | u32 tmp; | ||
286 | long r; | ||
287 | u32 crtc_int_mask; | ||
288 | |||
289 | r = 0; | ||
264 | 290 | ||
265 | 291 | lock(dce); | lock(dce); |
266 | /* scheduling a page flip is enabling vblank interrupt */ | ||
267 | tmp = RR32(regs_crtc_int_mask[i]); | ||
268 | tmp |= IM_VBLANK_INT_MASK; | ||
269 | WR32(tmp, regs_crtc_int_mask[i]); | ||
270 | 292 | ||
293 | /* if we are alreading waiting for a pf, notify the user */ | ||
271 | 294 | spin_lock_irq(&dce->dps[i].pf.lock); | spin_lock_irq(&dce->dps[i].pf.lock); |
295 | if (dce->dps[i].pf.notify) { | ||
296 | spin_unlock_irq(&dce->dps[i].pf.lock); | ||
297 | r = SI_DCE_PF_PENDING; | ||
298 | goto unlock_dce; | ||
299 | } | ||
300 | spin_unlock_irq(&dce->dps[i].pf.lock); | ||
301 | |||
302 | r = page_flip(dce, i); | ||
303 | if (r == -DCE6_ERR) | ||
304 | goto unlock_dce; | ||
305 | |||
306 | /* the notify function will be run in hard irq context */ | ||
272 | 307 | dce->dps[i].pf.notify = notify; | dce->dps[i].pf.notify = notify; |
273 | 308 | dce->dps[i].pf.data = data; | dce->dps[i].pf.data = data; |
274 | spin_unlock_irq(&dce->dps[i].pf.lock); | ||
275 | 309 | ||
310 | /* a page flip happens in a vblank */ | ||
311 | crtc_int_mask = RR32(regs_crtc_int_mask[i]); | ||
312 | crtc_int_mask |= IM_VBLANK_INT_MASK; | ||
313 | WR32(crtc_int_mask, regs_crtc_int_mask[i]); | ||
314 | |||
315 | unlock_dce: | ||
276 | 316 | unlock(dce); | unlock(dce); |
277 | return 0; | ||
317 | return r; | ||
278 | 318 | } | } |
279 | 319 | EXPORT_SYMBOL_GPL(dce6_pf); | EXPORT_SYMBOL_GPL(dce6_pf); |
280 | 320 | ||
... | ... | void dce6_pf_cancel_all(struct dce6 *dce) | |
288 | 328 | ||
289 | 329 | lock(dce); | lock(dce); |
290 | 330 | for (i = 0; i < dce->ddev.crtcs_n; ++i) { | for (i = 0; i < dce->ddev.crtcs_n; ++i) { |
331 | u32 crtc_int_mask; | ||
332 | |||
291 | 333 | if ((dce->dps_used & BIT(i)) == 0) | if ((dce->dps_used & BIT(i)) == 0) |
292 | 334 | continue; | continue; |
293 | 335 | ||
336 | /* shut down the vblank interrupt */ | ||
337 | crtc_int_mask = RR32(regs_crtc_int_mask[i]); | ||
338 | crtc_int_mask &= ~IM_VBLANK_INT_MASK; | ||
339 | WR32(crtc_int_mask, regs_crtc_int_mask[i]); | ||
340 | |||
294 | 341 | spin_lock_irq(&dce->dps[i].pf.lock); | spin_lock_irq(&dce->dps[i].pf.lock); |
295 | 342 | dce->dps[i].pf.notify = NULL; | dce->dps[i].pf.notify = NULL; |
296 | 343 | dce->dps[i].pf.data = NULL; | dce->dps[i].pf.data = NULL; |
File drivers/gpu/alga/amd/dce6/dce6.h changed (mode: 100644) (index 3fe78f9..17e1dd2) | |||
... | ... | struct crtc_surfs { | |
26 | 26 | u64 secondary; | u64 secondary; |
27 | 27 | }; | }; |
28 | 28 | ||
29 | #define PF_STATE_NONE 0 | ||
30 | #define PF_STATE_NOT_SUBMITED 1 | ||
31 | #define PF_STATE_SUBMITED 2 | ||
29 | 32 | struct pf { | struct pf { |
30 | 33 | struct crtc_surfs crtc_surfs; | struct crtc_surfs crtc_surfs; |
31 | /* this function will run in irq hard context */ | ||
34 | /* this function will run in irq hard context */ | ||
32 | 35 | spinlock_t lock; | spinlock_t lock; |
33 | 36 | void (*notify)(u8 i, u32 v_blanks_n, struct timespec monotonic_raw_tp, | void (*notify)(u8 i, u32 v_blanks_n, struct timespec monotonic_raw_tp, |
34 | 37 | void *data); | void *data); |
... | ... | struct dp { | |
64 | 67 | }; | }; |
65 | 68 | ||
66 | 69 | struct irq { | struct irq { |
67 | spinlock_t lock; | ||
70 | spinlock_t hpds_lock; | ||
68 | 71 | u8 hpds;/* protected by above spinlock */ | u8 hpds;/* protected by above spinlock */ |
69 | |||
70 | 72 | /* avoid child device registration after suspend "prepare" call */ | /* avoid child device registration after suspend "prepare" call */ |
71 | 73 | u8 hpd_dev_registration_lock;/* protected by the dce mutex */ | u8 hpd_dev_registration_lock;/* protected by the dce mutex */ |
72 | 74 | }; | }; |
File drivers/gpu/alga/amd/dce6/hpd.c changed (mode: 100644) (index 42b29f7..1f050b9) | |||
... | ... | long hpd_irq(struct dce6 *dce, u8 hpd) | |
226 | 226 | if (dce->dps[i].connected != sense) { | if (dce->dps[i].connected != sense) { |
227 | 227 | if (dce->irq.hpd_dev_registration_lock == 1 | if (dce->irq.hpd_dev_registration_lock == 1 |
228 | 228 | && sense == 1) { | && sense == 1) { |
229 | dev_warn(dce->ddev.dev, | ||
230 | "dce6:attempt to register a display device on dp%u while suspending\n", i); | ||
229 | dev_warn(dce->ddev.dev, "dce6:attempt to register a display device on dp%u while suspending\n", | ||
230 | i); | ||
231 | 231 | } else { | } else { |
232 | 232 | r = dp_toggle(dce, i); | r = dp_toggle(dce, i); |
233 | 233 | } | } |
... | ... | EXPORT_SYMBOL_GPL(dce6_hpds_intr_ena); | |
260 | 260 | ||
261 | 261 | void dce6_hpd_irq(struct dce6 *dce, u8 hpd) | void dce6_hpd_irq(struct dce6 *dce, u8 hpd) |
262 | 262 | { | { |
263 | unsigned long flgs; | ||
264 | |||
265 | spin_lock_irqsave(&dce->irq.lock, flgs); | ||
263 | /* we just flag the hpd and we will do the work in the irq thread */ | ||
264 | spin_lock(&dce->irq.hpds_lock); | ||
266 | 265 | dce->irq.hpds |= BIT(hpd); | dce->irq.hpds |= BIT(hpd); |
267 | spin_unlock_irqrestore(&dce->irq.lock, flgs); | ||
266 | spin_unlock(&dce->irq.hpds_lock); | ||
268 | 267 | } | } |
269 | 268 | EXPORT_SYMBOL_GPL(dce6_hpd_irq); | EXPORT_SYMBOL_GPL(dce6_hpd_irq); |
File drivers/gpu/alga/amd/dce6/irq.c changed (mode: 100644) (index 1ce0190..4b13811) | |||
... | ... | void dce6_irqs_ack(struct dce6 *dce) | |
63 | 63 | } | } |
64 | 64 | EXPORT_SYMBOL_GPL(dce6_irqs_ack); | EXPORT_SYMBOL_GPL(dce6_irqs_ack); |
65 | 65 | ||
66 | /* this will be run in the irq thread, then not the hard context */ | ||
66 | 67 | long dce6_irqs_thd(struct dce6 *dce) | long dce6_irqs_thd(struct dce6 *dce) |
67 | 68 | { | { |
68 | 69 | long r; | long r; |
69 | 70 | u8 i; | u8 i; |
70 | 71 | u8 hpds; | u8 hpds; |
71 | unsigned long flgs; | ||
72 | 72 | ||
73 | spin_lock_irqsave(&dce->irq.lock, flgs); | ||
73 | /* grab the flagged hpd pins */ | ||
74 | spin_lock_irq(&dce->irq.hpds_lock); | ||
74 | 75 | hpds = dce->irq.hpds; | hpds = dce->irq.hpds; |
75 | 76 | dce->irq.hpds = 0; | dce->irq.hpds = 0; |
76 | spin_unlock_irqrestore(&dce->irq.lock, flgs); | ||
77 | spin_unlock_irq(&dce->irq.hpds_lock); | ||
77 | 78 | ||
78 | 79 | r = 0; | r = 0; |
79 | 80 | for (i = 0; i < HPDS_N; ++i) | for (i = 0; i < HPDS_N; ++i) |
80 | 81 | if (hpds & BIT(i)) { | if (hpds & BIT(i)) { |
81 | 82 | r = hpd_irq(dce, i); | r = hpd_irq(dce, i); |
82 | 83 | if (r != 0) | if (r != 0) |
83 | dev_err(dce->ddev.dev, | ||
84 | "dce6:unable to service hpd%u interrupt request\n", i); | ||
84 | dev_err(dce->ddev.dev, "dce6:unable to service hpd%u interrupt request\n", | ||
85 | i); | ||
85 | 86 | } | } |
86 | 87 | return r; | return r; |
87 | 88 | } | } |
File drivers/gpu/alga/amd/dce6/mod.c changed (mode: 100644) (index 29bb03e..48604d2) | |||
... | ... | static void dps_connected_sysfs_shutdown(struct dce6 *dce) | |
557 | 557 | } | } |
558 | 558 | } | } |
559 | 559 | ||
560 | static void dps_pf_init_once(struct dce6 *dce) | ||
560 | static void dps_used_pf_lock_init_once(struct dce6 *dce) | ||
561 | 561 | { | { |
562 | 562 | u8 i; | u8 i; |
563 | |||
563 | 564 | for (i = 0; i < dce->ddev.crtcs_n; ++i) { | for (i = 0; i < dce->ddev.crtcs_n; ++i) { |
564 | 565 | if ((dce->dps_used & BIT(i)) == 0) | if ((dce->dps_used & BIT(i)) == 0) |
565 | 566 | continue; | continue; |
... | ... | long dce6_init_once(struct dce6 *dce) | |
572 | 573 | long r; | long r; |
573 | 574 | ||
574 | 575 | mutex_init(&dce->mutex); | mutex_init(&dce->mutex); |
575 | spin_lock_init(&dce->irq.lock); | ||
576 | |||
576 | spin_lock_init(&dce->irq.hpds_lock); | ||
577 | 577 | r = paths_parse(dce); | r = paths_parse(dce); |
578 | 578 | if (r == -DCE6_ERR) | if (r == -DCE6_ERR) |
579 | 579 | return -DCE6_ERR; | return -DCE6_ERR; |
580 | 580 | ||
581 | dps_pf_init_once(dce); | ||
582 | |||
581 | dps_used_pf_lock_init_once(dce); | ||
583 | 582 | dce_dump(dce); | dce_dump(dce); |
584 | 583 | return 0; | return 0; |
585 | 584 | } | } |
File drivers/gpu/alga/amd/dce6/regs.h changed (mode: 100644) (index 8f31975..c17b9ad) | |||
... | ... | static inline u32 get(u32 mask, u32 v) | |
475 | 475 | #define VIEWPORT_START 0x6d70 | #define VIEWPORT_START 0x6d70 |
476 | 476 | #define VIEWPORT_SZ 0x6d74 | #define VIEWPORT_SZ 0x6d74 |
477 | 477 | ||
478 | /* 0x6e34 ... */ | ||
479 | #define CRTC_VBLANK_START_END 0x6e34 | ||
480 | /* VSTART is the first line of VBLANK */ | ||
481 | #define CVSE_VSTART 0x00001fff | ||
482 | /* VEND is the first line after VBLANK space ??? */ | ||
483 | #define CVSE_VEND 0x1fff0000 | ||
484 | |||
478 | 485 | /* 0x6e70 ... */ | /* 0x6e70 ... */ |
479 | 486 | #define CRTC_CTL 0x6e70 | #define CRTC_CTL 0x6e70 |
480 | 487 | #define CC_MASTER_ENA BIT(0) | #define CC_MASTER_ENA BIT(0) |
481 | 488 | #define CC_VBLANK BIT(1) | #define CC_VBLANK BIT(1) |
482 | 489 | #define CC_DISP_READ_REQ_DIS BIT(24) | #define CC_DISP_READ_REQ_DIS BIT(24) |
490 | #define CRTC_STATUS_POS 0x6e90 | ||
491 | #define CSP_VPOS 0x00001fff | ||
492 | #define CSP_HPOS 0x1fff0000 | ||
483 | 493 | #define CRTC_STATUS_FRAME_CNT 0x6e98 | #define CRTC_STATUS_FRAME_CNT 0x6e98 |
484 | 494 | #define CRTC_UPDATE_LOCK 0x6ed4 | #define CRTC_UPDATE_LOCK 0x6ed4 |
485 | 495 | #define MASTER_UPDATE_MODE 0x6ef8 | #define MASTER_UPDATE_MODE 0x6ef8 |
486 | 496 | ||
497 | |||
498 | static u32 regs_crtc_status_pos[CRTCS_N_MAX] __attribute__ ((unused)) = { | ||
499 | CRTC_STATUS_POS + CRTC0_REG_OF, | ||
500 | CRTC_STATUS_POS + CRTC1_REG_OF, | ||
501 | CRTC_STATUS_POS + CRTC2_REG_OF, | ||
502 | CRTC_STATUS_POS + CRTC3_REG_OF, | ||
503 | CRTC_STATUS_POS + CRTC4_REG_OF, | ||
504 | CRTC_STATUS_POS + CRTC5_REG_OF | ||
505 | }; | ||
506 | |||
507 | static u32 regs_crtc_vblank_start_end[CRTCS_N_MAX] __attribute__ ((unused)) = { | ||
508 | CRTC_VBLANK_START_END + CRTC0_REG_OF, | ||
509 | CRTC_VBLANK_START_END + CRTC1_REG_OF, | ||
510 | CRTC_VBLANK_START_END + CRTC2_REG_OF, | ||
511 | CRTC_VBLANK_START_END + CRTC3_REG_OF, | ||
512 | CRTC_VBLANK_START_END + CRTC4_REG_OF, | ||
513 | CRTC_VBLANK_START_END + CRTC5_REG_OF | ||
514 | }; | ||
515 | |||
487 | 516 | static u32 regs_lut_30_color[CRTCS_N_MAX] __attribute__ ((unused)) = { | static u32 regs_lut_30_color[CRTCS_N_MAX] __attribute__ ((unused)) = { |
488 | 517 | LUT_30_COLOR + CRTC0_REG_OF, | LUT_30_COLOR + CRTC0_REG_OF, |
489 | 518 | LUT_30_COLOR + CRTC1_REG_OF, | LUT_30_COLOR + CRTC1_REG_OF, |
File drivers/gpu/alga/amd/si/drv.c changed (mode: 100644) (index ff51883..ba36e3c) | |||
... | ... | u32 rr32(struct pci_dev *dev, u32 aligned_of) | |
71 | 71 | if (aligned_of <= (dd->regs_sz - sizeof(u32))) { | if (aligned_of <= (dd->regs_sz - sizeof(u32))) { |
72 | 72 | val = readl(dd->regs + aligned_of); | val = readl(dd->regs + aligned_of); |
73 | 73 | } else { | } else { |
74 | /* FIXME: should have a spinlock to make it atomic */ | ||
74 | 75 | writel((u32)(aligned_of >> 31), dd->regs + MM_IDX_HI); | writel((u32)(aligned_of >> 31), dd->regs + MM_IDX_HI); |
75 | 76 | writel(lower_32_bits(aligned_of) & ~MI_VRAM, dd->regs + MM_IDX); | writel(lower_32_bits(aligned_of) & ~MI_VRAM, dd->regs + MM_IDX); |
76 | 77 | val = readl(dd->regs + MM_DATA); | val = readl(dd->regs + MM_DATA); |
... | ... | void wr32(struct pci_dev *dev, u32 val, u32 aligned_of) | |
97 | 98 | if (aligned_of <= (dd->regs_sz - sizeof(u32))) { | if (aligned_of <= (dd->regs_sz - sizeof(u32))) { |
98 | 99 | writel(val, dd->regs + aligned_of); | writel(val, dd->regs + aligned_of); |
99 | 100 | } else { | } else { |
101 | /* FIXME: should have a spinlock to make it atomic */ | ||
100 | 102 | writel((u32)(aligned_of >> 31), dd->regs + MM_IDX_HI); | writel((u32)(aligned_of >> 31), dd->regs + MM_IDX_HI); |
101 | 103 | writel(lower_32_bits(aligned_of) & ~MI_VRAM, dd->regs + MM_IDX); | writel(lower_32_bits(aligned_of) & ~MI_VRAM, dd->regs + MM_IDX); |
102 | 104 | writel(val, dd->regs + MM_DATA); | writel(val, dd->regs + MM_DATA); |
File drivers/gpu/alga/amd/si/fops/dce.c changed (mode: 100644) (index fac2c59..2589fff) | |||
... | ... | long fops_dce_pf(struct pci_dev *dev, u8 __user *user_i, void *data) | |
125 | 125 | dd = pci_get_drvdata(dev); | dd = pci_get_drvdata(dev); |
126 | 126 | ||
127 | 127 | r = dce6_pf(dd->dce, i, pf_notify, data); | r = dce6_pf(dd->dce, i, pf_notify, data); |
128 | if (r != 0) | ||
129 | return -ENODEV; | ||
130 | return 0; | ||
128 | if (r == -DCE6_ERR) | ||
129 | r = -ENODEV; | ||
130 | return r; /* pass-thru for other return codes */ | ||
131 | 131 | } | } |
132 | 132 | ||
133 | 133 | #define EDID_SZ_MAX ((255 + 1) * 128) | #define EDID_SZ_MAX ((255 + 1) * 128) |
File drivers/gpu/alga/amd/si/fops/fops.c changed (mode: 100644) (index 6c93db8..2c680c7) | |||
... | ... | static int open(struct inode *i, struct file *f) | |
65 | 65 | struct file_private_data *data; | struct file_private_data *data; |
66 | 66 | struct dev_drv_data *dd; | struct dev_drv_data *dd; |
67 | 67 | ||
68 | /* FIXME: should close file options/flags possibities */ | ||
69 | |||
68 | 70 | dd = container_of(i->i_cdev, struct dev_drv_data, char_cdev); | dd = container_of(i->i_cdev, struct dev_drv_data, char_cdev); |
69 | 71 | ||
70 | 72 | data = kzalloc(sizeof(*data), GFP_KERNEL); | data = kzalloc(sizeof(*data), GFP_KERNEL); |
... | ... | static int release(struct inode *i, struct file *f) | |
340 | 342 | { | { |
341 | 343 | struct file_private_data *data; | struct file_private_data *data; |
342 | 344 | ||
343 | |||
344 | 345 | data = f->private_data; | data = f->private_data; |
345 | 346 | spin_lock(&files_private_data_lock); | spin_lock(&files_private_data_lock); |
346 | 347 | list_del(&data->n); | list_del(&data->n); |
... | ... | static ssize_t fops_read(struct file *f, char __user *buf, size_t buf_sz, | |
408 | 409 | ||
409 | 410 | data = f->private_data; | data = f->private_data; |
410 | 411 | ||
412 | if (*of != 0) | ||
413 | return -EINVAL; | ||
414 | |||
411 | 415 | spin_lock_irq(&data->evts_lock); | spin_lock_irq(&data->evts_lock); |
416 | |||
417 | if (f->f_flags & O_NONBLOCK) | ||
418 | if (list_empty(&data->evts)) { | ||
419 | spin_unlock_irq(&data->evts_lock); | ||
420 | return -EAGAIN; | ||
421 | } | ||
422 | |||
412 | 423 | r = wait_event_interruptible_lock_irq(data->evts_wq, | r = wait_event_interruptible_lock_irq(data->evts_wq, |
413 | 424 | !list_empty(&data->evts), data->evts_lock); | !list_empty(&data->evts), data->evts_lock); |
414 | 425 | if (r == -ERESTARTSYS) { | if (r == -ERESTARTSYS) { |
File drivers/gpu/alga/amd/si/ih.c changed (mode: 100644) (index 675f6e3..d4ebc53) | |||
... | ... | void ih_init(struct pci_dev *dev) | |
142 | 142 | * [127:80] - reserved | * [127:80] - reserved |
143 | 143 | */ | */ |
144 | 144 | static void vector(struct pci_dev *dev, u32 id, u32 data, u8 ring_id, | static void vector(struct pci_dev *dev, u32 id, u32 data, u8 ring_id, |
145 | u8 *irq_thd) | ||
145 | u8 *irq_thd, u8 *dce6_irqs_acked) | ||
146 | 146 | { | { |
147 | 147 | struct dev_drv_data *dd; | struct dev_drv_data *dd; |
148 | 148 | ||
... | ... | static void vector(struct pci_dev *dev, u32 id, u32 data, u8 ring_id, | |
150 | 150 | ||
151 | 151 | switch (id) { | switch (id) { |
152 | 152 | case VECTOR_ID_HPD: | case VECTOR_ID_HPD: |
153 | if (!*dce6_irqs_acked) { | ||
154 | dce6_irqs_ack(dd->dce); | ||
155 | *dce6_irqs_acked = 1; | ||
156 | } | ||
153 | 157 | dce6_hpd_irq(dd->dce, data); | dce6_hpd_irq(dd->dce, data); |
154 | 158 | *irq_thd = IRQ_THD_ENA; | *irq_thd = IRQ_THD_ENA; |
155 | 159 | break; | break; |
... | ... | static void vector(struct pci_dev *dev, u32 id, u32 data, u8 ring_id, | |
159 | 163 | case VECTOR_ID_D3: | case VECTOR_ID_D3: |
160 | 164 | case VECTOR_ID_D4: | case VECTOR_ID_D4: |
161 | 165 | case VECTOR_ID_D5: | case VECTOR_ID_D5: |
166 | if (!*dce6_irqs_acked) { | ||
167 | dce6_irqs_ack(dd->dce); | ||
168 | *dce6_irqs_acked = 1; | ||
169 | } | ||
162 | 170 | if (data == Dx_VBLANK) {/* only page flipping in vblank */ | if (data == Dx_VBLANK) {/* only page flipping in vblank */ |
163 | 171 | struct timespec tp; | struct timespec tp; |
164 | 172 | getrawmonotonic(&tp); | getrawmonotonic(&tp); |
165 | 173 | ||
166 | 174 | dce6_pf_irq(dd->dce, id - 1, tp); | dce6_pf_irq(dd->dce, id - 1, tp); |
167 | *irq_thd = IRQ_THD_DIS; /* useless to run the thread */ | ||
168 | 175 | } | } |
169 | 176 | break; | break; |
170 | 177 | case VECTOR_ID_EOP: | case VECTOR_ID_EOP: |
... | ... | u8 ih_parse(struct pci_dev *dev) | |
245 | 252 | ||
246 | 253 | spin_lock_irqsave(&dd->ih.lock, flgs); | spin_lock_irqsave(&dd->ih.lock, flgs); |
247 | 254 | while (1) { | while (1) { |
255 | u8 dce6_irqs_acked; | ||
256 | |||
248 | 257 | rmb(); | rmb(); |
249 | 258 | ||
250 | 259 | wp = le32_to_cpup(dd->ba.wb_map->cpu_addr + WB_IH_WPTR_OF); | wp = le32_to_cpup(dd->ba.wb_map->cpu_addr + WB_IH_WPTR_OF); |
... | ... | u8 ih_parse(struct pci_dev *dev) | |
254 | 263 | if (rp == wp) | if (rp == wp) |
255 | 264 | break; | break; |
256 | 265 | ||
257 | /* must ack dce irqs ourself HERE AND NOW! */ | ||
258 | dce6_irqs_ack(dd->dce); | ||
259 | |||
266 | ///* must ack dce irqs ourself HERE AND NOW! */ | ||
267 | //dce6_irqs_ack(dd->dce); | ||
268 | dce6_irqs_acked = 0; | ||
260 | 269 | do { | do { |
261 | 270 | u32 id; | u32 id; |
262 | 271 | u32 data; | u32 data; |
... | ... | u8 ih_parse(struct pci_dev *dev) | |
269 | 278 | ring_id = le32_to_cpup(dd->ba.ih_ring_map->cpu_addr + rp | ring_id = le32_to_cpup(dd->ba.ih_ring_map->cpu_addr + rp |
270 | 279 | + sizeof(id) + sizeof(data)) & 0xff; | + sizeof(id) + sizeof(data)) & 0xff; |
271 | 280 | ||
272 | vector(dev, id, data, ring_id, &irq_thd); | ||
281 | vector(dev, id, data, ring_id, &irq_thd, | ||
282 | &dce6_irqs_acked); | ||
273 | 283 | ||
274 | 284 | rp += VECTOR_SZ; | rp += VECTOR_SZ; |
275 | 285 | rp &= IH_RING_MASK; | rp &= IH_RING_MASK; |
File drivers/gpu/alga/amd/si/intr_irq.c changed (mode: 100644) (index 10ea10a..e0af0b6) | |||
... | ... | irqreturn_t irq(int irq, void *dev_id) | |
62 | 62 | else | else |
63 | 63 | return IRQ_NONE; | return IRQ_NONE; |
64 | 64 | } | } |
65 |
File include/uapi/alga/amd/si/ioctl.h changed (mode: 100644) (index c93b72b..347efb3) | |||
22 | 22 | #define SI_CONTEXT_LOST 1/* for instance, back from suspend */ | #define SI_CONTEXT_LOST 1/* for instance, back from suspend */ |
23 | 23 | #define SI_RING_TIMEOUT 2 | #define SI_RING_TIMEOUT 2 |
24 | 24 | #define SI_FENCE_TIMEOUT 3 | #define SI_FENCE_TIMEOUT 3 |
25 | #define SI_DCE_PF_PENDING 4 | ||
25 | 26 | ||
26 | 27 | struct si_timeout_info { | struct si_timeout_info { |
27 | 28 | uint32_t n_max; | uint32_t n_max; |