Commit a486d4d4 authored by Tony Lindgren's avatar Tony Lindgren

ARM: OMAP: Additional 24xx DMA fixes and functions

- DMA priority is set for each channel on 24xx, not for each port

- Add support for setting 24xx DMA write mode

- Add support for changing dma callback function and data
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
parent 5ecbcfcb
...@@ -119,32 +119,41 @@ static void clear_lch_regs(int lch) ...@@ -119,32 +119,41 @@ static void clear_lch_regs(int lch)
omap_writew(0, lch_base + i); omap_writew(0, lch_base + i);
} }
void omap_set_dma_priority(int dst_port, int priority) void omap_set_dma_priority(int lch, int dst_port, int priority)
{ {
unsigned long reg; unsigned long reg;
u32 l; u32 l;
switch (dst_port) { if (cpu_class_is_omap1()) {
case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */ switch (dst_port) {
reg = OMAP_TC_OCPT1_PRIOR; case OMAP_DMA_PORT_OCP_T1: /* FFFECC00 */
break; reg = OMAP_TC_OCPT1_PRIOR;
case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */ break;
reg = OMAP_TC_OCPT2_PRIOR; case OMAP_DMA_PORT_OCP_T2: /* FFFECCD0 */
break; reg = OMAP_TC_OCPT2_PRIOR;
case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */ break;
reg = OMAP_TC_EMIFF_PRIOR; case OMAP_DMA_PORT_EMIFF: /* FFFECC08 */
break; reg = OMAP_TC_EMIFF_PRIOR;
case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */ break;
reg = OMAP_TC_EMIFS_PRIOR; case OMAP_DMA_PORT_EMIFS: /* FFFECC04 */
break; reg = OMAP_TC_EMIFS_PRIOR;
default: break;
BUG(); default:
return; BUG();
return;
}
l = omap_readl(reg);
l &= ~(0xf << 8);
l |= (priority & 0xf) << 8;
omap_writel(l, reg);
}
if (cpu_is_omap24xx()) {
if (priority)
OMAP_DMA_CCR_REG(lch) |= (1 << 6);
else
OMAP_DMA_CCR_REG(lch) &= ~(1 << 6);
} }
l = omap_readl(reg);
l &= ~(0xf << 8);
l |= (priority & 0xf) << 8;
omap_writel(l, reg);
} }
void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, void omap_set_dma_transfer_params(int lch, int data_type, int elem_count,
...@@ -234,6 +243,14 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) ...@@ -234,6 +243,14 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color)
OMAP1_DMA_LCH_CTRL_REG(lch) = w; OMAP1_DMA_LCH_CTRL_REG(lch) = w;
} }
void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode)
{
if (cpu_is_omap24xx()) {
OMAP_DMA_CSDP_REG(lch) &= ~(0x3 << 16);
OMAP_DMA_CSDP_REG(lch) |= (mode << 16);
}
}
/* Note that src_port is only for omap1 */ /* Note that src_port is only for omap1 */
void omap_set_dma_src_params(int lch, int src_port, int src_amode, void omap_set_dma_src_params(int lch, int src_port, int src_amode,
unsigned long src_start, unsigned long src_start,
...@@ -697,6 +714,28 @@ void omap_stop_dma(int lch) ...@@ -697,6 +714,28 @@ void omap_stop_dma(int lch)
dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE;
} }
/*
* Allows changing the DMA callback function or data. This may be needed if
* the driver shares a single DMA channel for multiple dma triggers.
*/
int omap_set_dma_callback(int lch,
void (* callback)(int lch, u16 ch_status, void *data),
void *data)
{
unsigned long flags;
spin_lock_irqsave(&dma_chan_lock, flags);
if (dma_chan[lch].dev_id == -1) {
printk(KERN_ERR "DMA callback for not set for free channel\n");
return -EINVAL;
}
dma_chan[lch].callback = callback;
dma_chan[lch].data = data;
spin_unlock_irqrestore(&dma_chan_lock, flags);
return 0;
}
/* /*
* Returns current physical source address for the given DMA channel. * Returns current physical source address for the given DMA channel.
* If the channel is running the caller must disable interrupts prior calling * If the channel is running the caller must disable interrupts prior calling
......
...@@ -1337,7 +1337,8 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel ...@@ -1337,7 +1337,8 @@ static int omapfb_do_probe(struct platform_device *pdev, struct lcd_panel *panel
#ifdef CONFIG_FB_OMAP_DMA_TUNE #ifdef CONFIG_FB_OMAP_DMA_TUNE
/* Set DMA priority for EMIFF access to highest */ /* Set DMA priority for EMIFF access to highest */
omap_set_dma_priority(OMAP_DMA_PORT_EMIFF, 15); if (cpu_class_is_omap1())
omap_set_dma_priority(0, OMAP_DMA_PORT_EMIFF, 15);
#endif #endif
r = ctrl_change_mode(fbdev); r = ctrl_change_mode(fbdev);
......
...@@ -331,6 +331,12 @@ enum omap_dma_color_mode { ...@@ -331,6 +331,12 @@ enum omap_dma_color_mode {
OMAP_DMA_TRANSPARENT_COPY OMAP_DMA_TRANSPARENT_COPY
}; };
enum omap_dma_write_mode {
OMAP_DMA_WRITE_NON_POSTED = 0,
OMAP_DMA_WRITE_POSTED,
OMAP_DMA_WRITE_LAST_NON_POSTED
};
struct omap_dma_channel_params { struct omap_dma_channel_params {
int data_type; /* data type 8,16,32 */ int data_type; /* data type 8,16,32 */
int elem_count; /* number of elements in a frame */ int elem_count; /* number of elements in a frame */
...@@ -356,7 +362,7 @@ struct omap_dma_channel_params { ...@@ -356,7 +362,7 @@ struct omap_dma_channel_params {
}; };
extern void omap_set_dma_priority(int dst_port, int priority); extern void omap_set_dma_priority(int lch, int dst_port, int priority);
extern int omap_request_dma(int dev_id, const char *dev_name, extern int omap_request_dma(int dev_id, const char *dev_name,
void (* callback)(int lch, u16 ch_status, void *data), void (* callback)(int lch, u16 ch_status, void *data),
void *data, int *dma_ch); void *data, int *dma_ch);
...@@ -371,6 +377,7 @@ extern void omap_set_dma_transfer_params(int lch, int data_type, ...@@ -371,6 +377,7 @@ extern void omap_set_dma_transfer_params(int lch, int data_type,
int dma_trigger, int src_or_dst_synch); int dma_trigger, int src_or_dst_synch);
extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, extern void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode,
u32 color); u32 color);
extern void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode);
extern void omap_set_dma_src_params(int lch, int src_port, int src_amode, extern void omap_set_dma_src_params(int lch, int src_port, int src_amode,
unsigned long src_start, unsigned long src_start,
...@@ -394,6 +401,9 @@ extern void omap_set_dma_params(int lch, ...@@ -394,6 +401,9 @@ extern void omap_set_dma_params(int lch,
extern void omap_dma_link_lch (int lch_head, int lch_queue); extern void omap_dma_link_lch (int lch_head, int lch_queue);
extern void omap_dma_unlink_lch (int lch_head, int lch_queue); extern void omap_dma_unlink_lch (int lch_head, int lch_queue);
extern int omap_set_dma_callback(int lch,
void (* callback)(int lch, u16 ch_status, void *data),
void *data);
extern dma_addr_t omap_get_dma_src_pos(int lch); extern dma_addr_t omap_get_dma_src_pos(int lch);
extern dma_addr_t omap_get_dma_dst_pos(int lch); extern dma_addr_t omap_get_dma_dst_pos(int lch);
extern int omap_get_dma_src_addr_counter(int lch); extern int omap_get_dma_src_addr_counter(int lch);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment