0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #include <drm/drm_device.h>
0039 #include <drm/drm_vblank.h>
0040 #include <drm/via_drm.h>
0041
0042 #include "via_drv.h"
0043
0044 #define VIA_REG_INTERRUPT 0x200
0045
0046
0047 #define VIA_IRQ_GLOBAL (1 << 31)
0048 #define VIA_IRQ_VBLANK_ENABLE (1 << 19)
0049 #define VIA_IRQ_VBLANK_PENDING (1 << 3)
0050 #define VIA_IRQ_HQV0_ENABLE (1 << 11)
0051 #define VIA_IRQ_HQV1_ENABLE (1 << 25)
0052 #define VIA_IRQ_HQV0_PENDING (1 << 9)
0053 #define VIA_IRQ_HQV1_PENDING (1 << 10)
0054 #define VIA_IRQ_DMA0_DD_ENABLE (1 << 20)
0055 #define VIA_IRQ_DMA0_TD_ENABLE (1 << 21)
0056 #define VIA_IRQ_DMA1_DD_ENABLE (1 << 22)
0057 #define VIA_IRQ_DMA1_TD_ENABLE (1 << 23)
0058 #define VIA_IRQ_DMA0_DD_PENDING (1 << 4)
0059 #define VIA_IRQ_DMA0_TD_PENDING (1 << 5)
0060 #define VIA_IRQ_DMA1_DD_PENDING (1 << 6)
0061 #define VIA_IRQ_DMA1_TD_PENDING (1 << 7)
0062
0063
0064
0065
0066
0067
0068
0069
0070 static maskarray_t via_pro_group_a_irqs[] = {
0071 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010,
0072 0x00000000 },
0073 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010,
0074 0x00000000 },
0075 {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
0076 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
0077 {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
0078 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
0079 };
0080 static int via_num_pro_group_a = ARRAY_SIZE(via_pro_group_a_irqs);
0081 static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3};
0082
0083 static maskarray_t via_unichrome_irqs[] = {
0084 {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0,
0085 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008},
0086 {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1,
0087 VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}
0088 };
0089 static int via_num_unichrome = ARRAY_SIZE(via_unichrome_irqs);
0090 static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
0091
0092
0093 u32 via_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
0094 {
0095 drm_via_private_t *dev_priv = dev->dev_private;
0096
0097 if (pipe != 0)
0098 return 0;
0099
0100 return atomic_read(&dev_priv->vbl_received);
0101 }
0102
0103 irqreturn_t via_driver_irq_handler(int irq, void *arg)
0104 {
0105 struct drm_device *dev = (struct drm_device *) arg;
0106 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0107 u32 status;
0108 int handled = 0;
0109 ktime_t cur_vblank;
0110 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
0111 int i;
0112
0113 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0114 if (status & VIA_IRQ_VBLANK_PENDING) {
0115 atomic_inc(&dev_priv->vbl_received);
0116 if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
0117 cur_vblank = ktime_get();
0118 if (dev_priv->last_vblank_valid) {
0119 dev_priv->nsec_per_vblank =
0120 ktime_sub(cur_vblank,
0121 dev_priv->last_vblank) >> 4;
0122 }
0123 dev_priv->last_vblank = cur_vblank;
0124 dev_priv->last_vblank_valid = 1;
0125 }
0126 if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
0127 DRM_DEBUG("nsec per vblank is: %llu\n",
0128 ktime_to_ns(dev_priv->nsec_per_vblank));
0129 }
0130 drm_handle_vblank(dev, 0);
0131 handled = 1;
0132 }
0133
0134 for (i = 0; i < dev_priv->num_irqs; ++i) {
0135 if (status & cur_irq->pending_mask) {
0136 atomic_inc(&cur_irq->irq_received);
0137 wake_up(&cur_irq->irq_queue);
0138 handled = 1;
0139 if (dev_priv->irq_map[drm_via_irq_dma0_td] == i)
0140 via_dmablit_handler(dev, 0, 1);
0141 else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i)
0142 via_dmablit_handler(dev, 1, 1);
0143 }
0144 cur_irq++;
0145 }
0146
0147
0148 via_write(dev_priv, VIA_REG_INTERRUPT, status);
0149
0150
0151 if (handled)
0152 return IRQ_HANDLED;
0153 else
0154 return IRQ_NONE;
0155 }
0156
0157 static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv)
0158 {
0159 u32 status;
0160
0161 if (dev_priv) {
0162
0163 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0164 via_write(dev_priv, VIA_REG_INTERRUPT, status |
0165 dev_priv->irq_pending_mask);
0166 }
0167 }
0168
0169 int via_enable_vblank(struct drm_device *dev, unsigned int pipe)
0170 {
0171 drm_via_private_t *dev_priv = dev->dev_private;
0172 u32 status;
0173
0174 if (pipe != 0) {
0175 DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
0176 return -EINVAL;
0177 }
0178
0179 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0180 via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE);
0181
0182 via_write8(dev_priv, 0x83d4, 0x11);
0183 via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
0184
0185 return 0;
0186 }
0187
0188 void via_disable_vblank(struct drm_device *dev, unsigned int pipe)
0189 {
0190 drm_via_private_t *dev_priv = dev->dev_private;
0191 u32 status;
0192
0193 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0194 via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE);
0195
0196 via_write8(dev_priv, 0x83d4, 0x11);
0197 via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
0198
0199 if (pipe != 0)
0200 DRM_ERROR("%s: bad crtc %u\n", __func__, pipe);
0201 }
0202
0203 static int
0204 via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence,
0205 unsigned int *sequence)
0206 {
0207 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0208 unsigned int cur_irq_sequence;
0209 drm_via_irq_t *cur_irq;
0210 int ret = 0;
0211 maskarray_t *masks;
0212 int real_irq;
0213
0214 DRM_DEBUG("\n");
0215
0216 if (!dev_priv) {
0217 DRM_ERROR("called with no initialization\n");
0218 return -EINVAL;
0219 }
0220
0221 if (irq >= drm_via_irq_num) {
0222 DRM_ERROR("Trying to wait on unknown irq %d\n", irq);
0223 return -EINVAL;
0224 }
0225
0226 real_irq = dev_priv->irq_map[irq];
0227
0228 if (real_irq < 0) {
0229 DRM_ERROR("Video IRQ %d not available on this hardware.\n",
0230 irq);
0231 return -EINVAL;
0232 }
0233
0234 masks = dev_priv->irq_masks;
0235 cur_irq = dev_priv->via_irqs + real_irq;
0236
0237 if (masks[real_irq][2] && !force_sequence) {
0238 VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
0239 ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) ==
0240 masks[irq][4]));
0241 cur_irq_sequence = atomic_read(&cur_irq->irq_received);
0242 } else {
0243 VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ,
0244 (((cur_irq_sequence =
0245 atomic_read(&cur_irq->irq_received)) -
0246 *sequence) <= (1 << 23)));
0247 }
0248 *sequence = cur_irq_sequence;
0249 return ret;
0250 }
0251
0252
0253
0254
0255
0256
0257 void via_driver_irq_preinstall(struct drm_device *dev)
0258 {
0259 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0260 u32 status;
0261 drm_via_irq_t *cur_irq;
0262 int i;
0263
0264 DRM_DEBUG("dev_priv: %p\n", dev_priv);
0265 if (dev_priv) {
0266 cur_irq = dev_priv->via_irqs;
0267
0268 dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
0269 dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
0270
0271 if (dev_priv->chipset == VIA_PRO_GROUP_A ||
0272 dev_priv->chipset == VIA_DX9_0) {
0273 dev_priv->irq_masks = via_pro_group_a_irqs;
0274 dev_priv->num_irqs = via_num_pro_group_a;
0275 dev_priv->irq_map = via_irqmap_pro_group_a;
0276 } else {
0277 dev_priv->irq_masks = via_unichrome_irqs;
0278 dev_priv->num_irqs = via_num_unichrome;
0279 dev_priv->irq_map = via_irqmap_unichrome;
0280 }
0281
0282 for (i = 0; i < dev_priv->num_irqs; ++i) {
0283 atomic_set(&cur_irq->irq_received, 0);
0284 cur_irq->enable_mask = dev_priv->irq_masks[i][0];
0285 cur_irq->pending_mask = dev_priv->irq_masks[i][1];
0286 init_waitqueue_head(&cur_irq->irq_queue);
0287 dev_priv->irq_enable_mask |= cur_irq->enable_mask;
0288 dev_priv->irq_pending_mask |= cur_irq->pending_mask;
0289 cur_irq++;
0290
0291 DRM_DEBUG("Initializing IRQ %d\n", i);
0292 }
0293
0294 dev_priv->last_vblank_valid = 0;
0295
0296
0297 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0298 via_write(dev_priv, VIA_REG_INTERRUPT, status &
0299 ~(dev_priv->irq_enable_mask));
0300
0301
0302 viadrv_acknowledge_irqs(dev_priv);
0303 }
0304 }
0305
0306 int via_driver_irq_postinstall(struct drm_device *dev)
0307 {
0308 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0309 u32 status;
0310
0311 DRM_DEBUG("fun: %s\n", __func__);
0312 if (!dev_priv)
0313 return -EINVAL;
0314
0315 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0316 via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
0317 | dev_priv->irq_enable_mask);
0318
0319
0320 via_write8(dev_priv, 0x83d4, 0x11);
0321 via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30);
0322
0323 return 0;
0324 }
0325
0326 void via_driver_irq_uninstall(struct drm_device *dev)
0327 {
0328 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0329 u32 status;
0330
0331 DRM_DEBUG("\n");
0332 if (dev_priv) {
0333
0334
0335
0336 via_write8(dev_priv, 0x83d4, 0x11);
0337 via_write8_mask(dev_priv, 0x83d5, 0x30, 0);
0338
0339 status = via_read(dev_priv, VIA_REG_INTERRUPT);
0340 via_write(dev_priv, VIA_REG_INTERRUPT, status &
0341 ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
0342 }
0343 }
0344
0345 int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv)
0346 {
0347 drm_via_irqwait_t *irqwait = data;
0348 struct timespec64 now;
0349 int ret = 0;
0350 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
0351 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
0352 int force_sequence;
0353
0354 if (irqwait->request.irq >= dev_priv->num_irqs) {
0355 DRM_ERROR("Trying to wait on unknown irq %d\n",
0356 irqwait->request.irq);
0357 return -EINVAL;
0358 }
0359
0360 cur_irq += irqwait->request.irq;
0361
0362 switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) {
0363 case VIA_IRQ_RELATIVE:
0364 irqwait->request.sequence +=
0365 atomic_read(&cur_irq->irq_received);
0366 irqwait->request.type &= ~_DRM_VBLANK_RELATIVE;
0367 break;
0368 case VIA_IRQ_ABSOLUTE:
0369 break;
0370 default:
0371 return -EINVAL;
0372 }
0373
0374 if (irqwait->request.type & VIA_IRQ_SIGNAL) {
0375 DRM_ERROR("Signals on Via IRQs not implemented yet.\n");
0376 return -EINVAL;
0377 }
0378
0379 force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE);
0380
0381 ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence,
0382 &irqwait->request.sequence);
0383 ktime_get_ts64(&now);
0384 irqwait->reply.tval_sec = now.tv_sec;
0385 irqwait->reply.tval_usec = now.tv_nsec / NSEC_PER_USEC;
0386
0387 return ret;
0388 }