aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/media
diff options
context:
space:
mode:
authorMichael Tretter <m.tretter@pengutronix.de>2020-07-13 16:42:18 +0200
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-07-19 14:00:31 +0200
commit94dc765602618fdab8bc4eaa96e3053929d8ff8f (patch)
treeb7135a581e0525b1a342773110168f8d3054388f /drivers/staging/media
parentmedia: v4l2-subdev.h: drop duplicated word in comment (diff)
downloadlinux-dev-94dc765602618fdab8bc4eaa96e3053929d8ff8f.tar.xz
linux-dev-94dc765602618fdab8bc4eaa96e3053929d8ff8f.zip
media: allegro: rework mbox handling
Add a send/notify abstraction for the mailbox and separate the message handling in the driver from the code to read and write message to the mailbox. This untangles how mails are written into the MCU's SRAM and signaled to the MCU from the protocol between the driver and the firmware. Signed-off-by: Michael Tretter <m.tretter@pengutronix.de> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/staging/media')
-rw-r--r--drivers/staging/media/allegro-dvt/allegro-core.c145
1 files changed, 87 insertions, 58 deletions
diff --git a/drivers/staging/media/allegro-dvt/allegro-core.c b/drivers/staging/media/allegro-dvt/allegro-core.c
index 3ed66aae741d..11333f900302 100644
--- a/drivers/staging/media/allegro-dvt/allegro-core.c
+++ b/drivers/staging/media/allegro-dvt/allegro-core.c
@@ -105,9 +105,11 @@ struct allegro_buffer {
struct list_head head;
};
+struct allegro_dev;
struct allegro_channel;
struct allegro_mbox {
+ struct allegro_dev *dev;
unsigned int head;
unsigned int tail;
unsigned int data;
@@ -134,8 +136,8 @@ struct allegro_dev {
struct completion init_complete;
/* The mailbox interface */
- struct allegro_mbox mbox_command;
- struct allegro_mbox mbox_status;
+ struct allegro_mbox *mbox_command;
+ struct allegro_mbox *mbox_status;
/*
* The downstream driver limits the users to 64 users, thus I can use
@@ -583,12 +585,20 @@ static void allegro_free_buffer(struct allegro_dev *dev,
* Mailbox interface to send messages to the MCU.
*/
-static int allegro_mbox_init(struct allegro_dev *dev,
- struct allegro_mbox *mbox,
- unsigned int base, size_t size)
+static void allegro_mcu_interrupt(struct allegro_dev *dev);
+static void allegro_handle_message(struct allegro_dev *dev,
+ union mcu_msg_response *msg);
+
+static struct allegro_mbox *allegro_mbox_init(struct allegro_dev *dev,
+ unsigned int base, size_t size)
{
+ struct allegro_mbox *mbox;
+
+ mbox = devm_kmalloc(&dev->plat_dev->dev, sizeof(*mbox), GFP_KERNEL);
if (!mbox)
- return -EINVAL;
+ return ERR_PTR(-ENOMEM);
+
+ mbox->dev = dev;
mbox->head = base;
mbox->tail = base + 0x4;
@@ -599,7 +609,7 @@ static int allegro_mbox_init(struct allegro_dev *dev,
regmap_write(dev->sram, mbox->head, 0);
regmap_write(dev->sram, mbox->tail, 0);
- return 0;
+ return mbox;
}
static int allegro_mbox_write(struct allegro_dev *dev,
@@ -713,9 +723,50 @@ static ssize_t allegro_mbox_read(struct allegro_dev *dev,
return size;
}
-static void allegro_mcu_interrupt(struct allegro_dev *dev)
+/**
+ * allegro_mbox_send() - Send a message via the mailbox
+ * @mbox: the mailbox which is used to send the message
+ * @msg: the message to send
+ */
+static int allegro_mbox_send(struct allegro_mbox *mbox, void *msg)
{
- regmap_write(dev->regmap, AL5_MCU_INTERRUPT, BIT(0));
+ struct allegro_dev *dev = mbox->dev;
+ struct mcu_msg_header *header = msg;
+ ssize_t size = sizeof(*header) + header->length;
+ int err;
+
+ err = allegro_mbox_write(dev, mbox, msg, size);
+ if (err)
+ goto out;
+
+ allegro_mcu_interrupt(dev);
+
+out:
+ return err;
+}
+
+/**
+ * allegro_mbox_notify() - Notify the mailbox about a new message
+ * @mbox: The allegro_mbox to notify
+ */
+static void allegro_mbox_notify(struct allegro_mbox *mbox)
+{
+ struct allegro_dev *dev = mbox->dev;
+ union mcu_msg_response *msg;
+ ssize_t size;
+
+ msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return;
+
+ size = allegro_mbox_read(dev, mbox, msg, sizeof(*msg));
+ if (size < 0)
+ goto out;
+
+ allegro_handle_message(dev, msg);
+
+out:
+ kfree(msg);
}
static void allegro_mcu_send_init(struct allegro_dev *dev,
@@ -736,8 +787,7 @@ static void allegro_mcu_send_init(struct allegro_dev *dev,
msg.l2_cache[1] = -1;
msg.l2_cache[2] = -1;
- allegro_mbox_write(dev, &dev->mbox_command, &msg, sizeof(msg));
- allegro_mcu_interrupt(dev);
+ allegro_mbox_send(dev->mbox_command, &msg);
}
static u32 v4l2_pixelformat_to_mcu_format(u32 pixelformat)
@@ -946,8 +996,7 @@ static int allegro_mcu_send_create_channel(struct allegro_dev *dev,
fill_create_channel_param(channel, &msg.param);
- allegro_mbox_write(dev, &dev->mbox_command, &msg, sizeof(msg));
- allegro_mcu_interrupt(dev);
+ allegro_mbox_send(dev->mbox_command, &msg);
return 0;
}
@@ -964,8 +1013,7 @@ static int allegro_mcu_send_destroy_channel(struct allegro_dev *dev,
msg.channel_id = channel->mcu_channel_id;
- allegro_mbox_write(dev, &dev->mbox_command, &msg, sizeof(msg));
- allegro_mcu_interrupt(dev);
+ allegro_mbox_send(dev->mbox_command, &msg);
return 0;
}
@@ -991,8 +1039,7 @@ static int allegro_mcu_send_put_stream_buffer(struct allegro_dev *dev,
/* copied to mcu_msg_encode_frame_response */
msg.stream_id = stream_id;
- allegro_mbox_write(dev, &dev->mbox_command, &msg, sizeof(msg));
- allegro_mcu_interrupt(dev);
+ allegro_mbox_send(dev->mbox_command, &msg);
return 0;
}
@@ -1021,8 +1068,7 @@ static int allegro_mcu_send_encode_frame(struct allegro_dev *dev,
msg.ep2 = 0x0;
msg.ep2_v = to_mcu_addr(dev, msg.ep2);
- allegro_mbox_write(dev, &dev->mbox_command, &msg, sizeof(msg));
- allegro_mcu_interrupt(dev);
+ allegro_mbox_send(dev->mbox_command, &msg);
return 0;
}
@@ -1084,12 +1130,8 @@ static int allegro_mcu_push_buffer_internal(struct allegro_channel *channel,
buffer++;
}
- err = allegro_mbox_write(dev, &dev->mbox_command, msg, size);
- if (err)
- goto out;
- allegro_mcu_interrupt(dev);
+ err = allegro_mbox_send(dev->mbox_command, msg);
-out:
kfree(msg);
return err;
}
@@ -1681,51 +1723,28 @@ allegro_handle_encode_frame(struct allegro_dev *dev,
return 0;
}
-static int allegro_receive_message(struct allegro_dev *dev)
+static void allegro_handle_message(struct allegro_dev *dev,
+ union mcu_msg_response *msg)
{
- union mcu_msg_response *msg;
- ssize_t size;
- int err = 0;
-
- msg = kmalloc(sizeof(*msg), GFP_KERNEL);
- if (!msg)
- return -ENOMEM;
-
- size = allegro_mbox_read(dev, &dev->mbox_status, msg, sizeof(*msg));
- if (size < sizeof(msg->header)) {
- v4l2_err(&dev->v4l2_dev,
- "invalid mbox message (%zd): must be at least %zu\n",
- size, sizeof(msg->header));
- err = -EINVAL;
- goto out;
- }
-
switch (msg->header.type) {
case MCU_MSG_TYPE_INIT:
- err = allegro_handle_init(dev, &msg->init);
+ allegro_handle_init(dev, &msg->init);
break;
case MCU_MSG_TYPE_CREATE_CHANNEL:
- err = allegro_handle_create_channel(dev, &msg->create_channel);
+ allegro_handle_create_channel(dev, &msg->create_channel);
break;
case MCU_MSG_TYPE_DESTROY_CHANNEL:
- err = allegro_handle_destroy_channel(dev,
- &msg->destroy_channel);
+ allegro_handle_destroy_channel(dev, &msg->destroy_channel);
break;
case MCU_MSG_TYPE_ENCODE_FRAME:
- err = allegro_handle_encode_frame(dev, &msg->encode_frame);
+ allegro_handle_encode_frame(dev, &msg->encode_frame);
break;
default:
v4l2_warn(&dev->v4l2_dev,
"%s: unknown message %s\n",
__func__, msg_type_name(msg->header.type));
- err = -EINVAL;
break;
}
-
-out:
- kfree(msg);
-
- return err;
}
static irqreturn_t allegro_hardirq(int irq, void *data)
@@ -1746,7 +1765,7 @@ static irqreturn_t allegro_irq_thread(int irq, void *data)
{
struct allegro_dev *dev = data;
- allegro_receive_message(dev);
+ allegro_mbox_notify(dev->mbox_status);
return IRQ_HANDLED;
}
@@ -1895,6 +1914,11 @@ static int allegro_mcu_reset(struct allegro_dev *dev)
return allegro_mcu_wait_for_sleep(dev);
}
+static void allegro_mcu_interrupt(struct allegro_dev *dev)
+{
+ regmap_write(dev->regmap, AL5_MCU_INTERRUPT, BIT(0));
+}
+
static void allegro_destroy_channel(struct allegro_channel *channel)
{
struct allegro_dev *dev = channel->dev;
@@ -2887,10 +2911,15 @@ static int allegro_mcu_hw_init(struct allegro_dev *dev,
{
int err;
- allegro_mbox_init(dev, &dev->mbox_command,
- info->mailbox_cmd, info->mailbox_size);
- allegro_mbox_init(dev, &dev->mbox_status,
- info->mailbox_status, info->mailbox_size);
+ dev->mbox_command = allegro_mbox_init(dev, info->mailbox_cmd,
+ info->mailbox_size);
+ dev->mbox_status = allegro_mbox_init(dev, info->mailbox_status,
+ info->mailbox_size);
+ if (!dev->mbox_command || !dev->mbox_status) {
+ v4l2_err(&dev->v4l2_dev,
+ "failed to initialize mailboxes\n");
+ return -EIO;
+ }
allegro_mcu_enable_interrupts(dev);