mirror of
https://github.com/patjak/facetimehd.git
synced 2026-04-09 19:10:01 +02:00
Merge branch 'my_fixes' of git://github.com/sschnelle/facetimehd
This commit is contained in:
60
fthd_drv.c
60
fthd_drv.c
@@ -80,13 +80,13 @@ static int fthd_pci_reserve_mem(struct fthd_private *dev_priv)
|
|||||||
dev_priv->isp_io = ioremap_nocache(start, len);
|
dev_priv->isp_io = ioremap_nocache(start, len);
|
||||||
dev_priv->isp_io_len = len;
|
dev_priv->isp_io_len = len;
|
||||||
|
|
||||||
pr_debug("Allocated S2 regs (BAR %d). %u bytes at 0x%p",
|
pr_debug("Allocated S2 regs (BAR %d). %u bytes at 0x%p\n",
|
||||||
FTHD_PCI_S2_IO, dev_priv->s2_io_len, dev_priv->s2_io);
|
FTHD_PCI_S2_IO, dev_priv->s2_io_len, dev_priv->s2_io);
|
||||||
|
|
||||||
pr_debug("Allocated S2 mem (BAR %d). %u bytes at 0x%p",
|
pr_debug("Allocated S2 mem (BAR %d). %u bytes at 0x%p\n",
|
||||||
FTHD_PCI_S2_MEM, dev_priv->s2_mem_len, dev_priv->s2_mem);
|
FTHD_PCI_S2_MEM, dev_priv->s2_mem_len, dev_priv->s2_mem);
|
||||||
|
|
||||||
pr_debug("Allocated ISP regs (BAR %d). %u bytes at 0x%p",
|
pr_debug("Allocated ISP regs (BAR %d). %u bytes at 0x%p\n",
|
||||||
FTHD_PCI_ISP_IO, dev_priv->isp_io_len, dev_priv->isp_io);
|
FTHD_PCI_ISP_IO, dev_priv->isp_io_len, dev_priv->isp_io);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -104,6 +104,7 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv,
|
|||||||
{
|
{
|
||||||
u32 request_size, response_size, address;
|
u32 request_size, response_size, address;
|
||||||
struct isp_mem_obj *obj;
|
struct isp_mem_obj *obj;
|
||||||
|
int ret;
|
||||||
|
|
||||||
request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE);
|
request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE);
|
||||||
response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
||||||
@@ -114,7 +115,9 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv,
|
|||||||
FTHD_S2_MEMCPY_FROMIO(&obj, address - 64, sizeof(obj));
|
FTHD_S2_MEMCPY_FROMIO(&obj, address - 64, sizeof(obj));
|
||||||
isp_mem_destroy(obj);
|
isp_mem_destroy(obj);
|
||||||
|
|
||||||
fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0);
|
ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
} else {
|
} else {
|
||||||
if (!request_size)
|
if (!request_size)
|
||||||
return;
|
return;
|
||||||
@@ -126,7 +129,10 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv,
|
|||||||
response_size >> 24,response_size >> 16,
|
response_size >> 24,response_size >> 16,
|
||||||
response_size >> 8, response_size);
|
response_size >> 8, response_size);
|
||||||
FTHD_S2_MEMCPY_TOIO(obj->offset, &obj, sizeof(obj));
|
FTHD_S2_MEMCPY_TOIO(obj->offset, &obj, sizeof(obj));
|
||||||
fthd_channel_ringbuf_send(dev_priv, chan, obj->offset + 64, 0, 0);
|
ret = fthd_channel_ringbuf_send(dev_priv, chan, obj->offset + 64, 0, 0, NULL);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -157,7 +163,7 @@ static void buf_t2h_handler(struct fthd_private *dev_priv,
|
|||||||
u32 entry)
|
u32 entry)
|
||||||
{
|
{
|
||||||
u32 request_size, response_size, address;
|
u32 request_size, response_size, address;
|
||||||
|
int ret;
|
||||||
request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE);
|
request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE);
|
||||||
response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
||||||
address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS);
|
address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS);
|
||||||
@@ -167,27 +173,42 @@ static void buf_t2h_handler(struct fthd_private *dev_priv,
|
|||||||
|
|
||||||
|
|
||||||
fthd_buffer_return_handler(dev_priv, address & ~3, request_size);
|
fthd_buffer_return_handler(dev_priv, address & ~3, request_size);
|
||||||
fthd_channel_ringbuf_send(dev_priv, chan, (response_size & 0x10000000) ? address : 0,
|
ret = fthd_channel_ringbuf_send(dev_priv, chan, (response_size & 0x10000000) ? address : 0,
|
||||||
0, 0x80000000);
|
0, 0x80000000, NULL);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_t2h_handler(struct fthd_private *dev_priv,
|
static void io_t2h_handler(struct fthd_private *dev_priv,
|
||||||
struct fw_channel *chan,
|
struct fw_channel *chan,
|
||||||
u32 entry)
|
u32 entry)
|
||||||
{
|
{
|
||||||
fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0);
|
int ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL);
|
||||||
}
|
if (ret)
|
||||||
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
|
|
||||||
static void buf_h2t_handler(struct fthd_private *dev_priv,
|
|
||||||
struct fw_channel *chan,
|
|
||||||
u32 entry)
|
|
||||||
{
|
|
||||||
fthd_buffer_queued_handler(dev_priv, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & ~3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *chan)
|
static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *chan)
|
||||||
{
|
{
|
||||||
u32 entry;
|
u32 entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (chan == dev_priv->channel_io) {
|
||||||
|
pr_debug("IO channel ready\n");
|
||||||
|
wake_up_interruptible(&chan->wq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan == dev_priv->channel_buf_h2t) {
|
||||||
|
pr_debug("H2T channel ready\n");
|
||||||
|
wake_up_interruptible(&chan->wq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan == dev_priv->channel_debug)
|
||||||
|
return;
|
||||||
|
|
||||||
while((entry = fthd_channel_ringbuf_receive(dev_priv, chan)) != (u32)-1) {
|
while((entry = fthd_channel_ringbuf_receive(dev_priv, chan)) != (u32)-1) {
|
||||||
pr_debug("channel %s: message available, address %08x\n", chan->name, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS));
|
pr_debug("channel %s: message available, address %08x\n", chan->name, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS));
|
||||||
@@ -195,15 +216,13 @@ static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *ch
|
|||||||
sharedmalloc_handler(dev_priv, chan, entry);
|
sharedmalloc_handler(dev_priv, chan, entry);
|
||||||
} else if (chan == dev_priv->channel_terminal) {
|
} else if (chan == dev_priv->channel_terminal) {
|
||||||
terminal_handler(dev_priv, chan, entry);
|
terminal_handler(dev_priv, chan, entry);
|
||||||
fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0);
|
ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL);
|
||||||
|
if (ret)
|
||||||
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
} else if (chan == dev_priv->channel_buf_t2h) {
|
} else if (chan == dev_priv->channel_buf_t2h) {
|
||||||
buf_t2h_handler(dev_priv, chan, entry);
|
buf_t2h_handler(dev_priv, chan, entry);
|
||||||
} else if (chan == dev_priv->channel_io) {
|
|
||||||
wake_up_interruptible(&dev_priv->cmd_wq);
|
|
||||||
} else if (chan == dev_priv->channel_io_t2h) {
|
} else if (chan == dev_priv->channel_io_t2h) {
|
||||||
io_t2h_handler(dev_priv, chan, entry);
|
io_t2h_handler(dev_priv, chan, entry);
|
||||||
} else if (chan == dev_priv->channel_buf_h2t) {
|
|
||||||
buf_h2t_handler(dev_priv, chan, entry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,7 +460,6 @@ static int fthd_pci_probe(struct pci_dev *pdev,
|
|||||||
mutex_init(&dev_priv->vb2_queue_lock);
|
mutex_init(&dev_priv->vb2_queue_lock);
|
||||||
|
|
||||||
mutex_init(&dev_priv->ioctl_lock);
|
mutex_init(&dev_priv->ioctl_lock);
|
||||||
init_waitqueue_head(&dev_priv->cmd_wq);
|
|
||||||
INIT_LIST_HEAD(&dev_priv->buffer_queue);
|
INIT_LIST_HEAD(&dev_priv->buffer_queue);
|
||||||
INIT_WORK(&dev_priv->irq_work, fthd_irq_work);
|
INIT_WORK(&dev_priv->irq_work, fthd_irq_work);
|
||||||
|
|
||||||
|
|||||||
@@ -49,11 +49,10 @@ struct fw_channel {
|
|||||||
u32 size;
|
u32 size;
|
||||||
u32 source;
|
u32 source;
|
||||||
u32 type;
|
u32 type;
|
||||||
int tx_lock;
|
|
||||||
int rx_lock;
|
|
||||||
struct fthd_ringbuf ringbuf;
|
struct fthd_ringbuf ringbuf;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
/* waitqueue for signaling completion */
|
||||||
|
wait_queue_head_t wq;
|
||||||
char *name;
|
char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -68,9 +67,6 @@ struct fthd_private {
|
|||||||
/* lock for synchronizing with irq/workqueue */
|
/* lock for synchronizing with irq/workqueue */
|
||||||
spinlock_t io_lock;
|
spinlock_t io_lock;
|
||||||
|
|
||||||
/* waitqueue for signaling command completion */
|
|
||||||
wait_queue_head_t cmd_wq;
|
|
||||||
|
|
||||||
/* Mapped PCI resources */
|
/* Mapped PCI resources */
|
||||||
void __iomem *s2_io;
|
void __iomem *s2_io;
|
||||||
u32 s2_io_len;
|
u32 s2_io_len;
|
||||||
|
|||||||
23
fthd_isp.c
23
fthd_isp.c
@@ -210,13 +210,14 @@ static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!num_channels)
|
if (!num_channels)
|
||||||
return 0;
|
return -EINVAL;
|
||||||
|
|
||||||
dev_priv->num_channels = num_channels;
|
|
||||||
dev_priv->channels = kzalloc(num_channels * sizeof(struct fw_channel *), GFP_KERNEL);
|
dev_priv->channels = kzalloc(num_channels * sizeof(struct fw_channel *), GFP_KERNEL);
|
||||||
if (!dev_priv->channels)
|
if (!dev_priv->channels)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
dev_priv->num_channels = num_channels;
|
||||||
|
|
||||||
for(i = 0; i < num_channels; i++) {
|
for(i = 0; i < num_channels; i++) {
|
||||||
FTHD_S2_MEMCPY_FROMIO(&info, offset + i * 256, sizeof(info));
|
FTHD_S2_MEMCPY_FROMIO(&info, offset + i * 256, sizeof(info));
|
||||||
|
|
||||||
@@ -237,11 +238,8 @@ static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int
|
|||||||
chan->source = info.source;
|
chan->source = info.source;
|
||||||
chan->size = info.size;
|
chan->size = info.size;
|
||||||
chan->offset = info.offset;
|
chan->offset = info.offset;
|
||||||
if (chan->type == FW_CHAN_TYPE_OUT)
|
|
||||||
chan->rx_lock = 1;
|
|
||||||
if (chan->type == FW_CHAN_TYPE_IN)
|
|
||||||
chan->tx_lock = 1;
|
|
||||||
spin_lock_init(&chan->lock);
|
spin_lock_init(&chan->lock);
|
||||||
|
init_waitqueue_head(&chan->wq);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_priv->channel_terminal = isp_get_chan_index(dev_priv, "TERMINAL");
|
dev_priv->channel_terminal = isp_get_chan_index(dev_priv, "TERMINAL");
|
||||||
@@ -297,8 +295,10 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman
|
|||||||
if (request_len)
|
if (request_len)
|
||||||
FTHD_S2_MEMCPY_TOIO(request->offset + sizeof(struct isp_cmd_hdr), buf, request_len);
|
FTHD_S2_MEMCPY_TOIO(request->offset + sizeof(struct isp_cmd_hdr), buf, request_len);
|
||||||
|
|
||||||
entry = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_io,
|
ret = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_io,
|
||||||
request->offset, request_len + 8, (response_len ? *response_len : 0) + 8);
|
request->offset, request_len + 8, (response_len ? *response_len : 0) + 8, &entry);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (entry == (u32)-1) {
|
if (entry == (u32)-1) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
@@ -311,13 +311,10 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_event_interruptible_timeout(dev_priv->cmd_wq,
|
ret = fthd_channel_wait_ready(dev_priv, dev_priv->channel_io, entry, 2000);
|
||||||
FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1, HZ) <= 0) {
|
if (ret) {
|
||||||
dev_err(&dev_priv->pdev->dev, "timeout wait for command %d\n", cmd.opcode);
|
|
||||||
fthd_channel_ringbuf_dump(dev_priv, dev_priv->channel_io);
|
|
||||||
if (response_len)
|
if (response_len)
|
||||||
*response_len = 0;
|
*response_len = 0;
|
||||||
ret = -ETIMEDOUT;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,8 @@ void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan,
|
int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan,
|
||||||
u32 data_offset, u32 request_size, u32 response_size)
|
u32 data_offset, u32 request_size, u32 response_size, u32 *entryp)
|
||||||
{
|
{
|
||||||
u32 entry;
|
u32 entry;
|
||||||
|
|
||||||
@@ -86,16 +86,13 @@ u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *
|
|||||||
spin_lock_irq(&chan->lock);
|
spin_lock_irq(&chan->lock);
|
||||||
entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx);
|
entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx);
|
||||||
|
|
||||||
if (chan->tx_lock) {
|
if (++chan->ringbuf.idx >= chan->size)
|
||||||
spin_unlock_irq(&chan->lock);
|
|
||||||
return (u32)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chan->type != FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size)
|
|
||||||
chan->ringbuf.idx = 0;
|
chan->ringbuf.idx = 0;
|
||||||
|
|
||||||
chan->tx_lock = 1;
|
if (!(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0)) {
|
||||||
chan->rx_lock = 0;
|
spin_unlock_irq(&chan->lock);
|
||||||
|
return -EAGAIN;
|
||||||
|
}
|
||||||
|
|
||||||
FTHD_S2_MEM_WRITE(request_size, entry + FTHD_RINGBUF_REQUEST_SIZE);
|
FTHD_S2_MEM_WRITE(request_size, entry + FTHD_RINGBUF_REQUEST_SIZE);
|
||||||
FTHD_S2_MEM_WRITE(response_size, entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
FTHD_S2_MEM_WRITE(response_size, entry + FTHD_RINGBUF_RESPONSE_SIZE);
|
||||||
@@ -107,7 +104,9 @@ u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *
|
|||||||
spin_lock_irq(&dev_priv->io_lock);
|
spin_lock_irq(&dev_priv->io_lock);
|
||||||
FTHD_ISP_REG_WRITE(0x10 << chan->source, ISP_REG_41020);
|
FTHD_ISP_REG_WRITE(0x10 << chan->source, ISP_REG_41020);
|
||||||
spin_unlock_irq(&dev_priv->io_lock);
|
spin_unlock_irq(&dev_priv->io_lock);
|
||||||
return entry;
|
if (entryp)
|
||||||
|
*entryp = entry;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
||||||
@@ -116,8 +115,6 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
|||||||
u32 entry, ret = (u32)-1;
|
u32 entry, ret = (u32)-1;
|
||||||
|
|
||||||
spin_lock_irq(&chan->lock);
|
spin_lock_irq(&chan->lock);
|
||||||
if (chan->rx_lock)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx);
|
entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx);
|
||||||
|
|
||||||
@@ -130,9 +127,19 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
|||||||
if (chan->type == FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size)
|
if (chan->type == FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size)
|
||||||
chan->ringbuf.idx = 0;
|
chan->ringbuf.idx = 0;
|
||||||
|
|
||||||
chan->rx_lock = 1;
|
|
||||||
chan->tx_lock = 0;
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_irq(&chan->lock);
|
spin_unlock_irq(&chan->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout)
|
||||||
|
{
|
||||||
|
if (wait_event_interruptible_timeout(chan->wq,
|
||||||
|
(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0),
|
||||||
|
msecs_to_jiffies(timeout)) <= 0) {
|
||||||
|
dev_err(&dev_priv->pdev->dev, "%s: timeout\n", chan->name);
|
||||||
|
fthd_channel_ringbuf_dump(dev_priv, chan);
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,10 +42,11 @@ struct fthd_private;
|
|||||||
extern void fthd_channel_ringbuf_dump(struct fthd_private *dev_priv, struct fw_channel *chan);
|
extern void fthd_channel_ringbuf_dump(struct fthd_private *dev_priv, struct fw_channel *chan);
|
||||||
extern void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel *chan);
|
extern void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel *chan);
|
||||||
extern u32 fthd_channel_ringbuf_get_entry(struct fthd_private *, struct fw_channel *);
|
extern u32 fthd_channel_ringbuf_get_entry(struct fthd_private *, struct fw_channel *);
|
||||||
extern u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan,
|
extern int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan,
|
||||||
u32 data_offset, u32 request_size, u32 response_size);
|
u32 data_offset, u32 request_size, u32 response_size, u32 *entry);
|
||||||
|
|
||||||
extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv,
|
||||||
struct fw_channel *chan);
|
struct fw_channel *chan);
|
||||||
|
|
||||||
|
extern int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
60
fthd_v4l2.c
60
fthd_v4l2.c
@@ -33,6 +33,11 @@
|
|||||||
#include "fthd_ringbuf.h"
|
#include "fthd_ringbuf.h"
|
||||||
#include "fthd_buffer.h"
|
#include "fthd_buffer.h"
|
||||||
|
|
||||||
|
#define FTHD_MAX_WIDTH 2560
|
||||||
|
#define FTHD_MAX_HEIGHT 1600
|
||||||
|
#define FTHD_MIN_WIDTH 320
|
||||||
|
#define FTHD_MIN_HEIGHT 240
|
||||||
|
|
||||||
#define FTHD_FMT(_desc, _x, _y, _sizeimage, _planes, _pixfmt) \
|
#define FTHD_FMT(_desc, _x, _y, _sizeimage, _planes, _pixfmt) \
|
||||||
{ \
|
{ \
|
||||||
.fmt.width = (_x), \
|
.fmt.width = (_x), \
|
||||||
@@ -126,39 +131,18 @@ static void fthd_buffer_cleanup(struct vb2_buffer *vb)
|
|||||||
static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ctx *ctx)
|
static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ctx *ctx)
|
||||||
{
|
{
|
||||||
u32 entry;
|
u32 entry;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pr_debug("sending buffer %p size %ld, ctx %p\n", ctx->vb, sizeof(ctx->dma_desc_list), ctx);
|
pr_debug("sending buffer %p size %ld, ctx %p\n", ctx->vb, sizeof(ctx->dma_desc_list), ctx);
|
||||||
FTHD_S2_MEMCPY_TOIO(ctx->dma_desc_obj->offset, &ctx->dma_desc_list, sizeof(ctx->dma_desc_list));
|
FTHD_S2_MEMCPY_TOIO(ctx->dma_desc_obj->offset, &ctx->dma_desc_list, sizeof(ctx->dma_desc_list));
|
||||||
entry = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_buf_h2t,
|
ret = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_buf_h2t,
|
||||||
ctx->dma_desc_obj->offset, 0x180, 0x30000000);
|
ctx->dma_desc_obj->offset, 0x180, 0x30000000, &entry);
|
||||||
|
|
||||||
if (entry == (u32)-1) {
|
if (ret) {
|
||||||
pr_debug("send failed\n");
|
pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret);
|
||||||
return -EIO;
|
return ret;
|
||||||
}
|
}
|
||||||
|
return fthd_channel_wait_ready(dev_priv, dev_priv->channel_buf_h2t, entry, 2000);
|
||||||
if (wait_event_interruptible_timeout(ctx->wq, ctx->done, HZ) <= 0) {
|
|
||||||
dev_err(&dev_priv->pdev->dev, "timeout wait for buffer %p\n", ctx->vb);
|
|
||||||
return -ETIMEDOUT;
|
|
||||||
}
|
|
||||||
ctx->done = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fthd_buffer_queued_handler(struct fthd_private *dev_priv, u32 offset)
|
|
||||||
{
|
|
||||||
|
|
||||||
struct dma_descriptor_list list;
|
|
||||||
struct h2t_buf_ctx *ctx;
|
|
||||||
|
|
||||||
|
|
||||||
FTHD_S2_MEMCPY_FROMIO(&list, offset, sizeof(list));
|
|
||||||
|
|
||||||
ctx = (struct h2t_buf_ctx *)list.desc[0].tag;
|
|
||||||
pr_debug("vb %p, ctx = %p\n", ctx->vb, ctx);
|
|
||||||
memcpy(&ctx->dma_desc_list, &list, sizeof(ctx->dma_desc_list));
|
|
||||||
ctx->done = 1;
|
|
||||||
wake_up_interruptible(&ctx->wq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fthd_buffer_queue(struct vb2_buffer *vb)
|
static void fthd_buffer_queue(struct vb2_buffer *vb)
|
||||||
@@ -541,11 +525,11 @@ static int fthd_v4l2_ioctl_enum_framesizes(struct file *filp, void *priv,
|
|||||||
if (sizes->index)
|
if (sizes->index)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
|
sizes->type = V4L2_FRMSIZE_TYPE_STEPWISE;
|
||||||
sizes->stepwise.min_width = 320;
|
sizes->stepwise.min_width = FTHD_MIN_WIDTH;
|
||||||
sizes->stepwise.max_width = 2560;
|
sizes->stepwise.max_width = FTHD_MAX_WIDTH;
|
||||||
sizes->stepwise.min_height = 240;
|
sizes->stepwise.min_height = FTHD_MIN_HEIGHT;
|
||||||
sizes->stepwise.max_height = 1600;
|
sizes->stepwise.max_height = FTHD_MAX_HEIGHT;
|
||||||
sizes->stepwise.step_width = 8;
|
sizes->stepwise.step_width = 8;
|
||||||
sizes->stepwise.step_height = 1;
|
sizes->stepwise.step_height = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -564,13 +548,19 @@ static int fthd_v4l2_ioctl_enum_frameintervals(struct file *filp, void *priv,
|
|||||||
interval->pixel_format != V4L2_PIX_FMT_NV16)
|
interval->pixel_format != V4L2_PIX_FMT_NV16)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (interval->width & 7
|
||||||
|
|| interval->width > FTHD_MAX_WIDTH
|
||||||
|
|| interval->height > FTHD_MAX_HEIGHT)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
interval->type = V4L2_FRMIVAL_TYPE_STEPWISE;
|
interval->type = V4L2_FRMIVAL_TYPE_STEPWISE;
|
||||||
|
interval->stepwise.step.numerator = 1;
|
||||||
|
interval->stepwise.step.denominator = 1000;
|
||||||
interval->stepwise.min.numerator = 33;
|
interval->stepwise.min.numerator = 33;
|
||||||
interval->stepwise.min.denominator = 1000;
|
interval->stepwise.min.denominator = 1000;
|
||||||
interval->stepwise.max.numerator = 500;
|
interval->stepwise.max.numerator = 500;
|
||||||
interval->stepwise.max.denominator = 1000;
|
interval->stepwise.max.denominator = 1000;
|
||||||
|
return 0;
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct v4l2_ioctl_ops fthd_ioctl_ops = {
|
static struct v4l2_ioctl_ops fthd_ioctl_ops = {
|
||||||
|
|||||||
Reference in New Issue
Block a user