1/* 2 * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com 3 * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 */ 19 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/pci.h> 23#include <linux/interrupt.h> 24#include <linux/slab.h> 25#include <linux/videodev2.h> 26#include "solo6x10.h" 27#include "tw28.h" 28 29MODULE_DESCRIPTION("Softlogic 6x10 MP4/H.264 Encoder/Decoder V4L2/ALSA Driver"); 30MODULE_AUTHOR("Ben Collins <bcollins@bluecherry.net>"); 31MODULE_VERSION(SOLO6X10_VERSION); 32MODULE_LICENSE("GPL"); 33 34void solo_irq_on(struct solo_dev *solo_dev, u32 mask) 35{ 36 solo_dev->irq_mask |= mask; 37 solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask); 38} 39 40void solo_irq_off(struct solo_dev *solo_dev, u32 mask) 41{ 42 solo_dev->irq_mask &= ~mask; 43 solo_reg_write(solo_dev, SOLO_IRQ_ENABLE, solo_dev->irq_mask); 44} 45 46/* XXX We should check the return value of the sub-device ISR's */ 47static irqreturn_t solo_isr(int irq, void *data) 48{ 49 struct solo_dev *solo_dev = data; 50 u32 status; 51 int i; 52 53 status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); 54 if (!status) 55 return IRQ_NONE; 56 57 if (status & ~solo_dev->irq_mask) { 58 solo_reg_write(solo_dev, SOLO_IRQ_STAT, 59 status & ~solo_dev->irq_mask); 60 status &= solo_dev->irq_mask; 61 } 62 63 if (status & SOLO_IRQ_PCI_ERR) { 64 u32 err = solo_reg_read(solo_dev, SOLO_PCI_ERR); 65 solo_p2m_error_isr(solo_dev, err); 66 solo_reg_write(solo_dev, SOLO_IRQ_STAT, SOLO_IRQ_PCI_ERR); 67 } 68 69 for (i = 0; i < SOLO_NR_P2M; i++) 70 if (status & SOLO_IRQ_P2M(i)) 71 solo_p2m_isr(solo_dev, i); 72 73 if (status & SOLO_IRQ_IIC) 74 solo_i2c_isr(solo_dev); 75 76 if (status & SOLO_IRQ_VIDEO_IN) 77 solo_video_in_isr(solo_dev); 78 79 /* Call this first so enc gets detected flag set */ 80 if (status & SOLO_IRQ_MOTION) 81 solo_motion_isr(solo_dev); 82 83 if (status & SOLO_IRQ_ENCODER) 84 solo_enc_v4l2_isr(solo_dev); 85 86 if (status & SOLO_IRQ_G723) 87 solo_g723_isr(solo_dev); 88 89 return IRQ_HANDLED; 90} 91 92static void free_solo_dev(struct solo_dev *solo_dev) 93{ 94 struct pci_dev *pdev; 95 96 if (!solo_dev) 97 return; 98 99 pdev = solo_dev->pdev; 100 101 /* If we never initialized the PCI device, then nothing else 102 * below here needs cleanup */ 103 if (!pdev) { 104 kfree(solo_dev); 105 return; 106 } 107 108 /* Bring down the sub-devices first */ 109 solo_g723_exit(solo_dev); 110 solo_enc_v4l2_exit(solo_dev); 111 solo_enc_exit(solo_dev); 112 solo_v4l2_exit(solo_dev); 113 solo_disp_exit(solo_dev); 114 solo_gpio_exit(solo_dev); 115 solo_p2m_exit(solo_dev); 116 solo_i2c_exit(solo_dev); 117 118 /* Now cleanup the PCI device */ 119 if (solo_dev->reg_base) { 120 solo_irq_off(solo_dev, ~0); 121 pci_iounmap(pdev, solo_dev->reg_base); 122 free_irq(pdev->irq, solo_dev); 123 } 124 125 pci_release_regions(pdev); 126 pci_disable_device(pdev); 127 pci_set_drvdata(pdev, NULL); 128 129 kfree(solo_dev); 130} 131 132static int __devinit solo_pci_probe(struct pci_dev *pdev, 133 const struct pci_device_id *id) 134{ 135 struct solo_dev *solo_dev; 136 int ret; 137 int sdram; 138 u8 chip_id; 139 u32 reg; 140 141 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); 142 if (solo_dev == NULL) 143 return -ENOMEM; 144 145 solo_dev->pdev = pdev; 146 spin_lock_init(&solo_dev->reg_io_lock); 147 pci_set_drvdata(pdev, solo_dev); 148 149 ret = pci_enable_device(pdev); 150 if (ret) 151 goto fail_probe; 152 153 pci_set_master(pdev); 154 155 ret = pci_request_regions(pdev, SOLO6X10_NAME); 156 if (ret) 157 goto fail_probe; 158 159 solo_dev->reg_base = pci_ioremap_bar(pdev, 0); 160 if (solo_dev->reg_base == NULL) { 161 ret = -ENOMEM; 162 goto fail_probe; 163 } 164 165 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & 166 SOLO_CHIP_ID_MASK; 167 switch (chip_id) { 168 case 7: 169 solo_dev->nr_chans = 16; 170 solo_dev->nr_ext = 5; 171 break; 172 case 6: 173 solo_dev->nr_chans = 8; 174 solo_dev->nr_ext = 2; 175 break; 176 default: 177 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, " 178 "defaulting to 4 channels\n", 179 chip_id); 180 case 5: 181 solo_dev->nr_chans = 4; 182 solo_dev->nr_ext = 1; 183 } 184 185 solo_dev->flags = id->driver_data; 186 187 /* Disable all interrupts to start */ 188 solo_irq_off(solo_dev, ~0); 189 190 reg = SOLO_SYS_CFG_SDRAM64BIT; 191 /* Initial global settings */ 192 if (!(solo_dev->flags & FLAGS_6110)) 193 reg |= SOLO6010_SYS_CFG_INPUTDIV(25) | 194 SOLO6010_SYS_CFG_FEEDBACKDIV((SOLO_CLOCK_MHZ * 2) - 2) | 195 SOLO6010_SYS_CFG_OUTDIV(3); 196 solo_reg_write(solo_dev, SOLO_SYS_CFG, reg); 197 198 if (solo_dev->flags & FLAGS_6110) { 199 u32 sys_clock_MHz = SOLO_CLOCK_MHZ; 200 u32 pll_DIVQ; 201 u32 pll_DIVF; 202 203 if (sys_clock_MHz < 125) { 204 pll_DIVQ = 3; 205 pll_DIVF = (sys_clock_MHz * 4) / 3; 206 } else { 207 pll_DIVQ = 2; 208 pll_DIVF = (sys_clock_MHz * 2) / 3; 209 } 210 211 solo_reg_write(solo_dev, SOLO6110_PLL_CONFIG, 212 SOLO6110_PLL_RANGE_5_10MHZ | 213 SOLO6110_PLL_DIVR(9) | 214 SOLO6110_PLL_DIVQ_EXP(pll_DIVQ) | 215 SOLO6110_PLL_DIVF(pll_DIVF) | SOLO6110_PLL_FSEN); 216 mdelay(1); /* PLL Locking time (1ms) */ 217 218 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 3 << 8); /* ? */ 219 } else 220 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 1 << 8); /* ? */ 221 222 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, SOLO_CLOCK_MHZ - 1); 223 224 /* PLL locking time of 1ms */ 225 mdelay(1); 226 227 ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME, 228 solo_dev); 229 if (ret) 230 goto fail_probe; 231 232 /* Handle this from the start */ 233 solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); 234 235 ret = solo_i2c_init(solo_dev); 236 if (ret) 237 goto fail_probe; 238 239 /* Setup the DMA engine */ 240 sdram = (solo_dev->nr_chans >= 8) ? 2 : 1; 241 solo_reg_write(solo_dev, SOLO_DMA_CTRL, 242 SOLO_DMA_CTRL_REFRESH_CYCLE(1) | 243 SOLO_DMA_CTRL_SDRAM_SIZE(sdram) | 244 SOLO_DMA_CTRL_SDRAM_CLK_INVERT | 245 SOLO_DMA_CTRL_READ_CLK_SELECT | 246 SOLO_DMA_CTRL_LATENCY(1)); 247 248 ret = solo_p2m_init(solo_dev); 249 if (ret) 250 goto fail_probe; 251 252 ret = solo_disp_init(solo_dev); 253 if (ret) 254 goto fail_probe; 255 256 ret = solo_gpio_init(solo_dev); 257 if (ret) 258 goto fail_probe; 259 260 ret = solo_tw28_init(solo_dev); 261 if (ret) 262 goto fail_probe; 263 264 ret = solo_v4l2_init(solo_dev); 265 if (ret) 266 goto fail_probe; 267 268 ret = solo_enc_init(solo_dev); 269 if (ret) 270 goto fail_probe; 271 272 ret = solo_enc_v4l2_init(solo_dev); 273 if (ret) 274 goto fail_probe; 275 276 ret = solo_g723_init(solo_dev); 277 if (ret) 278 goto fail_probe; 279 280 return 0; 281 282fail_probe: 283 free_solo_dev(solo_dev); 284 return ret; 285} 286 287static void __devexit solo_pci_remove(struct pci_dev *pdev) 288{ 289 struct solo_dev *solo_dev = pci_get_drvdata(pdev); 290 291 free_solo_dev(solo_dev); 292} 293 294static struct pci_device_id solo_id_table[] = { 295 /* 6010 based cards */ 296 {PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010)}, 297 {PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), 298 .driver_data = FLAGS_6110}, 299 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4)}, 300 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9)}, 301 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16)}, 302 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4)}, 303 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9)}, 304 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16)}, 305 /* 6110 based cards */ 306 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4)}, 307 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8)}, 308 {PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16)}, 309 {0,} 310}; 311 312MODULE_DEVICE_TABLE(pci, solo_id_table); 313 314static struct pci_driver solo_pci_driver = { 315 .name = SOLO6X10_NAME, 316 .id_table = solo_id_table, 317 .probe = solo_pci_probe, 318 .remove = solo_pci_remove, 319}; 320 321static int __init solo_module_init(void) 322{ 323 return pci_register_driver(&solo_pci_driver); 324} 325 326static void __exit solo_module_exit(void) 327{ 328 pci_unregister_driver(&solo_pci_driver); 329} 330 331module_init(solo_module_init); 332module_exit(solo_module_exit); 333