diff --git a/fthd_buffer.h b/fthd_buffer.h index 2b8808f..4a75938 100644 --- a/fthd_buffer.h +++ b/fthd_buffer.h @@ -45,6 +45,7 @@ struct dma_descriptor_list { u32 field0; u32 count; struct dma_descriptor desc[4]; + char unknown[216]; } __attribute__((packed)); struct iommu_obj { @@ -56,7 +57,7 @@ struct iommu_obj { struct fthd_plane { u8 *virt; u64 phys; - dma_addr_t dma; + dma_addr_t dma; int len; struct iommu_obj *iommu; }; @@ -66,7 +67,7 @@ struct h2t_buf_ctx { struct vb2_buffer *vb; struct iommu_obj *plane[4]; struct isp_mem_obj *dma_desc_obj; - struct dma_descriptor_list *dma_desc_list; + struct dma_descriptor_list dma_desc_list; /* waitqueue for signaling buffer completion */ wait_queue_head_t wq; int done; @@ -75,8 +76,8 @@ struct h2t_buf_ctx { extern int setup_buffers(struct fthd_private *dev_priv); extern int fthd_buffer_init(struct fthd_private *dev_priv); extern void fthd_buffer_exit(struct fthd_private *dev_priv); -extern void fthd_buffer_return_handler(struct fthd_private *dev_priv, struct dma_descriptor_list *list, int size); -extern void fthd_buffer_queued_handler(struct fthd_private *dev_priv, struct dma_descriptor_list *list); +extern void fthd_buffer_return_handler(struct fthd_private *dev_priv, u32 offset, int size); +extern void fthd_buffer_queued_handler(struct fthd_private *dev_priv, u32 offset); extern struct iommu_obj *iommu_allocate_sgtable(struct fthd_private *dev_priv, struct sg_table *); extern void iommu_free(struct fthd_private *dev_priv, struct iommu_obj *obj); #endif diff --git a/fthd_drv.c b/fthd_drv.c index cb159aa..09e343f 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -100,19 +100,19 @@ static void fthd_irq_disable(struct fthd_private *dev_priv) static void sharedmalloc_handler(struct fthd_private *dev_priv, struct fw_channel *chan, - struct fthd_ringbuf_entry *entry) + u32 entry) { u32 request_size, response_size, address; - struct isp_mem_obj *obj, **p; + struct isp_mem_obj *obj; - request_size = entry->request_size; - response_size = entry->response_size; - address = entry->address_flags & ~ 3; + request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); + response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); + address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & ~ 3; if (address) { pr_debug("Firmware wants to free memory at %08x\n", address); - p = dev_priv->s2_mem + address - 64; - isp_mem_destroy(*p); + FTHD_S2_MEMCPY_FROMIO(&obj, address - 64, sizeof(obj)); + isp_mem_destroy(obj); fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0); } else { @@ -125,8 +125,7 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv, pr_debug("Firmware allocated %d bytes at %08lx (tag %c%c%c%c)\n", request_size, obj->offset, response_size >> 24,response_size >> 16, response_size >> 8, response_size); - p = dev_priv->s2_mem + obj->offset; - *p = obj; + FTHD_S2_MEMCPY_TOIO(obj->offset, &obj, sizeof(obj)); fthd_channel_ringbuf_send(dev_priv, chan, obj->offset + 64, 0, 0); } @@ -135,59 +134,63 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv, static void terminal_handler(struct fthd_private *dev_priv, struct fw_channel *chan, - struct fthd_ringbuf_entry *entry) + u32 entry) { u32 request_size, response_size, address; + char buf[512]; - request_size = entry->request_size; - response_size = entry->response_size; - address = entry->address_flags & ~ 3; + request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); + response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); + address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & ~ 3; if (!address || !request_size) return; - pr_info("FWMSG: %.*s", request_size, (char *)(dev_priv->s2_mem + address)); - + if (request_size > 512) + request_size = 512; + FTHD_S2_MEMCPY_FROMIO(buf, address, request_size); + pr_info("FWMSG: %.*s", request_size, buf); } static void buf_t2h_handler(struct fthd_private *dev_priv, struct fw_channel *chan, - struct fthd_ringbuf_entry *entry) + u32 entry) { u32 request_size, response_size, address; - request_size = entry->request_size; - response_size = entry->response_size; - address = entry->address_flags & ~ 3; + request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); + response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); + address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS); - if (entry->address_flags & 1) + if (address & 1) return; - fthd_buffer_return_handler(dev_priv, dev_priv->s2_mem + address, request_size); + + fthd_buffer_return_handler(dev_priv, address & ~3, request_size); fthd_channel_ringbuf_send(dev_priv, chan, (response_size & 0x10000000) ? address : 0, 0, 0x80000000); } static void io_t2h_handler(struct fthd_private *dev_priv, struct fw_channel *chan, - struct fthd_ringbuf_entry *entry) + u32 entry) { fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0); } static void buf_h2t_handler(struct fthd_private *dev_priv, struct fw_channel *chan, - struct fthd_ringbuf_entry *entry) + u32 entry) { - fthd_buffer_queued_handler(dev_priv, (struct dma_descriptor_list *)(dev_priv->s2_mem + (entry->address_flags & ~3))); + 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) { - struct fthd_ringbuf_entry *entry; + u32 entry; - while((entry = fthd_channel_ringbuf_receive(dev_priv, chan))) { - pr_debug("channel %s: message available, address %08x\n", chan->name, entry->address_flags); + 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)); if (chan == dev_priv->channel_shared_malloc) { sharedmalloc_handler(dev_priv, chan, entry); } else if (chan == dev_priv->channel_terminal) { diff --git a/fthd_drv.h b/fthd_drv.h index 2343f7f..c6eae90 100644 --- a/fthd_drv.h +++ b/fthd_drv.h @@ -78,13 +78,13 @@ struct fthd_private { wait_queue_head_t cmd_wq; int cmd_ready; /* Mapped PCI resources */ - void *s2_io; + void __iomem *s2_io; u32 s2_io_len; - void *s2_mem; + void __iomem *s2_mem; u32 s2_mem_len; - void *isp_io; + void __iomem *isp_io; u32 isp_io_len; struct work_struct irq_work; diff --git a/fthd_hw.h b/fthd_hw.h index aac1b5e..7982c7b 100644 --- a/fthd_hw.h +++ b/fthd_hw.h @@ -33,6 +33,8 @@ static inline void fthd_hw_pci_post(struct fthd_private *dev_priv) #define FTHD_S2_MEM_READ(offset) _FTHD_S2_MEM_READ(dev_priv, (offset)) #define FTHD_S2_MEM_WRITE(val, offset) _FTHD_S2_MEM_WRITE(dev_priv, (val), (offset)) +#define FTHD_S2_MEMCPY_TOIO(offset, buf, len) _FTHD_S2_MEMCPY_TOIO(dev_priv, (buf), (offset), (len)) +#define FTHD_S2_MEMCPY_FROMIO(buf, offset, len) _FTHD_S2_MEMCPY_FROMIO(dev_priv, (buf), (offset), (len)) #define FTHD_ISP_REG_READ(offset) _FTHD_ISP_REG_READ(dev_priv, (offset)) #define FTHD_ISP_REG_WRITE(val, offset) _FTHD_ISP_REG_WRITE(dev_priv, (val), (offset)) @@ -88,6 +90,19 @@ static inline void _FTHD_S2_MEM_WRITE(struct fthd_private *dev_priv, u32 val, iowrite32(val, dev_priv->s2_mem + offset); } +static inline void _FTHD_S2_MEMCPY_TOIO(struct fthd_private *dev_priv, const void *buf, + u32 offset, int len) +{ + memcpy_toio(dev_priv->s2_mem + offset, buf, len); +} + + +static inline void _FTHD_S2_MEMCPY_FROMIO(struct fthd_private *dev_priv, void *buf, + u32 offset, int len) +{ + memcpy_fromio(buf, dev_priv->s2_mem + offset, len); +} + static inline u32 _FTHD_ISP_REG_READ(struct fthd_private *dev_priv, u32 offset) { if (offset >= dev_priv->isp_io_len) { diff --git a/fthd_isp.c b/fthd_isp.c index b9ec8c5..debced8 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -90,7 +90,7 @@ int isp_mem_destroy(struct isp_mem_obj *obj) return 0; } -int isp_acpi_set_power(struct fthd_private *dev_priv, int power) +static int isp_acpi_set_power(struct fthd_private *dev_priv, int power) { acpi_status status; acpi_handle handle; @@ -163,8 +163,7 @@ static int isp_load_firmware(struct fthd_private *dev_priv) return -EBUSY; } - memcpy(dev_priv->s2_mem + dev_priv->firmware->offset, fw->data, - fw->size); + FTHD_S2_MEMCPY_TOIO(dev_priv->firmware->offset, fw->data, fw->size); /* Might need a flush here if we map ISP memory cached */ @@ -203,40 +202,40 @@ static struct fw_channel *isp_get_chan_index(struct fthd_private *priv, const ch return NULL; } -static int isp_fill_channel_info(struct fthd_private *priv, int offset, int num_channels) +static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int num_channels) { - struct isp_channel_info *info; + struct isp_channel_info info; struct fw_channel *chan; int i; if (!num_channels) return 0; - priv->num_channels = num_channels; - priv->channels = kzalloc(num_channels * sizeof(struct fw_channel *), GFP_KERNEL); - if (!priv->channels) + dev_priv->num_channels = num_channels; + dev_priv->channels = kzalloc(num_channels * sizeof(struct fw_channel *), GFP_KERNEL); + if (!dev_priv->channels) goto out; for(i = 0; i < num_channels; i++) { - info = (struct isp_channel_info *)(priv->s2_mem + offset + i * 256); + FTHD_S2_MEMCPY_FROMIO(&info, offset + i * 256, sizeof(info)); chan = kzalloc(sizeof(struct fw_channel), GFP_KERNEL); if (!chan) goto out; - priv->channels[i] = chan; + dev_priv->channels[i] = chan; pr_debug("Channel %d: %s, type %d, source %d, size %d, offset %x\n", - i, info->name, info->type, info->source, info->size, info->offset); + i, info.name, info.type, info.source, info.size, info.offset); - chan->name = kstrdup(info->name, GFP_KERNEL); + chan->name = kstrdup(info.name, GFP_KERNEL); if (!chan->name) goto out; - chan->type = info->type; - chan->source = info->source; - chan->size = info->size; - chan->offset = info->offset; + chan->type = info.type; + chan->source = info.source; + chan->size = info.size; + chan->offset = info.offset; if (chan->type == FW_CHAN_TYPE_OUT) chan->rx_lock = 1; if (chan->type == FW_CHAN_TYPE_IN) @@ -244,35 +243,38 @@ static int isp_fill_channel_info(struct fthd_private *priv, int offset, int num_ spin_lock_init(&chan->lock); } - priv->channel_terminal = isp_get_chan_index(priv, "TERMINAL"); - priv->channel_debug = isp_get_chan_index(priv, "DEBUG"); - priv->channel_shared_malloc = isp_get_chan_index(priv, "SHAREDMALLOC"); - priv->channel_io = isp_get_chan_index(priv, "IO"); - priv->channel_buf_h2t = isp_get_chan_index(priv, "BUF_H2T"); - priv->channel_buf_t2h = isp_get_chan_index(priv, "BUF_T2H"); - priv->channel_io_t2h = isp_get_chan_index(priv, "IO_T2H"); + dev_priv->channel_terminal = isp_get_chan_index(dev_priv, "TERMINAL"); + dev_priv->channel_debug = isp_get_chan_index(dev_priv, "DEBUG"); + dev_priv->channel_shared_malloc = isp_get_chan_index(dev_priv, "SHAREDMALLOC"); + dev_priv->channel_io = isp_get_chan_index(dev_priv, "IO"); + dev_priv->channel_buf_h2t = isp_get_chan_index(dev_priv, "BUF_H2T"); + dev_priv->channel_buf_t2h = isp_get_chan_index(dev_priv, "BUF_T2H"); + dev_priv->channel_io_t2h = isp_get_chan_index(dev_priv, "IO_T2H"); - if (!priv->channel_terminal || !priv->channel_debug - || !priv->channel_shared_malloc || !priv->channel_io - || !priv->channel_buf_h2t || !priv->channel_buf_t2h - || !priv->channel_io_t2h) { - dev_err(&priv->pdev->dev, "did not find all of the required channels\n"); + if (!dev_priv->channel_terminal || !dev_priv->channel_debug + || !dev_priv->channel_shared_malloc || !dev_priv->channel_io + || !dev_priv->channel_buf_h2t || !dev_priv->channel_buf_t2h + || !dev_priv->channel_io_t2h) { + dev_err(&dev_priv->pdev->dev, "did not find all of the required channels\n"); goto out; } return 0; out: - isp_free_channel_info(priv); + isp_free_channel_info(dev_priv); return -ENOMEM; } -int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds command, void *buf, +static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds command, void *buf, int request_len, int *response_len) { struct isp_mem_obj *request; - struct isp_cmd_hdr *cmd; - struct fthd_ringbuf_entry *entry; + struct isp_cmd_hdr cmd; + u32 address, request_size, response_size; + u32 entry; int len, ret; + memset(&cmd, 0, sizeof(cmd)); + if (response_len) { len = MAX(request_len, *response_len); } else { @@ -288,20 +290,20 @@ int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds command, void return -ENOMEM; } - cmd = dev_priv->s2_mem + request->offset; - memset(cmd, 0, len); - cmd->opcode = command; + cmd.opcode = command; + FTHD_S2_MEMCPY_TOIO(request->offset, &cmd, sizeof(struct isp_cmd_hdr)); if (request_len) - memcpy((char *)cmd + 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, request->offset, request_len + 8, (response_len ? *response_len : 0) + 8); - if (!entry) { + if (entry == (u32)-1) { ret = -EIO; goto out; } + if (command == CISP_CMD_POWER_DOWN) { /* powerdown doesn't seem to generate a response */ ret = 0; @@ -309,21 +311,29 @@ int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds command, void } if (wait_event_interruptible_timeout(dev_priv->cmd_wq, dev_priv->cmd_ready, HZ) <= 0) { - dev_err(&dev_priv->pdev->dev, "timeout wait for command %d\n", cmd->opcode); + 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) *response_len = 0; ret = -ETIMEDOUT; goto out; } + dev_priv->cmd_ready = 0; + + FTHD_S2_MEMCPY_FROMIO(&cmd, request->offset, sizeof(struct isp_cmd_hdr)); + address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS); + request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); + response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); + /* XXX: response size in the ringbuf is zero after command completion, how is buffer size verification done? */ if (response_len && *response_len) - memcpy(buf, (entry->address_flags & ~3) + dev_priv->s2_mem + sizeof(struct isp_cmd_hdr), *response_len); + FTHD_S2_MEMCPY_FROMIO(buf, (address & ~3) + sizeof(struct isp_cmd_hdr), + *response_len); - pr_debug("status %04x, request_len %d response len %d address_flags %x\n", cmd->status, - entry->request_size, entry->response_size, entry->address_flags); + pr_debug("status %04x, request_len %d response len %d address_flags %x\n", cmd.status, + request_size, response_size, address); ret = 0; out: @@ -362,7 +372,7 @@ int fthd_isp_cmd_stop(struct fthd_private *dev_priv) return fthd_isp_cmd(dev_priv, CISP_CMD_STOP, NULL, 0, NULL); } -int fthd_isp_cmd_powerdown(struct fthd_private *dev_priv) +static int fthd_isp_cmd_powerdown(struct fthd_private *dev_priv) { return fthd_isp_cmd(dev_priv, CISP_CMD_POWER_DOWN, NULL, 0, NULL); } @@ -509,7 +519,7 @@ int fthd_isp_cmd_set_loadfile(struct fthd_private *dev_priv) BUG_ON(dev_priv->set_file); file = isp_mem_create(dev_priv, FTHD_MEM_SET_FILE, fw->size); - memcpy(dev_priv->s2_mem + file->offset, fw->data, fw->size); + FTHD_S2_MEMCPY_TOIO(file->offset, fw->data, fw->size); release_firmware(fw); @@ -1138,7 +1148,7 @@ int fthd_stop_channel(struct fthd_private *dev_priv, int channel) int isp_init(struct fthd_private *dev_priv) { struct isp_mem_obj *ipc_queue, *heap, *fw_args; - struct isp_fw_args *fw_args_data; + struct isp_fw_args fw_args_data; u32 num_channels, queue_size, heap_size, reg, offset; int i, retries, ret; @@ -1261,11 +1271,11 @@ int isp_init(struct fthd_private *dev_priv) if (!fw_args) return -ENOMEM; - fw_args_data = dev_priv->s2_mem + fw_args->offset; + FTHD_S2_MEMCPY_TOIO(fw_args->offset, &fw_args_data, sizeof(fw_args_data)); - fw_args_data->__unknown = 2; - fw_args_data->fw_arg = 0; - fw_args_data->full_stats_mode = 0; + fw_args_data.__unknown = 2; + fw_args_data.fw_arg = 0; + fw_args_data.full_stats_mode = 0; FTHD_ISP_REG_WRITE(fw_args->offset, ISP_REG_C301C); diff --git a/fthd_ringbuf.c b/fthd_ringbuf.c index 3c48228..5617041 100644 --- a/fthd_ringbuf.c +++ b/fthd_ringbuf.c @@ -27,16 +27,15 @@ #include "fthd_ringbuf.h" #include "fthd_isp.h" -static struct fthd_ringbuf_entry *get_entry_addr(struct fthd_private *dev_priv, - struct fw_channel *chan, int num) +static u32 get_entry_addr(struct fthd_private *dev_priv, + struct fw_channel *chan, int num) { - return (struct fthd_ringbuf_entry *)(chan->ringbuf.virt_addr \ - + num * sizeof(struct fthd_ringbuf_entry)); + return chan->offset + num * FTHD_RINGBUF_ENTRY_SIZE; } void fthd_channel_ringbuf_dump(struct fthd_private *dev_priv, struct fw_channel *chan) { - struct fthd_ringbuf_entry *entry; + u32 entry; char pos; int i; @@ -45,41 +44,42 @@ void fthd_channel_ringbuf_dump(struct fthd_private *dev_priv, struct fw_channel pos = '*'; else pos = ' '; - entry = dev_priv->s2_mem + chan->offset + i * sizeof(struct fthd_ringbuf_entry); - pr_debug("%s: %c%3.3d: ADDRESS %08x REQUEST_SIZE %08x RESPONSE_SIZE %08x\n", chan->name, - pos, i, entry->address_flags, entry->request_size, entry->response_size); - + entry = get_entry_addr(dev_priv, chan, i); + pr_debug("%s: %c%3.3d: ADDRESS %08x REQUEST_SIZE %08x RESPONSE_SIZE %08x\n", + chan->name, pos, i, + FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS), + FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE), + FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE)); } } void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel *chan) { - struct fthd_ringbuf_entry *entry; + u32 entry; int i; chan->ringbuf.idx = 0; - chan->ringbuf.phys_offset = chan->offset; - chan->ringbuf.virt_addr = dev_priv->s2_mem + chan->offset; if (chan->type == RINGBUF_TYPE_H2T) { - entry = (struct fthd_ringbuf_entry *)chan->ringbuf.virt_addr; - pr_debug("clearing ringbuf %s at %p (size %d)\n", chan->name, entry, chan->size); + pr_debug("clearing ringbuf %s at %08x (size %d)\n", + chan->name, chan->offset, chan->size); spin_lock_irq(&chan->lock); for(i = 0; i < chan->size; i++) { - entry->address_flags = 1; - entry->request_size = 0; - entry->response_size = 0; - entry++; + entry = get_entry_addr(dev_priv, chan, i); + FTHD_S2_MEM_WRITE(1, entry + FTHD_RINGBUF_ADDRESS_FLAGS); + FTHD_S2_MEM_WRITE(0, entry + FTHD_RINGBUF_REQUEST_SIZE); + FTHD_S2_MEM_WRITE(0, entry + FTHD_RINGBUF_RESPONSE_SIZE); + entry += FTHD_RINGBUF_ENTRY_SIZE; } spin_unlock_irq(&chan->lock); } } -struct fthd_ringbuf_entry *fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, +u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, u32 data_offset, u32 request_size, u32 response_size) { - struct fthd_ringbuf_entry *entry; + u32 entry; pr_debug("send %08x\n", data_offset); @@ -88,7 +88,7 @@ struct fthd_ringbuf_entry *fthd_channel_ringbuf_send(struct fthd_private *dev_pr if (chan->tx_lock) { spin_unlock_irq(&chan->lock); - return NULL; + return (u32)-1; } if (chan->type != FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) @@ -97,10 +97,11 @@ struct fthd_ringbuf_entry *fthd_channel_ringbuf_send(struct fthd_private *dev_pr chan->tx_lock = 1; chan->rx_lock = 0; - entry->request_size = request_size; - entry->response_size = response_size; + FTHD_S2_MEM_WRITE(request_size, entry + FTHD_RINGBUF_REQUEST_SIZE); + FTHD_S2_MEM_WRITE(response_size, entry + FTHD_RINGBUF_RESPONSE_SIZE); wmb(); - entry->address_flags = data_offset | (chan->type == 0 ? 0 : 1); + FTHD_S2_MEM_WRITE(data_offset | (chan->type == 0 ? 0 : 1), + entry + FTHD_RINGBUF_ADDRESS_FLAGS); spin_unlock_irq(&chan->lock); spin_lock_irq(&dev_priv->io_lock); @@ -109,10 +110,10 @@ struct fthd_ringbuf_entry *fthd_channel_ringbuf_send(struct fthd_private *dev_pr return entry; } -struct fthd_ringbuf_entry *fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, +u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, struct fw_channel *chan) { - struct fthd_ringbuf_entry *entry, *ret = NULL; + u32 entry, ret = (u32)-1; spin_lock_irq(&chan->lock); if (chan->rx_lock) @@ -120,7 +121,8 @@ struct fthd_ringbuf_entry *fthd_channel_ringbuf_receive(struct fthd_private *dev entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx); - if (!(entry->address_flags & 1) ^ (chan->type != 0)) + + if (!(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0)) goto out; ret = entry; diff --git a/fthd_ringbuf.h b/fthd_ringbuf.h index cf45797..06783fa 100644 --- a/fthd_ringbuf.h +++ b/fthd_ringbuf.h @@ -20,6 +20,12 @@ #ifndef _FTHD_RINGBUF_H #define _FTHD_RINGBUF_H +#define FTHD_RINGBUF_ENTRY_SIZE 64 + +#define FTHD_RINGBUF_ADDRESS_FLAGS 0 +#define FTHD_RINGBUF_REQUEST_SIZE 4 +#define FTHD_RINGBUF_RESPONSE_SIZE 8 + enum ringbuf_type_t { RINGBUF_TYPE_H2T=0, RINGBUF_TYPE_T2H=1, @@ -28,27 +34,18 @@ enum ringbuf_type_t { struct fthd_ringbuf { void *doorbell; - u32 phys_offset; int idx; - u8 *virt_addr; }; -struct fthd_ringbuf_entry { - u32 address_flags; - u32 request_size; - u32 response_size; - u32 __unused[13]; -} __attribute__((packed)); - struct fw_channel; struct fthd_private; 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 struct fthd_ringbuf_entry *fthd_channel_ringbuf_get_entry(struct fthd_private *, struct fw_channel *); -extern struct fthd_ringbuf_entry *fthd_channel_ringbuf_send(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_send(struct fthd_private *dev_priv, struct fw_channel *chan, u32 data_offset, u32 request_size, u32 response_size); -struct fthd_ringbuf_entry *fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, - struct fw_channel *chan); +extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, + struct fw_channel *chan); #endif diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 6d2e368..6807f55 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -42,7 +42,7 @@ .desc = (_desc), \ } -struct fthd_fmt fthd_formats[] = { +static struct fthd_fmt fthd_formats[] = { FTHD_FMT("1280x720 YUYV (4:2:2)", 1280, 720, 1280 * 720 * 2, 1, V4L2_PIX_FMT_YUYV), FTHD_FMT("1280x720 YVYU (4:2:2)", 1280, 720, 1280 * 720 * 2, 1, V4L2_PIX_FMT_YVYU), FTHD_FMT("1280x720 NV16", 1280, 720, 1280 * 720, 2, V4L2_PIX_FMT_NV16), @@ -102,6 +102,7 @@ static void fthd_buffer_cleanup(struct vb2_buffer *vb) struct h2t_buf_ctx *ctx = NULL; int i; + pr_debug("%p\n", vb); for(i = 0; i < FTHD_BUFFERS; i++) { if (dev_priv->h2t_bufs[i].vb == vb) { ctx = dev_priv->h2t_bufs + i; @@ -123,14 +124,17 @@ 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) { - volatile struct fthd_ringbuf_entry *entry; + u32 entry; - // pr_debug("sending buffer %p\n", ctx->vb); + 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)); entry = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_buf_h2t, ctx->dma_desc_obj->offset, 0x180, 0x30000000); - if (!entry) + if (entry == (u32)-1) { + pr_debug("send failed\n"); return -EIO; + } 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); @@ -140,9 +144,18 @@ static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ct return 0; } -void fthd_buffer_queued_handler(struct fthd_private *dev_priv, struct dma_descriptor_list *list) +void fthd_buffer_queued_handler(struct fthd_private *dev_priv, u32 offset) { - struct h2t_buf_ctx *ctx = (struct h2t_buf_ctx *)list->desc[0].tag; + + 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); } @@ -171,7 +184,7 @@ static void fthd_buffer_queue(struct vb2_buffer *vb) if (!vb->vb2_queue->streaming) { ctx->state = BUF_DRV_QUEUED; } else { - list = ctx->dma_desc_list; + list = &ctx->dma_desc_list; list->field0 = 1; ctx->state = BUF_HW_QUEUED; wmb(); @@ -194,6 +207,7 @@ static int fthd_buffer_prepare(struct vb2_buffer *vb) struct dma_descriptor_list *dma_list; int i; + pr_debug("%p\n", vb); for(i = 0; i < FTHD_BUFFERS; i++) { if (dev_priv->h2t_bufs[i].state == BUF_FREE || (dev_priv->h2t_bufs[i].state == BUF_ALLOC && dev_priv->h2t_bufs[i].vb == vb)) { @@ -211,7 +225,6 @@ static int fthd_buffer_prepare(struct vb2_buffer *vb) if (!ctx->dma_desc_obj) return -ENOMEM; - ctx->dma_desc_list = dev_priv->s2_mem + ctx->dma_desc_obj->offset; ctx->vb = vb; ctx->state = BUF_ALLOC; @@ -225,7 +238,7 @@ static int fthd_buffer_prepare(struct vb2_buffer *vb) vb2_set_plane_payload(vb, 0, dev_priv->fmt.fmt.sizeimage); - dma_list = ctx->dma_desc_list; + dma_list = &ctx->dma_desc_list; memset(dma_list, 0, 0x180); dma_list->field0 = 1; @@ -244,15 +257,18 @@ static int fthd_buffer_prepare(struct vb2_buffer *vb) return 0; } -void fthd_buffer_return_handler(struct fthd_private *dev_priv, struct dma_descriptor_list *list, int size) +void fthd_buffer_return_handler(struct fthd_private *dev_priv, u32 offset, int size) { + struct dma_descriptor_list list; struct h2t_buf_ctx *ctx; int i; - for(i = 0; i < list->count; i++) { - ctx = (struct h2t_buf_ctx *)list->desc[i].tag; - pr_debug("%d: field0: %d, count %d, pool %d, addr0 0x%08x, addr1 0x%08x tag 0x%08llx vb = %p\n", i, list->field0, - list->desc[i].count, list->desc[i].pool, list->desc[i].addr0, list->desc[i].addr1, list->desc[i].tag, ctx->vb); + FTHD_S2_MEMCPY_FROMIO(&list, offset, sizeof(list)); + + for(i = 0; i < list.count; i++) { + ctx = (struct h2t_buf_ctx *)list.desc[i].tag; + pr_debug("%d: field0: %d, count %d, pool %d, addr0 0x%08x, addr1 0x%08x tag 0x%08llx vb = %p, ctx = %p\n", i, list.field0, + list.desc[i].count, list.desc[i].pool, list.desc[i].addr0, list.desc[i].addr1, list.desc[i].tag, ctx->vb, ctx); if (ctx->state == BUF_HW_QUEUED || ctx->state == BUF_DRV_QUEUED) { ctx->state = BUF_ALLOC;