summaryrefslogtreecommitdiff
path: root/drivers/dma/pxp/pxp_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dma/pxp/pxp_dma.c')
-rw-r--r--drivers/dma/pxp/pxp_dma.c211
1 files changed, 69 insertions, 142 deletions
diff --git a/drivers/dma/pxp/pxp_dma.c b/drivers/dma/pxp/pxp_dma.c
index b8648049de89..e418f6c9715e 100644
--- a/drivers/dma/pxp/pxp_dma.c
+++ b/drivers/dma/pxp/pxp_dma.c
@@ -31,7 +31,6 @@
#include <linux/vmalloc.h>
#include <linux/dmaengine.h>
#include <linux/pxp_dma.h>
-#include <linux/timer.h>
#include <linux/clk.h>
#include "regs-pxp.h"
@@ -51,23 +50,16 @@ struct pxps {
int irq; /* PXP IRQ to the CPU */
spinlock_t lock;
- struct mutex mutex_clk;
- int clk_stat;
-#define CLK_STAT_OFF 0
-#define CLK_STAT_ON 1
+ struct mutex mutex;
struct device *dev;
struct pxp_dma pxp_dma;
struct pxp_channel channel[NR_PXP_VIRT_CHANNEL];
struct work_struct work;
struct workqueue_struct *workqueue;
- wait_queue_head_t done;
/* describes most recent processing configuration */
struct pxp_config_data pxp_conf_state;
-
- /* to turn clock off when pxp is inactive */
- struct timer_list clk_timer;
};
#define to_pxp_dma(d) container_of(d, struct pxp_dma, dma)
@@ -78,9 +70,6 @@ struct pxps {
#define PXP_DEF_BUFS 2
#define PXP_MIN_PIX 8
-#define PXP_WAITCON ((__raw_readl(pxp->base + HW_PXP_STAT) & \
- BM_PXP_STAT_IRQ) != BM_PXP_STAT_IRQ)
-
static uint32_t pxp_s0_formats[] = {
PXP_PIX_FMT_RGB24,
PXP_PIX_FMT_RGB565,
@@ -94,76 +83,72 @@ static uint32_t pxp_s0_formats[] = {
*/
static void dump_pxp_reg(struct pxps *pxp)
{
- dev_dbg(pxp->dev, "PXP_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_CTRL));
- dev_dbg(pxp->dev, "PXP_STAT 0x%x",
+ dev_err(pxp->dev, "PXP_STAT 0x%x",
__raw_readl(pxp->base + HW_PXP_STAT));
- dev_dbg(pxp->dev, "PXP_OUTBUF 0x%x",
+ dev_err(pxp->dev, "PXP_OUTBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTBUF));
- dev_dbg(pxp->dev, "PXP_OUTBUF2 0x%x",
+ dev_err(pxp->dev, "PXP_OUTBUF2 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTBUF2));
- dev_dbg(pxp->dev, "PXP_OUTSIZE 0x%x",
+ dev_err(pxp->dev, "PXP_OUTSIZE 0x%x",
__raw_readl(pxp->base + HW_PXP_OUTSIZE));
- dev_dbg(pxp->dev, "PXP_S0BUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0BUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0BUF));
- dev_dbg(pxp->dev, "PXP_S0UBUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0UBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0UBUF));
- dev_dbg(pxp->dev, "PXP_S0VBUF 0x%x",
+ dev_err(pxp->dev, "PXP_S0VBUF 0x%x",
__raw_readl(pxp->base + HW_PXP_S0VBUF));
- dev_dbg(pxp->dev, "PXP_S0PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_S0PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_S0PARAM));
- dev_dbg(pxp->dev, "PXP_S0BACKGROUND 0x%x",
+ dev_err(pxp->dev, "PXP_S0BACKGROUND 0x%x",
__raw_readl(pxp->base + HW_PXP_S0BACKGROUND));
- dev_dbg(pxp->dev, "PXP_S0CROP 0x%x",
+ dev_err(pxp->dev, "PXP_S0CROP 0x%x",
__raw_readl(pxp->base + HW_PXP_S0CROP));
- dev_dbg(pxp->dev, "PXP_S0SCALE 0x%x",
+ dev_err(pxp->dev, "PXP_S0SCALE 0x%x",
__raw_readl(pxp->base + HW_PXP_S0SCALE));
- dev_dbg(pxp->dev, "PXP_OLn 0x%x",
+ dev_err(pxp->dev, "PXP_OLn 0x%x",
__raw_readl(pxp->base + HW_PXP_OLn(0)));
- dev_dbg(pxp->dev, "PXP_OLnSIZE 0x%x",
+ dev_err(pxp->dev, "PXP_OLnSIZE 0x%x",
__raw_readl(pxp->base + HW_PXP_OLnSIZE(0)));
- dev_dbg(pxp->dev, "PXP_OLnPARAM 0x%x",
+ dev_err(pxp->dev, "PXP_OLnPARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_OLnPARAM(0)));
- dev_dbg(pxp->dev, "PXP_CSCCOEF0 0x%x",
+ dev_err(pxp->dev, "PXP_CSCCOEF0 0x%x",
__raw_readl(pxp->base + HW_PXP_CSCCOEF0));
- dev_dbg(pxp->dev, "PXP_CSCCOEF1 0x%x",
- __raw_readl(pxp->base + HW_PXP_CSCCOEF1));
- dev_dbg(pxp->dev, "PXP_CSCCOEF2 0x%x",
- __raw_readl(pxp->base + HW_PXP_CSCCOEF2));
- dev_dbg(pxp->dev, "PXP_CSC2CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2CTRL));
- dev_dbg(pxp->dev, "PXP_CSC2COEF0 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF0 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF0));
- dev_dbg(pxp->dev, "PXP_CSC2COEF1 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF1 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF1));
- dev_dbg(pxp->dev, "PXP_CSC2COEF2 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF2 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF2));
- dev_dbg(pxp->dev, "PXP_CSC2COEF3 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF3 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF3));
- dev_dbg(pxp->dev, "PXP_CSC2COEF4 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF4 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF4));
- dev_dbg(pxp->dev, "PXP_CSC2COEF5 0x%x",
+ dev_err(pxp->dev, "PXP_CSC2COEF5 0x%x",
__raw_readl(pxp->base + HW_PXP_CSC2COEF5));
- dev_dbg(pxp->dev, "PXP_LUT_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_LUT_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_LUT_CTRL));
- dev_dbg(pxp->dev, "PXP_LUT 0x%x", __raw_readl(pxp->base + HW_PXP_LUT));
- dev_dbg(pxp->dev, "PXP_HIST_CTRL 0x%x",
+ dev_err(pxp->dev, "PXP_LUT 0x%x", __raw_readl(pxp->base + HW_PXP_LUT));
+ dev_err(pxp->dev, "PXP_HIST_CTRL 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST_CTRL));
- dev_dbg(pxp->dev, "PXP_HIST2_PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_HIST2_PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST2_PARAM));
- dev_dbg(pxp->dev, "PXP_HIST4_PARAM 0x%x",
+ dev_err(pxp->dev, "PXP_HIST4_PARAM 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST4_PARAM));
- dev_dbg(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
+ dev_err(pxp->dev, "PXP_HIST8_PARAM0 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST8_PARAM0));
- dev_dbg(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
+ dev_err(pxp->dev, "PXP_HIST8_PARAM1 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST8_PARAM1));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM0 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM0));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM1 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM1));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM2 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM2));
- dev_dbg(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
+ dev_err(pxp->dev, "PXP_HIST16_PARAM3 0x%x",
__raw_readl(pxp->base + HW_PXP_HIST16_PARAM3));
}
@@ -268,7 +253,6 @@ static int pxp_start(struct pxps *pxp)
static void pxp_set_outbuf(struct pxps *pxp)
{
struct pxp_config_data *pxp_conf = &pxp->pxp_conf_state;
- struct pxp_proc_data *proc_data = &pxp_conf->proc_data;
struct pxp_layer_param *out_params = &pxp_conf->out_param;
__raw_writel(out_params->paddr, pxp->base + HW_PXP_OUTBUF);
@@ -340,7 +324,7 @@ static void pxp_set_olparam(int layer_no, struct pxps *pxp)
else
olparam |=
BF_PXP_OLnPARAM_FORMAT(BV_PXP_OLnPARAM_FORMAT__RGB565);
- if (olparams_data->global_alpha_enable)
+ if (olparams_data->global_alpha)
olparam |=
BF_PXP_OLnPARAM_ALPHA_CNTL
(BV_PXP_OLnPARAM_ALPHA_CNTL__Override);
@@ -493,9 +477,9 @@ static void pxp_set_csc(struct pxps *pxp)
*/
/* CSC1 - YUV->RGB */
- __raw_writel(0x84ab01f0, pxp->base + HW_PXP_CSCCOEF0);
- __raw_writel(0x01230204, pxp->base + HW_PXP_CSCCOEF1);
- __raw_writel(0x0730079c, pxp->base + HW_PXP_CSCCOEF2);
+ __raw_writel(0x04030000, pxp->base + HW_PXP_CSCCOEF0);
+ __raw_writel(0x01230208, pxp->base + HW_PXP_CSCCOEF1);
+ __raw_writel(0x076b079c, pxp->base + HW_PXP_CSCCOEF2);
/* CSC2 - Bypass */
__raw_writel(0x1, pxp->base + HW_PXP_CSC2CTRL);
@@ -596,43 +580,6 @@ static int pxp_config(struct pxps *pxp, struct pxp_channel *pxp_chan)
return 0;
}
-static void pxp_clk_enable(struct pxps *pxp)
-{
- mutex_lock(&pxp->mutex_clk);
-
- if (pxp->clk_stat == CLK_STAT_ON) {
- mutex_unlock(&pxp->mutex_clk);
- return;
- }
-
- clk_enable(pxp->clk);
- pxp->clk_stat = CLK_STAT_ON;
-
- mutex_unlock(&pxp->mutex_clk);
-}
-
-static void pxp_clk_disable(struct pxps *pxp)
-{
- mutex_lock(&pxp->mutex_clk);
-
- if (pxp->clk_stat == CLK_STAT_OFF) {
- mutex_unlock(&pxp->mutex_clk);
- return;
- }
-
- clk_disable(pxp->clk);
- pxp->clk_stat = CLK_STAT_OFF;
-
- mutex_unlock(&pxp->mutex_clk);
-}
-
-static void pxp_clkoff_timer(unsigned long arg)
-{
- struct pxps *pxp = (struct pxps *)arg;
-
- pxp_clk_disable(pxp);
-}
-
static struct pxp_tx_desc *pxpdma_first_active(struct pxp_channel *pxp_chan)
{
return list_entry(pxp_chan->active_list.next, struct pxp_tx_desc, list);
@@ -689,9 +636,13 @@ static void pxpdma_dostart_work(struct work_struct *w)
struct pxps *pxp = container_of(w, struct pxps, work);
struct pxp_channel *pxp_chan = NULL;
unsigned long flags, flags1;
+ int val;
- while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
- ;
+ val = __raw_readl(pxp->base + HW_PXP_CTRL);
+ if (val & BM_PXP_CTRL_ENABLE) {
+ pr_warning("pxp is active, quit.\n");
+ return;
+ }
spin_lock_irqsave(&pxp->lock, flags);
if (list_empty(&head)) {
@@ -813,7 +764,7 @@ static int pxp_init_channel(struct pxp_dma *pxp_dma,
spin_lock_irqsave(&pxp->lock, flags);
/* max desc nr: S0+OL+OUT = 1+8+1 */
- n_desc = 16;
+ n_desc = 10;
spin_unlock_irqrestore(&pxp->lock, flags);
@@ -844,38 +795,25 @@ static int pxp_uninit_channel(struct pxp_dma *pxp_dma,
static irqreturn_t pxp_irq(int irq, void *dev_id)
{
- struct pxps *pxp = dev_id;
- struct pxp_channel *pxp_chan;
+ struct pxp_channel *pxp_chan = dev_id;
+ struct pxp_dma *pxp_dma = to_pxp_dma(pxp_chan->dma_chan.device);
+ struct pxps *pxp = to_pxp(pxp_dma);
struct pxp_tx_desc *desc;
dma_async_tx_callback callback;
void *callback_param;
- unsigned long flags, flags1;
+ unsigned long flags;
u32 hist_status;
- dump_pxp_reg(pxp);
-
hist_status =
__raw_readl(pxp->base + HW_PXP_HIST_CTRL) & BM_PXP_HIST_CTRL_STATUS;
__raw_writel(BM_PXP_STAT_IRQ, pxp->base + HW_PXP_STAT_CLR);
- mod_timer(&pxp->clk_timer, jiffies + msecs_to_jiffies(4000));
-
spin_lock_irqsave(&pxp->lock, flags);
- if (list_empty(&head)) {
- spin_unlock_irqrestore(&pxp->lock, flags);
- return IRQ_NONE;
- }
-
- spin_lock_irqsave(&pxp_chan->lock, flags1);
- pxp_chan = list_entry(head.next, struct pxp_channel, list);
- list_del_init(&pxp_chan->list);
-
if (list_empty(&pxp_chan->active_list)) {
pr_debug("PXP_IRQ pxp_chan->active_list empty. chan_id %d\n",
pxp_chan->dma_chan.chan_id);
- spin_unlock_irqrestore(&pxp_chan->lock, flags1);
spin_unlock_irqrestore(&pxp->lock, flags);
return IRQ_NONE;
}
@@ -901,11 +839,10 @@ static irqreturn_t pxp_irq(int irq, void *dev_id)
list_del(&pxp_chan->list);
- wake_up(&pxp->done);
-
- spin_unlock_irqrestore(&pxp_chan->lock, flags1);
spin_unlock_irqrestore(&pxp->lock, flags);
+ queue_work(pxp->workqueue, &pxp->work);
+
return IRQ_HANDLED;
}
@@ -1021,27 +958,17 @@ static void pxp_issue_pending(struct dma_chan *chan)
spin_lock_irqsave(&pxp->lock, flags0);
spin_lock_irqsave(&pxp_chan->lock, flags);
+ if (!list_empty(&pxp_chan->active_list))
+ queue_work(pxp->workqueue, &pxp->work);
if (!list_empty(&pxp_chan->queue)) {
pxpdma_dequeue(pxp_chan, &pxp_chan->active_list);
pxp_chan->status = PXP_CHANNEL_READY;
list_add_tail(&pxp_chan->list, &head);
- } else {
- spin_unlock_irqrestore(&pxp_chan->lock, flags);
- spin_unlock_irqrestore(&pxp->lock, flags0);
- return;
+ queue_work(pxp->workqueue, &pxp->work);
}
spin_unlock_irqrestore(&pxp_chan->lock, flags);
spin_unlock_irqrestore(&pxp->lock, flags0);
-
- pxp_clk_enable(pxp);
- if (!wait_event_interruptible_timeout(pxp->done, PXP_WAITCON, 2 * HZ) ||
- signal_pending(current)) {
- pxp_clk_disable(pxp);
- return;
- }
-
- queue_work(pxp->workqueue, &pxp->work);
}
static void __pxp_terminate_all(struct dma_chan *chan)
@@ -1089,6 +1016,11 @@ static int pxp_alloc_chan_resources(struct dma_chan *chan)
if (ret < 0)
goto err_chan;
+ ret = request_irq(pxp_chan->eof_irq, pxp_irq, IRQF_SHARED,
+ "pxp-irq", pxp_chan);
+ if (ret < 0)
+ goto err_irq;
+
pxp_chan->status = PXP_CHANNEL_INITIALIZED;
dev_dbg(&chan->dev->device, "Found channel 0x%x, irq %d\n",
@@ -1096,6 +1028,8 @@ static int pxp_alloc_chan_resources(struct dma_chan *chan)
return ret;
+err_irq:
+ pxp_uninit_channel(pxp_dma, pxp_chan);
err_chan:
return ret;
}
@@ -1113,6 +1047,8 @@ static void pxp_free_chan_resources(struct dma_chan *chan)
pxp_uninit_channel(pxp_dma, pxp_chan);
+ free_irq(pxp_chan->eof_irq, pxp_chan);
+
mutex_unlock(&pxp_chan->chan_mutex);
}
@@ -1315,7 +1251,7 @@ static int pxp_probe(struct platform_device *pdev)
pxp->irq = irq;
spin_lock_init(&pxp->lock);
- mutex_init(&pxp->mutex_clk);
+ mutex_init(&pxp->mutex);
if (!request_mem_region(res->start, resource_size(res), "pxp-mem")) {
err = -EBUSY;
@@ -1333,26 +1269,19 @@ static int pxp_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "failed to initialize hardware\n");
goto release;
}
- clk_disable(pxp->clk);
- err = request_irq(pxp->irq, pxp_irq, 0, "pxp-irq", pxp);
- if (err)
- goto release;
/* Initialize DMA engine */
err = pxp_dma_init(pxp);
if (err < 0)
goto err_dma_init;
- init_waitqueue_head(&pxp->done);
INIT_WORK(&pxp->work, pxpdma_dostart_work);
pxp->workqueue = create_singlethread_workqueue("pxp_dma");
- init_timer(&pxp->clk_timer);
- pxp->clk_timer.function = pxp_clkoff_timer;
- pxp->clk_timer.data = (unsigned long)pxp;
exit:
return err;
err_dma_init:
free_irq(pxp->irq, pxp);
+ clk_disable(pxp->clk);
release:
release_mem_region(res->start, resource_size(res));
freepxp:
@@ -1366,8 +1295,8 @@ static int __devexit pxp_remove(struct platform_device *pdev)
struct pxps *pxp = platform_get_drvdata(pdev);
cancel_work_sync(&pxp->work);
+ kfree(pxp);
- del_timer_sync(&pxp->clk_timer);
free_irq(pxp->irq, pxp);
clk_disable(pxp->clk);
clk_put(pxp->clk);
@@ -1383,12 +1312,11 @@ static int pxp_suspend(struct platform_device *pdev, pm_message_t state)
{
struct pxps *pxp = platform_get_drvdata(pdev);
- pxp_clk_enable(pxp);
while (__raw_readl(pxp->base + HW_PXP_CTRL) & BM_PXP_CTRL_ENABLE)
;
__raw_writel(BM_PXP_CTRL_SFTRST, pxp->base + HW_PXP_CTRL);
- pxp_clk_disable(pxp);
+ clk_disable(pxp->clk);
return 0;
}
@@ -1397,10 +1325,9 @@ static int pxp_resume(struct platform_device *pdev)
{
struct pxps *pxp = platform_get_drvdata(pdev);
- pxp_clk_enable(pxp);
+ clk_enable(pxp->clk);
/* Pull PxP out of reset */
__raw_writel(0, pxp->base + HW_PXP_CTRL);
- pxp_clk_disable(pxp);
return 0;
}