mirror of
https://github.com/patjak/facetimehd.git
synced 2026-04-09 11:02:31 +02:00
facetimehd: don't access __iomem directly
This commit is contained in:
@@ -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
|
||||
|
||||
57
fthd_drv.c
57
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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
15
fthd_hw.h
15
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) {
|
||||
|
||||
106
fthd_isp.c
106
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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
44
fthd_v4l2.c
44
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;
|
||||
|
||||
Reference in New Issue
Block a user