0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/via-core.h>
0012 #include <linux/via_i2c.h>
0013 #include <linux/via-gpio.h>
0014 #include "global.h"
0015
0016 #include <linux/module.h>
0017 #include <linux/interrupt.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/list.h>
0020 #include <linux/pm.h>
0021
0022
0023
0024
0025 static struct via_port_cfg adap_configs[] = {
0026 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
0027 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
0028 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
0029 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_I2C, VIASR, 0x2c },
0030 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
0031 { 0, 0, 0, 0 }
0032 };
0033
0034
0035
0036
0037
0038 static struct via_port_cfg olpc_adap_configs[] = {
0039 [VIA_PORT_26] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x26 },
0040 [VIA_PORT_31] = { VIA_PORT_I2C, VIA_MODE_I2C, VIASR, 0x31 },
0041 [VIA_PORT_25] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x25 },
0042 [VIA_PORT_2C] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x2c },
0043 [VIA_PORT_3D] = { VIA_PORT_GPIO, VIA_MODE_GPIO, VIASR, 0x3d },
0044 { 0, 0, 0, 0 }
0045 };
0046
0047
0048
0049
0050
0051 static struct viafb_dev global_dev;
0052
0053
0054
0055
0056
0057 static inline void viafb_mmio_write(int reg, u32 v)
0058 {
0059 iowrite32(v, global_dev.engine_mmio + reg);
0060 }
0061
0062 static inline int viafb_mmio_read(int reg)
0063 {
0064 return ioread32(global_dev.engine_mmio + reg);
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 static u32 viafb_enabled_ints;
0082
0083 static void viafb_int_init(void)
0084 {
0085 viafb_enabled_ints = 0;
0086
0087 viafb_mmio_write(VDE_INTERRUPT, 0);
0088 }
0089
0090
0091
0092
0093
0094 void viafb_irq_enable(u32 mask)
0095 {
0096 viafb_enabled_ints |= mask;
0097 viafb_mmio_write(VDE_INTERRUPT, viafb_enabled_ints | VDE_I_ENABLE);
0098 }
0099 EXPORT_SYMBOL_GPL(viafb_irq_enable);
0100
0101 void viafb_irq_disable(u32 mask)
0102 {
0103 viafb_enabled_ints &= ~mask;
0104 if (viafb_enabled_ints == 0)
0105 viafb_mmio_write(VDE_INTERRUPT, 0);
0106 else
0107 viafb_mmio_write(VDE_INTERRUPT,
0108 viafb_enabled_ints | VDE_I_ENABLE);
0109 }
0110 EXPORT_SYMBOL_GPL(viafb_irq_disable);
0111
0112
0113
0114
0115
0116
0117
0118
0119 #if IS_ENABLED(CONFIG_VIDEO_VIA_CAMERA)
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 static int viafb_dma_users;
0133 static DECLARE_COMPLETION(viafb_dma_completion);
0134
0135
0136
0137
0138
0139 static DEFINE_MUTEX(viafb_dma_lock);
0140
0141
0142
0143
0144
0145 struct viafb_vx855_dma_descr {
0146 u32 addr_low;
0147 u32 addr_high;
0148 u32 fb_offset;
0149 u32 seg_size;
0150 u32 tile_mode;
0151 u32 next_desc_low;
0152 u32 next_desc_high;
0153 u32 pad;
0154 };
0155
0156
0157
0158
0159 #define VIAFB_DMA_MAGIC 0x01
0160 #define VIAFB_DMA_FINAL_SEGMENT 0x02
0161
0162
0163
0164
0165 static irqreturn_t viafb_dma_irq(int irq, void *data)
0166 {
0167 int csr;
0168 irqreturn_t ret = IRQ_NONE;
0169
0170 spin_lock(&global_dev.reg_lock);
0171 csr = viafb_mmio_read(VDMA_CSR0);
0172 if (csr & VDMA_C_DONE) {
0173 viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
0174 complete(&viafb_dma_completion);
0175 ret = IRQ_HANDLED;
0176 }
0177 spin_unlock(&global_dev.reg_lock);
0178 return ret;
0179 }
0180
0181
0182
0183
0184 int viafb_request_dma(void)
0185 {
0186 int ret = 0;
0187
0188
0189
0190
0191 if (global_dev.chip_type != UNICHROME_VX855)
0192 return -ENODEV;
0193
0194
0195
0196
0197 mutex_lock(&viafb_dma_lock);
0198 viafb_dma_users++;
0199 if (viafb_dma_users == 1) {
0200 ret = request_irq(global_dev.pdev->irq, viafb_dma_irq,
0201 IRQF_SHARED, "via-dma", &viafb_dma_users);
0202 if (ret)
0203 viafb_dma_users--;
0204 else
0205 viafb_irq_enable(VDE_I_DMA0TDEN);
0206 }
0207 mutex_unlock(&viafb_dma_lock);
0208 return ret;
0209 }
0210 EXPORT_SYMBOL_GPL(viafb_request_dma);
0211
0212 void viafb_release_dma(void)
0213 {
0214 mutex_lock(&viafb_dma_lock);
0215 viafb_dma_users--;
0216 if (viafb_dma_users == 0) {
0217 viafb_irq_disable(VDE_I_DMA0TDEN);
0218 free_irq(global_dev.pdev->irq, &viafb_dma_users);
0219 }
0220 mutex_unlock(&viafb_dma_lock);
0221 }
0222 EXPORT_SYMBOL_GPL(viafb_release_dma);
0223
0224
0225
0226
0227
0228 int viafb_dma_copy_out_sg(unsigned int offset, struct scatterlist *sg, int nsg)
0229 {
0230 struct viafb_vx855_dma_descr *descr;
0231 void *descrpages;
0232 dma_addr_t descr_handle;
0233 unsigned long flags;
0234 int i;
0235 struct scatterlist *sgentry;
0236 dma_addr_t nextdesc;
0237
0238
0239
0240
0241 descrpages = dma_alloc_coherent(&global_dev.pdev->dev,
0242 nsg*sizeof(struct viafb_vx855_dma_descr),
0243 &descr_handle, GFP_KERNEL);
0244 if (descrpages == NULL) {
0245 dev_err(&global_dev.pdev->dev, "Unable to get descr page.\n");
0246 return -ENOMEM;
0247 }
0248 mutex_lock(&viafb_dma_lock);
0249
0250
0251
0252 descr = descrpages;
0253 nextdesc = descr_handle + sizeof(struct viafb_vx855_dma_descr);
0254 for_each_sg(sg, sgentry, nsg, i) {
0255 dma_addr_t paddr = sg_dma_address(sgentry);
0256 descr->addr_low = paddr & 0xfffffff0;
0257 descr->addr_high = ((u64) paddr >> 32) & 0x0fff;
0258 descr->fb_offset = offset;
0259 descr->seg_size = sg_dma_len(sgentry) >> 4;
0260 descr->tile_mode = 0;
0261 descr->next_desc_low = (nextdesc&0xfffffff0) | VIAFB_DMA_MAGIC;
0262 descr->next_desc_high = ((u64) nextdesc >> 32) & 0x0fff;
0263 descr->pad = 0xffffffff;
0264 offset += sg_dma_len(sgentry);
0265 nextdesc += sizeof(struct viafb_vx855_dma_descr);
0266 descr++;
0267 }
0268 descr[-1].next_desc_low = VIAFB_DMA_FINAL_SEGMENT|VIAFB_DMA_MAGIC;
0269
0270
0271
0272 spin_lock_irqsave(&global_dev.reg_lock, flags);
0273 init_completion(&viafb_dma_completion);
0274 viafb_mmio_write(VDMA_DQWCR0, 0);
0275 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_DONE);
0276 viafb_mmio_write(VDMA_MR0, VDMA_MR_TDIE | VDMA_MR_CHAIN);
0277 viafb_mmio_write(VDMA_DPRL0, descr_handle | VIAFB_DMA_MAGIC);
0278 viafb_mmio_write(VDMA_DPRH0,
0279 (((u64)descr_handle >> 32) & 0x0fff) | 0xf0000);
0280 (void) viafb_mmio_read(VDMA_CSR0);
0281 viafb_mmio_write(VDMA_CSR0, VDMA_C_ENABLE|VDMA_C_START);
0282 spin_unlock_irqrestore(&global_dev.reg_lock, flags);
0283
0284
0285
0286
0287
0288
0289 wait_for_completion_timeout(&viafb_dma_completion, 1);
0290 msleep(1);
0291 if ((viafb_mmio_read(VDMA_CSR0)&VDMA_C_DONE) == 0)
0292 printk(KERN_ERR "VIA DMA timeout!\n");
0293
0294
0295
0296 viafb_mmio_write(VDMA_CSR0, VDMA_C_DONE);
0297 viafb_mmio_write(VDMA_MR0, 0);
0298 mutex_unlock(&viafb_dma_lock);
0299 dma_free_coherent(&global_dev.pdev->dev,
0300 nsg*sizeof(struct viafb_vx855_dma_descr), descrpages,
0301 descr_handle);
0302 return 0;
0303 }
0304 EXPORT_SYMBOL_GPL(viafb_dma_copy_out_sg);
0305 #endif
0306
0307
0308
0309
0310
0311
0312
0313 static u16 via_function3[] = {
0314 CLE266_FUNCTION3, KM400_FUNCTION3, CN400_FUNCTION3, CN700_FUNCTION3,
0315 CX700_FUNCTION3, KM800_FUNCTION3, KM890_FUNCTION3, P4M890_FUNCTION3,
0316 P4M900_FUNCTION3, VX800_FUNCTION3, VX855_FUNCTION3, VX900_FUNCTION3,
0317 };
0318
0319
0320
0321 static int viafb_get_fb_size_from_pci(int chip_type)
0322 {
0323 int i;
0324 u8 offset = 0;
0325 u32 FBSize;
0326 u32 VideoMemSize;
0327
0328
0329 for (i = 0; i < ARRAY_SIZE(via_function3); i++) {
0330 struct pci_dev *pdev;
0331
0332 pdev = pci_get_device(PCI_VENDOR_ID_VIA, via_function3[i],
0333 NULL);
0334 if (!pdev)
0335 continue;
0336
0337 DEBUG_MSG(KERN_INFO "Device ID = %x\n", pdev->device);
0338
0339 switch (pdev->device) {
0340 case CLE266_FUNCTION3:
0341 case KM400_FUNCTION3:
0342 offset = 0xE0;
0343 break;
0344 case CN400_FUNCTION3:
0345 case CN700_FUNCTION3:
0346 case CX700_FUNCTION3:
0347 case KM800_FUNCTION3:
0348 case KM890_FUNCTION3:
0349 case P4M890_FUNCTION3:
0350 case P4M900_FUNCTION3:
0351 case VX800_FUNCTION3:
0352 case VX855_FUNCTION3:
0353 case VX900_FUNCTION3:
0354
0355 offset = 0xA0;
0356 break;
0357 }
0358
0359 if (!offset)
0360 break;
0361
0362 pci_read_config_dword(pdev, offset, &FBSize);
0363 pci_dev_put(pdev);
0364 }
0365
0366 if (!offset) {
0367 printk(KERN_ERR "cannot determine framebuffer size\n");
0368 return -EIO;
0369 }
0370
0371 FBSize = FBSize & 0x00007000;
0372 DEBUG_MSG(KERN_INFO "FB Size = %x\n", FBSize);
0373
0374 if (chip_type < UNICHROME_CX700) {
0375 switch (FBSize) {
0376 case 0x00004000:
0377 VideoMemSize = (16 << 20);
0378 break;
0379
0380 case 0x00005000:
0381 VideoMemSize = (32 << 20);
0382 break;
0383
0384 case 0x00006000:
0385 VideoMemSize = (64 << 20);
0386 break;
0387
0388 default:
0389 VideoMemSize = (32 << 20);
0390 break;
0391 }
0392 } else {
0393 switch (FBSize) {
0394 case 0x00001000:
0395 VideoMemSize = (8 << 20);
0396 break;
0397
0398 case 0x00002000:
0399 VideoMemSize = (16 << 20);
0400 break;
0401
0402 case 0x00003000:
0403 VideoMemSize = (32 << 20);
0404 break;
0405
0406 case 0x00004000:
0407 VideoMemSize = (64 << 20);
0408 break;
0409
0410 case 0x00005000:
0411 VideoMemSize = (128 << 20);
0412 break;
0413
0414 case 0x00006000:
0415 VideoMemSize = (256 << 20);
0416 break;
0417
0418 case 0x00007000:
0419 VideoMemSize = (512 << 20);
0420 break;
0421
0422 default:
0423 VideoMemSize = (32 << 20);
0424 break;
0425 }
0426 }
0427
0428 return VideoMemSize;
0429 }
0430
0431
0432
0433
0434
0435 static int via_pci_setup_mmio(struct viafb_dev *vdev)
0436 {
0437 int ret;
0438
0439
0440
0441
0442
0443 vdev->engine_start = pci_resource_start(vdev->pdev, 1);
0444 vdev->engine_len = pci_resource_len(vdev->pdev, 1);
0445 vdev->engine_mmio = ioremap(vdev->engine_start,
0446 vdev->engine_len);
0447 if (vdev->engine_mmio == NULL)
0448 dev_err(&vdev->pdev->dev,
0449 "Unable to map engine MMIO; operation will be "
0450 "slow and crippled.\n");
0451
0452
0453
0454
0455
0456
0457
0458 if (vdev->chip_type == UNICHROME_VX900)
0459 vdev->fbmem_start = pci_resource_start(vdev->pdev, 2);
0460 else
0461 vdev->fbmem_start = pci_resource_start(vdev->pdev, 0);
0462 ret = vdev->fbmem_len = viafb_get_fb_size_from_pci(vdev->chip_type);
0463 if (ret < 0)
0464 goto out_unmap;
0465
0466
0467 for (; vdev->fbmem_len >= 8 << 20; vdev->fbmem_len /= 2) {
0468 vdev->fbmem = ioremap_wc(vdev->fbmem_start, vdev->fbmem_len);
0469 if (vdev->fbmem)
0470 break;
0471 }
0472
0473 if (vdev->fbmem == NULL) {
0474 ret = -ENOMEM;
0475 goto out_unmap;
0476 }
0477 return 0;
0478 out_unmap:
0479 iounmap(vdev->engine_mmio);
0480 return ret;
0481 }
0482
0483 static void via_pci_teardown_mmio(struct viafb_dev *vdev)
0484 {
0485 iounmap(vdev->fbmem);
0486 iounmap(vdev->engine_mmio);
0487 }
0488
0489
0490
0491
0492 static struct viafb_subdev_info {
0493 char *name;
0494 struct platform_device *platdev;
0495 } viafb_subdevs[] = {
0496 {
0497 .name = "viafb-gpio",
0498 },
0499 {
0500 .name = "viafb-i2c",
0501 },
0502 #if IS_ENABLED(CONFIG_VIDEO_VIA_CAMERA)
0503 {
0504 .name = "viafb-camera",
0505 },
0506 #endif
0507 };
0508 #define N_SUBDEVS ARRAY_SIZE(viafb_subdevs)
0509
0510 static int via_create_subdev(struct viafb_dev *vdev,
0511 struct viafb_subdev_info *info)
0512 {
0513 int ret;
0514
0515 info->platdev = platform_device_alloc(info->name, -1);
0516 if (!info->platdev) {
0517 dev_err(&vdev->pdev->dev, "Unable to allocate pdev %s\n",
0518 info->name);
0519 return -ENOMEM;
0520 }
0521 info->platdev->dev.parent = &vdev->pdev->dev;
0522 info->platdev->dev.platform_data = vdev;
0523 ret = platform_device_add(info->platdev);
0524 if (ret) {
0525 dev_err(&vdev->pdev->dev, "Unable to add pdev %s\n",
0526 info->name);
0527 platform_device_put(info->platdev);
0528 info->platdev = NULL;
0529 }
0530 return ret;
0531 }
0532
0533 static int via_setup_subdevs(struct viafb_dev *vdev)
0534 {
0535 int i;
0536
0537
0538
0539
0540
0541
0542 for (i = 0; i < N_SUBDEVS; i++)
0543 via_create_subdev(vdev, viafb_subdevs + i);
0544 return 0;
0545 }
0546
0547 static void via_teardown_subdevs(void)
0548 {
0549 int i;
0550
0551 for (i = 0; i < N_SUBDEVS; i++)
0552 if (viafb_subdevs[i].platdev) {
0553 viafb_subdevs[i].platdev->dev.platform_data = NULL;
0554 platform_device_unregister(viafb_subdevs[i].platdev);
0555 }
0556 }
0557
0558
0559
0560
0561 static __maybe_unused LIST_HEAD(viafb_pm_hooks);
0562 static __maybe_unused DEFINE_MUTEX(viafb_pm_hooks_lock);
0563
0564 void viafb_pm_register(struct viafb_pm_hooks *hooks)
0565 {
0566 INIT_LIST_HEAD(&hooks->list);
0567
0568 mutex_lock(&viafb_pm_hooks_lock);
0569 list_add_tail(&hooks->list, &viafb_pm_hooks);
0570 mutex_unlock(&viafb_pm_hooks_lock);
0571 }
0572 EXPORT_SYMBOL_GPL(viafb_pm_register);
0573
0574 void viafb_pm_unregister(struct viafb_pm_hooks *hooks)
0575 {
0576 mutex_lock(&viafb_pm_hooks_lock);
0577 list_del(&hooks->list);
0578 mutex_unlock(&viafb_pm_hooks_lock);
0579 }
0580 EXPORT_SYMBOL_GPL(viafb_pm_unregister);
0581
0582 static int __maybe_unused via_suspend(struct device *dev)
0583 {
0584 struct viafb_pm_hooks *hooks;
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595 mutex_lock(&viafb_pm_hooks_lock);
0596 list_for_each_entry_reverse(hooks, &viafb_pm_hooks, list)
0597 hooks->suspend(hooks->private);
0598 mutex_unlock(&viafb_pm_hooks_lock);
0599
0600 return 0;
0601 }
0602
0603 static int __maybe_unused via_resume(struct device *dev)
0604 {
0605 struct viafb_pm_hooks *hooks;
0606
0607
0608 mutex_lock(&viafb_pm_hooks_lock);
0609 list_for_each_entry(hooks, &viafb_pm_hooks, list)
0610 hooks->resume(hooks->private);
0611 mutex_unlock(&viafb_pm_hooks_lock);
0612
0613 return 0;
0614 }
0615
0616 static int via_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
0617 {
0618 int ret;
0619
0620 ret = pci_enable_device(pdev);
0621 if (ret)
0622 return ret;
0623
0624
0625
0626
0627 memset(&global_dev, 0, sizeof(global_dev));
0628 global_dev.pdev = pdev;
0629 global_dev.chip_type = ent->driver_data;
0630 global_dev.port_cfg = adap_configs;
0631 if (machine_is_olpc())
0632 global_dev.port_cfg = olpc_adap_configs;
0633
0634 spin_lock_init(&global_dev.reg_lock);
0635 ret = via_pci_setup_mmio(&global_dev);
0636 if (ret)
0637 goto out_disable;
0638
0639
0640
0641
0642 viafb_int_init();
0643 via_setup_subdevs(&global_dev);
0644
0645
0646
0647 ret = via_fb_pci_probe(&global_dev);
0648 if (ret)
0649 goto out_subdevs;
0650 return 0;
0651
0652 out_subdevs:
0653 via_teardown_subdevs();
0654 via_pci_teardown_mmio(&global_dev);
0655 out_disable:
0656 pci_disable_device(pdev);
0657 return ret;
0658 }
0659
0660 static void via_pci_remove(struct pci_dev *pdev)
0661 {
0662 via_teardown_subdevs();
0663 via_fb_pci_remove(pdev);
0664 via_pci_teardown_mmio(&global_dev);
0665 pci_disable_device(pdev);
0666 }
0667
0668
0669 static const struct pci_device_id via_pci_table[] = {
0670 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CLE266_DID),
0671 .driver_data = UNICHROME_CLE266 },
0672 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K400_DID),
0673 .driver_data = UNICHROME_K400 },
0674 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K800_DID),
0675 .driver_data = UNICHROME_K800 },
0676 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_PM800_DID),
0677 .driver_data = UNICHROME_PM800 },
0678 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN700_DID),
0679 .driver_data = UNICHROME_CN700 },
0680 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CX700_DID),
0681 .driver_data = UNICHROME_CX700 },
0682 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_CN750_DID),
0683 .driver_data = UNICHROME_CN750 },
0684 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_K8M890_DID),
0685 .driver_data = UNICHROME_K8M890 },
0686 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M890_DID),
0687 .driver_data = UNICHROME_P4M890 },
0688 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_P4M900_DID),
0689 .driver_data = UNICHROME_P4M900 },
0690 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX800_DID),
0691 .driver_data = UNICHROME_VX800 },
0692 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX855_DID),
0693 .driver_data = UNICHROME_VX855 },
0694 { PCI_DEVICE(PCI_VENDOR_ID_VIA, UNICHROME_VX900_DID),
0695 .driver_data = UNICHROME_VX900 },
0696 { }
0697 };
0698 MODULE_DEVICE_TABLE(pci, via_pci_table);
0699
0700 static const struct dev_pm_ops via_pm_ops = {
0701 #ifdef CONFIG_PM_SLEEP
0702 .suspend = via_suspend,
0703 .resume = via_resume,
0704 .freeze = NULL,
0705 .thaw = via_resume,
0706 .poweroff = NULL,
0707 .restore = via_resume,
0708 #endif
0709 };
0710
0711 static struct pci_driver via_driver = {
0712 .name = "viafb",
0713 .id_table = via_pci_table,
0714 .probe = via_pci_probe,
0715 .remove = via_pci_remove,
0716 .driver.pm = &via_pm_ops,
0717 };
0718
0719 static int __init via_core_init(void)
0720 {
0721 int ret;
0722
0723 ret = viafb_init();
0724 if (ret)
0725 return ret;
0726 viafb_i2c_init();
0727 viafb_gpio_init();
0728 return pci_register_driver(&via_driver);
0729 }
0730
0731 static void __exit via_core_exit(void)
0732 {
0733 pci_unregister_driver(&via_driver);
0734 viafb_gpio_exit();
0735 viafb_i2c_exit();
0736 viafb_exit();
0737 }
0738
0739 module_init(via_core_init);
0740 module_exit(via_core_exit);