Merge branch 'for-paul' of git://gitorious.org/linux-omap-dss2/linux

Conflicts:
	drivers/video/omap2/dss/dsi.c
	drivers/video/omap2/dss/dss_features.c
	drivers/video/omap2/dss/dss_features.h

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
Paul Mundt 2011-05-24 15:35:54 +09:00
commit a6b5825aa7
55 changed files with 5099 additions and 2112 deletions

View File

@ -37,8 +37,8 @@
#include <plat/common.h>
#include <plat/dma.h>
#include <plat/gpmc.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/gpmc-smc91x.h>

View File

@ -36,7 +36,7 @@
#include <plat/usb.h>
#include <plat/mmc.h>
#include <plat/omap4-keypad.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "mux.h"
#include "hsmmc.h"
@ -680,6 +680,15 @@ static struct omap_dss_device sdp4430_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
.type = OMAP_DISPLAY_TYPE_HDMI,
.clocks = {
.dispc = {
.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
},
.hdmi = {
.regn = 15,
.regm2 = 1,
},
},
.platform_enable = sdp4430_panel_enable_hdmi,
.platform_disable = sdp4430_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,

View File

@ -34,8 +34,8 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include "mux.h"
#include "control.h"

View File

@ -45,8 +45,8 @@
#include <plat/nand.h>
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/mcspi.h>
#include <mach/hardware.h>

View File

@ -45,8 +45,8 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>

View File

@ -31,8 +31,8 @@
#include <plat/common.h>
#include <plat/gpmc.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/onenand.h>
#include "mux.h"

View File

@ -41,8 +41,8 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>

View File

@ -44,8 +44,8 @@
#include <plat/usb.h>
#include <plat/common.h>
#include <plat/mcspi.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include "mux.h"
#include "sdram-micron-mt46h32m32lf-6.h"

View File

@ -46,7 +46,7 @@
#include <mach/hardware.h>
#include <plat/mcspi.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/nand.h>
#include "mux.h"

View File

@ -39,8 +39,8 @@
#include <plat/gpmc.h>
#include <plat/nand.h>
#include <plat/usb.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <plat/mcspi.h>
#include <linux/input/matrix_keypad.h>

View File

@ -34,13 +34,13 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/board.h>
#include <plat/common.h>
#include <plat/usb.h>
#include <plat/mmc.h>
#include <plat/panel-generic-dpi.h>
#include <video/omap-panel-generic-dpi.h>
#include "timer-gp.h"
#include "hsmmc.h"

View File

@ -43,8 +43,8 @@
#include <plat/board.h>
#include <plat/common.h>
#include <plat/display.h>
#include <plat/panel-generic-dpi.h>
#include <video/omapdss.h>
#include <video/omap-panel-generic-dpi.h>
#include <mach/gpio.h>
#include <plat/gpmc.h>
#include <mach/hardware.h>

View File

@ -15,7 +15,7 @@
#include <linux/spi/spi.h>
#include <linux/mm.h>
#include <asm/mach-types.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/vram.h>
#include <plat/mcspi.h>

View File

@ -15,7 +15,7 @@
#include <linux/i2c/twl.h>
#include <linux/spi/spi.h>
#include <plat/mcspi.h>
#include <plat/display.h>
#include <video/omapdss.h>
#define LCD_PANEL_RESET_GPIO_PROD 96
#define LCD_PANEL_RESET_GPIO_PILOT 55

View File

@ -22,7 +22,7 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
@ -56,37 +56,58 @@ static bool opt_clock_available(const char *clk_role)
return false;
}
struct omap_dss_hwmod_data {
const char *oh_name;
const char *dev_name;
const int id;
};
static const struct omap_dss_hwmod_data omap2_dss_hwmod_data[] __initdata = {
{ "dss_core", "omapdss_dss", -1 },
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
{ "dss_venc", "omapdss_venc", -1 },
};
static const struct omap_dss_hwmod_data omap3_dss_hwmod_data[] __initdata = {
{ "dss_core", "omapdss_dss", -1 },
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
{ "dss_venc", "omapdss_venc", -1 },
{ "dss_dsi1", "omapdss_dsi1", -1 },
};
static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
{ "dss_core", "omapdss_dss", -1 },
{ "dss_dispc", "omapdss_dispc", -1 },
{ "dss_rfbi", "omapdss_rfbi", -1 },
{ "dss_venc", "omapdss_venc", -1 },
{ "dss_dsi1", "omapdss_dsi1", -1 },
{ "dss_dsi2", "omapdss_dsi2", -1 },
{ "dss_hdmi", "omapdss_hdmi", -1 },
};
int __init omap_display_init(struct omap_dss_board_info *board_data)
{
int r = 0;
struct omap_hwmod *oh;
struct omap_device *od;
int i;
int i, oh_count;
struct omap_display_platform_data pdata;
/*
* omap: valid DSS hwmod names
* omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc
* omap3,4: dss_dsi1
* omap4: dss_dsi2, dss_hdmi
*/
char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc",
"dss_dsi1", "dss_dsi2", "dss_hdmi" };
char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi",
"omapdss_venc", "omapdss_dsi1", "omapdss_dsi2",
"omapdss_hdmi" };
int oh_count;
const struct omap_dss_hwmod_data *curr_dss_hwmod;
memset(&pdata, 0, sizeof(pdata));
if (cpu_is_omap24xx())
oh_count = ARRAY_SIZE(oh_name) - 3;
/* last 3 hwmod dev in oh_name are not available for omap2 */
else if (cpu_is_omap44xx())
oh_count = ARRAY_SIZE(oh_name);
else
oh_count = ARRAY_SIZE(oh_name) - 2;
/* last 2 hwmod dev in oh_name are not available for omap3 */
if (cpu_is_omap24xx()) {
curr_dss_hwmod = omap2_dss_hwmod_data;
oh_count = ARRAY_SIZE(omap2_dss_hwmod_data);
} else if (cpu_is_omap34xx()) {
curr_dss_hwmod = omap3_dss_hwmod_data;
oh_count = ARRAY_SIZE(omap3_dss_hwmod_data);
} else {
curr_dss_hwmod = omap4_dss_hwmod_data;
oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
}
/* opt_clks are always associated with dss hwmod */
oh_core = omap_hwmod_lookup("dss_core");
@ -100,19 +121,21 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
pdata.opt_clock_available = opt_clock_available;
for (i = 0; i < oh_count; i++) {
oh = omap_hwmod_lookup(oh_name[i]);
oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
if (!oh) {
pr_err("Could not look up %s\n", oh_name[i]);
pr_err("Could not look up %s\n",
curr_dss_hwmod[i].oh_name);
return -ENODEV;
}
od = omap_device_build(dev_name[i], -1, oh, &pdata,
od = omap_device_build(curr_dss_hwmod[i].dev_name,
curr_dss_hwmod[i].id, oh, &pdata,
sizeof(struct omap_display_platform_data),
omap_dss_latency,
ARRAY_SIZE(omap_dss_latency), 0);
if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
oh_name[i]))
curr_dss_hwmod[i].oh_name))
return -ENODEV;
}
omap_display_device.dev.platform_data = board_data;

View File

@ -1,7 +1,7 @@
/*
* Defines for zoom boards
*/
#include <plat/display.h>
#include <video/omapdss.h>
#define ZOOM_NAND_CS 0

View File

@ -47,7 +47,7 @@
#include <plat/dma.h>
#include <plat/vram.h>
#include <plat/vrfb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "omap_voutlib.h"
#include "omap_voutdef.h"

View File

@ -11,7 +11,7 @@
#ifndef OMAP_VOUTDEF_H
#define OMAP_VOUTDEF_H
#include <plat/display.h>
#include <video/omapdss.h>
#define YUYV_BPP 2
#define RGB565_BPP 2

View File

@ -922,14 +922,14 @@ static int get_dss_clocks(void)
return PTR_ERR(dispc.dss_ick);
}
dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "dss1_fck");
dispc.dss1_fck = clk_get(&dispc.fbdev->dssdev->dev, "fck");
if (IS_ERR(dispc.dss1_fck)) {
dev_err(dispc.fbdev->dev, "can't get dss1_fck\n");
clk_put(dispc.dss_ick);
return PTR_ERR(dispc.dss1_fck);
}
dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_fck");
dispc.dss_54m_fck = clk_get(&dispc.fbdev->dssdev->dev, "tv_clk");
if (IS_ERR(dispc.dss_54m_fck)) {
dev_err(dispc.fbdev->dev, "can't get tv_fck\n");
clk_put(dispc.dss_ick);

View File

@ -90,7 +90,7 @@ static void omapdss_release(struct device *dev)
/* dummy device for clocks */
static struct platform_device omapdss_device = {
.name = "omapdss",
.name = "omapdss_dss",
.id = -1,
.dev = {
.release = omapdss_release,

View File

@ -90,7 +90,7 @@ static int rfbi_get_clocks(void)
return PTR_ERR(rfbi.dss_ick);
}
rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "dss1_fck");
rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck");
if (IS_ERR(rfbi.dss1_fck)) {
dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n");
clk_put(rfbi.dss_ick);

View File

@ -1,6 +1,6 @@
obj-$(CONFIG_OMAP2_VRAM) += vram.o
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-y += dss/
obj-y += omapfb/
obj-$(CONFIG_OMAP2_DSS) += dss/
obj-$(CONFIG_FB_OMAP2) += omapfb/
obj-y += displays/

View File

@ -30,7 +30,7 @@
#include <linux/backlight.h>
#include <linux/fb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#define MIPID_CMD_READ_DISP_ID 0x04
#define MIPID_CMD_READ_RED 0x06

View File

@ -33,8 +33,9 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <video/omapdss.h>
#include <plat/panel-generic-dpi.h>
#include <video/omap-panel-generic-dpi.h>
struct panel_config {
struct omap_video_timings timings;
@ -181,6 +182,56 @@ static struct panel_config generic_dpi_panels[] = {
.power_off_delay = 0,
.name = "samsung_lte430wq_f0c",
},
/* Seiko 70WVW1TZ3Z3 */
{
{
.x_res = 800,
.y_res = 480,
.pixel_clock = 33000,
.hsw = 128,
.hfp = 10,
.hbp = 10,
.vsw = 2,
.vfp = 4,
.vbp = 11,
},
.acbi = 0x0,
.acb = 0x0,
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS,
.power_on_delay = 0,
.power_off_delay = 0,
.name = "seiko_70wvw1tz3",
},
/* Powertip PH480272T */
{
{
.x_res = 480,
.y_res = 272,
.pixel_clock = 9000,
.hsw = 40,
.hfp = 2,
.hbp = 2,
.vsw = 10,
.vfp = 2,
.vbp = 2,
},
.acbi = 0x0,
.acb = 0x0,
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO,
.power_on_delay = 0,
.power_off_delay = 0,
.name = "powertip_ph480272t",
},
};
struct panel_drv_data {
@ -285,7 +336,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev)
return 0;
}
static void generic_dpi_panel_remove(struct omap_dss_device *dssdev)
static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev)
{
struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
@ -358,7 +409,7 @@ static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
static struct omap_dss_driver dpi_driver = {
.probe = generic_dpi_panel_probe,
.remove = generic_dpi_panel_remove,
.remove = __exit_p(generic_dpi_panel_remove),
.enable = generic_dpi_panel_enable,
.disable = generic_dpi_panel_disable,

View File

@ -21,7 +21,7 @@
#include <linux/spi/spi.h>
#include <linux/mutex.h>
#include <plat/display.h>
#include <video/omapdss.h>
struct lb035q02_data {
struct mutex lock;

View File

@ -22,7 +22,7 @@
#include <linux/backlight.h>
#include <linux/fb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#define LCD_XRES 800
#define LCD_YRES 480

View File

@ -25,7 +25,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <plat/display.h>
#include <video/omapdss.h>
struct sharp_data {
struct backlight_device *bl;
@ -120,7 +120,7 @@ static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
return 0;
}
static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev)
{
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
struct backlight_device *bl = sd->bl;
@ -205,7 +205,7 @@ static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
static struct omap_dss_driver sharp_ls_driver = {
.probe = sharp_ls_panel_probe,
.remove = sharp_ls_panel_remove,
.remove = __exit_p(sharp_ls_panel_remove),
.enable = sharp_ls_panel_enable,
.disable = sharp_ls_panel_disable,

View File

@ -33,8 +33,8 @@
#include <linux/regulator/consumer.h>
#include <linux/mutex.h>
#include <plat/display.h>
#include <plat/nokia-dsi-panel.h>
#include <video/omapdss.h>
#include <video/omap-panel-nokia-dsi.h>
/* DSI Virtual channel. Hardcoded for now. */
#define TCH 0
@ -63,12 +63,12 @@
#define DCS_GET_ID2 0xdb
#define DCS_GET_ID3 0xdc
#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
static irqreturn_t taal_te_isr(int irq, void *data);
static void taal_te_timeout_work_callback(struct work_struct *work);
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
static int taal_panel_reset(struct omap_dss_device *dssdev);
struct panel_regulator {
struct regulator *regulator;
const char *name;
@ -229,8 +229,14 @@ struct taal_data {
bool intro_printed;
struct workqueue_struct *esd_wq;
struct workqueue_struct *workqueue;
struct delayed_work esd_work;
unsigned esd_interval;
bool ulps_enabled;
unsigned ulps_timeout;
struct delayed_work ulps_work;
struct panel_config *panel_config;
};
@ -242,6 +248,7 @@ static inline struct nokia_dsi_panel_data
}
static void taal_esd_work(struct work_struct *work);
static void taal_ulps_work(struct work_struct *work);
static void hw_guard_start(struct taal_data *td, int guard_msec)
{
@ -264,7 +271,7 @@ static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data)
int r;
u8 buf[1];
r = dsi_vc_dcs_read(td->channel, dcs_cmd, buf, 1);
r = dsi_vc_dcs_read(td->dssdev, td->channel, dcs_cmd, buf, 1);
if (r < 0)
return r;
@ -276,7 +283,7 @@ static int taal_dcs_read_1(struct taal_data *td, u8 dcs_cmd, u8 *data)
static int taal_dcs_write_0(struct taal_data *td, u8 dcs_cmd)
{
return dsi_vc_dcs_write(td->channel, &dcs_cmd, 1);
return dsi_vc_dcs_write(td->dssdev, td->channel, &dcs_cmd, 1);
}
static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param)
@ -284,7 +291,7 @@ static int taal_dcs_write_1(struct taal_data *td, u8 dcs_cmd, u8 param)
u8 buf[2];
buf[0] = dcs_cmd;
buf[1] = param;
return dsi_vc_dcs_write(td->channel, buf, 2);
return dsi_vc_dcs_write(td->dssdev, td->channel, buf, 2);
}
static int taal_sleep_in(struct taal_data *td)
@ -296,7 +303,7 @@ static int taal_sleep_in(struct taal_data *td)
hw_guard_wait(td);
cmd = DCS_SLEEP_IN;
r = dsi_vc_dcs_write_nosync(td->channel, &cmd, 1);
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, &cmd, 1);
if (r)
return r;
@ -402,7 +409,7 @@ static int taal_set_update_window(struct taal_data *td,
buf[3] = (x2 >> 8) & 0xff;
buf[4] = (x2 >> 0) & 0xff;
r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf));
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
if (r)
return r;
@ -412,15 +419,132 @@ static int taal_set_update_window(struct taal_data *td,
buf[3] = (y2 >> 8) & 0xff;
buf[4] = (y2 >> 0) & 0xff;
r = dsi_vc_dcs_write_nosync(td->channel, buf, sizeof(buf));
r = dsi_vc_dcs_write_nosync(td->dssdev, td->channel, buf, sizeof(buf));
if (r)
return r;
dsi_vc_send_bta_sync(td->channel);
dsi_vc_send_bta_sync(td->dssdev, td->channel);
return r;
}
static void taal_queue_esd_work(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
if (td->esd_interval > 0)
queue_delayed_work(td->workqueue, &td->esd_work,
msecs_to_jiffies(td->esd_interval));
}
static void taal_cancel_esd_work(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
cancel_delayed_work(&td->esd_work);
}
static void taal_queue_ulps_work(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
if (td->ulps_timeout > 0)
queue_delayed_work(td->workqueue, &td->ulps_work,
msecs_to_jiffies(td->ulps_timeout));
}
static void taal_cancel_ulps_work(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
cancel_delayed_work(&td->ulps_work);
}
static int taal_enter_ulps(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
if (td->ulps_enabled)
return 0;
taal_cancel_ulps_work(dssdev);
r = _taal_enable_te(dssdev, false);
if (r)
goto err;
disable_irq(gpio_to_irq(panel_data->ext_te_gpio));
omapdss_dsi_display_disable(dssdev, false, true);
td->ulps_enabled = true;
return 0;
err:
dev_err(&dssdev->dev, "enter ULPS failed");
taal_panel_reset(dssdev);
td->ulps_enabled = false;
taal_queue_ulps_work(dssdev);
return r;
}
static int taal_exit_ulps(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
if (!td->ulps_enabled)
return 0;
r = omapdss_dsi_display_enable(dssdev);
if (r)
goto err;
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
r = _taal_enable_te(dssdev, true);
if (r)
goto err;
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
taal_queue_ulps_work(dssdev);
td->ulps_enabled = false;
return 0;
err:
dev_err(&dssdev->dev, "exit ULPS failed");
r = taal_panel_reset(dssdev);
enable_irq(gpio_to_irq(panel_data->ext_te_gpio));
td->ulps_enabled = false;
taal_queue_ulps_work(dssdev);
return r;
}
static int taal_wake_up(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
if (td->ulps_enabled)
return taal_exit_ulps(dssdev);
taal_cancel_ulps_work(dssdev);
taal_queue_ulps_work(dssdev);
return 0;
}
static int taal_bl_update_status(struct backlight_device *dev)
{
struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev);
@ -441,9 +565,13 @@ static int taal_bl_update_status(struct backlight_device *dev)
if (td->use_dsi_bl) {
if (td->enabled) {
dsi_bus_lock();
r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
dsi_bus_unlock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (!r)
r = taal_dcs_write_1(td, DCS_BRIGHTNESS, level);
dsi_bus_unlock(dssdev);
} else {
r = 0;
}
@ -504,9 +632,13 @@ static ssize_t taal_num_errors_show(struct device *dev,
mutex_lock(&td->lock);
if (td->enabled) {
dsi_bus_lock();
r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
dsi_bus_unlock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (!r)
r = taal_dcs_read_1(td, DCS_READ_NUM_ERRORS, &errors);
dsi_bus_unlock(dssdev);
} else {
r = -ENODEV;
}
@ -530,9 +662,13 @@ static ssize_t taal_hw_revision_show(struct device *dev,
mutex_lock(&td->lock);
if (td->enabled) {
dsi_bus_lock();
r = taal_get_id(td, &id1, &id2, &id3);
dsi_bus_unlock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (!r)
r = taal_get_id(td, &id1, &id2, &id3);
dsi_bus_unlock(dssdev);
} else {
r = -ENODEV;
}
@ -579,6 +715,7 @@ static ssize_t store_cabc_mode(struct device *dev,
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
int i;
int r;
for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
if (sysfs_streq(cabc_modes[i], buf))
@ -591,10 +728,19 @@ static ssize_t store_cabc_mode(struct device *dev,
mutex_lock(&td->lock);
if (td->enabled) {
dsi_bus_lock();
if (!td->cabc_broken)
taal_dcs_write_1(td, DCS_WRITE_CABC, i);
dsi_bus_unlock();
dsi_bus_lock(dssdev);
if (!td->cabc_broken) {
r = taal_wake_up(dssdev);
if (r)
goto err;
r = taal_dcs_write_1(td, DCS_WRITE_CABC, i);
if (r)
goto err;
}
dsi_bus_unlock(dssdev);
}
td->cabc_mode = i;
@ -602,6 +748,10 @@ static ssize_t store_cabc_mode(struct device *dev,
mutex_unlock(&td->lock);
return count;
err:
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return r;
}
static ssize_t show_cabc_available_modes(struct device *dev,
@ -620,18 +770,161 @@ static ssize_t show_cabc_available_modes(struct device *dev,
return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
}
static ssize_t taal_store_esd_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned long t;
int r;
r = strict_strtoul(buf, 10, &t);
if (r)
return r;
mutex_lock(&td->lock);
taal_cancel_esd_work(dssdev);
td->esd_interval = t;
if (td->enabled)
taal_queue_esd_work(dssdev);
mutex_unlock(&td->lock);
return count;
}
static ssize_t taal_show_esd_interval(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned t;
mutex_lock(&td->lock);
t = td->esd_interval;
mutex_unlock(&td->lock);
return snprintf(buf, PAGE_SIZE, "%u\n", t);
}
static ssize_t taal_store_ulps(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned long t;
int r;
r = strict_strtoul(buf, 10, &t);
if (r)
return r;
mutex_lock(&td->lock);
if (td->enabled) {
dsi_bus_lock(dssdev);
if (t)
r = taal_enter_ulps(dssdev);
else
r = taal_wake_up(dssdev);
dsi_bus_unlock(dssdev);
}
mutex_unlock(&td->lock);
if (r)
return r;
return count;
}
static ssize_t taal_show_ulps(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned t;
mutex_lock(&td->lock);
t = td->ulps_enabled;
mutex_unlock(&td->lock);
return snprintf(buf, PAGE_SIZE, "%u\n", t);
}
static ssize_t taal_store_ulps_timeout(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned long t;
int r;
r = strict_strtoul(buf, 10, &t);
if (r)
return r;
mutex_lock(&td->lock);
td->ulps_timeout = t;
if (td->enabled) {
/* taal_wake_up will restart the timer */
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
dsi_bus_unlock(dssdev);
}
mutex_unlock(&td->lock);
if (r)
return r;
return count;
}
static ssize_t taal_show_ulps_timeout(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
unsigned t;
mutex_lock(&td->lock);
t = td->ulps_timeout;
mutex_unlock(&td->lock);
return snprintf(buf, PAGE_SIZE, "%u\n", t);
}
static DEVICE_ATTR(num_dsi_errors, S_IRUGO, taal_num_errors_show, NULL);
static DEVICE_ATTR(hw_revision, S_IRUGO, taal_hw_revision_show, NULL);
static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
show_cabc_mode, store_cabc_mode);
static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
show_cabc_available_modes, NULL);
static DEVICE_ATTR(esd_interval, S_IRUGO | S_IWUSR,
taal_show_esd_interval, taal_store_esd_interval);
static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
taal_show_ulps, taal_store_ulps);
static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
taal_show_ulps_timeout, taal_store_ulps_timeout);
static struct attribute *taal_attrs[] = {
&dev_attr_num_dsi_errors.attr,
&dev_attr_hw_revision.attr,
&dev_attr_cabc_mode.attr,
&dev_attr_cabc_available_modes.attr,
&dev_attr_esd_interval.attr,
&dev_attr_ulps.attr,
&dev_attr_ulps_timeout.attr,
NULL,
};
@ -700,6 +993,9 @@ static int taal_probe(struct omap_dss_device *dssdev)
}
td->dssdev = dssdev;
td->panel_config = panel_config;
td->esd_interval = panel_data->esd_interval;
td->ulps_enabled = false;
td->ulps_timeout = panel_data->ulps_timeout;
mutex_init(&td->lock);
@ -710,13 +1006,14 @@ static int taal_probe(struct omap_dss_device *dssdev)
if (r)
goto err_reg;
td->esd_wq = create_singlethread_workqueue("taal_esd");
if (td->esd_wq == NULL) {
td->workqueue = create_singlethread_workqueue("taal_esd");
if (td->workqueue == NULL) {
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
r = -ENOMEM;
goto err_wq;
}
INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
INIT_DELAYED_WORK(&td->ulps_work, taal_ulps_work);
dev_set_drvdata(&dssdev->dev, td);
@ -734,8 +1031,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
props.max_brightness = 127;
props.type = BACKLIGHT_RAW;
bldev = backlight_device_register("taal", &dssdev->dev, dssdev,
&taal_bl_ops, &props);
bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev,
dssdev, &taal_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
goto err_bl;
@ -810,7 +1107,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
err_gpio:
backlight_device_unregister(bldev);
err_bl:
destroy_workqueue(td->esd_wq);
destroy_workqueue(td->workqueue);
err_wq:
free_regulators(panel_config->regulators, panel_config->num_regulators);
err_reg:
@ -819,7 +1116,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
return r;
}
static void taal_remove(struct omap_dss_device *dssdev)
static void __exit taal_remove(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
@ -841,8 +1138,9 @@ static void taal_remove(struct omap_dss_device *dssdev)
taal_bl_update_status(bldev);
backlight_device_unregister(bldev);
cancel_delayed_work(&td->esd_work);
destroy_workqueue(td->esd_wq);
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
destroy_workqueue(td->workqueue);
/* reset, to be sure that the panel is in a valid state */
taal_hw_reset(dssdev);
@ -867,7 +1165,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
omapdss_dsi_vc_enable_hs(td->channel, false);
omapdss_dsi_vc_enable_hs(dssdev, td->channel, false);
r = taal_sleep_out(td);
if (r)
@ -924,7 +1222,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
td->intro_printed = true;
}
omapdss_dsi_vc_enable_hs(td->channel, true);
omapdss_dsi_vc_enable_hs(dssdev, td->channel, true);
return 0;
err:
@ -932,7 +1230,7 @@ static int taal_power_on(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
omapdss_dsi_display_disable(dssdev);
omapdss_dsi_display_disable(dssdev, true, false);
err0:
return r;
}
@ -955,15 +1253,23 @@ static void taal_power_off(struct omap_dss_device *dssdev)
taal_hw_reset(dssdev);
}
omapdss_dsi_display_disable(dssdev);
omapdss_dsi_display_disable(dssdev, true, false);
td->enabled = 0;
}
static int taal_panel_reset(struct omap_dss_device *dssdev)
{
dev_err(&dssdev->dev, "performing LCD reset\n");
taal_power_off(dssdev);
taal_hw_reset(dssdev);
return taal_power_on(dssdev);
}
static int taal_enable(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "enable\n");
@ -975,18 +1281,16 @@ static int taal_enable(struct omap_dss_device *dssdev)
goto err;
}
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_power_on(dssdev);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
if (r)
goto err;
if (panel_data->use_esd_check)
queue_delayed_work(td->esd_wq, &td->esd_work,
TAAL_ESD_CHECK_PERIOD);
taal_queue_esd_work(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
@ -1007,14 +1311,17 @@ static void taal_disable(struct omap_dss_device *dssdev)
mutex_lock(&td->lock);
cancel_delayed_work(&td->esd_work);
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
dsi_bus_lock();
dsi_bus_lock(dssdev);
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
taal_wake_up(dssdev);
taal_power_off(dssdev);
}
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
@ -1035,13 +1342,16 @@ static int taal_suspend(struct omap_dss_device *dssdev)
goto err;
}
cancel_delayed_work(&td->esd_work);
taal_cancel_ulps_work(dssdev);
taal_cancel_esd_work(dssdev);
dsi_bus_lock();
dsi_bus_lock(dssdev);
taal_power_off(dssdev);
r = taal_wake_up(dssdev);
if (!r)
taal_power_off(dssdev);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
@ -1056,7 +1366,6 @@ static int taal_suspend(struct omap_dss_device *dssdev)
static int taal_resume(struct omap_dss_device *dssdev)
{
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
struct nokia_dsi_panel_data *panel_data = get_panel_data(dssdev);
int r;
dev_dbg(&dssdev->dev, "resume\n");
@ -1068,19 +1377,17 @@ static int taal_resume(struct omap_dss_device *dssdev)
goto err;
}
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_power_on(dssdev);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
if (r) {
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
} else {
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
if (panel_data->use_esd_check)
queue_delayed_work(td->esd_wq, &td->esd_work,
TAAL_ESD_CHECK_PERIOD);
taal_queue_esd_work(dssdev);
}
mutex_unlock(&td->lock);
@ -1095,7 +1402,7 @@ static void taal_framedone_cb(int err, void *data)
{
struct omap_dss_device *dssdev = data;
dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
}
static irqreturn_t taal_te_isr(int irq, void *data)
@ -1123,7 +1430,7 @@ static irqreturn_t taal_te_isr(int irq, void *data)
return IRQ_HANDLED;
err:
dev_err(&dssdev->dev, "start update failed\n");
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
return IRQ_HANDLED;
}
@ -1136,7 +1443,7 @@ static void taal_te_timeout_work_callback(struct work_struct *work)
dev_err(&dssdev->dev, "TE not received for 250ms!\n");
atomic_set(&td->do_update, 0);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
}
static int taal_update(struct omap_dss_device *dssdev,
@ -1149,7 +1456,11 @@ static int taal_update(struct omap_dss_device *dssdev,
dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
mutex_lock(&td->lock);
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (r)
goto err;
if (!td->enabled) {
r = 0;
@ -1184,7 +1495,7 @@ static int taal_update(struct omap_dss_device *dssdev,
mutex_unlock(&td->lock);
return 0;
err:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return r;
}
@ -1196,8 +1507,8 @@ static int taal_sync(struct omap_dss_device *dssdev)
dev_dbg(&dssdev->dev, "sync\n");
mutex_lock(&td->lock);
dsi_bus_lock();
dsi_bus_unlock();
dsi_bus_lock(dssdev);
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
dev_dbg(&dssdev->dev, "sync done\n");
@ -1235,9 +1546,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
if (td->te_enabled == enable)
goto end;
dsi_bus_lock();
dsi_bus_lock(dssdev);
if (td->enabled) {
r = taal_wake_up(dssdev);
if (r)
goto err;
r = _taal_enable_te(dssdev, enable);
if (r)
goto err;
@ -1245,13 +1560,13 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
td->te_enabled = enable;
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
end:
mutex_unlock(&td->lock);
return 0;
err:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return r;
@ -1281,9 +1596,13 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
if (td->rotate == rotate)
goto end;
dsi_bus_lock();
dsi_bus_lock(dssdev);
if (td->enabled) {
r = taal_wake_up(dssdev);
if (r)
goto err;
r = taal_set_addr_mode(td, rotate, td->mirror);
if (r)
goto err;
@ -1291,12 +1610,12 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
td->rotate = rotate;
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
end:
mutex_unlock(&td->lock);
return 0;
err:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return r;
}
@ -1325,8 +1644,12 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
if (td->mirror == enable)
goto end;
dsi_bus_lock();
dsi_bus_lock(dssdev);
if (td->enabled) {
r = taal_wake_up(dssdev);
if (r)
goto err;
r = taal_set_addr_mode(td, td->rotate, enable);
if (r)
goto err;
@ -1334,12 +1657,12 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
td->mirror = enable;
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
end:
mutex_unlock(&td->lock);
return 0;
err:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return r;
}
@ -1369,7 +1692,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
goto err1;
}
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (r)
goto err2;
r = taal_dcs_read_1(td, DCS_GET_ID1, &id1);
if (r)
@ -1381,11 +1708,11 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
if (r)
goto err2;
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
return 0;
err2:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
err1:
mutex_unlock(&td->lock);
return r;
@ -1415,7 +1742,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
dssdev->panel.timings.x_res *
dssdev->panel.timings.y_res * 3);
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (r)
goto err2;
/* plen 1 or 2 goes into short packet. until checksum error is fixed,
* use short packets. plen 32 works, but bigger packets seem to cause
@ -1427,7 +1758,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
taal_set_update_window(td, x, y, w, h);
r = dsi_vc_set_max_rx_packet_size(td->channel, plen);
r = dsi_vc_set_max_rx_packet_size(dssdev, td->channel, plen);
if (r)
goto err2;
@ -1435,7 +1766,7 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
u8 dcs_cmd = first ? 0x2e : 0x3e;
first = 0;
r = dsi_vc_dcs_read(td->channel, dcs_cmd,
r = dsi_vc_dcs_read(dssdev, td->channel, dcs_cmd,
buf + buf_used, size - buf_used);
if (r < 0) {
@ -1461,14 +1792,35 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
r = buf_used;
err3:
dsi_vc_set_max_rx_packet_size(td->channel, 1);
dsi_vc_set_max_rx_packet_size(dssdev, td->channel, 1);
err2:
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
err1:
mutex_unlock(&td->lock);
return r;
}
static void taal_ulps_work(struct work_struct *work)
{
struct taal_data *td = container_of(work, struct taal_data,
ulps_work.work);
struct omap_dss_device *dssdev = td->dssdev;
mutex_lock(&td->lock);
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !td->enabled) {
mutex_unlock(&td->lock);
return;
}
dsi_bus_lock(dssdev);
taal_enter_ulps(dssdev);
dsi_bus_unlock(dssdev);
mutex_unlock(&td->lock);
}
static void taal_esd_work(struct work_struct *work)
{
struct taal_data *td = container_of(work, struct taal_data,
@ -1485,7 +1837,13 @@ static void taal_esd_work(struct work_struct *work)
return;
}
dsi_bus_lock();
dsi_bus_lock(dssdev);
r = taal_wake_up(dssdev);
if (r) {
dev_err(&dssdev->dev, "failed to exit ULPS\n");
goto err;
}
r = taal_dcs_read_1(td, DCS_RDDSDR, &state1);
if (r) {
@ -1521,22 +1879,20 @@ static void taal_esd_work(struct work_struct *work)
goto err;
}
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
taal_queue_esd_work(dssdev);
mutex_unlock(&td->lock);
return;
err:
dev_err(&dssdev->dev, "performing LCD reset\n");
taal_power_off(dssdev);
taal_hw_reset(dssdev);
taal_power_on(dssdev);
taal_panel_reset(dssdev);
dsi_bus_unlock();
dsi_bus_unlock(dssdev);
queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
taal_queue_esd_work(dssdev);
mutex_unlock(&td->lock);
}
@ -1557,7 +1913,7 @@ static enum omap_dss_update_mode taal_get_update_mode(
static struct omap_dss_driver taal_driver = {
.probe = taal_probe,
.remove = taal_remove,
.remove = __exit_p(taal_remove),
.enable = taal_enable,
.disable = taal_disable,

View File

@ -17,7 +17,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <plat/display.h>
#include <video/omapdss.h>
#define TPO_R02_MODE(x) ((x) & 7)
#define TPO_R02_MODE_800x480 7
@ -144,13 +144,15 @@ static ssize_t tpo_td043_vmirror_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
long val;
int val;
int ret;
ret = strict_strtol(buf, 0, &val);
ret = kstrtoint(buf, 0, &val);
if (ret < 0)
return ret;
val = !!val;
ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
if (ret < 0)
return ret;
@ -175,7 +177,7 @@ static ssize_t tpo_td043_mode_store(struct device *dev,
long val;
int ret;
ret = strict_strtol(buf, 0, &val);
ret = kstrtol(buf, 0, &val);
if (ret != 0 || val & ~7)
return -EINVAL;

View File

@ -80,7 +80,7 @@ config OMAP2_DSS_SDI
config OMAP2_DSS_DSI
bool "DSI support"
depends on ARCH_OMAP3
depends on ARCH_OMAP3 || ARCH_OMAP4
default n
help
MIPI DSI (Display Serial Interface) support.
@ -90,14 +90,6 @@ config OMAP2_DSS_DSI
See http://www.mipi.org/ for DSI spesifications.
config OMAP2_DSS_USE_DSI_PLL
bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
default n
depends on OMAP2_DSS_DSI
help
Use DSI PLL to generate pixel clock. Currently only for DPI output.
DSI PLL can be used to generate higher and more precise pixel clocks.
config OMAP2_DSS_FAKE_VSYNC
bool "Fake VSYNC irq from manual update displays"
default n
@ -125,4 +117,27 @@ config OMAP2_DSS_MIN_FCK_PER_PCK
Max FCK is 173MHz, so this doesn't work if your PCK
is very high.
config OMAP2_DSS_SLEEP_BEFORE_RESET
bool "Sleep 50ms before DSS reset"
default y
help
For some unknown reason we may get SYNC_LOST errors from the display
subsystem at initialization time if we don't sleep before resetting
the DSS. See the source (dss.c) for more comments.
However, 50ms is quite long time to sleep, and with some
configurations the SYNC_LOST may never happen, so the sleep can
be disabled here.
config OMAP2_DSS_SLEEP_AFTER_VENC_RESET
bool "Sleep 20ms after VENC reset"
default y
help
There is a 20ms sleep after VENC reset which seemed to fix the
reset. The reason for the bug is unclear, and it's also unclear
on what platforms this happens.
This option enables the sleep, and is enabled by default. You can
disable the sleep if it doesn't cause problems on your platform.
endif

View File

@ -33,7 +33,7 @@
#include <linux/device.h>
#include <linux/regulator/consumer.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "dss.h"
#include "dss_features.h"
@ -54,6 +54,9 @@ unsigned int dss_debug;
module_param_named(debug, dss_debug, bool, 0644);
#endif
static int omap_dss_register_device(struct omap_dss_device *);
static void omap_dss_unregister_device(struct omap_dss_device *);
/* REGULATORS */
struct regulator *dss_get_vdds_dsi(void)
@ -124,8 +127,7 @@ static int dss_initialize_debugfs(void)
#endif
#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir,
&dsi_dump_irqs, &dss_debug_fops);
dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops);
#endif
debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
@ -137,8 +139,7 @@ static int dss_initialize_debugfs(void)
&rfbi_dump_regs, &dss_debug_fops);
#endif
#ifdef CONFIG_OMAP2_DSS_DSI
debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
&dsi_dump_regs, &dss_debug_fops);
dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops);
#endif
#ifdef CONFIG_OMAP2_DSS_VENC
debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
@ -480,7 +481,7 @@ static void omap_dss_dev_release(struct device *dev)
reset_device(dev, 0);
}
int omap_dss_register_device(struct omap_dss_device *dssdev)
static int omap_dss_register_device(struct omap_dss_device *dssdev)
{
static int dev_num;
@ -494,7 +495,7 @@ int omap_dss_register_device(struct omap_dss_device *dssdev)
return device_register(&dssdev->dev);
}
void omap_dss_unregister_device(struct omap_dss_device *dssdev)
static void omap_dss_unregister_device(struct omap_dss_device *dssdev)
{
device_unregister(&dssdev->dev);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,691 @@
/*
* linux/drivers/video/omap2/dss/dispc.h
*
* Copyright (C) 2011 Texas Instruments
* Author: Archit Taneja <archit@ti.com>
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __OMAP2_DISPC_REG_H
#define __OMAP2_DISPC_REG_H
/* DISPC common registers */
#define DISPC_REVISION 0x0000
#define DISPC_SYSCONFIG 0x0010
#define DISPC_SYSSTATUS 0x0014
#define DISPC_IRQSTATUS 0x0018
#define DISPC_IRQENABLE 0x001C
#define DISPC_CONTROL 0x0040
#define DISPC_CONFIG 0x0044
#define DISPC_CAPABLE 0x0048
#define DISPC_LINE_STATUS 0x005C
#define DISPC_LINE_NUMBER 0x0060
#define DISPC_GLOBAL_ALPHA 0x0074
#define DISPC_CONTROL2 0x0238
#define DISPC_CONFIG2 0x0620
#define DISPC_DIVISOR 0x0804
/* DISPC overlay registers */
#define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \
DISPC_BA0_OFFSET(n))
#define DISPC_OVL_BA1(n) (DISPC_OVL_BASE(n) + \
DISPC_BA1_OFFSET(n))
#define DISPC_OVL_BA0_UV(n) (DISPC_OVL_BASE(n) + \
DISPC_BA0_UV_OFFSET(n))
#define DISPC_OVL_BA1_UV(n) (DISPC_OVL_BASE(n) + \
DISPC_BA1_UV_OFFSET(n))
#define DISPC_OVL_POSITION(n) (DISPC_OVL_BASE(n) + \
DISPC_POS_OFFSET(n))
#define DISPC_OVL_SIZE(n) (DISPC_OVL_BASE(n) + \
DISPC_SIZE_OFFSET(n))
#define DISPC_OVL_ATTRIBUTES(n) (DISPC_OVL_BASE(n) + \
DISPC_ATTR_OFFSET(n))
#define DISPC_OVL_ATTRIBUTES2(n) (DISPC_OVL_BASE(n) + \
DISPC_ATTR2_OFFSET(n))
#define DISPC_OVL_FIFO_THRESHOLD(n) (DISPC_OVL_BASE(n) + \
DISPC_FIFO_THRESH_OFFSET(n))
#define DISPC_OVL_FIFO_SIZE_STATUS(n) (DISPC_OVL_BASE(n) + \
DISPC_FIFO_SIZE_STATUS_OFFSET(n))
#define DISPC_OVL_ROW_INC(n) (DISPC_OVL_BASE(n) + \
DISPC_ROW_INC_OFFSET(n))
#define DISPC_OVL_PIXEL_INC(n) (DISPC_OVL_BASE(n) + \
DISPC_PIX_INC_OFFSET(n))
#define DISPC_OVL_WINDOW_SKIP(n) (DISPC_OVL_BASE(n) + \
DISPC_WINDOW_SKIP_OFFSET(n))
#define DISPC_OVL_TABLE_BA(n) (DISPC_OVL_BASE(n) + \
DISPC_TABLE_BA_OFFSET(n))
#define DISPC_OVL_FIR(n) (DISPC_OVL_BASE(n) + \
DISPC_FIR_OFFSET(n))
#define DISPC_OVL_FIR2(n) (DISPC_OVL_BASE(n) + \
DISPC_FIR2_OFFSET(n))
#define DISPC_OVL_PICTURE_SIZE(n) (DISPC_OVL_BASE(n) + \
DISPC_PIC_SIZE_OFFSET(n))
#define DISPC_OVL_ACCU0(n) (DISPC_OVL_BASE(n) + \
DISPC_ACCU0_OFFSET(n))
#define DISPC_OVL_ACCU1(n) (DISPC_OVL_BASE(n) + \
DISPC_ACCU1_OFFSET(n))
#define DISPC_OVL_ACCU2_0(n) (DISPC_OVL_BASE(n) + \
DISPC_ACCU2_0_OFFSET(n))
#define DISPC_OVL_ACCU2_1(n) (DISPC_OVL_BASE(n) + \
DISPC_ACCU2_1_OFFSET(n))
#define DISPC_OVL_FIR_COEF_H(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_H_OFFSET(n, i))
#define DISPC_OVL_FIR_COEF_HV(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_HV_OFFSET(n, i))
#define DISPC_OVL_FIR_COEF_H2(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_H2_OFFSET(n, i))
#define DISPC_OVL_FIR_COEF_HV2(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_HV2_OFFSET(n, i))
#define DISPC_OVL_CONV_COEF(n, i) (DISPC_OVL_BASE(n) + \
DISPC_CONV_COEF_OFFSET(n, i))
#define DISPC_OVL_FIR_COEF_V(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_V_OFFSET(n, i))
#define DISPC_OVL_FIR_COEF_V2(n, i) (DISPC_OVL_BASE(n) + \
DISPC_FIR_COEF_V2_OFFSET(n, i))
#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
DISPC_PRELOAD_OFFSET(n))
/* DISPC manager/channel specific registers */
static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x004C;
case OMAP_DSS_CHANNEL_DIGIT:
return 0x0050;
case OMAP_DSS_CHANNEL_LCD2:
return 0x03AC;
default:
BUG();
}
}
static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0054;
case OMAP_DSS_CHANNEL_DIGIT:
return 0x0058;
case OMAP_DSS_CHANNEL_LCD2:
return 0x03B0;
default:
BUG();
}
}
static inline u16 DISPC_TIMING_H(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0064;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x0400;
default:
BUG();
}
}
static inline u16 DISPC_TIMING_V(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0068;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x0404;
default:
BUG();
}
}
static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x006C;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x0408;
default:
BUG();
}
}
static inline u16 DISPC_DIVISORo(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0070;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x040C;
default:
BUG();
}
}
/* Named as DISPC_SIZE_LCD, DISPC_SIZE_DIGIT and DISPC_SIZE_LCD2 in TRM */
static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x007C;
case OMAP_DSS_CHANNEL_DIGIT:
return 0x0078;
case OMAP_DSS_CHANNEL_LCD2:
return 0x03CC;
default:
BUG();
}
}
static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x01D4;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03C0;
default:
BUG();
}
}
static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x01D8;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03C4;
default:
BUG();
}
}
static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x01DC;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03C8;
default:
BUG();
}
}
static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0220;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03BC;
default:
BUG();
}
}
static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0224;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03B8;
default:
BUG();
}
}
static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
{
switch (channel) {
case OMAP_DSS_CHANNEL_LCD:
return 0x0228;
case OMAP_DSS_CHANNEL_DIGIT:
BUG();
case OMAP_DSS_CHANNEL_LCD2:
return 0x03B4;
default:
BUG();
}
}
/* DISPC overlay register base addresses */
static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0080;
case OMAP_DSS_VIDEO1:
return 0x00BC;
case OMAP_DSS_VIDEO2:
return 0x014C;
default:
BUG();
}
}
/* DISPC overlay register offsets */
static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0000;
default:
BUG();
}
}
static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0004;
default:
BUG();
}
}
static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0544;
case OMAP_DSS_VIDEO2:
return 0x04BC;
default:
BUG();
}
}
static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0548;
case OMAP_DSS_VIDEO2:
return 0x04C0;
default:
BUG();
}
}
static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0008;
default:
BUG();
}
}
static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x000C;
default:
BUG();
}
}
static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0020;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0010;
default:
BUG();
}
}
static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0568;
case OMAP_DSS_VIDEO2:
return 0x04DC;
default:
BUG();
}
}
static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0024;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0014;
default:
BUG();
}
}
static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0028;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0018;
default:
BUG();
}
}
static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x002C;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x001C;
default:
BUG();
}
}
static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0030;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0020;
default:
BUG();
}
}
static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0034;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
BUG();
default:
BUG();
}
}
static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x0038;
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
BUG();
default:
BUG();
}
}
static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0024;
default:
BUG();
}
}
static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0580;
case OMAP_DSS_VIDEO2:
return 0x055C;
default:
BUG();
}
}
static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0028;
default:
BUG();
}
}
static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x002C;
default:
BUG();
}
}
static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0584;
case OMAP_DSS_VIDEO2:
return 0x0560;
default:
BUG();
}
}
static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0030;
default:
BUG();
}
}
static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0588;
case OMAP_DSS_VIDEO2:
return 0x0564;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0034 + i * 0x8;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x058C + i * 0x8;
case OMAP_DSS_VIDEO2:
return 0x0568 + i * 0x8;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0038 + i * 0x8;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0590 + i * 8;
case OMAP_DSS_VIDEO2:
return 0x056C + i * 0x8;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4,} */
static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
case OMAP_DSS_VIDEO2:
return 0x0074 + i * 0x4;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x0124 + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x00B4 + i * 0x4;
default:
BUG();
}
}
/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */
static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
{
switch (plane) {
case OMAP_DSS_GFX:
BUG();
case OMAP_DSS_VIDEO1:
return 0x05CC + i * 0x4;
case OMAP_DSS_VIDEO2:
return 0x05A8 + i * 0x4;
default:
BUG();
}
}
static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
{
switch (plane) {
case OMAP_DSS_GFX:
return 0x01AC;
case OMAP_DSS_VIDEO1:
return 0x0174;
case OMAP_DSS_VIDEO2:
return 0x00E8;
default:
BUG();
}
}
#endif

View File

@ -27,7 +27,7 @@
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "dss.h"
static ssize_t display_enabled_show(struct device *dev,
@ -44,9 +44,13 @@ static ssize_t display_enabled_store(struct device *dev,
const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
bool enabled, r;
int r, enabled;
enabled = simple_strtoul(buf, NULL, 10);
r = kstrtoint(buf, 0, &enabled);
if (r)
return r;
enabled = !!enabled;
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
if (enabled) {
@ -82,7 +86,9 @@ static ssize_t display_upd_mode_store(struct device *dev,
if (!dssdev->driver->set_update_mode)
return -EINVAL;
val = simple_strtoul(buf, NULL, 10);
r = kstrtoint(buf, 0, &val);
if (r)
return r;
switch (val) {
case OMAP_DSS_UPDATE_DISABLED:
@ -114,13 +120,16 @@ static ssize_t display_tear_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
unsigned long te;
int r;
int te, r;
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
return -ENOENT;
te = simple_strtoul(buf, NULL, 0);
r = kstrtoint(buf, 0, &te);
if (r)
return r;
te = !!te;
r = dssdev->driver->enable_te(dssdev, te);
if (r)
@ -196,13 +205,14 @@ static ssize_t display_rotate_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
unsigned long rot;
int r;
int rot, r;
if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
return -ENOENT;
rot = simple_strtoul(buf, NULL, 0);
r = kstrtoint(buf, 0, &rot);
if (r)
return r;
r = dssdev->driver->set_rotate(dssdev, rot);
if (r)
@ -226,13 +236,16 @@ static ssize_t display_mirror_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
unsigned long mirror;
int r;
int mirror, r;
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
return -ENOENT;
mirror = simple_strtoul(buf, NULL, 0);
r = kstrtoint(buf, 0, &mirror);
if (r)
return r;
mirror = !!mirror;
r = dssdev->driver->set_mirror(dssdev, mirror);
if (r)
@ -259,14 +272,15 @@ static ssize_t display_wss_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
struct omap_dss_device *dssdev = to_dss_device(dev);
unsigned long wss;
u32 wss;
int r;
if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
return -ENOENT;
if (strict_strtoul(buf, 0, &wss))
return -EINVAL;
r = kstrtou32(buf, 0, &wss);
if (r)
return r;
if (wss > 0xfffff)
return -EINVAL;

View File

@ -30,16 +30,40 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
static struct {
struct regulator *vdds_dsi_reg;
struct platform_device *dsidev;
} dpi;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
static struct platform_device *dpi_get_dsidev(enum omap_dss_clk_source clk)
{
int dsi_module;
dsi_module = clk == OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ? 0 : 1;
return dsi_get_dsidev_from_id(dsi_module);
}
static bool dpi_use_dsi_pll(struct omap_dss_device *dssdev)
{
if (dssdev->clocks.dispc.dispc_fclk_src ==
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
dssdev->clocks.dispc.dispc_fclk_src ==
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC ||
dssdev->clocks.dispc.channel.lcd_clk_src ==
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC ||
dssdev->clocks.dispc.channel.lcd_clk_src ==
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC)
return true;
else
return false;
}
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
unsigned long pck_req, unsigned long *fck, int *lck_div,
int *pck_div)
@ -48,16 +72,16 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
struct dispc_clock_info dispc_cinfo;
int r;
r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
&dispc_cinfo);
r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req,
&dsi_cinfo, &dispc_cinfo);
if (r)
return r;
r = dsi_pll_set_clock_div(&dsi_cinfo);
r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
if (r)
return r;
dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
if (r)
@ -69,7 +93,7 @@ static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
return 0;
}
#else
static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
unsigned long pck_req, unsigned long *fck, int *lck_div,
int *pck_div)
@ -96,13 +120,12 @@ static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
return 0;
}
#endif
static int dpi_set_mode(struct omap_dss_device *dssdev)
{
struct omap_video_timings *t = &dssdev->panel.timings;
int lck_div, pck_div;
unsigned long fck;
int lck_div = 0, pck_div = 0;
unsigned long fck = 0;
unsigned long pck;
bool is_tft;
int r = 0;
@ -114,13 +137,12 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck,
&lck_div, &pck_div);
#else
r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000, &fck,
&lck_div, &pck_div);
#endif
if (dpi_use_dsi_pll(dssdev))
r = dpi_set_dsi_clk(dssdev, is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
else
r = dpi_set_dispc_clk(dssdev, is_tft, t->pixel_clock * 1000,
&fck, &lck_div, &pck_div);
if (r)
goto err0;
@ -179,12 +201,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
if (r)
goto err2;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_pll_init(dssdev, 0, 1);
if (r)
goto err3;
#endif
if (dpi_use_dsi_pll(dssdev)) {
dss_clk_enable(DSS_CLK_SYSCK);
r = dsi_pll_init(dpi.dsidev, 0, 1);
if (r)
goto err3;
}
r = dpi_set_mode(dssdev);
if (r)
goto err4;
@ -196,11 +219,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
return 0;
err4:
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dsi_pll_uninit();
if (dpi_use_dsi_pll(dssdev))
dsi_pll_uninit(dpi.dsidev, true);
err3:
dss_clk_disable(DSS_CLK_SYSCK);
#endif
if (dpi_use_dsi_pll(dssdev))
dss_clk_disable(DSS_CLK_SYSCK);
err2:
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
if (cpu_is_omap34xx())
@ -216,11 +239,11 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
{
dssdev->manager->disable(dssdev->manager);
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
dsi_pll_uninit();
dss_clk_disable(DSS_CLK_SYSCK);
#endif
if (dpi_use_dsi_pll(dssdev)) {
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
dsi_pll_uninit(dpi.dsidev, true);
dss_clk_disable(DSS_CLK_SYSCK);
}
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
@ -251,6 +274,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
int lck_div, pck_div;
unsigned long fck;
unsigned long pck;
struct dispc_clock_info dispc_cinfo;
if (!dispc_lcd_timings_ok(timings))
return -EINVAL;
@ -260,11 +284,9 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
{
if (dpi_use_dsi_pll(dssdev)) {
struct dsi_clock_info dsi_cinfo;
struct dispc_clock_info dispc_cinfo;
r = dsi_pll_calc_clock_div_pck(is_tft,
r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft,
timings->pixel_clock * 1000,
&dsi_cinfo, &dispc_cinfo);
@ -272,13 +294,8 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
return r;
fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
lck_div = dispc_cinfo.lck_div;
pck_div = dispc_cinfo.pck_div;
}
#else
{
} else {
struct dss_clock_info dss_cinfo;
struct dispc_clock_info dispc_cinfo;
r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
&dss_cinfo, &dispc_cinfo);
@ -286,10 +303,10 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
return r;
fck = dss_cinfo.fck;
lck_div = dispc_cinfo.lck_div;
pck_div = dispc_cinfo.pck_div;
}
#endif
lck_div = dispc_cinfo.lck_div;
pck_div = dispc_cinfo.pck_div;
pck = fck / lck_div / pck_div / 1000;
@ -316,6 +333,12 @@ int dpi_init_display(struct omap_dss_device *dssdev)
dpi.vdds_dsi_reg = vdds_dsi;
}
if (dpi_use_dsi_pll(dssdev)) {
enum omap_dss_clk_source dispc_fclk_src =
dssdev->clocks.dispc.dispc_fclk_src;
dpi.dsidev = dpi_get_dsidev(dispc_fclk_src);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
#include <linux/seq_file.h>
#include <linux/clk.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/clock.h>
#include "dss.h"
#include "dss_features.h"
@ -45,7 +45,6 @@ struct dss_reg {
#define DSS_REVISION DSS_REG(0x0000)
#define DSS_SYSCONFIG DSS_REG(0x0010)
#define DSS_SYSSTATUS DSS_REG(0x0014)
#define DSS_IRQSTATUS DSS_REG(0x0018)
#define DSS_CONTROL DSS_REG(0x0040)
#define DSS_SDI_CONTROL DSS_REG(0x0044)
#define DSS_PLL_CONTROL DSS_REG(0x0048)
@ -75,17 +74,17 @@ static struct {
struct dss_clock_info cache_dss_cinfo;
struct dispc_clock_info cache_dispc_cinfo;
enum dss_clk_source dsi_clk_source;
enum dss_clk_source dispc_clk_source;
enum dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI];
enum omap_dss_clk_source dispc_clk_source;
enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS];
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
} dss;
static const char * const dss_generic_clk_source_names[] = {
[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
[DSS_CLK_SRC_FCK] = "DSS_FCK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK",
};
static void dss_clk_enable_all_no_ctx(void);
@ -230,7 +229,7 @@ void dss_sdi_disable(void)
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
}
const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src)
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src)
{
return dss_generic_clk_source_names[clk_src];
}
@ -246,8 +245,8 @@ void dss_dump_clocks(struct seq_file *s)
seq_printf(s, "- DSS -\n");
fclk_name = dss_get_generic_clk_source_name(DSS_CLK_SRC_FCK);
fclk_real_name = dss_feat_get_clk_source_name(DSS_CLK_SRC_FCK);
fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK);
fclk_rate = dss_clk_get_rate(DSS_CLK_FCK);
if (dss.dpll4_m4_ck) {
@ -286,7 +285,6 @@ void dss_dump_regs(struct seq_file *s)
DUMPREG(DSS_REVISION);
DUMPREG(DSS_SYSCONFIG);
DUMPREG(DSS_SYSSTATUS);
DUMPREG(DSS_IRQSTATUS);
DUMPREG(DSS_CONTROL);
if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) &
@ -300,18 +298,25 @@ void dss_dump_regs(struct seq_file *s)
#undef DUMPREG
}
void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
{
struct platform_device *dsidev;
int b;
u8 start, end;
switch (clk_src) {
case DSS_CLK_SRC_FCK:
case OMAP_DSS_CLK_SRC_FCK:
b = 0;
break;
case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
b = 1;
dsi_wait_pll_hsdiv_dispc_active();
dsidev = dsi_get_dsidev_from_id(0);
dsi_wait_pll_hsdiv_dispc_active(dsidev);
break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
b = 2;
dsidev = dsi_get_dsidev_from_id(1);
dsi_wait_pll_hsdiv_dispc_active(dsidev);
break;
default:
BUG();
@ -324,17 +329,27 @@ void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
dss.dispc_clk_source = clk_src;
}
void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src)
{
struct platform_device *dsidev;
int b;
switch (clk_src) {
case DSS_CLK_SRC_FCK:
case OMAP_DSS_CLK_SRC_FCK:
b = 0;
break;
case DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI:
BUG_ON(dsi_module != 0);
b = 1;
dsi_wait_pll_hsdiv_dsi_active();
dsidev = dsi_get_dsidev_from_id(0);
dsi_wait_pll_hsdiv_dsi_active(dsidev);
break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI:
BUG_ON(dsi_module != 1);
b = 1;
dsidev = dsi_get_dsidev_from_id(1);
dsi_wait_pll_hsdiv_dsi_active(dsidev);
break;
default:
BUG();
@ -342,25 +357,33 @@ void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
dss.dsi_clk_source = clk_src;
dss.dsi_clk_source[dsi_module] = clk_src;
}
void dss_select_lcd_clk_source(enum omap_channel channel,
enum dss_clk_source clk_src)
enum omap_dss_clk_source clk_src)
{
struct platform_device *dsidev;
int b, ix, pos;
if (!dss_has_feature(FEAT_LCD_CLK_SRC))
return;
switch (clk_src) {
case DSS_CLK_SRC_FCK:
case OMAP_DSS_CLK_SRC_FCK:
b = 0;
break;
case DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC:
BUG_ON(channel != OMAP_DSS_CHANNEL_LCD);
b = 1;
dsi_wait_pll_hsdiv_dispc_active();
dsidev = dsi_get_dsidev_from_id(0);
dsi_wait_pll_hsdiv_dispc_active(dsidev);
break;
case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC:
BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2);
b = 1;
dsidev = dsi_get_dsidev_from_id(1);
dsi_wait_pll_hsdiv_dispc_active(dsidev);
break;
default:
BUG();
@ -373,17 +396,17 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
dss.lcd_clk_source[ix] = clk_src;
}
enum dss_clk_source dss_get_dispc_clk_source(void)
enum omap_dss_clk_source dss_get_dispc_clk_source(void)
{
return dss.dispc_clk_source;
}
enum dss_clk_source dss_get_dsi_clk_source(void)
enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module)
{
return dss.dsi_clk_source;
return dss.dsi_clk_source[dsi_module];
}
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
{
if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
@ -665,13 +688,18 @@ static int dss_init(void)
* the kernel resets it */
omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
#ifdef CONFIG_OMAP2_DSS_SLEEP_BEFORE_RESET
/* We need to wait here a bit, otherwise we sometimes start to
* get synclost errors, and after that only power cycle will
* restore DSS functionality. I have no idea why this happens.
* And we have to wait _before_ resetting the DSS, but after
* enabling clocks.
*
* This bug was at least present on OMAP3430. It's unknown
* if it happens on OMAP2 or OMAP3630.
*/
msleep(50);
#endif
_omap_dss_reset();
@ -706,10 +734,11 @@ static int dss_init(void)
dss.dpll4_m4_ck = dpll4_m4_ck;
dss.dsi_clk_source = DSS_CLK_SRC_FCK;
dss.dispc_clk_source = DSS_CLK_SRC_FCK;
dss.lcd_clk_source[0] = DSS_CLK_SRC_FCK;
dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK;
dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK;
dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
dss_save_context();
@ -1021,6 +1050,14 @@ static void core_dump_clocks(struct seq_file *s)
dss.dss_video_fck
};
const char *names[5] = {
"ick",
"fck",
"sys_clk",
"tv_fck",
"video_fck"
};
seq_printf(s, "- CORE -\n");
seq_printf(s, "internal clk count\t\t%u\n", dss.num_clks_enabled);
@ -1028,8 +1065,11 @@ static void core_dump_clocks(struct seq_file *s)
for (i = 0; i < 5; i++) {
if (!clocks[i])
continue;
seq_printf(s, "%-15s\t%lu\t%d\n",
seq_printf(s, "%s (%s)%*s\t%lu\t%d\n",
names[i],
clocks[i]->name,
24 - strlen(names[i]) - strlen(clocks[i]->name),
"",
clk_get_rate(clocks[i]),
clocks[i]->usecount);
}

View File

@ -117,15 +117,6 @@ enum dss_clock {
DSS_CLK_VIDFCK = 1 << 4, /* DSS_96M_FCLK*/
};
enum dss_clk_source {
DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
* OMAP4: PLL1_CLK1 */
DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
* OMAP4: PLL1_CLK2 */
DSS_CLK_SRC_FCK, /* OMAP2/3: DSS1_ALWON_FCLK
* OMAP4: DSS_FCLK */
};
enum dss_hdmi_venc_clk_source_select {
DSS_VENC_TV_CLK = 0,
DSS_HDMI_M_PCLK = 1,
@ -236,7 +227,7 @@ void dss_clk_enable(enum dss_clock clks);
void dss_clk_disable(enum dss_clock clks);
unsigned long dss_clk_get_rate(enum dss_clock clk);
int dss_need_ctx_restore(void);
const char *dss_get_generic_clk_source_name(enum dss_clk_source clk_src);
const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src);
void dss_dump_clocks(struct seq_file *s);
void dss_dump_regs(struct seq_file *s);
@ -248,13 +239,14 @@ void dss_sdi_init(u8 datapairs);
int dss_sdi_enable(void);
void dss_sdi_disable(void);
void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src);
void dss_select_dsi_clk_source(int dsi_module,
enum omap_dss_clk_source clk_src);
void dss_select_lcd_clk_source(enum omap_channel channel,
enum dss_clk_source clk_src);
enum dss_clk_source dss_get_dispc_clk_source(void);
enum dss_clk_source dss_get_dsi_clk_source(void);
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
enum omap_dss_clk_source clk_src);
enum omap_dss_clk_source dss_get_dispc_clk_source(void);
enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module);
enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel);
void dss_set_venc_output(enum omap_dss_venc_type type);
void dss_set_dac_pwrdn_bgz(bool enable);
@ -284,31 +276,39 @@ static inline void sdi_exit(void)
/* DSI */
#ifdef CONFIG_OMAP2_DSS_DSI
struct dentry;
struct file_operations;
int dsi_init_platform_driver(void);
void dsi_uninit_platform_driver(void);
void dsi_dump_clocks(struct seq_file *s);
void dsi_dump_irqs(struct seq_file *s);
void dsi_dump_regs(struct seq_file *s);
void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
const struct file_operations *debug_fops);
void dsi_save_context(void);
void dsi_restore_context(void);
int dsi_init_display(struct omap_dss_device *display);
void dsi_irq_handler(void);
unsigned long dsi_get_pll_hsdiv_dispc_rate(void);
int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo);
int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
struct dsi_clock_info *cinfo,
unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev);
int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo);
int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, bool is_tft,
unsigned long req_pck, struct dsi_clock_info *cinfo,
struct dispc_clock_info *dispc_cinfo);
int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk,
bool enable_hsdiv);
void dsi_pll_uninit(void);
void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes);
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
u32 fifo_size, enum omap_burst_size *burst_size,
u32 *fifo_low, u32 *fifo_high);
void dsi_wait_pll_hsdiv_dispc_active(void);
void dsi_wait_pll_hsdiv_dsi_active(void);
void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev);
void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev);
struct platform_device *dsi_get_dsidev_from_id(int module);
#else
static inline int dsi_init_platform_driver(void)
{
@ -317,17 +317,47 @@ static inline int dsi_init_platform_driver(void)
static inline void dsi_uninit_platform_driver(void)
{
}
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(void)
static inline unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev)
{
WARN("%s: DSI not compiled in, returning rate as 0\n", __func__);
return 0;
}
static inline void dsi_wait_pll_hsdiv_dispc_active(void)
static inline int dsi_pll_set_clock_div(struct platform_device *dsidev,
struct dsi_clock_info *cinfo)
{
WARN("%s: DSI not compiled in\n", __func__);
return -ENODEV;
}
static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev,
bool is_tft, unsigned long req_pck,
struct dsi_clock_info *dsi_cinfo,
struct dispc_clock_info *dispc_cinfo)
{
WARN("%s: DSI not compiled in\n", __func__);
return -ENODEV;
}
static inline int dsi_pll_init(struct platform_device *dsidev,
bool enable_hsclk, bool enable_hsdiv)
{
WARN("%s: DSI not compiled in\n", __func__);
return -ENODEV;
}
static inline void dsi_pll_uninit(struct platform_device *dsidev,
bool disconnect_lanes)
{
}
static inline void dsi_wait_pll_hsdiv_dsi_active(void)
static inline void dsi_wait_pll_hsdiv_dispc_active(struct platform_device *dsidev)
{
}
static inline void dsi_wait_pll_hsdiv_dsi_active(struct platform_device *dsidev)
{
}
static inline struct platform_device *dsi_get_dsidev_from_id(int module)
{
WARN("%s: DSI not compiled in, returning platform device as NULL\n",
__func__);
return NULL;
}
#endif
/* DPI */
@ -391,7 +421,8 @@ int dispc_setup_plane(enum omap_plane plane,
enum omap_dss_rotation_type rotation_type,
u8 rotation, bool mirror,
u8 global_alpha, u8 pre_mult_alpha,
enum omap_channel channel);
enum omap_channel channel,
u32 puv_addr);
bool dispc_go_busy(enum omap_channel channel);
void dispc_go(enum omap_channel channel);
@ -485,13 +516,6 @@ void hdmi_panel_exit(void);
int rfbi_init_platform_driver(void);
void rfbi_uninit_platform_driver(void);
void rfbi_dump_regs(struct seq_file *s);
int rfbi_configure(int rfbi_module, int bpp, int lines);
void rfbi_enable_rfbi(bool enable);
void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
u16 height, void (callback)(void *data), void *data);
void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
unsigned long rfbi_get_max_tx_rate(void);
int rfbi_init_display(struct omap_dss_device *display);
#else
static inline int rfbi_init_platform_driver(void)

