提交 a9bd32a8 编写于 作者: S Stephen Boyd 提交者: Tomi Valkeinen

msm: msm_fb: Remove dead code

This code is no longer used now that mach-msm has been removed.
Delete it.

Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: David Brown <davidb@codeaurora.org>
Cc: Bryan Huntsman <bryanh@codeaurora.org>
Cc: Daniel Walker <dwalker@fifo99.com>
Signed-off-by: NStephen Boyd <sboyd@codeaurora.org>
Acked-by: NJean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Signed-off-by: NTomi Valkeinen <tomi.valkeinen@ti.com>
上级 a8998202
......@@ -2326,13 +2326,6 @@ config FB_PRE_INIT_FB
Select this option if display contents should be inherited as set by
the bootloader.
config FB_MSM
tristate "MSM Framebuffer support"
depends on FB && ARCH_MSM
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
config FB_MX3
tristate "MX3 Framebuffer support"
depends on FB && MX3_IPU
......
......@@ -126,7 +126,6 @@ obj-y += omap2/
obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o
obj-$(CONFIG_FB_CARMINE) += carminefb.o
obj-$(CONFIG_FB_MB862XX) += mb862xx/
obj-$(CONFIG_FB_MSM) += msm/
obj-$(CONFIG_FB_NUC900) += nuc900fb.o
obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
......
# core framebuffer
#
obj-y := msm_fb.o
# MDP DMA/PPP engine
#
obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
# MDDI interface
#
obj-y += mddi.o
# MDDI client/panel drivers
#
obj-y += mddi_client_dummy.o
obj-y += mddi_client_toshiba.o
obj-y += mddi_client_nt35399.o
此差异已折叠。
/* drivers/video/msm_fb/mddi_client_dummy.c
*
* Support for "dummy" mddi client devices which require no
* special initialization code.
*
* Copyright (C) 2007 Google Incorporated
*
* 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/device.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/platform_data/video-msm_fb.h>
struct panel_info {
struct platform_device pdev;
struct msm_panel_data panel_data;
};
static int mddi_dummy_suspend(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_resume(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_blank(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_unblank(struct msm_panel_data *panel_data)
{
return 0;
}
static int mddi_dummy_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct panel_info *panel =
devm_kzalloc(&pdev->dev, sizeof(struct panel_info), GFP_KERNEL);
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
panel->panel_data.suspend = mddi_dummy_suspend;
panel->panel_data.resume = mddi_dummy_resume;
panel->panel_data.blank = mddi_dummy_blank;
panel->panel_data.unblank = mddi_dummy_unblank;
panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
panel->pdev.name = "msm_panel";
panel->pdev.id = pdev->id;
platform_device_add_resources(&panel->pdev,
client_data->fb_resource, 1);
panel->panel_data.fb_data = client_data->private_client_data;
panel->pdev.dev.platform_data = &panel->panel_data;
return platform_device_register(&panel->pdev);
}
static struct platform_driver mddi_client_dummy = {
.probe = mddi_dummy_probe,
.driver = { .name = "mddi_c_dummy" },
};
static int __init mddi_client_dummy_init(void)
{
platform_driver_register(&mddi_client_dummy);
return 0;
}
module_init(mddi_client_dummy_init);
/* drivers/video/msm_fb/mddi_client_nt35399.c
*
* Support for Novatek NT35399 MDDI client of Sapphire
*
* Copyright (C) 2008 HTC Incorporated
* Author: Solomon Chiu (solomon_chiu@htc.com)
*
* 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/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/platform_data/video-msm_fb.h>
static DECLARE_WAIT_QUEUE_HEAD(nt35399_vsync_wait);
struct panel_info {
struct msm_mddi_client_data *client_data;
struct platform_device pdev;
struct msm_panel_data panel_data;
struct msmfb_callback *fb_callback;
struct work_struct panel_work;
struct workqueue_struct *fb_wq;
int nt35399_got_int;
};
static void
nt35399_request_vsync(struct msm_panel_data *panel_data,
struct msmfb_callback *callback)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
panel->fb_callback = callback;
if (panel->nt35399_got_int) {
panel->nt35399_got_int = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
}
static void nt35399_wait_vsync(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
if (panel->nt35399_got_int) {
panel->nt35399_got_int = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
if (wait_event_timeout(nt35399_vsync_wait, panel->nt35399_got_int,
HZ/2) == 0)
printk(KERN_ERR "timeout waiting for VSYNC\n");
panel->nt35399_got_int = 0;
/* interrupt clears when screen dma starts */
}
static int nt35399_suspend(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
ret = bridge_data->uninit(bridge_data, client_data);
if (ret) {
printk(KERN_INFO "mddi nt35399 client: non zero return from "
"uninit\n");
return ret;
}
client_data->suspend(client_data);
return 0;
}
static int nt35399_resume(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
client_data->resume(client_data);
ret = bridge_data->init(bridge_data, client_data);
if (ret)
return ret;
return 0;
}
static int nt35399_blank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
return bridge_data->blank(bridge_data, client_data);
}
static int nt35399_unblank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
return bridge_data->unblank(bridge_data, client_data);
}
irqreturn_t nt35399_vsync_interrupt(int irq, void *data)
{
struct panel_info *panel = data;
panel->nt35399_got_int = 1;
if (panel->fb_callback) {
panel->fb_callback->func(panel->fb_callback);
panel->fb_callback = NULL;
}
wake_up(&nt35399_vsync_wait);
return IRQ_HANDLED;
}
static int setup_vsync(struct panel_info *panel, int init)
{
int ret;
int gpio = 97;
unsigned int irq;
if (!init) {
ret = 0;
goto uninit;
}
ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
if (ret)
goto err_request_gpio_failed;
ret = irq = gpio_to_irq(gpio);
if (ret < 0)
goto err_get_irq_num_failed;
ret = request_irq(irq, nt35399_vsync_interrupt, IRQF_TRIGGER_RISING,
"vsync", panel);
if (ret)
goto err_request_irq_failed;
printk(KERN_INFO "vsync on gpio %d now %d\n",
gpio, gpio_get_value(gpio));
return 0;
uninit:
free_irq(gpio_to_irq(gpio), panel->client_data);
err_request_irq_failed:
err_get_irq_num_failed:
gpio_free(gpio);
err_request_gpio_failed:
return ret;
}
static int mddi_nt35399_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
struct panel_info *panel = devm_kzalloc(&pdev->dev,
sizeof(struct panel_info),
GFP_KERNEL);
printk(KERN_DEBUG "%s: enter.\n", __func__);
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
ret = setup_vsync(panel, 1);
if (ret) {
dev_err(&pdev->dev, "mddi_nt35399_setup_vsync failed\n");
return ret;
}
panel->client_data = client_data;
panel->panel_data.suspend = nt35399_suspend;
panel->panel_data.resume = nt35399_resume;
panel->panel_data.wait_vsync = nt35399_wait_vsync;
panel->panel_data.request_vsync = nt35399_request_vsync;
panel->panel_data.blank = nt35399_blank;
panel->panel_data.unblank = nt35399_unblank;
panel->panel_data.fb_data = &bridge_data->fb_data;
panel->panel_data.caps = 0;
panel->pdev.name = "msm_panel";
panel->pdev.id = pdev->id;
panel->pdev.resource = client_data->fb_resource;
panel->pdev.num_resources = 1;
panel->pdev.dev.platform_data = &panel->panel_data;
if (bridge_data->init)
bridge_data->init(bridge_data, client_data);
platform_device_register(&panel->pdev);
return 0;
}
static int mddi_nt35399_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
setup_vsync(panel, 0);
return 0;
}
static struct platform_driver mddi_client_0bda_8a47 = {
.probe = mddi_nt35399_probe,
.remove = mddi_nt35399_remove,
.driver = { .name = "mddi_c_0bda_8a47" },
};
static int __init mddi_client_nt35399_init(void)
{
return platform_driver_register(&mddi_client_0bda_8a47);
}
module_init(mddi_client_nt35399_init);
/* drivers/video/msm_fb/mddi_client_toshiba.c
*
* Support for Toshiba TC358720XBG mddi client devices which require no
* special initialization code.
*
* Copyright (C) 2007 Google Incorporated
*
* 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/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/platform_data/video-msm_fb.h>
#define LCD_CONTROL_BLOCK_BASE 0x110000
#define CMN (LCD_CONTROL_BLOCK_BASE|0x10)
#define INTFLG (LCD_CONTROL_BLOCK_BASE|0x18)
#define HCYCLE (LCD_CONTROL_BLOCK_BASE|0x34)
#define HDE_START (LCD_CONTROL_BLOCK_BASE|0x3C)
#define VPOS (LCD_CONTROL_BLOCK_BASE|0xC0)
#define MPLFBUF (LCD_CONTROL_BLOCK_BASE|0x20)
#define WAKEUP (LCD_CONTROL_BLOCK_BASE|0x54)
#define WSYN_DLY (LCD_CONTROL_BLOCK_BASE|0x58)
#define REGENB (LCD_CONTROL_BLOCK_BASE|0x5C)
#define BASE5 0x150000
#define BASE6 0x160000
#define BASE7 0x170000
#define GPIOIEV (BASE5 + 0x10)
#define GPIOIE (BASE5 + 0x14)
#define GPIORIS (BASE5 + 0x18)
#define GPIOMIS (BASE5 + 0x1C)
#define GPIOIC (BASE5 + 0x20)
#define INTMASK (BASE6 + 0x0C)
#define INTMASK_VWAKEOUT (1U << 0)
#define INTMASK_VWAKEOUT_ACTIVE_LOW (1U << 8)
#define GPIOSEL (BASE7 + 0x00)
#define GPIOSEL_VWAKEINT (1U << 0)
static DECLARE_WAIT_QUEUE_HEAD(toshiba_vsync_wait);
struct panel_info {
struct msm_mddi_client_data *client_data;
struct platform_device pdev;
struct msm_panel_data panel_data;
struct msmfb_callback *toshiba_callback;
int toshiba_got_int;
};
static void toshiba_request_vsync(struct msm_panel_data *panel_data,
struct msmfb_callback *callback)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
panel->toshiba_callback = callback;
if (panel->toshiba_got_int) {
panel->toshiba_got_int = 0;
client_data->activate_link(client_data);
}
}
static void toshiba_clear_vsync(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
client_data->activate_link(client_data);
}
static void toshiba_wait_vsync(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
if (panel->toshiba_got_int) {
panel->toshiba_got_int = 0;
client_data->activate_link(client_data); /* clears interrupt */
}
if (wait_event_timeout(toshiba_vsync_wait, panel->toshiba_got_int,
HZ/2) == 0)
printk(KERN_ERR "timeout waiting for VSYNC\n");
panel->toshiba_got_int = 0;
/* interrupt clears when screen dma starts */
}
static int toshiba_suspend(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
ret = bridge_data->uninit(bridge_data, client_data);
if (ret) {
printk(KERN_INFO "mddi toshiba client: non zero return from "
"uninit\n");
return ret;
}
client_data->suspend(client_data);
return 0;
}
static int toshiba_resume(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
int ret;
client_data->resume(client_data);
ret = bridge_data->init(bridge_data, client_data);
if (ret)
return ret;
return 0;
}
static int toshiba_blank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
return bridge_data->blank(bridge_data, client_data);
}
static int toshiba_unblank(struct msm_panel_data *panel_data)
{
struct panel_info *panel = container_of(panel_data, struct panel_info,
panel_data);
struct msm_mddi_client_data *client_data = panel->client_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
return bridge_data->unblank(bridge_data, client_data);
}
irqreturn_t toshiba_vsync_interrupt(int irq, void *data)
{
struct panel_info *panel = data;
panel->toshiba_got_int = 1;
if (panel->toshiba_callback) {
panel->toshiba_callback->func(panel->toshiba_callback);
panel->toshiba_callback = 0;
}
wake_up(&toshiba_vsync_wait);
return IRQ_HANDLED;
}
static int setup_vsync(struct panel_info *panel,
int init)
{
int ret;
int gpio = 97;
unsigned int irq;
if (!init) {
ret = 0;
goto uninit;
}
ret = gpio_request_one(gpio, GPIOF_IN, "vsync");
if (ret)
goto err_request_gpio_failed;
ret = irq = gpio_to_irq(gpio);
if (ret < 0)
goto err_get_irq_num_failed;
ret = request_irq(irq, toshiba_vsync_interrupt, IRQF_TRIGGER_RISING,
"vsync", panel);
if (ret)
goto err_request_irq_failed;
printk(KERN_INFO "vsync on gpio %d now %d\n",
gpio, gpio_get_value(gpio));
return 0;
uninit:
free_irq(gpio_to_irq(gpio), panel);
err_request_irq_failed:
err_get_irq_num_failed:
gpio_free(gpio);
err_request_gpio_failed:
return ret;
}
static int mddi_toshiba_probe(struct platform_device *pdev)
{
int ret;
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct msm_mddi_bridge_platform_data *bridge_data =
client_data->private_client_data;
struct panel_info *panel =
kzalloc(sizeof(struct panel_info), GFP_KERNEL);
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
/* mddi_remote_write(mddi, 0, WAKEUP); */
client_data->remote_write(client_data, GPIOSEL_VWAKEINT, GPIOSEL);
client_data->remote_write(client_data, INTMASK_VWAKEOUT, INTMASK);
ret = setup_vsync(panel, 1);
if (ret) {
dev_err(&pdev->dev, "mddi_bridge_setup_vsync failed\n");
return ret;
}
panel->client_data = client_data;
panel->panel_data.suspend = toshiba_suspend;
panel->panel_data.resume = toshiba_resume;
panel->panel_data.wait_vsync = toshiba_wait_vsync;
panel->panel_data.request_vsync = toshiba_request_vsync;
panel->panel_data.clear_vsync = toshiba_clear_vsync;
panel->panel_data.blank = toshiba_blank;
panel->panel_data.unblank = toshiba_unblank;
panel->panel_data.fb_data = &bridge_data->fb_data;
panel->panel_data.caps = MSMFB_CAP_PARTIAL_UPDATES;
panel->pdev.name = "msm_panel";
panel->pdev.id = pdev->id;
panel->pdev.resource = client_data->fb_resource;
panel->pdev.num_resources = 1;
panel->pdev.dev.platform_data = &panel->panel_data;
bridge_data->init(bridge_data, client_data);
platform_device_register(&panel->pdev);
return 0;
}
static int mddi_toshiba_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
setup_vsync(panel, 0);
kfree(panel);
return 0;
}
static struct platform_driver mddi_client_d263_0000 = {
.probe = mddi_toshiba_probe,
.remove = mddi_toshiba_remove,
.driver = { .name = "mddi_c_d263_0000" },
};
static int __init mddi_client_toshiba_init(void)
{
platform_driver_register(&mddi_client_d263_0000);
return 0;
}
module_init(mddi_client_toshiba_init);
/* drivers/video/msm_fb/mddi_hw.h
*
* MSM MDDI Hardware Registers and Structures
*
* Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
*
* 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.
*/
#ifndef _MDDI_HW_H_
#define _MDDI_HW_H_
#include <linux/types.h>
#define MDDI_CMD 0x0000
#define MDDI_VERSION 0x0004
#define MDDI_PRI_PTR 0x0008
#define MDDI_SEC_PTR 0x000c
#define MDDI_BPS 0x0010
#define MDDI_SPM 0x0014
#define MDDI_INT 0x0018
#define MDDI_INTEN 0x001c
#define MDDI_REV_PTR 0x0020
#define MDDI_REV_SIZE 0x0024
#define MDDI_STAT 0x0028
#define MDDI_REV_RATE_DIV 0x002c
#define MDDI_REV_CRC_ERR 0x0030
#define MDDI_TA1_LEN 0x0034
#define MDDI_TA2_LEN 0x0038
#define MDDI_TEST_BUS 0x003c
#define MDDI_TEST 0x0040
#define MDDI_REV_PKT_CNT 0x0044
#define MDDI_DRIVE_HI 0x0048
#define MDDI_DRIVE_LO 0x004c
#define MDDI_DISP_WAKE 0x0050
#define MDDI_REV_ENCAP_SZ 0x0054
#define MDDI_RTD_VAL 0x0058
#define MDDI_PAD_CTL 0x0068
#define MDDI_DRIVER_START_CNT 0x006c
#define MDDI_NEXT_PRI_PTR 0x0070
#define MDDI_NEXT_SEC_PTR 0x0074
#define MDDI_MISR_CTL 0x0078
#define MDDI_MISR_DATA 0x007c
#define MDDI_SF_CNT 0x0080
#define MDDI_MF_CNT 0x0084
#define MDDI_CURR_REV_PTR 0x0088
#define MDDI_CORE_VER 0x008c
#define MDDI_INT_PRI_PTR_READ 0x0001
#define MDDI_INT_SEC_PTR_READ 0x0002
#define MDDI_INT_REV_DATA_AVAIL 0x0004
#define MDDI_INT_DISP_REQ 0x0008
#define MDDI_INT_PRI_UNDERFLOW 0x0010
#define MDDI_INT_SEC_UNDERFLOW 0x0020
#define MDDI_INT_REV_OVERFLOW 0x0040
#define MDDI_INT_CRC_ERROR 0x0080
#define MDDI_INT_MDDI_IN 0x0100
#define MDDI_INT_PRI_OVERWRITE 0x0200
#define MDDI_INT_SEC_OVERWRITE 0x0400
#define MDDI_INT_REV_OVERWRITE 0x0800
#define MDDI_INT_DMA_FAILURE 0x1000
#define MDDI_INT_LINK_ACTIVE 0x2000
#define MDDI_INT_IN_HIBERNATION 0x4000
#define MDDI_INT_PRI_LINK_LIST_DONE 0x8000
#define MDDI_INT_SEC_LINK_LIST_DONE 0x10000
#define MDDI_INT_NO_CMD_PKTS_PEND 0x20000
#define MDDI_INT_RTD_FAILURE 0x40000
#define MDDI_INT_REV_PKT_RECEIVED 0x80000
#define MDDI_INT_REV_PKTS_AVAIL 0x100000
#define MDDI_INT_NEED_CLEAR ( \
MDDI_INT_REV_DATA_AVAIL | \
MDDI_INT_PRI_UNDERFLOW | \
MDDI_INT_SEC_UNDERFLOW | \
MDDI_INT_REV_OVERFLOW | \
MDDI_INT_CRC_ERROR | \
MDDI_INT_REV_PKT_RECEIVED)
#define MDDI_STAT_LINK_ACTIVE 0x0001
#define MDDI_STAT_NEW_REV_PTR 0x0002
#define MDDI_STAT_NEW_PRI_PTR 0x0004
#define MDDI_STAT_NEW_SEC_PTR 0x0008
#define MDDI_STAT_IN_HIBERNATION 0x0010
#define MDDI_STAT_PRI_LINK_LIST_DONE 0x0020
#define MDDI_STAT_SEC_LINK_LIST_DONE 0x0040
#define MDDI_STAT_PENDING_TIMING_PKT 0x0080
#define MDDI_STAT_PENDING_REV_ENCAP 0x0100
#define MDDI_STAT_PENDING_POWERDOWN 0x0200
#define MDDI_STAT_RTD_MEAS_FAIL 0x0800
#define MDDI_STAT_CLIENT_WAKEUP_REQ 0x1000
#define MDDI_CMD_POWERDOWN 0x0100
#define MDDI_CMD_POWERUP 0x0200
#define MDDI_CMD_HIBERNATE 0x0300
#define MDDI_CMD_RESET 0x0400
#define MDDI_CMD_DISP_IGNORE 0x0501
#define MDDI_CMD_DISP_LISTEN 0x0500
#define MDDI_CMD_SEND_REV_ENCAP 0x0600
#define MDDI_CMD_GET_CLIENT_CAP 0x0601
#define MDDI_CMD_GET_CLIENT_STATUS 0x0602
#define MDDI_CMD_SEND_RTD 0x0700
#define MDDI_CMD_LINK_ACTIVE 0x0900
#define MDDI_CMD_PERIODIC_REV_ENCAP 0x0A00
#define MDDI_CMD_FORCE_NEW_REV_PTR 0x0C00
#define MDDI_VIDEO_REV_PKT_SIZE 0x40
#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60
#define MDDI_MAX_REV_PKT_SIZE 0x60
/* #define MDDI_REV_BUFFER_SIZE 128 */
#define MDDI_REV_BUFFER_SIZE (MDDI_MAX_REV_PKT_SIZE * 4)
/* MDP sends 256 pixel packets, so lower value hibernates more without
* significantly increasing latency of waiting for next subframe */
#define MDDI_HOST_BYTES_PER_SUBFRAME 0x3C00
#define MDDI_HOST_TA2_LEN 0x000c
#define MDDI_HOST_REV_RATE_DIV 0x0002
struct __attribute__((packed)) mddi_rev_packet {
uint16_t length;
uint16_t type;
uint16_t client_id;
};
struct __attribute__((packed)) mddi_client_status {
uint16_t length;
uint16_t type;
uint16_t client_id;
uint16_t reverse_link_request; /* bytes needed in rev encap message */
uint8_t crc_error_count;
uint8_t capability_change;
uint16_t graphics_busy_flags;
uint16_t crc16;
};
struct __attribute__((packed)) mddi_client_caps {
uint16_t length; /* length, exclusive of this field */
uint16_t type; /* 66 */
uint16_t client_id;
uint16_t Protocol_Version;
uint16_t Minimum_Protocol_Version;
uint16_t Data_Rate_Capability;
uint8_t Interface_Type_Capability;
uint8_t Number_of_Alt_Displays;
uint16_t PostCal_Data_Rate;
uint16_t Bitmap_Width;
uint16_t Bitmap_Height;
uint16_t Display_Window_Width;
uint16_t Display_Window_Height;
uint32_t Color_Map_Size;
uint16_t Color_Map_RGB_Width;
uint16_t RGB_Capability;
uint8_t Monochrome_Capability;
uint8_t Reserved_1;
uint16_t Y_Cb_Cr_Capability;
uint16_t Bayer_Capability;
uint16_t Alpha_Cursor_Image_Planes;
uint32_t Client_Feature_Capability_Indicators;
uint8_t Maximum_Video_Frame_Rate_Capability;
uint8_t Minimum_Video_Frame_Rate_Capability;
uint16_t Minimum_Sub_frame_Rate;
uint16_t Audio_Buffer_Depth;
uint16_t Audio_Channel_Capability;
uint16_t Audio_Sample_Rate_Capability;
uint8_t Audio_Sample_Resolution;
uint8_t Mic_Audio_Sample_Resolution;
uint16_t Mic_Sample_Rate_Capability;
uint8_t Keyboard_Data_Format;
uint8_t pointing_device_data_format;
uint16_t content_protection_type;
uint16_t Mfr_Name;
uint16_t Product_Code;
uint16_t Reserved_3;
uint32_t Serial_Number;
uint8_t Week_of_Manufacture;
uint8_t Year_of_Manufacture;
uint16_t crc16;
} mddi_client_capability_type;
struct __attribute__((packed)) mddi_video_stream {
uint16_t length;
uint16_t type; /* 16 */
uint16_t client_id; /* 0 */
uint16_t video_data_format_descriptor;
/* format of each pixel in the Pixel Data in the present stream in the
* present packet.
* If bits [15:13] = 000 monochrome
* If bits [15:13] = 001 color pixels (palette).
* If bits [15:13] = 010 color pixels in raw RGB
* If bits [15:13] = 011 data in 4:2:2 Y Cb Cr format
* If bits [15:13] = 100 Bayer pixels
*/
uint16_t pixel_data_attributes;
/* interpreted as follows:
* Bits [1:0] = 11 pixel data is displayed to both eyes
* Bits [1:0] = 10 pixel data is routed to the left eye only.
* Bits [1:0] = 01 pixel data is routed to the right eye only.
* Bits [1:0] = 00 pixel data is routed to the alternate display.
* Bit 2 is 0 Pixel Data is in the standard progressive format.
* Bit 2 is 1 Pixel Data is in interlace format.
* Bit 3 is 0 Pixel Data is in the standard progressive format.
* Bit 3 is 1 Pixel Data is in alternate pixel format.
* Bit 4 is 0 Pixel Data is to or from the display frame buffer.
* Bit 4 is 1 Pixel Data is to or from the camera.
* Bit 5 is 0 pixel data contains the next consecutive row of pixels.
* Bit 5 is 1 X Left Edge, Y Top Edge, X Right Edge, Y Bottom Edge,
* X Start, and Y Start parameters are not defined and
* shall be ignored by the client.
* Bits [7:6] = 01 Pixel data is written to the offline image buffer.
* Bits [7:6] = 00 Pixel data is written to the buffer to refresh display.
* Bits [7:6] = 11 Pixel data is written to all image buffers.
* Bits [7:6] = 10 Invalid. Reserved for future use.
* Bits 8 through 11 alternate display number.
* Bits 12 through 14 are reserved for future use and shall be set to zero.
* Bit 15 is 1 the row of pixels is the last row of pixels in a frame.
*/
uint16_t x_left_edge;
uint16_t y_top_edge;
/* X,Y coordinate of the top left edge of the screen window */
uint16_t x_right_edge;
uint16_t y_bottom_edge;
/* X,Y coordinate of the bottom right edge of the window being
* updated. */
uint16_t x_start;
uint16_t y_start;
/* (X Start, Y Start) is the first pixel in the Pixel Data field
* below. */
uint16_t pixel_count;
/* number of pixels in the Pixel Data field below. */
uint16_t parameter_CRC;
/* 16-bit CRC of all bytes from the Packet Length to the Pixel Count. */
uint16_t reserved;
/* 16-bit variable to make structure align on 4 byte boundary */
};
#define TYPE_VIDEO_STREAM 16
#define TYPE_CLIENT_CAPS 66
#define TYPE_REGISTER_ACCESS 146
#define TYPE_CLIENT_STATUS 70
struct __attribute__((packed)) mddi_register_access {
uint16_t length;
uint16_t type; /* 146 */
uint16_t client_id;
uint16_t read_write_info;
/* Bits 13:0 a 14-bit unsigned integer that specifies the number of
* 32-bit Register Data List items to be transferred in the
* Register Data List field.
* Bits[15:14] = 00 Write to register(s);
* Bits[15:14] = 10 Read from register(s);
* Bits[15:14] = 11 Response to a Read.
* Bits[15:14] = 01 this value is reserved for future use. */
#define MDDI_WRITE (0 << 14)
#define MDDI_READ (2 << 14)
#define MDDI_READ_RESP (3 << 14)
uint32_t register_address;
/* the register address that is to be written to or read from. */
uint16_t crc16;
uint32_t register_data_list;
/* list of 4-byte register data values for/from client registers */
};
struct __attribute__((packed)) mddi_llentry {
uint16_t flags;
uint16_t header_count;
uint16_t data_count;
dma_addr_t data; /* 32 bit */
struct mddi_llentry *next;
uint16_t reserved;
union {
struct mddi_video_stream v;
struct mddi_register_access r;
uint32_t _[12];
} u;
};
#endif
/* drivers/video/msm_fb/mdp.c
*
* MSM MDP Interface (used by framebuffer core)
*
* Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
*
* 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/kernel.h>
#include <linux/fb.h>
#include <linux/msm_mdp.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/clk.h>
#include <linux/file.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/platform_data/video-msm_fb.h>
#include <linux/platform_device.h>
#include <linux/export.h>
#include "mdp_hw.h"
struct class *mdp_class;
#define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
static uint16_t mdp_default_ccs[] = {
0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
0x010, 0x080, 0x080
};
static DECLARE_WAIT_QUEUE_HEAD(mdp_dma2_waitqueue);
static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
static struct msmfb_callback *dma_callback;
static struct clk *clk;
static unsigned int mdp_irq_mask;
static DEFINE_SPINLOCK(mdp_lock);
DEFINE_MUTEX(mdp_mutex);
static int enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
unsigned long irq_flags;
int ret = 0;
BUG_ON(!mask);
spin_lock_irqsave(&mdp_lock, irq_flags);
/* if the mask bits are already set return an error, this interrupt
* is already enabled */
if (mdp_irq_mask & mask) {
printk(KERN_ERR "mdp irq already on already on %x %x\n",
mdp_irq_mask, mask);
ret = -1;
}
/* if the mdp irq is not already enabled enable it */
if (!mdp_irq_mask) {
if (clk)
clk_enable(clk);
enable_irq(mdp->irq);
}
/* update the irq mask to reflect the fact that the interrupt is
* enabled */
mdp_irq_mask |= mask;
spin_unlock_irqrestore(&mdp_lock, irq_flags);
return ret;
}
static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
/* this interrupt is already disabled! */
if (!(mdp_irq_mask & mask)) {
printk(KERN_ERR "mdp irq already off %x %x\n",
mdp_irq_mask, mask);
return -1;
}
/* update the irq mask to reflect the fact that the interrupt is
* disabled */
mdp_irq_mask &= ~(mask);
/* if no one is waiting on the interrupt, disable it */
if (!mdp_irq_mask) {
disable_irq_nosync(mdp->irq);
if (clk)
clk_disable(clk);
}
return 0;
}
static int disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
{
unsigned long irq_flags;
int ret;
spin_lock_irqsave(&mdp_lock, irq_flags);
ret = locked_disable_mdp_irq(mdp, mask);
spin_unlock_irqrestore(&mdp_lock, irq_flags);
return ret;
}
static irqreturn_t mdp_isr(int irq, void *data)
{
uint32_t status;
unsigned long irq_flags;
struct mdp_info *mdp = data;
spin_lock_irqsave(&mdp_lock, irq_flags);
status = mdp_readl(mdp, MDP_INTR_STATUS);
mdp_writel(mdp, status, MDP_INTR_CLEAR);
status &= mdp_irq_mask;
if (status & DL0_DMA2_TERM_DONE) {
if (dma_callback) {
dma_callback->func(dma_callback);
dma_callback = NULL;
}
wake_up(&mdp_dma2_waitqueue);
}
if (status & DL0_ROI_DONE)
wake_up(&mdp_ppp_waitqueue);
if (status)
locked_disable_mdp_irq(mdp, status);
spin_unlock_irqrestore(&mdp_lock, irq_flags);
return IRQ_HANDLED;
}
static uint32_t mdp_check_mask(uint32_t mask)
{
uint32_t ret;
unsigned long irq_flags;
spin_lock_irqsave(&mdp_lock, irq_flags);
ret = mdp_irq_mask & mask;
spin_unlock_irqrestore(&mdp_lock, irq_flags);
return ret;
}
static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
{
int ret = 0;
unsigned long irq_flags;
wait_event_timeout(*wq, !mdp_check_mask(mask), HZ);
spin_lock_irqsave(&mdp_lock, irq_flags);
if (mdp_irq_mask & mask) {
locked_disable_mdp_irq(mdp, mask);
printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
mask);
ret = -ETIMEDOUT;
}
spin_unlock_irqrestore(&mdp_lock, irq_flags);
return ret;
}
void mdp_dma_wait(struct mdp_device *mdp_dev)
{
#define MDP_MAX_TIMEOUTS 20
static int timeout_count;
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
if (mdp_wait(mdp, DL0_DMA2_TERM_DONE, &mdp_dma2_waitqueue) == -ETIMEDOUT)
timeout_count++;
else
timeout_count = 0;
if (timeout_count > MDP_MAX_TIMEOUTS) {
printk(KERN_ERR "mdp: dma failed %d times, somethings wrong!\n",
MDP_MAX_TIMEOUTS);
BUG();
}
}
static int mdp_ppp_wait(struct mdp_info *mdp)
{
return mdp_wait(mdp, DL0_ROI_DONE, &mdp_ppp_waitqueue);
}
void mdp_dma_to_mddi(struct mdp_info *mdp, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x, uint32_t y,
struct msmfb_callback *callback)
{
uint32_t dma2_cfg;
uint16_t ld_param = 0; /* 0=PRIM, 1=SECD, 2=EXT */
if (enable_mdp_irq(mdp, DL0_DMA2_TERM_DONE)) {
printk(KERN_ERR "mdp_dma_to_mddi: busy\n");
return;
}
dma_callback = callback;
dma2_cfg = DMA_PACK_TIGHT |
DMA_PACK_ALIGN_LSB |
DMA_PACK_PATTERN_RGB |
DMA_OUT_SEL_AHB |
DMA_IBUF_NONCONTIGUOUS;
dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
dma2_cfg |= DMA_OUT_SEL_MDDI;
dma2_cfg |= DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY;
dma2_cfg |= DMA_DITHER_EN;
/* setup size, address, and stride */
mdp_writel(mdp, (height << 16) | (width),
MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);
/* 666 18BPP */
dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
/* set y & x offset and MDDI transaction parameters */
mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
MDP_CMD_DEBUG_ACCESS_BASE + 0x01a4);
mdp_writel(mdp, dma2_cfg, MDP_CMD_DEBUG_ACCESS_BASE + 0x0180);
/* start DMA2 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
}
void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
uint32_t width, uint32_t height, uint32_t x, uint32_t y,
struct msmfb_callback *callback, int interface)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
if (interface == MSM_MDDI_PMDH_INTERFACE) {
mdp_dma_to_mddi(mdp, addr, stride, width, height, x, y,
callback);
}
}
int get_img(struct mdp_img *img, struct fb_info *info,
unsigned long *start, unsigned long *len,
struct file **filep)
{
int ret = 0;
struct fd f = fdget(img->memory_id);
if (f.file == NULL)
return -1;
if (MAJOR(file_inode(f.file)->i_rdev) == FB_MAJOR) {
*start = info->fix.smem_start;
*len = info->fix.smem_len;
} else
ret = -1;
fdput(f);
return ret;
}
void put_img(struct file *src_file, struct file *dst_file)
{
}
int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
struct mdp_blit_req *req)
{
int ret;
unsigned long src_start = 0, src_len = 0, dst_start = 0, dst_len = 0;
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
struct file *src_file = 0, *dst_file = 0;
/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
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 -EINVAL;
/* do this first so that if this fails, the caller can always
* safely call put_img */
if (unlikely(get_img(&req->src, fb, &src_start, &src_len, &src_file))) {
printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
"memory\n");
return -EINVAL;
}
if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len, &dst_file))) {
printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
"memory\n");
return -EINVAL;
}
mutex_lock(&mdp_mutex);
/* transp_masking unimplemented */
req->transp_mask = MDP_TRANSP_NOP;
if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
req->alpha != MDP_ALPHA_NOP ||
HAS_ALPHA(req->src.format)) &&
(req->flags & MDP_ROT_90 &&
req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
int i;
unsigned int tiles = req->dst_rect.h / 16;
unsigned int remainder = req->dst_rect.h % 16;
req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = 16;
for (i = 0; i < tiles; i++) {
enable_mdp_irq(mdp, DL0_ROI_DONE);
ret = mdp_ppp_blit(mdp, req, src_file, src_start,
src_len, dst_file, dst_start,
dst_len);
if (ret)
goto err_bad_blit;
ret = mdp_ppp_wait(mdp);
if (ret)
goto err_wait_failed;
req->dst_rect.y += 16;
req->src_rect.x += req->src_rect.w;
}
if (!remainder)
goto end;
req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
req->dst_rect.h = remainder;
}
enable_mdp_irq(mdp, DL0_ROI_DONE);
ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
dst_start,
dst_len);
if (ret)
goto err_bad_blit;
ret = mdp_ppp_wait(mdp);
if (ret)
goto err_wait_failed;
end:
put_img(src_file, dst_file);
mutex_unlock(&mdp_mutex);
return 0;
err_bad_blit:
disable_mdp_irq(mdp, DL0_ROI_DONE);
err_wait_failed:
put_img(src_file, dst_file);
mutex_unlock(&mdp_mutex);
return ret;
}
void mdp_set_grp_disp(struct mdp_device *mdp_dev, unsigned disp_id)
{
struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
disp_id &= 0xf;
mdp_writel(mdp, disp_id, MDP_FULL_BYPASS_WORD43);
}
int register_mdp_client(struct class_interface *cint)
{
if (!mdp_class) {
pr_err("mdp: no mdp_class when registering mdp client\n");
return -ENODEV;
}
cint->class = mdp_class;
return class_interface_register(cint);
}
#include "mdp_csc_table.h"
#include "mdp_scale_tables.h"
int mdp_probe(struct platform_device *pdev)
{
struct resource *resource;
int ret;
int n;
struct mdp_info *mdp;
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!resource) {
pr_err("mdp: can not get mdp mem resource!\n");
return -ENOMEM;
}
mdp = kzalloc(sizeof(struct mdp_info), GFP_KERNEL);
if (!mdp)
return -ENOMEM;
mdp->irq = platform_get_irq(pdev, 0);
if (mdp->irq < 0) {
pr_err("mdp: can not get mdp irq\n");
ret = mdp->irq;
goto error_get_irq;
}
mdp->base = ioremap(resource->start, resource_size(resource));
if (mdp->base == 0) {
printk(KERN_ERR "msmfb: cannot allocate mdp regs!\n");
ret = -ENOMEM;
goto error_ioremap;
}
mdp->mdp_dev.dma = mdp_dma;
mdp->mdp_dev.dma_wait = mdp_dma_wait;
mdp->mdp_dev.blit = mdp_blit;
mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
clk = clk_get(&pdev->dev, "mdp_clk");
if (IS_ERR(clk)) {
printk(KERN_INFO "mdp: failed to get mdp clk");
ret = PTR_ERR(clk);
goto error_get_clk;
}
ret = request_irq(mdp->irq, mdp_isr, 0, "msm_mdp", mdp);
if (ret)
goto error_request_irq;
disable_irq(mdp->irq);
mdp_irq_mask = 0;
/* debug interface write access */
mdp_writel(mdp, 1, 0x60);
mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
for (n = 0; n < ARRAY_SIZE(csc_table); n++)
mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
/* clear up unused fg/main registers */
/* comp.plane 2&3 ystride */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
/* unpacked pattern */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
/* comp.plane 2 & 3 */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
/* clear unused bg registers */
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
mdp_writel(mdp, mdp_upscale_table[n].val,
mdp_upscale_table[n].reg);
for (n = 0; n < 9; n++)
mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
/* register mdp device */
mdp->mdp_dev.dev.parent = &pdev->dev;
mdp->mdp_dev.dev.class = mdp_class;
dev_set_name(&mdp->mdp_dev.dev, "mdp%d", pdev->id);
/* if you can remove the platform device you'd have to implement
* this:
mdp_dev.release = mdp_class; */
ret = device_register(&mdp->mdp_dev.dev);
if (ret)
goto error_device_register;
return 0;
error_device_register:
free_irq(mdp->irq, mdp);
error_request_irq:
error_get_clk:
iounmap(mdp->base);
error_get_irq:
error_ioremap:
kfree(mdp);
return ret;
}
static struct platform_driver msm_mdp_driver = {
.probe = mdp_probe,
.driver = {.name = "msm_mdp"},
};
static int __init mdp_init(void)
{
mdp_class = class_create(THIS_MODULE, "msm_mdp");
if (IS_ERR(mdp_class)) {
printk(KERN_ERR "Error creating mdp class\n");
return PTR_ERR(mdp_class);
}
return platform_driver_register(&msm_mdp_driver);
}
subsys_initcall(mdp_init);
/* drivers/video/msm_fb/mdp_csc_table.h
*
* Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
*
* 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.
*/
static struct {
uint32_t reg;
uint32_t val;
} csc_table[] = {
{ 0x40400, 0x83 },
{ 0x40404, 0x102 },
{ 0x40408, 0x32 },
{ 0x4040c, 0xffffffb5 },
{ 0x40410, 0xffffff6c },
{ 0x40414, 0xe1 },
{ 0x40418, 0xe1 },
{ 0x4041c, 0xffffff45 },
{ 0x40420, 0xffffffdc },
{ 0x40440, 0x254 },
{ 0x40444, 0x0 },
{ 0x40448, 0x331 },
{ 0x4044c, 0x254 },
{ 0x40450, 0xffffff38 },
{ 0x40454, 0xfffffe61 },
{ 0x40458, 0x254 },
{ 0x4045c, 0x409 },
{ 0x40460, 0x0 },
{ 0x40480, 0x5d },
{ 0x40484, 0x13a },
{ 0x40488, 0x20 },
{ 0x4048c, 0xffffffcd },
{ 0x40490, 0xffffff54 },
{ 0x40494, 0xe1 },
{ 0x40498, 0xe1 },
{ 0x4049c, 0xffffff35 },
{ 0x404a0, 0xffffffec },
{ 0x404c0, 0x254 },
{ 0x404c4, 0x0 },
{ 0x404c8, 0x396 },
{ 0x404cc, 0x254 },
{ 0x404d0, 0xffffff94 },
{ 0x404d4, 0xfffffef0 },
{ 0x404d8, 0x254 },
{ 0x404dc, 0x43a },
{ 0x404e0, 0x0 },
{ 0x40500, 0x10 },
{ 0x40504, 0x80 },
{ 0x40508, 0x80 },
{ 0x40540, 0x10 },
{ 0x40544, 0x80 },
{ 0x40548, 0x80 },
{ 0x40580, 0x10 },
{ 0x40584, 0xeb },
{ 0x40588, 0x10 },
{ 0x4058c, 0xf0 },
{ 0x405c0, 0x10 },
{ 0x405c4, 0xeb },
{ 0x405c8, 0x10 },
{ 0x405cc, 0xf0 },
{ 0x40800, 0x0 },
{ 0x40804, 0x151515 },
{ 0x40808, 0x1d1d1d },
{ 0x4080c, 0x232323 },
{ 0x40810, 0x272727 },
{ 0x40814, 0x2b2b2b },
{ 0x40818, 0x2f2f2f },
{ 0x4081c, 0x333333 },
{ 0x40820, 0x363636 },
{ 0x40824, 0x393939 },
{ 0x40828, 0x3b3b3b },
{ 0x4082c, 0x3e3e3e },
{ 0x40830, 0x404040 },
{ 0x40834, 0x434343 },
{ 0x40838, 0x454545 },
{ 0x4083c, 0x474747 },
{ 0x40840, 0x494949 },
{ 0x40844, 0x4b4b4b },
{ 0x40848, 0x4d4d4d },
{ 0x4084c, 0x4f4f4f },
{ 0x40850, 0x515151 },
{ 0x40854, 0x535353 },
{ 0x40858, 0x555555 },
{ 0x4085c, 0x565656 },
{ 0x40860, 0x585858 },
{ 0x40864, 0x5a5a5a },
{ 0x40868, 0x5b5b5b },
{ 0x4086c, 0x5d5d5d },
{ 0x40870, 0x5e5e5e },
{ 0x40874, 0x606060 },
{ 0x40878, 0x616161 },
{ 0x4087c, 0x636363 },
{ 0x40880, 0x646464 },
{ 0x40884, 0x666666 },
{ 0x40888, 0x676767 },
{ 0x4088c, 0x686868 },
{ 0x40890, 0x6a6a6a },
{ 0x40894, 0x6b6b6b },
{ 0x40898, 0x6c6c6c },
{ 0x4089c, 0x6e6e6e },
{ 0x408a0, 0x6f6f6f },
{ 0x408a4, 0x707070 },
{ 0x408a8, 0x717171 },
{ 0x408ac, 0x727272 },
{ 0x408b0, 0x747474 },
{ 0x408b4, 0x757575 },
{ 0x408b8, 0x767676 },
{ 0x408bc, 0x777777 },
{ 0x408c0, 0x787878 },
{ 0x408c4, 0x797979 },
{ 0x408c8, 0x7a7a7a },
{ 0x408cc, 0x7c7c7c },
{ 0x408d0, 0x7d7d7d },
{ 0x408d4, 0x7e7e7e },
{ 0x408d8, 0x7f7f7f },
{ 0x408dc, 0x808080 },
{ 0x408e0, 0x818181 },
{ 0x408e4, 0x828282 },
{ 0x408e8, 0x838383 },
{ 0x408ec, 0x848484 },
{ 0x408f0, 0x858585 },
{ 0x408f4, 0x868686 },
{ 0x408f8, 0x878787 },
{ 0x408fc, 0x888888 },
{ 0x40900, 0x898989 },
{ 0x40904, 0x8a8a8a },
{ 0x40908, 0x8b8b8b },
{ 0x4090c, 0x8c8c8c },
{ 0x40910, 0x8d8d8d },
{ 0x40914, 0x8e8e8e },
{ 0x40918, 0x8f8f8f },
{ 0x4091c, 0x8f8f8f },
{ 0x40920, 0x909090 },
{ 0x40924, 0x919191 },
{ 0x40928, 0x929292 },
{ 0x4092c, 0x939393 },
{ 0x40930, 0x949494 },
{ 0x40934, 0x959595 },
{ 0x40938, 0x969696 },
{ 0x4093c, 0x969696 },
{ 0x40940, 0x979797 },
{ 0x40944, 0x989898 },
{ 0x40948, 0x999999 },
{ 0x4094c, 0x9a9a9a },
{ 0x40950, 0x9b9b9b },
{ 0x40954, 0x9c9c9c },
{ 0x40958, 0x9c9c9c },
{ 0x4095c, 0x9d9d9d },
{ 0x40960, 0x9e9e9e },
{ 0x40964, 0x9f9f9f },
{ 0x40968, 0xa0a0a0 },
{ 0x4096c, 0xa0a0a0 },
{ 0x40970, 0xa1a1a1 },
{ 0x40974, 0xa2a2a2 },
{ 0x40978, 0xa3a3a3 },
{ 0x4097c, 0xa4a4a4 },
{ 0x40980, 0xa4a4a4 },
{ 0x40984, 0xa5a5a5 },
{ 0x40988, 0xa6a6a6 },
{ 0x4098c, 0xa7a7a7 },
{ 0x40990, 0xa7a7a7 },
{ 0x40994, 0xa8a8a8 },
{ 0x40998, 0xa9a9a9 },
{ 0x4099c, 0xaaaaaa },
{ 0x409a0, 0xaaaaaa },
{ 0x409a4, 0xababab },
{ 0x409a8, 0xacacac },
{ 0x409ac, 0xadadad },
{ 0x409b0, 0xadadad },
{ 0x409b4, 0xaeaeae },
{ 0x409b8, 0xafafaf },
{ 0x409bc, 0xafafaf },
{ 0x409c0, 0xb0b0b0 },
{ 0x409c4, 0xb1b1b1 },
{ 0x409c8, 0xb2b2b2 },
{ 0x409cc, 0xb2b2b2 },
{ 0x409d0, 0xb3b3b3 },
{ 0x409d4, 0xb4b4b4 },
{ 0x409d8, 0xb4b4b4 },
{ 0x409dc, 0xb5b5b5 },
{ 0x409e0, 0xb6b6b6 },
{ 0x409e4, 0xb6b6b6 },
{ 0x409e8, 0xb7b7b7 },
{ 0x409ec, 0xb8b8b8 },
{ 0x409f0, 0xb8b8b8 },
{ 0x409f4, 0xb9b9b9 },
{ 0x409f8, 0xbababa },
{ 0x409fc, 0xbababa },
{ 0x40a00, 0xbbbbbb },
{ 0x40a04, 0xbcbcbc },
{ 0x40a08, 0xbcbcbc },
{ 0x40a0c, 0xbdbdbd },
{ 0x40a10, 0xbebebe },
{ 0x40a14, 0xbebebe },
{ 0x40a18, 0xbfbfbf },
{ 0x40a1c, 0xc0c0c0 },
{ 0x40a20, 0xc0c0c0 },
{ 0x40a24, 0xc1c1c1 },
{ 0x40a28, 0xc1c1c1 },
{ 0x40a2c, 0xc2c2c2 },
{ 0x40a30, 0xc3c3c3 },
{ 0x40a34, 0xc3c3c3 },
{ 0x40a38, 0xc4c4c4 },
{ 0x40a3c, 0xc5c5c5 },
{ 0x40a40, 0xc5c5c5 },
{ 0x40a44, 0xc6c6c6 },
{ 0x40a48, 0xc6c6c6 },
{ 0x40a4c, 0xc7c7c7 },
{ 0x40a50, 0xc8c8c8 },
{ 0x40a54, 0xc8c8c8 },
{ 0x40a58, 0xc9c9c9 },
{ 0x40a5c, 0xc9c9c9 },
{ 0x40a60, 0xcacaca },
{ 0x40a64, 0xcbcbcb },
{ 0x40a68, 0xcbcbcb },
{ 0x40a6c, 0xcccccc },
{ 0x40a70, 0xcccccc },
{ 0x40a74, 0xcdcdcd },
{ 0x40a78, 0xcecece },
{ 0x40a7c, 0xcecece },
{ 0x40a80, 0xcfcfcf },
{ 0x40a84, 0xcfcfcf },
{ 0x40a88, 0xd0d0d0 },
{ 0x40a8c, 0xd0d0d0 },
{ 0x40a90, 0xd1d1d1 },
{ 0x40a94, 0xd2d2d2 },
{ 0x40a98, 0xd2d2d2 },
{ 0x40a9c, 0xd3d3d3 },
{ 0x40aa0, 0xd3d3d3 },
{ 0x40aa4, 0xd4d4d4 },
{ 0x40aa8, 0xd4d4d4 },
{ 0x40aac, 0xd5d5d5 },
{ 0x40ab0, 0xd6d6d6 },
{ 0x40ab4, 0xd6d6d6 },
{ 0x40ab8, 0xd7d7d7 },
{ 0x40abc, 0xd7d7d7 },
{ 0x40ac0, 0xd8d8d8 },
{ 0x40ac4, 0xd8d8d8 },
{ 0x40ac8, 0xd9d9d9 },
{ 0x40acc, 0xd9d9d9 },
{ 0x40ad0, 0xdadada },
{ 0x40ad4, 0xdbdbdb },
{ 0x40ad8, 0xdbdbdb },
{ 0x40adc, 0xdcdcdc },
{ 0x40ae0, 0xdcdcdc },
{ 0x40ae4, 0xdddddd },
{ 0x40ae8, 0xdddddd },
{ 0x40aec, 0xdedede },
{ 0x40af0, 0xdedede },
{ 0x40af4, 0xdfdfdf },
{ 0x40af8, 0xdfdfdf },
{ 0x40afc, 0xe0e0e0 },
{ 0x40b00, 0xe0e0e0 },
{ 0x40b04, 0xe1e1e1 },
{ 0x40b08, 0xe1e1e1 },
{ 0x40b0c, 0xe2e2e2 },
{ 0x40b10, 0xe3e3e3 },
{ 0x40b14, 0xe3e3e3 },
{ 0x40b18, 0xe4e4e4 },
{ 0x40b1c, 0xe4e4e4 },
{ 0x40b20, 0xe5e5e5 },
{ 0x40b24, 0xe5e5e5 },
{ 0x40b28, 0xe6e6e6 },
{ 0x40b2c, 0xe6e6e6 },
{ 0x40b30, 0xe7e7e7 },
{ 0x40b34, 0xe7e7e7 },
{ 0x40b38, 0xe8e8e8 },
{ 0x40b3c, 0xe8e8e8 },
{ 0x40b40, 0xe9e9e9 },
{ 0x40b44, 0xe9e9e9 },
{ 0x40b48, 0xeaeaea },
{ 0x40b4c, 0xeaeaea },
{ 0x40b50, 0xebebeb },
{ 0x40b54, 0xebebeb },
{ 0x40b58, 0xececec },
{ 0x40b5c, 0xececec },
{ 0x40b60, 0xededed },
{ 0x40b64, 0xededed },
{ 0x40b68, 0xeeeeee },
{ 0x40b6c, 0xeeeeee },
{ 0x40b70, 0xefefef },
{ 0x40b74, 0xefefef },
{ 0x40b78, 0xf0f0f0 },
{ 0x40b7c, 0xf0f0f0 },
{ 0x40b80, 0xf1f1f1 },
{ 0x40b84, 0xf1f1f1 },
{ 0x40b88, 0xf2f2f2 },
{ 0x40b8c, 0xf2f2f2 },
{ 0x40b90, 0xf2f2f2 },
{ 0x40b94, 0xf3f3f3 },
{ 0x40b98, 0xf3f3f3 },
{ 0x40b9c, 0xf4f4f4 },
{ 0x40ba0, 0xf4f4f4 },
{ 0x40ba4, 0xf5f5f5 },
{ 0x40ba8, 0xf5f5f5 },
{ 0x40bac, 0xf6f6f6 },
{ 0x40bb0, 0xf6f6f6 },
{ 0x40bb4, 0xf7f7f7 },
{ 0x40bb8, 0xf7f7f7 },
{ 0x40bbc, 0xf8f8f8 },
{ 0x40bc0, 0xf8f8f8 },
{ 0x40bc4, 0xf9f9f9 },
{ 0x40bc8, 0xf9f9f9 },
{ 0x40bcc, 0xfafafa },
{ 0x40bd0, 0xfafafa },
{ 0x40bd4, 0xfafafa },
{ 0x40bd8, 0xfbfbfb },
{ 0x40bdc, 0xfbfbfb },
{ 0x40be0, 0xfcfcfc },
{ 0x40be4, 0xfcfcfc },
{ 0x40be8, 0xfdfdfd },
{ 0x40bec, 0xfdfdfd },
{ 0x40bf0, 0xfefefe },
{ 0x40bf4, 0xfefefe },
{ 0x40bf8, 0xffffff },
{ 0x40bfc, 0xffffff },
{ 0x40c00, 0x0 },
{ 0x40c04, 0x0 },
{ 0x40c08, 0x0 },
{ 0x40c0c, 0x0 },
{ 0x40c10, 0x0 },
{ 0x40c14, 0x0 },
{ 0x40c18, 0x0 },
{ 0x40c1c, 0x0 },
{ 0x40c20, 0x0 },
{ 0x40c24, 0x0 },
{ 0x40c28, 0x0 },
{ 0x40c2c, 0x0 },
{ 0x40c30, 0x0 },
{ 0x40c34, 0x0 },
{ 0x40c38, 0x0 },
{ 0x40c3c, 0x0 },
{ 0x40c40, 0x10101 },
{ 0x40c44, 0x10101 },
{ 0x40c48, 0x10101 },
{ 0x40c4c, 0x10101 },
{ 0x40c50, 0x10101 },
{ 0x40c54, 0x10101 },
{ 0x40c58, 0x10101 },
{ 0x40c5c, 0x10101 },
{ 0x40c60, 0x10101 },
{ 0x40c64, 0x10101 },
{ 0x40c68, 0x20202 },
{ 0x40c6c, 0x20202 },
{ 0x40c70, 0x20202 },
{ 0x40c74, 0x20202 },
{ 0x40c78, 0x20202 },
{ 0x40c7c, 0x20202 },
{ 0x40c80, 0x30303 },
{ 0x40c84, 0x30303 },
{ 0x40c88, 0x30303 },
{ 0x40c8c, 0x30303 },
{ 0x40c90, 0x30303 },
{ 0x40c94, 0x40404 },
{ 0x40c98, 0x40404 },
{ 0x40c9c, 0x40404 },
{ 0x40ca0, 0x40404 },
{ 0x40ca4, 0x40404 },
{ 0x40ca8, 0x50505 },
{ 0x40cac, 0x50505 },
{ 0x40cb0, 0x50505 },
{ 0x40cb4, 0x50505 },
{ 0x40cb8, 0x60606 },
{ 0x40cbc, 0x60606 },
{ 0x40cc0, 0x60606 },
{ 0x40cc4, 0x70707 },
{ 0x40cc8, 0x70707 },
{ 0x40ccc, 0x70707 },
{ 0x40cd0, 0x70707 },
{ 0x40cd4, 0x80808 },
{ 0x40cd8, 0x80808 },
{ 0x40cdc, 0x80808 },
{ 0x40ce0, 0x90909 },
{ 0x40ce4, 0x90909 },
{ 0x40ce8, 0xa0a0a },
{ 0x40cec, 0xa0a0a },
{ 0x40cf0, 0xa0a0a },
{ 0x40cf4, 0xb0b0b },
{ 0x40cf8, 0xb0b0b },
{ 0x40cfc, 0xb0b0b },
{ 0x40d00, 0xc0c0c },
{ 0x40d04, 0xc0c0c },
{ 0x40d08, 0xd0d0d },
{ 0x40d0c, 0xd0d0d },
{ 0x40d10, 0xe0e0e },
{ 0x40d14, 0xe0e0e },
{ 0x40d18, 0xe0e0e },
{ 0x40d1c, 0xf0f0f },
{ 0x40d20, 0xf0f0f },
{ 0x40d24, 0x101010 },
{ 0x40d28, 0x101010 },
{ 0x40d2c, 0x111111 },
{ 0x40d30, 0x111111 },
{ 0x40d34, 0x121212 },
{ 0x40d38, 0x121212 },
{ 0x40d3c, 0x131313 },
{ 0x40d40, 0x131313 },
{ 0x40d44, 0x141414 },
{ 0x40d48, 0x151515 },
{ 0x40d4c, 0x151515 },
{ 0x40d50, 0x161616 },
{ 0x40d54, 0x161616 },
{ 0x40d58, 0x171717 },
{ 0x40d5c, 0x171717 },
{ 0x40d60, 0x181818 },
{ 0x40d64, 0x191919 },
{ 0x40d68, 0x191919 },
{ 0x40d6c, 0x1a1a1a },
{ 0x40d70, 0x1b1b1b },
{ 0x40d74, 0x1b1b1b },
{ 0x40d78, 0x1c1c1c },
{ 0x40d7c, 0x1c1c1c },
{ 0x40d80, 0x1d1d1d },
{ 0x40d84, 0x1e1e1e },
{ 0x40d88, 0x1f1f1f },
{ 0x40d8c, 0x1f1f1f },
{ 0x40d90, 0x202020 },
{ 0x40d94, 0x212121 },
{ 0x40d98, 0x212121 },
{ 0x40d9c, 0x222222 },
{ 0x40da0, 0x232323 },
{ 0x40da4, 0x242424 },
{ 0x40da8, 0x242424 },
{ 0x40dac, 0x252525 },
{ 0x40db0, 0x262626 },
{ 0x40db4, 0x272727 },
{ 0x40db8, 0x272727 },
{ 0x40dbc, 0x282828 },
{ 0x40dc0, 0x292929 },
{ 0x40dc4, 0x2a2a2a },
{ 0x40dc8, 0x2b2b2b },
{ 0x40dcc, 0x2c2c2c },
{ 0x40dd0, 0x2c2c2c },
{ 0x40dd4, 0x2d2d2d },
{ 0x40dd8, 0x2e2e2e },
{ 0x40ddc, 0x2f2f2f },
{ 0x40de0, 0x303030 },
{ 0x40de4, 0x313131 },
{ 0x40de8, 0x323232 },
{ 0x40dec, 0x333333 },
{ 0x40df0, 0x333333 },
{ 0x40df4, 0x343434 },
{ 0x40df8, 0x353535 },
{ 0x40dfc, 0x363636 },
{ 0x40e00, 0x373737 },
{ 0x40e04, 0x383838 },
{ 0x40e08, 0x393939 },
{ 0x40e0c, 0x3a3a3a },
{ 0x40e10, 0x3b3b3b },
{ 0x40e14, 0x3c3c3c },
{ 0x40e18, 0x3d3d3d },
{ 0x40e1c, 0x3e3e3e },
{ 0x40e20, 0x3f3f3f },
{ 0x40e24, 0x404040 },
{ 0x40e28, 0x414141 },
{ 0x40e2c, 0x424242 },
{ 0x40e30, 0x434343 },
{ 0x40e34, 0x444444 },
{ 0x40e38, 0x464646 },
{ 0x40e3c, 0x474747 },
{ 0x40e40, 0x484848 },
{ 0x40e44, 0x494949 },
{ 0x40e48, 0x4a4a4a },
{ 0x40e4c, 0x4b4b4b },
{ 0x40e50, 0x4c4c4c },
{ 0x40e54, 0x4d4d4d },
{ 0x40e58, 0x4f4f4f },
{ 0x40e5c, 0x505050 },
{ 0x40e60, 0x515151 },
{ 0x40e64, 0x525252 },
{ 0x40e68, 0x535353 },
{ 0x40e6c, 0x545454 },
{ 0x40e70, 0x565656 },
{ 0x40e74, 0x575757 },
{ 0x40e78, 0x585858 },
{ 0x40e7c, 0x595959 },
{ 0x40e80, 0x5b5b5b },
{ 0x40e84, 0x5c5c5c },
{ 0x40e88, 0x5d5d5d },
{ 0x40e8c, 0x5e5e5e },
{ 0x40e90, 0x606060 },
{ 0x40e94, 0x616161 },
{ 0x40e98, 0x626262 },
{ 0x40e9c, 0x646464 },
{ 0x40ea0, 0x656565 },
{ 0x40ea4, 0x666666 },
{ 0x40ea8, 0x686868 },
{ 0x40eac, 0x696969 },
{ 0x40eb0, 0x6a6a6a },
{ 0x40eb4, 0x6c6c6c },
{ 0x40eb8, 0x6d6d6d },
{ 0x40ebc, 0x6f6f6f },
{ 0x40ec0, 0x707070 },
{ 0x40ec4, 0x717171 },
{ 0x40ec8, 0x737373 },
{ 0x40ecc, 0x747474 },
{ 0x40ed0, 0x767676 },
{ 0x40ed4, 0x777777 },
{ 0x40ed8, 0x797979 },
{ 0x40edc, 0x7a7a7a },
{ 0x40ee0, 0x7c7c7c },
{ 0x40ee4, 0x7d7d7d },
{ 0x40ee8, 0x7f7f7f },
{ 0x40eec, 0x808080 },
{ 0x40ef0, 0x828282 },
{ 0x40ef4, 0x838383 },
{ 0x40ef8, 0x858585 },
{ 0x40efc, 0x868686 },
{ 0x40f00, 0x888888 },
{ 0x40f04, 0x898989 },
{ 0x40f08, 0x8b8b8b },
{ 0x40f0c, 0x8d8d8d },
{ 0x40f10, 0x8e8e8e },
{ 0x40f14, 0x909090 },
{ 0x40f18, 0x919191 },
{ 0x40f1c, 0x939393 },
{ 0x40f20, 0x959595 },
{ 0x40f24, 0x969696 },
{ 0x40f28, 0x989898 },
{ 0x40f2c, 0x9a9a9a },
{ 0x40f30, 0x9b9b9b },
{ 0x40f34, 0x9d9d9d },
{ 0x40f38, 0x9f9f9f },
{ 0x40f3c, 0xa1a1a1 },
{ 0x40f40, 0xa2a2a2 },
{ 0x40f44, 0xa4a4a4 },
{ 0x40f48, 0xa6a6a6 },
{ 0x40f4c, 0xa7a7a7 },
{ 0x40f50, 0xa9a9a9 },
{ 0x40f54, 0xababab },
{ 0x40f58, 0xadadad },
{ 0x40f5c, 0xafafaf },
{ 0x40f60, 0xb0b0b0 },
{ 0x40f64, 0xb2b2b2 },
{ 0x40f68, 0xb4b4b4 },
{ 0x40f6c, 0xb6b6b6 },
{ 0x40f70, 0xb8b8b8 },
{ 0x40f74, 0xbababa },
{ 0x40f78, 0xbbbbbb },
{ 0x40f7c, 0xbdbdbd },
{ 0x40f80, 0xbfbfbf },
{ 0x40f84, 0xc1c1c1 },
{ 0x40f88, 0xc3c3c3 },
{ 0x40f8c, 0xc5c5c5 },
{ 0x40f90, 0xc7c7c7 },
{ 0x40f94, 0xc9c9c9 },
{ 0x40f98, 0xcbcbcb },
{ 0x40f9c, 0xcdcdcd },
{ 0x40fa0, 0xcfcfcf },
{ 0x40fa4, 0xd1d1d1 },
{ 0x40fa8, 0xd3d3d3 },
{ 0x40fac, 0xd5d5d5 },
{ 0x40fb0, 0xd7d7d7 },
{ 0x40fb4, 0xd9d9d9 },
{ 0x40fb8, 0xdbdbdb },
{ 0x40fbc, 0xdddddd },
{ 0x40fc0, 0xdfdfdf },
{ 0x40fc4, 0xe1e1e1 },
{ 0x40fc8, 0xe3e3e3 },
{ 0x40fcc, 0xe5e5e5 },
{ 0x40fd0, 0xe7e7e7 },
{ 0x40fd4, 0xe9e9e9 },
{ 0x40fd8, 0xebebeb },
{ 0x40fdc, 0xeeeeee },
{ 0x40fe0, 0xf0f0f0 },
{ 0x40fe4, 0xf2f2f2 },
{ 0x40fe8, 0xf4f4f4 },
{ 0x40fec, 0xf6f6f6 },
{ 0x40ff0, 0xf8f8f8 },
{ 0x40ff4, 0xfbfbfb },
{ 0x40ff8, 0xfdfdfd },
{ 0x40ffc, 0xffffff },
};
此差异已折叠。
此差异已折叠。
此差异已折叠。
/* drivers/video/msm_fb/mdp_scale_tables.h
*
* Copyright (C) 2007 QUALCOMM Incorporated
* Copyright (C) 2007 Google Incorporated
*
* 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.
*/
#ifndef _MDP_SCALE_TABLES_H_
#define _MDP_SCALE_TABLES_H_
#include <linux/types.h>
struct mdp_table_entry {
uint32_t reg;
uint32_t val;
};
extern struct mdp_table_entry mdp_upscale_table[64];
enum {
MDP_DOWNSCALE_PT2TOPT4,
MDP_DOWNSCALE_PT4TOPT6,
MDP_DOWNSCALE_PT6TOPT8,
MDP_DOWNSCALE_PT8TO1,
MDP_DOWNSCALE_MAX,
};
extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
extern struct mdp_table_entry mdp_gaussian_blur_table[];
#endif
/* drivers/video/msm/msm_fb.c
*
* Core MSM framebuffer driver.
*
* Copyright (C) 2007 Google Incorporated
*
* 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/platform_device.h>
#include <linux/module.h>
#include <linux/fb.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/wait.h>
#include <linux/msm_mdp.h>
#include <linux/io.h>
#include <linux/uaccess.h>
#include <linux/platform_data/video-msm_fb.h>
#include <linux/workqueue.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/dma-mapping.h>
#define PRINT_FPS 0
#define PRINT_BLIT_TIME 0
#define SLEEPING 0x4
#define UPDATING 0x3
#define FULL_UPDATE_DONE 0x2
#define WAKING 0x1
#define AWAKE 0x0
#define NONE 0
#define SUSPEND_RESUME 0x1
#define FPS 0x2
#define BLIT_TIME 0x4
#define SHOW_UPDATES 0x8
#define DLOG(mask, fmt, args...) \
do { \
if (msmfb_debug_mask & mask) \
printk(KERN_INFO "msmfb: "fmt, ##args); \
} while (0)
static int msmfb_debug_mask;
module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
S_IRUGO | S_IWUSR | S_IWGRP);
struct mdp_device *mdp;
struct msmfb_info {
struct fb_info *fb;
struct msm_panel_data *panel;
int xres;
int yres;
unsigned output_format;
unsigned yoffset;
unsigned frame_requested;
unsigned frame_done;
int sleeping;
unsigned update_frame;
struct {
int left;
int top;
int eright; /* exclusive */
int ebottom; /* exclusive */
} update_info;
char *black;
spinlock_t update_lock;
struct mutex panel_init_lock;
wait_queue_head_t frame_wq;
struct work_struct resume_work;
struct msmfb_callback dma_callback;
struct msmfb_callback vsync_callback;
struct hrtimer fake_vsync;
ktime_t vsync_request_time;
};
static int msmfb_open(struct fb_info *info, int user)
{
return 0;
}
static int msmfb_release(struct fb_info *info, int user)
{
return 0;
}
/* Called from dma interrupt handler, must not sleep */
static void msmfb_handle_dma_interrupt(struct msmfb_callback *callback)
{
unsigned long irq_flags;
struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
dma_callback);
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
msmfb->frame_done = msmfb->frame_requested;
if (msmfb->sleeping == UPDATING &&
msmfb->frame_done == msmfb->update_frame) {
DLOG(SUSPEND_RESUME, "full update completed\n");
schedule_work(&msmfb->resume_work);
}
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
wake_up(&msmfb->frame_wq);
}
static int msmfb_start_dma(struct msmfb_info *msmfb)
{
uint32_t x, y, w, h;
unsigned addr;
unsigned long irq_flags;
uint32_t yoffset;
s64 time_since_request;
struct msm_panel_data *panel = msmfb->panel;
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
time_since_request = ktime_to_ns(ktime_sub(ktime_get(),
msmfb->vsync_request_time));
if (time_since_request > 20 * NSEC_PER_MSEC) {
uint32_t us;
us = do_div(time_since_request, NSEC_PER_MSEC) / NSEC_PER_USEC;
printk(KERN_WARNING "msmfb_start_dma %lld.%03u ms after vsync "
"request\n", time_since_request, us);
}
if (msmfb->frame_done == msmfb->frame_requested) {
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
return -1;
}
if (msmfb->sleeping == SLEEPING) {
DLOG(SUSPEND_RESUME, "tried to start dma while asleep\n");
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
return -1;
}
x = msmfb->update_info.left;
y = msmfb->update_info.top;
w = msmfb->update_info.eright - x;
h = msmfb->update_info.ebottom - y;
yoffset = msmfb->yoffset;
msmfb->update_info.left = msmfb->xres + 1;
msmfb->update_info.top = msmfb->yres + 1;
msmfb->update_info.eright = 0;
msmfb->update_info.ebottom = 0;
if (unlikely(w > msmfb->xres || h > msmfb->yres ||
w == 0 || h == 0)) {
printk(KERN_INFO "invalid update: %d %d %d "
"%d\n", x, y, w, h);
msmfb->frame_done = msmfb->frame_requested;
goto error;
}
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
addr = ((msmfb->xres * (yoffset + y) + x) * 2);
mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
panel->interface_type);
return 0;
error:
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
/* some clients need to clear their vsync interrupt */
if (panel->clear_vsync)
panel->clear_vsync(panel);
wake_up(&msmfb->frame_wq);
return 0;
}
/* Called from esync interrupt handler, must not sleep */
static void msmfb_handle_vsync_interrupt(struct msmfb_callback *callback)
{
struct msmfb_info *msmfb = container_of(callback, struct msmfb_info,
vsync_callback);
msmfb_start_dma(msmfb);
}
static enum hrtimer_restart msmfb_fake_vsync(struct hrtimer *timer)
{
struct msmfb_info *msmfb = container_of(timer, struct msmfb_info,
fake_vsync);
msmfb_start_dma(msmfb);
return HRTIMER_NORESTART;
}
static void msmfb_pan_update(struct fb_info *info, uint32_t left, uint32_t top,
uint32_t eright, uint32_t ebottom,
uint32_t yoffset, int pan_display)
{
struct msmfb_info *msmfb = info->par;
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
int sleeping;
int retry = 1;
DLOG(SHOW_UPDATES, "update %d %d %d %d %d %d\n",
left, top, eright, ebottom, yoffset, pan_display);
restart:
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
/* if we are sleeping, on a pan_display wait 10ms (to throttle back
* drawing otherwise return */
if (msmfb->sleeping == SLEEPING) {
DLOG(SUSPEND_RESUME, "drawing while asleep\n");
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
if (pan_display)
wait_event_interruptible_timeout(msmfb->frame_wq,
msmfb->sleeping != SLEEPING, HZ/10);
return;
}
sleeping = msmfb->sleeping;
/* on a full update, if the last frame has not completed, wait for it */
if ((pan_display && msmfb->frame_requested != msmfb->frame_done) ||
sleeping == UPDATING) {
int ret;
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
ret = wait_event_interruptible_timeout(msmfb->frame_wq,
msmfb->frame_done == msmfb->frame_requested &&
msmfb->sleeping != UPDATING, 5 * HZ);
if (ret <= 0 && (msmfb->frame_requested != msmfb->frame_done ||
msmfb->sleeping == UPDATING)) {
if (retry && panel->request_vsync &&
(sleeping == AWAKE)) {
panel->request_vsync(panel,
&msmfb->vsync_callback);
retry = 0;
printk(KERN_WARNING "msmfb_pan_display timeout "
"rerequest vsync\n");
} else {
printk(KERN_WARNING "msmfb_pan_display timeout "
"waiting for frame start, %d %d\n",
msmfb->frame_requested,
msmfb->frame_done);
return;
}
}
goto restart;
}
msmfb->frame_requested++;
/* if necessary, update the y offset, if this is the
* first full update on resume, set the sleeping state */
if (pan_display) {
msmfb->yoffset = yoffset;
if (left == 0 && top == 0 && eright == info->var.xres &&
ebottom == info->var.yres) {
if (sleeping == WAKING) {
msmfb->update_frame = msmfb->frame_requested;
DLOG(SUSPEND_RESUME, "full update starting\n");
msmfb->sleeping = UPDATING;
}
}
}
/* set the update request */
if (left < msmfb->update_info.left)
msmfb->update_info.left = left;
if (top < msmfb->update_info.top)
msmfb->update_info.top = top;
if (eright > msmfb->update_info.eright)
msmfb->update_info.eright = eright;
if (ebottom > msmfb->update_info.ebottom)
msmfb->update_info.ebottom = ebottom;
DLOG(SHOW_UPDATES, "update queued %d %d %d %d %d\n",
msmfb->update_info.left, msmfb->update_info.top,
msmfb->update_info.eright, msmfb->update_info.ebottom,
msmfb->yoffset);
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
/* if the panel is all the way on wait for vsync, otherwise sleep
* for 16 ms (long enough for the dma to panel) and then begin dma */
msmfb->vsync_request_time = ktime_get();
if (panel->request_vsync && (sleeping == AWAKE)) {
panel->request_vsync(panel, &msmfb->vsync_callback);
} else {
if (!hrtimer_active(&msmfb->fake_vsync)) {
hrtimer_start(&msmfb->fake_vsync,
ktime_set(0, NSEC_PER_SEC/60),
HRTIMER_MODE_REL);
}
}
}
static void msmfb_update(struct fb_info *info, uint32_t left, uint32_t top,
uint32_t eright, uint32_t ebottom)
{
msmfb_pan_update(info, left, top, eright, ebottom, 0, 0);
}
static void power_on_panel(struct work_struct *work)
{
struct msmfb_info *msmfb =
container_of(work, struct msmfb_info, resume_work);
struct msm_panel_data *panel = msmfb->panel;
unsigned long irq_flags;
mutex_lock(&msmfb->panel_init_lock);
DLOG(SUSPEND_RESUME, "turning on panel\n");
if (msmfb->sleeping == UPDATING) {
if (panel->unblank(panel)) {
printk(KERN_INFO "msmfb: panel unblank failed,"
"not starting drawing\n");
goto error;
}
spin_lock_irqsave(&msmfb->update_lock, irq_flags);
msmfb->sleeping = AWAKE;
wake_up(&msmfb->frame_wq);
spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
}
error:
mutex_unlock(&msmfb->panel_init_lock);
}
static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
if ((var->xres != info->var.xres) ||
(var->yres != info->var.yres) ||
(var->xres_virtual != info->var.xres_virtual) ||
(var->yres_virtual != info->var.yres_virtual) ||
(var->xoffset != info->var.xoffset) ||
(var->bits_per_pixel != info->var.bits_per_pixel) ||
(var->grayscale != info->var.grayscale))
return -EINVAL;
return 0;
}
int msmfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{
struct msmfb_info *msmfb = info->par;
struct msm_panel_data *panel = msmfb->panel;
/* "UPDT" */
if ((panel->caps & MSMFB_CAP_PARTIAL_UPDATES) &&
(var->reserved[0] == 0x54445055)) {
msmfb_pan_update(info, var->reserved[1] & 0xffff,
var->reserved[1] >> 16,
var->reserved[2] & 0xffff,
var->reserved[2] >> 16, var->yoffset, 1);
} else {
msmfb_pan_update(info, 0, 0, info->var.xres, info->var.yres,
var->yoffset, 1);
}
return 0;
}
static void msmfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
cfb_fillrect(p, rect);
msmfb_update(p, rect->dx, rect->dy, rect->dx + rect->width,
rect->dy + rect->height);
}
static void msmfb_copyarea(struct fb_info *p, const struct fb_copyarea *area)
{
cfb_copyarea(p, area);
msmfb_update(p, area->dx, area->dy, area->dx + area->width,
area->dy + area->height);
}
static void msmfb_imageblit(struct fb_info *p, const struct fb_image *image)
{
cfb_imageblit(p, image);
msmfb_update(p, image->dx, image->dy, image->dx + image->width,
image->dy + image->height);
}
static int msmfb_blit(struct fb_info *info,
void __user *p)
{
struct mdp_blit_req req;
struct mdp_blit_req_list req_list;
int i;
int ret;
if (copy_from_user(&req_list, p, sizeof(req_list)))
return -EFAULT;
for (i = 0; i < req_list.count; i++) {
struct mdp_blit_req_list *list =
(struct mdp_blit_req_list *)p;
if (copy_from_user(&req, &list->req[i], sizeof(req)))
return -EFAULT;
ret = mdp->blit(mdp, info, &req);
if (ret)
return ret;
}
return 0;
}
DEFINE_MUTEX(mdp_ppp_lock);
static int msmfb_ioctl(struct fb_info *p, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int ret;
switch (cmd) {
case MSMFB_GRP_DISP:
mdp->set_grp_disp(mdp, arg);
break;
case MSMFB_BLIT:
ret = msmfb_blit(p, argp);
if (ret)
return ret;
break;
default:
printk(KERN_INFO "msmfb unknown ioctl: %d\n", cmd);
return -EINVAL;
}
return 0;
}
static struct fb_ops msmfb_ops = {
.owner = THIS_MODULE,
.fb_open = msmfb_open,
.fb_release = msmfb_release,
.fb_check_var = msmfb_check_var,
.fb_pan_display = msmfb_pan_display,
.fb_fillrect = msmfb_fillrect,
.fb_copyarea = msmfb_copyarea,
.fb_imageblit = msmfb_imageblit,
.fb_ioctl = msmfb_ioctl,
};
static unsigned PP[16];
#define BITS_PER_PIXEL 16
static void setup_fb_info(struct msmfb_info *msmfb)
{
struct fb_info *fb_info = msmfb->fb;
int r;
/* finish setting up the fb_info struct */
strncpy(fb_info->fix.id, "msmfb", 16);
fb_info->fix.ypanstep = 1;
fb_info->fbops = &msmfb_ops;
fb_info->flags = FBINFO_DEFAULT;
fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
fb_info->fix.line_length = msmfb->xres * 2;
fb_info->var.xres = msmfb->xres;
fb_info->var.yres = msmfb->yres;
fb_info->var.width = msmfb->panel->fb_data->width;
fb_info->var.height = msmfb->panel->fb_data->height;
fb_info->var.xres_virtual = msmfb->xres;
fb_info->var.yres_virtual = msmfb->yres * 2;
fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
fb_info->var.accel_flags = 0;
fb_info->var.yoffset = 0;
if (msmfb->panel->caps & MSMFB_CAP_PARTIAL_UPDATES) {
/*
* Set the param in the fixed screen, so userspace can't
* change it. This will be used to check for the
* capability.
*/
fb_info->fix.reserved[0] = 0x5444;
fb_info->fix.reserved[1] = 0x5055;
/*
* This preloads the value so that if userspace doesn't
* change it, it will be a full update
*/
fb_info->var.reserved[0] = 0x54445055;
fb_info->var.reserved[1] = 0;
fb_info->var.reserved[2] = (uint16_t)msmfb->xres |
((uint32_t)msmfb->yres << 16);
}
fb_info->var.red.offset = 11;
fb_info->var.red.length = 5;
fb_info->var.red.msb_right = 0;
fb_info->var.green.offset = 5;
fb_info->var.green.length = 6;
fb_info->var.green.msb_right = 0;
fb_info->var.blue.offset = 0;
fb_info->var.blue.length = 5;
fb_info->var.blue.msb_right = 0;
r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
fb_info->pseudo_palette = PP;
PP[0] = 0;
for (r = 1; r < 16; r++)
PP[r] = 0xffffffff;
}
static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
{
struct fb_info *fb = msmfb->fb;
struct resource *resource;
unsigned long size = msmfb->xres * msmfb->yres *
(BITS_PER_PIXEL >> 3) * 2;
unsigned char *fbram;
/* board file might have attached a resource describing an fb */
resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!resource)
return -EINVAL;
/* check the resource is large enough to fit the fb */
if (resource->end - resource->start < size) {
printk(KERN_ERR "allocated resource is too small for "
"fb\n");
return -ENOMEM;
}
fb->fix.smem_start = resource->start;
fb->fix.smem_len = resource_size(resource);
fbram = ioremap(resource->start, resource_size(resource));
if (fbram == NULL) {
printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
return -ENOMEM;
}
fb->screen_base = fbram;
return 0;
}
static int msmfb_probe(struct platform_device *pdev)
{
struct fb_info *fb;
struct msmfb_info *msmfb;
struct msm_panel_data *panel = pdev->dev.platform_data;
int ret;
if (!panel) {
pr_err("msmfb_probe: no platform data\n");
return -EINVAL;
}
if (!panel->fb_data) {
pr_err("msmfb_probe: no fb_data\n");
return -EINVAL;
}
fb = framebuffer_alloc(sizeof(struct msmfb_info), &pdev->dev);
if (!fb)
return -ENOMEM;
msmfb = fb->par;
msmfb->fb = fb;
msmfb->panel = panel;
msmfb->xres = panel->fb_data->xres;
msmfb->yres = panel->fb_data->yres;
ret = setup_fbmem(msmfb, pdev);
if (ret)
goto error_setup_fbmem;
setup_fb_info(msmfb);
spin_lock_init(&msmfb->update_lock);
mutex_init(&msmfb->panel_init_lock);
init_waitqueue_head(&msmfb->frame_wq);
INIT_WORK(&msmfb->resume_work, power_on_panel);
msmfb->black = devm_kzalloc(&pdev->dev,
msmfb->fb->var.bits_per_pixel*msmfb->xres,
GFP_KERNEL);
if (!msmfb->black) {
ret = -ENOMEM;
goto error_register_framebuffer;
}
printk(KERN_INFO "msmfb_probe() installing %d x %d panel\n",
msmfb->xres, msmfb->yres);
msmfb->dma_callback.func = msmfb_handle_dma_interrupt;
msmfb->vsync_callback.func = msmfb_handle_vsync_interrupt;
hrtimer_init(&msmfb->fake_vsync, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
msmfb->fake_vsync.function = msmfb_fake_vsync;
ret = register_framebuffer(fb);
if (ret)
goto error_register_framebuffer;
msmfb->sleeping = WAKING;
platform_set_drvdata(pdev, msmfb);
return 0;
error_register_framebuffer:
iounmap(fb->screen_base);
error_setup_fbmem:
framebuffer_release(msmfb->fb);
return ret;
}
static int msmfb_remove(struct platform_device *pdev)
{
struct msmfb_info *msmfb;
msmfb = platform_get_drvdata(pdev);
unregister_framebuffer(msmfb->fb);
iounmap(msmfb->fb->screen_base);
framebuffer_release(msmfb->fb);
return 0;
}
static struct platform_driver msm_panel_driver = {
/* need to write remove */
.probe = msmfb_probe,
.remove = msmfb_remove,
.driver = {.name = "msm_panel"},
};
static int msmfb_add_mdp_device(struct device *dev,
struct class_interface *class_intf)
{
/* might need locking if mulitple mdp devices */
if (mdp)
return 0;
mdp = container_of(dev, struct mdp_device, dev);
return platform_driver_register(&msm_panel_driver);
}
static void msmfb_remove_mdp_device(struct device *dev,
struct class_interface *class_intf)
{
/* might need locking if mulitple mdp devices */
if (dev != &mdp->dev)
return;
platform_driver_unregister(&msm_panel_driver);
mdp = NULL;
}
static struct class_interface msm_fb_interface = {
.add_dev = &msmfb_add_mdp_device,
.remove_dev = &msmfb_remove_mdp_device,
};
static int __init msmfb_init(void)
{
return register_mdp_client(&msm_fb_interface);
}
module_init(msmfb_init);
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册