diff options
Diffstat (limited to 'drivers/staging/msm/msm_fb.c')
-rw-r--r-- | drivers/staging/msm/msm_fb.c | 2354 |
1 files changed, 0 insertions, 2354 deletions
diff --git a/drivers/staging/msm/msm_fb.c b/drivers/staging/msm/msm_fb.c deleted file mode 100644 index e7ef836eb8d..00000000000 --- a/drivers/staging/msm/msm_fb.c +++ /dev/null @@ -1,2354 +0,0 @@ -/* - * - * Core MSM framebuffer driver. - * - * Copyright (C) 2007 Google Incorporated - * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include "msm_mdp.h" -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> -#include <mach/board.h> -#include <linux/uaccess.h> - -#include <linux/workqueue.h> -#include <linux/string.h> -#include <linux/version.h> -#include <linux/proc_fs.h> -#include <linux/vmalloc.h> -#include <linux/debugfs.h> -#include <linux/console.h> -#include <linux/leds.h> -#include <asm/dma-mapping.h> - - -#define MSM_FB_C -#include "msm_fb.h" -#include "mddihosti.h" -#include "tvenc.h" -#include "mdp.h" -#include "mdp4.h" - -#ifdef CONFIG_FB_MSM_LOGO -#define INIT_IMAGE_FILE "/logo.rle" -extern int load_565rle_image(char *filename); -#endif - - -#define pgprot_noncached(prot) \ - __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) -#define pgprot_writecombine(prot) \ - __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) -#define pgprot_device(prot) \ - __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_DEV_NONSHARED) -#define pgprot_writethroughcache(prot) \ - __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITETHROUGH) -#define pgprot_writebackcache(prot) \ - __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEBACK) -#define pgprot_writebackwacache(prot) \ - __pgprot((pgprot_val(prot) & ~L_PTE_MT_MASK) | L_PTE_MT_WRITEALLOC) - -static unsigned char *fbram; -static unsigned char *fbram_phys; -static int fbram_size; - -static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST]; -static int pdev_list_cnt; - -int vsync_mode = 1; - -#define MAX_FBI_LIST 32 -static struct fb_info *fbi_list[MAX_FBI_LIST]; -static int fbi_list_index; - -static struct msm_fb_data_type *mfd_list[MAX_FBI_LIST]; -static int mfd_list_index; - -static u32 msm_fb_pseudo_palette[16] = { - 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff -}; - -u32 msm_fb_debug_enabled; -/* Setting msm_fb_msg_level to 8 prints out ALL messages */ -u32 msm_fb_msg_level = 7; - -/* Setting mddi_msg_level to 8 prints out ALL messages */ -u32 mddi_msg_level = 5; - -extern int32 mdp_block_power_cnt[MDP_MAX_BLOCK]; -extern unsigned long mdp_timer_duration; - -static int msm_fb_register(struct msm_fb_data_type *mfd); -static int msm_fb_open(struct fb_info *info, int user); -static int msm_fb_release(struct fb_info *info, int user); -static int msm_fb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info); -static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd); -int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd); -static int msm_fb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info); -static int msm_fb_set_par(struct fb_info *info); -static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, - boolean op_enable); -static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd); -static int msm_fb_resume_sub(struct msm_fb_data_type *mfd); -static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg); -static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma); - -#ifdef MSM_FB_ENABLE_DBGFS - -#define MSM_FB_MAX_DBGFS 1024 -#define MAX_BACKLIGHT_BRIGHTNESS 255 - -int msm_fb_debugfs_file_index; -struct dentry *msm_fb_debugfs_root; -struct dentry *msm_fb_debugfs_file[MSM_FB_MAX_DBGFS]; - -struct dentry *msm_fb_get_debugfs_root(void) -{ - if (msm_fb_debugfs_root == NULL) - msm_fb_debugfs_root = debugfs_create_dir("msm_fb", NULL); - - return msm_fb_debugfs_root; -} - -void msm_fb_debugfs_file_create(struct dentry *root, const char *name, - u32 *var) -{ - if (msm_fb_debugfs_file_index >= MSM_FB_MAX_DBGFS) - return; - - msm_fb_debugfs_file[msm_fb_debugfs_file_index++] = - debugfs_create_u32(name, S_IRUGO | S_IWUSR, root, var); -} -#endif - -int msm_fb_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - if (!mfd->cursor_update) - return -ENODEV; - - return mfd->cursor_update(info, cursor); -} - -static int msm_fb_resource_initialized; - -#ifndef CONFIG_FB_BACKLIGHT -static int lcd_backlight_registered; - -static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, - enum led_brightness value) -{ - struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent); - int bl_lvl; - - if (value > MAX_BACKLIGHT_BRIGHTNESS) - value = MAX_BACKLIGHT_BRIGHTNESS; - - /* This maps android backlight level 0 to 255 into - driver backlight level 0 to bl_max with rounding */ - bl_lvl = (2 * value * mfd->panel_info.bl_max + MAX_BACKLIGHT_BRIGHTNESS) - /(2 * MAX_BACKLIGHT_BRIGHTNESS); - - if (!bl_lvl && value) - bl_lvl = 1; - - msm_fb_set_backlight(mfd, bl_lvl, 1); -} - -static struct led_classdev backlight_led = { - .name = "lcd-backlight", - .brightness = MAX_BACKLIGHT_BRIGHTNESS, - .brightness_set = msm_fb_set_bl_brightness, -}; -#endif - -static struct msm_fb_platform_data *msm_fb_pdata; - -int msm_fb_detect_client(const char *name) -{ - int ret = -EPERM; -#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT - u32 id; -#endif - - if (msm_fb_pdata && msm_fb_pdata->detect_client) { - ret = msm_fb_pdata->detect_client(name); - - /* if it's non mddi panel, we need to pre-scan - mddi client to see if we can disable mddi host */ - -#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT - if (!ret && msm_fb_pdata->mddi_prescan) - id = mddi_get_client_id(); -#endif - } - - return ret; -} - -static int msm_fb_probe(struct platform_device *pdev) -{ - struct msm_fb_data_type *mfd; - int rc; - - MSM_FB_DEBUG("msm_fb_probe\n"); - - if ((pdev->id == 0) && (pdev->num_resources > 0)) { - msm_fb_pdata = pdev->dev.platform_data; - fbram_size = - pdev->resource[0].end - pdev->resource[0].start + 1; - fbram_phys = (char *)pdev->resource[0].start; - fbram = ioremap((unsigned long)fbram_phys, fbram_size); - - if (!fbram) { - printk(KERN_ERR "fbram ioremap failed!\n"); - return -ENOMEM; - } - MSM_FB_INFO("msm_fb_probe: phy_Addr = 0x%x virt = 0x%x\n", - (int)fbram_phys, (int)fbram); - - msm_fb_resource_initialized = 1; - return 0; - } - - if (!msm_fb_resource_initialized) - return -EPERM; - - mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); - - if (!mfd) - return -ENODEV; - - if (mfd->key != MFD_KEY) - return -EINVAL; - - if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST) - return -ENOMEM; - - mfd->panel_info.frame_count = 0; - mfd->bl_level = mfd->panel_info.bl_max; - - if (mfd->panel_info.type == LCDC_PANEL) - mfd->allow_set_offset = - msm_fb_pdata->allow_set_offset != NULL ? - msm_fb_pdata->allow_set_offset() : 0; - else - mfd->allow_set_offset = 0; - - rc = msm_fb_register(mfd); - if (rc) - return rc; - -#ifdef CONFIG_FB_BACKLIGHT - msm_fb_config_backlight(mfd); -#else - /* android supports only one lcd-backlight/lcd for now */ - if (!lcd_backlight_registered) { - if (led_classdev_register(&pdev->dev, &backlight_led)) - printk(KERN_ERR "led_classdev_register failed\n"); - else - lcd_backlight_registered = 1; - } -#endif - - pdev_list[pdev_list_cnt++] = pdev; - return 0; -} - -static int msm_fb_remove(struct platform_device *pdev) -{ - struct msm_fb_data_type *mfd; - - MSM_FB_DEBUG("msm_fb_remove\n"); - - mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); - - if (!mfd) - return -ENODEV; - - if (mfd->key != MFD_KEY) - return -EINVAL; - - if (msm_fb_suspend_sub(mfd)) - printk(KERN_ERR "msm_fb_remove: can't stop the device %d\n", mfd->index); - - if (mfd->channel_irq != 0) - free_irq(mfd->channel_irq, (void *)mfd); - - if (mfd->vsync_width_boundary) - vfree(mfd->vsync_width_boundary); - - if (mfd->vsync_resync_timer.function) - del_timer(&mfd->vsync_resync_timer); - - if (mfd->refresh_timer.function) - del_timer(&mfd->refresh_timer); - - if (mfd->dma_hrtimer.function) - hrtimer_cancel(&mfd->dma_hrtimer); - - /* remove /dev/fb* */ - unregister_framebuffer(mfd->fbi); - -#ifdef CONFIG_FB_BACKLIGHT - /* remove /sys/class/backlight */ - backlight_device_unregister(mfd->fbi->bl_dev); -#else - if (lcd_backlight_registered) { - lcd_backlight_registered = 0; - led_classdev_unregister(&backlight_led); - } -#endif - -#ifdef MSM_FB_ENABLE_DBGFS - if (mfd->sub_dir) - debugfs_remove(mfd->sub_dir); -#endif - - return 0; -} - -#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) -static int msm_fb_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct msm_fb_data_type *mfd; - int ret = 0; - - MSM_FB_DEBUG("msm_fb_suspend\n"); - - mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); - - if ((!mfd) || (mfd->key != MFD_KEY)) - return 0; - - console_lock(); - fb_set_suspend(mfd->fbi, 1); - - ret = msm_fb_suspend_sub(mfd); - if (ret != 0) { - printk(KERN_ERR "msm_fb: failed to suspend! %d\n", ret); - fb_set_suspend(mfd->fbi, 0); - } else { - pdev->dev.power.power_state = state; - } - - console_unlock(); - return ret; -} -#else -#define msm_fb_suspend NULL -#endif - -static int msm_fb_suspend_sub(struct msm_fb_data_type *mfd) -{ - int ret = 0; - - if ((!mfd) || (mfd->key != MFD_KEY)) - return 0; - - /* - * suspend this channel - */ - mfd->suspend.sw_refreshing_enable = mfd->sw_refreshing_enable; - mfd->suspend.op_enable = mfd->op_enable; - mfd->suspend.panel_power_on = mfd->panel_power_on; - - if (mfd->op_enable) { - ret = - msm_fb_blank_sub(FB_BLANK_POWERDOWN, mfd->fbi, - mfd->suspend.op_enable); - if (ret) { - MSM_FB_INFO - ("msm_fb_suspend: can't turn off display!\n"); - return ret; - } - mfd->op_enable = FALSE; - } - /* - * try to power down - */ - mdp_pipe_ctrl(MDP_MASTER_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); - - /* - * detach display channel irq if there's any - * or wait until vsync-resync completes - */ - if ((mfd->dest == DISPLAY_LCD)) { - if (mfd->panel_info.lcd.vsync_enable) { - if (mfd->panel_info.lcd.hw_vsync_mode) { - if (mfd->channel_irq != 0) - disable_irq(mfd->channel_irq); - } else { - volatile boolean vh_pending; - do { - vh_pending = mfd->vsync_handler_pending; - } while (vh_pending); - } - } - } - - return 0; -} - -#if defined(CONFIG_PM) && !defined(CONFIG_HAS_EARLYSUSPEND) -static int msm_fb_resume(struct platform_device *pdev) -{ - /* This resume function is called when interrupt is enabled. - */ - int ret = 0; - struct msm_fb_data_type *mfd; - - MSM_FB_DEBUG("msm_fb_resume\n"); - - mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev); - - if ((!mfd) || (mfd->key != MFD_KEY)) - return 0; - - console_lock(); - ret = msm_fb_resume_sub(mfd); - pdev->dev.power.power_state = PMSG_ON; - fb_set_suspend(mfd->fbi, 1); - console_unlock(); - - return ret; -} -#else -#define msm_fb_resume NULL -#endif - -static int msm_fb_resume_sub(struct msm_fb_data_type *mfd) -{ - int ret = 0; - - if ((!mfd) || (mfd->key != MFD_KEY)) - return 0; - - /* attach display channel irq if there's any */ - if (mfd->channel_irq != 0) - enable_irq(mfd->channel_irq); - - /* resume state var recover */ - mfd->sw_refreshing_enable = mfd->suspend.sw_refreshing_enable; - mfd->op_enable = mfd->suspend.op_enable; - - if (mfd->suspend.panel_power_on) { - ret = - msm_fb_blank_sub(FB_BLANK_UNBLANK, mfd->fbi, - mfd->op_enable); - if (ret) - MSM_FB_INFO("msm_fb_resume: can't turn on display!\n"); - } - - return ret; -} - -static struct platform_driver msm_fb_driver = { - .probe = msm_fb_probe, - .remove = msm_fb_remove, -#ifndef CONFIG_HAS_EARLYSUSPEND - .suspend = msm_fb_suspend, - .resume = msm_fb_resume, -#endif - .shutdown = NULL, - .driver = { - /* Driver name must match the device name added in platform.c. */ - .name = "msm_fb", - }, -}; - -#ifdef CONFIG_HAS_EARLYSUSPEND -static void msmfb_early_suspend(struct early_suspend *h) -{ - struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, - early_suspend); - msm_fb_suspend_sub(mfd); -} - -static void msmfb_early_resume(struct early_suspend *h) -{ - struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type, - early_suspend); - msm_fb_resume_sub(mfd); -} -#endif - -void msm_fb_set_backlight(struct msm_fb_data_type *mfd, __u32 bkl_lvl, u32 save) -{ - struct msm_fb_panel_data *pdata; - - pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; - - if ((pdata) && (pdata->set_backlight)) { - down(&mfd->sem); - if ((bkl_lvl != mfd->bl_level) || (!save)) { - u32 old_lvl; - - old_lvl = mfd->bl_level; - mfd->bl_level = bkl_lvl; - pdata->set_backlight(mfd); - - if (!save) - mfd->bl_level = old_lvl; - } - up(&mfd->sem); - } -} - -static int msm_fb_blank_sub(int blank_mode, struct fb_info *info, - boolean op_enable) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - struct msm_fb_panel_data *pdata = NULL; - int ret = 0; - - if (!op_enable) - return -EPERM; - - pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data; - if ((!pdata) || (!pdata->on) || (!pdata->off)) { - printk(KERN_ERR "msm_fb_blank_sub: no panel operation detected!\n"); - return -ENODEV; - } - - switch (blank_mode) { - case FB_BLANK_UNBLANK: - if (!mfd->panel_power_on) { - mdelay(100); - ret = pdata->on(mfd->pdev); - if (ret == 0) { - mfd->panel_power_on = TRUE; - - msm_fb_set_backlight(mfd, - mfd->bl_level, 0); - -/* ToDo: possible conflict with android which doesn't expect sw refresher */ -/* - if (!mfd->hw_refresh) - { - if ((ret = msm_fb_resume_sw_refresher(mfd)) != 0) - { - MSM_FB_INFO("msm_fb_blank_sub: msm_fb_resume_sw_refresher failed = %d!\n",ret); - } - } -*/ - } - } - break; - - case FB_BLANK_VSYNC_SUSPEND: - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_NORMAL: - case FB_BLANK_POWERDOWN: - default: - if (mfd->panel_power_on) { - int curr_pwr_state; - - mfd->op_enable = FALSE; - curr_pwr_state = mfd->panel_power_on; - mfd->panel_power_on = FALSE; - - mdelay(100); - ret = pdata->off(mfd->pdev); - if (ret) - mfd->panel_power_on = curr_pwr_state; - - msm_fb_set_backlight(mfd, 0, 0); - mfd->op_enable = TRUE; - } - break; - } - - return ret; -} - -static void msm_fb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - cfb_fillrect(info, rect); - if (!mfd->hw_refresh && (info->var.yoffset == 0) && - !mfd->sw_currently_refreshing) { - struct fb_var_screeninfo var; - - var = info->var; - var.reserved[0] = 0x54445055; - var.reserved[1] = (rect->dy << 16) | (rect->dx); - var.reserved[2] = ((rect->dy + rect->height) << 16) | - (rect->dx + rect->width); - - msm_fb_pan_display(&var, info); - } -} - -static void msm_fb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - cfb_copyarea(info, area); - if (!mfd->hw_refresh && (info->var.yoffset == 0) && - !mfd->sw_currently_refreshing) { - struct fb_var_screeninfo var; - - var = info->var; - var.reserved[0] = 0x54445055; - var.reserved[1] = (area->dy << 16) | (area->dx); - var.reserved[2] = ((area->dy + area->height) << 16) | - (area->dx + area->width); - - msm_fb_pan_display(&var, info); - } -} - -static void msm_fb_imageblit(struct fb_info *info, const struct fb_image *image) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - cfb_imageblit(info, image); - if (!mfd->hw_refresh && (info->var.yoffset == 0) && - !mfd->sw_currently_refreshing) { - struct fb_var_screeninfo var; - - var = info->var; - var.reserved[0] = 0x54445055; - var.reserved[1] = (image->dy << 16) | (image->dx); - var.reserved[2] = ((image->dy + image->height) << 16) | - (image->dx + image->width); - - msm_fb_pan_display(&var, info); - } -} - -static int msm_fb_blank(int blank_mode, struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - return msm_fb_blank_sub(blank_mode, info, mfd->op_enable); -} - -static int msm_fb_set_lut(struct fb_cmap *cmap, struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - if (!mfd->lut_update) - return -ENODEV; - - mfd->lut_update(info, cmap); - return 0; -} - -/* - * Custom Framebuffer mmap() function for MSM driver. - * Differs from standard mmap() function by allowing for customized - * page-protection. - */ -static int msm_fb_mmap(struct fb_info *info, struct vm_area_struct * vma) -{ - /* Get frame buffer memory range. */ - unsigned long start = info->fix.smem_start; - u32 len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); - unsigned long off = vma->vm_pgoff << PAGE_SHIFT; - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - if (off >= len) { - /* memory mapped io */ - off -= len; - if (info->var.accel_flags) { - mutex_unlock(&info->lock); - return -EINVAL; - } - start = info->fix.mmio_start; - len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); - } - - /* Set VM flags. */ - start &= PAGE_MASK; - if ((vma->vm_end - vma->vm_start + off) > len) - return -EINVAL; - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - /* This is an IO map - tell maydump to skip this VMA */ - vma->vm_flags |= VM_IO | VM_RESERVED; - - /* Set VM page protection */ - if (mfd->mdp_fb_page_protection == MDP_FB_PAGE_PROTECTION_WRITECOMBINE) - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - else if (mfd->mdp_fb_page_protection == - MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE) - vma->vm_page_prot = pgprot_writethroughcache(vma->vm_page_prot); - else if (mfd->mdp_fb_page_protection == - MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE) - vma->vm_page_prot = pgprot_writebackcache(vma->vm_page_prot); - else if (mfd->mdp_fb_page_protection == - MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE) - vma->vm_page_prot = pgprot_writebackwacache(vma->vm_page_prot); - else - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - /* Remap the frame buffer I/O range */ - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; -} - -static struct fb_ops msm_fb_ops = { - .owner = THIS_MODULE, - .fb_open = msm_fb_open, - .fb_release = msm_fb_release, - .fb_read = NULL, - .fb_write = NULL, - .fb_cursor = NULL, - .fb_check_var = msm_fb_check_var, /* vinfo check */ - .fb_set_par = msm_fb_set_par, /* set the video mode according to info->var */ - .fb_setcolreg = NULL, /* set color register */ - .fb_blank = msm_fb_blank, /* blank display */ - .fb_pan_display = msm_fb_pan_display, /* pan display */ - .fb_fillrect = msm_fb_fillrect, /* Draws a rectangle */ - .fb_copyarea = msm_fb_copyarea, /* Copy data from area to another */ - .fb_imageblit = msm_fb_imageblit, /* Draws a image to the display */ - .fb_rotate = NULL, - .fb_sync = NULL, /* wait for blit idle, optional */ - .fb_ioctl = msm_fb_ioctl, /* perform fb specific ioctl (optional) */ - .fb_mmap = msm_fb_mmap, -}; - -static int msm_fb_register(struct msm_fb_data_type *mfd) -{ - int ret = -ENODEV; - int bpp; - struct msm_panel_info *panel_info = &mfd->panel_info; - struct fb_info *fbi = mfd->fbi; - struct fb_fix_screeninfo *fix; - struct fb_var_screeninfo *var; - int *id; - int fbram_offset; - - /* - * fb info initialization - */ - fix = &fbi->fix; - var = &fbi->var; - - fix->type_aux = 0; /* if type == FB_TYPE_INTERLEAVED_PLANES */ - fix->visual = FB_VISUAL_TRUECOLOR; /* True Color */ - fix->ywrapstep = 0; /* No support */ - fix->mmio_start = 0; /* No MMIO Address */ - fix->mmio_len = 0; /* No MMIO Address */ - fix->accel = FB_ACCEL_NONE;/* FB_ACCEL_MSM needes to be added in fb.h */ - - var->xoffset = 0, /* Offset from virtual to visible */ - var->yoffset = 0, /* resolution */ - var->grayscale = 0, /* No graylevels */ - var->nonstd = 0, /* standard pixel format */ - var->activate = FB_ACTIVATE_VBL, /* activate it at vsync */ - var->height = -1, /* height of picture in mm */ - var->width = -1, /* width of picture in mm */ - var->accel_flags = 0, /* acceleration flags */ - var->sync = 0, /* see FB_SYNC_* */ - var->rotate = 0, /* angle we rotate counter clockwise */ - mfd->op_enable = FALSE; - - switch (mfd->fb_imgType) { - case MDP_RGB_565: - fix->type = FB_TYPE_PACKED_PIXELS; - fix->xpanstep = 1; - fix->ypanstep = 1; - var->vmode = FB_VMODE_NONINTERLACED; - var->blue.offset = 0; - var->green.offset = 5; - var->red.offset = 11; - var->blue.length = 5; - var->green.length = 6; - var->red.length = 5; - var->blue.msb_right = 0; - var->green.msb_right = 0; - var->red.msb_right = 0; - var->transp.offset = 0; - var->transp.length = 0; - bpp = 2; - break; - - case MDP_RGB_888: - fix->type = FB_TYPE_PACKED_PIXELS; - fix->xpanstep = 1; - fix->ypanstep = 1; - var->vmode = FB_VMODE_NONINTERLACED; - var->blue.offset = 0; - var->green.offset = 8; - var->red.offset = 16; - var->blue.length = 8; - var->green.length = 8; - var->red.length = 8; - var->blue.msb_right = 0; - var->green.msb_right = 0; - var->red.msb_right = 0; - var->transp.offset = 0; - var->transp.length = 0; - bpp = 3; - break; - - case MDP_ARGB_8888: - fix->type = FB_TYPE_PACKED_PIXELS; - fix->xpanstep = 1; - fix->ypanstep = 1; - var->vmode = FB_VMODE_NONINTERLACED; - var->blue.offset = 0; - var->green.offset = 8; - var->red.offset = 16; - var->blue.length = 8; - var->green.length = 8; - var->red.length = 8; - var->blue.msb_right = 0; - var->green.msb_right = 0; - var->red.msb_right = 0; - var->transp.offset = 24; - var->transp.length = 8; - bpp = 3; - break; - - case MDP_YCRYCB_H2V1: - /* ToDo: need to check TV-Out YUV422i framebuffer format */ - /* we might need to create new type define */ - fix->type = FB_TYPE_INTERLEAVED_PLANES; - fix->xpanstep = 2; - fix->ypanstep = 1; - var->vmode = FB_VMODE_NONINTERLACED; - - /* how about R/G/B offset? */ - var->blue.offset = 0; - var->green.offset = 5; - var->red.offset = 11; - var->blue.length = 5; - var->green.length = 6; - var->red.length = 5; - var->blue.msb_right = 0; - var->green.msb_right = 0; - var->red.msb_right = 0; - var->transp.offset = 0; - var->transp.length = 0; - bpp = 2; - break; - - default: - MSM_FB_ERR("msm_fb_init: fb %d unknown image type!\n", - mfd->index); - return ret; - } - - /* The adreno GPU hardware requires that the pitch be aligned to - 32 pixels for color buffers, so for the cases where the GPU - is writing directly to fb0, the framebuffer pitch - also needs to be 32 pixel aligned */ - - if (mfd->index == 0) - fix->line_length = ALIGN(panel_info->xres * bpp, 32); - else - fix->line_length = panel_info->xres * bpp; - - fix->smem_len = fix->line_length * panel_info->yres * mfd->fb_page; - - mfd->var_xres = panel_info->xres; - mfd->var_yres = panel_info->yres; - - var->pixclock = mfd->panel_info.clk_rate; - mfd->var_pixclock = var->pixclock; - - var->xres = panel_info->xres; - var->yres = panel_info->yres; - var->xres_virtual = panel_info->xres; - var->yres_virtual = panel_info->yres * mfd->fb_page; - var->bits_per_pixel = bpp * 8, /* FrameBuffer color depth */ - /* - * id field for fb app - */ - id = (int *)&mfd->panel; - -#if defined(CONFIG_FB_MSM_MDP22) - snprintf(fix->id, sizeof(fix->id), "msmfb22_%x", (__u32) *id); -#elif defined(CONFIG_FB_MSM_MDP30) - snprintf(fix->id, sizeof(fix->id), "msmfb30_%x", (__u32) *id); -#elif defined(CONFIG_FB_MSM_MDP31) - snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id); -#elif defined(CONFIG_FB_MSM_MDP40) - snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id); -#else - error CONFIG_FB_MSM_MDP undefined ! -#endif - fbi->fbops = &msm_fb_ops; - fbi->flags = FBINFO_FLAG_DEFAULT; - fbi->pseudo_palette = msm_fb_pseudo_palette; - - mfd->ref_cnt = 0; - mfd->sw_currently_refreshing = FALSE; - mfd->sw_refreshing_enable = TRUE; - mfd->panel_power_on = FALSE; - - mfd->pan_waiting = FALSE; - init_completion(&mfd->pan_comp); - init_completion(&mfd->refresher_comp); - sema_init(&mfd->sem, 1); - - fbram_offset = PAGE_ALIGN((int)fbram)-(int)fbram; - fbram += fbram_offset; - fbram_phys += fbram_offset; - fbram_size -= fbram_offset; - - if (fbram_size < fix->smem_len) { - printk(KERN_ERR "error: no more framebuffer memory!\n"); - return -ENOMEM; - } - - fbi->screen_base = fbram; - fbi->fix.smem_start = (unsigned long)fbram_phys; - - memset(fbi->screen_base, 0x0, fix->smem_len); - - mfd->op_enable = TRUE; - mfd->panel_power_on = FALSE; - - /* cursor memory allocation */ - if (mfd->cursor_update) { - mfd->cursor_buf = dma_alloc_coherent(NULL, - MDP_CURSOR_SIZE, - (dma_addr_t *) &mfd->cursor_buf_phys, - GFP_KERNEL); - if (!mfd->cursor_buf) - mfd->cursor_update = 0; - } - - if (mfd->lut_update) { - ret = fb_alloc_cmap(&fbi->cmap, 256, 0); - if (ret) - printk(KERN_ERR "%s: fb_alloc_cmap() failed!\n", - __func__); - } - - if (register_framebuffer(fbi) < 0) { - if (mfd->lut_update) - fb_dealloc_cmap(&fbi->cmap); - - if (mfd->cursor_buf) - dma_free_coherent(NULL, - MDP_CURSOR_SIZE, - mfd->cursor_buf, - (dma_addr_t) mfd->cursor_buf_phys); - - mfd->op_enable = FALSE; - return -EPERM; - } - - fbram += fix->smem_len; - fbram_phys += fix->smem_len; - fbram_size -= fix->smem_len; - - MSM_FB_INFO - ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n", - mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); - -#ifdef CONFIG_FB_MSM_LOGO - if (!load_565rle_image(INIT_IMAGE_FILE)) ; /* Flip buffer */ -#endif - ret = 0; - -#ifdef CONFIG_HAS_EARLYSUSPEND - mfd->early_suspend.suspend = msmfb_early_suspend; - mfd->early_suspend.resume = msmfb_early_resume; - mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2; - register_early_suspend(&mfd->early_suspend); -#endif - -#ifdef MSM_FB_ENABLE_DBGFS - { - struct dentry *root; - struct dentry *sub_dir; - char sub_name[2]; - - root = msm_fb_get_debugfs_root(); - if (root != NULL) { - sub_name[0] = (char)(mfd->index + 0x30); - sub_name[1] = '\0'; - sub_dir = debugfs_create_dir(sub_name, root); - } else { - sub_dir = NULL; - } - - mfd->sub_dir = sub_dir; - - if (sub_dir) { - msm_fb_debugfs_file_create(sub_dir, "op_enable", - (u32 *) &mfd->op_enable); - msm_fb_debugfs_file_create(sub_dir, "panel_power_on", - (u32 *) &mfd-> - panel_power_on); - msm_fb_debugfs_file_create(sub_dir, "ref_cnt", - (u32 *) &mfd->ref_cnt); - msm_fb_debugfs_file_create(sub_dir, "fb_imgType", - (u32 *) &mfd->fb_imgType); - msm_fb_debugfs_file_create(sub_dir, - "sw_currently_refreshing", - (u32 *) &mfd-> - sw_currently_refreshing); - msm_fb_debugfs_file_create(sub_dir, - "sw_refreshing_enable", - (u32 *) &mfd-> - sw_refreshing_enable); - - msm_fb_debugfs_file_create(sub_dir, "xres", - (u32 *) &mfd->panel_info. - xres); - msm_fb_debugfs_file_create(sub_dir, "yres", - (u32 *) &mfd->panel_info. - yres); - msm_fb_debugfs_file_create(sub_dir, "bpp", - (u32 *) &mfd->panel_info. - bpp); - msm_fb_debugfs_file_create(sub_dir, "type", - (u32 *) &mfd->panel_info. - type); - msm_fb_debugfs_file_create(sub_dir, "wait_cycle", - (u32 *) &mfd->panel_info. - wait_cycle); - msm_fb_debugfs_file_create(sub_dir, "pdest", - (u32 *) &mfd->panel_info. - pdest); - msm_fb_debugfs_file_create(sub_dir, "backbuff", - (u32 *) &mfd->panel_info. - fb_num); - msm_fb_debugfs_file_create(sub_dir, "clk_rate", - (u32 *) &mfd->panel_info. - clk_rate); - msm_fb_debugfs_file_create(sub_dir, "frame_count", - (u32 *) &mfd->panel_info. - frame_count); - - - switch (mfd->dest) { - case DISPLAY_LCD: - msm_fb_debugfs_file_create(sub_dir, - "vsync_enable", - (u32 *)&mfd->panel_info.lcd.vsync_enable); - msm_fb_debugfs_file_create(sub_dir, - "refx100", - (u32 *) &mfd->panel_info.lcd. refx100); - msm_fb_debugfs_file_create(sub_dir, - "v_back_porch", - (u32 *) &mfd->panel_info.lcd.v_back_porch); - msm_fb_debugfs_file_create(sub_dir, - "v_front_porch", - (u32 *) &mfd->panel_info.lcd.v_front_porch); - msm_fb_debugfs_file_create(sub_dir, - "v_pulse_width", - (u32 *) &mfd->panel_info.lcd.v_pulse_width); - msm_fb_debugfs_file_create(sub_dir, - "hw_vsync_mode", - (u32 *) &mfd->panel_info.lcd.hw_vsync_mode); - msm_fb_debugfs_file_create(sub_dir, - "vsync_notifier_period", (u32 *) - &mfd->panel_info.lcd.vsync_notifier_period); - break; - - case DISPLAY_LCDC: - msm_fb_debugfs_file_create(sub_dir, - "h_back_porch", - (u32 *) &mfd->panel_info.lcdc.h_back_porch); - msm_fb_debugfs_file_create(sub_dir, - "h_front_porch", - (u32 *) &mfd->panel_info.lcdc.h_front_porch); - msm_fb_debugfs_file_create(sub_dir, - "h_pulse_width", - (u32 *) &mfd->panel_info.lcdc.h_pulse_width); - msm_fb_debugfs_file_create(sub_dir, - "v_back_porch", - (u32 *) &mfd->panel_info.lcdc.v_back_porch); - msm_fb_debugfs_file_create(sub_dir, - "v_front_porch", - (u32 *) &mfd->panel_info.lcdc.v_front_porch); - msm_fb_debugfs_file_create(sub_dir, - "v_pulse_width", - (u32 *) &mfd->panel_info.lcdc.v_pulse_width); - msm_fb_debugfs_file_create(sub_dir, - "border_clr", - (u32 *) &mfd->panel_info.lcdc.border_clr); - msm_fb_debugfs_file_create(sub_dir, - "underflow_clr", - (u32 *) &mfd->panel_info.lcdc.underflow_clr); - msm_fb_debugfs_file_create(sub_dir, - "hsync_skew", - (u32 *) &mfd->panel_info.lcdc.hsync_skew); - break; - - default: - break; - } - } - } -#endif /* MSM_FB_ENABLE_DBGFS */ - - return ret; -} - -static int msm_fb_open(struct fb_info *info, int user) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - if (!mfd->ref_cnt) { - mdp_set_dma_pan_info(info, NULL, TRUE); - - if (msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable)) { - printk(KERN_ERR "msm_fb_open: can't turn on display!\n"); - return -1; - } - } - - mfd->ref_cnt++; - return 0; -} - -static int msm_fb_release(struct fb_info *info, int user) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - int ret = 0; - - if (!mfd->ref_cnt) { - MSM_FB_INFO("msm_fb_release: try to close unopened fb %d!\n", - mfd->index); - return -EINVAL; - } - - mfd->ref_cnt--; - - if (!mfd->ref_cnt) { - if ((ret = - msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, - mfd->op_enable)) != 0) { - printk(KERN_ERR "msm_fb_release: can't turn off display!\n"); - return ret; - } - } - - return ret; -} - -DEFINE_SEMAPHORE(msm_fb_pan_sem); - -static int msm_fb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct mdp_dirty_region dirty; - struct mdp_dirty_region *dirtyPtr = NULL; - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - if ((!mfd->op_enable) || (!mfd->panel_power_on)) - return -EPERM; - - if (var->xoffset > (info->var.xres_virtual - info->var.xres)) - return -EINVAL; - - if (var->yoffset > (info->var.yres_virtual - info->var.yres)) - return -EINVAL; - - if (info->fix.xpanstep) - info->var.xoffset = - (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep; - - if (info->fix.ypanstep) - info->var.yoffset = - (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep; - - /* "UPDT" */ - if (var->reserved[0] == 0x54445055) { - dirty.xoffset = var->reserved[1] & 0xffff; - dirty.yoffset = (var->reserved[1] >> 16) & 0xffff; - - if ((var->reserved[2] & 0xffff) <= dirty.xoffset) - return -EINVAL; - if (((var->reserved[2] >> 16) & 0xffff) <= dirty.yoffset) - return -EINVAL; - - dirty.width = (var->reserved[2] & 0xffff) - dirty.xoffset; - dirty.height = - ((var->reserved[2] >> 16) & 0xffff) - dirty.yoffset; - info->var.yoffset = var->yoffset; - - if (dirty.xoffset < 0) - return -EINVAL; - - if (dirty.yoffset < 0) - return -EINVAL; - - if ((dirty.xoffset + dirty.width) > info->var.xres) - return -EINVAL; - - if ((dirty.yoffset + dirty.height) > info->var.yres) - return -EINVAL; - - if ((dirty.width <= 0) || (dirty.height <= 0)) - return -EINVAL; - - dirtyPtr = &dirty; - } - - /* Flip */ - /* A constant value is used to indicate that we should change the DMA - output buffer instead of just panning */ - - if (var->reserved[0] == 0x466c6970) { - unsigned long length, address; - struct file *p_src_file; - struct mdp_img imgdata; - int bpp; - - if (mfd->allow_set_offset) { - imgdata.memory_id = var->reserved[1]; - imgdata.priv = var->reserved[2]; - - /* If there is no memory ID then we want to reset back - to the original fb visibility */ - if (var->reserved[1]) { - if (var->reserved[4] == MDP_BLIT_SRC_GEM) { - panic("waaaaaaaaaaaaaah"); - if ( /*get_gem_img(&imgdata, - (unsigned long *) &address, - &length)*/ -1 < 0) { - return -1; - } - } else { - /*get_img(&imgdata, info, &address, - &length, &p_src_file);*/ - panic("waaaaaah"); - } - mfd->ibuf.visible_swapped = TRUE; - } else { - /* Flip back to the original address - adjusted for xoffset and yoffset */ - - bpp = info->var.bits_per_pixel / 8; - address = (unsigned long) info->fix.smem_start; - address += info->var.xoffset * bpp + - info->var.yoffset * info->fix.line_length; - - mfd->ibuf.visible_swapped = FALSE; - } - - mdp_set_offset_info(info, address, - (var->activate == FB_ACTIVATE_VBL)); - - mfd->dma_fnc(mfd); - return 0; - } else - return -EINVAL; - } - - down(&msm_fb_pan_sem); - mdp_set_dma_pan_info(info, dirtyPtr, - (var->activate == FB_ACTIVATE_VBL)); - mdp_dma_pan_update(info); - up(&msm_fb_pan_sem); - - ++mfd->panel_info.frame_count; - return 0; -} - -static int msm_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - - if (var->rotate != FB_ROTATE_UR) - return -EINVAL; - if (var->grayscale != info->var.grayscale) - return -EINVAL; - - switch (var->bits_per_pixel) { - case 16: - if ((var->green.offset != 5) || - !((var->blue.offset == 11) - || (var->blue.offset == 0)) || - !((var->red.offset == 11) - || (var->red.offset == 0)) || - (var->blue.length != 5) || - (var->green.length != 6) || - (var->red.length != 5) || - (var->blue.msb_right != 0) || - (var->green.msb_right != 0) || - (var->red.msb_right != 0) || - (var->transp.offset != 0) || - (var->transp.length != 0)) - return -EINVAL; - break; - - case 24: - if ((var->blue.offset != 0) || - (var->green.offset != 8) || - (var->red.offset != 16) || - (var->blue.length != 8) || - (var->green.length != 8) || - (var->red.length != 8) || - (var->blue.msb_right != 0) || - (var->green.msb_right != 0) || - (var->red.msb_right != 0) || - !(((var->transp.offset == 0) && - (var->transp.length == 0)) || - ((var->transp.offset == 24) && - (var->transp.length == 8)))) - return -EINVAL; - break; - - default: - return -EINVAL; - } - - if ((var->xres_virtual <= 0) || (var->yres_virtual <= 0)) - return -EINVAL; - - if (info->fix.smem_len < - (var->xres_virtual*var->yres_virtual*(var->bits_per_pixel/8))) - return -EINVAL; - - if ((var->xres == 0) || (var->yres == 0)) - return -EINVAL; - - if ((var->xres > mfd->panel_info.xres) || - (var->yres > mfd->panel_info.yres)) - return -EINVAL; - - if (var->xoffset > (var->xres_virtual - var->xres)) - return -EINVAL; - - if (var->yoffset > (var->yres_virtual - var->yres)) - return -EINVAL; - - return 0; -} - -static int msm_fb_set_par(struct fb_info *info) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - struct fb_var_screeninfo *var = &info->var; - int old_imgType; - int blank = 0; - - old_imgType = mfd->fb_imgType; - switch (var->bits_per_pixel) { - case 16: - if (var->red.offset == 0) - mfd->fb_imgType = MDP_BGR_565; - else - mfd->fb_imgType = MDP_RGB_565; - break; - - case 24: - if ((var->transp.offset == 0) && (var->transp.length == 0)) - mfd->fb_imgType = MDP_RGB_888; - else if ((var->transp.offset == 24) && - (var->transp.length == 8)) { - mfd->fb_imgType = MDP_ARGB_8888; - info->var.bits_per_pixel = 32; - } - break; - - default: - return -EINVAL; - } - - if ((mfd->var_pixclock != var->pixclock) || - (mfd->hw_refresh && ((mfd->fb_imgType != old_imgType) || - (mfd->var_pixclock != var->pixclock) || - (mfd->var_xres != var->xres) || - (mfd->var_yres != var->yres)))) { - mfd->var_xres = var->xres; - mfd->var_yres = var->yres; - mfd->var_pixclock = var->pixclock; - blank = 1; - } - - if (blank) { - msm_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable); - msm_fb_blank_sub(FB_BLANK_UNBLANK, info, mfd->op_enable); - } - - return 0; -} - -static int msm_fb_stop_sw_refresher(struct msm_fb_data_type *mfd) -{ - if (mfd->hw_refresh) - return -EPERM; - - if (mfd->sw_currently_refreshing) { - down(&mfd->sem); - mfd->sw_currently_refreshing = FALSE; - up(&mfd->sem); - - /* wait until the refresher finishes the last job */ - wait_for_completion_killable(&mfd->refresher_comp); - } - - return 0; -} - -int msm_fb_resume_sw_refresher(struct msm_fb_data_type *mfd) -{ - boolean do_refresh; - - if (mfd->hw_refresh) - return -EPERM; - - down(&mfd->sem); - if ((!mfd->sw_currently_refreshing) && (mfd->sw_refreshing_enable)) { - do_refresh = TRUE; - mfd->sw_currently_refreshing = TRUE; - } else { - do_refresh = FALSE; - } - up(&mfd->sem); - - if (do_refresh) - mdp_refresh_screen((unsigned long)mfd); - - return 0; -} - -void mdp_ppp_put_img(struct file *p_src_file, struct file *p_dst_file) -{ -#ifdef CONFIG_ANDROID_PMEM - if (p_src_file) - put_pmem_file(p_src_file); - if (p_dst_file) - put_pmem_file(p_dst_file); -#endif -} - -int mdp_blit(struct fb_info *info, struct mdp_blit_req *req) -{ - int ret; - struct file *p_src_file = 0, *p_dst_file = 0; - if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) { - printk(KERN_ERR "mpd_ppp: src img of zero size!\n"); - return -EINVAL; - } - if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0)) - return 0; - - ret = mdp_ppp_blit(info, req, &p_src_file, &p_dst_file); - mdp_ppp_put_img(p_src_file, p_dst_file); - return ret; -} - -typedef void (*msm_dma_barrier_function_pointer) (void *, size_t); - -static inline void msm_fb_dma_barrier_for_rect(struct fb_info *info, - struct mdp_img *img, struct mdp_rect *rect, - msm_dma_barrier_function_pointer dma_barrier_fp - ) -{ - /* - * Compute the start and end addresses of the rectangles. - * NOTE: As currently implemented, the data between - * the end of one row and the start of the next is - * included in the address range rather than - * doing multiple calls for each row. - */ - - char * const pmem_start = info->screen_base; -/* int bytes_per_pixel = mdp_get_bytes_per_pixel(img->format); - unsigned long start = (unsigned long)pmem_start + img->offset + - (img->width * rect->y + rect->x) * bytes_per_pixel; - size_t size = ((rect->h - 1) * img->width + rect->w) * bytes_per_pixel; - (*dma_barrier_fp) ((void *) start, size); -*/ - panic("waaaaah"); -} - -static inline void msm_dma_nc_pre(void) -{ - dmb(); -} -static inline void msm_dma_wt_pre(void) -{ - dmb(); -} -static inline void msm_dma_todevice_wb_pre(void *start, size_t size) -{ - #warning this -// dma_cache_pre_ops(start, size, DMA_TO_DEVICE); -} - -static inline void msm_dma_fromdevice_wb_pre(void *start, size_t size) -{ - #warning this -// dma_cache_pre_ops(start, size, DMA_FROM_DEVICE); -} - -static inline void msm_dma_nc_post(void) -{ - dmb(); -} - -static inline void msm_dma_fromdevice_wt_post(void *start, size_t size) -{ - #warning this -// dma_cache_post_ops(start, size, DMA_FROM_DEVICE); -} - -static inline void msm_dma_todevice_wb_post(void *start, size_t size) -{ - #warning this -// dma_cache_post_ops(start, size, DMA_TO_DEVICE); -} - -static inline void msm_dma_fromdevice_wb_post(void *start, size_t size) -{ - #warning this -// dma_cache_post_ops(start, size, DMA_FROM_DEVICE); -} - -/* - * Do the write barriers required to guarantee data is committed to RAM - * (from CPU cache or internal buffers) before a DMA operation starts. - * NOTE: As currently implemented, the data between - * the end of one row and the start of the next is - * included in the address range rather than - * doing multiple calls for each row. -*/ -static void msm_fb_ensure_memory_coherency_before_dma(struct fb_info *info, - struct mdp_blit_req *req_list, - int req_list_count) -{ -#ifdef CONFIG_ARCH_QSD8X50 - int i; - - /* - * Normally, do the requested barriers for each address - * range that corresponds to a rectangle. - * - * But if at least one write barrier is requested for data - * going to or from the device but no address range is - * needed for that barrier, then do the barrier, but do it - * only once, no matter how many requests there are. - */ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - switch (mfd->mdp_fb_page_protection) { - default: - case MDP_FB_PAGE_PROTECTION_NONCACHED: - case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: - /* - * The following barrier is only done at most once, - * since further calls would be redundant. - */ - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags - & MDP_NO_DMA_BARRIER_START)) { - msm_dma_nc_pre(); - break; - } - } - break; - - case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: - /* - * The following barrier is only done at most once, - * since further calls would be redundant. - */ - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags - & MDP_NO_DMA_BARRIER_START)) { - msm_dma_wt_pre(); - break; - } - } - break; - - case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: - case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags & - MDP_NO_DMA_BARRIER_START)) { - - msm_fb_dma_barrier_for_rect(info, - &(req_list[i].src), - &(req_list[i].src_rect), - msm_dma_todevice_wb_pre - ); - - msm_fb_dma_barrier_for_rect(info, - &(req_list[i].dst), - &(req_list[i].dst_rect), - msm_dma_todevice_wb_pre - ); - } - } - break; - } -#else - dmb(); -#endif -} - - -/* - * Do the write barriers required to guarantee data will be re-read from RAM by - * the CPU after a DMA operation ends. - * NOTE: As currently implemented, the data between - * the end of one row and the start of the next is - * included in the address range rather than - * doing multiple calls for each row. -*/ -static void msm_fb_ensure_memory_coherency_after_dma(struct fb_info *info, - struct mdp_blit_req *req_list, - int req_list_count) -{ -#ifdef CONFIG_ARCH_QSD8X50 - int i; - - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - switch (mfd->mdp_fb_page_protection) { - default: - case MDP_FB_PAGE_PROTECTION_NONCACHED: - case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: - /* - * The following barrier is only done at most once, - * since further calls would be redundant. - */ - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags - & MDP_NO_DMA_BARRIER_END)) { - msm_dma_nc_post(); - break; - } - } - break; - - case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags & - MDP_NO_DMA_BARRIER_END)) { - - msm_fb_dma_barrier_for_rect(info, - &(req_list[i].dst), - &(req_list[i].dst_rect), - msm_dma_fromdevice_wt_post - ); - } - } - break; - case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: - case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags & - MDP_NO_DMA_BARRIER_END)) { - - msm_fb_dma_barrier_for_rect(info, - &(req_list[i].dst), - &(req_list[i].dst_rect), - msm_dma_fromdevice_wb_post - ); - } - } - break; - } -#else - dmb(); -#endif -} - -#ifdef CONFIG_MDP_PPP_ASYNC_OP -void msm_fb_ensure_mem_coherency_after_dma(struct fb_info *info, - struct mdp_blit_req *req_list, int req_list_count) -{ - BUG_ON(!info); - - /* - * Ensure that CPU cache and other internal CPU state is - * updated to reflect any change in memory modified by MDP blit - * DMA. - */ - msm_fb_ensure_memory_coherency_after_dma(info, - req_list, req_list_count); -} - -static int msmfb_async_blit(struct fb_info *info, void __user *p) -{ - /* - * CAUTION: The names of the struct types intentionally *DON'T* match - * the names of the variables declared -- they appear to be swapped. - * Read the code carefully and you should see that the variable names - * make sense. - */ - const int MAX_LIST_WINDOW = 16; - struct mdp_blit_req req_list[MAX_LIST_WINDOW]; - struct mdp_blit_req_list req_list_header; - - int count, i, req_list_count; - - /* Get the count size for the total BLIT request. */ - if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) - return -EFAULT; - p += sizeof(req_list_header); - count = req_list_header.count; - while (count > 0) { - /* - * Access the requests through a narrow window to decrease copy - * overhead and make larger requests accessible to the - * coherency management code. - * NOTE: The window size is intended to be larger than the - * typical request size, but not require more than 2 - * kbytes of stack storage. - */ - req_list_count = count; - if (req_list_count > MAX_LIST_WINDOW) - req_list_count = MAX_LIST_WINDOW; - if (copy_from_user(&req_list, p, - sizeof(struct mdp_blit_req)*req_list_count)) - return -EFAULT; - - /* - * Ensure that any data CPU may have previously written to - * internal state (but not yet committed to memory) is - * guaranteed to be committed to memory now. - */ - msm_fb_ensure_memory_coherency_before_dma(info, - req_list, req_list_count); - - /* - * Do the blit DMA, if required -- returning early only if - * there is a failure. - */ - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags & MDP_NO_BLIT)) { - int ret = 0; - struct mdp_ppp_djob *job = NULL; - - if (unlikely(req_list[i].src_rect.h == 0 || - req_list[i].src_rect.w == 0)) { - MSM_FB_ERR("mpd_ppp: " - "src img of zero size!\n"); - return -EINVAL; - } - - if (unlikely(req_list[i].dst_rect.h == 0 || - req_list[i].dst_rect.w == 0)) - continue; - - /* create a new display job */ - job = mdp_ppp_new_djob(); - if (unlikely(!job)) - return -ENOMEM; - - job->info = info; - memcpy(&job->req, &req_list[i], - sizeof(struct mdp_blit_req)); - - /* Do the actual blit. */ - ret = mdp_ppp_blit(info, &job->req, - &job->p_src_file, &job->p_dst_file); - - /* - * Note that early returns don't guarantee - * memory coherency. - */ - if (ret || mdp_ppp_get_ret_code()) { - mdp_ppp_clear_curr_djob(); - return ret; - } - } - } - - /* Go to next window of requests. */ - count -= req_list_count; - p += sizeof(struct mdp_blit_req)*req_list_count; - } - return 0; -} -#else - -/* - * NOTE: The userspace issues blit operations in a sequence, the sequence - * start with a operation marked START and ends in an operation marked - * END. It is guaranteed by the userspace that all the blit operations - * between START and END are only within the regions of areas designated - * by the START and END operations and that the userspace doesn't modify - * those areas. Hence it would be enough to perform barrier/cache operations - * only on the START and END operations. - */ -static int msmfb_blit(struct fb_info *info, void __user *p) -{ - /* - * CAUTION: The names of the struct types intentionally *DON'T* match - * the names of the variables declared -- they appear to be swapped. - * Read the code carefully and you should see that the variable names - * make sense. - */ - const int MAX_LIST_WINDOW = 16; - struct mdp_blit_req req_list[MAX_LIST_WINDOW]; - struct mdp_blit_req_list req_list_header; - - int count, i, req_list_count; - - /* Get the count size for the total BLIT request. */ - if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) - return -EFAULT; - p += sizeof(req_list_header); - count = req_list_header.count; - while (count > 0) { - /* - * Access the requests through a narrow window to decrease copy - * overhead and make larger requests accessible to the - * coherency management code. - * NOTE: The window size is intended to be larger than the - * typical request size, but not require more than 2 - * kbytes of stack storage. - */ - req_list_count = count; - if (req_list_count > MAX_LIST_WINDOW) - req_list_count = MAX_LIST_WINDOW; - if (copy_from_user(&req_list, p, - sizeof(struct mdp_blit_req)*req_list_count)) - return -EFAULT; - - /* - * Ensure that any data CPU may have previously written to - * internal state (but not yet committed to memory) is - * guaranteed to be committed to memory now. - */ - msm_fb_ensure_memory_coherency_before_dma(info, - req_list, req_list_count); - - /* - * Do the blit DMA, if required -- returning early only if - * there is a failure. - */ - for (i = 0; i < req_list_count; i++) { - if (!(req_list[i].flags & MDP_NO_BLIT)) { - /* Do the actual blit. */ - int ret = mdp_blit(info, &(req_list[i])); - - /* - * Note that early returns don't guarantee - * memory coherency. - */ - if (ret) - return ret; - } - } - - /* - * Ensure that CPU cache and other internal CPU state is - * updated to reflect any change in memory modified by MDP blit - * DMA. - */ - msm_fb_ensure_memory_coherency_after_dma(info, - req_list, - req_list_count); - - /* Go to next window of requests. */ - count -= req_list_count; - p += sizeof(struct mdp_blit_req)*req_list_count; - } - return 0; -} -#endif - -#ifdef CONFIG_FB_MSM_OVERLAY -static int msmfb_overlay_get(struct fb_info *info, void __user *p) -{ - struct mdp_overlay req; - int ret; - - if (copy_from_user(&req, p, sizeof(req))) - return -EFAULT; - - ret = mdp4_overlay_get(info, &req); - if (ret) { - printk(KERN_ERR "%s: ioctl failed \n", - __func__); - return ret; - } - if (copy_to_user(p, &req, sizeof(req))) { - printk(KERN_ERR "%s: copy2user failed \n", - __func__); - return -EFAULT; - } - - return 0; -} - -static int msmfb_overlay_set(struct fb_info *info, void __user *p) -{ - struct mdp_overlay req; - int ret; - - if (copy_from_user(&req, p, sizeof(req))) - return -EFAULT; - - ret = mdp4_overlay_set(info, &req); - if (ret) { - printk(KERN_ERR "%s:ioctl failed \n", - __func__); - return ret; - } - - if (copy_to_user(p, &req, sizeof(req))) { - printk(KERN_ERR "%s: copy2user failed \n", - __func__); - return -EFAULT; - } - - return 0; -} - -static int msmfb_overlay_unset(struct fb_info *info, unsigned long *argp) -{ - int ret, ndx; - - ret = copy_from_user(&ndx, argp, sizeof(ndx)); - if (ret) { - printk(KERN_ERR "%s:msmfb_overlay_unset ioctl failed \n", - __func__); - return ret; - } - - return mdp4_overlay_unset(info, ndx); -} - -static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp) -{ - int ret; - struct msmfb_overlay_data req; - struct file *p_src_file = 0; - - ret = copy_from_user(&req, argp, sizeof(req)); - if (ret) { - printk(KERN_ERR "%s:msmfb_overlay_play ioctl failed \n", - __func__); - return ret; - } - - ret = mdp4_overlay_play(info, &req, &p_src_file); - - if (p_src_file) - put_pmem_file(p_src_file); - - return ret; -} - -#endif - -DEFINE_SEMAPHORE(msm_fb_ioctl_ppp_sem); -DEFINE_MUTEX(msm_fb_ioctl_lut_sem); -DEFINE_MUTEX(msm_fb_ioctl_hist_sem); - -/* Set color conversion matrix from user space */ - -#ifndef CONFIG_FB_MSM_MDP40 -static void msmfb_set_color_conv(struct mdp_ccs *p) -{ - int i; - - if (p->direction == MDP_CCS_RGB2YUV) { - /* MDP cmd block enable */ - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - - /* RGB->YUV primary forward matrix */ - for (i = 0; i < MDP_CCS_SIZE; i++) - writel(p->ccs[i], MDP_CSC_PFMVn(i)); - - #ifdef CONFIG_FB_MSM_MDP31 - for (i = 0; i < MDP_BV_SIZE; i++) - writel(p->bv[i], MDP_CSC_POST_BV2n(i)); - #endif - - /* MDP cmd block disable */ - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); - } else { - /* MDP cmd block enable */ - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - - /* YUV->RGB primary reverse matrix */ - for (i = 0; i < MDP_CCS_SIZE; i++) - writel(p->ccs[i], MDP_CSC_PRMVn(i)); - for (i = 0; i < MDP_BV_SIZE; i++) - writel(p->bv[i], MDP_CSC_PRE_BV1n(i)); - - /* MDP cmd block disable */ - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); - } -} -#endif - - -static int msm_fb_ioctl(struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par; - void __user *argp = (void __user *)arg; - struct fb_cursor cursor; - struct fb_cmap cmap; - struct mdp_histogram hist; -#ifndef CONFIG_FB_MSM_MDP40 - struct mdp_ccs ccs_matrix; -#endif - struct mdp_page_protection fb_page_protection; - int ret = 0; - - if (!mfd->op_enable) - return -EPERM; - - switch (cmd) { -#ifdef CONFIG_FB_MSM_OVERLAY - case MSMFB_OVERLAY_GET: - down(&msm_fb_ioctl_ppp_sem); - ret = msmfb_overlay_get(info, argp); - up(&msm_fb_ioctl_ppp_sem); - break; - case MSMFB_OVERLAY_SET: - down(&msm_fb_ioctl_ppp_sem); - ret = msmfb_overlay_set(info, argp); - up(&msm_fb_ioctl_ppp_sem); - break; - case MSMFB_OVERLAY_UNSET: - down(&msm_fb_ioctl_ppp_sem); - ret = msmfb_overlay_unset(info, argp); - up(&msm_fb_ioctl_ppp_sem); - break; - case MSMFB_OVERLAY_PLAY: - down(&msm_fb_ioctl_ppp_sem); - ret = msmfb_overlay_play(info, argp); - up(&msm_fb_ioctl_ppp_sem); - break; -#endif - case MSMFB_BLIT: - down(&msm_fb_ioctl_ppp_sem); -#ifdef CONFIG_MDP_PPP_ASYNC_OP - ret = msmfb_async_blit(info, argp); - mdp_ppp_wait(); /* Wait for all blits to be finished. */ -#else - ret = msmfb_blit(info, argp); -#endif - up(&msm_fb_ioctl_ppp_sem); - - break; - - /* Ioctl for setting ccs matrix from user space */ - case MSMFB_SET_CCS_MATRIX: -#ifndef CONFIG_FB_MSM_MDP40 - ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)); - if (ret) { - printk(KERN_ERR - "%s:MSMFB_SET_CCS_MATRIX ioctl failed \n", - __func__); - return ret; - } - - down(&msm_fb_ioctl_ppp_sem); - if (ccs_matrix.direction == MDP_CCS_RGB2YUV) - mdp_ccs_rgb2yuv = ccs_matrix; - else - mdp_ccs_yuv2rgb = ccs_matrix; - - msmfb_set_color_conv(&ccs_matrix) ; - up(&msm_fb_ioctl_ppp_sem); -#else - ret = -EINVAL; -#endif - - break; - - /* Ioctl for getting ccs matrix to user space */ - case MSMFB_GET_CCS_MATRIX: -#ifndef CONFIG_FB_MSM_MDP40 - ret = copy_from_user(&ccs_matrix, argp, sizeof(ccs_matrix)) ; - if (ret) { - printk(KERN_ERR - "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", - __func__); - return ret; - } - - down(&msm_fb_ioctl_ppp_sem); - if (ccs_matrix.direction == MDP_CCS_RGB2YUV) - ccs_matrix = mdp_ccs_rgb2yuv; - else - ccs_matrix = mdp_ccs_yuv2rgb; - - ret = copy_to_user(argp, &ccs_matrix, sizeof(ccs_matrix)); - - if (ret) { - printk(KERN_ERR - "%s:MSMFB_GET_CCS_MATRIX ioctl failed \n", - __func__); - return ret ; - } - up(&msm_fb_ioctl_ppp_sem); -#else - ret = -EINVAL; -#endif - - break; - -#ifdef CONFIG_MDP_PPP_ASYNC_OP - case MSMFB_ASYNC_BLIT: - down(&msm_fb_ioctl_ppp_sem); - ret = msmfb_async_blit(info, argp); - up(&msm_fb_ioctl_ppp_sem); - break; - - case MSMFB_BLIT_FLUSH: - down(&msm_fb_ioctl_ppp_sem); - mdp_ppp_wait(); - up(&msm_fb_ioctl_ppp_sem); - break; -#endif - - case MSMFB_GRP_DISP: -#ifdef CONFIG_FB_MSM_MDP22 - { - unsigned long grp_id; - - ret = copy_from_user(&grp_id, argp, sizeof(grp_id)); - if (ret) - return ret; - - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - writel(grp_id, MDP_FULL_BYPASS_WORD43); - mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, - FALSE); - break; - } -#else - return -EFAULT; -#endif - case MSMFB_SUSPEND_SW_REFRESHER: - if (!mfd->panel_power_on) - return -EPERM; - - mfd->sw_refreshing_enable = FALSE; - ret = msm_fb_stop_sw_refresher(mfd); - break; - - case MSMFB_RESUME_SW_REFRESHER: - if (!mfd->panel_power_on) - return -EPERM; - - mfd->sw_refreshing_enable = TRUE; - ret = msm_fb_resume_sw_refresher(mfd); - break; - - case MSMFB_CURSOR: - ret = copy_from_user(&cursor, argp, sizeof(cursor)); - if (ret) - return ret; - - ret = msm_fb_cursor(info, &cursor); - break; - - case MSMFB_SET_LUT: - ret = copy_from_user(&cmap, argp, sizeof(cmap)); - if (ret) - return ret; - - mutex_lock(&msm_fb_ioctl_lut_sem); - ret = msm_fb_set_lut(&cmap, info); - mutex_unlock(&msm_fb_ioctl_lut_sem); - break; - - case MSMFB_HISTOGRAM: - if (!mfd->do_histogram) - return -ENODEV; - - ret = copy_from_user(&hist, argp, sizeof(hist)); - if (ret) - return ret; - - mutex_lock(&msm_fb_ioctl_hist_sem); - ret = mfd->do_histogram(info, &hist); - mutex_unlock(&msm_fb_ioctl_hist_sem); - break; - - case MSMFB_GET_PAGE_PROTECTION: - fb_page_protection.page_protection - = mfd->mdp_fb_page_protection; - ret = copy_to_user(argp, &fb_page_protection, - sizeof(fb_page_protection)); - if (ret) - return ret; - break; - - case MSMFB_SET_PAGE_PROTECTION: -#ifdef CONFIG_ARCH_QSD8X50 - ret = copy_from_user(&fb_page_protection, argp, - sizeof(fb_page_protection)); - if (ret) - return ret; - - /* Validate the proposed page protection settings. */ - switch (fb_page_protection.page_protection) { - case MDP_FB_PAGE_PROTECTION_NONCACHED: - case MDP_FB_PAGE_PROTECTION_WRITECOMBINE: - case MDP_FB_PAGE_PROTECTION_WRITETHROUGHCACHE: - /* Write-back cache (read allocate) */ - case MDP_FB_PAGE_PROTECTION_WRITEBACKCACHE: - /* Write-back cache (write allocate) */ - case MDP_FB_PAGE_PROTECTION_WRITEBACKWACACHE: - mfd->mdp_fb_page_protection = - fb_page_protection.page_protection; - break; - default: - ret = -EINVAL; - break; - } -#else - /* - * Don't allow caching until 7k DMA cache operations are - * available. - */ - ret = -EINVAL; -#endif - break; - - default: - MSM_FB_INFO("MDP: unknown ioctl (cmd=%d) received!\n", cmd); - ret = -EINVAL; - break; - } - - return ret; -} - -static int msm_fb_register_driver(void) -{ - return platform_driver_register(&msm_fb_driver); -} - -void msm_fb_add_device(struct platform_device *pdev) -{ - struct msm_fb_panel_data *pdata; - struct platform_device *this_dev = NULL; - struct fb_info *fbi; - struct msm_fb_data_type *mfd = NULL; - u32 type, id, fb_num; - - if (!pdev) - return; - id = pdev->id; - - pdata = pdev->dev.platform_data; - if (!pdata) - return; - type = pdata->panel_info.type; - fb_num = pdata->panel_info.fb_num; - - if (fb_num <= 0) - return; - - if (fbi_list_index >= MAX_FBI_LIST) { - printk(KERN_ERR "msm_fb: no more framebuffer info list!\n"); - return; - } - /* - * alloc panel device data - */ - this_dev = msm_fb_device_alloc(pdata, type, id); - - if (!this_dev) { - printk(KERN_ERR - "%s: msm_fb_device_alloc failed!\n", __func__); - return; - } - - /* - * alloc framebuffer info + par data - */ - fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL); - if (fbi == NULL) { - platform_device_put(this_dev); - printk(KERN_ERR "msm_fb: can't alloca framebuffer info data!\n"); - return; - } - - mfd = (struct msm_fb_data_type *)fbi->par; - mfd->key = MFD_KEY; - mfd->fbi = fbi; - mfd->panel.type = type; - mfd->panel.id = id; - mfd->fb_page = fb_num; - mfd->index = fbi_list_index; - mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE; - - /* link to the latest pdev */ - mfd->pdev = this_dev; - - mfd_list[mfd_list_index++] = mfd; - fbi_list[fbi_list_index++] = fbi; - - /* - * set driver data - */ - platform_set_drvdata(this_dev, mfd); - - if (platform_device_add(this_dev)) { - printk(KERN_ERR "msm_fb: platform_device_add failed!\n"); - platform_device_put(this_dev); - framebuffer_release(fbi); - fbi_list_index--; - return; - } -} -EXPORT_SYMBOL(msm_fb_add_device); - -int __init msm_fb_init(void) -{ - int rc = -ENODEV; - - if (msm_fb_register_driver()) - return rc; - -#ifdef MSM_FB_ENABLE_DBGFS - { - struct dentry *root; - - if ((root = msm_fb_get_debugfs_root()) != NULL) { - msm_fb_debugfs_file_create(root, - "msm_fb_msg_printing_level", - (u32 *) &msm_fb_msg_level); - msm_fb_debugfs_file_create(root, - "mddi_msg_printing_level", - (u32 *) &mddi_msg_level); - msm_fb_debugfs_file_create(root, "msm_fb_debug_enabled", - (u32 *) &msm_fb_debug_enabled); - } - } -#endif - - return 0; -} - -module_init(msm_fb_init); |