View File

@ -22,7 +22,7 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
@ -52,7 +52,7 @@ struct omap_dss_features {
};
/* This struct is assigned to one of the below during initialization */
static struct omap_dss_features *omap_current_dss_features;
static const struct omap_dss_features *omap_current_dss_features;
static const struct dss_reg_field omap2_dss_reg_fields[] = {
[FEAT_REG_FIRHINC] = { 11, 0 },
@ -177,22 +177,55 @@ static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
};
static const enum omap_color_mode omap4_dss_supported_color_modes[] = {
/* OMAP_DSS_GFX */
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32 |
OMAP_DSS_COLOR_ARGB16_1555,
/* OMAP_DSS_VIDEO1 */
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
OMAP_DSS_COLOR_RGBX32,
/* OMAP_DSS_VIDEO2 */
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB12U |
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_ARGB16_1555 |
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_NV12 |
OMAP_DSS_COLOR_RGBA16 | OMAP_DSS_COLOR_RGB24U |
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_UYVY |
OMAP_DSS_COLOR_ARGB16 | OMAP_DSS_COLOR_XRGB16_1555 |
OMAP_DSS_COLOR_ARGB32 | OMAP_DSS_COLOR_RGBX16 |
OMAP_DSS_COLOR_RGBX32,
};
static const char * const omap2_dss_clk_source_names[] = {
[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
[DSS_CLK_SRC_FCK] = "DSS_FCLK1",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "N/A",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "N/A",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK1",
};
static const char * const omap3_dss_clk_source_names[] = {
[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
[DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI1_PLL_FCLK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI2_PLL_FCLK",
[OMAP_DSS_CLK_SRC_FCK] = "DSS1_ALWON_FCLK",
};
static const char * const omap4_dss_clk_source_names[] = {
[DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
[DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
[DSS_CLK_SRC_FCK] = "DSS_FCLK",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "PLL1_CLK1",
[OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "PLL1_CLK2",
[OMAP_DSS_CLK_SRC_FCK] = "DSS_FCLK",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "PLL2_CLK1",
[OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "PLL2_CLK2",
};
static const struct dss_param_range omap2_dss_param_range[] = {
@ -226,7 +259,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
};
/* OMAP2 DSS Features */
static struct omap_dss_features omap2_dss_features = {
static const struct omap_dss_features omap2_dss_features = {
.reg_fields = omap2_dss_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
@ -244,7 +277,7 @@ static struct omap_dss_features omap2_dss_features = {
};
/* OMAP3 DSS Features */
static struct omap_dss_features omap3430_dss_features = {
static const struct omap_dss_features omap3430_dss_features = {
.reg_fields = omap3_dss_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
@ -252,7 +285,8 @@ static struct omap_dss_features omap3430_dss_features = {
FEAT_GLOBAL_ALPHA | FEAT_LCDENABLEPOL |
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_FUNCGATED | FEAT_ROWREPEATENABLE |
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF,
FEAT_LINEBUFFERSPLIT | FEAT_RESIZECONF |
FEAT_DSI_PLL_FREQSEL | FEAT_DSI_REVERSE_TXCLKESC,
.num_mgrs = 2,
.num_ovls = 3,
@ -262,7 +296,7 @@ static struct omap_dss_features omap3430_dss_features = {
.dss_params = omap3_dss_param_range,
};
static struct omap_dss_features omap3630_dss_features = {
static const struct omap_dss_features omap3630_dss_features = {
.reg_fields = omap3_dss_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
@ -271,7 +305,8 @@ static struct omap_dss_features omap3630_dss_features = {
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG,
FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG |
FEAT_DSI_PLL_FREQSEL,
.num_mgrs = 2,
.num_ovls = 3,
@ -282,19 +317,43 @@ static struct omap_dss_features omap3630_dss_features = {
};
/* OMAP4 DSS Features */
static struct omap_dss_features omap4_dss_features = {
/* For OMAP4430 ES 1.0 revision */
static const struct omap_dss_features omap4430_es1_0_dss_features = {
.reg_fields = omap4_dss_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC,
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap3_dss_supported_color_modes,
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
};
/* For all the other OMAP4 versions */
static const struct omap_dss_features omap4_dss_features = {
.reg_fields = omap4_dss_reg_fields,
.num_reg_fields = ARRAY_SIZE(omap4_dss_reg_fields),
.has_feature =
FEAT_GLOBAL_ALPHA | FEAT_PRE_MULT_ALPHA |
FEAT_MGR_LCD2 | FEAT_GLOBAL_ALPHA_VID1 |
FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2,
.num_mgrs = 3,
.num_ovls = 3,
.supported_displays = omap4_dss_supported_displays,
.supported_color_modes = omap4_dss_supported_color_modes,
.clksrc_names = omap4_dss_clk_source_names,
.dss_params = omap4_dss_param_range,
};
@ -337,7 +396,7 @@ bool dss_feat_color_mode_supported(enum omap_plane plane,
color_mode;
}
const char *dss_feat_get_clk_source_name(enum dss_clk_source id)
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id)
{
return omap_current_dss_features->clksrc_names[id];
}
@ -365,6 +424,10 @@ void dss_features_init(void)
omap_current_dss_features = &omap3630_dss_features;
else if (cpu_is_omap34xx())
omap_current_dss_features = &omap3430_dss_features;
else
else if (omap_rev() == OMAP4430_REV_ES1_0)
omap_current_dss_features = &omap4430_es1_0_dss_features;
else if (cpu_is_omap44xx())
omap_current_dss_features = &omap4_dss_features;
else
DSSWARN("Unsupported OMAP version");
}

View File

@ -23,25 +23,34 @@
#define MAX_DSS_MANAGERS 3
#define MAX_DSS_OVERLAYS 3
#define MAX_DSS_LCD_MANAGERS 2
#define MAX_NUM_DSI 2
/* DSS has feature id */
enum dss_feat_id {
FEAT_GLOBAL_ALPHA = 1 << 0,
FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
FEAT_PRE_MULT_ALPHA = 1 << 2,
FEAT_LCDENABLEPOL = 1 << 3,
FEAT_LCDENABLESIGNAL = 1 << 4,
FEAT_PCKFREEENABLE = 1 << 5,
FEAT_FUNCGATED = 1 << 6,
FEAT_MGR_LCD2 = 1 << 7,
FEAT_LINEBUFFERSPLIT = 1 << 8,
FEAT_ROWREPEATENABLE = 1 << 9,
FEAT_RESIZECONF = 1 << 10,
FEAT_GLOBAL_ALPHA = 1 << 0,
FEAT_GLOBAL_ALPHA_VID1 = 1 << 1,
FEAT_PRE_MULT_ALPHA = 1 << 2,
FEAT_LCDENABLEPOL = 1 << 3,
FEAT_LCDENABLESIGNAL = 1 << 4,
FEAT_PCKFREEENABLE = 1 << 5,
FEAT_FUNCGATED = 1 << 6,
FEAT_MGR_LCD2 = 1 << 7,
FEAT_LINEBUFFERSPLIT = 1 << 8,
FEAT_ROWREPEATENABLE = 1 << 9,
FEAT_RESIZECONF = 1 << 10,
/* Independent core clk divider */
FEAT_CORE_CLK_DIV = 1 << 11,
FEAT_LCD_CLK_SRC = 1 << 12,
FEAT_CORE_CLK_DIV = 1 << 11,
FEAT_LCD_CLK_SRC = 1 << 12,
/* DSI-PLL power command 0x3 is not working */
FEAT_DSI_PLL_PWR_BUG = 1 << 13,
FEAT_DSI_PLL_PWR_BUG = 1 << 13,
FEAT_DSI_PLL_FREQSEL = 1 << 14,
FEAT_DSI_DCS_CMD_CONFIG_VC = 1 << 15,
FEAT_DSI_VC_OCP_WIDTH = 1 << 16,
FEAT_DSI_REVERSE_TXCLKESC = 1 << 17,
FEAT_DSI_GNQ = 1 << 18,
FEAT_HDMI_CTS_SWMODE = 1 << 19,
FEAT_HANDLE_UV_SEPARATE = 1 << 20,
FEAT_ATTR2 = 1 << 21,
};
/* DSS register field id */
@ -79,7 +88,7 @@ enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel
enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
bool dss_feat_color_mode_supported(enum omap_plane plane,
enum omap_color_mode color_mode);
const char *dss_feat_get_clk_source_name(enum dss_clk_source id);
const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);

View File

@ -29,10 +29,16 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <plat/display.h>
#include <video/omapdss.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
#include <sound/soc.h>
#include <sound/pcm_params.h>
#endif
#include "dss.h"
#include "hdmi.h"
#include "dss_features.h"
static struct {
struct mutex lock;
@ -1052,25 +1058,26 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
cfg->timings.hsync_pol = cea_vesa_timings[code].hsync_pol;
}
static void hdmi_compute_pll(unsigned long clkin, int phy,
int n, struct hdmi_pll_info *pi)
static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
struct hdmi_pll_info *pi)
{
unsigned long refclk;
unsigned long clkin, refclk;
u32 mf;
clkin = dss_clk_get_rate(DSS_CLK_SYSCK) / 10000;
/*
* Input clock is predivided by N + 1
* out put of which is reference clk
*/
refclk = clkin / (n + 1);
pi->regn = n;
pi->regn = dssdev->clocks.hdmi.regn;
refclk = clkin / (pi->regn + 1);
/*
* multiplier is pixel_clk/ref_clk
* Multiplying by 100 to avoid fractional part removal
*/
pi->regm = (phy * 100/(refclk))/100;
pi->regm2 = 1;
pi->regm = (phy * 100 / (refclk)) / 100;
pi->regm2 = dssdev->clocks.hdmi.regm2;
/*
* fractional multiplier is remainder of the difference between
@ -1078,14 +1085,14 @@ static void hdmi_compute_pll(unsigned long clkin, int phy,
* multiplied by 2^18(262144) divided by the reference clock
*/
mf = (phy - pi->regm * refclk) * 262144;
pi->regmf = mf/(refclk);
pi->regmf = mf / (refclk);
/*
* Dcofreq should be set to 1 if required pixel clock
* is greater than 1000MHz
*/
pi->dcofreq = phy > 1000 * 100;
pi->regsd = ((pi->regm * clkin / 10) / ((n + 1) * 250) + 5) / 10;
pi->regsd = ((pi->regm * clkin / 10) / ((pi->regn + 1) * 250) + 5) / 10;
DSSDBG("M = %d Mf = %d\n", pi->regm, pi->regmf);
DSSDBG("range = %d sd = %d\n", pi->dcofreq, pi->regsd);
@ -1106,7 +1113,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
int r, code = 0;
struct hdmi_pll_info pll_data;
struct omap_video_timings *p;
int clkin, n, phy;
unsigned long phy;
hdmi_enable_clocks(1);
@ -1126,11 +1133,9 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
dssdev->panel.timings = cea_vesa_timings[code].timings;
update_hdmi_timings(&hdmi.cfg, p, code);
clkin = 3840; /* 38.4 MHz */
n = 15; /* this is a constant for our math */
phy = p->pixel_clock;
hdmi_compute_pll(clkin, phy, n, &pll_data);
hdmi_compute_pll(dssdev, phy, &pll_data);
hdmi_wp_video_start(0);
@ -1160,7 +1165,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
* dynamically by user. This can be moved to single location , say
* Boardfile.
*/
dss_select_dispc_clk_source(DSS_CLK_SRC_FCK);
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
/* bypass TV gamma table */
dispc_enable_gamma_table(0);
@ -1275,10 +1280,420 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
mutex_unlock(&hdmi.lock);
}
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
static void hdmi_wp_audio_config_format(
struct hdmi_audio_format *aud_fmt)
{
u32 r;
DSSDBG("Enter hdmi_wp_audio_config_format\n");
r = hdmi_read_reg(HDMI_WP_AUDIO_CFG);
r = FLD_MOD(r, aud_fmt->stereo_channels, 26, 24);
r = FLD_MOD(r, aud_fmt->active_chnnls_msk, 23, 16);
r = FLD_MOD(r, aud_fmt->en_sig_blk_strt_end, 5, 5);
r = FLD_MOD(r, aud_fmt->type, 4, 4);
r = FLD_MOD(r, aud_fmt->justification, 3, 3);
r = FLD_MOD(r, aud_fmt->sample_order, 2, 2);
r = FLD_MOD(r, aud_fmt->samples_per_word, 1, 1);
r = FLD_MOD(r, aud_fmt->sample_size, 0, 0);
hdmi_write_reg(HDMI_WP_AUDIO_CFG, r);
}
static void hdmi_wp_audio_config_dma(struct hdmi_audio_dma *aud_dma)
{
u32 r;
DSSDBG("Enter hdmi_wp_audio_config_dma\n");
r = hdmi_read_reg(HDMI_WP_AUDIO_CFG2);
r = FLD_MOD(r, aud_dma->transfer_size, 15, 8);
r = FLD_MOD(r, aud_dma->block_size, 7, 0);
hdmi_write_reg(HDMI_WP_AUDIO_CFG2, r);
r = hdmi_read_reg(HDMI_WP_AUDIO_CTRL);
r = FLD_MOD(r, aud_dma->mode, 9, 9);
r = FLD_MOD(r, aud_dma->fifo_threshold, 8, 0);
hdmi_write_reg(HDMI_WP_AUDIO_CTRL, r);
}
static void hdmi_core_audio_config(struct hdmi_core_audio_config *cfg)
{
u32 r;
/* audio clock recovery parameters */
r = hdmi_read_reg(HDMI_CORE_AV_ACR_CTRL);
r = FLD_MOD(r, cfg->use_mclk, 2, 2);
r = FLD_MOD(r, cfg->en_acr_pkt, 1, 1);
r = FLD_MOD(r, cfg->cts_mode, 0, 0);
hdmi_write_reg(HDMI_CORE_AV_ACR_CTRL, r);
REG_FLD_MOD(HDMI_CORE_AV_N_SVAL1, cfg->n, 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_N_SVAL2, cfg->n >> 8, 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_N_SVAL3, cfg->n >> 16, 7, 0);
if (cfg->cts_mode == HDMI_AUDIO_CTS_MODE_SW) {
REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL1, cfg->cts, 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL2, cfg->cts >> 8, 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_CTS_SVAL3, cfg->cts >> 16, 7, 0);
} else {
/*
* HDMI IP uses this configuration to divide the MCLK to
* update CTS value.
*/
REG_FLD_MOD(HDMI_CORE_AV_FREQ_SVAL, cfg->mclk_mode, 2, 0);
/* Configure clock for audio packets */
REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_1,
cfg->aud_par_busclk, 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_2,
(cfg->aud_par_busclk >> 8), 7, 0);
REG_FLD_MOD(HDMI_CORE_AV_AUD_PAR_BUSCLK_3,
(cfg->aud_par_busclk >> 16), 7, 0);
}
/* Override of SPDIF sample frequency with value in I2S_CHST4 */
REG_FLD_MOD(HDMI_CORE_AV_SPDIF_CTRL, cfg->fs_override, 1, 1);
/* I2S parameters */
REG_FLD_MOD(HDMI_CORE_AV_I2S_CHST4, cfg->freq_sample, 3, 0);
r = hdmi_read_reg(HDMI_CORE_AV_I2S_IN_CTRL);
r = FLD_MOD(r, cfg->i2s_cfg.en_high_bitrate_aud, 7, 7);
r = FLD_MOD(r, cfg->i2s_cfg.sck_edge_mode, 6, 6);
r = FLD_MOD(r, cfg->i2s_cfg.cbit_order, 5, 5);
r = FLD_MOD(r, cfg->i2s_cfg.vbit, 4, 4);
r = FLD_MOD(r, cfg->i2s_cfg.ws_polarity, 3, 3);
r = FLD_MOD(r, cfg->i2s_cfg.justification, 2, 2);
r = FLD_MOD(r, cfg->i2s_cfg.direction, 1, 1);
r = FLD_MOD(r, cfg->i2s_cfg.shift, 0, 0);
hdmi_write_reg(HDMI_CORE_AV_I2S_IN_CTRL, r);
r = hdmi_read_reg(HDMI_CORE_AV_I2S_CHST5);
r = FLD_MOD(r, cfg->freq_sample, 7, 4);
r = FLD_MOD(r, cfg->i2s_cfg.word_length, 3, 1);
r = FLD_MOD(r, cfg->i2s_cfg.word_max_length, 0, 0);
hdmi_write_reg(HDMI_CORE_AV_I2S_CHST5, r);
REG_FLD_MOD(HDMI_CORE_AV_I2S_IN_LEN, cfg->i2s_cfg.in_length_bits, 3, 0);
/* Audio channels and mode parameters */
REG_FLD_MOD(HDMI_CORE_AV_HDMI_CTRL, cfg->layout, 2, 1);
r = hdmi_read_reg(HDMI_CORE_AV_AUD_MODE);
r = FLD_MOD(r, cfg->i2s_cfg.active_sds, 7, 4);
r = FLD_MOD(r, cfg->en_dsd_audio, 3, 3);
r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
r = FLD_MOD(r, cfg->en_spdif, 1, 1);
hdmi_write_reg(HDMI_CORE_AV_AUD_MODE, r);
}
static void hdmi_core_audio_infoframe_config(
struct hdmi_core_infoframe_audio *info_aud)
{
u8 val;
u8 sum = 0, checksum = 0;
/*
* Set audio info frame type, version and length as
* described in HDMI 1.4a Section 8.2.2 specification.
* Checksum calculation is defined in Section 5.3.5.
*/
hdmi_write_reg(HDMI_CORE_AV_AUDIO_TYPE, 0x84);
hdmi_write_reg(HDMI_CORE_AV_AUDIO_VERS, 0x01);
hdmi_write_reg(HDMI_CORE_AV_AUDIO_LEN, 0x0a);
sum += 0x84 + 0x001 + 0x00a;
val = (info_aud->db1_coding_type << 4)
| (info_aud->db1_channel_count - 1);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(0), val);
sum += val;
val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(1), val);
sum += val;
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
val = info_aud->db4_channel_alloc;
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(3), val);
sum += val;
val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(4), val);
sum += val;
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(7), 0x00);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(8), 0x00);
hdmi_write_reg(HDMI_CORE_AV_AUD_DBYTE(9), 0x00);
checksum = 0x100 - sum;
hdmi_write_reg(HDMI_CORE_AV_AUDIO_CHSUM, checksum);
/*
* TODO: Add MPEG and SPD enable and repeat cfg when EDID parsing
* is available.
*/
}
static int hdmi_config_audio_acr(u32 sample_freq, u32 *n, u32 *cts)
{
u32 r;
u32 deep_color = 0;
u32 pclk = hdmi.cfg.timings.timings.pixel_clock;
if (n == NULL || cts == NULL)
return -EINVAL;
/*
* Obtain current deep color configuration. This needed
* to calculate the TMDS clock based on the pixel clock.
*/
r = REG_GET(HDMI_WP_VIDEO_CFG, 1, 0);
switch (r) {
case 1: /* No deep color selected */
deep_color = 100;
break;
case 2: /* 10-bit deep color selected */
deep_color = 125;
break;
case 3: /* 12-bit deep color selected */
deep_color = 150;
break;
default:
return -EINVAL;
}
switch (sample_freq) {
case 32000:
if ((deep_color == 125) && ((pclk == 54054)
|| (pclk == 74250)))
*n = 8192;
else
*n = 4096;
break;
case 44100:
*n = 6272;
break;
case 48000:
if ((deep_color == 125) && ((pclk == 54054)
|| (pclk == 74250)))
*n = 8192;
else
*n = 6144;
break;
default:
*n = 0;
return -EINVAL;
}
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
return 0;
}
static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
struct hdmi_audio_format audio_format;
struct hdmi_audio_dma audio_dma;
struct hdmi_core_audio_config core_cfg;
struct hdmi_core_infoframe_audio aud_if_cfg;
int err, n, cts;
enum hdmi_core_audio_sample_freq sample_freq;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
core_cfg.i2s_cfg.word_max_length =
HDMI_AUDIO_I2S_MAX_WORD_20BITS;
core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_16_BITS;
core_cfg.i2s_cfg.in_length_bits =
HDMI_AUDIO_I2S_INPUT_LENGTH_16;
core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
audio_dma.transfer_size = 0x10;
break;
case SNDRV_PCM_FORMAT_S24_LE:
core_cfg.i2s_cfg.word_max_length =
HDMI_AUDIO_I2S_MAX_WORD_24BITS;
core_cfg.i2s_cfg.word_length = HDMI_AUDIO_I2S_CHST_WORD_24_BITS;
core_cfg.i2s_cfg.in_length_bits =
HDMI_AUDIO_I2S_INPUT_LENGTH_24;
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
core_cfg.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
audio_dma.transfer_size = 0x20;
break;
default:
return -EINVAL;
}
switch (params_rate(params)) {
case 32000:
sample_freq = HDMI_AUDIO_FS_32000;
break;
case 44100:
sample_freq = HDMI_AUDIO_FS_44100;
break;
case 48000:
sample_freq = HDMI_AUDIO_FS_48000;
break;
default:
return -EINVAL;
}
err = hdmi_config_audio_acr(params_rate(params), &n, &cts);
if (err < 0)
return err;
/* Audio wrapper config */
audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
audio_format.active_chnnls_msk = 0x03;
audio_format.type = HDMI_AUDIO_TYPE_LPCM;
audio_format.sample_order = HDMI_AUDIO_SAMPLE_LEFT_FIRST;
/* Disable start/stop signals of IEC 60958 blocks */
audio_format.en_sig_blk_strt_end = HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF;
audio_dma.block_size = 0xC0;
audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
audio_dma.fifo_threshold = 0x20; /* in number of samples */
hdmi_wp_audio_config_dma(&audio_dma);
hdmi_wp_audio_config_format(&audio_format);
/*
* I2S config
*/
core_cfg.i2s_cfg.en_high_bitrate_aud = false;
/* Only used with high bitrate audio */
core_cfg.i2s_cfg.cbit_order = false;
/* Serial data and word select should change on sck rising edge */
core_cfg.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
core_cfg.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
/* Set I2S word select polarity */
core_cfg.i2s_cfg.ws_polarity = HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT;
core_cfg.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
/* Set serial data to word select shift. See Phillips spec. */
core_cfg.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
/* Enable one of the four available serial data channels */
core_cfg.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
/* Core audio config */
core_cfg.freq_sample = sample_freq;
core_cfg.n = n;
core_cfg.cts = cts;
if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
core_cfg.aud_par_busclk = 0;
core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
core_cfg.use_mclk = false;
} else {
core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
core_cfg.use_mclk = true;
core_cfg.mclk_mode = HDMI_AUDIO_MCLK_128FS;
}
core_cfg.layout = HDMI_AUDIO_LAYOUT_2CH;
core_cfg.en_spdif = false;
/* Use sample frequency from channel status word */
core_cfg.fs_override = true;
/* Enable ACR packets */
core_cfg.en_acr_pkt = true;
/* Disable direct streaming digital audio */
core_cfg.en_dsd_audio = false;
/* Use parallel audio interface */
core_cfg.en_parallel_aud_input = true;
hdmi_core_audio_config(&core_cfg);
/*
* Configure packet
* info frame audio see doc CEA861-D page 74
*/
aud_if_cfg.db1_coding_type = HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM;
aud_if_cfg.db1_channel_count = 2;
aud_if_cfg.db2_sample_freq = HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM;
aud_if_cfg.db2_sample_size = HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM;
aud_if_cfg.db4_channel_alloc = 0x00;
aud_if_cfg.db5_downmix_inh = false;
aud_if_cfg.db5_lsv = 0;
hdmi_core_audio_infoframe_config(&aud_if_cfg);
return 0;
}
static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
int err = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 31, 31);
REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 1, 30, 30);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
REG_FLD_MOD(HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 30, 30);
REG_FLD_MOD(HDMI_WP_AUDIO_CTRL, 0, 31, 31);
break;
default:
err = -EINVAL;
}
return err;
}
static int hdmi_audio_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
if (!hdmi.mode) {
pr_err("Current video settings do not support audio.\n");
return -EIO;
}
return 0;
}
static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
};
static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
.hw_params = hdmi_audio_hw_params,
.trigger = hdmi_audio_trigger,
.startup = hdmi_audio_startup,
};
static struct snd_soc_dai_driver hdmi_codec_dai_drv = {
.name = "hdmi-audio-codec",
.playback = {
.channels_min = 2,
.channels_max = 2,
.rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE,
},
.ops = &hdmi_audio_codec_ops,
};
#endif
/* HDMI HW IP initialisation */
static int omapdss_hdmihw_probe(struct platform_device *pdev)
{
struct resource *hdmi_mem;
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
int ret;
#endif
hdmi.pdata = pdev->dev.platform_data;
hdmi.pdev = pdev;
@ -1300,6 +1715,17 @@ static int omapdss_hdmihw_probe(struct platform_device *pdev)
hdmi_panel_init();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
/* Register ASoC codec DAI */
ret = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
&hdmi_codec_dai_drv, 1);
if (ret) {
DSSERR("can't register ASoC HDMI audio codec\n");
return ret;
}
#endif
return 0;
}
@ -1307,6 +1733,11 @@ static int omapdss_hdmihw_remove(struct platform_device *pdev)
{
hdmi_panel_exit();
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
snd_soc_unregister_codec(&pdev->dev);
#endif
iounmap(hdmi.base_wp);
return 0;

View File

@ -22,7 +22,7 @@
#define _OMAP4_DSS_HDMI_H_
#include <linux/string.h>
#include <plat/display.h>
#include <video/omapdss.h>
#define HDMI_WP 0x0
#define HDMI_CORE_SYS 0x400
@ -48,6 +48,10 @@ struct hdmi_reg { u16 idx; };
#define HDMI_WP_VIDEO_TIMING_H HDMI_WP_REG(0x68)
#define HDMI_WP_VIDEO_TIMING_V HDMI_WP_REG(0x6C)
#define HDMI_WP_WP_CLK HDMI_WP_REG(0x70)
#define HDMI_WP_AUDIO_CFG HDMI_WP_REG(0x80)
#define HDMI_WP_AUDIO_CFG2 HDMI_WP_REG(0x84)
#define HDMI_WP_AUDIO_CTRL HDMI_WP_REG(0x88)
#define HDMI_WP_AUDIO_DATA HDMI_WP_REG(0x8C)
/* HDMI IP Core System */
#define HDMI_CORE_SYS_REG(idx) HDMI_REG(HDMI_CORE_SYS + idx)
@ -105,6 +109,8 @@ struct hdmi_reg { u16 idx; };
#define HDMI_CORE_AV_AVI_DBYTE_NELEMS HDMI_CORE_AV_REG(15)
#define HDMI_CORE_AV_SPD_DBYTE HDMI_CORE_AV_REG(0x190)
#define HDMI_CORE_AV_SPD_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
#define HDMI_CORE_AV_AUD_DBYTE(n) HDMI_CORE_AV_REG(n * 4 + 0x210)
#define HDMI_CORE_AV_AUD_DBYTE_NELEMS HDMI_CORE_AV_REG(10)
#define HDMI_CORE_AV_MPEG_DBYTE HDMI_CORE_AV_REG(0x290)
#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS HDMI_CORE_AV_REG(27)
#define HDMI_CORE_AV_GEN_DBYTE HDMI_CORE_AV_REG(0x300)
@ -153,6 +159,10 @@ struct hdmi_reg { u16 idx; };
#define HDMI_CORE_AV_SPD_VERS HDMI_CORE_AV_REG(0x184)
#define HDMI_CORE_AV_SPD_LEN HDMI_CORE_AV_REG(0x188)
#define HDMI_CORE_AV_SPD_CHSUM HDMI_CORE_AV_REG(0x18C)
#define HDMI_CORE_AV_AUDIO_TYPE HDMI_CORE_AV_REG(0x200)
#define HDMI_CORE_AV_AUDIO_VERS HDMI_CORE_AV_REG(0x204)
#define HDMI_CORE_AV_AUDIO_LEN HDMI_CORE_AV_REG(0x208)
#define HDMI_CORE_AV_AUDIO_CHSUM HDMI_CORE_AV_REG(0x20C)
#define HDMI_CORE_AV_MPEG_TYPE HDMI_CORE_AV_REG(0x280)
#define HDMI_CORE_AV_MPEG_VERS HDMI_CORE_AV_REG(0x284)
#define HDMI_CORE_AV_MPEG_LEN HDMI_CORE_AV_REG(0x288)
@ -272,7 +282,7 @@ enum hdmi_core_packet_ctrl {
HDMI_PACKETREPEATOFF = 0
};
/* INFOFRAME_AVI_ definitions */
/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
enum hdmi_core_infoframe {
HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
@ -317,7 +327,36 @@ enum hdmi_core_infoframe {
HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
HDMI_INFOFRAME_AVI_DB5PR_10 = 9
HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
HDMI_INFOFRAME_AUDIO_DB1CT_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB1CT_IEC60958 = 1,
HDMI_INFOFRAME_AUDIO_DB1CT_AC3 = 2,
HDMI_INFOFRAME_AUDIO_DB1CT_MPEG1 = 3,
HDMI_INFOFRAME_AUDIO_DB1CT_MP3 = 4,
HDMI_INFOFRAME_AUDIO_DB1CT_MPEG2_MULTICH = 5,
HDMI_INFOFRAME_AUDIO_DB1CT_AAC = 6,
HDMI_INFOFRAME_AUDIO_DB1CT_DTS = 7,
HDMI_INFOFRAME_AUDIO_DB1CT_ATRAC = 8,
HDMI_INFOFRAME_AUDIO_DB1CT_ONEBIT = 9,
HDMI_INFOFRAME_AUDIO_DB1CT_DOLBY_DIGITAL_PLUS = 10,
HDMI_INFOFRAME_AUDIO_DB1CT_DTS_HD = 11,
HDMI_INFOFRAME_AUDIO_DB1CT_MAT = 12,
HDMI_INFOFRAME_AUDIO_DB1CT_DST = 13,
HDMI_INFOFRAME_AUDIO_DB1CT_WMA_PRO = 14,
HDMI_INFOFRAME_AUDIO_DB2SF_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB2SF_32000 = 1,
HDMI_INFOFRAME_AUDIO_DB2SF_44100 = 2,
HDMI_INFOFRAME_AUDIO_DB2SF_48000 = 3,
HDMI_INFOFRAME_AUDIO_DB2SF_88200 = 4,
HDMI_INFOFRAME_AUDIO_DB2SF_96000 = 5,
HDMI_INFOFRAME_AUDIO_DB2SF_176400 = 6,
HDMI_INFOFRAME_AUDIO_DB2SF_192000 = 7,
HDMI_INFOFRAME_AUDIO_DB2SS_FROM_STREAM = 0,
HDMI_INFOFRAME_AUDIO_DB2SS_16BIT = 1,
HDMI_INFOFRAME_AUDIO_DB2SS_20BIT = 2,
HDMI_INFOFRAME_AUDIO_DB2SS_24BIT = 3,
HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PERMITTED = 0,
HDMI_INFOFRAME_AUDIO_DB5_DM_INH_PROHIBITED = 1
};
enum hdmi_packing_mode {
@ -327,6 +366,121 @@ enum hdmi_packing_mode {
HDMI_PACK_ALREADYPACKED = 7
};
enum hdmi_core_audio_sample_freq {
HDMI_AUDIO_FS_32000 = 0x3,
HDMI_AUDIO_FS_44100 = 0x0,
HDMI_AUDIO_FS_48000 = 0x2,
HDMI_AUDIO_FS_88200 = 0x8,
HDMI_AUDIO_FS_96000 = 0xA,
HDMI_AUDIO_FS_176400 = 0xC,
HDMI_AUDIO_FS_192000 = 0xE,
HDMI_AUDIO_FS_NOT_INDICATED = 0x1
};
enum hdmi_core_audio_layout {
HDMI_AUDIO_LAYOUT_2CH = 0,
HDMI_AUDIO_LAYOUT_8CH = 1
};
enum hdmi_core_cts_mode {
HDMI_AUDIO_CTS_MODE_HW = 0,
HDMI_AUDIO_CTS_MODE_SW = 1
};
enum hdmi_stereo_channels {
HDMI_AUDIO_STEREO_NOCHANNELS = 0,
HDMI_AUDIO_STEREO_ONECHANNEL = 1,
HDMI_AUDIO_STEREO_TWOCHANNELS = 2,
HDMI_AUDIO_STEREO_THREECHANNELS = 3,
HDMI_AUDIO_STEREO_FOURCHANNELS = 4
};
enum hdmi_audio_type {
HDMI_AUDIO_TYPE_LPCM = 0,
HDMI_AUDIO_TYPE_IEC = 1
};
enum hdmi_audio_justify {
HDMI_AUDIO_JUSTIFY_LEFT = 0,
HDMI_AUDIO_JUSTIFY_RIGHT = 1
};
enum hdmi_audio_sample_order {
HDMI_AUDIO_SAMPLE_RIGHT_FIRST = 0,
HDMI_AUDIO_SAMPLE_LEFT_FIRST = 1
};
enum hdmi_audio_samples_perword {
HDMI_AUDIO_ONEWORD_ONESAMPLE = 0,
HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
};
enum hdmi_audio_sample_size {
HDMI_AUDIO_SAMPLE_16BITS = 0,
HDMI_AUDIO_SAMPLE_24BITS = 1
};
enum hdmi_audio_transf_mode {
HDMI_AUDIO_TRANSF_DMA = 0,
HDMI_AUDIO_TRANSF_IRQ = 1
};
enum hdmi_audio_blk_strt_end_sig {
HDMI_AUDIO_BLOCK_SIG_STARTEND_ON = 0,
HDMI_AUDIO_BLOCK_SIG_STARTEND_OFF = 1
};
enum hdmi_audio_i2s_config {
HDMI_AUDIO_I2S_WS_POLARITY_LOW_IS_LEFT = 0,
HDMI_AUDIO_I2S_WS_POLARIT_YLOW_IS_RIGHT = 1,
HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST = 0,
HDMI_AUDIO_I2S_LSB_SHIFTED_FIRST = 1,
HDMI_AUDIO_I2S_MAX_WORD_20BITS = 0,
HDMI_AUDIO_I2S_MAX_WORD_24BITS = 1,
HDMI_AUDIO_I2S_CHST_WORD_NOT_SPECIFIED = 0,
HDMI_AUDIO_I2S_CHST_WORD_16_BITS = 1,
HDMI_AUDIO_I2S_CHST_WORD_17_BITS = 6,
HDMI_AUDIO_I2S_CHST_WORD_18_BITS = 2,
HDMI_AUDIO_I2S_CHST_WORD_19_BITS = 4,
HDMI_AUDIO_I2S_CHST_WORD_20_BITS_20MAX = 5,
HDMI_AUDIO_I2S_CHST_WORD_20_BITS_24MAX = 1,
HDMI_AUDIO_I2S_CHST_WORD_21_BITS = 6,
HDMI_AUDIO_I2S_CHST_WORD_22_BITS = 2,
HDMI_AUDIO_I2S_CHST_WORD_23_BITS = 4,
HDMI_AUDIO_I2S_CHST_WORD_24_BITS = 5,
HDMI_AUDIO_I2S_SCK_EDGE_FALLING = 0,
HDMI_AUDIO_I2S_SCK_EDGE_RISING = 1,
HDMI_AUDIO_I2S_VBIT_FOR_PCM = 0,
HDMI_AUDIO_I2S_VBIT_FOR_COMPRESSED = 1,
HDMI_AUDIO_I2S_INPUT_LENGTH_NA = 0,
HDMI_AUDIO_I2S_INPUT_LENGTH_16 = 2,
HDMI_AUDIO_I2S_INPUT_LENGTH_17 = 12,
HDMI_AUDIO_I2S_INPUT_LENGTH_18 = 4,
HDMI_AUDIO_I2S_INPUT_LENGTH_19 = 8,
HDMI_AUDIO_I2S_INPUT_LENGTH_20 = 10,
HDMI_AUDIO_I2S_INPUT_LENGTH_21 = 13,
HDMI_AUDIO_I2S_INPUT_LENGTH_22 = 5,
HDMI_AUDIO_I2S_INPUT_LENGTH_23 = 9,
HDMI_AUDIO_I2S_INPUT_LENGTH_24 = 11,
HDMI_AUDIO_I2S_FIRST_BIT_SHIFT = 0,
HDMI_AUDIO_I2S_FIRST_BIT_NO_SHIFT = 1,
HDMI_AUDIO_I2S_SD0_EN = 1,
HDMI_AUDIO_I2S_SD1_EN = 1 << 1,
HDMI_AUDIO_I2S_SD2_EN = 1 << 2,
HDMI_AUDIO_I2S_SD3_EN = 1 << 3,
};
enum hdmi_audio_mclk_mode {
HDMI_AUDIO_MCLK_128FS = 0,
HDMI_AUDIO_MCLK_256FS = 1,
HDMI_AUDIO_MCLK_384FS = 2,
HDMI_AUDIO_MCLK_512FS = 3,
HDMI_AUDIO_MCLK_768FS = 4,
HDMI_AUDIO_MCLK_1024FS = 5,
HDMI_AUDIO_MCLK_1152FS = 6,
HDMI_AUDIO_MCLK_192FS = 7
};
struct hdmi_core_video_config {
enum hdmi_core_inputbus_width ip_bus_width;
enum hdmi_core_dither_trunc op_dither_truc;
@ -376,6 +530,19 @@ struct hdmi_core_infoframe_avi {
u16 db12_13_pixel_sofright;
/* Pixel number start of right bar */
};
/*
* Refer to section 8.2 in HDMI 1.3 specification for
* details about infoframe databytes
*/
struct hdmi_core_infoframe_audio {
u8 db1_coding_type;
u8 db1_channel_count;
u8 db2_sample_freq;
u8 db2_sample_size;
u8 db4_channel_alloc;
bool db5_downmix_inh;
u8 db5_lsv; /* Level shift values for downmix */
};
struct hdmi_core_packet_enable_repeat {
u32 audio_pkt;
@ -412,4 +579,53 @@ struct hdmi_config {
struct hdmi_cm cm;
};
struct hdmi_audio_format {
enum hdmi_stereo_channels stereo_channels;
u8 active_chnnls_msk;
enum hdmi_audio_type type;
enum hdmi_audio_justify justification;
enum hdmi_audio_sample_order sample_order;
enum hdmi_audio_samples_perword samples_per_word;
enum hdmi_audio_sample_size sample_size;
enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end;
};
struct hdmi_audio_dma {
u8 transfer_size;
u8 block_size;
enum hdmi_audio_transf_mode mode;
u16 fifo_threshold;
};
struct hdmi_core_audio_i2s_config {
u8 word_max_length;
u8 word_length;
u8 in_length_bits;
u8 justification;
u8 en_high_bitrate_aud;
u8 sck_edge_mode;
u8 cbit_order;
u8 vbit;
u8 ws_polarity;
u8 direction;
u8 shift;
u8 active_sds;
};
struct hdmi_core_audio_config {
struct hdmi_core_audio_i2s_config i2s_cfg;
enum hdmi_core_audio_sample_freq freq_sample;
bool fs_override;
u32 n;
u32 cts;
u32 aud_par_busclk;
enum hdmi_core_audio_layout layout;
enum hdmi_core_cts_mode cts_mode;
bool use_mclk;
enum hdmi_audio_mclk_mode mclk_mode;
bool en_acr_pkt;
bool en_dsd_audio;
bool en_parallel_aud_input;
bool en_spdif;
};
#endif

View File

@ -24,7 +24,7 @@
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "dss.h"

View File

@ -29,7 +29,7 @@
#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
@ -393,6 +393,7 @@ struct overlay_cache_data {
u32 paddr;
void __iomem *vaddr;
u32 p_uv_addr; /* relevant for NV12 format only */
u16 screen_width;
u16 width;
u16 height;
@ -775,10 +776,17 @@ static int configure_overlay(enum omap_plane plane)
}
switch (c->color_mode) {
case OMAP_DSS_COLOR_NV12:
bpp = 8;
break;
case OMAP_DSS_COLOR_RGB16:
case OMAP_DSS_COLOR_ARGB16:
case OMAP_DSS_COLOR_YUV2:
case OMAP_DSS_COLOR_UYVY:
case OMAP_DSS_COLOR_RGBA16:
case OMAP_DSS_COLOR_RGBX16:
case OMAP_DSS_COLOR_ARGB16_1555:
case OMAP_DSS_COLOR_XRGB16_1555:
bpp = 16;
break;
@ -854,7 +862,8 @@ static int configure_overlay(enum omap_plane plane)
c->mirror,
c->global_alpha,
c->pre_mult_alpha,
c->channel);
c->channel,
c->p_uv_addr);
if (r) {
/* this shouldn't happen */
@ -1269,6 +1278,7 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
oc->paddr = ovl->info.paddr;
oc->vaddr = ovl->info.vaddr;
oc->p_uv_addr = ovl->info.p_uv_addr;
oc->screen_width = ovl->info.screen_width;
oc->width = ovl->info.width;
oc->height = ovl->info.height;

View File

@ -31,7 +31,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
@ -201,12 +201,16 @@ static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
size_t size)
{
int r;
int r, enable;
struct omap_overlay_info info;
ovl->get_overlay_info(ovl, &info);
info.enabled = simple_strtoul(buf, NULL, 10);
r = kstrtoint(buf, 0, &enable);
if (r)
return r;
info.enabled = !!enable;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -231,8 +235,13 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
const char *buf, size_t size)
{
int r;
u8 alpha;
struct omap_overlay_info info;
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
ovl->get_overlay_info(ovl, &info);
/* Video1 plane does not support global alpha
@ -242,7 +251,7 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
ovl->id == OMAP_DSS_VIDEO1)
info.global_alpha = 255;
else
info.global_alpha = simple_strtoul(buf, NULL, 10);
info.global_alpha = alpha;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -268,8 +277,13 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
const char *buf, size_t size)
{
int r;
u8 alpha;
struct omap_overlay_info info;
r = kstrtou8(buf, 0, &alpha);
if (r)
return r;
ovl->get_overlay_info(ovl, &info);
/* only GFX and Video2 plane support pre alpha multiplied
@ -279,7 +293,7 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
ovl->id == OMAP_DSS_VIDEO1)
info.pre_mult_alpha = 0;
else
info.pre_mult_alpha = simple_strtoul(buf, NULL, 10);
info.pre_mult_alpha = alpha;
r = ovl->set_overlay_info(ovl, &info);
if (r)
@ -491,13 +505,18 @@ static int omap_dss_set_manager(struct omap_overlay *ovl,
ovl->manager = mgr;
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK);
/* XXX: on manual update display, in auto update mode, a bug happens
* here. When an overlay is first enabled on LCD, then it's disabled,
* and the manager is changed to TV, we sometimes get SYNC_LOST_DIGIT
* errors. Waiting before changing the channel_out fixes it. I'm
* guessing that the overlay is still somehow being used for the LCD,
* but I don't understand how or why. */
msleep(40);
/* XXX: When there is an overlay on a DSI manual update display, and
* the overlay is first disabled, then moved to tv, and enabled, we
* seem to get SYNC_LOST_DIGIT error.
*
* Waiting doesn't seem to help, but updating the manual update display
* after disabling the overlay seems to fix this. This hints that the
* overlay is perhaps somehow tied to the LCD output until the output
* is updated.
*
* Userspace workaround for this is to update the LCD after disabling
* the overlay, but before moving the overlay to TV.
*/
dispc_set_channel_out(ovl->id, mgr->id);
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);

View File

@ -32,8 +32,9 @@
#include <linux/ktime.h>
#include <linux/hrtimer.h>
#include <linux/seq_file.h>
#include <linux/semaphore.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include "dss.h"
struct rfbi_reg { u16 idx; };
@ -65,9 +66,6 @@ struct rfbi_reg { u16 idx; };
#define REG_FLD_MOD(idx, val, start, end) \
rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
/* To work around an RFBI transfer rate limitation */
#define OMAP_RFBI_RATE_LIMIT 1
enum omap_rfbi_cycleformat {
OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0,
OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1,
@ -89,11 +87,6 @@ enum omap_rfbi_parallelmode {
OMAP_DSS_RFBI_PARALLELMODE_16 = 3,
};
enum update_cmd {
RFBI_CMD_UPDATE = 0,
RFBI_CMD_SYNC = 1,
};
static int rfbi_convert_timings(struct rfbi_timings *t);
static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
@ -114,20 +107,9 @@ static struct {
struct omap_dss_device *dssdev[2];
struct kfifo cmd_fifo;
spinlock_t cmd_lock;
struct completion cmd_done;
atomic_t cmd_fifo_full;
atomic_t cmd_pending;
struct semaphore bus_lock;
} rfbi;
struct update_region {
u16 x;
u16 y;
u16 w;
u16 h;
};
static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
{
__raw_writel(val, rfbi.base + idx.idx);
@ -146,9 +128,20 @@ static void rfbi_enable_clocks(bool enable)
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK);
}
void rfbi_bus_lock(void)
{
down(&rfbi.bus_lock);
}
EXPORT_SYMBOL(rfbi_bus_lock);
void rfbi_bus_unlock(void)
{
up(&rfbi.bus_lock);
}
EXPORT_SYMBOL(rfbi_bus_unlock);
void omap_rfbi_write_command(const void *buf, u32 len)
{
rfbi_enable_clocks(1);
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
{
@ -172,13 +165,11 @@ void omap_rfbi_write_command(const void *buf, u32 len)
default:
BUG();
}
rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omap_rfbi_write_command);
void omap_rfbi_read_data(void *buf, u32 len)
{
rfbi_enable_clocks(1);
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
{
@ -206,13 +197,11 @@ void omap_rfbi_read_data(void *buf, u32 len)
default:
BUG();
}
rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omap_rfbi_read_data);
void omap_rfbi_write_data(const void *buf, u32 len)
{
rfbi_enable_clocks(1);
switch (rfbi.parallelmode) {
case OMAP_DSS_RFBI_PARALLELMODE_8:
{
@ -237,7 +226,6 @@ void omap_rfbi_write_data(const void *buf, u32 len)
BUG();
}
rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omap_rfbi_write_data);
@ -249,8 +237,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
int horiz_offset = scr_width - w;
int i;
rfbi_enable_clocks(1);
if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 &&
rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) {
const u16 __iomem *pd = buf;
@ -295,12 +281,10 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
} else {
BUG();
}
rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omap_rfbi_write_pixels);
void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
u16 height, void (*callback)(void *data), void *data)
{
u32 l;
@ -317,8 +301,6 @@ void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
rfbi.framedone_callback = callback;
rfbi.framedone_callback_data = data;
rfbi_enable_clocks(1);
rfbi_write_reg(RFBI_PIXEL_CNT, width * height);
l = rfbi_read_reg(RFBI_CONTROL);
@ -337,15 +319,11 @@ static void framedone_callback(void *data, u32 mask)
REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
rfbi_enable_clocks(0);
callback = rfbi.framedone_callback;
rfbi.framedone_callback = NULL;
if (callback != NULL)
callback(rfbi.framedone_callback_data);
atomic_set(&rfbi.cmd_pending, 0);
}
#if 1 /* VERBOSE */
@ -435,7 +413,7 @@ static int calc_extif_timings(struct rfbi_timings *t)
}
void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
{
int r;
@ -447,7 +425,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
BUG_ON(!t->converted);
rfbi_enable_clocks(1);
rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]);
rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]);
@ -456,7 +433,6 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t)
(t->tim[2] ? 1 : 0), 4, 4);
rfbi_print_timings();
rfbi_enable_clocks(0);
}
static int ps_to_rfbi_ticks(int time, int div)
@ -472,59 +448,6 @@ static int ps_to_rfbi_ticks(int time, int div)
return ret;
}
#ifdef OMAP_RFBI_RATE_LIMIT
unsigned long rfbi_get_max_tx_rate(void)
{
unsigned long l4_rate, dss1_rate;
int min_l4_ticks = 0;
int i;
/* According to TI this can't be calculated so make the
* adjustments for a couple of known frequencies and warn for
* others.
*/
static const struct {
unsigned long l4_clk; /* HZ */
unsigned long dss1_clk; /* HZ */
unsigned long min_l4_ticks;
} ftab[] = {
{ 55, 132, 7, }, /* 7.86 MPix/s */
{ 110, 110, 12, }, /* 9.16 MPix/s */
{ 110, 132, 10, }, /* 11 Mpix/s */
{ 120, 120, 10, }, /* 12 Mpix/s */
{ 133, 133, 10, }, /* 13.3 Mpix/s */
};
l4_rate = rfbi.l4_khz / 1000;
dss1_rate = dss_clk_get_rate(DSS_CLK_FCK) / 1000000;
for (i = 0; i < ARRAY_SIZE(ftab); i++) {
/* Use a window instead of an exact match, to account
* for different DPLL multiplier / divider pairs.
*/
if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
abs(ftab[i].dss1_clk - dss1_rate) < 3) {
min_l4_ticks = ftab[i].min_l4_ticks;
break;
}
}
if (i == ARRAY_SIZE(ftab)) {
/* Can't be sure, return anyway the maximum not
* rate-limited. This might cause a problem only for the
* tearing synchronisation.
*/
DSSERR("can't determine maximum RFBI transfer rate\n");
return rfbi.l4_khz * 1000;
}
return rfbi.l4_khz * 1000 / min_l4_ticks;
}
#else
int rfbi_get_max_tx_rate(void)
{
return rfbi.l4_khz * 1000;
}
#endif
static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div)
{
*clk_period = 1000000000 / rfbi.l4_khz;
@ -644,7 +567,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n",
mode, hs, vs, hs_pol_inv, vs_pol_inv);
rfbi_enable_clocks(1);
rfbi_write_reg(RFBI_HSYNC_WIDTH, hs);
rfbi_write_reg(RFBI_VSYNC_WIDTH, vs);
@ -657,7 +579,6 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
l &= ~(1 << 20);
else
l |= 1 << 20;
rfbi_enable_clocks(0);
return 0;
}
@ -672,7 +593,6 @@ int omap_rfbi_enable_te(bool enable, unsigned line)
if (line > (1 << 11) - 1)
return -EINVAL;
rfbi_enable_clocks(1);
l = rfbi_read_reg(RFBI_CONFIG(0));
l &= ~(0x3 << 2);
if (enable) {
@ -682,50 +602,12 @@ int omap_rfbi_enable_te(bool enable, unsigned line)
rfbi.te_enabled = 0;
rfbi_write_reg(RFBI_CONFIG(0), l);
rfbi_write_reg(RFBI_LINE_NUMBER, line);
rfbi_enable_clocks(0);
return 0;
}
EXPORT_SYMBOL(omap_rfbi_enable_te);
#if 0
static void rfbi_enable_config(int enable1, int enable2)
{
u32 l;
int cs = 0;
if (enable1)
cs |= 1<<0;
if (enable2)
cs |= 1<<1;
rfbi_enable_clocks(1);
l = rfbi_read_reg(RFBI_CONTROL);
l = FLD_MOD(l, cs, 3, 2);
l = FLD_MOD(l, 0, 1, 1);
rfbi_write_reg(RFBI_CONTROL, l);
l = rfbi_read_reg(RFBI_CONFIG(0));
l = FLD_MOD(l, 0, 3, 2); /* TRIGGERMODE: ITE */
/*l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */
/*l |= FLD_VAL(0, 8, 7); */ /* L4FORMAT, 1pix/L4 */
l = FLD_MOD(l, 0, 16, 16); /* A0POLARITY */
l = FLD_MOD(l, 1, 20, 20); /* TE_VSYNC_POLARITY */
l = FLD_MOD(l, 1, 21, 21); /* HSYNCPOLARITY */
l = FLD_MOD(l, OMAP_DSS_RFBI_PARALLELMODE_8, 1, 0);
rfbi_write_reg(RFBI_CONFIG(0), l);
rfbi_enable_clocks(0);
}
#endif
int rfbi_configure(int rfbi_module, int bpp, int lines)
static int rfbi_configure(int rfbi_module, int bpp, int lines)
{
u32 l;
int cycle1 = 0, cycle2 = 0, cycle3 = 0;
@ -821,8 +703,6 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
break;
}
rfbi_enable_clocks(1);
REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */
l = 0;
@ -856,11 +736,15 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n",
bpp, lines, cycle1, cycle2, cycle3);
rfbi_enable_clocks(0);
return 0;
}
EXPORT_SYMBOL(rfbi_configure);
int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
int data_lines)
{
return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines);
}
EXPORT_SYMBOL(omap_rfbi_configure);
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
u16 *x, u16 *y, u16 *w, u16 *h)
@ -960,6 +844,8 @@ int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
int r;
rfbi_enable_clocks(1);
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
@ -1002,6 +888,8 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
omap_dispc_unregister_isr(framedone_callback, NULL,
DISPC_IRQ_FRAMEDONE);
omap_dss_stop_device(dssdev);
rfbi_enable_clocks(0);
}
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
@ -1021,11 +909,7 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
rfbi.pdev = pdev;
spin_lock_init(&rfbi.cmd_lock);
init_completion(&rfbi.cmd_done);
atomic_set(&rfbi.cmd_fifo_full, 0);
atomic_set(&rfbi.cmd_pending, 0);
sema_init(&rfbi.bus_lock, 1);
rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0);
if (!rfbi_mem) {

View File

@ -25,7 +25,7 @@
#include <linux/err.h>
#include <linux/regulator/consumer.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"

View File

@ -34,7 +34,7 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/cpu.h>
#include "dss.h"
@ -373,8 +373,11 @@ static void venc_reset(void)
}
}
#ifdef CONFIG_OMAP2_DSS_SLEEP_AFTER_VENC_RESET
/* the magical sleep that makes things work */
/* XXX more info? What bug this circumvents? */
msleep(20);
#endif
}
static void venc_enable_clocks(int enable)
@ -473,6 +476,12 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
mutex_lock(&venc.venc_lock);
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
goto err0;
}
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
r = -EINVAL;
goto err1;
@ -484,10 +493,11 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
/* wait couple of vsyncs until enabling the LCD */
msleep(50);
mutex_unlock(&venc.venc_lock);
return 0;
err1:
omap_dss_stop_device(dssdev);
err0:
mutex_unlock(&venc.venc_lock);
return r;
@ -510,10 +520,9 @@ static void venc_panel_disable(struct omap_dss_device *dssdev)
venc_power_off(dssdev);
/* wait at least 5 vsyncs after disabling the LCD */
msleep(100);
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
omap_dss_stop_device(dssdev);
end:
mutex_unlock(&venc.venc_lock);
}

View File

@ -28,7 +28,7 @@
#include <linux/omapfb.h>
#include <linux/vmalloc.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/vrfb.h>
#include <plat/vram.h>
@ -895,8 +895,16 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
p.display_info.xres = xres;
p.display_info.yres = yres;
p.display_info.width = 0;
p.display_info.height = 0;
if (display->driver->get_dimensions) {
u32 w, h;
display->driver->get_dimensions(display, &w, &h);
p.display_info.width = w;
p.display_info.height = h;
} else {
p.display_info.width = 0;
p.display_info.height = 0;
}
if (copy_to_user((void __user *)arg, &p.display_info,
sizeof(p.display_info)))

View File

@ -30,7 +30,7 @@
#include <linux/platform_device.h>
#include <linux/omapfb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/vram.h>
#include <plat/vrfb.h>
@ -702,8 +702,16 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
var->xres, var->yres,
var->xres_virtual, var->yres_virtual);
var->height = -1;
var->width = -1;
if (display && display->driver->get_dimensions) {
u32 w, h;
display->driver->get_dimensions(display, &w, &h);
var->width = DIV_ROUND_CLOSEST(w, 1000);
var->height = DIV_ROUND_CLOSEST(h, 1000);
} else {
var->height = -1;
var->width = -1;
}
var->grayscale = 0;
if (display && display->driver->get_timings) {
@ -749,35 +757,6 @@ static int omapfb_open(struct fb_info *fbi, int user)
static int omapfb_release(struct fb_info *fbi, int user)
{
#if 0
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
DBG("Closing fb with plane index %d\n", ofbi->id);
omapfb_lock(fbdev);
if (display && display->get_update_mode && display->update) {
/* XXX this update should be removed, I think. But it's
* good for debugging */
if (display->get_update_mode(display) ==
OMAP_DSS_UPDATE_MANUAL) {
u16 w, h;
if (display->sync)
display->sync(display);
display->get_resolution(display, &w, &h);
display->update(display, 0, 0, w, h);
}
}
if (display && display->sync)
display->sync(display);
omapfb_unlock(fbdev);
#endif
return 0;
}
@ -1263,7 +1242,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_device *fbdev = ofbi->fbdev;
struct omap_dss_device *display = fb2display(fbi);
int do_update = 0;
int r = 0;
if (!display)
@ -1279,11 +1257,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
if (display->driver->resume)
r = display->driver->resume(display);
if (r == 0 && display->driver->get_update_mode &&
display->driver->get_update_mode(display) ==
OMAP_DSS_UPDATE_MANUAL)
do_update = 1;
break;
case FB_BLANK_NORMAL:
@ -1307,13 +1280,6 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
exit:
omapfb_unlock(fbdev);
if (r == 0 && do_update && display->driver->update) {
u16 w, h;
display->driver->get_resolution(display, &w, &h);
r = display->driver->update(display, 0, 0, w, h);
}
return r;
}
@ -2030,9 +1996,9 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
static int omapfb_mode_to_timings(const char *mode_str,
struct omap_video_timings *timings, u8 *bpp)
{
struct fb_info fbi;
struct fb_var_screeninfo var;
struct fb_ops fbops;
struct fb_info *fbi;
struct fb_var_screeninfo *var;
struct fb_ops *fbops;
int r;
#ifdef CONFIG_OMAP2_DSS_VENC
@ -2050,39 +2016,66 @@ static int omapfb_mode_to_timings(const char *mode_str,
/* this is quite a hack, but I wanted to use the modedb and for
* that we need fb_info and var, so we create dummy ones */
memset(&fbi, 0, sizeof(fbi));
memset(&var, 0, sizeof(var));
memset(&fbops, 0, sizeof(fbops));
fbi.fbops = &fbops;
*bpp = 0;
fbi = NULL;
var = NULL;
fbops = NULL;
r = fb_find_mode(&var, &fbi, mode_str, NULL, 0, NULL, 24);
if (r != 0) {
timings->pixel_clock = PICOS2KHZ(var.pixclock);
timings->hbp = var.left_margin;
timings->hfp = var.right_margin;
timings->vbp = var.upper_margin;
timings->vfp = var.lower_margin;
timings->hsw = var.hsync_len;
timings->vsw = var.vsync_len;
timings->x_res = var.xres;
timings->y_res = var.yres;
switch (var.bits_per_pixel) {
case 16:
*bpp = 16;
break;
case 24:
case 32:
default:
*bpp = 24;
break;
}
return 0;
} else {
return -EINVAL;
fbi = kzalloc(sizeof(*fbi), GFP_KERNEL);
if (fbi == NULL) {
r = -ENOMEM;
goto err;
}
var = kzalloc(sizeof(*var), GFP_KERNEL);
if (var == NULL) {
r = -ENOMEM;
goto err;
}
fbops = kzalloc(sizeof(*fbops), GFP_KERNEL);
if (fbops == NULL) {
r = -ENOMEM;
goto err;
}
fbi->fbops = fbops;
r = fb_find_mode(var, fbi, mode_str, NULL, 0, NULL, 24);
if (r == 0) {
r = -EINVAL;
goto err;
}
timings->pixel_clock = PICOS2KHZ(var->pixclock);
timings->hbp = var->left_margin;
timings->hfp = var->right_margin;
timings->vbp = var->upper_margin;
timings->vfp = var->lower_margin;
timings->hsw = var->hsync_len;
timings->vsw = var->vsync_len;
timings->x_res = var->xres;
timings->y_res = var->yres;
switch (var->bits_per_pixel) {
case 16:
*bpp = 16;
break;
case 24:
case 32:
default:
*bpp = 24;
break;
}
r = 0;
err:
kfree(fbi);
kfree(var);
kfree(fbops);
return r;
}
static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
@ -2185,6 +2178,61 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
return r;
}
static int omapfb_init_display(struct omapfb2_device *fbdev,
struct omap_dss_device *dssdev)
{
struct omap_dss_driver *dssdrv = dssdev->driver;
int r;
r = dssdrv->enable(dssdev);
if (r) {
dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
dssdev->name);
return r;
}
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
u16 w, h;
if (dssdrv->enable_te) {
r = dssdrv->enable_te(dssdev, 1);
if (r) {
dev_err(fbdev->dev, "Failed to set TE\n");
return r;
}
}
if (dssdrv->set_update_mode) {
r = dssdrv->set_update_mode(dssdev,
OMAP_DSS_UPDATE_MANUAL);
if (r) {
dev_err(fbdev->dev,
"Failed to set update mode\n");
return r;
}
}
dssdrv->get_resolution(dssdev, &w, &h);
r = dssdrv->update(dssdev, 0, 0, w, h);
if (r) {
dev_err(fbdev->dev,
"Failed to update display\n");
return r;
}
} else {
if (dssdrv->set_update_mode) {
r = dssdrv->set_update_mode(dssdev,
OMAP_DSS_UPDATE_AUTO);
if (r) {
dev_err(fbdev->dev,
"Failed to set update mode\n");
return r;
}
}
}
return 0;
}
static int omapfb_probe(struct platform_device *pdev)
{
struct omapfb2_device *fbdev = NULL;
@ -2284,30 +2332,13 @@ static int omapfb_probe(struct platform_device *pdev)
}
if (def_display) {
struct omap_dss_driver *dssdrv = def_display->driver;
r = def_display->driver->enable(def_display);
r = omapfb_init_display(fbdev, def_display);
if (r) {
dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
def_display->name);
dev_err(fbdev->dev,
"failed to initialize default "
"display\n");
goto cleanup;
}
if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
u16 w, h;
if (dssdrv->enable_te)
dssdrv->enable_te(def_display, 1);
if (dssdrv->set_update_mode)
dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_MANUAL);
dssdrv->get_resolution(def_display, &w, &h);
def_display->driver->update(def_display, 0, 0, w, h);
} else {
if (dssdrv->set_update_mode)
dssdrv->set_update_mode(def_display,
OMAP_DSS_UPDATE_AUTO);
}
}
DBG("create sysfs for fbs\n");

View File

@ -29,7 +29,7 @@
#include <linux/mm.h>
#include <linux/omapfb.h>
#include <plat/display.h>
#include <video/omapdss.h>
#include <plat/vrfb.h>
#include "omapfb.h"
@ -50,10 +50,12 @@ static ssize_t store_rotate_type(struct device *dev,
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
struct omapfb2_mem_region *rg;
enum omap_dss_rotation_type rot_type;
int rot_type;
int r;
rot_type = simple_strtoul(buf, NULL, 0);
r = kstrtoint(buf, 0, &rot_type);
if (r)
return r;
if (rot_type != OMAP_DSS_ROT_DMA && rot_type != OMAP_DSS_ROT_VRFB)
return -EINVAL;
@ -102,14 +104,15 @@ static ssize_t store_mirror(struct device *dev,
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct omapfb_info *ofbi = FB2OFB(fbi);
unsigned long mirror;
int mirror;
int r;
struct fb_var_screeninfo new_var;
mirror = simple_strtoul(buf, NULL, 0);
r = kstrtoint(buf, 0, &mirror);
if (r)
return r;
if (mirror != 0 && mirror != 1)
return -EINVAL;
mirror = !!mirror;
if (!lock_fb_info(fbi))
return -ENODEV;
@ -445,7 +448,11 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
int r;
int i;
size = PAGE_ALIGN(simple_strtoul(buf, NULL, 0));
r = kstrtoul(buf, 0, &size);
if (r)
return r;
size = PAGE_ALIGN(size);
if (!lock_fb_info(fbi))
return -ENODEV;

View File

@ -29,13 +29,15 @@
#include <linux/rwsem.h>
#include <plat/display.h>
#include <video/omapdss.h>
#ifdef DEBUG
extern unsigned int omapfb_debug;
#define DBG(format, ...) \
if (omapfb_debug) \
printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__)
do { \
if (omapfb_debug) \
printk(KERN_DEBUG "OMAPFB: " format, ## __VA_ARGS__); \
} while (0)
#else
#define DBG(format, ...)
#endif

View File

@ -17,10 +17,10 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H
#define __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H
#ifndef __OMAP_PANEL_GENERIC_DPI_H
#define __OMAP_PANEL_GENERIC_DPI_H
#include "display.h"
struct omap_dss_device;
/**
* struct panel_generic_dpi_data - panel driver configuration data
@ -34,4 +34,4 @@ struct panel_generic_dpi_data {
void (*platform_disable)(struct omap_dss_device *dssdev);
};
#endif /* __ARCH_ARM_PLAT_OMAP_PANEL_GENERIC_DPI_H */
#endif /* __OMAP_PANEL_GENERIC_DPI_H */

View File

@ -1,14 +1,15 @@
#ifndef __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H
#define __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H
#ifndef __OMAP_NOKIA_DSI_PANEL_H
#define __OMAP_NOKIA_DSI_PANEL_H
#include "display.h"
struct omap_dss_device;
/**
* struct nokia_dsi_panel_data - Nokia DSI panel driver configuration
* @name: panel name
* @use_ext_te: use external TE
* @ext_te_gpio: external TE GPIO
* @use_esd_check: perform ESD checks
* @esd_interval: interval of ESD checks, 0 = disabled (ms)
* @ulps_timeout: time to wait before entering ULPS, 0 = disabled (ms)
* @max_backlight_level: maximum backlight level
* @set_backlight: pointer to backlight set function
* @get_backlight: pointer to backlight get function
@ -21,11 +22,12 @@ struct nokia_dsi_panel_data {
bool use_ext_te;
int ext_te_gpio;
bool use_esd_check;
unsigned esd_interval;
unsigned ulps_timeout;
int max_backlight_level;
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
int (*get_backlight)(struct omap_dss_device *dssdev);
};
#endif /* __ARCH_ARM_PLAT_OMAP_NOKIA_DSI_PANEL_H */
#endif /* __OMAP_NOKIA_DSI_PANEL_H */

View File

@ -1,6 +1,4 @@
/*
* linux/include/asm-arm/arch-omap/display.h
*
* Copyright (C) 2008 Nokia Corporation
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
*
@ -17,8 +15,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ARCH_OMAP_DISPLAY_H
#define __ASM_ARCH_OMAP_DISPLAY_H
#ifndef __OMAP_OMAPDSS_H
#define __OMAP_OMAPDSS_H
#include <linux/list.h>
#include <linux/kobject.h>
@ -88,6 +86,11 @@ enum omap_color_mode {
OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
OMAP_DSS_COLOR_NV12 = 1 << 14, /* NV12 format: YUV 4:2:0 */
OMAP_DSS_COLOR_RGBA16 = 1 << 15, /* RGBA16 - 4444 */
OMAP_DSS_COLOR_RGBX16 = 1 << 16, /* RGBx16 - 4444 */
OMAP_DSS_COLOR_ARGB16_1555 = 1 << 17, /* ARGB16 - 1555 */
OMAP_DSS_COLOR_XRGB16_1555 = 1 << 18, /* xRGB16 - 1555 */
};
enum omap_lcd_display_type {
@ -174,6 +177,17 @@ enum omap_overlay_manager_caps {
OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
};
enum omap_dss_clk_source {
OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK
* OMAP4: DSS_FCLK */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
* OMAP4: PLL1_CLK1 */
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
* OMAP4: PLL1_CLK2 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
};
/* RFBI */
struct rfbi_timings {
@ -205,20 +219,30 @@ int omap_rfbi_enable_te(bool enable, unsigned line);
int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
unsigned hs_pulse_time, unsigned vs_pulse_time,
int hs_pol_inv, int vs_pol_inv, int extif_div);
void rfbi_bus_lock(void);
void rfbi_bus_unlock(void);
/* DSI */
void dsi_bus_lock(void);
void dsi_bus_unlock(void);
int dsi_vc_dcs_write(int channel, u8 *data, int len);
int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd);
int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param);
int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data);
int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u8 *data1, u8 *data2);
int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
int dsi_vc_send_null(int channel);
int dsi_vc_send_bta_sync(int channel);
void dsi_bus_lock(struct omap_dss_device *dssdev);
void dsi_bus_unlock(struct omap_dss_device *dssdev);
int dsi_vc_dcs_write(struct omap_dss_device *dssdev, int channel, u8 *data,
int len);
int dsi_vc_dcs_write_0(struct omap_dss_device *dssdev, int channel,
u8 dcs_cmd);
int dsi_vc_dcs_write_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 param);
int dsi_vc_dcs_write_nosync(struct omap_dss_device *dssdev, int channel,
u8 *data, int len);
int dsi_vc_dcs_read(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 *buf, int buflen);
int dsi_vc_dcs_read_1(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 *data);
int dsi_vc_dcs_read_2(struct omap_dss_device *dssdev, int channel, u8 dcs_cmd,
u8 *data1, u8 *data2);
int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
u16 len);
int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
/* Board specific data */
struct omap_dss_board_info {
@ -226,6 +250,7 @@ struct omap_dss_board_info {
int num_devices;
struct omap_dss_device **devices;
struct omap_dss_device *default_device;
void (*dsi_mux_pads)(bool enable);
};
#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
@ -280,6 +305,7 @@ struct omap_overlay_info {
u32 paddr;
void __iomem *vaddr;
u32 p_uv_addr; /* for NV12 format */
u16 screen_width;
u16 width;
u16 height;
@ -400,18 +426,12 @@ struct omap_dss_device {
u8 data1_pol;
u8 data2_lane;
u8 data2_pol;
u8 data3_lane;
u8 data3_pol;
u8 data4_lane;
u8 data4_pol;
struct {
u16 regn;
u16 regm;
u16 regm_dispc;
u16 regm_dsi;
u16 lp_clk_div;
u16 lck_div;
u16 pck_div;
} div;
int module;
bool ext_te;
u8 ext_te_gpio;
@ -423,6 +443,33 @@ struct omap_dss_device {
} venc;
} phy;
struct {
struct {
struct {
u16 lck_div;
u16 pck_div;
enum omap_dss_clk_source lcd_clk_src;
} channel;
enum omap_dss_clk_source dispc_fclk_src;
} dispc;
struct {
u16 regn;
u16 regm;
u16 regm_dispc;
u16 regm_dsi;
u16 lp_clk_div;
enum omap_dss_clk_source dsi_fclk_src;
} dsi;
struct {
u16 regn;
u16 regm2;
} hdmi;
} clocks;
struct {
struct omap_video_timings timings;
@ -503,6 +550,8 @@ struct omap_dss_driver {
void (*get_resolution)(struct omap_dss_device *dssdev,
u16 *xres, u16 *yres);
void (*get_dimensions)(struct omap_dss_device *dssdev,
u32 *width, u32 *height);
int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
int (*check_timings)(struct omap_dss_device *dssdev,
@ -519,9 +568,6 @@ struct omap_dss_driver {
int omap_dss_register_driver(struct omap_dss_driver *);
void omap_dss_unregister_driver(struct omap_dss_driver *);
int omap_dss_register_device(struct omap_dss_device *);
void omap_dss_unregister_device(struct omap_dss_device *);
void omap_dss_get_device(struct omap_dss_device *dssdev);
void omap_dss_put_device(struct omap_dss_device *dssdev);
#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
@ -553,7 +599,8 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
void omapdss_dsi_vc_enable_hs(int channel, bool enable);
void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
bool enable);
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
@ -568,7 +615,8 @@ int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev,
bool disconnect_lanes, bool enter_ulps);
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
@ -587,5 +635,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
int omap_rfbi_update(struct omap_dss_device *dssdev,
u16 x, u16 y, u16 w, u16 h,
void (*callback)(void *), void *data);
int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size,
int data_lines);
#endif