162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/arch/arm/mach-omap1/lcd_dma.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Extracted from arch/arm/plat-omap/dma.c 662306a36Sopenharmony_ci * Copyright (C) 2003 - 2008 Nokia Corporation 762306a36Sopenharmony_ci * Author: Juha Yrjölä <juha.yrjola@nokia.com> 862306a36Sopenharmony_ci * DMA channel linking for 1610 by Samuel Ortiz <samuel.ortiz@nokia.com> 962306a36Sopenharmony_ci * Graphics DMA and LCD DMA graphics tranformations 1062306a36Sopenharmony_ci * by Imre Deak <imre.deak@nokia.com> 1162306a36Sopenharmony_ci * OMAP2/3 support Copyright (C) 2004-2007 Texas Instruments, Inc. 1262306a36Sopenharmony_ci * Merged to support both OMAP1 and OMAP2 by Tony Lindgren <tony@atomide.com> 1362306a36Sopenharmony_ci * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Copyright (C) 2009 Texas Instruments 1662306a36Sopenharmony_ci * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * Support functions for the OMAP internal DMA channels. 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/spinlock.h> 2362306a36Sopenharmony_ci#include <linux/interrupt.h> 2462306a36Sopenharmony_ci#include <linux/io.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/omap-dma.h> 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <linux/soc/ti/omap1-soc.h> 2962306a36Sopenharmony_ci#include <linux/soc/ti/omap1-io.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include "lcdc.h" 3262306a36Sopenharmony_ci#include "lcd_dma.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ciint omap_lcd_dma_running(void) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci /* 3762306a36Sopenharmony_ci * On OMAP1510, internal LCD controller will start the transfer 3862306a36Sopenharmony_ci * when it gets enabled, so assume DMA running if LCD enabled. 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_ci if (cpu_is_omap15xx()) 4162306a36Sopenharmony_ci if (omap_readw(OMAP_LCDC_CONTROL) & OMAP_LCDC_CTRL_LCD_EN) 4262306a36Sopenharmony_ci return 1; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* Check if LCD DMA is running */ 4562306a36Sopenharmony_ci if (cpu_is_omap16xx()) 4662306a36Sopenharmony_ci if (omap_readw(OMAP1610_DMA_LCD_CCR) & OMAP_DMA_CCR_EN) 4762306a36Sopenharmony_ci return 1; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic struct lcd_dma_info { 5362306a36Sopenharmony_ci spinlock_t lock; 5462306a36Sopenharmony_ci int reserved; 5562306a36Sopenharmony_ci void (*callback)(u16 status, void *data); 5662306a36Sopenharmony_ci void *cb_data; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci int active; 5962306a36Sopenharmony_ci unsigned long addr; 6062306a36Sopenharmony_ci int rotate, data_type, xres, yres; 6162306a36Sopenharmony_ci int vxres; 6262306a36Sopenharmony_ci int mirror; 6362306a36Sopenharmony_ci int xscale, yscale; 6462306a36Sopenharmony_ci int ext_ctrl; 6562306a36Sopenharmony_ci int src_port; 6662306a36Sopenharmony_ci int single_transfer; 6762306a36Sopenharmony_ci} lcd_dma; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_civoid omap_set_lcd_dma_b1(unsigned long addr, u16 fb_xres, u16 fb_yres, 7062306a36Sopenharmony_ci int data_type) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci lcd_dma.addr = addr; 7362306a36Sopenharmony_ci lcd_dma.data_type = data_type; 7462306a36Sopenharmony_ci lcd_dma.xres = fb_xres; 7562306a36Sopenharmony_ci lcd_dma.yres = fb_yres; 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_b1); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_civoid omap_set_lcd_dma_ext_controller(int external) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci lcd_dma.ext_ctrl = external; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_ext_controller); 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_civoid omap_set_lcd_dma_single_transfer(int single) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci lcd_dma.single_transfer = single; 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_single_transfer); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_civoid omap_set_lcd_dma_b1_rotation(int rotate) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci if (cpu_is_omap15xx()) { 9462306a36Sopenharmony_ci printk(KERN_ERR "DMA rotation is not supported in 1510 mode\n"); 9562306a36Sopenharmony_ci BUG(); 9662306a36Sopenharmony_ci return; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci lcd_dma.rotate = rotate; 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_b1_rotation); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_civoid omap_set_lcd_dma_b1_mirror(int mirror) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci if (cpu_is_omap15xx()) { 10562306a36Sopenharmony_ci printk(KERN_ERR "DMA mirror is not supported in 1510 mode\n"); 10662306a36Sopenharmony_ci BUG(); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci lcd_dma.mirror = mirror; 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_b1_mirror); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_civoid omap_set_lcd_dma_b1_vxres(unsigned long vxres) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci if (cpu_is_omap15xx()) { 11562306a36Sopenharmony_ci pr_err("DMA virtual resolution is not supported in 1510 mode\n"); 11662306a36Sopenharmony_ci BUG(); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci lcd_dma.vxres = vxres; 11962306a36Sopenharmony_ci} 12062306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_b1_vxres); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_civoid omap_set_lcd_dma_b1_scale(unsigned int xscale, unsigned int yscale) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci if (cpu_is_omap15xx()) { 12562306a36Sopenharmony_ci printk(KERN_ERR "DMA scale is not supported in 1510 mode\n"); 12662306a36Sopenharmony_ci BUG(); 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci lcd_dma.xscale = xscale; 12962306a36Sopenharmony_ci lcd_dma.yscale = yscale; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ciEXPORT_SYMBOL(omap_set_lcd_dma_b1_scale); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic void set_b1_regs(void) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci unsigned long top, bottom; 13662306a36Sopenharmony_ci int es; 13762306a36Sopenharmony_ci u16 w; 13862306a36Sopenharmony_ci unsigned long en, fn; 13962306a36Sopenharmony_ci long ei, fi; 14062306a36Sopenharmony_ci unsigned long vxres; 14162306a36Sopenharmony_ci unsigned int xscale, yscale; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci switch (lcd_dma.data_type) { 14462306a36Sopenharmony_ci case OMAP_DMA_DATA_TYPE_S8: 14562306a36Sopenharmony_ci es = 1; 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci case OMAP_DMA_DATA_TYPE_S16: 14862306a36Sopenharmony_ci es = 2; 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci case OMAP_DMA_DATA_TYPE_S32: 15162306a36Sopenharmony_ci es = 4; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci default: 15462306a36Sopenharmony_ci BUG(); 15562306a36Sopenharmony_ci return; 15662306a36Sopenharmony_ci } 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci vxres = lcd_dma.vxres ? lcd_dma.vxres : lcd_dma.xres; 15962306a36Sopenharmony_ci xscale = lcd_dma.xscale ? lcd_dma.xscale : 1; 16062306a36Sopenharmony_ci yscale = lcd_dma.yscale ? lcd_dma.yscale : 1; 16162306a36Sopenharmony_ci BUG_ON(vxres < lcd_dma.xres); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#define PIXADDR(x, y) (lcd_dma.addr + \ 16462306a36Sopenharmony_ci ((y) * vxres * yscale + (x) * xscale) * es) 16562306a36Sopenharmony_ci#define PIXSTEP(sx, sy, dx, dy) (PIXADDR(dx, dy) - PIXADDR(sx, sy) - es + 1) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci switch (lcd_dma.rotate) { 16862306a36Sopenharmony_ci case 0: 16962306a36Sopenharmony_ci if (!lcd_dma.mirror) { 17062306a36Sopenharmony_ci top = PIXADDR(0, 0); 17162306a36Sopenharmony_ci bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); 17262306a36Sopenharmony_ci /* 1510 DMA requires the bottom address to be 2 more 17362306a36Sopenharmony_ci * than the actual last memory access location. */ 17462306a36Sopenharmony_ci if (cpu_is_omap15xx() && 17562306a36Sopenharmony_ci lcd_dma.data_type == OMAP_DMA_DATA_TYPE_S32) 17662306a36Sopenharmony_ci bottom += 2; 17762306a36Sopenharmony_ci ei = PIXSTEP(0, 0, 1, 0); 17862306a36Sopenharmony_ci fi = PIXSTEP(lcd_dma.xres - 1, 0, 0, 1); 17962306a36Sopenharmony_ci } else { 18062306a36Sopenharmony_ci top = PIXADDR(lcd_dma.xres - 1, 0); 18162306a36Sopenharmony_ci bottom = PIXADDR(0, lcd_dma.yres - 1); 18262306a36Sopenharmony_ci ei = PIXSTEP(1, 0, 0, 0); 18362306a36Sopenharmony_ci fi = PIXSTEP(0, 0, lcd_dma.xres - 1, 1); 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci en = lcd_dma.xres; 18662306a36Sopenharmony_ci fn = lcd_dma.yres; 18762306a36Sopenharmony_ci break; 18862306a36Sopenharmony_ci case 90: 18962306a36Sopenharmony_ci if (!lcd_dma.mirror) { 19062306a36Sopenharmony_ci top = PIXADDR(0, lcd_dma.yres - 1); 19162306a36Sopenharmony_ci bottom = PIXADDR(lcd_dma.xres - 1, 0); 19262306a36Sopenharmony_ci ei = PIXSTEP(0, 1, 0, 0); 19362306a36Sopenharmony_ci fi = PIXSTEP(0, 0, 1, lcd_dma.yres - 1); 19462306a36Sopenharmony_ci } else { 19562306a36Sopenharmony_ci top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); 19662306a36Sopenharmony_ci bottom = PIXADDR(0, 0); 19762306a36Sopenharmony_ci ei = PIXSTEP(0, 1, 0, 0); 19862306a36Sopenharmony_ci fi = PIXSTEP(1, 0, 0, lcd_dma.yres - 1); 19962306a36Sopenharmony_ci } 20062306a36Sopenharmony_ci en = lcd_dma.yres; 20162306a36Sopenharmony_ci fn = lcd_dma.xres; 20262306a36Sopenharmony_ci break; 20362306a36Sopenharmony_ci case 180: 20462306a36Sopenharmony_ci if (!lcd_dma.mirror) { 20562306a36Sopenharmony_ci top = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); 20662306a36Sopenharmony_ci bottom = PIXADDR(0, 0); 20762306a36Sopenharmony_ci ei = PIXSTEP(1, 0, 0, 0); 20862306a36Sopenharmony_ci fi = PIXSTEP(0, 1, lcd_dma.xres - 1, 0); 20962306a36Sopenharmony_ci } else { 21062306a36Sopenharmony_ci top = PIXADDR(0, lcd_dma.yres - 1); 21162306a36Sopenharmony_ci bottom = PIXADDR(lcd_dma.xres - 1, 0); 21262306a36Sopenharmony_ci ei = PIXSTEP(0, 0, 1, 0); 21362306a36Sopenharmony_ci fi = PIXSTEP(lcd_dma.xres - 1, 1, 0, 0); 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci en = lcd_dma.xres; 21662306a36Sopenharmony_ci fn = lcd_dma.yres; 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci case 270: 21962306a36Sopenharmony_ci if (!lcd_dma.mirror) { 22062306a36Sopenharmony_ci top = PIXADDR(lcd_dma.xres - 1, 0); 22162306a36Sopenharmony_ci bottom = PIXADDR(0, lcd_dma.yres - 1); 22262306a36Sopenharmony_ci ei = PIXSTEP(0, 0, 0, 1); 22362306a36Sopenharmony_ci fi = PIXSTEP(1, lcd_dma.yres - 1, 0, 0); 22462306a36Sopenharmony_ci } else { 22562306a36Sopenharmony_ci top = PIXADDR(0, 0); 22662306a36Sopenharmony_ci bottom = PIXADDR(lcd_dma.xres - 1, lcd_dma.yres - 1); 22762306a36Sopenharmony_ci ei = PIXSTEP(0, 0, 0, 1); 22862306a36Sopenharmony_ci fi = PIXSTEP(0, lcd_dma.yres - 1, 1, 0); 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci en = lcd_dma.yres; 23162306a36Sopenharmony_ci fn = lcd_dma.xres; 23262306a36Sopenharmony_ci break; 23362306a36Sopenharmony_ci default: 23462306a36Sopenharmony_ci BUG(); 23562306a36Sopenharmony_ci return; /* Suppress warning about uninitialized vars */ 23662306a36Sopenharmony_ci } 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (cpu_is_omap15xx()) { 23962306a36Sopenharmony_ci omap_writew(top >> 16, OMAP1510_DMA_LCD_TOP_F1_U); 24062306a36Sopenharmony_ci omap_writew(top, OMAP1510_DMA_LCD_TOP_F1_L); 24162306a36Sopenharmony_ci omap_writew(bottom >> 16, OMAP1510_DMA_LCD_BOT_F1_U); 24262306a36Sopenharmony_ci omap_writew(bottom, OMAP1510_DMA_LCD_BOT_F1_L); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci return; 24562306a36Sopenharmony_ci } 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 1610 regs */ 24862306a36Sopenharmony_ci omap_writew(top >> 16, OMAP1610_DMA_LCD_TOP_B1_U); 24962306a36Sopenharmony_ci omap_writew(top, OMAP1610_DMA_LCD_TOP_B1_L); 25062306a36Sopenharmony_ci omap_writew(bottom >> 16, OMAP1610_DMA_LCD_BOT_B1_U); 25162306a36Sopenharmony_ci omap_writew(bottom, OMAP1610_DMA_LCD_BOT_B1_L); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci omap_writew(en, OMAP1610_DMA_LCD_SRC_EN_B1); 25462306a36Sopenharmony_ci omap_writew(fn, OMAP1610_DMA_LCD_SRC_FN_B1); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CSDP); 25762306a36Sopenharmony_ci w &= ~0x03; 25862306a36Sopenharmony_ci w |= lcd_dma.data_type; 25962306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CSDP); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CTRL); 26262306a36Sopenharmony_ci /* Always set the source port as SDRAM for now*/ 26362306a36Sopenharmony_ci w &= ~(0x03 << 6); 26462306a36Sopenharmony_ci if (lcd_dma.callback != NULL) 26562306a36Sopenharmony_ci w |= 1 << 1; /* Block interrupt enable */ 26662306a36Sopenharmony_ci else 26762306a36Sopenharmony_ci w &= ~(1 << 1); 26862306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CTRL); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci if (!(lcd_dma.rotate || lcd_dma.mirror || 27162306a36Sopenharmony_ci lcd_dma.vxres || lcd_dma.xscale || lcd_dma.yscale)) 27262306a36Sopenharmony_ci return; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CCR); 27562306a36Sopenharmony_ci /* Set the double-indexed addressing mode */ 27662306a36Sopenharmony_ci w |= (0x03 << 12); 27762306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CCR); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci omap_writew(ei, OMAP1610_DMA_LCD_SRC_EI_B1); 28062306a36Sopenharmony_ci omap_writew(fi >> 16, OMAP1610_DMA_LCD_SRC_FI_B1_U); 28162306a36Sopenharmony_ci omap_writew(fi, OMAP1610_DMA_LCD_SRC_FI_B1_L); 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic irqreturn_t lcd_dma_irq_handler(int irq, void *dev_id) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci u16 w; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CTRL); 28962306a36Sopenharmony_ci if (unlikely(!(w & (1 << 3)))) { 29062306a36Sopenharmony_ci printk(KERN_WARNING "Spurious LCD DMA IRQ\n"); 29162306a36Sopenharmony_ci return IRQ_NONE; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci /* Ack the IRQ */ 29462306a36Sopenharmony_ci w |= (1 << 3); 29562306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CTRL); 29662306a36Sopenharmony_ci lcd_dma.active = 0; 29762306a36Sopenharmony_ci if (lcd_dma.callback != NULL) 29862306a36Sopenharmony_ci lcd_dma.callback(w, lcd_dma.cb_data); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci return IRQ_HANDLED; 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ciint omap_request_lcd_dma(void (*callback)(u16 status, void *data), 30462306a36Sopenharmony_ci void *data) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci spin_lock_irq(&lcd_dma.lock); 30762306a36Sopenharmony_ci if (lcd_dma.reserved) { 30862306a36Sopenharmony_ci spin_unlock_irq(&lcd_dma.lock); 30962306a36Sopenharmony_ci printk(KERN_ERR "LCD DMA channel already reserved\n"); 31062306a36Sopenharmony_ci BUG(); 31162306a36Sopenharmony_ci return -EBUSY; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci lcd_dma.reserved = 1; 31462306a36Sopenharmony_ci spin_unlock_irq(&lcd_dma.lock); 31562306a36Sopenharmony_ci lcd_dma.callback = callback; 31662306a36Sopenharmony_ci lcd_dma.cb_data = data; 31762306a36Sopenharmony_ci lcd_dma.active = 0; 31862306a36Sopenharmony_ci lcd_dma.single_transfer = 0; 31962306a36Sopenharmony_ci lcd_dma.rotate = 0; 32062306a36Sopenharmony_ci lcd_dma.vxres = 0; 32162306a36Sopenharmony_ci lcd_dma.mirror = 0; 32262306a36Sopenharmony_ci lcd_dma.xscale = 0; 32362306a36Sopenharmony_ci lcd_dma.yscale = 0; 32462306a36Sopenharmony_ci lcd_dma.ext_ctrl = 0; 32562306a36Sopenharmony_ci lcd_dma.src_port = 0; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return 0; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ciEXPORT_SYMBOL(omap_request_lcd_dma); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_civoid omap_free_lcd_dma(void) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci spin_lock(&lcd_dma.lock); 33462306a36Sopenharmony_ci if (!lcd_dma.reserved) { 33562306a36Sopenharmony_ci spin_unlock(&lcd_dma.lock); 33662306a36Sopenharmony_ci printk(KERN_ERR "LCD DMA is not reserved\n"); 33762306a36Sopenharmony_ci BUG(); 33862306a36Sopenharmony_ci return; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci if (!cpu_is_omap15xx()) 34162306a36Sopenharmony_ci omap_writew(omap_readw(OMAP1610_DMA_LCD_CCR) & ~1, 34262306a36Sopenharmony_ci OMAP1610_DMA_LCD_CCR); 34362306a36Sopenharmony_ci lcd_dma.reserved = 0; 34462306a36Sopenharmony_ci spin_unlock(&lcd_dma.lock); 34562306a36Sopenharmony_ci} 34662306a36Sopenharmony_ciEXPORT_SYMBOL(omap_free_lcd_dma); 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_civoid omap_enable_lcd_dma(void) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci u16 w; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci /* 35362306a36Sopenharmony_ci * Set the Enable bit only if an external controller is 35462306a36Sopenharmony_ci * connected. Otherwise the OMAP internal controller will 35562306a36Sopenharmony_ci * start the transfer when it gets enabled. 35662306a36Sopenharmony_ci */ 35762306a36Sopenharmony_ci if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) 35862306a36Sopenharmony_ci return; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CTRL); 36162306a36Sopenharmony_ci w |= 1 << 8; 36262306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CTRL); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci lcd_dma.active = 1; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CCR); 36762306a36Sopenharmony_ci w |= 1 << 7; 36862306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CCR); 36962306a36Sopenharmony_ci} 37062306a36Sopenharmony_ciEXPORT_SYMBOL(omap_enable_lcd_dma); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_civoid omap_setup_lcd_dma(void) 37362306a36Sopenharmony_ci{ 37462306a36Sopenharmony_ci BUG_ON(lcd_dma.active); 37562306a36Sopenharmony_ci if (!cpu_is_omap15xx()) { 37662306a36Sopenharmony_ci /* Set some reasonable defaults */ 37762306a36Sopenharmony_ci omap_writew(0x5440, OMAP1610_DMA_LCD_CCR); 37862306a36Sopenharmony_ci omap_writew(0x9102, OMAP1610_DMA_LCD_CSDP); 37962306a36Sopenharmony_ci omap_writew(0x0004, OMAP1610_DMA_LCD_LCH_CTRL); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci set_b1_regs(); 38262306a36Sopenharmony_ci if (!cpu_is_omap15xx()) { 38362306a36Sopenharmony_ci u16 w; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CCR); 38662306a36Sopenharmony_ci /* 38762306a36Sopenharmony_ci * If DMA was already active set the end_prog bit to have 38862306a36Sopenharmony_ci * the programmed register set loaded into the active 38962306a36Sopenharmony_ci * register set. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci w |= 1 << 11; /* End_prog */ 39262306a36Sopenharmony_ci if (!lcd_dma.single_transfer) 39362306a36Sopenharmony_ci w |= (3 << 8); /* Auto_init, repeat */ 39462306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CCR); 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ciEXPORT_SYMBOL(omap_setup_lcd_dma); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_civoid omap_stop_lcd_dma(void) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci u16 w; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci lcd_dma.active = 0; 40462306a36Sopenharmony_ci if (cpu_is_omap15xx() || !lcd_dma.ext_ctrl) 40562306a36Sopenharmony_ci return; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CCR); 40862306a36Sopenharmony_ci w &= ~(1 << 7); 40962306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CCR); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CTRL); 41262306a36Sopenharmony_ci w &= ~(1 << 8); 41362306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CTRL); 41462306a36Sopenharmony_ci} 41562306a36Sopenharmony_ciEXPORT_SYMBOL(omap_stop_lcd_dma); 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic int __init omap_init_lcd_dma(void) 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci int r; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (!cpu_class_is_omap1()) 42262306a36Sopenharmony_ci return -ENODEV; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci if (cpu_is_omap16xx()) { 42562306a36Sopenharmony_ci u16 w; 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci /* this would prevent OMAP sleep */ 42862306a36Sopenharmony_ci w = omap_readw(OMAP1610_DMA_LCD_CTRL); 42962306a36Sopenharmony_ci w &= ~(1 << 8); 43062306a36Sopenharmony_ci omap_writew(w, OMAP1610_DMA_LCD_CTRL); 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci spin_lock_init(&lcd_dma.lock); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci r = request_irq(INT_DMA_LCD, lcd_dma_irq_handler, 0, 43662306a36Sopenharmony_ci "LCD DMA", NULL); 43762306a36Sopenharmony_ci if (r != 0) 43862306a36Sopenharmony_ci pr_err("unable to request IRQ for LCD DMA (error %d)\n", r); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci return r; 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ciarch_initcall(omap_init_lcd_dma); 44462306a36Sopenharmony_ci 445