📄 sdum.c
字号:
/* Clear the cmdstrings */ cmdstrings = (u32 *)ioremap_nocache(*cmdptrs, BYTES_PER_CMDSTRING * NR_OF_CMDSTRINGS); if (!cmdstrings) goto out; for (i = 0; i < NR_OF_CMDSTRINGS * BYTES_PER_CMDSTRING / sizeof(u32); i++) iowrite32(0, cmdstrings + i); iounmap((u32 *)cmdstrings);out: iounmap((u32 *)cmdptrs);}static void lcd_init(void){ lcd_reset(); DUM_OUTP_FORMAT1 = 0; /* RGB666 */ udelay(1); iowrite32(V_LCD_STANDBY_OFF, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_USE_9BIT_BUS, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_SYNC_RISE_L, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_SYNC_RISE_H, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_SYNC_FALL_L, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_SYNC_FALL_H, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_SYNC_ENABLE, dum_data.slave_virt_base); udelay(1); iowrite32(V_LCD_DISPLAY_ON, dum_data.slave_virt_base); udelay(1);}/* Interface exported to framebuffer drivers */int pnx4008_get_fb_addresses(int fb_type, void **virt_addr, dma_addr_t *phys_addr, int *fb_length){ int i; int ret = -1; for (i = 0; i < ARRAY_SIZE(fb_addr); i++) if (fb_addr[i].fb_type == fb_type) { *virt_addr = (void *)(dum_data.lcd_virt_start + fb_addr[i].addr_offset); *phys_addr = dum_data.lcd_phys_start + fb_addr[i].addr_offset; *fb_length = fb_addr[i].fb_length; ret = 0; break; } return ret;}EXPORT_SYMBOL(pnx4008_get_fb_addresses);int pnx4008_alloc_dum_channel(int dev_id){ int i = 0; while ((i < MAX_DUM_CHANNELS) && (dum_data.fb_owning_channel[i] != -1)) i++; if (i == MAX_DUM_CHANNELS) return -ENORESOURCESLEFT; else { dum_data.fb_owning_channel[i] = dev_id; return i; }}EXPORT_SYMBOL(pnx4008_alloc_dum_channel);int pnx4008_free_dum_channel(int channr, int dev_id){ if (channr < 0 || channr > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[channr] != dev_id) return -EFBNOTOWNER; else { clear_channel(channr); dum_data.fb_owning_channel[channr] = -1; } return 0;}EXPORT_SYMBOL(pnx4008_free_dum_channel);int pnx4008_put_dum_channel_uf(struct dumchannel_uf chan_uf, int dev_id){ int i = chan_uf.channelnr; int ret; if (i < 0 || i > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[i] != dev_id) return -EFBNOTOWNER; else if ((ret = display_open(chan_uf.channelnr, 0, chan_uf.dirty, chan_uf.source, chan_uf.y_offset, chan_uf.x_offset, chan_uf.height, chan_uf.width)) != 0) return ret; else { dum_data.chan_uf_store[i].dirty = chan_uf.dirty; dum_data.chan_uf_store[i].source = chan_uf.source; dum_data.chan_uf_store[i].x_offset = chan_uf.x_offset; dum_data.chan_uf_store[i].y_offset = chan_uf.y_offset; dum_data.chan_uf_store[i].width = chan_uf.width; dum_data.chan_uf_store[i].height = chan_uf.height; } return 0;}EXPORT_SYMBOL(pnx4008_put_dum_channel_uf);int pnx4008_set_dum_channel_sync(int channr, int val, int dev_id){ if (channr < 0 || channr > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[channr] != dev_id) return -EFBNOTOWNER; else { if (val == CONF_SYNC_ON) { DUM_CH_CONF(channr) |= CONF_SYNCENABLE; DUM_CH_CONF(channr) |= DUM_CHANNEL_CFG_SYNC_MASK | DUM_CHANNEL_CFG_SYNC_MASK_SET; } else if (val == CONF_SYNC_OFF) DUM_CH_CONF(channr) &= ~CONF_SYNCENABLE; else return -EINVAL; } return 0;}EXPORT_SYMBOL(pnx4008_set_dum_channel_sync);int pnx4008_set_dum_channel_dirty_detect(int channr, int val, int dev_id){ if (channr < 0 || channr > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[channr] != dev_id) return -EFBNOTOWNER; else { if (val == CONF_DIRTYDETECTION_ON) DUM_CH_CONF(channr) |= CONF_DIRTYENABLE; else if (val == CONF_DIRTYDETECTION_OFF) DUM_CH_CONF(channr) &= ~CONF_DIRTYENABLE; else return -EINVAL; } return 0;}EXPORT_SYMBOL(pnx4008_set_dum_channel_dirty_detect);#if 0 /* Functions not used currently, but likely to be used in future */static int get_channel(struct dumchannel *p_chan){ int i = p_chan->channelnr; if (i < 0 || i > MAX_DUM_CHANNELS) return -EINVAL; else { p_chan->dum_ch_min = DUM_CH_MIN(i); p_chan->dum_ch_max = DUM_CH_MAX(i); p_chan->dum_ch_conf = DUM_CH_CONF(i); p_chan->dum_ch_stat = DUM_CH_STAT(i); p_chan->dum_ch_ctrl = 0; /* WriteOnly control register */ } return 0;}int pnx4008_get_dum_channel_uf(struct dumchannel_uf *p_chan_uf, int dev_id){ int i = p_chan_uf->channelnr; if (i < 0 || i > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[i] != dev_id) return -EFBNOTOWNER; else { p_chan_uf->dirty = dum_data.chan_uf_store[i].dirty; p_chan_uf->source = dum_data.chan_uf_store[i].source; p_chan_uf->x_offset = dum_data.chan_uf_store[i].x_offset; p_chan_uf->y_offset = dum_data.chan_uf_store[i].y_offset; p_chan_uf->width = dum_data.chan_uf_store[i].width; p_chan_uf->height = dum_data.chan_uf_store[i].height; } return 0;}EXPORT_SYMBOL(pnx4008_get_dum_channel_uf);int pnx4008_get_dum_channel_config(int channr, int dev_id){ int ret; struct dumchannel chan; if (channr < 0 || channr > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[channr] != dev_id) return -EFBNOTOWNER; else { chan.channelnr = channr; if ((ret = get_channel(&chan)) != 0) return ret; } return (chan.dum_ch_conf & DUM_CHANNEL_CFG_MASK);}EXPORT_SYMBOL(pnx4008_get_dum_channel_config);int pnx4008_force_update_dum_channel(int channr, int dev_id){ if (channr < 0 || channr > MAX_DUM_CHANNELS) return -EINVAL; else if (dum_data.fb_owning_channel[channr] != dev_id) return -EFBNOTOWNER; else DUM_CH_CTRL(channr) = CTRL_SETDIRTY; return 0;}EXPORT_SYMBOL(pnx4008_force_update_dum_channel);#endifint pnx4008_sdum_mmap(struct fb_info *info, struct vm_area_struct *vma, struct device *dev){ unsigned long off = vma->vm_pgoff << PAGE_SHIFT; if (off < info->fix.smem_len) { vma->vm_pgoff += 1; return dma_mmap_writecombine(dev, vma, (void *)dum_data.lcd_virt_start, dum_data.lcd_phys_start, FB_DMA_SIZE); } return -EINVAL;}EXPORT_SYMBOL(pnx4008_sdum_mmap);int pnx4008_set_dum_exit_notification(int dev_id){ int i; for (i = 0; i < MAX_DUM_CHANNELS; i++) if (dum_data.fb_owning_channel[i] == dev_id) return -ERESOURCESNOTFREED; return 0;}EXPORT_SYMBOL(pnx4008_set_dum_exit_notification);/* Platform device driver for DUM */static int sdum_suspend(struct platform_device *pdev, pm_message_t state){ int retval = 0; struct clk *clk; clk = clk_get(0, "dum_ck"); if (!IS_ERR(clk)) { clk_set_rate(clk, 0); clk_put(clk); } else retval = PTR_ERR(clk); /* disable BAC */ DUM_CTRL = V_BAC_DISABLE_IDLE; /* LCD standby & turn off display */ lcd_reset(); return retval;}static int sdum_resume(struct platform_device *pdev){ int retval = 0; struct clk *clk; clk = clk_get(0, "dum_ck"); if (!IS_ERR(clk)) { clk_set_rate(clk, 1); clk_put(clk); } else retval = PTR_ERR(clk); /* wait for BAC disable */ DUM_CTRL = V_BAC_DISABLE_TRIG; while (DUM_CTRL & BAC_ENABLED) udelay(10); /* re-init LCD */ lcd_init(); /* enable BAC and reset MUX */ DUM_CTRL = V_BAC_ENABLE; udelay(1); DUM_CTRL = V_MUX_RESET; return 0;}static int __devinit sdum_probe(struct platform_device *pdev){ int ret = 0, i = 0; /* map frame buffer */ dum_data.lcd_virt_start = (u32) dma_alloc_writecombine(&pdev->dev, FB_DMA_SIZE, &dum_data.lcd_phys_start, GFP_KERNEL); if (!dum_data.lcd_virt_start) { ret = -ENOMEM; goto out_3; } /* map slave registers */ dum_data.slave_phys_base = PNX4008_DUM_SLAVE_BASE; dum_data.slave_virt_base = (u32 *) ioremap_nocache(dum_data.slave_phys_base, sizeof(u32)); if (dum_data.slave_virt_base == NULL) { ret = -ENOMEM; goto out_2; } /* initialize DUM and LCD display */ ret = dum_init(pdev); if (ret) goto out_1; dum_chan_init(); lcd_init(); DUM_CTRL = V_BAC_ENABLE; udelay(1); DUM_CTRL = V_MUX_RESET; /* set decode address and sync clock divider */ DUM_DECODE = dum_data.lcd_phys_start & DUM_DECODE_MASK; DUM_CLK_DIV = PNX4008_DUM_CLK_DIV; for (i = 0; i < MAX_DUM_CHANNELS; i++) dum_data.fb_owning_channel[i] = -1; /*setup wakeup interrupt */ start_int_set_rising_edge(SE_DISP_SYNC_INT); start_int_ack(SE_DISP_SYNC_INT); start_int_umask(SE_DISP_SYNC_INT); return 0;out_1: iounmap((void *)dum_data.slave_virt_base);out_2: dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, (void *)dum_data.lcd_virt_start, dum_data.lcd_phys_start);out_3: return ret;}static int sdum_remove(struct platform_device *pdev){ struct clk *clk; start_int_mask(SE_DISP_SYNC_INT); clk = clk_get(0, "dum_ck"); if (!IS_ERR(clk)) { clk_set_rate(clk, 0); clk_put(clk); } iounmap((void *)dum_data.slave_virt_base); dma_free_writecombine(&pdev->dev, FB_DMA_SIZE, (void *)dum_data.lcd_virt_start, dum_data.lcd_phys_start); return 0;}static struct platform_driver sdum_driver = { .driver = { .name = "pnx4008-sdum", }, .probe = sdum_probe, .remove = sdum_remove, .suspend = sdum_suspend, .resume = sdum_resume,};int __init sdum_init(void){ return platform_driver_register(&sdum_driver);}static void __exit sdum_exit(void){ platform_driver_unregister(&sdum_driver);};module_init(sdum_init);module_exit(sdum_exit);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -