facetimehd: don't access __iomem directly

This commit is contained in:
Sven Schnelle
2015-11-28 07:29:47 +01:00
parent 5305cee744
commit 9dd6bc2a02
8 changed files with 180 additions and 136 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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;