diff --git a/Makefile b/Makefile index 1425991..19b68e8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -bcwc_pcie-objs := bcwc_ddr.o bcwc_hw.o bcwc_drv.o +bcwc_pcie-objs := bcwc_ddr.o bcwc_hw.o bcwc_drv.o isp.o obj-m := bcwc_pcie.o KVERSION := $(shell uname -r) diff --git a/bcwc_hw.c b/bcwc_hw.c index 7fdac10..572159e 100644 --- a/bcwc_hw.c +++ b/bcwc_hw.c @@ -21,6 +21,7 @@ #include "bcwc_drv.h" #include "bcwc_hw.h" #include "bcwc_ddr.h" +#include "isp.h" /* FIXME: Double check these */ static u32 ddr_phy_reg_map[] = { @@ -657,100 +658,6 @@ static int bcwc_hw_ddr_phy_save_regs(struct bcwc_private *dev_priv) return 0; } -static int bcwc_hw_isp_init(struct bcwc_private *dev_priv) -{ - u32 num_channels, queue_size; - u32 reg; - int i, retries; - - BCWC_ISP_REG_WRITE(0, ISP_IPC_NUM_CHAN); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_IPC_QUEUE_SIZE); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_REG_08); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_FW_HEAP_SIZE); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_REG_10); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_REG_14); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_REG_18); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0, ISP_REG_1C); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0xffffffff, ISP_REG_41024); - bcwc_hw_pci_post(dev_priv); - - /* - * Probably the IPC queue - * FIXME: Check if we can do 64bit writes on PCIe - */ - for (i = IRQ_REG_RANGE_START; i <= IRQ_REG_RANGE_END; i += 8) { - BCWC_ISP_REG_WRITE(0xffffff, i); - BCWC_ISP_REG_WRITE(0x000000, i + 4); - } - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE( 0x80000000, ISP_REG_40008); - bcwc_hw_pci_post(dev_priv); - - BCWC_ISP_REG_WRITE(0x1, ISP_REG_40004); - bcwc_hw_pci_post(dev_priv); - - for (retries = 0; retries < 1000; retries++) { - reg = BCWC_ISP_REG_READ(ISP_REG_40004); - if ((reg & 0xff) == 0xf0) - break; - udelay(10); - } - - if (retries >= 1000) { - dev_info(&dev_priv->pdev->dev, "Init failed! No wake signal\n"); - return -EIO; - } - - BCWC_ISP_REG_WRITE(0xffffffff, ISP_REG_41024); - - num_channels = BCWC_ISP_REG_READ(ISP_IPC_NUM_CHAN) + 1; - queue_size = BCWC_ISP_REG_READ(ISP_IPC_QUEUE_SIZE); - - dev_info(&dev_priv->pdev->dev, - "Number of IPC channels: %u, queue size: %u\n", - num_channels, queue_size); - - if (num_channels > 32) { - dev_info(&dev_priv->pdev->dev, "Too many IPC channels: %u\n", - num_channels); - return -EIO; - } - - /* - bcwc_alloc_dev_mem(queue_size, &ret, 0); - */ - - /* Firmware must fit in 4194304 bytes */ - reg = BCWC_ISP_REG_READ(ISP_FW_HEAP_SIZE); - if (reg > 0x400000) { - dev_info(&dev_priv->pdev->dev, - "Firmware request size too big (%u bytes)\n", - reg); - return -ENOMEM; - } - - dev_info(&dev_priv->pdev->dev, "Firmware request size: %u\n", reg); - - return 0; -} - static int bcwc_hw_irq_enable(struct bcwc_private *dev_priv) { return 0; diff --git a/bcwc_reg.h b/bcwc_reg.h index fdead99..addbbb2 100644 --- a/bcwc_reg.h +++ b/bcwc_reg.h @@ -140,18 +140,18 @@ /* On iomem with pointer at 0x0ff0 (Bar 4: 1MB) */ #define ISP_IPC_NUM_CHAN 0xc3000 #define ISP_IPC_QUEUE_SIZE 0xc3004 -#define ISP_REG_08 0xc3008 +#define ISP_REG_C3008 0xc3008 #define ISP_FW_HEAP_SIZE 0xc300c -#define ISP_REG_10 0xc3010 -#define ISP_REG_14 0xc3014 -#define ISP_REG_18 0xc3018 -#define ISP_REG_1C 0xc301c +#define ISP_REG_C3010 0xc3010 +#define ISP_REG_C3014 0xc3014 +#define ISP_REG_C3018 0xc3018 +#define ISP_REG_C301C 0xc301c #define ISP_REG_40004 0x40004 #define ISP_REG_40008 0x40008 #define ISP_REG_41000 0x41000 #define ISP_REG_41024 0x41024 -#define IRQ_REG_RANGE_START 0x0128 -#define IRQ_REG_RANGE_END 0x0220 +#define ISP_IPC_CHAN_START 0x0128 +#define ISP_IPC_CHAN_END 0x0220 #endif diff --git a/isp.c b/isp.c new file mode 100644 index 0000000..bb85cc3 --- /dev/null +++ b/isp.c @@ -0,0 +1,117 @@ +/* + * Broadcom PCIe 1570 webcam driver + * Some of the register defines are taken from the crystalhd driver + * + * Copyright (C) 2014 Patrik Jakobsson (patrik.r.jakobsson@gmail.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ + +#include +#include "bcwc_drv.h" +#include "bcwc_hw.h" +#include "bcwc_reg.h" +#include "isp.h" + +int isp_init(struct bcwc_private *dev_priv) +{ + u32 num_channels, queue_size; + u32 reg; + int i, retries; + + BCWC_ISP_REG_WRITE(0, ISP_IPC_NUM_CHAN); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_IPC_QUEUE_SIZE); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_REG_C3008); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_FW_HEAP_SIZE); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_REG_C3010); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_REG_C3014); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_REG_C3018); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0, ISP_REG_C301C); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0xffffffff, ISP_REG_41024); + bcwc_hw_pci_post(dev_priv); + + /* + * Probably the IPC queue + * FIXME: Check if we can do 64bit writes on PCIe + */ + for (i = ISP_IPC_CHAN_START; i <= ISP_IPC_CHAN_END; i += 8) { + BCWC_ISP_REG_WRITE(0xffffffff, i); + BCWC_ISP_REG_WRITE(0, i + 4); + } + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE( 0x80000000, ISP_REG_40008); + bcwc_hw_pci_post(dev_priv); + + BCWC_ISP_REG_WRITE(0x1, ISP_REG_40004); + bcwc_hw_pci_post(dev_priv); + + for (retries = 0; retries < 1000; retries++) { + reg = BCWC_ISP_REG_READ(ISP_REG_40004); + if ((reg & 0xff) == 0xf0) + break; + udelay(10); + } + + if (retries >= 1000) { + dev_info(&dev_priv->pdev->dev, "Init failed! No wake signal\n"); + return -EIO; + } + + BCWC_ISP_REG_WRITE(0xffffffff, ISP_REG_41024); + + num_channels = BCWC_ISP_REG_READ(ISP_IPC_NUM_CHAN) + 1; + queue_size = BCWC_ISP_REG_READ(ISP_IPC_QUEUE_SIZE); + + dev_info(&dev_priv->pdev->dev, + "Number of IPC channels: %u, queue size: %u\n", + num_channels, queue_size); + + if (num_channels > 32) { + dev_info(&dev_priv->pdev->dev, "Too many IPC channels: %u\n", + num_channels); + return -EIO; + } + + /* + bcwc_alloc_dev_mem(queue_size, &ret, 0); + */ + + /* Firmware must fit in 4194304 bytes */ + reg = BCWC_ISP_REG_READ(ISP_FW_HEAP_SIZE); + if (reg > 0x400000) { + dev_info(&dev_priv->pdev->dev, + "Firmware request size too big (%u bytes)\n", + reg); + return -ENOMEM; + } + + dev_info(&dev_priv->pdev->dev, "Firmware request size: %u\n", reg); + + return 0; +} + + +int isp_uninit(struct bcwc_private *dev_priv) +{ + return 0; +} diff --git a/isp.h b/isp.h new file mode 100644 index 0000000..9e21252 --- /dev/null +++ b/isp.h @@ -0,0 +1,18 @@ +/* + * Broadcom PCIe 1570 webcam driver + * Some of the register defines are taken from the crystalhd driver + * + * Copyright (C) 2014 Patrik Jakobsson (patrik.r.jakobsson@gmail.com) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + */ + +#ifndef _ISP_H +#define _ISP_H + +extern int isp_init(struct bcwc_private *dev_priv); + +#endif