mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
fbdev updates for 3.5
It includes: - driver for AUO-K1900 and AUO-K1901 epaper controller - large updates for OMAP (e.g. decouple HDMI audio and video) - some updates for Exynos and SH Mobile - various other small fixes and cleanups -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.12 (GNU/Linux) iQIcBAABAgAGBQJPyAhmAAoJECSVL5KnPj1PBcoQAIWftuoXo3sk94f5jKcV4Ucx MthEc5iEpMVs8xaEruHHNHXWv8ic0x/PfdC2xrpKOEbNXQcNPlb/QE2xWmBRxmT1 ucDyu10HJ36jKcwcK4ra5IQwOW+GtbTBEoBZT+WNAjxHZtJmxzjQGM4C12zVQpdJ +qV2RP93JmsJoVBL9aKVAg1Ko135LLfD8TcKd+z8TmgFnLfSwKhfl7Jtd2xXwyvz /hmW3kJUEnD8E5wuj+/g8sKJhQkGalEiITTqG2j2vJyFgxHSqyLSw8BBixrFW1uT B9VnZsHF35ccCo+96UZRH4QsGJTx08+rea/qsv8IMSGczyRp5ey1ufjL+CzKiiIN FWfex6fY0HHqZGAopQhjag54e914SIbSxdBwWS/iRrtVt3e9d03BzkhYs4rXl4Ey CTC5obzWNTbQ6hLEjgWfVKkKcrF56BnRn3zGPgCTKGp2NK3vODdBkt/EmzUFvCWR CcyQhh+PvZzEWp3XsdOGossYs/0aP4bO+7XPGJxZaa3+WVcRaZwAG/uZvJXXBfnp DGRFy4wPsTTwKYIx4+t/KrsLtNVKioSMS5GEtuM1YEb8pA7mkUIkqwJv1I261h58 heTr6vWUsviUqHlKALJ+1CdwWGr3CtktCZssGsSUri61nm8CvlSRn2Nr2aJ/L3RN AkemC/33RE5X/+lfkdMx =tmIU -----END PGP SIGNATURE----- Merge tag 'fbdev-updates-for-3.5' of git://github.com/schandinat/linux-2.6 Pull fbdev updates from Florian Tobias Schandinat: - driver for AUO-K1900 and AUO-K1901 epaper controller - large updates for OMAP (e.g. decouple HDMI audio and video) - some updates for Exynos and SH Mobile - various other small fixes and cleanups * tag 'fbdev-updates-for-3.5' of git://github.com/schandinat/linux-2.6: (130 commits) video: bfin_adv7393fb: Fix cleanup code video: exynos_dp: reduce delay time when configuring video setting video: exynos_dp: move sw reset prioir to enabling sw defined function video: exynos_dp: use devm_ functions fb: handle NULL pointers in framebuffer release OMAPDSS: HDMI: OMAP4: Update IRQ flags for the HPD IRQ request OMAPDSS: Apply VENC timings even if panel is disabled OMAPDSS: VENC/DISPC: Delay dividing Y resolution for managers connected to VENC OMAPDSS: DISPC: Support rotation through TILER OMAPDSS: VRFB: remove compiler warnings when CONFIG_BUG=n OMAPFB: remove compiler warnings when CONFIG_BUG=n OMAPDSS: remove compiler warnings when CONFIG_BUG=n OMAPDSS: DISPC: fix usage of dispc_ovl_set_accu_uv OMAPDSS: use DSI_FIFO_BUG workaround only for manual update displays OMAPDSS: DSI: Support command mode interleaving during video mode blanking periods OMAPDSS: DISPC: Update Accumulator configuration for chroma plane drivers/video: fsl-diu-fb: don't initialize the THRESHOLDS registers video: exynos mipi dsi: support reverse panel type video: exynos mipi dsi: Properly interpret the interrupt source flags video: exynos mipi dsi: Avoid races in probe() ...
This commit is contained in:
commit
804ce9866d
@ -47,6 +47,51 @@ flexible way to enable non-common multi-display configuration. In addition to
|
||||
modelling the hardware overlays, omapdss supports virtual overlays and overlay
|
||||
managers. These can be used when updating a display with CPU or system DMA.
|
||||
|
||||
omapdss driver support for audio
|
||||
--------------------------------
|
||||
There exist several display technologies and standards that support audio as
|
||||
well. Hence, it is relevant to update the DSS device driver to provide an audio
|
||||
interface that may be used by an audio driver or any other driver interested in
|
||||
the functionality.
|
||||
|
||||
The audio_enable function is intended to prepare the relevant
|
||||
IP for playback (e.g., enabling an audio FIFO, taking in/out of reset
|
||||
some IP, enabling companion chips, etc). It is intended to be called before
|
||||
audio_start. The audio_disable function performs the reverse operation and is
|
||||
intended to be called after audio_stop.
|
||||
|
||||
While a given DSS device driver may support audio, it is possible that for
|
||||
certain configurations audio is not supported (e.g., an HDMI display using a
|
||||
VESA video timing). The audio_supported function is intended to query whether
|
||||
the current configuration of the display supports audio.
|
||||
|
||||
The audio_config function is intended to configure all the relevant audio
|
||||
parameters of the display. In order to make the function independent of any
|
||||
specific DSS device driver, a struct omap_dss_audio is defined. Its purpose
|
||||
is to contain all the required parameters for audio configuration. At the
|
||||
moment, such structure contains pointers to IEC-60958 channel status word
|
||||
and CEA-861 audio infoframe structures. This should be enough to support
|
||||
HDMI and DisplayPort, as both are based on CEA-861 and IEC-60958.
|
||||
|
||||
The audio_enable/disable, audio_config and audio_supported functions could be
|
||||
implemented as functions that may sleep. Hence, they should not be called
|
||||
while holding a spinlock or a readlock.
|
||||
|
||||
The audio_start/audio_stop function is intended to effectively start/stop audio
|
||||
playback after the configuration has taken place. These functions are designed
|
||||
to be used in an atomic context. Hence, audio_start should return quickly and be
|
||||
called only after all the needed resources for audio playback (audio FIFOs,
|
||||
DMA channels, companion chips, etc) have been enabled to begin data transfers.
|
||||
audio_stop is designed to only stop the audio transfers. The resources used
|
||||
for playback are released using audio_disable.
|
||||
|
||||
The enum omap_dss_audio_state may be used to help the implementations of
|
||||
the interface to keep track of the audio state. The initial state is _DISABLED;
|
||||
then, the state transitions to _CONFIGURED, and then, when it is ready to
|
||||
play audio, to _ENABLED. The state _PLAYING is used when the audio is being
|
||||
rendered.
|
||||
|
||||
|
||||
Panel and controller drivers
|
||||
----------------------------
|
||||
|
||||
@ -156,6 +201,7 @@ timings Display timings (pixclock,xres/hfp/hbp/hsw,yres/vfp/vbp/vsw)
|
||||
"pal" and "ntsc"
|
||||
panel_name
|
||||
tear_elim Tearing elimination 0=off, 1=on
|
||||
output_type Output type (video encoder only): "composite" or "svideo"
|
||||
|
||||
There are also some debugfs files at <debugfs>/omapdss/ which show information
|
||||
about clocks and registers.
|
||||
|
@ -237,25 +237,29 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
|
||||
#else
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win nuri_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 64,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 64,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 48,
|
||||
.vsync_len = 3,
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
.refresh = 60,
|
||||
},
|
||||
.max_bpp = 24,
|
||||
.default_bpp = 16,
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
.virtual_x = 1024,
|
||||
.virtual_y = 2 * 600,
|
||||
};
|
||||
|
||||
static struct fb_videomode nuri_lcd_timing = {
|
||||
.left_margin = 64,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 64,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 48,
|
||||
.vsync_len = 3,
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
.refresh = 60,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata nuri_fb_pdata __initdata = {
|
||||
.win[0] = &nuri_fb_win0,
|
||||
.vtiming = &nuri_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
|
||||
VIDCON0_CLKSEL_LCD,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -604,24 +604,28 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
|
||||
};
|
||||
#else
|
||||
static struct s3c_fb_pd_win origen_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 64,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 64,
|
||||
.lower_margin = 16,
|
||||
.hsync_len = 48,
|
||||
.vsync_len = 3,
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
},
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.virtual_x = 1024,
|
||||
.virtual_y = 2 * 600,
|
||||
};
|
||||
|
||||
static struct fb_videomode origen_lcd_timing = {
|
||||
.left_margin = 64,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 64,
|
||||
.lower_margin = 16,
|
||||
.hsync_len = 48,
|
||||
.vsync_len = 3,
|
||||
.xres = 1024,
|
||||
.yres = 600,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata origen_lcd_pdata __initdata = {
|
||||
.win[0] = &origen_fb_win0,
|
||||
.vtiming = &origen_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
|
||||
VIDCON1_INV_VCLK,
|
||||
|
@ -178,22 +178,26 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
|
||||
};
|
||||
#else
|
||||
static struct s3c_fb_pd_win smdkv310_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 13,
|
||||
.right_margin = 8,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdkv310_lcd_timing = {
|
||||
.left_margin = 13,
|
||||
.right_margin = 8,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smdkv310_lcd0_pdata __initdata = {
|
||||
.win[0] = &smdkv310_fb_win0,
|
||||
.vtiming = &smdkv310_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
.setup_gpio = exynos4_fimd0_gpio_setup_24bpp,
|
||||
|
@ -843,25 +843,29 @@ static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
|
||||
#else
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win universal_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 2,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.refresh = 55,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.virtual_x = 480,
|
||||
.virtual_y = 2 * 800,
|
||||
};
|
||||
|
||||
static struct fb_videomode universal_lcd_timing = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 2,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.refresh = 55,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata universal_lcd_pdata __initdata = {
|
||||
.win[0] = &universal_fb_win0,
|
||||
.vtiming = &universal_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
|
||||
VIDCON0_CLKSEL_LCD,
|
||||
.vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
|
||||
|
@ -180,16 +180,133 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
|
||||
omap4_dsi_mux_pads(dsi_id, 0);
|
||||
}
|
||||
|
||||
static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
|
||||
{
|
||||
return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput);
|
||||
}
|
||||
|
||||
static struct platform_device *create_dss_pdev(const char *pdev_name,
|
||||
int pdev_id, const char *oh_name, void *pdata, int pdata_len,
|
||||
struct platform_device *parent)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct omap_device *od;
|
||||
struct omap_hwmod *ohs[1];
|
||||
struct omap_hwmod *oh;
|
||||
int r;
|
||||
|
||||
oh = omap_hwmod_lookup(oh_name);
|
||||
if (!oh) {
|
||||
pr_err("Could not look up %s\n", oh_name);
|
||||
r = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pdev = platform_device_alloc(pdev_name, pdev_id);
|
||||
if (!pdev) {
|
||||
pr_err("Could not create pdev for %s\n", pdev_name);
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (parent != NULL)
|
||||
pdev->dev.parent = &parent->dev;
|
||||
|
||||
if (pdev->id != -1)
|
||||
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
|
||||
else
|
||||
dev_set_name(&pdev->dev, "%s", pdev->name);
|
||||
|
||||
ohs[0] = oh;
|
||||
od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
|
||||
if (!od) {
|
||||
pr_err("Could not alloc omap_device for %s\n", pdev_name);
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = platform_device_add_data(pdev, pdata, pdata_len);
|
||||
if (r) {
|
||||
pr_err("Could not set pdata for %s\n", pdev_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omap_device_register(pdev);
|
||||
if (r) {
|
||||
pr_err("Could not register omap_device for %s\n", pdev_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return pdev;
|
||||
|
||||
err:
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
|
||||
static struct platform_device *create_simple_dss_pdev(const char *pdev_name,
|
||||
int pdev_id, void *pdata, int pdata_len,
|
||||
struct platform_device *parent)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int r;
|
||||
|
||||
pdev = platform_device_alloc(pdev_name, pdev_id);
|
||||
if (!pdev) {
|
||||
pr_err("Could not create pdev for %s\n", pdev_name);
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (parent != NULL)
|
||||
pdev->dev.parent = &parent->dev;
|
||||
|
||||
if (pdev->id != -1)
|
||||
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
|
||||
else
|
||||
dev_set_name(&pdev->dev, "%s", pdev->name);
|
||||
|
||||
r = platform_device_add_data(pdev, pdata, pdata_len);
|
||||
if (r) {
|
||||
pr_err("Could not set pdata for %s\n", pdev_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omap_device_register(pdev);
|
||||
if (r) {
|
||||
pr_err("Could not register omap_device for %s\n", pdev_name);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return pdev;
|
||||
|
||||
err:
|
||||
return ERR_PTR(r);
|
||||
}
|
||||
|
||||
int __init omap_display_init(struct omap_dss_board_info *board_data)
|
||||
{
|
||||
int r = 0;
|
||||
struct omap_hwmod *oh;
|
||||
struct platform_device *pdev;
|
||||
int i, oh_count;
|
||||
struct omap_display_platform_data pdata;
|
||||
const struct omap_dss_hwmod_data *curr_dss_hwmod;
|
||||
struct platform_device *dss_pdev;
|
||||
|
||||
memset(&pdata, 0, sizeof(pdata));
|
||||
/* create omapdss device */
|
||||
|
||||
board_data->dsi_enable_pads = omap_dsi_enable_pads;
|
||||
board_data->dsi_disable_pads = omap_dsi_disable_pads;
|
||||
board_data->get_context_loss_count = omap_pm_get_dev_context_loss_count;
|
||||
board_data->set_min_bus_tput = omap_dss_set_min_bus_tput;
|
||||
|
||||
omap_display_device.dev.platform_data = board_data;
|
||||
|
||||
r = platform_device_register(&omap_display_device);
|
||||
if (r < 0) {
|
||||
pr_err("Unable to register omapdss device\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
/* create devices for dss hwmods */
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
curr_dss_hwmod = omap2_dss_hwmod_data;
|
||||
@ -202,39 +319,58 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
|
||||
oh_count = ARRAY_SIZE(omap4_dss_hwmod_data);
|
||||
}
|
||||
|
||||
if (board_data->dsi_enable_pads == NULL)
|
||||
board_data->dsi_enable_pads = omap_dsi_enable_pads;
|
||||
if (board_data->dsi_disable_pads == NULL)
|
||||
board_data->dsi_disable_pads = omap_dsi_disable_pads;
|
||||
/*
|
||||
* First create the pdev for dss_core, which is used as a parent device
|
||||
* by the other dss pdevs. Note: dss_core has to be the first item in
|
||||
* the hwmod list.
|
||||
*/
|
||||
dss_pdev = create_dss_pdev(curr_dss_hwmod[0].dev_name,
|
||||
curr_dss_hwmod[0].id,
|
||||
curr_dss_hwmod[0].oh_name,
|
||||
board_data, sizeof(*board_data),
|
||||
NULL);
|
||||
|
||||
pdata.board_data = board_data;
|
||||
pdata.board_data->get_context_loss_count =
|
||||
omap_pm_get_dev_context_loss_count;
|
||||
if (IS_ERR(dss_pdev)) {
|
||||
pr_err("Could not build omap_device for %s\n",
|
||||
curr_dss_hwmod[0].oh_name);
|
||||
|
||||
for (i = 0; i < oh_count; i++) {
|
||||
oh = omap_hwmod_lookup(curr_dss_hwmod[i].oh_name);
|
||||
if (!oh) {
|
||||
pr_err("Could not look up %s\n",
|
||||
curr_dss_hwmod[i].oh_name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdev = omap_device_build(curr_dss_hwmod[i].dev_name,
|
||||
curr_dss_hwmod[i].id, oh, &pdata,
|
||||
sizeof(struct omap_display_platform_data),
|
||||
NULL, 0, 0);
|
||||
|
||||
if (WARN((IS_ERR(pdev)), "Could not build omap_device for %s\n",
|
||||
curr_dss_hwmod[i].oh_name))
|
||||
return -ENODEV;
|
||||
return PTR_ERR(dss_pdev);
|
||||
}
|
||||
omap_display_device.dev.platform_data = board_data;
|
||||
|
||||
r = platform_device_register(&omap_display_device);
|
||||
if (r < 0)
|
||||
printk(KERN_ERR "Unable to register OMAP-Display device\n");
|
||||
for (i = 1; i < oh_count; i++) {
|
||||
pdev = create_dss_pdev(curr_dss_hwmod[i].dev_name,
|
||||
curr_dss_hwmod[i].id,
|
||||
curr_dss_hwmod[i].oh_name,
|
||||
board_data, sizeof(*board_data),
|
||||
dss_pdev);
|
||||
|
||||
return r;
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("Could not build omap_device for %s\n",
|
||||
curr_dss_hwmod[i].oh_name);
|
||||
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create devices for DPI and SDI */
|
||||
|
||||
pdev = create_simple_dss_pdev("omapdss_dpi", -1,
|
||||
board_data, sizeof(*board_data), dss_pdev);
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("Could not build platform_device for omapdss_dpi\n");
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
pdev = create_simple_dss_pdev("omapdss_sdi", -1,
|
||||
board_data, sizeof(*board_data), dss_pdev);
|
||||
if (IS_ERR(pdev)) {
|
||||
pr_err("Could not build platform_device for omapdss_sdi\n");
|
||||
return PTR_ERR(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dispc_disable_outputs(void)
|
||||
|
@ -148,23 +148,25 @@ static struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = {
|
||||
|
||||
static struct s3c_fb_pd_win smdk2416_fb_win[] = {
|
||||
[0] = {
|
||||
/* think this is the same as the smdk6410 */
|
||||
.win_mode = {
|
||||
.pixclock = 41094,
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.default_bpp = 16,
|
||||
.max_bpp = 32,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
};
|
||||
|
||||
static struct fb_videomode smdk2416_lcd_timing = {
|
||||
.pixclock = 41094,
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static void s3c2416_fb_gpio_setup_24bpp(void)
|
||||
{
|
||||
unsigned int gpio;
|
||||
@ -187,6 +189,7 @@ static void s3c2416_fb_gpio_setup_24bpp(void)
|
||||
|
||||
static struct s3c_fb_platdata smdk2416_fb_platdata = {
|
||||
.win[0] = &smdk2416_fb_win[0],
|
||||
.vtiming = &smdk2416_lcd_timing,
|
||||
.setup_gpio = s3c2416_fb_gpio_setup_24bpp,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -134,24 +134,27 @@ static struct platform_device anw6410_lcd_powerdev = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win anw6410_fb_win0 = {
|
||||
/* this is to ensure we use win0 */
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode anw6410_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
|
||||
static struct s3c_fb_platdata anw6410_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &anw6410_lcd_timing,
|
||||
.win[0] = &anw6410_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -151,26 +151,29 @@ static struct platform_device crag6410_lcd_powerdev = {
|
||||
|
||||
/* 640x480 URT */
|
||||
static struct s3c_fb_pd_win crag6410_fb_win0 = {
|
||||
/* this is to ensure we use win0 */
|
||||
.win_mode = {
|
||||
.left_margin = 150,
|
||||
.right_margin = 80,
|
||||
.upper_margin = 40,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 5,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
.virtual_y = 480 * 2,
|
||||
.virtual_x = 640,
|
||||
};
|
||||
|
||||
static struct fb_videomode crag6410_lcd_timing = {
|
||||
.left_margin = 150,
|
||||
.right_margin = 80,
|
||||
.upper_margin = 40,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 5,
|
||||
.xres = 640,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
|
||||
static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &crag6410_lcd_timing,
|
||||
.win[0] = &crag6410_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -129,23 +129,27 @@ static struct platform_device hmt_backlight_device = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win hmt_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode hmt_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
|
||||
static struct s3c_fb_platdata hmt_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &hmt_lcd_timing,
|
||||
.win[0] = &hmt_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -140,41 +140,59 @@ static struct s3c2410_platform_nand mini6410_nand_info = {
|
||||
.sets = mini6410_nand_sets,
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win mini6410_fb_win[] = {
|
||||
{
|
||||
.win_mode = { /* 4.3" 480x272 */
|
||||
.left_margin = 3,
|
||||
.right_margin = 2,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 272,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
}, {
|
||||
.win_mode = { /* 7.0" 800x480 */
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
},
|
||||
static struct s3c_fb_pd_win mini6410_lcd_type0_fb_win = {
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 272,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata mini6410_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.win[0] = &mini6410_fb_win[0],
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
static struct fb_videomode mini6410_lcd_type0_timing = {
|
||||
/* 4.3" 480x272 */
|
||||
.left_margin = 3,
|
||||
.right_margin = 2,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 272,
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win mini6410_lcd_type1_fb_win = {
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode mini6410_lcd_type1_timing = {
|
||||
/* 7.0" 800x480 */
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata mini6410_lcd_pdata[] __initdata = {
|
||||
{
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &mini6410_lcd_type0_timing,
|
||||
.win[0] = &mini6410_lcd_type0_fb_win,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
}, {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &mini6410_lcd_type1_timing,
|
||||
.win[0] = &mini6410_lcd_type1_fb_win,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static void mini6410_lcd_power_set(struct plat_lcd_data *pd,
|
||||
@ -272,7 +290,7 @@ static void mini6410_parse_features(
|
||||
"screen type already set\n", f);
|
||||
} else {
|
||||
int li = f - '0';
|
||||
if (li >= ARRAY_SIZE(mini6410_fb_win))
|
||||
if (li >= ARRAY_SIZE(mini6410_lcd_pdata))
|
||||
printk(KERN_INFO "MINI6410: '%c' out "
|
||||
"of range LCD mode\n", f);
|
||||
else {
|
||||
@ -296,14 +314,12 @@ static void __init mini6410_machine_init(void)
|
||||
/* Parse the feature string */
|
||||
mini6410_parse_features(&features, mini6410_features_str);
|
||||
|
||||
mini6410_lcd_pdata.win[0] = &mini6410_fb_win[features.lcd_index];
|
||||
|
||||
printk(KERN_INFO "MINI6410: selected LCD display is %dx%d\n",
|
||||
mini6410_lcd_pdata.win[0]->win_mode.xres,
|
||||
mini6410_lcd_pdata.win[0]->win_mode.yres);
|
||||
mini6410_lcd_pdata[features.lcd_index].win[0]->xres,
|
||||
mini6410_lcd_pdata[features.lcd_index].win[0]->yres);
|
||||
|
||||
s3c_nand_set_platdata(&mini6410_nand_info);
|
||||
s3c_fb_set_platdata(&mini6410_lcd_pdata);
|
||||
s3c_fb_set_platdata(&mini6410_lcd_pdata[features.lcd_index]);
|
||||
s3c24xx_ts_set_platdata(NULL);
|
||||
|
||||
/* configure nCS1 width to 16 bits */
|
||||
|
@ -106,41 +106,57 @@ static struct platform_device real6410_device_eth = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win real6410_fb_win[] = {
|
||||
{
|
||||
.win_mode = { /* 4.3" 480x272 */
|
||||
.left_margin = 3,
|
||||
.right_margin = 2,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 272,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
}, {
|
||||
.win_mode = { /* 7.0" 800x480 */
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
},
|
||||
static struct s3c_fb_pd_win real6410_lcd_type0_fb_win = {
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 272,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata real6410_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.win[0] = &real6410_fb_win[0],
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
static struct fb_videomode real6410_lcd_type0_timing = {
|
||||
/* 4.3" 480x272 */
|
||||
.left_margin = 3,
|
||||
.right_margin = 2,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 1,
|
||||
.hsync_len = 40,
|
||||
.vsync_len = 1,
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win real6410_lcd_type1_fb_win = {
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode real6410_lcd_type1_timing = {
|
||||
/* 7.0" 800x480 */
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata real6410_lcd_pdata[] __initdata = {
|
||||
{
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &real6410_lcd_type0_timing,
|
||||
.win[0] = &real6410_lcd_type0_fb_win,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
}, {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &real6410_lcd_type1_timing,
|
||||
.win[0] = &real6410_lcd_type1_fb_win,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct mtd_partition real6410_nand_part[] = {
|
||||
@ -253,7 +269,7 @@ static void real6410_parse_features(
|
||||
"screen type already set\n", f);
|
||||
} else {
|
||||
int li = f - '0';
|
||||
if (li >= ARRAY_SIZE(real6410_fb_win))
|
||||
if (li >= ARRAY_SIZE(real6410_lcd_pdata))
|
||||
printk(KERN_INFO "REAL6410: '%c' out "
|
||||
"of range LCD mode\n", f);
|
||||
else {
|
||||
@ -277,13 +293,11 @@ static void __init real6410_machine_init(void)
|
||||
/* Parse the feature string */
|
||||
real6410_parse_features(&features, real6410_features_str);
|
||||
|
||||
real6410_lcd_pdata.win[0] = &real6410_fb_win[features.lcd_index];
|
||||
|
||||
printk(KERN_INFO "REAL6410: selected LCD display is %dx%d\n",
|
||||
real6410_lcd_pdata.win[0]->win_mode.xres,
|
||||
real6410_lcd_pdata.win[0]->win_mode.yres);
|
||||
real6410_lcd_pdata[features.lcd_index].win[0]->xres,
|
||||
real6410_lcd_pdata[features.lcd_index].win[0]->yres);
|
||||
|
||||
s3c_fb_set_platdata(&real6410_lcd_pdata);
|
||||
s3c_fb_set_platdata(&real6410_lcd_pdata[features.lcd_index]);
|
||||
s3c_nand_set_platdata(&real6410_nand_info);
|
||||
s3c24xx_ts_set_platdata(NULL);
|
||||
|
||||
|
@ -108,23 +108,27 @@ static struct platform_device smartq5_buttons_device = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win smartq5_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 216,
|
||||
.right_margin = 40,
|
||||
.upper_margin = 35,
|
||||
.lower_margin = 10,
|
||||
.hsync_len = 1,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smartq5_lcd_timing = {
|
||||
.left_margin = 216,
|
||||
.right_margin = 40,
|
||||
.upper_margin = 35,
|
||||
.lower_margin = 10,
|
||||
.hsync_len = 1,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smartq5_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &smartq5_lcd_timing,
|
||||
.win[0] = &smartq5_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
|
||||
|
@ -124,23 +124,27 @@ static struct platform_device smartq7_buttons_device = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win smartq7_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 3,
|
||||
.right_margin = 5,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 20,
|
||||
.hsync_len = 10,
|
||||
.vsync_len = 3,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smartq7_lcd_timing = {
|
||||
.left_margin = 3,
|
||||
.right_margin = 5,
|
||||
.upper_margin = 1,
|
||||
.lower_margin = 20,
|
||||
.hsync_len = 10,
|
||||
.vsync_len = 3,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smartq7_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &smartq7_lcd_timing,
|
||||
.win[0] = &smartq7_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
|
||||
|
@ -146,26 +146,29 @@ static struct platform_device smdk6410_lcd_powerdev = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win smdk6410_fb_win0 = {
|
||||
/* this is to ensure we use win0 */
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.virtual_y = 480 * 2,
|
||||
.virtual_x = 800,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdk6410_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
/* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
|
||||
static struct s3c_fb_platdata smdk6410_lcd_pdata __initdata = {
|
||||
.setup_gpio = s3c64xx_fb_gpio_setup_24bpp,
|
||||
.vtiming = &smdk6410_lcd_timing,
|
||||
.win[0] = &smdk6410_fb_win0,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
|
@ -103,22 +103,26 @@ static struct s3c2410_uartcfg smdk6440_uartcfgs[] __initdata = {
|
||||
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win smdk6440_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdk6440_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smdk6440_lcd_pdata __initdata = {
|
||||
.win[0] = &smdk6440_fb_win0,
|
||||
.vtiming = &smdk6440_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
.setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
|
||||
|
@ -121,22 +121,26 @@ static struct s3c2410_uartcfg smdk6450_uartcfgs[] __initdata = {
|
||||
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win smdk6450_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdk6450_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smdk6450_lcd_pdata __initdata = {
|
||||
.win[0] = &smdk6450_fb_win0,
|
||||
.vtiming = &smdk6450_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
.setup_gpio = s5p64x0_fb_gpio_setup_24bpp,
|
||||
|
@ -136,24 +136,27 @@ static struct platform_device smdkc100_lcd_powerdev = {
|
||||
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win smdkc100_fb_win0 = {
|
||||
/* this is to ensure we use win0 */
|
||||
.win_mode = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdkc100_lcd_timing = {
|
||||
.left_margin = 8,
|
||||
.right_margin = 13,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
.refresh = 80,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smdkc100_lcd_pdata __initdata = {
|
||||
.win[0] = &smdkc100_fb_win0,
|
||||
.vtiming = &smdkc100_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
.setup_gpio = s5pc100_fb_gpio_setup_24bpp,
|
||||
|
@ -96,38 +96,34 @@ static struct s3c2410_uartcfg aquila_uartcfgs[] __initdata = {
|
||||
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win aquila_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 3,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 2,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win aquila_fb_win1 = {
|
||||
.win_mode = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 3,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 2,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
};
|
||||
|
||||
static struct fb_videomode aquila_lcd_timing = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 3,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 2,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata aquila_lcd_pdata __initdata = {
|
||||
.win[0] = &aquila_fb_win0,
|
||||
.win[1] = &aquila_fb_win1,
|
||||
.vtiming = &aquila_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC |
|
||||
VIDCON1_INV_VCLK | VIDCON1_INV_VDEN,
|
||||
|
@ -107,25 +107,29 @@ static struct s3c2410_uartcfg goni_uartcfgs[] __initdata = {
|
||||
|
||||
/* Frame Buffer */
|
||||
static struct s3c_fb_pd_win goni_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 2,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.refresh = 55,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 16,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.virtual_x = 480,
|
||||
.virtual_y = 2 * 800,
|
||||
};
|
||||
|
||||
static struct fb_videomode goni_lcd_timing = {
|
||||
.left_margin = 16,
|
||||
.right_margin = 16,
|
||||
.upper_margin = 2,
|
||||
.lower_margin = 28,
|
||||
.hsync_len = 2,
|
||||
.vsync_len = 1,
|
||||
.xres = 480,
|
||||
.yres = 800,
|
||||
.refresh = 55,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
|
||||
.win[0] = &goni_fb_win0,
|
||||
.vtiming = &goni_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB |
|
||||
VIDCON0_CLKSEL_LCD,
|
||||
.vidcon1 = VIDCON1_INV_VCLK | VIDCON1_INV_VDEN
|
||||
|
@ -178,22 +178,26 @@ static struct platform_device smdkv210_lcd_lte480wv = {
|
||||
};
|
||||
|
||||
static struct s3c_fb_pd_win smdkv210_fb_win0 = {
|
||||
.win_mode = {
|
||||
.left_margin = 13,
|
||||
.right_margin = 8,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
},
|
||||
.max_bpp = 32,
|
||||
.default_bpp = 24,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct fb_videomode smdkv210_lcd_timing = {
|
||||
.left_margin = 13,
|
||||
.right_margin = 8,
|
||||
.upper_margin = 7,
|
||||
.lower_margin = 5,
|
||||
.hsync_len = 3,
|
||||
.vsync_len = 1,
|
||||
.xres = 800,
|
||||
.yres = 480,
|
||||
};
|
||||
|
||||
static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
|
||||
.win[0] = &smdkv210_fb_win0,
|
||||
.vtiming = &smdkv210_lcd_timing,
|
||||
.vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
|
||||
.vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
|
||||
.setup_gpio = s5pv210_fb_gpio_setup_24bpp,
|
||||
|
@ -24,15 +24,16 @@
|
||||
|
||||
/**
|
||||
* struct s3c_fb_pd_win - per window setup data
|
||||
* @win_mode: The display parameters to initialise (not for window 0)
|
||||
* @xres : The window X size.
|
||||
* @yres : The window Y size.
|
||||
* @virtual_x: The virtual X size.
|
||||
* @virtual_y: The virtual Y size.
|
||||
*/
|
||||
struct s3c_fb_pd_win {
|
||||
struct fb_videomode win_mode;
|
||||
|
||||
unsigned short default_bpp;
|
||||
unsigned short max_bpp;
|
||||
unsigned short xres;
|
||||
unsigned short yres;
|
||||
unsigned short virtual_x;
|
||||
unsigned short virtual_y;
|
||||
};
|
||||
@ -45,6 +46,7 @@ struct s3c_fb_pd_win {
|
||||
* @default_win: default window layer number to be used for UI layer.
|
||||
* @vidcon0: The base vidcon0 values to control the panel data format.
|
||||
* @vidcon1: The base vidcon1 values to control the panel data output.
|
||||
* @vtiming: Video timing when connected to a RGB type panel.
|
||||
* @win: The setup data for each hardware window, or NULL for unused.
|
||||
* @display_mode: The LCD output display mode.
|
||||
*
|
||||
@ -58,8 +60,7 @@ struct s3c_fb_platdata {
|
||||
void (*setup_gpio)(void);
|
||||
|
||||
struct s3c_fb_pd_win *win[S3C_FB_MAX_WIN];
|
||||
|
||||
u32 default_win;
|
||||
struct fb_videomode *vtiming;
|
||||
|
||||
u32 vidcon0;
|
||||
u32 vidcon1;
|
||||
|
@ -2210,7 +2210,7 @@ config FB_XILINX
|
||||
|
||||
config FB_COBALT
|
||||
tristate "Cobalt server LCD frame buffer support"
|
||||
depends on FB && MIPS_COBALT
|
||||
depends on FB && (MIPS_COBALT || MIPS_SEAD3)
|
||||
|
||||
config FB_SH7760
|
||||
bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
|
||||
@ -2382,6 +2382,39 @@ config FB_BROADSHEET
|
||||
and could also have been called by other names when coupled with
|
||||
a bridge adapter.
|
||||
|
||||
config FB_AUO_K190X
|
||||
tristate "AUO-K190X EPD controller support"
|
||||
depends on FB
|
||||
select FB_SYS_FILLRECT
|
||||
select FB_SYS_COPYAREA
|
||||
select FB_SYS_IMAGEBLIT
|
||||
select FB_SYS_FOPS
|
||||
select FB_DEFERRED_IO
|
||||
help
|
||||
Provides support for epaper controllers from the K190X series
|
||||
of AUO. These controllers can be used to drive epaper displays
|
||||
from Sipix.
|
||||
|
||||
This option enables the common support, shared by the individual
|
||||
controller drivers. You will also have to enable the driver
|
||||
for the controller type used in your device.
|
||||
|
||||
config FB_AUO_K1900
|
||||
tristate "AUO-K1900 EPD controller support"
|
||||
depends on FB && FB_AUO_K190X
|
||||
help
|
||||
This driver implements support for the AUO K1900 epd-controller.
|
||||
This controller can drive Sipix epaper displays but can only do
|
||||
serial updates, reducing the number of possible frames per second.
|
||||
|
||||
config FB_AUO_K1901
|
||||
tristate "AUO-K1901 EPD controller support"
|
||||
depends on FB && FB_AUO_K190X
|
||||
help
|
||||
This driver implements support for the AUO K1901 epd-controller.
|
||||
This controller can drive Sipix epaper displays and supports
|
||||
concurrent updates, making higher frames per second possible.
|
||||
|
||||
config FB_JZ4740
|
||||
tristate "JZ4740 LCD framebuffer support"
|
||||
depends on FB && MACH_JZ4740
|
||||
|
@ -118,6 +118,9 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
|
||||
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
|
||||
obj-$(CONFIG_FB_METRONOME) += metronomefb.o
|
||||
obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
|
||||
obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
|
||||
obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
|
||||
obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
|
||||
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
|
||||
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
|
||||
obj-$(CONFIG_FB_IMX) += imxfb.o
|
||||
|
198
drivers/video/auo_k1900fb.c
Normal file
198
drivers/video/auo_k1900fb.c
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* auok190xfb.c -- FB driver for AUO-K1900 controllers
|
||||
*
|
||||
* Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* based on broadsheetfb.c
|
||||
*
|
||||
* Copyright (C) 2008, Jaya Kumar
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
|
||||
*
|
||||
* This driver is written to be used with the AUO-K1900 display controller.
|
||||
*
|
||||
* It is intended to be architecture independent. A board specific driver
|
||||
* must be used to perform all the physical IO interactions.
|
||||
*
|
||||
* The controller supports different update modes:
|
||||
* mode0+1 16 step gray (4bit)
|
||||
* mode2 4 step gray (2bit) - FIXME: add strange refresh
|
||||
* mode3 2 step gray (1bit) - FIXME: add strange refresh
|
||||
* mode4 handwriting mode (strange behaviour)
|
||||
* mode5 automatic selection of update mode
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <video/auo_k190xfb.h>
|
||||
|
||||
#include "auo_k190x.h"
|
||||
|
||||
/*
|
||||
* AUO-K1900 specific commands
|
||||
*/
|
||||
|
||||
#define AUOK1900_CMD_PARTIALDISP 0x1001
|
||||
#define AUOK1900_CMD_ROTATION 0x1006
|
||||
#define AUOK1900_CMD_LUT_STOP 0x1009
|
||||
|
||||
#define AUOK1900_INIT_TEMP_AVERAGE (1 << 13)
|
||||
#define AUOK1900_INIT_ROTATE(_x) ((_x & 0x3) << 10)
|
||||
#define AUOK1900_INIT_RESOLUTION(_res) ((_res & 0x7) << 2)
|
||||
|
||||
static void auok1900_init(struct auok190xfb_par *par)
|
||||
{
|
||||
struct auok190x_board *board = par->board;
|
||||
u16 init_param = 0;
|
||||
|
||||
init_param |= AUOK1900_INIT_TEMP_AVERAGE;
|
||||
init_param |= AUOK1900_INIT_ROTATE(par->rotation);
|
||||
init_param |= AUOK190X_INIT_INVERSE_WHITE;
|
||||
init_param |= AUOK190X_INIT_FORMAT0;
|
||||
init_param |= AUOK1900_INIT_RESOLUTION(par->resolution);
|
||||
init_param |= AUOK190X_INIT_SHIFT_RIGHT;
|
||||
|
||||
auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
|
||||
|
||||
/* let the controller finish */
|
||||
board->wait_for_rdy(par);
|
||||
}
|
||||
|
||||
static void auok1900_update_region(struct auok190xfb_par *par, int mode,
|
||||
u16 y1, u16 y2)
|
||||
{
|
||||
struct device *dev = par->info->device;
|
||||
unsigned char *buf = (unsigned char *)par->info->screen_base;
|
||||
int xres = par->info->var.xres;
|
||||
u16 args[4];
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&(par->io_lock));
|
||||
|
||||
/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
|
||||
y1 &= 0xfffe;
|
||||
y2 &= 0xfffe;
|
||||
|
||||
dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
|
||||
1, y1+1, xres, y2-y1, mode);
|
||||
|
||||
/* to FIX handle different partial update modes */
|
||||
args[0] = mode | 1;
|
||||
args[1] = y1 + 1;
|
||||
args[2] = xres;
|
||||
args[3] = y2 - y1;
|
||||
buf += y1 * xres;
|
||||
auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
|
||||
((y2 - y1) * xres)/2, (u16 *) buf);
|
||||
auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
|
||||
|
||||
par->update_cnt++;
|
||||
|
||||
mutex_unlock(&(par->io_lock));
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par,
|
||||
u16 y1, u16 y2)
|
||||
{
|
||||
int mode;
|
||||
|
||||
if (par->update_mode < 0) {
|
||||
mode = AUOK190X_UPDATE_MODE(1);
|
||||
par->last_mode = -1;
|
||||
} else {
|
||||
mode = AUOK190X_UPDATE_MODE(par->update_mode);
|
||||
par->last_mode = par->update_mode;
|
||||
}
|
||||
|
||||
if (par->flash)
|
||||
mode |= AUOK190X_UPDATE_NONFLASH;
|
||||
|
||||
auok1900_update_region(par, mode, y1, y2);
|
||||
}
|
||||
|
||||
static void auok1900fb_dpy_update(struct auok190xfb_par *par)
|
||||
{
|
||||
int mode;
|
||||
|
||||
if (par->update_mode < 0) {
|
||||
mode = AUOK190X_UPDATE_MODE(0);
|
||||
par->last_mode = -1;
|
||||
} else {
|
||||
mode = AUOK190X_UPDATE_MODE(par->update_mode);
|
||||
par->last_mode = par->update_mode;
|
||||
}
|
||||
|
||||
if (par->flash)
|
||||
mode |= AUOK190X_UPDATE_NONFLASH;
|
||||
|
||||
auok1900_update_region(par, mode, 0, par->info->var.yres);
|
||||
par->update_cnt = 0;
|
||||
}
|
||||
|
||||
static bool auok1900fb_need_refresh(struct auok190xfb_par *par)
|
||||
{
|
||||
return (par->update_cnt > 10);
|
||||
}
|
||||
|
||||
static int __devinit auok1900fb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct auok190x_init_data init;
|
||||
struct auok190x_board *board;
|
||||
|
||||
/* pick up board specific routines */
|
||||
board = pdev->dev.platform_data;
|
||||
if (!board)
|
||||
return -EINVAL;
|
||||
|
||||
/* fill temporary init struct for common init */
|
||||
init.id = "auo_k1900fb";
|
||||
init.board = board;
|
||||
init.update_partial = auok1900fb_dpy_update_pages;
|
||||
init.update_all = auok1900fb_dpy_update;
|
||||
init.need_refresh = auok1900fb_need_refresh;
|
||||
init.init = auok1900_init;
|
||||
|
||||
return auok190x_common_probe(pdev, &init);
|
||||
}
|
||||
|
||||
static int __devexit auok1900fb_remove(struct platform_device *pdev)
|
||||
{
|
||||
return auok190x_common_remove(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver auok1900fb_driver = {
|
||||
.probe = auok1900fb_probe,
|
||||
.remove = __devexit_p(auok1900fb_remove),
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "auo_k1900fb",
|
||||
.pm = &auok190x_pm,
|
||||
},
|
||||
};
|
||||
module_platform_driver(auok1900fb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller");
|
||||
MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
|
||||
MODULE_LICENSE("GPL");
|
251
drivers/video/auo_k1901fb.c
Normal file
251
drivers/video/auo_k1901fb.c
Normal file
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* auok190xfb.c -- FB driver for AUO-K1901 controllers
|
||||
*
|
||||
* Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* based on broadsheetfb.c
|
||||
*
|
||||
* Copyright (C) 2008, Jaya Kumar
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
|
||||
*
|
||||
* This driver is written to be used with the AUO-K1901 display controller.
|
||||
*
|
||||
* It is intended to be architecture independent. A board specific driver
|
||||
* must be used to perform all the physical IO interactions.
|
||||
*
|
||||
* The controller supports different update modes:
|
||||
* mode0+1 16 step gray (4bit)
|
||||
* mode2+3 4 step gray (2bit)
|
||||
* mode4+5 2 step gray (1bit)
|
||||
* - mode4 is described as "without LUT"
|
||||
* mode7 automatic selection of update mode
|
||||
*
|
||||
* The most interesting difference to the K1900 is the ability to do screen
|
||||
* updates in an asynchronous fashion. Where the K1900 needs to wait for the
|
||||
* current update to complete, the K1901 can process later updates already.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <video/auo_k190xfb.h>
|
||||
|
||||
#include "auo_k190x.h"
|
||||
|
||||
/*
|
||||
* AUO-K1901 specific commands
|
||||
*/
|
||||
|
||||
#define AUOK1901_CMD_LUT_INTERFACE 0x0005
|
||||
#define AUOK1901_CMD_DMA_START 0x1001
|
||||
#define AUOK1901_CMD_CURSOR_START 0x1007
|
||||
#define AUOK1901_CMD_CURSOR_STOP AUOK190X_CMD_DATA_STOP
|
||||
#define AUOK1901_CMD_DDMA_START 0x1009
|
||||
|
||||
#define AUOK1901_INIT_GATE_PULSE_LOW (0 << 14)
|
||||
#define AUOK1901_INIT_GATE_PULSE_HIGH (1 << 14)
|
||||
#define AUOK1901_INIT_SINGLE_GATE (0 << 13)
|
||||
#define AUOK1901_INIT_DOUBLE_GATE (1 << 13)
|
||||
|
||||
/* Bits to pixels
|
||||
* Mode 15-12 11-8 7-4 3-0
|
||||
* format2 2 T 1 T
|
||||
* format3 1 T 2 T
|
||||
* format4 T 2 T 1
|
||||
* format5 T 1 T 2
|
||||
*
|
||||
* halftone modes:
|
||||
* format6 2 2 1 1
|
||||
* format7 1 1 2 2
|
||||
*/
|
||||
#define AUOK1901_INIT_FORMAT2 (1 << 7)
|
||||
#define AUOK1901_INIT_FORMAT3 ((1 << 7) | (1 << 6))
|
||||
#define AUOK1901_INIT_FORMAT4 (1 << 8)
|
||||
#define AUOK1901_INIT_FORMAT5 ((1 << 8) | (1 << 6))
|
||||
#define AUOK1901_INIT_FORMAT6 ((1 << 8) | (1 << 7))
|
||||
#define AUOK1901_INIT_FORMAT7 ((1 << 8) | (1 << 7) | (1 << 6))
|
||||
|
||||
/* res[4] to bit 10
|
||||
* res[3-0] to bits 5-2
|
||||
*/
|
||||
#define AUOK1901_INIT_RESOLUTION(_res) (((_res & (1 << 4)) << 6) \
|
||||
| ((_res & 0xf) << 2))
|
||||
|
||||
/*
|
||||
* portrait / landscape orientation in AUOK1901_CMD_DMA_START
|
||||
*/
|
||||
#define AUOK1901_DMA_ROTATE90(_rot) ((_rot & 1) << 13)
|
||||
|
||||
/*
|
||||
* equivalent to 1 << 11, needs the ~ to have same rotation like K1900
|
||||
*/
|
||||
#define AUOK1901_DDMA_ROTATE180(_rot) ((~_rot & 2) << 10)
|
||||
|
||||
static void auok1901_init(struct auok190xfb_par *par)
|
||||
{
|
||||
struct auok190x_board *board = par->board;
|
||||
u16 init_param = 0;
|
||||
|
||||
init_param |= AUOK190X_INIT_INVERSE_WHITE;
|
||||
init_param |= AUOK190X_INIT_FORMAT0;
|
||||
init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
|
||||
init_param |= AUOK190X_INIT_SHIFT_LEFT;
|
||||
|
||||
auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
|
||||
|
||||
/* let the controller finish */
|
||||
board->wait_for_rdy(par);
|
||||
}
|
||||
|
||||
static void auok1901_update_region(struct auok190xfb_par *par, int mode,
|
||||
u16 y1, u16 y2)
|
||||
{
|
||||
struct device *dev = par->info->device;
|
||||
unsigned char *buf = (unsigned char *)par->info->screen_base;
|
||||
int xres = par->info->var.xres;
|
||||
u16 args[5];
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
mutex_lock(&(par->io_lock));
|
||||
|
||||
/* y1 and y2 must be a multiple of 2 so drop the lowest bit */
|
||||
y1 &= 0xfffe;
|
||||
y2 &= 0xfffe;
|
||||
|
||||
dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
|
||||
1, y1+1, xres, y2-y1, mode);
|
||||
|
||||
/* K1901: first transfer the region data */
|
||||
args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1;
|
||||
args[1] = y1 + 1;
|
||||
args[2] = xres;
|
||||
args[3] = y2 - y1;
|
||||
buf += y1 * xres;
|
||||
auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
|
||||
args, ((y2 - y1) * xres)/2,
|
||||
(u16 *) buf);
|
||||
auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
|
||||
|
||||
/* K1901: second tell the controller to update the region with mode */
|
||||
args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation);
|
||||
args[1] = 1;
|
||||
args[2] = y1 + 1;
|
||||
args[3] = xres;
|
||||
args[4] = y2 - y1;
|
||||
auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args);
|
||||
|
||||
par->update_cnt++;
|
||||
|
||||
mutex_unlock(&(par->io_lock));
|
||||
|
||||
pm_runtime_mark_last_busy(dev);
|
||||
pm_runtime_put_autosuspend(dev);
|
||||
}
|
||||
|
||||
static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par,
|
||||
u16 y1, u16 y2)
|
||||
{
|
||||
int mode;
|
||||
|
||||
if (par->update_mode < 0) {
|
||||
mode = AUOK190X_UPDATE_MODE(1);
|
||||
par->last_mode = -1;
|
||||
} else {
|
||||
mode = AUOK190X_UPDATE_MODE(par->update_mode);
|
||||
par->last_mode = par->update_mode;
|
||||
}
|
||||
|
||||
if (par->flash)
|
||||
mode |= AUOK190X_UPDATE_NONFLASH;
|
||||
|
||||
auok1901_update_region(par, mode, y1, y2);
|
||||
}
|
||||
|
||||
static void auok1901fb_dpy_update(struct auok190xfb_par *par)
|
||||
{
|
||||
int mode;
|
||||
|
||||
/* When doing full updates, wait for the controller to be ready
|
||||
* This will hopefully catch some hangs of the K1901
|
||||
*/
|
||||
par->board->wait_for_rdy(par);
|
||||
|
||||
if (par->update_mode < 0) {
|
||||
mode = AUOK190X_UPDATE_MODE(0);
|
||||
par->last_mode = -1;
|
||||
} else {
|
||||
mode = AUOK190X_UPDATE_MODE(par->update_mode);
|
||||
par->last_mode = par->update_mode;
|
||||
}
|
||||
|
||||
if (par->flash)
|
||||
mode |= AUOK190X_UPDATE_NONFLASH;
|
||||
|
||||
auok1901_update_region(par, mode, 0, par->info->var.yres);
|
||||
par->update_cnt = 0;
|
||||
}
|
||||
|
||||
static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
|
||||
{
|
||||
return (par->update_cnt > 10);
|
||||
}
|
||||
|
||||
static int __devinit auok1901fb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct auok190x_init_data init;
|
||||
struct auok190x_board *board;
|
||||
|
||||
/* pick up board specific routines */
|
||||
board = pdev->dev.platform_data;
|
||||
if (!board)
|
||||
return -EINVAL;
|
||||
|
||||
/* fill temporary init struct for common init */
|
||||
init.id = "auo_k1901fb";
|
||||
init.board = board;
|
||||
init.update_partial = auok1901fb_dpy_update_pages;
|
||||
init.update_all = auok1901fb_dpy_update;
|
||||
init.need_refresh = auok1901fb_need_refresh;
|
||||
init.init = auok1901_init;
|
||||
|
||||
return auok190x_common_probe(pdev, &init);
|
||||
}
|
||||
|
||||
static int __devexit auok1901fb_remove(struct platform_device *pdev)
|
||||
{
|
||||
return auok190x_common_remove(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver auok1901fb_driver = {
|
||||
.probe = auok1901fb_probe,
|
||||
.remove = __devexit_p(auok1901fb_remove),
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "auo_k1901fb",
|
||||
.pm = &auok190x_pm,
|
||||
},
|
||||
};
|
||||
module_platform_driver(auok1901fb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller");
|
||||
MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
|
||||
MODULE_LICENSE("GPL");
|
1046
drivers/video/auo_k190x.c
Normal file
1046
drivers/video/auo_k190x.c
Normal file
File diff suppressed because it is too large
Load Diff
129
drivers/video/auo_k190x.h
Normal file
129
drivers/video/auo_k190x.h
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Private common definitions for AUO-K190X framebuffer drivers
|
||||
*
|
||||
* Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* I80 interface specific defines
|
||||
*/
|
||||
|
||||
#define AUOK190X_I80_CS 0x01
|
||||
#define AUOK190X_I80_DC 0x02
|
||||
#define AUOK190X_I80_WR 0x03
|
||||
#define AUOK190X_I80_OE 0x04
|
||||
|
||||
/*
|
||||
* AUOK190x commands, common to both controllers
|
||||
*/
|
||||
|
||||
#define AUOK190X_CMD_INIT 0x0000
|
||||
#define AUOK190X_CMD_STANDBY 0x0001
|
||||
#define AUOK190X_CMD_WAKEUP 0x0002
|
||||
#define AUOK190X_CMD_TCON_RESET 0x0003
|
||||
#define AUOK190X_CMD_DATA_STOP 0x1002
|
||||
#define AUOK190X_CMD_LUT_START 0x1003
|
||||
#define AUOK190X_CMD_DISP_REFRESH 0x1004
|
||||
#define AUOK190X_CMD_DISP_RESET 0x1005
|
||||
#define AUOK190X_CMD_PRE_DISPLAY_START 0x100D
|
||||
#define AUOK190X_CMD_PRE_DISPLAY_STOP 0x100F
|
||||
#define AUOK190X_CMD_FLASH_W 0x2000
|
||||
#define AUOK190X_CMD_FLASH_E 0x2001
|
||||
#define AUOK190X_CMD_FLASH_STS 0x2002
|
||||
#define AUOK190X_CMD_FRAMERATE 0x3000
|
||||
#define AUOK190X_CMD_READ_VERSION 0x4000
|
||||
#define AUOK190X_CMD_READ_STATUS 0x4001
|
||||
#define AUOK190X_CMD_READ_LUT 0x4003
|
||||
#define AUOK190X_CMD_DRIVERTIMING 0x5000
|
||||
#define AUOK190X_CMD_LBALANCE 0x5001
|
||||
#define AUOK190X_CMD_AGINGMODE 0x6000
|
||||
#define AUOK190X_CMD_AGINGEXIT 0x6001
|
||||
|
||||
/*
|
||||
* Common settings for AUOK190X_CMD_INIT
|
||||
*/
|
||||
|
||||
#define AUOK190X_INIT_DATA_FILTER (0 << 12)
|
||||
#define AUOK190X_INIT_DATA_BYPASS (1 << 12)
|
||||
#define AUOK190X_INIT_INVERSE_WHITE (0 << 9)
|
||||
#define AUOK190X_INIT_INVERSE_BLACK (1 << 9)
|
||||
#define AUOK190X_INIT_SCAN_DOWN (0 << 1)
|
||||
#define AUOK190X_INIT_SCAN_UP (1 << 1)
|
||||
#define AUOK190X_INIT_SHIFT_LEFT (0 << 0)
|
||||
#define AUOK190X_INIT_SHIFT_RIGHT (1 << 0)
|
||||
|
||||
/* Common bits to pixels
|
||||
* Mode 15-12 11-8 7-4 3-0
|
||||
* format0 4 3 2 1
|
||||
* format1 3 4 1 2
|
||||
*/
|
||||
|
||||
#define AUOK190X_INIT_FORMAT0 0
|
||||
#define AUOK190X_INIT_FORMAT1 (1 << 6)
|
||||
|
||||
/*
|
||||
* settings for AUOK190X_CMD_RESET
|
||||
*/
|
||||
|
||||
#define AUOK190X_RESET_TCON (0 << 0)
|
||||
#define AUOK190X_RESET_NORMAL (1 << 0)
|
||||
#define AUOK190X_RESET_PON (1 << 1)
|
||||
|
||||
/*
|
||||
* AUOK190X_CMD_VERSION
|
||||
*/
|
||||
|
||||
#define AUOK190X_VERSION_TEMP_MASK (0x1ff)
|
||||
#define AUOK190X_VERSION_EPD_MASK (0xff)
|
||||
#define AUOK190X_VERSION_SIZE_INT(_val) ((_val & 0xfc00) >> 10)
|
||||
#define AUOK190X_VERSION_SIZE_FLOAT(_val) ((_val & 0x3c0) >> 6)
|
||||
#define AUOK190X_VERSION_MODEL(_val) (_val & 0x3f)
|
||||
#define AUOK190X_VERSION_LUT(_val) (_val & 0xff)
|
||||
#define AUOK190X_VERSION_TCON(_val) ((_val & 0xff00) >> 8)
|
||||
|
||||
/*
|
||||
* update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901
|
||||
*/
|
||||
|
||||
#define AUOK190X_UPDATE_MODE(_res) ((_res & 0x7) << 12)
|
||||
#define AUOK190X_UPDATE_NONFLASH (1 << 15)
|
||||
|
||||
/*
|
||||
* track panel specific parameters for common init
|
||||
*/
|
||||
|
||||
struct auok190x_init_data {
|
||||
char *id;
|
||||
struct auok190x_board *board;
|
||||
|
||||
void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
|
||||
void (*update_all)(struct auok190xfb_par *par);
|
||||
bool (*need_refresh)(struct auok190xfb_par *par);
|
||||
void (*init)(struct auok190xfb_par *par);
|
||||
};
|
||||
|
||||
|
||||
extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data);
|
||||
extern int auok190x_send_command(struct auok190xfb_par *par, u16 data);
|
||||
extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
|
||||
int argc, u16 *argv);
|
||||
extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
|
||||
int argc, u16 *argv);
|
||||
extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par,
|
||||
u16 cmd, int argc, u16 *argv,
|
||||
int size, u16 *data);
|
||||
extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
|
||||
int argc, u16 *argv, int size,
|
||||
u16 *data);
|
||||
extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
|
||||
int argc, u16 *argv);
|
||||
|
||||
extern int auok190x_common_probe(struct platform_device *pdev,
|
||||
struct auok190x_init_data *init);
|
||||
extern int auok190x_common_remove(struct platform_device *pdev);
|
||||
|
||||
extern const struct dev_pm_ops auok190x_pm;
|
@ -414,14 +414,14 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "PPI0_FS3 GPIO request failed\n");
|
||||
ret = -EBUSY;
|
||||
goto out_8;
|
||||
goto free_fbdev;
|
||||
}
|
||||
}
|
||||
|
||||
if (peripheral_request_list(ppi_pins, DRIVER_NAME)) {
|
||||
dev_err(&client->dev, "requesting PPI peripheral failed\n");
|
||||
ret = -EFAULT;
|
||||
goto out_8;
|
||||
goto free_gpio;
|
||||
}
|
||||
|
||||
fbdev->fb_mem =
|
||||
@ -432,7 +432,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
dev_err(&client->dev, "couldn't allocate dma buffer (%d bytes)\n",
|
||||
(u32) fbdev->fb_len);
|
||||
ret = -ENOMEM;
|
||||
goto out_7;
|
||||
goto free_ppi_pins;
|
||||
}
|
||||
|
||||
fbdev->info.screen_base = (void *)fbdev->fb_mem;
|
||||
@ -464,27 +464,27 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
if (!fbdev->info.pseudo_palette) {
|
||||
dev_err(&client->dev, "failed to allocate pseudo_palette\n");
|
||||
ret = -ENOMEM;
|
||||
goto out_6;
|
||||
goto free_fb_mem;
|
||||
}
|
||||
|
||||
if (fb_alloc_cmap(&fbdev->info.cmap, BFIN_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
|
||||
dev_err(&client->dev, "failed to allocate colormap (%d entries)\n",
|
||||
BFIN_LCD_NBR_PALETTE_ENTRIES);
|
||||
ret = -EFAULT;
|
||||
goto out_5;
|
||||
goto free_palette;
|
||||
}
|
||||
|
||||
if (request_dma(CH_PPI, "BF5xx_PPI_DMA") < 0) {
|
||||
dev_err(&client->dev, "unable to request PPI DMA\n");
|
||||
ret = -EFAULT;
|
||||
goto out_4;
|
||||
goto free_cmap;
|
||||
}
|
||||
|
||||
if (request_irq(IRQ_PPI_ERROR, ppi_irq_error, 0,
|
||||
"PPI ERROR", fbdev) < 0) {
|
||||
dev_err(&client->dev, "unable to request PPI ERROR IRQ\n");
|
||||
ret = -EFAULT;
|
||||
goto out_3;
|
||||
goto free_ch_ppi;
|
||||
}
|
||||
|
||||
fbdev->open = 0;
|
||||
@ -494,14 +494,14 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "i2c attach: init error\n");
|
||||
goto out_1;
|
||||
goto free_irq_ppi;
|
||||
}
|
||||
|
||||
|
||||
if (register_framebuffer(&fbdev->info) < 0) {
|
||||
dev_err(&client->dev, "unable to register framebuffer\n");
|
||||
ret = -EFAULT;
|
||||
goto out_1;
|
||||
goto free_irq_ppi;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "fb%d: %s frame buffer device\n",
|
||||
@ -512,7 +512,7 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
if (!entry) {
|
||||
dev_err(&client->dev, "unable to create /proc entry\n");
|
||||
ret = -EFAULT;
|
||||
goto out_0;
|
||||
goto free_fb;
|
||||
}
|
||||
|
||||
entry->read_proc = adv7393_read_proc;
|
||||
@ -521,22 +521,25 @@ static int __devinit bfin_adv7393_fb_probe(struct i2c_client *client,
|
||||
|
||||
return 0;
|
||||
|
||||
out_0:
|
||||
free_fb:
|
||||
unregister_framebuffer(&fbdev->info);
|
||||
out_1:
|
||||
free_irq_ppi:
|
||||
free_irq(IRQ_PPI_ERROR, fbdev);
|
||||
out_3:
|
||||
free_ch_ppi:
|
||||
free_dma(CH_PPI);
|
||||
out_4:
|
||||
free_cmap:
|
||||
fb_dealloc_cmap(&fbdev->info.cmap);
|
||||
free_palette:
|
||||
kfree(fbdev->info.pseudo_palette);
|
||||
free_fb_mem:
|
||||
dma_free_coherent(NULL, fbdev->fb_len, fbdev->fb_mem,
|
||||
fbdev->dma_handle);
|
||||
out_5:
|
||||
fb_dealloc_cmap(&fbdev->info.cmap);
|
||||
out_6:
|
||||
kfree(fbdev->info.pseudo_palette);
|
||||
out_7:
|
||||
free_ppi_pins:
|
||||
peripheral_free_list(ppi_pins);
|
||||
out_8:
|
||||
free_gpio:
|
||||
if (ANOMALY_05000400)
|
||||
gpio_free(P_IDENT(P_PPI0_FS3));
|
||||
free_fbdev:
|
||||
kfree(fbdev);
|
||||
|
||||
return ret;
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Cobalt server LCD frame buffer driver.
|
||||
* Cobalt/SEAD3 LCD frame buffer driver.
|
||||
*
|
||||
* Copyright (C) 2008 Yoichi Yuasa <yuasa@linux-mips.org>
|
||||
* Copyright (C) 2012 MIPS Technologies, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -62,6 +63,7 @@
|
||||
#define LCD_CUR_POS(x) ((x) & LCD_CUR_POS_MASK)
|
||||
#define LCD_TEXT_POS(x) ((x) | LCD_TEXT_MODE)
|
||||
|
||||
#ifdef CONFIG_MIPS_COBALT
|
||||
static inline void lcd_write_control(struct fb_info *info, u8 control)
|
||||
{
|
||||
writel((u32)control << 24, info->screen_base);
|
||||
@ -81,6 +83,47 @@ static inline u8 lcd_read_data(struct fb_info *info)
|
||||
{
|
||||
return readl(info->screen_base + LCD_DATA_REG_OFFSET) >> 24;
|
||||
}
|
||||
#else
|
||||
|
||||
#define LCD_CTL 0x00
|
||||
#define LCD_DATA 0x08
|
||||
#define CPLD_STATUS 0x10
|
||||
#define CPLD_DATA 0x18
|
||||
|
||||
static inline void cpld_wait(struct fb_info *info)
|
||||
{
|
||||
do {
|
||||
} while (readl(info->screen_base + CPLD_STATUS) & 1);
|
||||
}
|
||||
|
||||
static inline void lcd_write_control(struct fb_info *info, u8 control)
|
||||
{
|
||||
cpld_wait(info);
|
||||
writel(control, info->screen_base + LCD_CTL);
|
||||
}
|
||||
|
||||
static inline u8 lcd_read_control(struct fb_info *info)
|
||||
{
|
||||
cpld_wait(info);
|
||||
readl(info->screen_base + LCD_CTL);
|
||||
cpld_wait(info);
|
||||
return readl(info->screen_base + CPLD_DATA) & 0xff;
|
||||
}
|
||||
|
||||
static inline void lcd_write_data(struct fb_info *info, u8 data)
|
||||
{
|
||||
cpld_wait(info);
|
||||
writel(data, info->screen_base + LCD_DATA);
|
||||
}
|
||||
|
||||
static inline u8 lcd_read_data(struct fb_info *info)
|
||||
{
|
||||
cpld_wait(info);
|
||||
readl(info->screen_base + LCD_DATA);
|
||||
cpld_wait(info);
|
||||
return readl(info->screen_base + CPLD_DATA) & 0xff;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lcd_busy_wait(struct fb_info *info)
|
||||
{
|
||||
|
@ -507,16 +507,16 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
||||
|
||||
err = fb_alloc_cmap(&info->cmap, 256, 0);
|
||||
if (err)
|
||||
goto failed;
|
||||
goto failed_cmap;
|
||||
|
||||
err = ep93xxfb_alloc_videomem(info);
|
||||
if (err)
|
||||
goto failed;
|
||||
goto failed_videomem;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
err = -ENXIO;
|
||||
goto failed;
|
||||
goto failed_resource;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -532,7 +532,7 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
||||
fbi->mmio_base = ioremap(res->start, resource_size(res));
|
||||
if (!fbi->mmio_base) {
|
||||
err = -ENXIO;
|
||||
goto failed;
|
||||
goto failed_resource;
|
||||
}
|
||||
|
||||
strcpy(info->fix.id, pdev->name);
|
||||
@ -553,24 +553,24 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
||||
if (err == 0) {
|
||||
dev_err(info->dev, "No suitable video mode found\n");
|
||||
err = -EINVAL;
|
||||
goto failed;
|
||||
goto failed_mode;
|
||||
}
|
||||
|
||||
if (mach_info->setup) {
|
||||
err = mach_info->setup(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
goto failed_mode;
|
||||
}
|
||||
|
||||
err = ep93xxfb_check_var(&info->var, info);
|
||||
if (err)
|
||||
goto failed;
|
||||
goto failed_check;
|
||||
|
||||
fbi->clk = clk_get(info->dev, NULL);
|
||||
if (IS_ERR(fbi->clk)) {
|
||||
err = PTR_ERR(fbi->clk);
|
||||
fbi->clk = NULL;
|
||||
goto failed;
|
||||
goto failed_check;
|
||||
}
|
||||
|
||||
ep93xxfb_set_par(info);
|
||||
@ -585,15 +585,17 @@ static int __devinit ep93xxfb_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
if (fbi->clk)
|
||||
clk_put(fbi->clk);
|
||||
if (fbi->mmio_base)
|
||||
iounmap(fbi->mmio_base);
|
||||
ep93xxfb_dealloc_videomem(info);
|
||||
if (&info->cmap)
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
clk_put(fbi->clk);
|
||||
failed_check:
|
||||
if (fbi->mach_info->teardown)
|
||||
fbi->mach_info->teardown(pdev);
|
||||
failed_mode:
|
||||
iounmap(fbi->mmio_base);
|
||||
failed_resource:
|
||||
ep93xxfb_dealloc_videomem(info);
|
||||
failed_videomem:
|
||||
fb_dealloc_cmap(&info->cmap);
|
||||
failed_cmap:
|
||||
kfree(info);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
#include <video/exynos_dp.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "exynos_dp_core.h"
|
||||
|
||||
static int exynos_dp_init_dp(struct exynos_dp_device *dp)
|
||||
{
|
||||
exynos_dp_reset(dp);
|
||||
|
||||
exynos_dp_swreset(dp);
|
||||
|
||||
/* SW defined function Normal operation */
|
||||
exynos_dp_enable_sw_function(dp);
|
||||
|
||||
@ -478,7 +478,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
||||
int lane_count;
|
||||
u8 buf[5];
|
||||
|
||||
u8 *adjust_request;
|
||||
u8 adjust_request[2];
|
||||
u8 voltage_swing;
|
||||
u8 pre_emphasis;
|
||||
u8 training_lane;
|
||||
@ -493,8 +493,8 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
|
||||
/* set training pattern 2 for EQ */
|
||||
exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
|
||||
|
||||
adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
|
||||
- DPCD_ADDR_LANE0_1_STATUS);
|
||||
adjust_request[0] = link_status[4];
|
||||
adjust_request[1] = link_status[5];
|
||||
|
||||
exynos_dp_get_adjust_train(dp, adjust_request);
|
||||
|
||||
@ -566,7 +566,7 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
|
||||
u8 buf[5];
|
||||
u32 reg;
|
||||
|
||||
u8 *adjust_request;
|
||||
u8 adjust_request[2];
|
||||
|
||||
udelay(400);
|
||||
|
||||
@ -575,8 +575,8 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
|
||||
lane_count = dp->link_train.lane_count;
|
||||
|
||||
if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
|
||||
adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
|
||||
- DPCD_ADDR_LANE0_1_STATUS);
|
||||
adjust_request[0] = link_status[4];
|
||||
adjust_request[1] = link_status[5];
|
||||
|
||||
if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
|
||||
/* traing pattern Set to Normal */
|
||||
@ -770,7 +770,7 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
mdelay(100);
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
/* Set to use the register calculated M/N video */
|
||||
@ -804,7 +804,7 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp,
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
mdelay(100);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
if (retval != 0)
|
||||
@ -860,7 +860,8 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL);
|
||||
dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device),
|
||||
GFP_KERNEL);
|
||||
if (!dp) {
|
||||
dev_err(&pdev->dev, "no memory for device data\n");
|
||||
return -ENOMEM;
|
||||
@ -871,8 +872,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
dp->clock = clk_get(&pdev->dev, "dp");
|
||||
if (IS_ERR(dp->clock)) {
|
||||
dev_err(&pdev->dev, "failed to get clock\n");
|
||||
ret = PTR_ERR(dp->clock);
|
||||
goto err_dp;
|
||||
return PTR_ERR(dp->clock);
|
||||
}
|
||||
|
||||
clk_enable(dp->clock);
|
||||
@ -884,35 +884,25 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
res = request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&pdev->dev));
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "failed to request registers region\n");
|
||||
ret = -EINVAL;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
dp->res = res;
|
||||
|
||||
dp->reg_base = ioremap(res->start, resource_size(res));
|
||||
dp->reg_base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!dp->reg_base) {
|
||||
dev_err(&pdev->dev, "failed to ioremap\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_req_region;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
dp->irq = platform_get_irq(pdev, 0);
|
||||
if (!dp->irq) {
|
||||
dev_err(&pdev->dev, "failed to get irq\n");
|
||||
ret = -ENODEV;
|
||||
goto err_ioremap;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
ret = request_irq(dp->irq, exynos_dp_irq_handler, 0,
|
||||
"exynos-dp", dp);
|
||||
ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, 0,
|
||||
"exynos-dp", dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to request irq\n");
|
||||
goto err_ioremap;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
dp->video_info = pdata->video_info;
|
||||
@ -924,7 +914,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
ret = exynos_dp_detect_hpd(dp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to detect hpd\n");
|
||||
goto err_irq;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
exynos_dp_handle_edid(dp);
|
||||
@ -933,7 +923,7 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
dp->video_info->link_rate);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to do link train\n");
|
||||
goto err_irq;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
exynos_dp_enable_scramble(dp, 1);
|
||||
@ -947,23 +937,15 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
|
||||
ret = exynos_dp_config_video(dp, dp->video_info);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to config video\n");
|
||||
goto err_irq;
|
||||
goto err_clock;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dp);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
free_irq(dp->irq, dp);
|
||||
err_ioremap:
|
||||
iounmap(dp->reg_base);
|
||||
err_req_region:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_clock:
|
||||
clk_put(dp->clock);
|
||||
err_dp:
|
||||
kfree(dp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -976,16 +958,9 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
|
||||
if (pdata && pdata->phy_exit)
|
||||
pdata->phy_exit();
|
||||
|
||||
free_irq(dp->irq, dp);
|
||||
iounmap(dp->reg_base);
|
||||
|
||||
clk_disable(dp->clock);
|
||||
clk_put(dp->clock);
|
||||
|
||||
release_mem_region(dp->res->start, resource_size(dp->res));
|
||||
|
||||
kfree(dp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ struct link_train {
|
||||
|
||||
struct exynos_dp_device {
|
||||
struct device *dev;
|
||||
struct resource *res;
|
||||
struct clk *clock;
|
||||
unsigned int irq;
|
||||
void __iomem *reg_base;
|
||||
@ -39,8 +38,10 @@ struct exynos_dp_device {
|
||||
void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_stop_video(struct exynos_dp_device *dp);
|
||||
void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
|
||||
void exynos_dp_init_analog_param(struct exynos_dp_device *dp);
|
||||
void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
|
||||
void exynos_dp_reset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_swreset(struct exynos_dp_device *dp);
|
||||
void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
|
||||
u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
|
||||
void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
#include <video/exynos_dp.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
|
||||
#include "exynos_dp_core.h"
|
||||
#include "exynos_dp_reg.h"
|
||||
|
||||
@ -65,6 +63,28 @@ void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
|
||||
}
|
||||
|
||||
void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
reg = TX_TERMINAL_CTRL_50_OHM;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
|
||||
|
||||
reg = SEL_24M | TX_DVDD_BIT_1_0625V;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
|
||||
|
||||
reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
|
||||
|
||||
reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
|
||||
TX_CUR1_2X | TX_CUR_8_MA;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
|
||||
|
||||
reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
|
||||
CH1_AMP_400_MV | CH0_AMP_400_MV;
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
|
||||
}
|
||||
|
||||
void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
|
||||
{
|
||||
/* Set interrupt pin assertion polarity as high */
|
||||
@ -89,8 +109,6 @@ void exynos_dp_reset(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
|
||||
|
||||
exynos_dp_stop_video(dp);
|
||||
exynos_dp_enable_video_mute(dp, 0);
|
||||
|
||||
@ -131,9 +149,15 @@ void exynos_dp_reset(struct exynos_dp_device *dp)
|
||||
|
||||
writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
|
||||
|
||||
exynos_dp_init_analog_param(dp);
|
||||
exynos_dp_init_interrupt(dp);
|
||||
}
|
||||
|
||||
void exynos_dp_swreset(struct exynos_dp_device *dp)
|
||||
{
|
||||
writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
|
||||
}
|
||||
|
||||
void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
@ -271,6 +295,7 @@ void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
|
||||
void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
|
||||
{
|
||||
u32 reg;
|
||||
int timeout_loop = 0;
|
||||
|
||||
exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
|
||||
|
||||
@ -282,9 +307,19 @@ void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
|
||||
writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
|
||||
|
||||
/* Power up PLL */
|
||||
if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED)
|
||||
if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
|
||||
exynos_dp_set_pll_power_down(dp, 0);
|
||||
|
||||
while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
|
||||
timeout_loop++;
|
||||
if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
|
||||
dev_err(dp->dev, "failed to get pll lock status\n");
|
||||
return;
|
||||
}
|
||||
usleep_range(10, 20);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable Serdes FIFO function and Link symbol clock domain module */
|
||||
reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
|
||||
reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
|
||||
|
@ -24,6 +24,12 @@
|
||||
|
||||
#define EXYNOS_DP_LANE_MAP 0x35C
|
||||
|
||||
#define EXYNOS_DP_ANALOG_CTL_1 0x370
|
||||
#define EXYNOS_DP_ANALOG_CTL_2 0x374
|
||||
#define EXYNOS_DP_ANALOG_CTL_3 0x378
|
||||
#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C
|
||||
#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380
|
||||
|
||||
#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390
|
||||
|
||||
#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4
|
||||
@ -166,6 +172,29 @@
|
||||
#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
|
||||
#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_1 */
|
||||
#define TX_TERMINAL_CTRL_50_OHM (0x1 << 4)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_2 */
|
||||
#define SEL_24M (0x1 << 3)
|
||||
#define TX_DVDD_BIT_1_0625V (0x4 << 0)
|
||||
|
||||
/* EXYNOS_DP_ANALOG_CTL_3 */
|
||||
#define DRIVE_DVDD_BIT_1_0625V (0x4 << 5)
|
||||
#define VCO_BIT_600_MICRO (0x5 << 0)
|
||||
|
||||
/* EXYNOS_DP_PLL_FILTER_CTL_1 */
|
||||
#define PD_RING_OSC (0x1 << 6)
|
||||
#define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4)
|
||||
#define TX_CUR1_2X (0x1 << 2)
|
||||
#define TX_CUR_8_MA (0x2 << 0)
|
||||
|
||||
/* EXYNOS_DP_TX_AMP_TUNING_CTL */
|
||||
#define CH3_AMP_400_MV (0x0 << 24)
|
||||
#define CH2_AMP_400_MV (0x0 << 16)
|
||||
#define CH1_AMP_400_MV (0x0 << 8)
|
||||
#define CH0_AMP_400_MV (0x0 << 0)
|
||||
|
||||
/* EXYNOS_DP_AUX_HW_RETRY_CTL */
|
||||
#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
|
||||
#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
|
||||
|
@ -58,7 +58,7 @@ static struct mipi_dsim_platform_data *to_dsim_plat(struct platform_device
|
||||
}
|
||||
|
||||
static struct regulator_bulk_data supplies[] = {
|
||||
{ .supply = "vdd10", },
|
||||
{ .supply = "vdd11", },
|
||||
{ .supply = "vdd18", },
|
||||
};
|
||||
|
||||
@ -102,6 +102,8 @@ static void exynos_mipi_update_cfg(struct mipi_dsim_device *dsim)
|
||||
/* set display timing. */
|
||||
exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
|
||||
|
||||
exynos_mipi_dsi_init_interrupt(dsim);
|
||||
|
||||
/*
|
||||
* data from Display controller(FIMD) is transferred in video mode
|
||||
* but in case of command mode, all settigs is updated to registers.
|
||||
@ -413,27 +415,30 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
|
||||
goto err_platform_get_irq;
|
||||
}
|
||||
|
||||
init_completion(&dsim_wr_comp);
|
||||
init_completion(&dsim_rd_comp);
|
||||
platform_set_drvdata(pdev, dsim);
|
||||
|
||||
ret = request_irq(dsim->irq, exynos_mipi_dsi_interrupt_handler,
|
||||
IRQF_SHARED, pdev->name, dsim);
|
||||
IRQF_SHARED, dev_name(&pdev->dev), dsim);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "failed to request dsim irq\n");
|
||||
ret = -EINVAL;
|
||||
goto err_bind;
|
||||
}
|
||||
|
||||
init_completion(&dsim_wr_comp);
|
||||
init_completion(&dsim_rd_comp);
|
||||
|
||||
/* enable interrupt */
|
||||
/* enable interrupts */
|
||||
exynos_mipi_dsi_init_interrupt(dsim);
|
||||
|
||||
/* initialize mipi-dsi client(lcd panel). */
|
||||
if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->probe)
|
||||
dsim_ddi->dsim_lcd_drv->probe(dsim_ddi->dsim_lcd_dev);
|
||||
|
||||
/* in case that mipi got enabled at bootloader. */
|
||||
if (dsim_pd->enabled)
|
||||
goto out;
|
||||
/* in case mipi-dsi has been enabled by bootloader */
|
||||
if (dsim_pd->enabled) {
|
||||
exynos_mipi_regulator_enable(dsim);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* lcd panel power on. */
|
||||
if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->power_on)
|
||||
@ -453,12 +458,11 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
|
||||
|
||||
dsim->suspended = false;
|
||||
|
||||
out:
|
||||
done:
|
||||
platform_set_drvdata(pdev, dsim);
|
||||
|
||||
dev_dbg(&pdev->dev, "mipi-dsi driver(%s mode) has been probed.\n",
|
||||
(dsim_config->e_interface == DSIM_COMMAND) ?
|
||||
"CPU" : "RGB");
|
||||
dev_dbg(&pdev->dev, "%s() completed sucessfuly (%s mode)\n", __func__,
|
||||
dsim_config->e_interface == DSIM_COMMAND ? "CPU" : "RGB");
|
||||
|
||||
return 0;
|
||||
|
||||
@ -515,10 +519,10 @@ static int __devexit exynos_mipi_dsi_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int exynos_mipi_dsi_suspend(struct platform_device *pdev,
|
||||
pm_message_t state)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int exynos_mipi_dsi_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
|
||||
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
|
||||
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
|
||||
@ -544,8 +548,9 @@ static int exynos_mipi_dsi_suspend(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int exynos_mipi_dsi_resume(struct platform_device *pdev)
|
||||
static int exynos_mipi_dsi_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct mipi_dsim_device *dsim = platform_get_drvdata(pdev);
|
||||
struct mipi_dsim_lcd_driver *client_drv = dsim->dsim_lcd_drv;
|
||||
struct mipi_dsim_lcd_device *client_dev = dsim->dsim_lcd_dev;
|
||||
@ -577,19 +582,19 @@ static int exynos_mipi_dsi_resume(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define exynos_mipi_dsi_suspend NULL
|
||||
#define exynos_mipi_dsi_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops exynos_mipi_dsi_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(exynos_mipi_dsi_suspend, exynos_mipi_dsi_resume)
|
||||
};
|
||||
|
||||
static struct platform_driver exynos_mipi_dsi_driver = {
|
||||
.probe = exynos_mipi_dsi_probe,
|
||||
.remove = __devexit_p(exynos_mipi_dsi_remove),
|
||||
.suspend = exynos_mipi_dsi_suspend,
|
||||
.resume = exynos_mipi_dsi_resume,
|
||||
.driver = {
|
||||
.name = "exynos-mipi-dsim",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &exynos_mipi_dsi_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -76,33 +76,25 @@ static unsigned int dpll_table[15] = {
|
||||
|
||||
irqreturn_t exynos_mipi_dsi_interrupt_handler(int irq, void *dev_id)
|
||||
{
|
||||
unsigned int intsrc = 0;
|
||||
unsigned int intmsk = 0;
|
||||
struct mipi_dsim_device *dsim = NULL;
|
||||
struct mipi_dsim_device *dsim = dev_id;
|
||||
unsigned int intsrc, intmsk;
|
||||
|
||||
dsim = dev_id;
|
||||
if (!dsim) {
|
||||
dev_dbg(dsim->dev, KERN_ERR "%s:error: wrong parameter\n",
|
||||
__func__);
|
||||
return IRQ_HANDLED;
|
||||
if (dsim == NULL) {
|
||||
dev_err(dsim->dev, "%s: wrong parameter\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
intsrc = exynos_mipi_dsi_read_interrupt(dsim);
|
||||
intmsk = exynos_mipi_dsi_read_interrupt_mask(dsim);
|
||||
intmsk = ~intmsk & intsrc;
|
||||
|
||||
intmsk = ~(intmsk) & intsrc;
|
||||
|
||||
switch (intmsk) {
|
||||
case INTMSK_RX_DONE:
|
||||
if (intsrc & INTMSK_RX_DONE) {
|
||||
complete(&dsim_rd_comp);
|
||||
dev_dbg(dsim->dev, "MIPI INTMSK_RX_DONE\n");
|
||||
break;
|
||||
case INTMSK_FIFO_EMPTY:
|
||||
}
|
||||
if (intsrc & INTMSK_FIFO_EMPTY) {
|
||||
complete(&dsim_wr_comp);
|
||||
dev_dbg(dsim->dev, "MIPI INTMSK_FIFO_EMPTY\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
exynos_mipi_dsi_clear_interrupt(dsim, intmsk);
|
||||
@ -738,11 +730,11 @@ int exynos_mipi_dsi_set_display_mode(struct mipi_dsim_device *dsim,
|
||||
if (dsim_config->auto_vertical_cnt == 0) {
|
||||
exynos_mipi_dsi_set_main_disp_vporch(dsim,
|
||||
dsim_config->cmd_allow,
|
||||
timing->upper_margin,
|
||||
timing->lower_margin);
|
||||
timing->lower_margin,
|
||||
timing->upper_margin);
|
||||
exynos_mipi_dsi_set_main_disp_hporch(dsim,
|
||||
timing->left_margin,
|
||||
timing->right_margin);
|
||||
timing->right_margin,
|
||||
timing->left_margin);
|
||||
exynos_mipi_dsi_set_main_disp_sync_area(dsim,
|
||||
timing->vsync_len,
|
||||
timing->hsync_len);
|
||||
|
@ -293,9 +293,20 @@ static void s6e8ax0_panel_cond(struct s6e8ax0 *lcd)
|
||||
0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
|
||||
0xc8, 0x08, 0x48, 0xc1, 0x00, 0xc1, 0xff, 0xff, 0xc8
|
||||
};
|
||||
static const unsigned char data_to_send_panel_reverse[] = {
|
||||
0xf8, 0x19, 0x35, 0x00, 0x00, 0x00, 0x93, 0x00, 0x3c, 0x7d,
|
||||
0x08, 0x27, 0x7d, 0x3f, 0x00, 0x00, 0x00, 0x20, 0x04, 0x08,
|
||||
0x6e, 0x00, 0x00, 0x00, 0x02, 0x08, 0x08, 0x23, 0x23, 0xc0,
|
||||
0xc1, 0x01, 0x41, 0xc1, 0x00, 0xc1, 0xf6, 0xf6, 0xc1
|
||||
};
|
||||
|
||||
ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
|
||||
data_to_send, ARRAY_SIZE(data_to_send));
|
||||
if (lcd->dsim_dev->panel_reverse)
|
||||
ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
|
||||
data_to_send_panel_reverse,
|
||||
ARRAY_SIZE(data_to_send_panel_reverse));
|
||||
else
|
||||
ops->cmd_write(lcd_to_master(lcd), MIPI_DSI_DCS_LONG_WRITE,
|
||||
data_to_send, ARRAY_SIZE(data_to_send));
|
||||
}
|
||||
|
||||
static void s6e8ax0_display_cond(struct s6e8ax0 *lcd)
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <linux/rmap.h>
|
||||
#include <linux/pagemap.h>
|
||||
|
||||
struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs)
|
||||
static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs)
|
||||
{
|
||||
void *screen_base = (void __force *) info->screen_base;
|
||||
struct page *page;
|
||||
@ -107,6 +107,10 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma,
|
||||
/* protect against the workqueue changing the page list */
|
||||
mutex_lock(&fbdefio->lock);
|
||||
|
||||
/* first write in this cycle, notify the driver */
|
||||
if (fbdefio->first_io && list_empty(&fbdefio->pagelist))
|
||||
fbdefio->first_io(info);
|
||||
|
||||
/*
|
||||
* We want the page to remain locked from ->page_mkwrite until
|
||||
* the PTE is marked dirty to avoid page_mkclean() being called
|
||||
|
@ -80,6 +80,8 @@ EXPORT_SYMBOL(framebuffer_alloc);
|
||||
*/
|
||||
void framebuffer_release(struct fb_info *info)
|
||||
{
|
||||
if (!info)
|
||||
return;
|
||||
kfree(info->apertures);
|
||||
kfree(info);
|
||||
}
|
||||
|
@ -834,7 +834,6 @@ static void update_lcdc(struct fb_info *info)
|
||||
diu_ops.set_pixel_clock(var->pixclock);
|
||||
|
||||
out_be32(&hw->syn_pol, 0); /* SYNC SIGNALS POLARITY */
|
||||
out_be32(&hw->thresholds, 0x00037800); /* The Thresholds */
|
||||
out_be32(&hw->int_status, 0); /* INTERRUPT STATUS */
|
||||
out_be32(&hw->plut, 0x01F5F666);
|
||||
|
||||
|
@ -680,6 +680,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
|
||||
+ dinfo->fb.size);
|
||||
if (!dinfo->aperture.virtual) {
|
||||
ERR_MSG("Cannot remap FB region.\n");
|
||||
agp_backend_release(bridge);
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -689,6 +690,7 @@ static int __devinit intelfb_pci_register(struct pci_dev *pdev,
|
||||
INTEL_REG_SIZE);
|
||||
if (!dinfo->mmio_base) {
|
||||
ERR_MSG("Cannot remap MMIO region.\n");
|
||||
agp_backend_release(bridge);
|
||||
cleanup(dinfo);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ static int mb862xx_i2c_read_byte(struct i2c_adapter *adap, u8 *byte, int last)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mb862xx_i2c_stop(struct i2c_adapter *adap)
|
||||
static void mb862xx_i2c_stop(struct i2c_adapter *adap)
|
||||
{
|
||||
struct mb862xxfb_par *par = adap->algo_data;
|
||||
|
||||
|
@ -579,7 +579,7 @@ static ssize_t mb862xxfb_show_dispregs(struct device *dev,
|
||||
|
||||
static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL);
|
||||
|
||||
irqreturn_t mb862xx_intr(int irq, void *dev_id)
|
||||
static irqreturn_t mb862xx_intr(int irq, void *dev_id)
|
||||
{
|
||||
struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id;
|
||||
unsigned long reg_ist, mask;
|
||||
|
@ -950,7 +950,7 @@ static int __devinit mbxfb_probe(struct platform_device *dev)
|
||||
|
||||
mfbi->fb_virt_addr = ioremap_nocache(mfbi->fb_phys_addr,
|
||||
res_size(mfbi->fb_req));
|
||||
if (!mfbi->reg_virt_addr) {
|
||||
if (!mfbi->fb_virt_addr) {
|
||||
dev_err(&dev->dev, "failed to ioremap frame buffer\n");
|
||||
ret = -EINVAL;
|
||||
goto err4;
|
||||
|
@ -889,6 +889,18 @@ static int __devexit mxsfb_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxsfb_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct fb_info *fb_info = platform_get_drvdata(pdev);
|
||||
struct mxsfb_info *host = to_imxfb_host(fb_info);
|
||||
|
||||
/*
|
||||
* Force stop the LCD controller as keeping it running during reboot
|
||||
* might interfere with the BootROM's boot mode pads sampling.
|
||||
*/
|
||||
writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
|
||||
}
|
||||
|
||||
static struct platform_device_id mxsfb_devtype[] = {
|
||||
{
|
||||
.name = "imx23-fb",
|
||||
@ -905,6 +917,7 @@ MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
|
||||
static struct platform_driver mxsfb_driver = {
|
||||
.probe = mxsfb_probe,
|
||||
.remove = __devexit_p(mxsfb_remove),
|
||||
.shutdown = mxsfb_shutdown,
|
||||
.id_table = mxsfb_devtype,
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
|
@ -39,14 +39,6 @@ config FB_OMAP_LCD_MIPID
|
||||
the Mobile Industry Processor Interface DBI-C/DCS
|
||||
specification. (Supported LCDs: Philips LPH8923, Sharp LS041Y3)
|
||||
|
||||
config FB_OMAP_BOOTLOADER_INIT
|
||||
bool "Check bootloader initialization"
|
||||
depends on FB_OMAP
|
||||
help
|
||||
Say Y here if you want to enable checking if the bootloader has
|
||||
already initialized the display controller. In this case the
|
||||
driver will skip the initialization.
|
||||
|
||||
config FB_OMAP_CONSISTENT_DMA_SIZE
|
||||
int "Consistent DMA memory size (MB)"
|
||||
depends on FB_OMAP
|
||||
|
@ -739,12 +739,6 @@ static void acx_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
}
|
||||
}
|
||||
|
||||
static void acx_panel_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static int acx_panel_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
@ -762,7 +756,6 @@ static struct omap_dss_driver acx_panel_driver = {
|
||||
.resume = acx_panel_resume,
|
||||
|
||||
.set_timings = acx_panel_set_timings,
|
||||
.get_timings = acx_panel_get_timings,
|
||||
.check_timings = acx_panel_check_timings,
|
||||
|
||||
.get_recommended_bpp = acx_get_recommended_bpp,
|
||||
|
@ -386,6 +386,106 @@ static struct panel_config generic_dpi_panels[] = {
|
||||
|
||||
.name = "innolux_at080tn52",
|
||||
},
|
||||
|
||||
/* Mitsubishi AA084SB01 */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 600,
|
||||
.pixel_clock = 40000,
|
||||
|
||||
.hsw = 1,
|
||||
.hfp = 254,
|
||||
.hbp = 1,
|
||||
|
||||
.vsw = 1,
|
||||
.vfp = 26,
|
||||
.vbp = 1,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT,
|
||||
.name = "mitsubishi_aa084sb01",
|
||||
},
|
||||
/* EDT ET0500G0DH6 */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 480,
|
||||
.pixel_clock = 33260,
|
||||
|
||||
.hsw = 128,
|
||||
.hfp = 216,
|
||||
.hbp = 40,
|
||||
|
||||
.vsw = 2,
|
||||
.vfp = 35,
|
||||
.vbp = 10,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT,
|
||||
.name = "edt_et0500g0dh6",
|
||||
},
|
||||
|
||||
/* Prime-View PD050VL1 */
|
||||
{
|
||||
{
|
||||
.x_res = 640,
|
||||
.y_res = 480,
|
||||
|
||||
.pixel_clock = 25000,
|
||||
|
||||
.hsw = 96,
|
||||
.hfp = 18,
|
||||
.hbp = 46,
|
||||
|
||||
.vsw = 2,
|
||||
.vfp = 10,
|
||||
.vbp = 33,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
|
||||
.name = "primeview_pd050vl1",
|
||||
},
|
||||
|
||||
/* Prime-View PM070WL4 */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 480,
|
||||
|
||||
.pixel_clock = 32000,
|
||||
|
||||
.hsw = 128,
|
||||
.hfp = 42,
|
||||
.hbp = 86,
|
||||
|
||||
.vsw = 2,
|
||||
.vfp = 10,
|
||||
.vbp = 33,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
|
||||
.name = "primeview_pm070wl4",
|
||||
},
|
||||
|
||||
/* Prime-View PD104SLF */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 600,
|
||||
|
||||
.pixel_clock = 40000,
|
||||
|
||||
.hsw = 128,
|
||||
.hfp = 42,
|
||||
.hbp = 86,
|
||||
|
||||
.vsw = 4,
|
||||
.vfp = 1,
|
||||
.vbp = 23,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
|
||||
.name = "primeview_pd104slf",
|
||||
},
|
||||
};
|
||||
|
||||
struct panel_drv_data {
|
||||
@ -549,12 +649,6 @@ static void generic_dpi_panel_set_timings(struct omap_dss_device *dssdev,
|
||||
dpi_set_timings(dssdev, timings);
|
||||
}
|
||||
|
||||
static void generic_dpi_panel_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static int generic_dpi_panel_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
@ -571,7 +665,6 @@ static struct omap_dss_driver dpi_driver = {
|
||||
.resume = generic_dpi_panel_resume,
|
||||
|
||||
.set_timings = generic_dpi_panel_set_timings,
|
||||
.get_timings = generic_dpi_panel_get_timings,
|
||||
.check_timings = generic_dpi_panel_check_timings,
|
||||
|
||||
.driver = {
|
||||
|
@ -610,12 +610,6 @@ static int n8x0_panel_resume(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void n8x0_panel_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres)
|
||||
{
|
||||
@ -678,8 +672,6 @@ static struct omap_dss_driver n8x0_panel_driver = {
|
||||
.get_resolution = n8x0_panel_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
||||
.get_timings = n8x0_panel_get_timings,
|
||||
|
||||
.driver = {
|
||||
.name = "n8x0_panel",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
@ -55,73 +54,6 @@ 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;
|
||||
int min_uV;
|
||||
int max_uV;
|
||||
};
|
||||
|
||||
static void free_regulators(struct panel_regulator *regulators, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
/* disable/put in reverse order */
|
||||
regulator_disable(regulators[n - i - 1].regulator);
|
||||
regulator_put(regulators[n - i - 1].regulator);
|
||||
}
|
||||
}
|
||||
|
||||
static int init_regulators(struct omap_dss_device *dssdev,
|
||||
struct panel_regulator *regulators, int n)
|
||||
{
|
||||
int r, i, v;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
struct regulator *reg;
|
||||
|
||||
reg = regulator_get(&dssdev->dev, regulators[i].name);
|
||||
if (IS_ERR(reg)) {
|
||||
dev_err(&dssdev->dev, "failed to get regulator %s\n",
|
||||
regulators[i].name);
|
||||
r = PTR_ERR(reg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* FIXME: better handling of fixed vs. variable regulators */
|
||||
v = regulator_get_voltage(reg);
|
||||
if (v < regulators[i].min_uV || v > regulators[i].max_uV) {
|
||||
r = regulator_set_voltage(reg, regulators[i].min_uV,
|
||||
regulators[i].max_uV);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev,
|
||||
"failed to set regulator %s voltage\n",
|
||||
regulators[i].name);
|
||||
regulator_put(reg);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
r = regulator_enable(reg);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable regulator %s\n",
|
||||
regulators[i].name);
|
||||
regulator_put(reg);
|
||||
goto err;
|
||||
}
|
||||
|
||||
regulators[i].regulator = reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free_regulators(regulators, i);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct panel_config - panel configuration
|
||||
* @name: panel name
|
||||
@ -150,8 +82,6 @@ struct panel_config {
|
||||
unsigned int low;
|
||||
} reset_sequence;
|
||||
|
||||
struct panel_regulator *regulators;
|
||||
int num_regulators;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -577,12 +507,6 @@ static const struct backlight_ops taal_bl_ops = {
|
||||
.update_status = taal_bl_update_status,
|
||||
};
|
||||
|
||||
static void taal_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static void taal_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres)
|
||||
{
|
||||
@ -977,11 +901,6 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
||||
|
||||
atomic_set(&td->do_update, 0);
|
||||
|
||||
r = init_regulators(dssdev, panel_config->regulators,
|
||||
panel_config->num_regulators);
|
||||
if (r)
|
||||
goto err_reg;
|
||||
|
||||
td->workqueue = create_singlethread_workqueue("taal_esd");
|
||||
if (td->workqueue == NULL) {
|
||||
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
|
||||
@ -1087,8 +1006,6 @@ err_bl:
|
||||
err_rst_gpio:
|
||||
destroy_workqueue(td->workqueue);
|
||||
err_wq:
|
||||
free_regulators(panel_config->regulators, panel_config->num_regulators);
|
||||
err_reg:
|
||||
kfree(td);
|
||||
err:
|
||||
return r;
|
||||
@ -1125,9 +1042,6 @@ static void __exit taal_remove(struct omap_dss_device *dssdev)
|
||||
/* reset, to be sure that the panel is in a valid state */
|
||||
taal_hw_reset(dssdev);
|
||||
|
||||
free_regulators(td->panel_config->regulators,
|
||||
td->panel_config->num_regulators);
|
||||
|
||||
if (gpio_is_valid(panel_data->reset_gpio))
|
||||
gpio_free(panel_data->reset_gpio);
|
||||
|
||||
@ -1909,8 +1823,6 @@ static struct omap_dss_driver taal_driver = {
|
||||
.run_test = taal_run_test,
|
||||
.memory_read = taal_memory_read,
|
||||
|
||||
.get_timings = taal_get_timings,
|
||||
|
||||
.driver = {
|
||||
.name = "taal",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -47,13 +47,9 @@ struct panel_drv_data {
|
||||
struct mutex lock;
|
||||
|
||||
int pd_gpio;
|
||||
};
|
||||
|
||||
static inline struct tfp410_platform_data
|
||||
*get_pdata(const struct omap_dss_device *dssdev)
|
||||
{
|
||||
return dssdev->data;
|
||||
}
|
||||
struct i2c_adapter *i2c_adapter;
|
||||
};
|
||||
|
||||
static int tfp410_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
@ -68,7 +64,7 @@ static int tfp410_power_on(struct omap_dss_device *dssdev)
|
||||
goto err0;
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_set_value(ddata->pd_gpio, 1);
|
||||
gpio_set_value_cansleep(ddata->pd_gpio, 1);
|
||||
|
||||
return 0;
|
||||
err0:
|
||||
@ -83,18 +79,18 @@ static void tfp410_power_off(struct omap_dss_device *dssdev)
|
||||
return;
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_set_value(ddata->pd_gpio, 0);
|
||||
gpio_set_value_cansleep(ddata->pd_gpio, 0);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int tfp410_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tfp410_platform_data *pdata = get_pdata(dssdev);
|
||||
struct panel_drv_data *ddata;
|
||||
int r;
|
||||
int i2c_bus_num;
|
||||
|
||||
ddata = kzalloc(sizeof(*ddata), GFP_KERNEL);
|
||||
ddata = devm_kzalloc(&dssdev->dev, sizeof(*ddata), GFP_KERNEL);
|
||||
if (!ddata)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -104,10 +100,15 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
||||
ddata->dssdev = dssdev;
|
||||
mutex_init(&ddata->lock);
|
||||
|
||||
if (pdata)
|
||||
if (dssdev->data) {
|
||||
struct tfp410_platform_data *pdata = dssdev->data;
|
||||
|
||||
ddata->pd_gpio = pdata->power_down_gpio;
|
||||
else
|
||||
i2c_bus_num = pdata->i2c_bus_num;
|
||||
} else {
|
||||
ddata->pd_gpio = -1;
|
||||
i2c_bus_num = -1;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio)) {
|
||||
r = gpio_request_one(ddata->pd_gpio, GPIOF_OUT_INIT_LOW,
|
||||
@ -115,13 +116,31 @@ static int tfp410_probe(struct omap_dss_device *dssdev)
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "Failed to request PD GPIO %d\n",
|
||||
ddata->pd_gpio);
|
||||
ddata->pd_gpio = -1;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (i2c_bus_num != -1) {
|
||||
struct i2c_adapter *adapter;
|
||||
|
||||
adapter = i2c_get_adapter(i2c_bus_num);
|
||||
if (!adapter) {
|
||||
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
|
||||
i2c_bus_num);
|
||||
r = -EINVAL;
|
||||
goto err_i2c;
|
||||
}
|
||||
|
||||
ddata->i2c_adapter = adapter;
|
||||
}
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, ddata);
|
||||
|
||||
return 0;
|
||||
err_i2c:
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
||||
@ -130,14 +149,15 @@ static void __exit tfp410_remove(struct omap_dss_device *dssdev)
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
||||
if (ddata->i2c_adapter)
|
||||
i2c_put_adapter(ddata->i2c_adapter);
|
||||
|
||||
if (gpio_is_valid(ddata->pd_gpio))
|
||||
gpio_free(ddata->pd_gpio);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, NULL);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
||||
kfree(ddata);
|
||||
}
|
||||
|
||||
static int tfp410_enable(struct omap_dss_device *dssdev)
|
||||
@ -269,27 +289,17 @@ static int tfp410_read_edid(struct omap_dss_device *dssdev,
|
||||
u8 *edid, int len)
|
||||
{
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
|
||||
struct tfp410_platform_data *pdata = get_pdata(dssdev);
|
||||
struct i2c_adapter *adapter;
|
||||
int r, l, bytes_read;
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
||||
if (pdata->i2c_bus_num == 0) {
|
||||
if (!ddata->i2c_adapter) {
|
||||
r = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
adapter = i2c_get_adapter(pdata->i2c_bus_num);
|
||||
if (!adapter) {
|
||||
dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n",
|
||||
pdata->i2c_bus_num);
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
l = min(EDID_LENGTH, len);
|
||||
r = tfp410_ddc_read(adapter, edid, l, 0);
|
||||
r = tfp410_ddc_read(ddata->i2c_adapter, edid, l, 0);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
@ -299,7 +309,7 @@ static int tfp410_read_edid(struct omap_dss_device *dssdev,
|
||||
if (len > EDID_LENGTH && edid[0x7e] > 0) {
|
||||
l = min(EDID_LENGTH, len - EDID_LENGTH);
|
||||
|
||||
r = tfp410_ddc_read(adapter, edid + EDID_LENGTH,
|
||||
r = tfp410_ddc_read(ddata->i2c_adapter, edid + EDID_LENGTH,
|
||||
l, EDID_LENGTH);
|
||||
if (r)
|
||||
goto err;
|
||||
@ -319,21 +329,15 @@ err:
|
||||
static bool tfp410_detect(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct panel_drv_data *ddata = dev_get_drvdata(&dssdev->dev);
|
||||
struct tfp410_platform_data *pdata = get_pdata(dssdev);
|
||||
struct i2c_adapter *adapter;
|
||||
unsigned char out;
|
||||
int r;
|
||||
|
||||
mutex_lock(&ddata->lock);
|
||||
|
||||
if (pdata->i2c_bus_num == 0)
|
||||
if (!ddata->i2c_adapter)
|
||||
goto out;
|
||||
|
||||
adapter = i2c_get_adapter(pdata->i2c_bus_num);
|
||||
if (!adapter)
|
||||
goto out;
|
||||
|
||||
r = tfp410_ddc_read(adapter, &out, 1, 0);
|
||||
r = tfp410_ddc_read(ddata->i2c_adapter, &out, 1, 0);
|
||||
|
||||
mutex_unlock(&ddata->lock);
|
||||
|
||||
|
@ -272,13 +272,16 @@ static const struct omap_video_timings tpo_td043_timings = {
|
||||
static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043)
|
||||
{
|
||||
int nreset_gpio = tpo_td043->nreset_gpio;
|
||||
int r;
|
||||
|
||||
if (tpo_td043->powered_on)
|
||||
return 0;
|
||||
|
||||
regulator_enable(tpo_td043->vcc_reg);
|
||||
r = regulator_enable(tpo_td043->vcc_reg);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
/* wait for regulator to stabilize */
|
||||
/* wait for panel to stabilize */
|
||||
msleep(160);
|
||||
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
@ -470,6 +473,18 @@ static void tpo_td043_remove(struct omap_dss_device *dssdev)
|
||||
gpio_free(nreset_gpio);
|
||||
}
|
||||
|
||||
static void tpo_td043_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
dpi_set_timings(dssdev, timings);
|
||||
}
|
||||
|
||||
static int tpo_td043_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
return dpi_check_timings(dssdev, timings);
|
||||
}
|
||||
|
||||
static struct omap_dss_driver tpo_td043_driver = {
|
||||
.probe = tpo_td043_probe,
|
||||
.remove = tpo_td043_remove,
|
||||
@ -481,6 +496,9 @@ static struct omap_dss_driver tpo_td043_driver = {
|
||||
.set_mirror = tpo_td043_set_hmirror,
|
||||
.get_mirror = tpo_td043_get_hmirror,
|
||||
|
||||
.set_timings = tpo_td043_set_timings,
|
||||
.check_timings = tpo_td043_check_timings,
|
||||
|
||||
.driver = {
|
||||
.name = "tpo_td043mtea1_panel",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -68,6 +68,10 @@ config OMAP4_DSS_HDMI
|
||||
HDMI Interface. This adds the High Definition Multimedia Interface.
|
||||
See http://www.hdmi.org/ for HDMI specification.
|
||||
|
||||
config OMAP4_DSS_HDMI_AUDIO
|
||||
bool
|
||||
depends on OMAP4_DSS_HDMI
|
||||
|
||||
config OMAP2_DSS_SDI
|
||||
bool "SDI support"
|
||||
depends on ARCH_OMAP3
|
||||
@ -90,15 +94,6 @@ config OMAP2_DSS_DSI
|
||||
|
||||
See http://www.mipi.org/ for DSI spesifications.
|
||||
|
||||
config OMAP2_DSS_FAKE_VSYNC
|
||||
bool "Fake VSYNC irq from manual update displays"
|
||||
default n
|
||||
help
|
||||
If this is selected, DSI will generate a fake DISPC VSYNC interrupt
|
||||
when DSI has sent a frame. This is only needed with DSI or RFBI
|
||||
displays using manual mode, and you want VSYNC to, for example,
|
||||
time animation.
|
||||
|
||||
config OMAP2_DSS_MIN_FCK_PER_PCK
|
||||
int "Minimum FCK/PCK ratio (for scaling)"
|
||||
range 0 32
|
||||
|
@ -99,6 +99,11 @@ struct mgr_priv_data {
|
||||
|
||||
/* If true, a display is enabled using this manager */
|
||||
bool enabled;
|
||||
|
||||
bool extra_info_dirty;
|
||||
bool shadow_extra_info_dirty;
|
||||
|
||||
struct omap_video_timings timings;
|
||||
};
|
||||
|
||||
static struct {
|
||||
@ -176,7 +181,7 @@ static bool mgr_manual_update(struct omap_overlay_manager *mgr)
|
||||
}
|
||||
|
||||
static int dss_check_settings_low(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev, bool applying)
|
||||
bool applying)
|
||||
{
|
||||
struct omap_overlay_info *oi;
|
||||
struct omap_overlay_manager_info *mi;
|
||||
@ -187,6 +192,9 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
|
||||
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (!mp->enabled)
|
||||
return 0;
|
||||
|
||||
if (applying && mp->user_info_dirty)
|
||||
mi = &mp->user_info;
|
||||
else
|
||||
@ -206,26 +214,24 @@ static int dss_check_settings_low(struct omap_overlay_manager *mgr,
|
||||
ois[ovl->id] = oi;
|
||||
}
|
||||
|
||||
return dss_mgr_check(mgr, dssdev, mi, ois);
|
||||
return dss_mgr_check(mgr, mi, &mp->timings, ois);
|
||||
}
|
||||
|
||||
/*
|
||||
* check manager and overlay settings using overlay_info from data->info
|
||||
*/
|
||||
static int dss_check_settings(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev)
|
||||
static int dss_check_settings(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
return dss_check_settings_low(mgr, dssdev, false);
|
||||
return dss_check_settings_low(mgr, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* check manager and overlay settings using overlay_info from ovl->info if
|
||||
* dirty and from data->info otherwise
|
||||
*/
|
||||
static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev)
|
||||
static int dss_check_settings_apply(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
return dss_check_settings_low(mgr, dssdev, true);
|
||||
return dss_check_settings_low(mgr, true);
|
||||
}
|
||||
|
||||
static bool need_isr(void)
|
||||
@ -261,6 +267,20 @@ static bool need_isr(void)
|
||||
if (mp->shadow_info_dirty)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* NOTE: we don't check extra_info flags for disabled
|
||||
* managers, once the manager is enabled, the extra_info
|
||||
* related manager changes will be taken in by HW.
|
||||
*/
|
||||
|
||||
/* to write new values to registers */
|
||||
if (mp->extra_info_dirty)
|
||||
return true;
|
||||
|
||||
/* to set GO bit */
|
||||
if (mp->shadow_extra_info_dirty)
|
||||
return true;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list) {
|
||||
struct ovl_priv_data *op;
|
||||
|
||||
@ -305,7 +325,7 @@ static bool need_go(struct omap_overlay_manager *mgr)
|
||||
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (mp->shadow_info_dirty)
|
||||
if (mp->shadow_info_dirty || mp->shadow_extra_info_dirty)
|
||||
return true;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list) {
|
||||
@ -320,20 +340,16 @@ static bool need_go(struct omap_overlay_manager *mgr)
|
||||
/* returns true if an extra_info field is currently being updated */
|
||||
static bool extra_info_update_ongoing(void)
|
||||
{
|
||||
const int num_ovls = omap_dss_get_num_overlays();
|
||||
struct ovl_priv_data *op;
|
||||
struct omap_overlay *ovl;
|
||||
struct mgr_priv_data *mp;
|
||||
const int num_mgrs = dss_feat_get_num_mgrs();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_ovls; ++i) {
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
op = get_ovl_priv(ovl);
|
||||
for (i = 0; i < num_mgrs; ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
struct omap_overlay *ovl;
|
||||
struct mgr_priv_data *mp;
|
||||
|
||||
if (!ovl->manager)
|
||||
continue;
|
||||
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mp = get_mgr_priv(mgr);
|
||||
|
||||
if (!mp->enabled)
|
||||
continue;
|
||||
@ -341,8 +357,15 @@ static bool extra_info_update_ongoing(void)
|
||||
if (!mp->updating)
|
||||
continue;
|
||||
|
||||
if (op->extra_info_dirty || op->shadow_extra_info_dirty)
|
||||
if (mp->extra_info_dirty || mp->shadow_extra_info_dirty)
|
||||
return true;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list) {
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
|
||||
if (op->extra_info_dirty || op->shadow_extra_info_dirty)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -525,11 +548,13 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
|
||||
|
||||
oi = &op->info;
|
||||
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
|
||||
replication = dss_use_replication(ovl->manager->device, oi->color_mode);
|
||||
|
||||
ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;
|
||||
|
||||
r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
|
||||
r = dispc_ovl_setup(ovl->id, oi, ilace, replication, &mp->timings);
|
||||
if (r) {
|
||||
/*
|
||||
* We can't do much here, as this function can be called from
|
||||
@ -543,8 +568,6 @@ static void dss_ovl_write_regs(struct omap_overlay *ovl)
|
||||
return;
|
||||
}
|
||||
|
||||
mp = get_mgr_priv(ovl->manager);
|
||||
|
||||
op->info_dirty = false;
|
||||
if (mp->updating)
|
||||
op->shadow_info_dirty = true;
|
||||
@ -601,6 +624,22 @@ static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
|
||||
}
|
||||
}
|
||||
|
||||
static void dss_mgr_write_regs_extra(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
DSSDBGF("%d", mgr->id);
|
||||
|
||||
if (!mp->extra_info_dirty)
|
||||
return;
|
||||
|
||||
dispc_mgr_set_timings(mgr->id, &mp->timings);
|
||||
|
||||
mp->extra_info_dirty = false;
|
||||
if (mp->updating)
|
||||
mp->shadow_extra_info_dirty = true;
|
||||
}
|
||||
|
||||
static void dss_write_regs_common(void)
|
||||
{
|
||||
const int num_mgrs = omap_dss_get_num_overlay_managers();
|
||||
@ -646,7 +685,7 @@ static void dss_write_regs(void)
|
||||
if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
|
||||
continue;
|
||||
|
||||
r = dss_check_settings(mgr, mgr->device);
|
||||
r = dss_check_settings(mgr);
|
||||
if (r) {
|
||||
DSSERR("cannot write registers for manager %s: "
|
||||
"illegal configuration\n", mgr->name);
|
||||
@ -654,6 +693,7 @@ static void dss_write_regs(void)
|
||||
}
|
||||
|
||||
dss_mgr_write_regs(mgr);
|
||||
dss_mgr_write_regs_extra(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,6 +733,7 @@ static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
|
||||
|
||||
mp = get_mgr_priv(mgr);
|
||||
mp->shadow_info_dirty = false;
|
||||
mp->shadow_extra_info_dirty = false;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list) {
|
||||
op = get_ovl_priv(ovl);
|
||||
@ -711,7 +752,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
||||
|
||||
WARN_ON(mp->updating);
|
||||
|
||||
r = dss_check_settings(mgr, mgr->device);
|
||||
r = dss_check_settings(mgr);
|
||||
if (r) {
|
||||
DSSERR("cannot start manual update: illegal configuration\n");
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
@ -719,6 +760,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
|
||||
}
|
||||
|
||||
dss_mgr_write_regs(mgr);
|
||||
dss_mgr_write_regs_extra(mgr);
|
||||
|
||||
dss_write_regs_common();
|
||||
|
||||
@ -857,7 +899,7 @@ int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
r = dss_check_settings_apply(mgr, mgr->device);
|
||||
r = dss_check_settings_apply(mgr);
|
||||
if (r) {
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
DSSERR("failed to apply settings: illegal configuration.\n");
|
||||
@ -918,16 +960,13 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl,
|
||||
bool use_fifo_merge)
|
||||
{
|
||||
struct ovl_priv_data *op = get_ovl_priv(ovl);
|
||||
struct omap_dss_device *dssdev;
|
||||
u32 fifo_low, fifo_high;
|
||||
|
||||
if (!op->enabled && !op->enabling)
|
||||
return;
|
||||
|
||||
dssdev = ovl->manager->device;
|
||||
|
||||
dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high,
|
||||
use_fifo_merge);
|
||||
use_fifo_merge, ovl_manual_update(ovl));
|
||||
|
||||
dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
|
||||
}
|
||||
@ -1050,7 +1089,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
||||
|
||||
mp->enabled = true;
|
||||
|
||||
r = dss_check_settings(mgr, mgr->device);
|
||||
r = dss_check_settings(mgr);
|
||||
if (r) {
|
||||
DSSERR("failed to enable manager %d: check_settings failed\n",
|
||||
mgr->id);
|
||||
@ -1225,6 +1264,35 @@ err:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_apply_mgr_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
struct mgr_priv_data *mp = get_mgr_priv(mgr);
|
||||
|
||||
mp->timings = *timings;
|
||||
mp->extra_info_dirty = true;
|
||||
}
|
||||
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&apply_lock);
|
||||
|
||||
spin_lock_irqsave(&data_lock, flags);
|
||||
|
||||
dss_apply_mgr_timings(mgr, timings);
|
||||
|
||||
dss_write_regs();
|
||||
dss_set_go_bits();
|
||||
|
||||
spin_unlock_irqrestore(&data_lock, flags);
|
||||
|
||||
wait_pending_extra_info_updates();
|
||||
|
||||
mutex_unlock(&apply_lock);
|
||||
}
|
||||
|
||||
int dss_ovl_set_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info)
|
||||
@ -1393,7 +1461,7 @@ int dss_ovl_enable(struct omap_overlay *ovl)
|
||||
|
||||
op->enabling = true;
|
||||
|
||||
r = dss_check_settings(ovl->manager, ovl->manager->device);
|
||||
r = dss_check_settings(ovl->manager);
|
||||
if (r) {
|
||||
DSSERR("failed to enable overlay %d: check_settings failed\n",
|
||||
ovl->id);
|
||||
|
@ -43,6 +43,8 @@ static struct {
|
||||
|
||||
struct regulator *vdds_dsi_reg;
|
||||
struct regulator *vdds_sdi_reg;
|
||||
|
||||
const char *default_display_name;
|
||||
} core;
|
||||
|
||||
static char *def_disp_name;
|
||||
@ -54,9 +56,6 @@ bool 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)
|
||||
@ -87,6 +86,51 @@ struct regulator *dss_get_vdds_sdi(void)
|
||||
return reg;
|
||||
}
|
||||
|
||||
int dss_get_ctx_loss_count(struct device *dev)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
|
||||
int cnt;
|
||||
|
||||
if (!board_data->get_context_loss_count)
|
||||
return -ENOENT;
|
||||
|
||||
cnt = board_data->get_context_loss_count(dev);
|
||||
|
||||
WARN_ONCE(cnt < 0, "get_context_loss_count failed: %d\n", cnt);
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
|
||||
|
||||
if (!board_data->dsi_enable_pads)
|
||||
return -ENOENT;
|
||||
|
||||
return board_data->dsi_enable_pads(dsi_id, lane_mask);
|
||||
}
|
||||
|
||||
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
struct omap_dss_board_info *board_data = core.pdev->dev.platform_data;
|
||||
|
||||
if (!board_data->dsi_enable_pads)
|
||||
return;
|
||||
|
||||
return board_data->dsi_disable_pads(dsi_id, lane_mask);
|
||||
}
|
||||
|
||||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
|
||||
if (pdata->set_min_bus_tput)
|
||||
return pdata->set_min_bus_tput(dev, tput);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
static int dss_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
@ -121,34 +165,6 @@ static int dss_initialize_debugfs(void)
|
||||
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_debug_dump_clocks, &dss_debug_fops);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
|
||||
&dispc_dump_irqs, &dss_debug_fops);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
|
||||
dsi_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops);
|
||||
#endif
|
||||
|
||||
debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_dump_regs, &dss_debug_fops);
|
||||
debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
|
||||
&dispc_dump_regs, &dss_debug_fops);
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
|
||||
&rfbi_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
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,
|
||||
&venc_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI
|
||||
debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
|
||||
&hdmi_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -157,6 +173,19 @@ static void dss_uninitialize_debugfs(void)
|
||||
if (dss_debugfs_dir)
|
||||
debugfs_remove_recursive(dss_debugfs_dir);
|
||||
}
|
||||
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
|
||||
write, &dss_debug_fops);
|
||||
|
||||
if (IS_ERR(d))
|
||||
return PTR_ERR(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
|
||||
static inline int dss_initialize_debugfs(void)
|
||||
{
|
||||
@ -165,14 +194,18 @@ static inline int dss_initialize_debugfs(void)
|
||||
static inline void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
}
|
||||
static inline int dss_debugfs_create_file(const char *name,
|
||||
void (*write)(struct seq_file *))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
|
||||
|
||||
/* PLATFORM DEVICE */
|
||||
static int omap_dss_probe(struct platform_device *pdev)
|
||||
static int __init omap_dss_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
core.pdev = pdev;
|
||||
|
||||
@ -187,28 +220,13 @@ static int omap_dss_probe(struct platform_device *pdev)
|
||||
if (r)
|
||||
goto err_debugfs;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
r = omap_dss_register_device(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %d %s register failed %d\n", i,
|
||||
dssdev->name ?: "unnamed", r);
|
||||
|
||||
while (--i >= 0)
|
||||
omap_dss_unregister_device(pdata->devices[i]);
|
||||
|
||||
goto err_register;
|
||||
}
|
||||
|
||||
if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
|
||||
pdata->default_device = dssdev;
|
||||
}
|
||||
if (def_disp_name)
|
||||
core.default_display_name = def_disp_name;
|
||||
else if (pdata->default_device)
|
||||
core.default_display_name = pdata->default_device->name;
|
||||
|
||||
return 0;
|
||||
|
||||
err_register:
|
||||
dss_uninitialize_debugfs();
|
||||
err_debugfs:
|
||||
|
||||
return r;
|
||||
@ -216,17 +234,11 @@ err_debugfs:
|
||||
|
||||
static int omap_dss_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i;
|
||||
|
||||
dss_uninitialize_debugfs();
|
||||
|
||||
dss_uninit_overlays(pdev);
|
||||
dss_uninit_overlay_managers(pdev);
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i)
|
||||
omap_dss_unregister_device(pdata->devices[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -251,7 +263,6 @@ static int omap_dss_resume(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static struct platform_driver omap_dss_driver = {
|
||||
.probe = omap_dss_probe,
|
||||
.remove = omap_dss_remove,
|
||||
.shutdown = omap_dss_shutdown,
|
||||
.suspend = omap_dss_suspend,
|
||||
@ -326,7 +337,6 @@ static int dss_driver_probe(struct device *dev)
|
||||
int r;
|
||||
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
bool force;
|
||||
|
||||
DSSDBG("driver_probe: dev %s/%s, drv %s\n",
|
||||
@ -335,7 +345,8 @@ static int dss_driver_probe(struct device *dev)
|
||||
|
||||
dss_init_device(core.pdev, dssdev);
|
||||
|
||||
force = pdata->default_device == dssdev;
|
||||
force = core.default_display_name &&
|
||||
strcmp(core.default_display_name, dssdev->name) == 0;
|
||||
dss_recheck_connections(dssdev, force);
|
||||
|
||||
r = dssdrv->probe(dssdev);
|
||||
@ -381,6 +392,8 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
|
||||
if (dssdriver->get_recommended_bpp == NULL)
|
||||
dssdriver->get_recommended_bpp =
|
||||
omapdss_default_get_recommended_bpp;
|
||||
if (dssdriver->get_timings == NULL)
|
||||
dssdriver->get_timings = omapdss_default_get_timings;
|
||||
|
||||
return driver_register(&dssdriver->driver);
|
||||
}
|
||||
@ -427,27 +440,38 @@ static void omap_dss_dev_release(struct device *dev)
|
||||
reset_device(dev, 0);
|
||||
}
|
||||
|
||||
static int omap_dss_register_device(struct omap_dss_device *dssdev)
|
||||
int omap_dss_register_device(struct omap_dss_device *dssdev,
|
||||
struct device *parent, int disp_num)
|
||||
{
|
||||
static int dev_num;
|
||||
|
||||
WARN_ON(!dssdev->driver_name);
|
||||
|
||||
reset_device(&dssdev->dev, 1);
|
||||
dssdev->dev.bus = &dss_bus_type;
|
||||
dssdev->dev.parent = &dss_bus;
|
||||
dssdev->dev.parent = parent;
|
||||
dssdev->dev.release = omap_dss_dev_release;
|
||||
dev_set_name(&dssdev->dev, "display%d", dev_num++);
|
||||
dev_set_name(&dssdev->dev, "display%d", disp_num);
|
||||
return device_register(&dssdev->dev);
|
||||
}
|
||||
|
||||
static void omap_dss_unregister_device(struct omap_dss_device *dssdev)
|
||||
void omap_dss_unregister_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_unregister(&dssdev->dev);
|
||||
}
|
||||
|
||||
static int dss_unregister_dss_dev(struct device *dev, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
omap_dss_unregister_device(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void omap_dss_unregister_child_devices(struct device *parent)
|
||||
{
|
||||
device_for_each_child(parent, NULL, dss_unregister_dss_dev);
|
||||
}
|
||||
|
||||
/* BUS */
|
||||
static int omap_dss_bus_register(void)
|
||||
static int __init omap_dss_bus_register(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -469,12 +493,56 @@ static int omap_dss_bus_register(void)
|
||||
}
|
||||
|
||||
/* INIT */
|
||||
static int (*dss_output_drv_reg_funcs[])(void) __initdata = {
|
||||
#ifdef CONFIG_OMAP2_DSS_DPI
|
||||
dpi_init_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
sdi_init_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
rfbi_init_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
venc_init_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_init_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI
|
||||
hdmi_init_platform_driver,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void (*dss_output_drv_unreg_funcs[])(void) __exitdata = {
|
||||
#ifdef CONFIG_OMAP2_DSS_DPI
|
||||
dpi_uninit_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
sdi_uninit_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
rfbi_uninit_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
venc_uninit_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_uninit_platform_driver,
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI
|
||||
hdmi_uninit_platform_driver,
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool dss_output_drv_loaded[ARRAY_SIZE(dss_output_drv_reg_funcs)];
|
||||
|
||||
static int __init omap_dss_register_drivers(void)
|
||||
{
|
||||
int r;
|
||||
int i;
|
||||
|
||||
r = platform_driver_register(&omap_dss_driver);
|
||||
r = platform_driver_probe(&omap_dss_driver, omap_dss_probe);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -490,40 +558,18 @@ static int __init omap_dss_register_drivers(void)
|
||||
goto err_dispc;
|
||||
}
|
||||
|
||||
r = rfbi_init_platform_driver();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize rfbi platform driver\n");
|
||||
goto err_rfbi;
|
||||
}
|
||||
|
||||
r = venc_init_platform_driver();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize venc platform driver\n");
|
||||
goto err_venc;
|
||||
}
|
||||
|
||||
r = dsi_init_platform_driver();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize DSI platform driver\n");
|
||||
goto err_dsi;
|
||||
}
|
||||
|
||||
r = hdmi_init_platform_driver();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize hdmi\n");
|
||||
goto err_hdmi;
|
||||
/*
|
||||
* It's ok if the output-driver register fails. It happens, for example,
|
||||
* when there is no output-device (e.g. SDI for OMAP4).
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(dss_output_drv_reg_funcs); ++i) {
|
||||
r = dss_output_drv_reg_funcs[i]();
|
||||
if (r == 0)
|
||||
dss_output_drv_loaded[i] = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_hdmi:
|
||||
dsi_uninit_platform_driver();
|
||||
err_dsi:
|
||||
venc_uninit_platform_driver();
|
||||
err_venc:
|
||||
rfbi_uninit_platform_driver();
|
||||
err_rfbi:
|
||||
dispc_uninit_platform_driver();
|
||||
err_dispc:
|
||||
dss_uninit_platform_driver();
|
||||
err_dss:
|
||||
@ -534,10 +580,13 @@ err_dss:
|
||||
|
||||
static void __exit omap_dss_unregister_drivers(void)
|
||||
{
|
||||
hdmi_uninit_platform_driver();
|
||||
dsi_uninit_platform_driver();
|
||||
venc_uninit_platform_driver();
|
||||
rfbi_uninit_platform_driver();
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dss_output_drv_unreg_funcs); ++i) {
|
||||
if (dss_output_drv_loaded[i])
|
||||
dss_output_drv_unreg_funcs[i]();
|
||||
}
|
||||
|
||||
dispc_uninit_platform_driver();
|
||||
dss_uninit_platform_driver();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -120,6 +120,7 @@ static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
|
||||
return 0x03AC;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,6 +135,7 @@ static inline u16 DISPC_TRANS_COLOR(enum omap_channel channel)
|
||||
return 0x03B0;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,10 +146,12 @@ static inline u16 DISPC_TIMING_H(enum omap_channel channel)
|
||||
return 0x0064;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x0400;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,10 +162,12 @@ static inline u16 DISPC_TIMING_V(enum omap_channel channel)
|
||||
return 0x0068;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x0404;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,10 +178,12 @@ static inline u16 DISPC_POL_FREQ(enum omap_channel channel)
|
||||
return 0x006C;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x0408;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -186,10 +194,12 @@ static inline u16 DISPC_DIVISORo(enum omap_channel channel)
|
||||
return 0x0070;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x040C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,6 +215,7 @@ static inline u16 DISPC_SIZE_MGR(enum omap_channel channel)
|
||||
return 0x03CC;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,10 +226,12 @@ static inline u16 DISPC_DATA_CYCLE1(enum omap_channel channel)
|
||||
return 0x01D4;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03C0;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,10 +242,12 @@ static inline u16 DISPC_DATA_CYCLE2(enum omap_channel channel)
|
||||
return 0x01D8;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03C4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -243,10 +258,12 @@ static inline u16 DISPC_DATA_CYCLE3(enum omap_channel channel)
|
||||
return 0x01DC;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03C8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,10 +274,12 @@ static inline u16 DISPC_CPR_COEF_R(enum omap_channel channel)
|
||||
return 0x0220;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03BC;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,10 +290,12 @@ static inline u16 DISPC_CPR_COEF_G(enum omap_channel channel)
|
||||
return 0x0224;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03B8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,10 +306,12 @@ static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel)
|
||||
return 0x0228;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return 0x03B4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,6 +329,7 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane)
|
||||
return 0x0300;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -321,6 +345,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane)
|
||||
return 0x0008;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,6 +360,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane)
|
||||
return 0x000C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -343,6 +369,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0544;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -351,6 +378,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane)
|
||||
return 0x0310;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,6 +387,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0548;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -367,6 +396,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane)
|
||||
return 0x0314;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,6 +411,7 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane)
|
||||
return 0x009C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,6 +426,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane)
|
||||
return 0x00A8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,6 +442,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane)
|
||||
return 0x0070;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,6 +451,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0568;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -426,6 +460,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane)
|
||||
return 0x032C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -441,6 +476,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane)
|
||||
return 0x008C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,6 +492,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane)
|
||||
return 0x0088;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,6 +508,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane)
|
||||
return 0x00A4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,6 +524,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane)
|
||||
return 0x0098;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,8 +537,10 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane)
|
||||
case OMAP_DSS_VIDEO2:
|
||||
case OMAP_DSS_VIDEO3:
|
||||
BUG();
|
||||
return 0;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -512,8 +553,10 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane)
|
||||
case OMAP_DSS_VIDEO2:
|
||||
case OMAP_DSS_VIDEO3:
|
||||
BUG();
|
||||
return 0;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,6 +565,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0024;
|
||||
@ -529,6 +573,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane)
|
||||
return 0x0090;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,6 +582,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0580;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -545,6 +591,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane)
|
||||
return 0x0424;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,6 +600,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0028;
|
||||
@ -560,6 +608,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane)
|
||||
return 0x0094;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -569,6 +618,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x002C;
|
||||
@ -576,6 +626,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane)
|
||||
return 0x0000;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -584,6 +635,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0584;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -592,6 +644,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane)
|
||||
return 0x0428;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -600,6 +653,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0030;
|
||||
@ -607,6 +661,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane)
|
||||
return 0x0004;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,6 +670,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0588;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -623,6 +679,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane)
|
||||
return 0x042C;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,6 +689,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0034 + i * 0x8;
|
||||
@ -639,6 +697,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0010 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -648,6 +707,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x058C + i * 0x8;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -656,6 +716,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0430 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -665,6 +726,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
return 0x0038 + i * 0x8;
|
||||
@ -672,6 +734,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0014 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -681,6 +744,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0590 + i * 8;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -689,6 +753,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0434 + i * 0x8;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,12 +763,14 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
case OMAP_DSS_VIDEO3:
|
||||
return 0x0074 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -713,6 +780,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x0124 + i * 0x4;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -721,6 +789,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0050 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -730,6 +799,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
BUG();
|
||||
return 0;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
return 0x05CC + i * 0x4;
|
||||
case OMAP_DSS_VIDEO2:
|
||||
@ -738,6 +808,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i)
|
||||
return 0x0470 + i * 0x4;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -754,6 +825,7 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane)
|
||||
return 0x00A0;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -304,10 +304,18 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
|
||||
return 24;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
|
||||
|
||||
void omapdss_default_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_timings);
|
||||
|
||||
/* Checks if replication logic should be used. Only use for active matrix,
|
||||
* when overlay is in RGB12U or RGB16 mode, and LCD interface is
|
||||
* 18bpp or 24bpp */
|
||||
@ -340,6 +348,7 @@ bool dss_use_replication(struct omap_dss_device *dssdev,
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return false;
|
||||
}
|
||||
|
||||
return bpp > 16;
|
||||
@ -352,46 +361,6 @@ void dss_init_device(struct platform_device *pdev,
|
||||
int i;
|
||||
int r;
|
||||
|
||||
switch (dssdev->type) {
|
||||
#ifdef CONFIG_OMAP2_DSS_DPI
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
r = dpi_init_display(dssdev);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
case OMAP_DISPLAY_TYPE_DBI:
|
||||
r = rfbi_init_display(dssdev);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
case OMAP_DISPLAY_TYPE_VENC:
|
||||
r = venc_init_display(dssdev);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
case OMAP_DISPLAY_TYPE_SDI:
|
||||
r = sdi_init_display(dssdev);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
case OMAP_DISPLAY_TYPE_DSI:
|
||||
r = dsi_init_display(dssdev);
|
||||
break;
|
||||
#endif
|
||||
case OMAP_DISPLAY_TYPE_HDMI:
|
||||
r = hdmi_init_display(dssdev);
|
||||
break;
|
||||
default:
|
||||
DSSERR("Support for display '%s' not compiled in.\n",
|
||||
dssdev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r) {
|
||||
DSSERR("failed to init display %s\n", dssdev->name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* create device sysfs files */
|
||||
i = 0;
|
||||
while ((attr = display_sysfs_attrs[i++]) != NULL) {
|
||||
|
@ -156,7 +156,7 @@ static int dpi_set_mode(struct omap_dss_device *dssdev)
|
||||
t->pixel_clock = pck;
|
||||
}
|
||||
|
||||
dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
|
||||
dss_mgr_set_timings(dssdev->manager, t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -202,10 +202,6 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
goto err_reg_enable;
|
||||
}
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dispc;
|
||||
@ -244,8 +240,6 @@ err_dsi_pll_init:
|
||||
err_get_dsi:
|
||||
dispc_runtime_put();
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
if (cpu_is_omap34xx())
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
err_reg_enable:
|
||||
@ -266,7 +260,6 @@ void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
}
|
||||
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
if (cpu_is_omap34xx())
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
@ -283,21 +276,15 @@ void dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
DSSDBG("dpi_set_timings\n");
|
||||
dssdev->panel.timings = *timings;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = dss_runtime_get();
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
return;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r) {
|
||||
dss_runtime_put();
|
||||
return;
|
||||
}
|
||||
|
||||
dpi_set_mode(dssdev);
|
||||
dispc_mgr_go(dssdev->manager->id);
|
||||
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dpi_set_timings);
|
||||
@ -312,7 +299,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
unsigned long pck;
|
||||
struct dispc_clock_info dispc_cinfo;
|
||||
|
||||
if (!dispc_lcd_timings_ok(timings))
|
||||
if (dss_mgr_check_timings(dssdev->manager, timings))
|
||||
return -EINVAL;
|
||||
|
||||
if (timings->pixel_clock == 0)
|
||||
@ -352,7 +339,7 @@ int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
}
|
||||
EXPORT_SYMBOL(dpi_check_timings);
|
||||
|
||||
int dpi_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init dpi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
@ -378,12 +365,58 @@ int dpi_init_display(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpi_init(void)
|
||||
static void __init dpi_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_DPI)
|
||||
continue;
|
||||
|
||||
r = dpi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init omap_dpi_probe(struct platform_device *pdev)
|
||||
{
|
||||
dpi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dpi_exit(void)
|
||||
static int __exit omap_dpi_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver omap_dpi_driver = {
|
||||
.remove = __exit_p(omap_dpi_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_dpi",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int __init dpi_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe);
|
||||
}
|
||||
|
||||
void __exit dpi_uninit_platform_driver(void)
|
||||
{
|
||||
platform_driver_unregister(&omap_dpi_driver);
|
||||
}
|
||||
|
@ -256,14 +256,13 @@ struct dsi_data {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
|
||||
int module_id;
|
||||
|
||||
int irq;
|
||||
|
||||
struct clk *dss_clk;
|
||||
struct clk *sys_clk;
|
||||
|
||||
int (*enable_pads)(int dsi_id, unsigned lane_mask);
|
||||
void (*disable_pads)(int dsi_id, unsigned lane_mask);
|
||||
|
||||
struct dsi_clock_info current_cinfo;
|
||||
|
||||
bool vdds_dsi_enabled;
|
||||
@ -361,11 +360,6 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
|
||||
return dsi_pdev_map[module];
|
||||
}
|
||||
|
||||
static inline int dsi_get_dsidev_id(struct platform_device *dsidev)
|
||||
{
|
||||
return dsidev->id;
|
||||
}
|
||||
|
||||
static inline void dsi_write_reg(struct platform_device *dsidev,
|
||||
const struct dsi_reg idx, u32 val)
|
||||
{
|
||||
@ -452,6 +446,7 @@ u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
|
||||
return 16;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1184,10 +1179,9 @@ static unsigned long dsi_get_txbyteclkhs(struct platform_device *dsidev)
|
||||
static unsigned long dsi_fclk_rate(struct platform_device *dsidev)
|
||||
{
|
||||
unsigned long r;
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
|
||||
if (dss_get_dsi_clk_source(dsi_module) == OMAP_DSS_CLK_SRC_FCK) {
|
||||
if (dss_get_dsi_clk_source(dsi->module_id) == OMAP_DSS_CLK_SRC_FCK) {
|
||||
/* DSI FCLK source is DSS_CLK_FCK */
|
||||
r = clk_get_rate(dsi->dss_clk);
|
||||
} else {
|
||||
@ -1279,10 +1273,9 @@ static int dsi_pll_power(struct platform_device *dsidev,
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
||||
static int dsi_calc_clock_rates(struct platform_device *dsidev,
|
||||
struct dsi_clock_info *cinfo)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
|
||||
if (cinfo->regn == 0 || cinfo->regn > dsi->regn_max)
|
||||
@ -1297,21 +1290,8 @@ static int dsi_calc_clock_rates(struct omap_dss_device *dssdev,
|
||||
if (cinfo->regm_dsi > dsi->regm_dsi_max)
|
||||
return -EINVAL;
|
||||
|
||||
if (cinfo->use_sys_clk) {
|
||||
cinfo->clkin = clk_get_rate(dsi->sys_clk);
|
||||
/* XXX it is unclear if highfreq should be used
|
||||
* with DSS_SYS_CLK source also */
|
||||
cinfo->highfreq = 0;
|
||||
} else {
|
||||
cinfo->clkin = dispc_mgr_pclk_rate(dssdev->manager->id);
|
||||
|
||||
if (cinfo->clkin < 32000000)
|
||||
cinfo->highfreq = 0;
|
||||
else
|
||||
cinfo->highfreq = 1;
|
||||
}
|
||||
|
||||
cinfo->fint = cinfo->clkin / (cinfo->regn * (cinfo->highfreq ? 2 : 1));
|
||||
cinfo->clkin = clk_get_rate(dsi->sys_clk);
|
||||
cinfo->fint = cinfo->clkin / cinfo->regn;
|
||||
|
||||
if (cinfo->fint > dsi->fint_max || cinfo->fint < dsi->fint_min)
|
||||
return -EINVAL;
|
||||
@ -1378,27 +1358,21 @@ retry:
|
||||
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
cur.clkin = dss_sys_clk;
|
||||
cur.use_sys_clk = 1;
|
||||
cur.highfreq = 0;
|
||||
|
||||
/* no highfreq: 0.75MHz < Fint = clkin / regn < 2.1MHz */
|
||||
/* highfreq: 0.75MHz < Fint = clkin / (2*regn) < 2.1MHz */
|
||||
/* 0.75MHz < Fint = clkin / regn < 2.1MHz */
|
||||
/* To reduce PLL lock time, keep Fint high (around 2 MHz) */
|
||||
for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) {
|
||||
if (cur.highfreq == 0)
|
||||
cur.fint = cur.clkin / cur.regn;
|
||||
else
|
||||
cur.fint = cur.clkin / (2 * cur.regn);
|
||||
cur.fint = cur.clkin / cur.regn;
|
||||
|
||||
if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min)
|
||||
continue;
|
||||
|
||||
/* DSIPHY(MHz) = (2 * regm / regn) * (clkin / (highfreq + 1)) */
|
||||
/* DSIPHY(MHz) = (2 * regm / regn) * clkin */
|
||||
for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) {
|
||||
unsigned long a, b;
|
||||
|
||||
a = 2 * cur.regm * (cur.clkin/1000);
|
||||
b = cur.regn * (cur.highfreq + 1);
|
||||
b = cur.regn;
|
||||
cur.clkin4ddr = a / b * 1000;
|
||||
|
||||
if (cur.clkin4ddr > 1800 * 1000 * 1000)
|
||||
@ -1486,9 +1460,7 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
|
||||
DSSDBGF();
|
||||
|
||||
dsi->current_cinfo.use_sys_clk = cinfo->use_sys_clk;
|
||||
dsi->current_cinfo.highfreq = cinfo->highfreq;
|
||||
|
||||
dsi->current_cinfo.clkin = cinfo->clkin;
|
||||
dsi->current_cinfo.fint = cinfo->fint;
|
||||
dsi->current_cinfo.clkin4ddr = cinfo->clkin4ddr;
|
||||
dsi->current_cinfo.dsi_pll_hsdiv_dispc_clk =
|
||||
@ -1503,17 +1475,13 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
|
||||
DSSDBG("DSI Fint %ld\n", cinfo->fint);
|
||||
|
||||
DSSDBG("clkin (%s) rate %ld, highfreq %d\n",
|
||||
cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree",
|
||||
cinfo->clkin,
|
||||
cinfo->highfreq);
|
||||
DSSDBG("clkin rate %ld\n", cinfo->clkin);
|
||||
|
||||
/* DSIPHY == CLKIN4DDR */
|
||||
DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu / %d = %lu\n",
|
||||
DSSDBG("CLKIN4DDR = 2 * %d / %d * %lu = %lu\n",
|
||||
cinfo->regm,
|
||||
cinfo->regn,
|
||||
cinfo->clkin,
|
||||
cinfo->highfreq + 1,
|
||||
cinfo->clkin4ddr);
|
||||
|
||||
DSSDBG("Data rate on 1 DSI lane %ld Mbps\n",
|
||||
@ -1568,10 +1536,6 @@ int dsi_pll_set_clock_div(struct platform_device *dsidev,
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_PLL_FREQSEL))
|
||||
l = FLD_MOD(l, f, 4, 1); /* DSI_PLL_FREQSEL */
|
||||
l = FLD_MOD(l, cinfo->use_sys_clk ? 0 : 1,
|
||||
11, 11); /* DSI_PLL_CLKSEL */
|
||||
l = FLD_MOD(l, cinfo->highfreq,
|
||||
12, 12); /* DSI_PLL_HIGHFREQ */
|
||||
l = FLD_MOD(l, 1, 13, 13); /* DSI_PLL_REFEN */
|
||||
l = FLD_MOD(l, 0, 14, 14); /* DSIPHY_CLKINEN */
|
||||
l = FLD_MOD(l, 1, 20, 20); /* DSI_HSDIVBYPASS */
|
||||
@ -1716,7 +1680,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct dsi_clock_info *cinfo = &dsi->current_cinfo;
|
||||
enum omap_dss_clk_source dispc_clk_src, dsi_clk_src;
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
int dsi_module = dsi->module_id;
|
||||
|
||||
dispc_clk_src = dss_get_dispc_clk_source();
|
||||
dsi_clk_src = dss_get_dsi_clk_source(dsi_module);
|
||||
@ -1726,8 +1690,7 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
|
||||
|
||||
seq_printf(s, "- DSI%d PLL -\n", dsi_module + 1);
|
||||
|
||||
seq_printf(s, "dsi pll source = %s\n",
|
||||
cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
|
||||
seq_printf(s, "dsi pll clkin\t%lu\n", cinfo->clkin);
|
||||
|
||||
seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
|
||||
|
||||
@ -1789,7 +1752,6 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
unsigned long flags;
|
||||
struct dsi_irq_stats stats;
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
|
||||
spin_lock_irqsave(&dsi->irq_stats_lock, flags);
|
||||
|
||||
@ -1806,7 +1768,7 @@ static void dsi_dump_dsidev_irqs(struct platform_device *dsidev,
|
||||
#define PIS(x) \
|
||||
seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
|
||||
|
||||
seq_printf(s, "-- DSI%d interrupts --\n", dsi_module + 1);
|
||||
seq_printf(s, "-- DSI%d interrupts --\n", dsi->module_id + 1);
|
||||
PIS(VC0);
|
||||
PIS(VC1);
|
||||
PIS(VC2);
|
||||
@ -1886,22 +1848,6 @@ static void dsi2_dump_irqs(struct seq_file *s)
|
||||
|
||||
dsi_dump_dsidev_irqs(dsidev, s);
|
||||
}
|
||||
|
||||
void dsi_create_debugfs_files_irq(struct dentry *debugfs_dir,
|
||||
const struct file_operations *debug_fops)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
|
||||
dsidev = dsi_get_dsidev_from_id(0);
|
||||
if (dsidev)
|
||||
debugfs_create_file("dsi1_irqs", S_IRUGO, debugfs_dir,
|
||||
&dsi1_dump_irqs, debug_fops);
|
||||
|
||||
dsidev = dsi_get_dsidev_from_id(1);
|
||||
if (dsidev)
|
||||
debugfs_create_file("dsi2_irqs", S_IRUGO, debugfs_dir,
|
||||
&dsi2_dump_irqs, debug_fops);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dsi_dump_dsidev_regs(struct platform_device *dsidev,
|
||||
@ -2002,21 +1948,6 @@ static void dsi2_dump_regs(struct seq_file *s)
|
||||
dsi_dump_dsidev_regs(dsidev, s);
|
||||
}
|
||||
|
||||
void dsi_create_debugfs_files_reg(struct dentry *debugfs_dir,
|
||||
const struct file_operations *debug_fops)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
|
||||
dsidev = dsi_get_dsidev_from_id(0);
|
||||
if (dsidev)
|
||||
debugfs_create_file("dsi1_regs", S_IRUGO, debugfs_dir,
|
||||
&dsi1_dump_regs, debug_fops);
|
||||
|
||||
dsidev = dsi_get_dsidev_from_id(1);
|
||||
if (dsidev)
|
||||
debugfs_create_file("dsi2_regs", S_IRUGO, debugfs_dir,
|
||||
&dsi2_dump_regs, debug_fops);
|
||||
}
|
||||
enum dsi_cio_power_state {
|
||||
DSI_COMPLEXIO_POWER_OFF = 0x0,
|
||||
DSI_COMPLEXIO_POWER_ON = 0x1,
|
||||
@ -2073,6 +2004,7 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
|
||||
return 1365 * 3; /* 1365x24 bits */
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2337,7 +2269,7 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
|
||||
|
||||
DSSDBGF();
|
||||
|
||||
r = dsi->enable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
|
||||
r = dss_dsi_enable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
@ -2447,7 +2379,7 @@ err_cio_pwr:
|
||||
dsi_cio_disable_lane_override(dsidev);
|
||||
err_scp_clk_dom:
|
||||
dsi_disable_scp_clk(dsidev);
|
||||
dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
|
||||
dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -2461,7 +2393,7 @@ static void dsi_cio_uninit(struct omap_dss_device *dssdev)
|
||||
|
||||
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_OFF);
|
||||
dsi_disable_scp_clk(dsidev);
|
||||
dsi->disable_pads(dsidev->id, dsi_get_lane_mask(dssdev));
|
||||
dss_dsi_disable_pads(dsi->module_id, dsi_get_lane_mask(dssdev));
|
||||
}
|
||||
|
||||
static void dsi_config_tx_fifo(struct platform_device *dsidev,
|
||||
@ -2485,6 +2417,7 @@ static void dsi_config_tx_fifo(struct platform_device *dsidev,
|
||||
if (add + size > 4) {
|
||||
DSSERR("Illegal FIFO configuration\n");
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
|
||||
@ -2517,6 +2450,7 @@ static void dsi_config_rx_fifo(struct platform_device *dsidev,
|
||||
if (add + size > 4) {
|
||||
DSSERR("Illegal FIFO configuration\n");
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
v = FLD_VAL(add, 2, 0) | FLD_VAL(size, 7, 4);
|
||||
@ -2658,6 +2592,7 @@ static int dsi_sync_vc(struct platform_device *dsidev, int channel)
|
||||
return dsi_sync_vc_l4(dsidev, channel);
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3226,6 +3161,7 @@ static int dsi_vc_generic_send_read_request(struct omap_dss_device *dssdev,
|
||||
data = reqdata[0] | (reqdata[1] << 8);
|
||||
} else {
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = dsi_vc_send_short(dsidev, channel, data_type, data, 0);
|
||||
@ -3340,7 +3276,6 @@ static int dsi_vc_read_rx_fifo(struct platform_device *dsidev, int channel,
|
||||
goto err;
|
||||
}
|
||||
|
||||
BUG();
|
||||
err:
|
||||
DSSERR("dsi_vc_read_rx_fifo(ch %d type %s) failed\n", channel,
|
||||
type == DSS_DSI_CONTENT_GENERIC ? "GENERIC" : "DCS");
|
||||
@ -3735,6 +3670,186 @@ static void dsi_config_blanking_modes(struct omap_dss_device *dssdev)
|
||||
dsi_write_reg(dsidev, DSI_CTRL, r);
|
||||
}
|
||||
|
||||
/*
|
||||
* According to section 'HS Command Mode Interleaving' in OMAP TRM, Scenario 3
|
||||
* results in maximum transition time for data and clock lanes to enter and
|
||||
* exit HS mode. Hence, this is the scenario where the least amount of command
|
||||
* mode data can be interleaved. We program the minimum amount of TXBYTECLKHS
|
||||
* clock cycles that can be used to interleave command mode data in HS so that
|
||||
* all scenarios are satisfied.
|
||||
*/
|
||||
static int dsi_compute_interleave_hs(int blank, bool ddr_alwon, int enter_hs,
|
||||
int exit_hs, int exiths_clk, int ddr_pre, int ddr_post)
|
||||
{
|
||||
int transition;
|
||||
|
||||
/*
|
||||
* If DDR_CLK_ALWAYS_ON is set, we need to consider HS mode transition
|
||||
* time of data lanes only, if it isn't set, we need to consider HS
|
||||
* transition time of both data and clock lanes. HS transition time
|
||||
* of Scenario 3 is considered.
|
||||
*/
|
||||
if (ddr_alwon) {
|
||||
transition = enter_hs + exit_hs + max(enter_hs, 2) + 1;
|
||||
} else {
|
||||
int trans1, trans2;
|
||||
trans1 = ddr_pre + enter_hs + exit_hs + max(enter_hs, 2) + 1;
|
||||
trans2 = ddr_pre + enter_hs + exiths_clk + ddr_post + ddr_pre +
|
||||
enter_hs + 1;
|
||||
transition = max(trans1, trans2);
|
||||
}
|
||||
|
||||
return blank > transition ? blank - transition : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* According to section 'LP Command Mode Interleaving' in OMAP TRM, Scenario 1
|
||||
* results in maximum transition time for data lanes to enter and exit LP mode.
|
||||
* Hence, this is the scenario where the least amount of command mode data can
|
||||
* be interleaved. We program the minimum amount of bytes that can be
|
||||
* interleaved in LP so that all scenarios are satisfied.
|
||||
*/
|
||||
static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs,
|
||||
int lp_clk_div, int tdsi_fclk)
|
||||
{
|
||||
int trans_lp; /* time required for a LP transition, in TXBYTECLKHS */
|
||||
int tlp_avail; /* time left for interleaving commands, in CLKIN4DDR */
|
||||
int ttxclkesc; /* period of LP transmit escape clock, in CLKIN4DDR */
|
||||
int thsbyte_clk = 16; /* Period of TXBYTECLKHS clock, in CLKIN4DDR */
|
||||
int lp_inter; /* cmd mode data that can be interleaved, in bytes */
|
||||
|
||||
/* maximum LP transition time according to Scenario 1 */
|
||||
trans_lp = exit_hs + max(enter_hs, 2) + 1;
|
||||
|
||||
/* CLKIN4DDR = 16 * TXBYTECLKHS */
|
||||
tlp_avail = thsbyte_clk * (blank - trans_lp);
|
||||
|
||||
ttxclkesc = tdsi_fclk / lp_clk_div;
|
||||
|
||||
lp_inter = ((tlp_avail - 8 * thsbyte_clk - 5 * tdsi_fclk) / ttxclkesc -
|
||||
26) / 16;
|
||||
|
||||
return max(lp_inter, 0);
|
||||
}
|
||||
|
||||
static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int blanking_mode;
|
||||
int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode;
|
||||
int hsa, hfp, hbp, width_bytes, bllp, lp_clk_div;
|
||||
int ddr_clk_pre, ddr_clk_post, enter_hs_mode_lat, exit_hs_mode_lat;
|
||||
int tclk_trail, ths_exit, exiths_clk;
|
||||
bool ddr_alwon;
|
||||
struct omap_video_timings *timings = &dssdev->panel.timings;
|
||||
int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
|
||||
int ndl = dsi->num_lanes_used - 1;
|
||||
int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1;
|
||||
int hsa_interleave_hs = 0, hsa_interleave_lp = 0;
|
||||
int hfp_interleave_hs = 0, hfp_interleave_lp = 0;
|
||||
int hbp_interleave_hs = 0, hbp_interleave_lp = 0;
|
||||
int bl_interleave_hs = 0, bl_interleave_lp = 0;
|
||||
u32 r;
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_CTRL);
|
||||
blanking_mode = FLD_GET(r, 20, 20);
|
||||
hfp_blanking_mode = FLD_GET(r, 21, 21);
|
||||
hbp_blanking_mode = FLD_GET(r, 22, 22);
|
||||
hsa_blanking_mode = FLD_GET(r, 23, 23);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VM_TIMING1);
|
||||
hbp = FLD_GET(r, 11, 0);
|
||||
hfp = FLD_GET(r, 23, 12);
|
||||
hsa = FLD_GET(r, 31, 24);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_CLK_TIMING);
|
||||
ddr_clk_post = FLD_GET(r, 7, 0);
|
||||
ddr_clk_pre = FLD_GET(r, 15, 8);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VM_TIMING7);
|
||||
exit_hs_mode_lat = FLD_GET(r, 15, 0);
|
||||
enter_hs_mode_lat = FLD_GET(r, 31, 16);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_CLK_CTRL);
|
||||
lp_clk_div = FLD_GET(r, 12, 0);
|
||||
ddr_alwon = FLD_GET(r, 13, 13);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
|
||||
ths_exit = FLD_GET(r, 7, 0);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG1);
|
||||
tclk_trail = FLD_GET(r, 15, 8);
|
||||
|
||||
exiths_clk = ths_exit + tclk_trail;
|
||||
|
||||
width_bytes = DIV_ROUND_UP(timings->x_res * bpp, 8);
|
||||
bllp = hbp + hfp + hsa + DIV_ROUND_UP(width_bytes + 6, ndl);
|
||||
|
||||
if (!hsa_blanking_mode) {
|
||||
hsa_interleave_hs = dsi_compute_interleave_hs(hsa, ddr_alwon,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
exiths_clk, ddr_clk_pre, ddr_clk_post);
|
||||
hsa_interleave_lp = dsi_compute_interleave_lp(hsa,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
lp_clk_div, dsi_fclk_hsdiv);
|
||||
}
|
||||
|
||||
if (!hfp_blanking_mode) {
|
||||
hfp_interleave_hs = dsi_compute_interleave_hs(hfp, ddr_alwon,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
exiths_clk, ddr_clk_pre, ddr_clk_post);
|
||||
hfp_interleave_lp = dsi_compute_interleave_lp(hfp,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
lp_clk_div, dsi_fclk_hsdiv);
|
||||
}
|
||||
|
||||
if (!hbp_blanking_mode) {
|
||||
hbp_interleave_hs = dsi_compute_interleave_hs(hbp, ddr_alwon,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
exiths_clk, ddr_clk_pre, ddr_clk_post);
|
||||
|
||||
hbp_interleave_lp = dsi_compute_interleave_lp(hbp,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
lp_clk_div, dsi_fclk_hsdiv);
|
||||
}
|
||||
|
||||
if (!blanking_mode) {
|
||||
bl_interleave_hs = dsi_compute_interleave_hs(bllp, ddr_alwon,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
exiths_clk, ddr_clk_pre, ddr_clk_post);
|
||||
|
||||
bl_interleave_lp = dsi_compute_interleave_lp(bllp,
|
||||
enter_hs_mode_lat, exit_hs_mode_lat,
|
||||
lp_clk_div, dsi_fclk_hsdiv);
|
||||
}
|
||||
|
||||
DSSDBG("DSI HS interleaving(TXBYTECLKHS) HSA %d, HFP %d, HBP %d, BLLP %d\n",
|
||||
hsa_interleave_hs, hfp_interleave_hs, hbp_interleave_hs,
|
||||
bl_interleave_hs);
|
||||
|
||||
DSSDBG("DSI LP interleaving(bytes) HSA %d, HFP %d, HBP %d, BLLP %d\n",
|
||||
hsa_interleave_lp, hfp_interleave_lp, hbp_interleave_lp,
|
||||
bl_interleave_lp);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VM_TIMING4);
|
||||
r = FLD_MOD(r, hsa_interleave_hs, 23, 16);
|
||||
r = FLD_MOD(r, hfp_interleave_hs, 15, 8);
|
||||
r = FLD_MOD(r, hbp_interleave_hs, 7, 0);
|
||||
dsi_write_reg(dsidev, DSI_VM_TIMING4, r);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VM_TIMING5);
|
||||
r = FLD_MOD(r, hsa_interleave_lp, 23, 16);
|
||||
r = FLD_MOD(r, hfp_interleave_lp, 15, 8);
|
||||
r = FLD_MOD(r, hbp_interleave_lp, 7, 0);
|
||||
dsi_write_reg(dsidev, DSI_VM_TIMING5, r);
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_VM_TIMING6);
|
||||
r = FLD_MOD(r, bl_interleave_hs, 31, 15);
|
||||
r = FLD_MOD(r, bl_interleave_lp, 16, 0);
|
||||
dsi_write_reg(dsidev, DSI_VM_TIMING6, r);
|
||||
}
|
||||
|
||||
static int dsi_proto_config(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
@ -3769,6 +3884,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_CTRL);
|
||||
@ -3793,6 +3909,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
|
||||
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
|
||||
dsi_config_vp_sync_events(dssdev);
|
||||
dsi_config_blanking_modes(dssdev);
|
||||
dsi_config_cmd_mode_interleaving(dssdev);
|
||||
}
|
||||
|
||||
dsi_vc_initial_config(dsidev, 0);
|
||||
@ -4008,6 +4125,7 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
dsi_if_enable(dsidev, false);
|
||||
@ -4192,10 +4310,6 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
|
||||
__cancel_delayed_work(&dsi->framedone_timeout_work);
|
||||
|
||||
dsi_handle_framedone(dsidev, 0);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC
|
||||
dispc_fake_vsync_irq();
|
||||
#endif
|
||||
}
|
||||
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
|
||||
@ -4259,13 +4373,12 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
||||
dispc_mgr_enable_stallmode(dssdev->manager->id, true);
|
||||
dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 1);
|
||||
|
||||
dispc_mgr_set_lcd_timings(dssdev->manager->id, &timings);
|
||||
dss_mgr_set_timings(dssdev->manager, &timings);
|
||||
} else {
|
||||
dispc_mgr_enable_stallmode(dssdev->manager->id, false);
|
||||
dispc_mgr_enable_fifohandcheck(dssdev->manager->id, 0);
|
||||
|
||||
dispc_mgr_set_lcd_timings(dssdev->manager->id,
|
||||
&dssdev->panel.timings);
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
}
|
||||
|
||||
dispc_mgr_set_lcd_display_type(dssdev->manager->id,
|
||||
@ -4294,13 +4407,11 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev)
|
||||
struct dsi_clock_info cinfo;
|
||||
int r;
|
||||
|
||||
/* we always use DSS_CLK_SYSCK as input clock */
|
||||
cinfo.use_sys_clk = true;
|
||||
cinfo.regn = dssdev->clocks.dsi.regn;
|
||||
cinfo.regm = dssdev->clocks.dsi.regm;
|
||||
cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc;
|
||||
cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi;
|
||||
r = dsi_calc_clock_rates(dssdev, &cinfo);
|
||||
r = dsi_calc_clock_rates(dsidev, &cinfo);
|
||||
if (r) {
|
||||
DSSERR("Failed to calc dsi clocks\n");
|
||||
return r;
|
||||
@ -4345,7 +4456,7 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev)
|
||||
static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int r;
|
||||
|
||||
r = dsi_pll_init(dsidev, true, true);
|
||||
@ -4357,7 +4468,7 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
||||
goto err1;
|
||||
|
||||
dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);
|
||||
dss_select_dsi_clk_source(dsi_module, dssdev->clocks.dsi.dsi_fclk_src);
|
||||
dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src);
|
||||
dss_select_lcd_clk_source(dssdev->manager->id,
|
||||
dssdev->clocks.dispc.channel.lcd_clk_src);
|
||||
|
||||
@ -4396,7 +4507,7 @@ err3:
|
||||
dsi_cio_uninit(dssdev);
|
||||
err2:
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
|
||||
|
||||
err1:
|
||||
@ -4410,7 +4521,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
|
||||
if (enter_ulps && !dsi->ulps_enabled)
|
||||
dsi_enter_ulps(dsidev);
|
||||
@ -4423,7 +4533,7 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev,
|
||||
dsi_vc_enable(dsidev, 3, 0);
|
||||
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi_module, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dss_select_lcd_clk_source(dssdev->manager->id, OMAP_DSS_CLK_SRC_FCK);
|
||||
dsi_cio_uninit(dssdev);
|
||||
dsi_pll_uninit(dsidev, disconnect_lanes);
|
||||
@ -4527,7 +4637,7 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dsi_enable_te);
|
||||
|
||||
int dsi_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init dsi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
@ -4680,13 +4790,39 @@ static void dsi_put_clocks(struct platform_device *dsidev)
|
||||
clk_put(dsi->sys_clk);
|
||||
}
|
||||
|
||||
/* DSI1 HW IP initialisation */
|
||||
static int omap_dsihw_probe(struct platform_device *dsidev)
|
||||
static void __init dsi_probe_pdata(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct omap_dss_board_info *pdata = dsidev->dev.platform_data;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_DSI)
|
||||
continue;
|
||||
|
||||
if (dssdev->phy.dsi.module != dsi->module_id)
|
||||
continue;
|
||||
|
||||
r = dsi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &dsidev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* DSI1 HW IP initialisation */
|
||||
static int __init omap_dsihw_probe(struct platform_device *dsidev)
|
||||
{
|
||||
struct omap_display_platform_data *dss_plat_data;
|
||||
struct omap_dss_board_info *board_info;
|
||||
u32 rev;
|
||||
int r, i, dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
int r, i;
|
||||
struct resource *dsi_mem;
|
||||
struct dsi_data *dsi;
|
||||
|
||||
@ -4694,15 +4830,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
|
||||
if (!dsi)
|
||||
return -ENOMEM;
|
||||
|
||||
dsi->module_id = dsidev->id;
|
||||
dsi->pdev = dsidev;
|
||||
dsi_pdev_map[dsi_module] = dsidev;
|
||||
dsi_pdev_map[dsi->module_id] = dsidev;
|
||||
dev_set_drvdata(&dsidev->dev, dsi);
|
||||
|
||||
dss_plat_data = dsidev->dev.platform_data;
|
||||
board_info = dss_plat_data->board_data;
|
||||
dsi->enable_pads = board_info->dsi_enable_pads;
|
||||
dsi->disable_pads = board_info->dsi_disable_pads;
|
||||
|
||||
spin_lock_init(&dsi->irq_lock);
|
||||
spin_lock_init(&dsi->errors_lock);
|
||||
dsi->errors = 0;
|
||||
@ -4780,8 +4912,21 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
|
||||
else
|
||||
dsi->num_lanes_supported = 3;
|
||||
|
||||
dsi_probe_pdata(dsidev);
|
||||
|
||||
dsi_runtime_put(dsidev);
|
||||
|
||||
if (dsi->module_id == 0)
|
||||
dss_debugfs_create_file("dsi1_regs", dsi1_dump_regs);
|
||||
else if (dsi->module_id == 1)
|
||||
dss_debugfs_create_file("dsi2_regs", dsi2_dump_regs);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
if (dsi->module_id == 0)
|
||||
dss_debugfs_create_file("dsi1_irqs", dsi1_dump_irqs);
|
||||
else if (dsi->module_id == 1)
|
||||
dss_debugfs_create_file("dsi2_irqs", dsi2_dump_irqs);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
err_runtime_get:
|
||||
@ -4790,12 +4935,14 @@ err_runtime_get:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_dsihw_remove(struct platform_device *dsidev)
|
||||
static int __exit omap_dsihw_remove(struct platform_device *dsidev)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
|
||||
WARN_ON(dsi->scp_clk_refcount > 0);
|
||||
|
||||
omap_dss_unregister_child_devices(&dsidev->dev);
|
||||
|
||||
pm_runtime_disable(&dsidev->dev);
|
||||
|
||||
dsi_put_clocks(dsidev);
|
||||
@ -4816,7 +4963,6 @@ static int omap_dsihw_remove(struct platform_device *dsidev)
|
||||
static int dsi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4825,20 +4971,11 @@ static int dsi_runtime_resume(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dispc;
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops dsi_pm_ops = {
|
||||
@ -4847,8 +4984,7 @@ static const struct dev_pm_ops dsi_pm_ops = {
|
||||
};
|
||||
|
||||
static struct platform_driver omap_dsihw_driver = {
|
||||
.probe = omap_dsihw_probe,
|
||||
.remove = omap_dsihw_remove,
|
||||
.remove = __exit_p(omap_dsihw_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_dsi",
|
||||
.owner = THIS_MODULE,
|
||||
@ -4856,12 +4992,12 @@ static struct platform_driver omap_dsihw_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int dsi_init_platform_driver(void)
|
||||
int __init dsi_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_register(&omap_dsihw_driver);
|
||||
return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe);
|
||||
}
|
||||
|
||||
void dsi_uninit_platform_driver(void)
|
||||
void __exit dsi_uninit_platform_driver(void)
|
||||
{
|
||||
return platform_driver_unregister(&omap_dsihw_driver);
|
||||
platform_driver_unregister(&omap_dsihw_driver);
|
||||
}
|
||||
|
@ -62,6 +62,9 @@ struct dss_reg {
|
||||
#define REG_FLD_MOD(idx, val, start, end) \
|
||||
dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
|
||||
|
||||
static int dss_runtime_get(void);
|
||||
static void dss_runtime_put(void);
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *base;
|
||||
@ -277,7 +280,7 @@ void dss_dump_clocks(struct seq_file *s)
|
||||
dss_runtime_put();
|
||||
}
|
||||
|
||||
void dss_dump_regs(struct seq_file *s)
|
||||
static void dss_dump_regs(struct seq_file *s)
|
||||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
|
||||
|
||||
@ -322,6 +325,7 @@ void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src)
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end);
|
||||
@ -335,7 +339,7 @@ void dss_select_dsi_clk_source(int dsi_module,
|
||||
enum omap_dss_clk_source clk_src)
|
||||
{
|
||||
struct platform_device *dsidev;
|
||||
int b;
|
||||
int b, pos;
|
||||
|
||||
switch (clk_src) {
|
||||
case OMAP_DSS_CLK_SRC_FCK:
|
||||
@ -355,9 +359,11 @@ void dss_select_dsi_clk_source(int dsi_module,
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
|
||||
pos = dsi_module == 0 ? 1 : 10;
|
||||
REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */
|
||||
|
||||
dss.dsi_clk_source[dsi_module] = clk_src;
|
||||
}
|
||||
@ -389,6 +395,7 @@ void dss_select_lcd_clk_source(enum omap_channel channel,
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 12;
|
||||
@ -706,7 +713,7 @@ static void dss_put_clocks(void)
|
||||
clk_put(dss.dss_clk);
|
||||
}
|
||||
|
||||
int dss_runtime_get(void)
|
||||
static int dss_runtime_get(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -717,7 +724,7 @@ int dss_runtime_get(void)
|
||||
return r < 0 ? r : 0;
|
||||
}
|
||||
|
||||
void dss_runtime_put(void)
|
||||
static void dss_runtime_put(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
@ -740,7 +747,7 @@ void dss_debug_dump_clocks(struct seq_file *s)
|
||||
#endif
|
||||
|
||||
/* DSS HW IP initialisation */
|
||||
static int omap_dsshw_probe(struct platform_device *pdev)
|
||||
static int __init omap_dsshw_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *dss_mem;
|
||||
u32 rev;
|
||||
@ -785,40 +792,24 @@ static int omap_dsshw_probe(struct platform_device *pdev)
|
||||
dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK;
|
||||
dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK;
|
||||
|
||||
r = dpi_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize DPI\n");
|
||||
goto err_dpi;
|
||||
}
|
||||
|
||||
r = sdi_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize SDI\n");
|
||||
goto err_sdi;
|
||||
}
|
||||
|
||||
rev = dss_read_reg(DSS_REVISION);
|
||||
printk(KERN_INFO "OMAP DSS rev %d.%d\n",
|
||||
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
||||
|
||||
dss_runtime_put();
|
||||
|
||||
dss_debugfs_create_file("dss", dss_dump_regs);
|
||||
|
||||
return 0;
|
||||
err_sdi:
|
||||
dpi_exit();
|
||||
err_dpi:
|
||||
dss_runtime_put();
|
||||
|
||||
err_runtime_get:
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
dss_put_clocks();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_dsshw_remove(struct platform_device *pdev)
|
||||
static int __exit omap_dsshw_remove(struct platform_device *pdev)
|
||||
{
|
||||
dpi_exit();
|
||||
sdi_exit();
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
dss_put_clocks();
|
||||
@ -829,11 +820,24 @@ static int omap_dsshw_remove(struct platform_device *pdev)
|
||||
static int dss_runtime_suspend(struct device *dev)
|
||||
{
|
||||
dss_save_context();
|
||||
dss_set_min_bus_tput(dev, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_runtime_resume(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
/*
|
||||
* Set an arbitrarily high tput request to ensure OPP100.
|
||||
* What we should really do is to make a request to stay in OPP100,
|
||||
* without any tput requirements, but that is not currently possible
|
||||
* via the PM layer.
|
||||
*/
|
||||
|
||||
r = dss_set_min_bus_tput(dev, 1000000000);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dss_restore_context();
|
||||
return 0;
|
||||
}
|
||||
@ -844,8 +848,7 @@ static const struct dev_pm_ops dss_pm_ops = {
|
||||
};
|
||||
|
||||
static struct platform_driver omap_dsshw_driver = {
|
||||
.probe = omap_dsshw_probe,
|
||||
.remove = omap_dsshw_remove,
|
||||
.remove = __exit_p(omap_dsshw_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_dss",
|
||||
.owner = THIS_MODULE,
|
||||
@ -853,12 +856,12 @@ static struct platform_driver omap_dsshw_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int dss_init_platform_driver(void)
|
||||
int __init dss_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_register(&omap_dsshw_driver);
|
||||
return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe);
|
||||
}
|
||||
|
||||
void dss_uninit_platform_driver(void)
|
||||
{
|
||||
return platform_driver_unregister(&omap_dsshw_driver);
|
||||
platform_driver_unregister(&omap_dsshw_driver);
|
||||
}
|
||||
|
@ -150,9 +150,6 @@ struct dsi_clock_info {
|
||||
u16 regm_dsi; /* OMAP3: REGM4
|
||||
* OMAP4: REGM5 */
|
||||
u16 lp_clk_div;
|
||||
|
||||
u8 highfreq;
|
||||
bool use_sys_clk;
|
||||
};
|
||||
|
||||
struct seq_file;
|
||||
@ -162,6 +159,16 @@ struct platform_device;
|
||||
struct bus_type *dss_get_bus(void);
|
||||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
int dss_get_ctx_loss_count(struct device *dev);
|
||||
int dss_dsi_enable_pads(int dsi_id, unsigned lane_mask);
|
||||
void dss_dsi_disable_pads(int dsi_id, unsigned lane_mask);
|
||||
int dss_set_min_bus_tput(struct device *dev, unsigned long tput);
|
||||
int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *));
|
||||
|
||||
int omap_dss_register_device(struct omap_dss_device *dssdev,
|
||||
struct device *parent, int disp_num);
|
||||
void omap_dss_unregister_device(struct omap_dss_device *dssdev);
|
||||
void omap_dss_unregister_child_devices(struct device *parent);
|
||||
|
||||
/* apply */
|
||||
void dss_apply_init(void);
|
||||
@ -179,6 +186,9 @@ void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
||||
int dss_mgr_set_device(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_set_timings(struct omap_overlay_manager *mgr,
|
||||
struct omap_video_timings *timings);
|
||||
const struct omap_video_timings *dss_mgr_get_timings(struct omap_overlay_manager *mgr);
|
||||
|
||||
bool dss_ovl_is_enabled(struct omap_overlay *ovl);
|
||||
int dss_ovl_enable(struct omap_overlay *ovl);
|
||||
@ -208,9 +218,11 @@ int dss_init_overlay_managers(struct platform_device *pdev);
|
||||
void dss_uninit_overlay_managers(struct platform_device *pdev);
|
||||
int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
|
||||
const struct omap_overlay_manager_info *info);
|
||||
int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings);
|
||||
int dss_mgr_check(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev,
|
||||
struct omap_overlay_manager_info *info,
|
||||
const struct omap_video_timings *mgr_timings,
|
||||
struct omap_overlay_info **overlay_infos);
|
||||
|
||||
/* overlay */
|
||||
@ -220,22 +232,18 @@ void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
|
||||
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
|
||||
int dss_ovl_simple_check(struct omap_overlay *ovl,
|
||||
const struct omap_overlay_info *info);
|
||||
int dss_ovl_check(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info, struct omap_dss_device *dssdev);
|
||||
int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
|
||||
const struct omap_video_timings *mgr_timings);
|
||||
|
||||
/* DSS */
|
||||
int dss_init_platform_driver(void);
|
||||
int dss_init_platform_driver(void) __init;
|
||||
void dss_uninit_platform_driver(void);
|
||||
|
||||
int dss_runtime_get(void);
|
||||
void dss_runtime_put(void);
|
||||
|
||||
void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select);
|
||||
enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void);
|
||||
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);
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
void dss_debug_dump_clocks(struct seq_file *s);
|
||||
#endif
|
||||
@ -265,19 +273,8 @@ int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
|
||||
/* SDI */
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
int sdi_init(void);
|
||||
void sdi_exit(void);
|
||||
int sdi_init_display(struct omap_dss_device *display);
|
||||
#else
|
||||
static inline int sdi_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void sdi_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
int sdi_init_platform_driver(void) __init;
|
||||
void sdi_uninit_platform_driver(void) __exit;
|
||||
|
||||
/* DSI */
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
@ -285,19 +282,14 @@ static inline void sdi_exit(void)
|
||||
struct dentry;
|
||||
struct file_operations;
|
||||
|
||||
int dsi_init_platform_driver(void);
|
||||
void dsi_uninit_platform_driver(void);
|
||||
int dsi_init_platform_driver(void) __init;
|
||||
void dsi_uninit_platform_driver(void) __exit;
|
||||
|
||||
int dsi_runtime_get(struct platform_device *dsidev);
|
||||
void dsi_runtime_put(struct platform_device *dsidev);
|
||||
|
||||
void dsi_dump_clocks(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);
|
||||
|
||||
int dsi_init_display(struct omap_dss_device *display);
|
||||
void dsi_irq_handler(void);
|
||||
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt);
|
||||
|
||||
@ -314,13 +306,6 @@ 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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void dsi_uninit_platform_driver(void)
|
||||
{
|
||||
}
|
||||
static inline int dsi_runtime_get(struct platform_device *dsidev)
|
||||
{
|
||||
return 0;
|
||||
@ -377,28 +362,14 @@ static inline struct platform_device *dsi_get_dsidev_from_id(int module)
|
||||
#endif
|
||||
|
||||
/* DPI */
|
||||
#ifdef CONFIG_OMAP2_DSS_DPI
|
||||
int dpi_init(void);
|
||||
void dpi_exit(void);
|
||||
int dpi_init_display(struct omap_dss_device *dssdev);
|
||||
#else
|
||||
static inline int dpi_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void dpi_exit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
int dpi_init_platform_driver(void) __init;
|
||||
void dpi_uninit_platform_driver(void) __exit;
|
||||
|
||||
/* DISPC */
|
||||
int dispc_init_platform_driver(void);
|
||||
void dispc_uninit_platform_driver(void);
|
||||
int dispc_init_platform_driver(void) __init;
|
||||
void dispc_uninit_platform_driver(void) __exit;
|
||||
void dispc_dump_clocks(struct seq_file *s);
|
||||
void dispc_dump_irqs(struct seq_file *s);
|
||||
void dispc_dump_regs(struct seq_file *s);
|
||||
void dispc_irq_handler(void);
|
||||
void dispc_fake_vsync_irq(void);
|
||||
|
||||
int dispc_runtime_get(void);
|
||||
void dispc_runtime_put(void);
|
||||
@ -409,12 +380,12 @@ void dispc_disable_sidle(void);
|
||||
void dispc_lcd_enable_signal_polarity(bool act_high);
|
||||
void dispc_lcd_enable_signal(bool enable);
|
||||
void dispc_pck_free_enable(bool enable);
|
||||
void dispc_set_digit_size(u16 width, u16 height);
|
||||
void dispc_enable_fifomerge(bool enable);
|
||||
void dispc_enable_gamma_table(bool enable);
|
||||
void dispc_set_loadmode(enum omap_dss_load_mode mode);
|
||||
|
||||
bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
|
||||
bool dispc_mgr_timings_ok(enum omap_channel channel,
|
||||
const struct omap_video_timings *timings);
|
||||
unsigned long dispc_fclk_rate(void);
|
||||
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
|
||||
struct dispc_clock_info *cinfo);
|
||||
@ -424,15 +395,16 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
||||
|
||||
void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
|
||||
void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane,
|
||||
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge);
|
||||
u32 *fifo_low, u32 *fifo_high, bool use_fifomerge,
|
||||
bool manual_update);
|
||||
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
||||
bool ilace, bool replication);
|
||||
bool ilace, bool replication,
|
||||
const struct omap_video_timings *mgr_timings);
|
||||
int dispc_ovl_enable(enum omap_plane plane, bool enable);
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel);
|
||||
|
||||
void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
|
||||
void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
|
||||
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
|
||||
bool dispc_mgr_go_busy(enum omap_channel channel);
|
||||
@ -445,12 +417,13 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
|
||||
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
|
||||
void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
|
||||
enum omap_lcd_display_type type);
|
||||
void dispc_mgr_set_lcd_timings(enum omap_channel channel,
|
||||
void dispc_mgr_set_timings(enum omap_channel channel,
|
||||
struct omap_video_timings *timings);
|
||||
void dispc_mgr_set_pol_freq(enum omap_channel channel,
|
||||
enum omap_panel_config config, u8 acbi, u8 acb);
|
||||
unsigned long dispc_mgr_lclk_rate(enum omap_channel channel);
|
||||
unsigned long dispc_mgr_pclk_rate(enum omap_channel channel);
|
||||
unsigned long dispc_core_clk_rate(void);
|
||||
int dispc_mgr_set_clock_div(enum omap_channel channel,
|
||||
struct dispc_clock_info *cinfo);
|
||||
int dispc_mgr_get_clock_div(enum omap_channel channel,
|
||||
@ -460,19 +433,10 @@ void dispc_mgr_setup(enum omap_channel channel,
|
||||
|
||||
/* VENC */
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
int venc_init_platform_driver(void);
|
||||
void venc_uninit_platform_driver(void);
|
||||
void venc_dump_regs(struct seq_file *s);
|
||||
int venc_init_display(struct omap_dss_device *display);
|
||||
int venc_init_platform_driver(void) __init;
|
||||
void venc_uninit_platform_driver(void) __exit;
|
||||
unsigned long venc_get_pixel_clock(void);
|
||||
#else
|
||||
static inline int venc_init_platform_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void venc_uninit_platform_driver(void)
|
||||
{
|
||||
}
|
||||
static inline unsigned long venc_get_pixel_clock(void)
|
||||
{
|
||||
WARN("%s: VENC not compiled in, returning pclk as 0\n", __func__);
|
||||
@ -482,23 +446,10 @@ static inline unsigned long venc_get_pixel_clock(void)
|
||||
|
||||
/* HDMI */
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI
|
||||
int hdmi_init_platform_driver(void);
|
||||
void hdmi_uninit_platform_driver(void);
|
||||
int hdmi_init_display(struct omap_dss_device *dssdev);
|
||||
int hdmi_init_platform_driver(void) __init;
|
||||
void hdmi_uninit_platform_driver(void) __exit;
|
||||
unsigned long hdmi_get_pixel_clock(void);
|
||||
void hdmi_dump_regs(struct seq_file *s);
|
||||
#else
|
||||
static inline int hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int hdmi_init_platform_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void hdmi_uninit_platform_driver(void)
|
||||
{
|
||||
}
|
||||
static inline unsigned long hdmi_get_pixel_clock(void)
|
||||
{
|
||||
WARN("%s: HDMI not compiled in, returning pclk as 0\n", __func__);
|
||||
@ -514,22 +465,18 @@ int omapdss_hdmi_read_edid(u8 *buf, int len);
|
||||
bool omapdss_hdmi_detect(void);
|
||||
int hdmi_panel_init(void);
|
||||
void hdmi_panel_exit(void);
|
||||
#ifdef CONFIG_OMAP4_DSS_HDMI_AUDIO
|
||||
int hdmi_audio_enable(void);
|
||||
void hdmi_audio_disable(void);
|
||||
int hdmi_audio_start(void);
|
||||
void hdmi_audio_stop(void);
|
||||
bool hdmi_mode_has_audio(void);
|
||||
int hdmi_audio_config(struct omap_dss_audio *audio);
|
||||
#endif
|
||||
|
||||
/* RFBI */
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
int rfbi_init_platform_driver(void);
|
||||
void rfbi_uninit_platform_driver(void);
|
||||
void rfbi_dump_regs(struct seq_file *s);
|
||||
int rfbi_init_display(struct omap_dss_device *display);
|
||||
#else
|
||||
static inline int rfbi_init_platform_driver(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void rfbi_uninit_platform_driver(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
int rfbi_init_platform_driver(void) __init;
|
||||
void rfbi_uninit_platform_driver(void) __exit;
|
||||
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
|
@ -52,6 +52,8 @@ struct omap_dss_features {
|
||||
const char * const *clksrc_names;
|
||||
const struct dss_param_range *dss_params;
|
||||
|
||||
const enum omap_dss_rotation_type supported_rotation_types;
|
||||
|
||||
const u32 buffer_size_unit;
|
||||
const u32 burst_size_unit;
|
||||
};
|
||||
@ -311,6 +313,8 @@ static const struct dss_param_range omap2_dss_param_range[] = {
|
||||
* scaler cannot scale a image with width more than 768.
|
||||
*/
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 768 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap3_dss_param_range[] = {
|
||||
@ -324,6 +328,8 @@ static const struct dss_param_range omap3_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap4_dss_param_range[] = {
|
||||
@ -337,6 +343,8 @@ static const struct dss_param_range omap4_dss_param_range[] = {
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_WIDTH] = { 1, 2048 },
|
||||
[FEAT_PARAM_MGR_HEIGHT] = { 1, 2048 },
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap2_dss_feat_list[] = {
|
||||
@ -399,6 +407,7 @@ static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = {
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
|
||||
@ -416,6 +425,7 @@ static const enum dss_feat_id omap4430_es2_0_1_2_dss_feat_list[] = {
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
static const enum dss_feat_id omap4_dss_feat_list[] = {
|
||||
@ -434,6 +444,7 @@ static const enum dss_feat_id omap4_dss_feat_list[] = {
|
||||
FEAT_FIR_COEF_V,
|
||||
FEAT_ALPHA_FREE_ZORDER,
|
||||
FEAT_FIFO_MERGE,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
/* OMAP2 DSS Features */
|
||||
@ -451,6 +462,7 @@ static const struct omap_dss_features omap2_dss_features = {
|
||||
.overlay_caps = omap2_dss_overlay_caps,
|
||||
.clksrc_names = omap2_dss_clk_source_names,
|
||||
.dss_params = omap2_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
@ -470,6 +482,7 @@ static const struct omap_dss_features omap3430_dss_features = {
|
||||
.overlay_caps = omap3430_dss_overlay_caps,
|
||||
.clksrc_names = omap3_dss_clk_source_names,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
@ -488,6 +501,7 @@ static const struct omap_dss_features omap3630_dss_features = {
|
||||
.overlay_caps = omap3630_dss_overlay_caps,
|
||||
.clksrc_names = omap3_dss_clk_source_names,
|
||||
.dss_params = omap3_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_VRFB,
|
||||
.buffer_size_unit = 1,
|
||||
.burst_size_unit = 8,
|
||||
};
|
||||
@ -508,6 +522,7 @@ static const struct omap_dss_features omap4430_es1_0_dss_features = {
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
@ -527,6 +542,7 @@ static const struct omap_dss_features omap4430_es2_0_1_2_dss_features = {
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
@ -546,6 +562,7 @@ static const struct omap_dss_features omap4_dss_features = {
|
||||
.overlay_caps = omap4_dss_overlay_caps,
|
||||
.clksrc_names = omap4_dss_clk_source_names,
|
||||
.dss_params = omap4_dss_param_range,
|
||||
.supported_rotation_types = OMAP_DSS_ROT_DMA | OMAP_DSS_ROT_TILER,
|
||||
.buffer_size_unit = 16,
|
||||
.burst_size_unit = 16,
|
||||
};
|
||||
@ -562,13 +579,17 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
|
||||
.pll_enable = ti_hdmi_4xxx_pll_enable,
|
||||
.pll_disable = ti_hdmi_4xxx_pll_disable,
|
||||
.video_enable = ti_hdmi_4xxx_wp_video_start,
|
||||
.video_disable = ti_hdmi_4xxx_wp_video_stop,
|
||||
.dump_wrapper = ti_hdmi_4xxx_wp_dump,
|
||||
.dump_core = ti_hdmi_4xxx_core_dump,
|
||||
.dump_pll = ti_hdmi_4xxx_pll_dump,
|
||||
.dump_phy = ti_hdmi_4xxx_phy_dump,
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
.audio_enable = ti_hdmi_4xxx_wp_audio_enable,
|
||||
.audio_disable = ti_hdmi_4xxx_wp_audio_disable,
|
||||
.audio_start = ti_hdmi_4xxx_audio_start,
|
||||
.audio_stop = ti_hdmi_4xxx_audio_stop,
|
||||
.audio_config = ti_hdmi_4xxx_audio_config,
|
||||
#endif
|
||||
|
||||
};
|
||||
@ -662,6 +683,11 @@ void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
|
||||
*end = omap_current_dss_features->reg_fields[id].end;
|
||||
}
|
||||
|
||||
bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
|
||||
{
|
||||
return omap_current_dss_features->supported_rotation_types & rot_type;
|
||||
}
|
||||
|
||||
void dss_features_init(void)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
|
@ -62,6 +62,7 @@ enum dss_feat_id {
|
||||
FEAT_FIFO_MERGE,
|
||||
/* An unknown HW bug causing the normal FIFO thresholds not to work */
|
||||
FEAT_OMAP3_DSI_FIFO_BUG,
|
||||
FEAT_BURST_2D,
|
||||
};
|
||||
|
||||
/* DSS register field id */
|
||||
@ -91,6 +92,8 @@ enum dss_range_param {
|
||||
FEAT_PARAM_DSIPLL_LPDIV,
|
||||
FEAT_PARAM_DOWNSCALE,
|
||||
FEAT_PARAM_LINEWIDTH,
|
||||
FEAT_PARAM_MGR_WIDTH,
|
||||
FEAT_PARAM_MGR_HEIGHT,
|
||||
};
|
||||
|
||||
/* DSS Feature Functions */
|
||||
@ -108,6 +111,8 @@ const char *dss_feat_get_clk_source_name(enum omap_dss_clk_source id);
|
||||
u32 dss_feat_get_buffer_size_unit(void); /* in bytes */
|
||||
u32 dss_feat_get_burst_size_unit(void); /* in bytes */
|
||||
|
||||
bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
|
||||
|
||||
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);
|
||||
void dss_features_init(void);
|
||||
|
@ -33,12 +33,6 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/clk.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>
|
||||
#include "ti_hdmi_4xxx_ip.h"
|
||||
#endif
|
||||
|
||||
#include "ti_hdmi.h"
|
||||
#include "dss.h"
|
||||
@ -63,7 +57,6 @@
|
||||
|
||||
static struct {
|
||||
struct mutex lock;
|
||||
struct omap_display_platform_data *pdata;
|
||||
struct platform_device *pdev;
|
||||
struct hdmi_ip_data ip_data;
|
||||
|
||||
@ -130,25 +123,12 @@ static int hdmi_runtime_get(void)
|
||||
|
||||
DSSDBG("hdmi_runtime_get\n");
|
||||
|
||||
/*
|
||||
* HACK: Add dss_runtime_get() to ensure DSS clock domain is enabled.
|
||||
* This should be removed later.
|
||||
*/
|
||||
r = dss_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dss;
|
||||
|
||||
r = pm_runtime_get_sync(&hdmi.pdev->dev);
|
||||
WARN_ON(r < 0);
|
||||
if (r < 0)
|
||||
goto err_get_hdmi;
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_hdmi:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_runtime_put(void)
|
||||
@ -159,15 +139,9 @@ static void hdmi_runtime_put(void)
|
||||
|
||||
r = pm_runtime_put_sync(&hdmi.pdev->dev);
|
||||
WARN_ON(r < 0);
|
||||
|
||||
/*
|
||||
* HACK: This is added to complement the dss_runtime_get() call in
|
||||
* hdmi_runtime_get(). This should be removed later.
|
||||
*/
|
||||
dss_runtime_put();
|
||||
}
|
||||
|
||||
int hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
@ -344,7 +318,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
|
||||
hdmi_compute_pll(dssdev, phy, &hdmi.ip_data.pll_data);
|
||||
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
|
||||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
|
||||
/* config the PLL and PHY hdmi_set_pll_pwrfirst */
|
||||
r = hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
|
||||
@ -376,10 +350,11 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
dispc_enable_gamma_table(0);
|
||||
|
||||
/* tv size */
|
||||
dispc_set_digit_size(dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res);
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
|
||||
r = hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
|
||||
if (r)
|
||||
goto err_vid_enable;
|
||||
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r)
|
||||
@ -388,7 +363,8 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
|
||||
err_mgr_enable:
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
|
||||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
err_vid_enable:
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
err:
|
||||
@ -400,7 +376,7 @@ static void hdmi_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
|
||||
hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
hdmi_runtime_put();
|
||||
@ -436,10 +412,12 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
|
||||
r = hdmi_power_on(dssdev);
|
||||
if (r)
|
||||
DSSERR("failed to power on device\n");
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
}
|
||||
}
|
||||
|
||||
void hdmi_dump_regs(struct seq_file *s)
|
||||
static void hdmi_dump_regs(struct seq_file *s)
|
||||
{
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
@ -555,220 +533,6 @@ 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 int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct platform_device *pdev = to_platform_device(codec->dev);
|
||||
struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
|
||||
int err = 0;
|
||||
|
||||
if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) {
|
||||
dev_err(&pdev->dev, "Cannot enable/disable audio\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
ip_data->ops->audio_enable(ip_data, true);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
ip_data->ops->audio_enable(ip_data, false);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
|
||||
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(ip_data, 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(ip_data, &audio_dma);
|
||||
hdmi_wp_audio_config_format(ip_data, &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 = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
|
||||
} else {
|
||||
core_cfg.aud_par_busclk = (((128 * 31) - 1) << 8);
|
||||
core_cfg.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
|
||||
core_cfg.use_mclk = true;
|
||||
}
|
||||
|
||||
if (core_cfg.use_mclk)
|
||||
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(ip_data, &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(ip_data, &aud_if_cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_audio_startup(struct snd_pcm_substream *substream,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
if (!hdmi.ip_data.cfg.cm.mode) {
|
||||
pr_err("Current video settings do not support audio.\n");
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_audio_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct hdmi_ip_data *priv = &hdmi.ip_data;
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
|
||||
.probe = hdmi_audio_codec_probe,
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
static int hdmi_get_clocks(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
@ -790,13 +554,180 @@ static void hdmi_put_clocks(void)
|
||||
clk_put(hdmi.sys_clk);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts)
|
||||
{
|
||||
u32 deep_color;
|
||||
bool deep_color_correct = false;
|
||||
u32 pclk = hdmi.ip_data.cfg.timings.pixel_clock;
|
||||
|
||||
if (n == NULL || cts == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
/* TODO: When implemented, query deep color mode here. */
|
||||
deep_color = 100;
|
||||
|
||||
/*
|
||||
* When using deep color, the default N value (as in the HDMI
|
||||
* specification) yields to an non-integer CTS. Hence, we
|
||||
* modify it while keeping the restrictions described in
|
||||
* section 7.2.1 of the HDMI 1.4a specification.
|
||||
*/
|
||||
switch (sample_freq) {
|
||||
case 32000:
|
||||
case 48000:
|
||||
case 96000:
|
||||
case 192000:
|
||||
if (deep_color == 125)
|
||||
if (pclk == 27027 || pclk == 74250)
|
||||
deep_color_correct = true;
|
||||
if (deep_color == 150)
|
||||
if (pclk == 27027)
|
||||
deep_color_correct = true;
|
||||
break;
|
||||
case 44100:
|
||||
case 88200:
|
||||
case 176400:
|
||||
if (deep_color == 125)
|
||||
if (pclk == 27027)
|
||||
deep_color_correct = true;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (deep_color_correct) {
|
||||
switch (sample_freq) {
|
||||
case 32000:
|
||||
*n = 8192;
|
||||
break;
|
||||
case 44100:
|
||||
*n = 12544;
|
||||
break;
|
||||
case 48000:
|
||||
*n = 8192;
|
||||
break;
|
||||
case 88200:
|
||||
*n = 25088;
|
||||
break;
|
||||
case 96000:
|
||||
*n = 16384;
|
||||
break;
|
||||
case 176400:
|
||||
*n = 50176;
|
||||
break;
|
||||
case 192000:
|
||||
*n = 32768;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
switch (sample_freq) {
|
||||
case 32000:
|
||||
*n = 4096;
|
||||
break;
|
||||
case 44100:
|
||||
*n = 6272;
|
||||
break;
|
||||
case 48000:
|
||||
*n = 6144;
|
||||
break;
|
||||
case 88200:
|
||||
*n = 12544;
|
||||
break;
|
||||
case 96000:
|
||||
*n = 12288;
|
||||
break;
|
||||
case 176400:
|
||||
*n = 25088;
|
||||
break;
|
||||
case 192000:
|
||||
*n = 24576;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* Calculate CTS. See HDMI 1.3a or 1.4a specifications */
|
||||
*cts = pclk * (*n / 128) * deep_color / (sample_freq / 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hdmi_audio_enable(void)
|
||||
{
|
||||
DSSDBG("audio_enable\n");
|
||||
|
||||
return hdmi.ip_data.ops->audio_enable(&hdmi.ip_data);
|
||||
}
|
||||
|
||||
void hdmi_audio_disable(void)
|
||||
{
|
||||
DSSDBG("audio_disable\n");
|
||||
|
||||
hdmi.ip_data.ops->audio_disable(&hdmi.ip_data);
|
||||
}
|
||||
|
||||
int hdmi_audio_start(void)
|
||||
{
|
||||
DSSDBG("audio_start\n");
|
||||
|
||||
return hdmi.ip_data.ops->audio_start(&hdmi.ip_data);
|
||||
}
|
||||
|
||||
void hdmi_audio_stop(void)
|
||||
{
|
||||
DSSDBG("audio_stop\n");
|
||||
|
||||
hdmi.ip_data.ops->audio_stop(&hdmi.ip_data);
|
||||
}
|
||||
|
||||
bool hdmi_mode_has_audio(void)
|
||||
{
|
||||
if (hdmi.ip_data.cfg.cm.mode == HDMI_HDMI)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int hdmi_audio_config(struct omap_dss_audio *audio)
|
||||
{
|
||||
return hdmi.ip_data.ops->audio_config(&hdmi.ip_data, audio);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void __init hdmi_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int r, i;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_HDMI)
|
||||
continue;
|
||||
|
||||
r = hdmi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* HDMI HW IP initialisation */
|
||||
static int omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
static int __init omapdss_hdmihw_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *hdmi_mem;
|
||||
int r;
|
||||
|
||||
hdmi.pdata = pdev->dev.platform_data;
|
||||
hdmi.pdev = pdev;
|
||||
|
||||
mutex_init(&hdmi.lock);
|
||||
@ -830,28 +761,18 @@ 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)
|
||||
dss_debugfs_create_file("hdmi", hdmi_dump_regs);
|
||||
|
||||
hdmi_probe_pdata(pdev);
|
||||
|
||||
/* Register ASoC codec DAI */
|
||||
r = snd_soc_register_codec(&pdev->dev, &hdmi_audio_codec_drv,
|
||||
&hdmi_codec_dai_drv, 1);
|
||||
if (r) {
|
||||
DSSERR("can't register ASoC HDMI audio codec\n");
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omapdss_hdmihw_remove(struct platform_device *pdev)
|
||||
static int __exit omapdss_hdmihw_remove(struct platform_device *pdev)
|
||||
{
|
||||
hdmi_panel_exit();
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
snd_soc_unregister_codec(&pdev->dev);
|
||||
#endif
|
||||
hdmi_panel_exit();
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
@ -867,7 +788,6 @@ static int hdmi_runtime_suspend(struct device *dev)
|
||||
clk_disable(hdmi.sys_clk);
|
||||
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -876,23 +796,13 @@ static int hdmi_runtime_resume(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dispc;
|
||||
|
||||
return r;
|
||||
|
||||
clk_enable(hdmi.sys_clk);
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops hdmi_pm_ops = {
|
||||
@ -901,8 +811,7 @@ static const struct dev_pm_ops hdmi_pm_ops = {
|
||||
};
|
||||
|
||||
static struct platform_driver omapdss_hdmihw_driver = {
|
||||
.probe = omapdss_hdmihw_probe,
|
||||
.remove = omapdss_hdmihw_remove,
|
||||
.remove = __exit_p(omapdss_hdmihw_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_hdmi",
|
||||
.owner = THIS_MODULE,
|
||||
@ -910,12 +819,12 @@ static struct platform_driver omapdss_hdmihw_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int hdmi_init_platform_driver(void)
|
||||
int __init hdmi_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_register(&omapdss_hdmihw_driver);
|
||||
return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe);
|
||||
}
|
||||
|
||||
void hdmi_uninit_platform_driver(void)
|
||||
void __exit hdmi_uninit_platform_driver(void)
|
||||
{
|
||||
return platform_driver_unregister(&omapdss_hdmihw_driver);
|
||||
platform_driver_unregister(&omapdss_hdmihw_driver);
|
||||
}
|
||||
|
@ -30,7 +30,12 @@
|
||||
#include "dss.h"
|
||||
|
||||
static struct {
|
||||
struct mutex hdmi_lock;
|
||||
/* This protects the panel ops, mainly when accessing the HDMI IP. */
|
||||
struct mutex lock;
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
/* This protects the audio ops, specifically. */
|
||||
spinlock_t audio_lock;
|
||||
#endif
|
||||
} hdmi;
|
||||
|
||||
|
||||
@ -54,12 +59,168 @@ static void hdmi_panel_remove(struct omap_dss_device *dssdev)
|
||||
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int r;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
spin_lock_irqsave(&hdmi.audio_lock, flags);
|
||||
|
||||
/* enable audio only if the display is active and supports audio */
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
|
||||
!hdmi_mode_has_audio()) {
|
||||
DSSERR("audio not supported or display is off\n");
|
||||
r = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = hdmi_audio_enable();
|
||||
|
||||
if (!r)
|
||||
dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hdmi.audio_lock, flags);
|
||||
|
||||
hdmi_audio_disable();
|
||||
|
||||
dssdev->audio_state = OMAP_DSS_AUDIO_DISABLED;
|
||||
|
||||
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
|
||||
}
|
||||
|
||||
static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int r;
|
||||
|
||||
spin_lock_irqsave(&hdmi.audio_lock, flags);
|
||||
/*
|
||||
* No need to check the panel state. It was checked when trasitioning
|
||||
* to AUDIO_ENABLED.
|
||||
*/
|
||||
if (dssdev->audio_state != OMAP_DSS_AUDIO_ENABLED) {
|
||||
DSSERR("audio start from invalid state\n");
|
||||
r = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = hdmi_audio_start();
|
||||
|
||||
if (!r)
|
||||
dssdev->audio_state = OMAP_DSS_AUDIO_PLAYING;
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&hdmi.audio_lock, flags);
|
||||
|
||||
hdmi_audio_stop();
|
||||
dssdev->audio_state = OMAP_DSS_AUDIO_ENABLED;
|
||||
|
||||
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
|
||||
}
|
||||
|
||||
static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
|
||||
{
|
||||
bool r = false;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
goto err;
|
||||
|
||||
if (!hdmi_mode_has_audio())
|
||||
goto err;
|
||||
|
||||
r = true;
|
||||
err:
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_audio *audio)
|
||||
{
|
||||
unsigned long flags;
|
||||
int r;
|
||||
|
||||
mutex_lock(&hdmi.lock);
|
||||
spin_lock_irqsave(&hdmi.audio_lock, flags);
|
||||
|
||||
/* config audio only if the display is active and supports audio */
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE ||
|
||||
!hdmi_mode_has_audio()) {
|
||||
DSSERR("audio not supported or display is off\n");
|
||||
r = -EPERM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = hdmi_audio_config(audio);
|
||||
|
||||
if (!r)
|
||||
dssdev->audio_state = OMAP_DSS_AUDIO_CONFIGURED;
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&hdmi.audio_lock, flags);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
static int hdmi_panel_audio_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static void hdmi_panel_audio_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int hdmi_panel_audio_start(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static void hdmi_panel_audio_stop(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static bool hdmi_panel_audio_supported(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static int hdmi_panel_audio_config(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_audio *audio)
|
||||
{
|
||||
return -EPERM;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int hdmi_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
DSSDBG("ENTER hdmi_panel_enable\n");
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
r = -EINVAL;
|
||||
@ -75,40 +236,52 @@ static int hdmi_panel_enable(struct omap_dss_device *dssdev)
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
err:
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void hdmi_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
/*
|
||||
* TODO: notify audio users that the display was disabled. For
|
||||
* now, disable audio locally to not break our audio state
|
||||
* machine.
|
||||
*/
|
||||
hdmi_panel_audio_disable(dssdev);
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static int hdmi_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
/*
|
||||
* TODO: notify audio users that the display was suspended. For now,
|
||||
* disable audio locally to not break our audio state machine.
|
||||
*/
|
||||
hdmi_panel_audio_disable(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
|
||||
err:
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -117,7 +290,7 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
r = -EINVAL;
|
||||
@ -129,11 +302,12 @@ static int hdmi_panel_resume(struct omap_dss_device *dssdev)
|
||||
DSSERR("failed to power on\n");
|
||||
goto err;
|
||||
}
|
||||
/* TODO: notify audio users that the panel resumed. */
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
err:
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -141,11 +315,11 @@ err:
|
||||
static void hdmi_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
*timings = dssdev->panel.timings;
|
||||
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static void hdmi_set_timings(struct omap_dss_device *dssdev,
|
||||
@ -153,12 +327,18 @@ static void hdmi_set_timings(struct omap_dss_device *dssdev,
|
||||
{
|
||||
DSSDBG("hdmi_set_timings\n");
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
/*
|
||||
* TODO: notify audio users that there was a timings change. For
|
||||
* now, disable audio locally to not break our audio state machine.
|
||||
*/
|
||||
hdmi_panel_audio_disable(dssdev);
|
||||
|
||||
dssdev->panel.timings = *timings;
|
||||
omapdss_hdmi_display_set_timing(dssdev);
|
||||
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
}
|
||||
|
||||
static int hdmi_check_timings(struct omap_dss_device *dssdev,
|
||||
@ -168,11 +348,11 @@ static int hdmi_check_timings(struct omap_dss_device *dssdev,
|
||||
|
||||
DSSDBG("hdmi_check_timings\n");
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
r = omapdss_hdmi_display_check_timing(dssdev, timings);
|
||||
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -180,7 +360,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
|
||||
{
|
||||
int r;
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
@ -194,7 +374,7 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, u8 *buf, int len)
|
||||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
err:
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -203,7 +383,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
mutex_lock(&hdmi.hdmi_lock);
|
||||
mutex_lock(&hdmi.lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = omapdss_hdmi_display_enable(dssdev);
|
||||
@ -217,7 +397,7 @@ static bool hdmi_detect(struct omap_dss_device *dssdev)
|
||||
dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
omapdss_hdmi_display_disable(dssdev);
|
||||
err:
|
||||
mutex_unlock(&hdmi.hdmi_lock);
|
||||
mutex_unlock(&hdmi.lock);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -234,6 +414,12 @@ static struct omap_dss_driver hdmi_driver = {
|
||||
.check_timings = hdmi_check_timings,
|
||||
.read_edid = hdmi_read_edid,
|
||||
.detect = hdmi_detect,
|
||||
.audio_enable = hdmi_panel_audio_enable,
|
||||
.audio_disable = hdmi_panel_audio_disable,
|
||||
.audio_start = hdmi_panel_audio_start,
|
||||
.audio_stop = hdmi_panel_audio_stop,
|
||||
.audio_supported = hdmi_panel_audio_supported,
|
||||
.audio_config = hdmi_panel_audio_config,
|
||||
.driver = {
|
||||
.name = "hdmi_panel",
|
||||
.owner = THIS_MODULE,
|
||||
@ -242,7 +428,11 @@ static struct omap_dss_driver hdmi_driver = {
|
||||
|
||||
int hdmi_panel_init(void)
|
||||
{
|
||||
mutex_init(&hdmi.hdmi_lock);
|
||||
mutex_init(&hdmi.lock);
|
||||
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
spin_lock_init(&hdmi.audio_lock);
|
||||
#endif
|
||||
|
||||
omap_dss_register_driver(&hdmi_driver);
|
||||
|
||||
|
@ -654,9 +654,20 @@ static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_mgr_check_timings(struct omap_overlay_manager *mgr,
|
||||
const struct omap_video_timings *timings)
|
||||
{
|
||||
if (!dispc_mgr_timings_ok(mgr->id, timings)) {
|
||||
DSSERR("check_manager: invalid timings\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_mgr_check(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev,
|
||||
struct omap_overlay_manager_info *info,
|
||||
const struct omap_video_timings *mgr_timings,
|
||||
struct omap_overlay_info **overlay_infos)
|
||||
{
|
||||
struct omap_overlay *ovl;
|
||||
@ -668,6 +679,10 @@ int dss_mgr_check(struct omap_overlay_manager *mgr,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dss_mgr_check_timings(mgr, mgr_timings);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
list_for_each_entry(ovl, &mgr->overlays, list) {
|
||||
struct omap_overlay_info *oi;
|
||||
int r;
|
||||
@ -677,7 +692,7 @@ int dss_mgr_check(struct omap_overlay_manager *mgr,
|
||||
if (oi == NULL)
|
||||
continue;
|
||||
|
||||
r = dss_ovl_check(ovl, oi, dssdev);
|
||||
r = dss_ovl_check(ovl, oi, mgr_timings);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -628,19 +628,23 @@ int dss_ovl_simple_check(struct omap_overlay *ovl,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dss_feat_rotation_type_supported(info->rotation_type) == 0) {
|
||||
DSSERR("check_overlay: rotation type %d not supported\n",
|
||||
info->rotation_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_ovl_check(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info, struct omap_dss_device *dssdev)
|
||||
int dss_ovl_check(struct omap_overlay *ovl, struct omap_overlay_info *info,
|
||||
const struct omap_video_timings *mgr_timings)
|
||||
{
|
||||
u16 outw, outh;
|
||||
u16 dw, dh;
|
||||
|
||||
if (dssdev == NULL)
|
||||
return 0;
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
dw = mgr_timings->x_res;
|
||||
dh = mgr_timings->y_res;
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
|
||||
outw = info->width;
|
||||
|
@ -304,13 +304,23 @@ static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width,
|
||||
u16 height, void (*callback)(void *data), void *data)
|
||||
{
|
||||
u32 l;
|
||||
struct omap_video_timings timings = {
|
||||
.hsw = 1,
|
||||
.hfp = 1,
|
||||
.hbp = 1,
|
||||
.vsw = 1,
|
||||
.vfp = 0,
|
||||
.vbp = 0,
|
||||
.x_res = width,
|
||||
.y_res = height,
|
||||
};
|
||||
|
||||
/*BUG_ON(callback == 0);*/
|
||||
BUG_ON(rfbi.framedone_callback != NULL);
|
||||
|
||||
DSSDBG("rfbi_transfer_area %dx%d\n", width, height);
|
||||
|
||||
dispc_mgr_set_lcd_size(dssdev->manager->id, width, height);
|
||||
dss_mgr_set_timings(dssdev->manager, &timings);
|
||||
|
||||
dispc_mgr_enable(dssdev->manager->id, true);
|
||||
|
||||
@ -766,6 +776,16 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h)
|
||||
{
|
||||
u16 dw, dh;
|
||||
struct omap_video_timings timings = {
|
||||
.hsw = 1,
|
||||
.hfp = 1,
|
||||
.hbp = 1,
|
||||
.vsw = 1,
|
||||
.vfp = 0,
|
||||
.vbp = 0,
|
||||
.x_res = *w,
|
||||
.y_res = *h,
|
||||
};
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
@ -784,7 +804,7 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
||||
if (*w == 0 || *h == 0)
|
||||
return -EINVAL;
|
||||
|
||||
dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
|
||||
dss_mgr_set_timings(dssdev->manager, &timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -799,7 +819,7 @@ int omap_rfbi_update(struct omap_dss_device *dssdev,
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_update);
|
||||
|
||||
void rfbi_dump_regs(struct seq_file *s)
|
||||
static void rfbi_dump_regs(struct seq_file *s)
|
||||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r))
|
||||
|
||||
@ -900,15 +920,39 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
|
||||
|
||||
int rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init rfbi_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_DBI)
|
||||
continue;
|
||||
|
||||
r = rfbi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* RFBI HW IP initialisation */
|
||||
static int omap_rfbihw_probe(struct platform_device *pdev)
|
||||
static int __init omap_rfbihw_probe(struct platform_device *pdev)
|
||||
{
|
||||
u32 rev;
|
||||
struct resource *rfbi_mem;
|
||||
@ -956,6 +1000,10 @@ static int omap_rfbihw_probe(struct platform_device *pdev)
|
||||
|
||||
rfbi_runtime_put();
|
||||
|
||||
dss_debugfs_create_file("rfbi", rfbi_dump_regs);
|
||||
|
||||
rfbi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_runtime_get:
|
||||
@ -963,8 +1011,9 @@ err_runtime_get:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_rfbihw_remove(struct platform_device *pdev)
|
||||
static int __exit omap_rfbihw_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
return 0;
|
||||
}
|
||||
@ -972,7 +1021,6 @@ static int omap_rfbihw_remove(struct platform_device *pdev)
|
||||
static int rfbi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -981,20 +1029,11 @@ static int rfbi_runtime_resume(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dispc;
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rfbi_pm_ops = {
|
||||
@ -1003,8 +1042,7 @@ static const struct dev_pm_ops rfbi_pm_ops = {
|
||||
};
|
||||
|
||||
static struct platform_driver omap_rfbihw_driver = {
|
||||
.probe = omap_rfbihw_probe,
|
||||
.remove = omap_rfbihw_remove,
|
||||
.remove = __exit_p(omap_rfbihw_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_rfbi",
|
||||
.owner = THIS_MODULE,
|
||||
@ -1012,12 +1050,12 @@ static struct platform_driver omap_rfbihw_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int rfbi_init_platform_driver(void)
|
||||
int __init rfbi_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_register(&omap_rfbihw_driver);
|
||||
return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe);
|
||||
}
|
||||
|
||||
void rfbi_uninit_platform_driver(void)
|
||||
void __exit rfbi_uninit_platform_driver(void)
|
||||
{
|
||||
return platform_driver_unregister(&omap_rfbihw_driver);
|
||||
platform_driver_unregister(&omap_rfbihw_driver);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/omapdss.h>
|
||||
#include "dss.h"
|
||||
@ -71,10 +72,6 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
||||
if (r)
|
||||
goto err_reg_enable;
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r)
|
||||
goto err_get_dispc;
|
||||
@ -107,7 +104,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
||||
}
|
||||
|
||||
|
||||
dispc_mgr_set_lcd_timings(dssdev->manager->id, t);
|
||||
dss_mgr_set_timings(dssdev->manager, t);
|
||||
|
||||
r = dss_set_clock_div(&dss_cinfo);
|
||||
if (r)
|
||||
@ -137,8 +134,6 @@ err_set_dss_clock_div:
|
||||
err_calc_clock_div:
|
||||
dispc_runtime_put();
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
regulator_disable(sdi.vdds_sdi_reg);
|
||||
err_reg_enable:
|
||||
omap_dss_stop_device(dssdev);
|
||||
@ -154,7 +149,6 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
dss_sdi_disable();
|
||||
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
regulator_disable(sdi.vdds_sdi_reg);
|
||||
|
||||
@ -162,7 +156,7 @@ void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_display_disable);
|
||||
|
||||
int sdi_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init sdi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("SDI init\n");
|
||||
|
||||
@ -182,11 +176,58 @@ int sdi_init_display(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sdi_init(void)
|
||||
static void __init sdi_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i, r;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_SDI)
|
||||
continue;
|
||||
|
||||
r = sdi_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init omap_sdi_probe(struct platform_device *pdev)
|
||||
{
|
||||
sdi_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sdi_exit(void)
|
||||
static int __exit omap_sdi_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver omap_sdi_driver = {
|
||||
.remove = __exit_p(omap_sdi_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_sdi",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
int __init sdi_init_platform_driver(void)
|
||||
{
|
||||
return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe);
|
||||
}
|
||||
|
||||
void __exit sdi_uninit_platform_driver(void)
|
||||
{
|
||||
platform_driver_unregister(&omap_sdi_driver);
|
||||
}
|
||||
|
@ -96,7 +96,9 @@ struct ti_hdmi_ip_ops {
|
||||
|
||||
void (*pll_disable)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
void (*video_enable)(struct hdmi_ip_data *ip_data, bool start);
|
||||
int (*video_enable)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
void (*video_disable)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
void (*dump_wrapper)(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
|
||||
@ -106,9 +108,17 @@ struct ti_hdmi_ip_ops {
|
||||
|
||||
void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start);
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
int (*audio_enable)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
void (*audio_disable)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
int (*audio_start)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
void (*audio_stop)(struct hdmi_ip_data *ip_data);
|
||||
|
||||
int (*audio_config)(struct hdmi_ip_data *ip_data,
|
||||
struct omap_dss_audio *audio);
|
||||
#endif
|
||||
|
||||
};
|
||||
@ -173,7 +183,8 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_phy_disable(struct hdmi_ip_data *ip_data);
|
||||
int ti_hdmi_4xxx_read_edid(struct hdmi_ip_data *ip_data, u8 *edid, int len);
|
||||
bool ti_hdmi_4xxx_detect(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start);
|
||||
int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data);
|
||||
int ti_hdmi_4xxx_pll_enable(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_pll_disable(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_basic_configure(struct hdmi_ip_data *ip_data);
|
||||
@ -181,8 +192,13 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable);
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts);
|
||||
int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data);
|
||||
int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data);
|
||||
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data);
|
||||
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
|
||||
struct omap_dss_audio *audio);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -29,9 +29,14 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/gpio.h>
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
#include <sound/asound.h>
|
||||
#include <sound/asoundef.h>
|
||||
#endif
|
||||
|
||||
#include "ti_hdmi_4xxx_ip.h"
|
||||
#include "dss.h"
|
||||
#include "dss_features.h"
|
||||
|
||||
static inline void hdmi_write_reg(void __iomem *base_addr,
|
||||
const u16 idx, u32 val)
|
||||
@ -298,9 +303,9 @@ int ti_hdmi_4xxx_phy_enable(struct hdmi_ip_data *ip_data)
|
||||
REG_FLD_MOD(phy_base, HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
|
||||
|
||||
r = request_threaded_irq(gpio_to_irq(ip_data->hpd_gpio),
|
||||
NULL, hpd_irq_handler,
|
||||
IRQF_DISABLED | IRQF_TRIGGER_RISING |
|
||||
IRQF_TRIGGER_FALLING, "hpd", ip_data);
|
||||
NULL, hpd_irq_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
|
||||
IRQF_ONESHOT, "hpd", ip_data);
|
||||
if (r) {
|
||||
DSSERR("HPD IRQ request failed\n");
|
||||
hdmi_set_phy_pwr(ip_data, HDMI_PHYPWRCMD_OFF);
|
||||
@ -699,9 +704,15 @@ static void hdmi_wp_init(struct omap_video_timings *timings,
|
||||
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data, bool start)
|
||||
int ti_hdmi_4xxx_wp_video_start(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, start, 31, 31);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, true, 31, 31);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_wp_video_stop(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, false, 31, 31);
|
||||
}
|
||||
|
||||
static void hdmi_wp_video_init_format(struct hdmi_video_format *video_fmt,
|
||||
@ -886,10 +897,12 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
|
||||
#define CORE_REG(i, name) name(i)
|
||||
#define DUMPCORE(r) seq_printf(s, "%-35s %08x\n", #r,\
|
||||
hdmi_read_reg(hdmi_pll_base(ip_data), r))
|
||||
#define DUMPCOREAV(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
|
||||
hdmi_read_reg(hdmi_core_sys_base(ip_data), r))
|
||||
#define DUMPCOREAV(r) seq_printf(s, "%-35s %08x\n", #r,\
|
||||
hdmi_read_reg(hdmi_av_base(ip_data), r))
|
||||
#define DUMPCOREAV2(i, r) seq_printf(s, "%s[%d]%*s %08x\n", #r, i, \
|
||||
(i < 10) ? 32 - strlen(#r) : 31 - strlen(#r), " ", \
|
||||
hdmi_read_reg(hdmi_pll_base(ip_data), CORE_REG(i, r)))
|
||||
hdmi_read_reg(hdmi_av_base(ip_data), CORE_REG(i, r)))
|
||||
|
||||
DUMPCORE(HDMI_CORE_SYS_VND_IDL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DEV_IDL);
|
||||
@ -898,6 +911,13 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
DUMPCORE(HDMI_CORE_SYS_SRST);
|
||||
DUMPCORE(HDMI_CORE_CTRL1);
|
||||
DUMPCORE(HDMI_CORE_SYS_SYS_STAT);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_DLY);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_TOP);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_LINL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
|
||||
DUMPCORE(HDMI_CORE_SYS_VID_ACEN);
|
||||
DUMPCORE(HDMI_CORE_SYS_VID_MODE);
|
||||
DUMPCORE(HDMI_CORE_SYS_INTR_STATE);
|
||||
@ -907,102 +927,91 @@ void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
DUMPCORE(HDMI_CORE_SYS_INTR4);
|
||||
DUMPCORE(HDMI_CORE_SYS_UMASK1);
|
||||
DUMPCORE(HDMI_CORE_SYS_TMDS_CTRL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_DLY);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CTRL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_TOP);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CNTL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_CNTH);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_LINL);
|
||||
DUMPCORE(HDMI_CORE_SYS_DE_LINH_1);
|
||||
|
||||
DUMPCORE(HDMI_CORE_DDC_CMD);
|
||||
DUMPCORE(HDMI_CORE_DDC_STATUS);
|
||||
DUMPCORE(HDMI_CORE_DDC_ADDR);
|
||||
DUMPCORE(HDMI_CORE_DDC_SEGM);
|
||||
DUMPCORE(HDMI_CORE_DDC_OFFSET);
|
||||
DUMPCORE(HDMI_CORE_DDC_COUNT1);
|
||||
DUMPCORE(HDMI_CORE_DDC_COUNT2);
|
||||
DUMPCORE(HDMI_CORE_DDC_STATUS);
|
||||
DUMPCORE(HDMI_CORE_DDC_CMD);
|
||||
DUMPCORE(HDMI_CORE_DDC_DATA);
|
||||
DUMPCORE(HDMI_CORE_DDC_SEGM);
|
||||
|
||||
DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_DPD);
|
||||
DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
|
||||
DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_VERS);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
|
||||
DUMPCOREAV(HDMI_CORE_AV_ACR_CTRL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_FREQ_SVAL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_N_SVAL1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_N_SVAL2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_N_SVAL3);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_SVAL3);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CTS_HVAL3);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUD_MODE);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPDIF_CTRL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_HW_SPDIF_FS);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SWAP_I2S);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPDIF_ERTH);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_IN_MAP);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_IN_CTRL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_CHST0);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_CHST1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_CHST2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_CHST4);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_CHST5);
|
||||
DUMPCOREAV(HDMI_CORE_AV_ASRC);
|
||||
DUMPCOREAV(HDMI_CORE_AV_I2S_IN_LEN);
|
||||
DUMPCOREAV(HDMI_CORE_AV_HDMI_CTRL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUDO_TXSTAT);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
|
||||
DUMPCOREAV(HDMI_CORE_AV_TEST_TXCTRL);
|
||||
DUMPCOREAV(HDMI_CORE_AV_DPD);
|
||||
DUMPCOREAV(HDMI_CORE_AV_PB_CTRL1);
|
||||
DUMPCOREAV(HDMI_CORE_AV_PB_CTRL2);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AVI_TYPE);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AVI_VERS);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AVI_LEN);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AVI_CHSUM);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_AVI_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_AVI_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_AVI_DBYTE);
|
||||
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPD_TYPE);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPD_VERS);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPD_LEN);
|
||||
DUMPCOREAV(HDMI_CORE_AV_SPD_CHSUM);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_SPD_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_SPD_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_SPD_DBYTE);
|
||||
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUDIO_TYPE);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUDIO_VERS);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUDIO_LEN);
|
||||
DUMPCOREAV(HDMI_CORE_AV_AUDIO_CHSUM);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_AUD_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_AUD_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_AUD_DBYTE);
|
||||
|
||||
DUMPCOREAV(HDMI_CORE_AV_MPEG_TYPE);
|
||||
DUMPCOREAV(HDMI_CORE_AV_MPEG_VERS);
|
||||
DUMPCOREAV(HDMI_CORE_AV_MPEG_LEN);
|
||||
DUMPCOREAV(HDMI_CORE_AV_MPEG_CHSUM);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_MPEG_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_MPEG_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_MPEG_DBYTE);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_GEN_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_GEN_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_GEN_DBYTE);
|
||||
|
||||
DUMPCOREAV(HDMI_CORE_AV_CP_BYTE1);
|
||||
|
||||
for (i = 0; i < HDMI_CORE_AV_GEN2_DBYTE_NELEMS; i++)
|
||||
DUMPCOREAV(i, HDMI_CORE_AV_GEN2_DBYTE);
|
||||
DUMPCOREAV2(i, HDMI_CORE_AV_GEN2_DBYTE);
|
||||
|
||||
DUMPCORE(HDMI_CORE_AV_ACR_CTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_FREQ_SVAL);
|
||||
DUMPCORE(HDMI_CORE_AV_N_SVAL1);
|
||||
DUMPCORE(HDMI_CORE_AV_N_SVAL2);
|
||||
DUMPCORE(HDMI_CORE_AV_N_SVAL3);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_SVAL1);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_SVAL2);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_SVAL3);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_HVAL1);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_HVAL2);
|
||||
DUMPCORE(HDMI_CORE_AV_CTS_HVAL3);
|
||||
DUMPCORE(HDMI_CORE_AV_AUD_MODE);
|
||||
DUMPCORE(HDMI_CORE_AV_SPDIF_CTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_HW_SPDIF_FS);
|
||||
DUMPCORE(HDMI_CORE_AV_SWAP_I2S);
|
||||
DUMPCORE(HDMI_CORE_AV_SPDIF_ERTH);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_IN_MAP);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_IN_CTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_CHST0);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_CHST1);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_CHST2);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_CHST4);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_CHST5);
|
||||
DUMPCORE(HDMI_CORE_AV_ASRC);
|
||||
DUMPCORE(HDMI_CORE_AV_I2S_IN_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_HDMI_CTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_AUDO_TXSTAT);
|
||||
DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_1);
|
||||
DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_2);
|
||||
DUMPCORE(HDMI_CORE_AV_AUD_PAR_BUSCLK_3);
|
||||
DUMPCORE(HDMI_CORE_AV_TEST_TXCTRL);
|
||||
DUMPCORE(HDMI_CORE_AV_DPD);
|
||||
DUMPCORE(HDMI_CORE_AV_PB_CTRL1);
|
||||
DUMPCORE(HDMI_CORE_AV_PB_CTRL2);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_TYPE);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_VERS);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_AVI_CHSUM);
|
||||
DUMPCORE(HDMI_CORE_AV_SPD_TYPE);
|
||||
DUMPCORE(HDMI_CORE_AV_SPD_VERS);
|
||||
DUMPCORE(HDMI_CORE_AV_SPD_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_SPD_CHSUM);
|
||||
DUMPCORE(HDMI_CORE_AV_AUDIO_TYPE);
|
||||
DUMPCORE(HDMI_CORE_AV_AUDIO_VERS);
|
||||
DUMPCORE(HDMI_CORE_AV_AUDIO_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_AUDIO_CHSUM);
|
||||
DUMPCORE(HDMI_CORE_AV_MPEG_TYPE);
|
||||
DUMPCORE(HDMI_CORE_AV_MPEG_VERS);
|
||||
DUMPCORE(HDMI_CORE_AV_MPEG_LEN);
|
||||
DUMPCORE(HDMI_CORE_AV_MPEG_CHSUM);
|
||||
DUMPCORE(HDMI_CORE_AV_CP_BYTE1);
|
||||
DUMPCORE(HDMI_CORE_AV_CEC_ADDR_ID);
|
||||
DUMPCOREAV(HDMI_CORE_AV_CEC_ADDR_ID);
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
@ -1016,9 +1025,8 @@ void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s)
|
||||
DUMPPHY(HDMI_TXPHY_PAD_CFG_CTRL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
|
||||
#if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO)
|
||||
static void ti_hdmi_4xxx_wp_audio_config_format(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_audio_format *aud_fmt)
|
||||
{
|
||||
u32 r;
|
||||
@ -1037,7 +1045,7 @@ void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
|
||||
hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CFG, r);
|
||||
}
|
||||
|
||||
void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
|
||||
static void ti_hdmi_4xxx_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_audio_dma *aud_dma)
|
||||
{
|
||||
u32 r;
|
||||
@ -1055,7 +1063,7 @@ void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
|
||||
hdmi_write_reg(hdmi_wp_base(ip_data), HDMI_WP_AUDIO_CTRL, r);
|
||||
}
|
||||
|
||||
void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
|
||||
static void ti_hdmi_4xxx_core_audio_config(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_core_audio_config *cfg)
|
||||
{
|
||||
u32 r;
|
||||
@ -1106,27 +1114,33 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
|
||||
REG_FLD_MOD(av_base, HDMI_CORE_AV_SPDIF_CTRL,
|
||||
cfg->fs_override, 1, 1);
|
||||
|
||||
/* I2S parameters */
|
||||
REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_CHST4,
|
||||
cfg->freq_sample, 3, 0);
|
||||
/*
|
||||
* Set IEC-60958-3 channel status word. It is passed to the IP
|
||||
* just as it is received. The user of the driver is responsible
|
||||
* for its contents.
|
||||
*/
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST0,
|
||||
cfg->iec60958_cfg->status[0]);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST1,
|
||||
cfg->iec60958_cfg->status[1]);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST2,
|
||||
cfg->iec60958_cfg->status[2]);
|
||||
/* yes, this is correct: status[3] goes to CHST4 register */
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST4,
|
||||
cfg->iec60958_cfg->status[3]);
|
||||
/* yes, this is correct: status[4] goes to CHST5 register */
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_CHST5,
|
||||
cfg->iec60958_cfg->status[4]);
|
||||
|
||||
/* set I2S parameters */
|
||||
r = hdmi_read_reg(av_base, 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(av_base, HDMI_CORE_AV_I2S_IN_CTRL, r);
|
||||
|
||||
r = hdmi_read_reg(av_base, 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(av_base, HDMI_CORE_AV_I2S_CHST5, r);
|
||||
|
||||
REG_FLD_MOD(av_base, HDMI_CORE_AV_I2S_IN_LEN,
|
||||
cfg->i2s_cfg.in_length_bits, 3, 0);
|
||||
|
||||
@ -1138,12 +1152,19 @@ void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
|
||||
r = FLD_MOD(r, cfg->en_parallel_aud_input, 2, 2);
|
||||
r = FLD_MOD(r, cfg->en_spdif, 1, 1);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_MODE, r);
|
||||
|
||||
/* Audio channel mappings */
|
||||
/* TODO: Make channel mapping dynamic. For now, map channels
|
||||
* in the ALSA order: FL/FR/RL/RR/C/LFE/SL/SR. Remapping is needed as
|
||||
* HDMI speaker order is different. See CEA-861 Section 6.6.2.
|
||||
*/
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_I2S_IN_MAP, 0x78);
|
||||
REG_FLD_MOD(av_base, HDMI_CORE_AV_SWAP_I2S, 1, 5, 5);
|
||||
}
|
||||
|
||||
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_core_infoframe_audio *info_aud)
|
||||
static void ti_hdmi_4xxx_core_audio_infoframe_cfg(struct hdmi_ip_data *ip_data,
|
||||
struct snd_cea_861_aud_if *info_aud)
|
||||
{
|
||||
u8 val;
|
||||
u8 sum = 0, checksum = 0;
|
||||
void __iomem *av_base = hdmi_av_base(ip_data);
|
||||
|
||||
@ -1157,24 +1178,23 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
|
||||
hdmi_write_reg(av_base, 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(av_base, HDMI_CORE_AV_AUD_DBYTE(0), val);
|
||||
sum += val;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(0),
|
||||
info_aud->db1_ct_cc);
|
||||
sum += info_aud->db1_ct_cc;
|
||||
|
||||
val = (info_aud->db2_sample_freq << 2) | info_aud->db2_sample_size;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1), val);
|
||||
sum += val;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(1),
|
||||
info_aud->db2_sf_ss);
|
||||
sum += info_aud->db2_sf_ss;
|
||||
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), 0x00);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(2), info_aud->db3);
|
||||
sum += info_aud->db3;
|
||||
|
||||
val = info_aud->db4_channel_alloc;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), val);
|
||||
sum += val;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(3), info_aud->db4_ca);
|
||||
sum += info_aud->db4_ca;
|
||||
|
||||
val = (info_aud->db5_downmix_inh << 7) | (info_aud->db5_lsv << 3);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4), val);
|
||||
sum += val;
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(4),
|
||||
info_aud->db5_dminh_lsv);
|
||||
sum += info_aud->db5_dminh_lsv;
|
||||
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(5), 0x00);
|
||||
hdmi_write_reg(av_base, HDMI_CORE_AV_AUD_DBYTE(6), 0x00);
|
||||
@ -1192,70 +1212,212 @@ void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
|
||||
*/
|
||||
}
|
||||
|
||||
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
|
||||
u32 sample_freq, u32 *n, u32 *cts)
|
||||
int ti_hdmi_4xxx_audio_config(struct hdmi_ip_data *ip_data,
|
||||
struct omap_dss_audio *audio)
|
||||
{
|
||||
u32 r;
|
||||
u32 deep_color = 0;
|
||||
u32 pclk = ip_data->cfg.timings.pixel_clock;
|
||||
struct hdmi_audio_format audio_format;
|
||||
struct hdmi_audio_dma audio_dma;
|
||||
struct hdmi_core_audio_config core;
|
||||
int err, n, cts, channel_count;
|
||||
unsigned int fs_nr;
|
||||
bool word_length_16b = false;
|
||||
|
||||
if (n == NULL || cts == NULL)
|
||||
if (!audio || !audio->iec || !audio->cea || !ip_data)
|
||||
return -EINVAL;
|
||||
|
||||
core.iec60958_cfg = audio->iec;
|
||||
/*
|
||||
* Obtain current deep color configuration. This needed
|
||||
* to calculate the TMDS clock based on the pixel clock.
|
||||
* In the IEC-60958 status word, check if the audio sample word length
|
||||
* is 16-bit as several optimizations can be performed in such case.
|
||||
*/
|
||||
r = REG_GET(hdmi_wp_base(ip_data), HDMI_WP_VIDEO_CFG, 1, 0);
|
||||
switch (r) {
|
||||
case 1: /* No deep color selected */
|
||||
deep_color = 100;
|
||||
if (!(audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24))
|
||||
if (audio->iec->status[4] & IEC958_AES4_CON_WORDLEN_20_16)
|
||||
word_length_16b = true;
|
||||
|
||||
/* I2S configuration. See Phillips' specification */
|
||||
if (word_length_16b)
|
||||
core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_LEFT;
|
||||
else
|
||||
core.i2s_cfg.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
|
||||
/*
|
||||
* The I2S input word length is twice the lenght given in the IEC-60958
|
||||
* status word. If the word size is greater than
|
||||
* 20 bits, increment by one.
|
||||
*/
|
||||
core.i2s_cfg.in_length_bits = audio->iec->status[4]
|
||||
& IEC958_AES4_CON_WORDLEN;
|
||||
if (audio->iec->status[4] & IEC958_AES4_CON_MAX_WORDLEN_24)
|
||||
core.i2s_cfg.in_length_bits++;
|
||||
core.i2s_cfg.sck_edge_mode = HDMI_AUDIO_I2S_SCK_EDGE_RISING;
|
||||
core.i2s_cfg.vbit = HDMI_AUDIO_I2S_VBIT_FOR_PCM;
|
||||
core.i2s_cfg.direction = HDMI_AUDIO_I2S_MSB_SHIFTED_FIRST;
|
||||
core.i2s_cfg.shift = HDMI_AUDIO_I2S_FIRST_BIT_SHIFT;
|
||||
|
||||
/* convert sample frequency to a number */
|
||||
switch (audio->iec->status[3] & IEC958_AES3_CON_FS) {
|
||||
case IEC958_AES3_CON_FS_32000:
|
||||
fs_nr = 32000;
|
||||
break;
|
||||
case 2: /* 10-bit deep color selected */
|
||||
deep_color = 125;
|
||||
case IEC958_AES3_CON_FS_44100:
|
||||
fs_nr = 44100;
|
||||
break;
|
||||
case 3: /* 12-bit deep color selected */
|
||||
deep_color = 150;
|
||||
case IEC958_AES3_CON_FS_48000:
|
||||
fs_nr = 48000;
|
||||
break;
|
||||
case IEC958_AES3_CON_FS_88200:
|
||||
fs_nr = 88200;
|
||||
break;
|
||||
case IEC958_AES3_CON_FS_96000:
|
||||
fs_nr = 96000;
|
||||
break;
|
||||
case IEC958_AES3_CON_FS_176400:
|
||||
fs_nr = 176400;
|
||||
break;
|
||||
case IEC958_AES3_CON_FS_192000:
|
||||
fs_nr = 192000;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (sample_freq) {
|
||||
case 32000:
|
||||
if ((deep_color == 125) && ((pclk == 54054)
|
||||
|| (pclk == 74250)))
|
||||
*n = 8192;
|
||||
else
|
||||
*n = 4096;
|
||||
err = hdmi_compute_acr(fs_nr, &n, &cts);
|
||||
|
||||
/* Audio clock regeneration settings */
|
||||
core.n = n;
|
||||
core.cts = cts;
|
||||
if (dss_has_feature(FEAT_HDMI_CTS_SWMODE)) {
|
||||
core.aud_par_busclk = 0;
|
||||
core.cts_mode = HDMI_AUDIO_CTS_MODE_SW;
|
||||
core.use_mclk = dss_has_feature(FEAT_HDMI_AUDIO_USE_MCLK);
|
||||
} else {
|
||||
core.aud_par_busclk = (((128 * 31) - 1) << 8);
|
||||
core.cts_mode = HDMI_AUDIO_CTS_MODE_HW;
|
||||
core.use_mclk = true;
|
||||
}
|
||||
|
||||
if (core.use_mclk)
|
||||
core.mclk_mode = HDMI_AUDIO_MCLK_128FS;
|
||||
|
||||
/* Audio channels settings */
|
||||
channel_count = (audio->cea->db1_ct_cc &
|
||||
CEA861_AUDIO_INFOFRAME_DB1CC) + 1;
|
||||
|
||||
switch (channel_count) {
|
||||
case 2:
|
||||
audio_format.active_chnnls_msk = 0x03;
|
||||
break;
|
||||
case 44100:
|
||||
*n = 6272;
|
||||
case 3:
|
||||
audio_format.active_chnnls_msk = 0x07;
|
||||
break;
|
||||
case 48000:
|
||||
if ((deep_color == 125) && ((pclk == 54054)
|
||||
|| (pclk == 74250)))
|
||||
*n = 8192;
|
||||
else
|
||||
*n = 6144;
|
||||
case 4:
|
||||
audio_format.active_chnnls_msk = 0x0f;
|
||||
break;
|
||||
case 5:
|
||||
audio_format.active_chnnls_msk = 0x1f;
|
||||
break;
|
||||
case 6:
|
||||
audio_format.active_chnnls_msk = 0x3f;
|
||||
break;
|
||||
case 7:
|
||||
audio_format.active_chnnls_msk = 0x7f;
|
||||
break;
|
||||
case 8:
|
||||
audio_format.active_chnnls_msk = 0xff;
|
||||
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);
|
||||
/*
|
||||
* the HDMI IP needs to enable four stereo channels when transmitting
|
||||
* more than 2 audio channels
|
||||
*/
|
||||
if (channel_count == 2) {
|
||||
audio_format.stereo_channels = HDMI_AUDIO_STEREO_ONECHANNEL;
|
||||
core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN;
|
||||
core.layout = HDMI_AUDIO_LAYOUT_2CH;
|
||||
} else {
|
||||
audio_format.stereo_channels = HDMI_AUDIO_STEREO_FOURCHANNELS;
|
||||
core.i2s_cfg.active_sds = HDMI_AUDIO_I2S_SD0_EN |
|
||||
HDMI_AUDIO_I2S_SD1_EN | HDMI_AUDIO_I2S_SD2_EN |
|
||||
HDMI_AUDIO_I2S_SD3_EN;
|
||||
core.layout = HDMI_AUDIO_LAYOUT_8CH;
|
||||
}
|
||||
|
||||
core.en_spdif = false;
|
||||
/* use sample frequency from channel status word */
|
||||
core.fs_override = true;
|
||||
/* enable ACR packets */
|
||||
core.en_acr_pkt = true;
|
||||
/* disable direct streaming digital audio */
|
||||
core.en_dsd_audio = false;
|
||||
/* use parallel audio interface */
|
||||
core.en_parallel_aud_input = true;
|
||||
|
||||
/* DMA settings */
|
||||
if (word_length_16b)
|
||||
audio_dma.transfer_size = 0x10;
|
||||
else
|
||||
audio_dma.transfer_size = 0x20;
|
||||
audio_dma.block_size = 0xC0;
|
||||
audio_dma.mode = HDMI_AUDIO_TRANSF_DMA;
|
||||
audio_dma.fifo_threshold = 0x20; /* in number of samples */
|
||||
|
||||
/* audio FIFO format settings */
|
||||
if (word_length_16b) {
|
||||
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_TWOSAMPLES;
|
||||
audio_format.sample_size = HDMI_AUDIO_SAMPLE_16BITS;
|
||||
audio_format.justification = HDMI_AUDIO_JUSTIFY_LEFT;
|
||||
} else {
|
||||
audio_format.samples_per_word = HDMI_AUDIO_ONEWORD_ONESAMPLE;
|
||||
audio_format.sample_size = HDMI_AUDIO_SAMPLE_24BITS;
|
||||
audio_format.justification = HDMI_AUDIO_JUSTIFY_RIGHT;
|
||||
}
|
||||
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_ON;
|
||||
|
||||
/* configure DMA and audio FIFO format*/
|
||||
ti_hdmi_4xxx_wp_audio_config_dma(ip_data, &audio_dma);
|
||||
ti_hdmi_4xxx_wp_audio_config_format(ip_data, &audio_format);
|
||||
|
||||
/* configure the core*/
|
||||
ti_hdmi_4xxx_core_audio_config(ip_data, &core);
|
||||
|
||||
/* configure CEA 861 audio infoframe*/
|
||||
ti_hdmi_4xxx_core_audio_infoframe_cfg(ip_data, audio->cea);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable)
|
||||
int ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, true, 31, 31);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_wp_audio_disable(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, false, 31, 31);
|
||||
}
|
||||
|
||||
int ti_hdmi_4xxx_audio_start(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_av_base(ip_data),
|
||||
HDMI_CORE_AV_AUD_MODE, enable, 0, 0);
|
||||
HDMI_CORE_AV_AUD_MODE, true, 0, 0);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, enable, 31, 31);
|
||||
HDMI_WP_AUDIO_CTRL, true, 30, 30);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ti_hdmi_4xxx_audio_stop(struct hdmi_ip_data *ip_data)
|
||||
{
|
||||
REG_FLD_MOD(hdmi_av_base(ip_data),
|
||||
HDMI_CORE_AV_AUD_MODE, false, 0, 0);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, enable, 30, 30);
|
||||
HDMI_WP_AUDIO_CTRL, false, 30, 30);
|
||||
}
|
||||
#endif
|
||||
|
@ -24,11 +24,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <video/omapdss.h>
|
||||
#include "ti_hdmi.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
|
||||
|
||||
/* HDMI Wrapper */
|
||||
|
||||
@ -57,6 +52,13 @@
|
||||
#define HDMI_CORE_SYS_SRST 0x14
|
||||
#define HDMI_CORE_CTRL1 0x20
|
||||
#define HDMI_CORE_SYS_SYS_STAT 0x24
|
||||
#define HDMI_CORE_SYS_DE_DLY 0xC8
|
||||
#define HDMI_CORE_SYS_DE_CTRL 0xCC
|
||||
#define HDMI_CORE_SYS_DE_TOP 0xD0
|
||||
#define HDMI_CORE_SYS_DE_CNTL 0xD8
|
||||
#define HDMI_CORE_SYS_DE_CNTH 0xDC
|
||||
#define HDMI_CORE_SYS_DE_LINL 0xE0
|
||||
#define HDMI_CORE_SYS_DE_LINH_1 0xE4
|
||||
#define HDMI_CORE_SYS_VID_ACEN 0x124
|
||||
#define HDMI_CORE_SYS_VID_MODE 0x128
|
||||
#define HDMI_CORE_SYS_INTR_STATE 0x1C0
|
||||
@ -66,50 +68,24 @@
|
||||
#define HDMI_CORE_SYS_INTR4 0x1D0
|
||||
#define HDMI_CORE_SYS_UMASK1 0x1D4
|
||||
#define HDMI_CORE_SYS_TMDS_CTRL 0x208
|
||||
#define HDMI_CORE_SYS_DE_DLY 0xC8
|
||||
#define HDMI_CORE_SYS_DE_CTRL 0xCC
|
||||
#define HDMI_CORE_SYS_DE_TOP 0xD0
|
||||
#define HDMI_CORE_SYS_DE_CNTL 0xD8
|
||||
#define HDMI_CORE_SYS_DE_CNTH 0xDC
|
||||
#define HDMI_CORE_SYS_DE_LINL 0xE0
|
||||
#define HDMI_CORE_SYS_DE_LINH_1 0xE4
|
||||
|
||||
#define HDMI_CORE_CTRL1_VEN_FOLLOWVSYNC 0x1
|
||||
#define HDMI_CORE_CTRL1_HEN_FOLLOWHSYNC 0x1
|
||||
#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
|
||||
#define HDMI_CORE_CTRL1_BSEL_24BITBUS 0x1
|
||||
#define HDMI_CORE_CTRL1_EDGE_RISINGEDGE 0x1
|
||||
|
||||
/* HDMI DDC E-DID */
|
||||
#define HDMI_CORE_DDC_CMD 0x3CC
|
||||
#define HDMI_CORE_DDC_STATUS 0x3C8
|
||||
#define HDMI_CORE_DDC_ADDR 0x3B4
|
||||
#define HDMI_CORE_DDC_SEGM 0x3B8
|
||||
#define HDMI_CORE_DDC_OFFSET 0x3BC
|
||||
#define HDMI_CORE_DDC_COUNT1 0x3C0
|
||||
#define HDMI_CORE_DDC_COUNT2 0x3C4
|
||||
#define HDMI_CORE_DDC_STATUS 0x3C8
|
||||
#define HDMI_CORE_DDC_CMD 0x3CC
|
||||
#define HDMI_CORE_DDC_DATA 0x3D0
|
||||
#define HDMI_CORE_DDC_SEGM 0x3B8
|
||||
|
||||
/* HDMI IP Core Audio Video */
|
||||
|
||||
#define HDMI_CORE_AV_HDMI_CTRL 0xBC
|
||||
#define HDMI_CORE_AV_DPD 0xF4
|
||||
#define HDMI_CORE_AV_PB_CTRL1 0xF8
|
||||
#define HDMI_CORE_AV_PB_CTRL2 0xFC
|
||||
#define HDMI_CORE_AV_AVI_TYPE 0x100
|
||||
#define HDMI_CORE_AV_AVI_VERS 0x104
|
||||
#define HDMI_CORE_AV_AVI_LEN 0x108
|
||||
#define HDMI_CORE_AV_AVI_CHSUM 0x10C
|
||||
#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
|
||||
#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
|
||||
#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
|
||||
#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
|
||||
#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
|
||||
#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
|
||||
#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
|
||||
#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
|
||||
#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
|
||||
#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
|
||||
#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
|
||||
#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
|
||||
#define HDMI_CORE_AV_ACR_CTRL 0x4
|
||||
#define HDMI_CORE_AV_FREQ_SVAL 0x8
|
||||
#define HDMI_CORE_AV_N_SVAL1 0xC
|
||||
@ -148,25 +124,39 @@
|
||||
#define HDMI_CORE_AV_AVI_VERS 0x104
|
||||
#define HDMI_CORE_AV_AVI_LEN 0x108
|
||||
#define HDMI_CORE_AV_AVI_CHSUM 0x10C
|
||||
#define HDMI_CORE_AV_AVI_DBYTE(n) (n * 4 + 0x110)
|
||||
#define HDMI_CORE_AV_SPD_TYPE 0x180
|
||||
#define HDMI_CORE_AV_SPD_VERS 0x184
|
||||
#define HDMI_CORE_AV_SPD_LEN 0x188
|
||||
#define HDMI_CORE_AV_SPD_CHSUM 0x18C
|
||||
#define HDMI_CORE_AV_SPD_DBYTE(n) (n * 4 + 0x190)
|
||||
#define HDMI_CORE_AV_AUDIO_TYPE 0x200
|
||||
#define HDMI_CORE_AV_AUDIO_VERS 0x204
|
||||
#define HDMI_CORE_AV_AUDIO_LEN 0x208
|
||||
#define HDMI_CORE_AV_AUDIO_CHSUM 0x20C
|
||||
#define HDMI_CORE_AV_AUD_DBYTE(n) (n * 4 + 0x210)
|
||||
#define HDMI_CORE_AV_MPEG_TYPE 0x280
|
||||
#define HDMI_CORE_AV_MPEG_VERS 0x284
|
||||
#define HDMI_CORE_AV_MPEG_LEN 0x288
|
||||
#define HDMI_CORE_AV_MPEG_CHSUM 0x28C
|
||||
#define HDMI_CORE_AV_MPEG_DBYTE(n) (n * 4 + 0x290)
|
||||
#define HDMI_CORE_AV_GEN_DBYTE(n) (n * 4 + 0x300)
|
||||
#define HDMI_CORE_AV_CP_BYTE1 0x37C
|
||||
#define HDMI_CORE_AV_GEN2_DBYTE(n) (n * 4 + 0x380)
|
||||
#define HDMI_CORE_AV_CEC_ADDR_ID 0x3FC
|
||||
|
||||
#define HDMI_CORE_AV_SPD_DBYTE_ELSIZE 0x4
|
||||
#define HDMI_CORE_AV_GEN2_DBYTE_ELSIZE 0x4
|
||||
#define HDMI_CORE_AV_MPEG_DBYTE_ELSIZE 0x4
|
||||
#define HDMI_CORE_AV_GEN_DBYTE_ELSIZE 0x4
|
||||
|
||||
#define HDMI_CORE_AV_AVI_DBYTE_NELEMS 15
|
||||
#define HDMI_CORE_AV_SPD_DBYTE_NELEMS 27
|
||||
#define HDMI_CORE_AV_AUD_DBYTE_NELEMS 10
|
||||
#define HDMI_CORE_AV_MPEG_DBYTE_NELEMS 27
|
||||
#define HDMI_CORE_AV_GEN_DBYTE_NELEMS 31
|
||||
#define HDMI_CORE_AV_GEN2_DBYTE_NELEMS 31
|
||||
|
||||
/* PLL */
|
||||
|
||||
#define PLLCTRL_PLL_CONTROL 0x0
|
||||
@ -284,35 +274,6 @@ enum hdmi_core_infoframe {
|
||||
HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
|
||||
HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
|
||||
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 {
|
||||
@ -322,17 +283,6 @@ 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
|
||||
@ -387,37 +337,12 @@ enum hdmi_audio_blk_strt_end_sig {
|
||||
};
|
||||
|
||||
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,
|
||||
@ -446,20 +371,6 @@ struct hdmi_core_video_config {
|
||||
enum hdmi_core_tclkselclkmult tclk_sel_clkmult;
|
||||
};
|
||||
|
||||
/*
|
||||
* 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;
|
||||
u32 audio_pkt_repeat;
|
||||
@ -496,15 +407,10 @@ struct hdmi_audio_dma {
|
||||
};
|
||||
|
||||
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;
|
||||
@ -512,7 +418,7 @@ struct hdmi_core_audio_i2s_config {
|
||||
|
||||
struct hdmi_core_audio_config {
|
||||
struct hdmi_core_audio_i2s_config i2s_cfg;
|
||||
enum hdmi_core_audio_sample_freq freq_sample;
|
||||
struct snd_aes_iec958 *iec60958_cfg;
|
||||
bool fs_override;
|
||||
u32 n;
|
||||
u32 cts;
|
||||
@ -527,17 +433,4 @@ struct hdmi_core_audio_config {
|
||||
bool en_spdif;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
|
||||
u32 sample_freq, u32 *n, u32 *cts);
|
||||
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_core_infoframe_audio *info_aud);
|
||||
void hdmi_core_audio_config(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_core_audio_config *cfg);
|
||||
void hdmi_wp_audio_config_dma(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_audio_dma *aud_dma);
|
||||
void hdmi_wp_audio_config_format(struct hdmi_ip_data *ip_data,
|
||||
struct hdmi_audio_format *aud_fmt);
|
||||
#endif
|
||||
#endif
|
||||
|
@ -415,6 +415,7 @@ static const struct venc_config *venc_timings_to_config(
|
||||
return &venc_config_ntsc_trm;
|
||||
|
||||
BUG();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int venc_power_on(struct omap_dss_device *dssdev)
|
||||
@ -440,10 +441,11 @@ static int venc_power_on(struct omap_dss_device *dssdev)
|
||||
|
||||
venc_write_reg(VENC_OUTPUT_CONTROL, l);
|
||||
|
||||
dispc_set_digit_size(dssdev->panel.timings.x_res,
|
||||
dssdev->panel.timings.y_res/2);
|
||||
dss_mgr_set_timings(dssdev->manager, &dssdev->panel.timings);
|
||||
|
||||
regulator_enable(venc.vdda_dac_reg);
|
||||
r = regulator_enable(venc.vdda_dac_reg);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
@ -485,16 +487,68 @@ unsigned long venc_get_pixel_clock(void)
|
||||
return 13500000;
|
||||
}
|
||||
|
||||
static ssize_t display_output_type_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
const char *ret;
|
||||
|
||||
switch (dssdev->phy.venc.type) {
|
||||
case OMAP_DSS_VENC_TYPE_COMPOSITE:
|
||||
ret = "composite";
|
||||
break;
|
||||
case OMAP_DSS_VENC_TYPE_SVIDEO:
|
||||
ret = "svideo";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", ret);
|
||||
}
|
||||
|
||||
static ssize_t display_output_type_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t size)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
enum omap_dss_venc_type new_type;
|
||||
|
||||
if (sysfs_streq("composite", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_COMPOSITE;
|
||||
else if (sysfs_streq("svideo", buf))
|
||||
new_type = OMAP_DSS_VENC_TYPE_SVIDEO;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
if (dssdev->phy.venc.type != new_type) {
|
||||
dssdev->phy.venc.type = new_type;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
venc_power_off(dssdev);
|
||||
venc_power_on(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(output_type, S_IRUGO | S_IWUSR,
|
||||
display_output_type_show, display_output_type_store);
|
||||
|
||||
/* driver */
|
||||
static int venc_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.timings = omap_dss_pal_timings;
|
||||
|
||||
return 0;
|
||||
return device_create_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static void venc_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_remove_file(&dssdev->dev, &dev_attr_output_type);
|
||||
}
|
||||
|
||||
static int venc_panel_enable(struct omap_dss_device *dssdev)
|
||||
@ -577,12 +631,6 @@ static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
static void venc_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static void venc_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
@ -597,6 +645,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
|
||||
/* turn the venc off and on to get new timings to use */
|
||||
venc_panel_disable(dssdev);
|
||||
venc_panel_enable(dssdev);
|
||||
} else {
|
||||
dss_mgr_set_timings(dssdev->manager, timings);
|
||||
}
|
||||
}
|
||||
|
||||
@ -661,7 +711,6 @@ static struct omap_dss_driver venc_driver = {
|
||||
.get_resolution = omapdss_default_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
||||
.get_timings = venc_get_timings,
|
||||
.set_timings = venc_set_timings,
|
||||
.check_timings = venc_check_timings,
|
||||
|
||||
@ -675,7 +724,7 @@ static struct omap_dss_driver venc_driver = {
|
||||
};
|
||||
/* driver end */
|
||||
|
||||
int venc_init_display(struct omap_dss_device *dssdev)
|
||||
static int __init venc_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
@ -695,7 +744,7 @@ int venc_init_display(struct omap_dss_device *dssdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void venc_dump_regs(struct seq_file *s)
|
||||
static void venc_dump_regs(struct seq_file *s)
|
||||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, venc_read_reg(r))
|
||||
|
||||
@ -779,8 +828,32 @@ static void venc_put_clocks(void)
|
||||
clk_put(venc.tv_dac_clk);
|
||||
}
|
||||
|
||||
static void __init venc_probe_pdata(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int r, i;
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
if (dssdev->type != OMAP_DISPLAY_TYPE_VENC)
|
||||
continue;
|
||||
|
||||
r = venc_init_display(dssdev);
|
||||
if (r) {
|
||||
DSSERR("device %s init failed: %d\n", dssdev->name, r);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = omap_dss_register_device(dssdev, &pdev->dev, i);
|
||||
if (r)
|
||||
DSSERR("device %s register failed: %d\n",
|
||||
dssdev->name, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* VENC HW IP initialisation */
|
||||
static int omap_venchw_probe(struct platform_device *pdev)
|
||||
static int __init omap_venchw_probe(struct platform_device *pdev)
|
||||
{
|
||||
u8 rev_id;
|
||||
struct resource *venc_mem;
|
||||
@ -824,6 +897,10 @@ static int omap_venchw_probe(struct platform_device *pdev)
|
||||
if (r)
|
||||
goto err_reg_panel_driver;
|
||||
|
||||
dss_debugfs_create_file("venc", venc_dump_regs);
|
||||
|
||||
venc_probe_pdata(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_reg_panel_driver:
|
||||
@ -833,12 +910,15 @@ err_runtime_get:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_venchw_remove(struct platform_device *pdev)
|
||||
static int __exit omap_venchw_remove(struct platform_device *pdev)
|
||||
{
|
||||
omap_dss_unregister_child_devices(&pdev->dev);
|
||||
|
||||
if (venc.vdda_dac_reg != NULL) {
|
||||
regulator_put(venc.vdda_dac_reg);
|
||||
venc.vdda_dac_reg = NULL;
|
||||
}
|
||||
|
||||
omap_dss_unregister_driver(&venc_driver);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
@ -853,7 +933,6 @@ static int venc_runtime_suspend(struct device *dev)
|
||||
clk_disable(venc.tv_dac_clk);
|
||||
|
||||
dispc_runtime_put();
|
||||
dss_runtime_put();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -862,23 +941,14 @@ static int venc_runtime_resume(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = dss_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dss;
|
||||
|
||||
r = dispc_runtime_get();
|
||||
if (r < 0)
|
||||
goto err_get_dispc;
|
||||
return r;
|
||||
|
||||
if (venc.tv_dac_clk)
|
||||
clk_enable(venc.tv_dac_clk);
|
||||
|
||||
return 0;
|
||||
|
||||
err_get_dispc:
|
||||
dss_runtime_put();
|
||||
err_get_dss:
|
||||
return r;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops venc_pm_ops = {
|
||||
@ -887,8 +957,7 @@ static const struct dev_pm_ops venc_pm_ops = {
|
||||
};
|
||||
|
||||
static struct platform_driver omap_venchw_driver = {
|
||||
.probe = omap_venchw_probe,
|
||||
.remove = omap_venchw_remove,
|
||||
.remove = __exit_p(omap_venchw_remove),
|
||||
.driver = {
|
||||
.name = "omapdss_venc",
|
||||
.owner = THIS_MODULE,
|
||||
@ -896,18 +965,18 @@ static struct platform_driver omap_venchw_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
int venc_init_platform_driver(void)
|
||||
int __init venc_init_platform_driver(void)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
return 0;
|
||||
|
||||
return platform_driver_register(&omap_venchw_driver);
|
||||
return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe);
|
||||
}
|
||||
|
||||
void venc_uninit_platform_driver(void)
|
||||
void __exit venc_uninit_platform_driver(void)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
return;
|
||||
|
||||
return platform_driver_unregister(&omap_venchw_driver);
|
||||
platform_driver_unregister(&omap_venchw_driver);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
||||
|
||||
DBG("omapfb_setup_plane\n");
|
||||
|
||||
if (ofbi->num_overlays != 1) {
|
||||
if (ofbi->num_overlays == 0) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -185,7 +185,7 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
|
||||
if (ofbi->num_overlays != 1) {
|
||||
if (ofbi->num_overlays == 0) {
|
||||
memset(pi, 0, sizeof(*pi));
|
||||
} else {
|
||||
struct omap_overlay *ovl;
|
||||
@ -225,6 +225,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
down_write_nested(&rg->lock, rg->id);
|
||||
atomic_inc(&rg->lock_count);
|
||||
|
||||
if (rg->size == size && rg->type == mi->type)
|
||||
goto out;
|
||||
|
||||
if (atomic_read(&rg->map_count)) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
@ -247,12 +250,10 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
||||
}
|
||||
}
|
||||
|
||||
if (rg->size != size || rg->type != mi->type) {
|
||||
r = omapfb_realloc_fbmem(fbi, size, mi->type);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "realloc fbmem failed\n");
|
||||
goto out;
|
||||
}
|
||||
r = omapfb_realloc_fbmem(fbi, size, mi->type);
|
||||
if (r) {
|
||||
dev_err(fbdev->dev, "realloc fbmem failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -179,6 +179,7 @@ static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset *= vrfb->bytespp;
|
||||
@ -1502,7 +1503,7 @@ static int omapfb_parse_vram_param(const char *param, int max_entries,
|
||||
|
||||
fbnum = simple_strtoul(p, &p, 10);
|
||||
|
||||
if (p == param)
|
||||
if (p == start)
|
||||
return -EINVAL;
|
||||
|
||||
if (*p != ':')
|
||||
@ -2307,7 +2308,7 @@ static int omapfb_init_display(struct omapfb2_device *fbdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omapfb_probe(struct platform_device *pdev)
|
||||
static int __init omapfb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omapfb2_device *fbdev = NULL;
|
||||
int r = 0;
|
||||
@ -2448,7 +2449,7 @@ err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omapfb_remove(struct platform_device *pdev)
|
||||
static int __exit omapfb_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct omapfb2_device *fbdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -2462,8 +2463,7 @@ static int omapfb_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
static struct platform_driver omapfb_driver = {
|
||||
.probe = omapfb_probe,
|
||||
.remove = omapfb_remove,
|
||||
.remove = __exit_p(omapfb_remove),
|
||||
.driver = {
|
||||
.name = "omapfb",
|
||||
.owner = THIS_MODULE,
|
||||
@ -2474,7 +2474,7 @@ static int __init omapfb_init(void)
|
||||
{
|
||||
DBG("omapfb_init\n");
|
||||
|
||||
if (platform_driver_register(&omapfb_driver)) {
|
||||
if (platform_driver_probe(&omapfb_driver, omapfb_probe)) {
|
||||
printk(KERN_ERR "failed to register omapfb driver\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ static inline struct omapfb_display_data *get_display_data(
|
||||
|
||||
/* This should never happen */
|
||||
BUG();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void omapfb_lock(struct omapfb2_device *fbdev)
|
||||
|
@ -179,8 +179,10 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
|
||||
pixel_size_exp = 2;
|
||||
else if (bytespp == 2)
|
||||
pixel_size_exp = 1;
|
||||
else
|
||||
else {
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
vrfb_width = ALIGN(width * bytespp, VRFB_PAGE_WIDTH) / bytespp;
|
||||
vrfb_height = ALIGN(height, VRFB_PAGE_HEIGHT);
|
||||
|
@ -316,12 +316,9 @@ pxa3xx_gcu_wait_idle(struct pxa3xx_gcu_priv *priv)
|
||||
ret = wait_event_interruptible_timeout(priv->wait_idle,
|
||||
!priv->shared->hw_running, HZ*4);
|
||||
|
||||
if (ret < 0)
|
||||
if (ret != 0)
|
||||
break;
|
||||
|
||||
if (ret > 0)
|
||||
continue;
|
||||
|
||||
if (gc_readl(priv, REG_GCRBEXHR) == rbexhr &&
|
||||
priv->shared->num_interrupts == num) {
|
||||
QERROR("TIMEOUT");
|
||||
|
@ -47,7 +47,7 @@
|
||||
#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
|
||||
#undef writel
|
||||
#define writel(v, r) do { \
|
||||
printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
|
||||
pr_debug("%s: %08x => %p\n", __func__, (unsigned int)v, r); \
|
||||
__raw_writel(v, r); \
|
||||
} while (0)
|
||||
#endif /* FB_S3C_DEBUG_REGWRITE */
|
||||
@ -495,7 +495,6 @@ static int s3c_fb_set_par(struct fb_info *info)
|
||||
u32 alpha = 0;
|
||||
u32 data;
|
||||
u32 pagewidth;
|
||||
int clkdiv;
|
||||
|
||||
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
|
||||
|
||||
@ -532,48 +531,9 @@ static int s3c_fb_set_par(struct fb_info *info)
|
||||
/* disable the window whilst we update it */
|
||||
writel(0, regs + WINCON(win_no));
|
||||
|
||||
/* use platform specified window as the basis for the lcd timings */
|
||||
|
||||
if (win_no == sfb->pdata->default_win) {
|
||||
clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
|
||||
|
||||
data = sfb->pdata->vidcon0;
|
||||
data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
|
||||
|
||||
if (clkdiv > 1)
|
||||
data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
|
||||
else
|
||||
data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
|
||||
|
||||
/* write the timing data to the panel */
|
||||
|
||||
if (sfb->variant.is_2443)
|
||||
data |= (1 << 5);
|
||||
|
||||
writel(data, regs + VIDCON0);
|
||||
|
||||
if (!sfb->output_on)
|
||||
s3c_fb_enable(sfb, 1);
|
||||
|
||||
data = VIDTCON0_VBPD(var->upper_margin - 1) |
|
||||
VIDTCON0_VFPD(var->lower_margin - 1) |
|
||||
VIDTCON0_VSPW(var->vsync_len - 1);
|
||||
|
||||
writel(data, regs + sfb->variant.vidtcon);
|
||||
|
||||
data = VIDTCON1_HBPD(var->left_margin - 1) |
|
||||
VIDTCON1_HFPD(var->right_margin - 1) |
|
||||
VIDTCON1_HSPW(var->hsync_len - 1);
|
||||
|
||||
/* VIDTCON1 */
|
||||
writel(data, regs + sfb->variant.vidtcon + 4);
|
||||
|
||||
data = VIDTCON2_LINEVAL(var->yres - 1) |
|
||||
VIDTCON2_HOZVAL(var->xres - 1) |
|
||||
VIDTCON2_LINEVAL_E(var->yres - 1) |
|
||||
VIDTCON2_HOZVAL_E(var->xres - 1);
|
||||
writel(data, regs + sfb->variant.vidtcon + 8);
|
||||
}
|
||||
|
||||
/* write the buffer address */
|
||||
|
||||
/* start and end registers stride is 8 */
|
||||
@ -839,6 +799,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
||||
struct s3c_fb *sfb = win->parent;
|
||||
unsigned int index = win->index;
|
||||
u32 wincon;
|
||||
u32 output_on = sfb->output_on;
|
||||
|
||||
dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
|
||||
|
||||
@ -877,34 +838,18 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
||||
|
||||
shadow_protect_win(win, 1);
|
||||
writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
|
||||
shadow_protect_win(win, 0);
|
||||
|
||||
/* Check the enabled state to see if we need to be running the
|
||||
* main LCD interface, as if there are no active windows then
|
||||
* it is highly likely that we also do not need to output
|
||||
* anything.
|
||||
*/
|
||||
|
||||
/* We could do something like the following code, but the current
|
||||
* system of using framebuffer events means that we cannot make
|
||||
* the distinction between just window 0 being inactive and all
|
||||
* the windows being down.
|
||||
*
|
||||
* s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
|
||||
*/
|
||||
|
||||
/* we're stuck with this until we can do something about overriding
|
||||
* the power control using the blanking event for a single fb.
|
||||
*/
|
||||
if (index == sfb->pdata->default_win) {
|
||||
shadow_protect_win(win, 1);
|
||||
s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
|
||||
shadow_protect_win(win, 0);
|
||||
}
|
||||
s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
|
||||
shadow_protect_win(win, 0);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
return output_on == sfb->output_on;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1111,7 +1056,7 @@ static struct fb_ops s3c_fb_ops = {
|
||||
*
|
||||
* Calculate the pixel clock when none has been given through platform data.
|
||||
*/
|
||||
static void __devinit s3c_fb_missing_pixclock(struct fb_videomode *mode)
|
||||
static void s3c_fb_missing_pixclock(struct fb_videomode *mode)
|
||||
{
|
||||
u64 pixclk = 1000000000000ULL;
|
||||
u32 div;
|
||||
@ -1144,11 +1089,11 @@ static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
|
||||
|
||||
dev_dbg(sfb->dev, "allocating memory for display\n");
|
||||
|
||||
real_size = windata->win_mode.xres * windata->win_mode.yres;
|
||||
real_size = windata->xres * windata->yres;
|
||||
virt_size = windata->virtual_x * windata->virtual_y;
|
||||
|
||||
dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
|
||||
real_size, windata->win_mode.xres, windata->win_mode.yres,
|
||||
real_size, windata->xres, windata->yres,
|
||||
virt_size, windata->virtual_x, windata->virtual_y);
|
||||
|
||||
size = (real_size > virt_size) ? real_size : virt_size;
|
||||
@ -1230,7 +1175,7 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
|
||||
struct s3c_fb_win **res)
|
||||
{
|
||||
struct fb_var_screeninfo *var;
|
||||
struct fb_videomode *initmode;
|
||||
struct fb_videomode initmode;
|
||||
struct s3c_fb_pd_win *windata;
|
||||
struct s3c_fb_win *win;
|
||||
struct fb_info *fbinfo;
|
||||
@ -1251,11 +1196,11 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
|
||||
}
|
||||
|
||||
windata = sfb->pdata->win[win_no];
|
||||
initmode = &windata->win_mode;
|
||||
initmode = *sfb->pdata->vtiming;
|
||||
|
||||
WARN_ON(windata->max_bpp == 0);
|
||||
WARN_ON(windata->win_mode.xres == 0);
|
||||
WARN_ON(windata->win_mode.yres == 0);
|
||||
WARN_ON(windata->xres == 0);
|
||||
WARN_ON(windata->yres == 0);
|
||||
|
||||
win = fbinfo->par;
|
||||
*res = win;
|
||||
@ -1294,7 +1239,9 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
|
||||
}
|
||||
|
||||
/* setup the initial video mode from the window */
|
||||
fb_videomode_to_var(&fbinfo->var, initmode);
|
||||
initmode.xres = windata->xres;
|
||||
initmode.yres = windata->yres;
|
||||
fb_videomode_to_var(&fbinfo->var, &initmode);
|
||||
|
||||
fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
fbinfo->fix.accel = FB_ACCEL_NONE;
|
||||
@ -1338,6 +1285,53 @@ static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_set_rgb_timing() - set video timing for rgb interface.
|
||||
* @sfb: The base resources for the hardware.
|
||||
*
|
||||
* Set horizontal and vertical lcd rgb interface timing.
|
||||
*/
|
||||
static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
|
||||
{
|
||||
struct fb_videomode *vmode = sfb->pdata->vtiming;
|
||||
void __iomem *regs = sfb->regs;
|
||||
int clkdiv;
|
||||
u32 data;
|
||||
|
||||
if (!vmode->pixclock)
|
||||
s3c_fb_missing_pixclock(vmode);
|
||||
|
||||
clkdiv = s3c_fb_calc_pixclk(sfb, vmode->pixclock);
|
||||
|
||||
data = sfb->pdata->vidcon0;
|
||||
data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
|
||||
|
||||
if (clkdiv > 1)
|
||||
data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
|
||||
else
|
||||
data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
|
||||
|
||||
if (sfb->variant.is_2443)
|
||||
data |= (1 << 5);
|
||||
writel(data, regs + VIDCON0);
|
||||
|
||||
data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
|
||||
VIDTCON0_VFPD(vmode->lower_margin - 1) |
|
||||
VIDTCON0_VSPW(vmode->vsync_len - 1);
|
||||
writel(data, regs + sfb->variant.vidtcon);
|
||||
|
||||
data = VIDTCON1_HBPD(vmode->left_margin - 1) |
|
||||
VIDTCON1_HFPD(vmode->right_margin - 1) |
|
||||
VIDTCON1_HSPW(vmode->hsync_len - 1);
|
||||
writel(data, regs + sfb->variant.vidtcon + 4);
|
||||
|
||||
data = VIDTCON2_LINEVAL(vmode->yres - 1) |
|
||||
VIDTCON2_HOZVAL(vmode->xres - 1) |
|
||||
VIDTCON2_LINEVAL_E(vmode->yres - 1) |
|
||||
VIDTCON2_HOZVAL_E(vmode->xres - 1);
|
||||
writel(data, regs + sfb->variant.vidtcon + 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_clear_win() - clear hardware window registers.
|
||||
* @sfb: The base resources for the hardware.
|
||||
@ -1481,15 +1475,14 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
|
||||
writel(0xffffff, regs + WKEYCON1);
|
||||
}
|
||||
|
||||
s3c_fb_set_rgb_timing(sfb);
|
||||
|
||||
/* we have the register setup, start allocating framebuffers */
|
||||
|
||||
for (win = 0; win < fbdrv->variant.nr_windows; win++) {
|
||||
if (!pd->win[win])
|
||||
continue;
|
||||
|
||||
if (!pd->win[win]->win_mode.pixclock)
|
||||
s3c_fb_missing_pixclock(&pd->win[win]->win_mode);
|
||||
|
||||
ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
|
||||
&sfb->windows[win]);
|
||||
if (ret < 0) {
|
||||
@ -1564,6 +1557,8 @@ static int s3c_fb_suspend(struct device *dev)
|
||||
struct s3c_fb_win *win;
|
||||
int win_no;
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
|
||||
win = sfb->windows[win_no];
|
||||
if (!win)
|
||||
@ -1577,6 +1572,9 @@ static int s3c_fb_suspend(struct device *dev)
|
||||
clk_disable(sfb->lcd_clk);
|
||||
|
||||
clk_disable(sfb->bus_clk);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1589,6 +1587,8 @@ static int s3c_fb_resume(struct device *dev)
|
||||
int win_no;
|
||||
u32 reg;
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
clk_enable(sfb->bus_clk);
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
@ -1623,6 +1623,8 @@ static int s3c_fb_resume(struct device *dev)
|
||||
shadow_protect_win(win, 0);
|
||||
}
|
||||
|
||||
s3c_fb_set_rgb_timing(sfb);
|
||||
|
||||
/* restore framebuffers */
|
||||
for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
|
||||
win = sfb->windows[win_no];
|
||||
@ -1633,6 +1635,8 @@ static int s3c_fb_resume(struct device *dev)
|
||||
s3c_fb_set_par(win->fbinfo);
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "sh_mobile_lcdcfb.h"
|
||||
|
||||
/* HDMI Core Control Register (HTOP0) */
|
||||
#define HDMI_SYSTEM_CTRL 0x00 /* System control */
|
||||
#define HDMI_L_R_DATA_SWAP_CTRL_RPKT 0x01 /* L/R data swap control,
|
||||
bits 19..16 of 20-bit N for Audio Clock Regeneration packet */
|
||||
@ -201,6 +202,68 @@
|
||||
#define HDMI_REVISION_ID 0xF1 /* Revision ID */
|
||||
#define HDMI_TEST_MODE 0xFE /* Test mode */
|
||||
|
||||
/* HDMI Control Register (HTOP1) */
|
||||
#define HDMI_HTOP1_TEST_MODE 0x0000 /* Test mode */
|
||||
#define HDMI_HTOP1_VIDEO_INPUT 0x0008 /* VideoInput */
|
||||
#define HDMI_HTOP1_CORE_RSTN 0x000C /* CoreResetn */
|
||||
#define HDMI_HTOP1_PLLBW 0x0018 /* PLLBW */
|
||||
#define HDMI_HTOP1_CLK_TO_PHY 0x001C /* Clk to Phy */
|
||||
#define HDMI_HTOP1_VIDEO_INPUT2 0x0020 /* VideoInput2 */
|
||||
#define HDMI_HTOP1_TISEMP0_1 0x0024 /* tisemp0-1 */
|
||||
#define HDMI_HTOP1_TISEMP2_C 0x0028 /* tisemp2-c */
|
||||
#define HDMI_HTOP1_TISIDRV 0x002C /* tisidrv */
|
||||
#define HDMI_HTOP1_TISEN 0x0034 /* tisen */
|
||||
#define HDMI_HTOP1_TISDREN 0x0038 /* tisdren */
|
||||
#define HDMI_HTOP1_CISRANGE 0x003C /* cisrange */
|
||||
#define HDMI_HTOP1_ENABLE_SELECTOR 0x0040 /* Enable Selector */
|
||||
#define HDMI_HTOP1_MACRO_RESET 0x0044 /* Macro reset */
|
||||
#define HDMI_HTOP1_PLL_CALIBRATION 0x0048 /* PLL calibration */
|
||||
#define HDMI_HTOP1_RE_CALIBRATION 0x004C /* Re-calibration */
|
||||
#define HDMI_HTOP1_CURRENT 0x0050 /* Current */
|
||||
#define HDMI_HTOP1_PLL_LOCK_DETECT 0x0054 /* PLL lock detect */
|
||||
#define HDMI_HTOP1_PHY_TEST_MODE 0x0058 /* PHY Test Mode */
|
||||
#define HDMI_HTOP1_CLK_SET 0x0080 /* Clock Set */
|
||||
#define HDMI_HTOP1_DDC_FAIL_SAFE 0x0084 /* DDC fail safe */
|
||||
#define HDMI_HTOP1_PRBS 0x0088 /* PRBS */
|
||||
#define HDMI_HTOP1_EDID_AINC_CONTROL 0x008C /* EDID ainc Control */
|
||||
#define HDMI_HTOP1_HTOP_DCL_MODE 0x00FC /* Deep Coloer Mode */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0 0x0100 /* Deep Color:FRC COEF0 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1 0x0104 /* Deep Color:FRC COEF1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2 0x0108 /* Deep Color:FRC COEF2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3 0x010C /* Deep Color:FRC COEF3 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF0_C 0x0110 /* Deep Color:FRC COEF0C */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF1_C 0x0114 /* Deep Color:FRC COEF1C */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF2_C 0x0118 /* Deep Color:FRC COEF2C */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_COEF3_C 0x011C /* Deep Color:FRC COEF3C */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FRC_MODE 0x0120 /* Deep Color:FRC Mode */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_START1 0x0124 /* Deep Color:Rect Start1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE1 0x0128 /* Deep Color:Rect Size1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_START2 0x012C /* Deep Color:Rect Start2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE2 0x0130 /* Deep Color:Rect Size2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_START3 0x0134 /* Deep Color:Rect Start3 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE3 0x0138 /* Deep Color:Rect Size3 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_START4 0x013C /* Deep Color:Rect Start4 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_RECT_SIZE4 0x0140 /* Deep Color:Rect Size4 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1 0x0144 /* Deep Color:Fil Para Y1_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2 0x0148 /* Deep Color:Fil Para Y1_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1 0x014C /* Deep Color:Fil Para CB1_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2 0x0150 /* Deep Color:Fil Para CB1_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1 0x0154 /* Deep Color:Fil Para CR1_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2 0x0158 /* Deep Color:Fil Para CR1_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1 0x015C /* Deep Color:Fil Para Y2_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2 0x0160 /* Deep Color:Fil Para Y2_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1 0x0164 /* Deep Color:Fil Para CB2_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2 0x0168 /* Deep Color:Fil Para CB2_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1 0x016C /* Deep Color:Fil Para CR2_1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2 0x0170 /* Deep Color:Fil Para CR2_2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1 0x0174 /* Deep Color:Cor Para Y1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1 0x0178 /* Deep Color:Cor Para CB1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1 0x017C /* Deep Color:Cor Para CR1 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2 0x0180 /* Deep Color:Cor Para Y2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2 0x0184 /* Deep Color:Cor Para CB2 */
|
||||
#define HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2 0x0188 /* Deep Color:Cor Para CR2 */
|
||||
#define HDMI_HTOP1_EDID_DATA_READ 0x0200 /* EDID Data Read 128Byte:0x03FC */
|
||||
|
||||
enum hotplug_state {
|
||||
HDMI_HOTPLUG_DISCONNECTED,
|
||||
HDMI_HOTPLUG_CONNECTED,
|
||||
@ -211,6 +274,7 @@ struct sh_hdmi {
|
||||
struct sh_mobile_lcdc_entity entity;
|
||||
|
||||
void __iomem *base;
|
||||
void __iomem *htop1;
|
||||
enum hotplug_state hp_state; /* hot-plug status */
|
||||
u8 preprogrammed_vic; /* use a pre-programmed VIC or
|
||||
the external mode */
|
||||
@ -222,20 +286,66 @@ struct sh_hdmi {
|
||||
struct delayed_work edid_work;
|
||||
struct fb_videomode mode;
|
||||
struct fb_monspecs monspec;
|
||||
|
||||
/* register access functions */
|
||||
void (*write)(struct sh_hdmi *hdmi, u8 data, u8 reg);
|
||||
u8 (*read)(struct sh_hdmi *hdmi, u8 reg);
|
||||
};
|
||||
|
||||
#define entity_to_sh_hdmi(e) container_of(e, struct sh_hdmi, entity)
|
||||
|
||||
static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
|
||||
static void __hdmi_write8(struct sh_hdmi *hdmi, u8 data, u8 reg)
|
||||
{
|
||||
iowrite8(data, hdmi->base + reg);
|
||||
}
|
||||
|
||||
static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
|
||||
static u8 __hdmi_read8(struct sh_hdmi *hdmi, u8 reg)
|
||||
{
|
||||
return ioread8(hdmi->base + reg);
|
||||
}
|
||||
|
||||
static void __hdmi_write32(struct sh_hdmi *hdmi, u8 data, u8 reg)
|
||||
{
|
||||
iowrite32((u32)data, hdmi->base + (reg * 4));
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
static u8 __hdmi_read32(struct sh_hdmi *hdmi, u8 reg)
|
||||
{
|
||||
return (u8)ioread32(hdmi->base + (reg * 4));
|
||||
}
|
||||
|
||||
static void hdmi_write(struct sh_hdmi *hdmi, u8 data, u8 reg)
|
||||
{
|
||||
hdmi->write(hdmi, data, reg);
|
||||
}
|
||||
|
||||
static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
|
||||
{
|
||||
return hdmi->read(hdmi, reg);
|
||||
}
|
||||
|
||||
static void hdmi_bit_set(struct sh_hdmi *hdmi, u8 mask, u8 data, u8 reg)
|
||||
{
|
||||
u8 val = hdmi_read(hdmi, reg);
|
||||
|
||||
val &= ~mask;
|
||||
val |= (data & mask);
|
||||
|
||||
hdmi_write(hdmi, val, reg);
|
||||
}
|
||||
|
||||
static void hdmi_htop1_write(struct sh_hdmi *hdmi, u32 data, u32 reg)
|
||||
{
|
||||
iowrite32(data, hdmi->htop1 + reg);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
static u32 hdmi_htop1_read(struct sh_hdmi *hdmi, u32 reg)
|
||||
{
|
||||
return ioread32(hdmi->htop1 + reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* HDMI sound
|
||||
*/
|
||||
@ -693,11 +803,11 @@ static void sh_hdmi_configure(struct sh_hdmi *hdmi)
|
||||
msleep(10);
|
||||
|
||||
/* PS mode b->d, reset PLLA and PLLB */
|
||||
hdmi_write(hdmi, 0x4C, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x4C, HDMI_SYSTEM_CTRL);
|
||||
|
||||
udelay(10);
|
||||
|
||||
hdmi_write(hdmi, 0x40, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x40, HDMI_SYSTEM_CTRL);
|
||||
}
|
||||
|
||||
static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi,
|
||||
@ -746,7 +856,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate,
|
||||
/* Read EDID */
|
||||
dev_dbg(hdmi->dev, "Read back EDID code:");
|
||||
for (i = 0; i < 128; i++) {
|
||||
edid[i] = hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
|
||||
edid[i] = (hdmi->htop1) ?
|
||||
(u8)hdmi_htop1_read(hdmi, HDMI_HTOP1_EDID_DATA_READ + (i * 4)) :
|
||||
hdmi_read(hdmi, HDMI_EDID_KSV_FIFO_ACCESS_WINDOW);
|
||||
#ifdef DEBUG
|
||||
if ((i % 16) == 0) {
|
||||
printk(KERN_CONT "\n");
|
||||
@ -917,13 +1029,13 @@ static irqreturn_t sh_hdmi_hotplug(int irq, void *dev_id)
|
||||
u8 status1, status2, mask1, mask2;
|
||||
|
||||
/* mode_b and PLLA and PLLB reset */
|
||||
hdmi_write(hdmi, 0x2C, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x2C, HDMI_SYSTEM_CTRL);
|
||||
|
||||
/* How long shall reset be held? */
|
||||
udelay(10);
|
||||
|
||||
/* mode_b and PLLA and PLLB reset release */
|
||||
hdmi_write(hdmi, 0x20, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x20, HDMI_SYSTEM_CTRL);
|
||||
|
||||
status1 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_1);
|
||||
status2 = hdmi_read(hdmi, HDMI_INTERRUPT_STATUS_2);
|
||||
@ -1001,7 +1113,7 @@ static int sh_hdmi_display_on(struct sh_mobile_lcdc_entity *entity)
|
||||
*/
|
||||
if (hdmi->hp_state == HDMI_HOTPLUG_EDID_DONE) {
|
||||
/* PS mode d->e. All functions are active */
|
||||
hdmi_write(hdmi, 0x80, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x80, HDMI_SYSTEM_CTRL);
|
||||
dev_dbg(hdmi->dev, "HDMI running\n");
|
||||
}
|
||||
|
||||
@ -1016,7 +1128,7 @@ static void sh_hdmi_display_off(struct sh_mobile_lcdc_entity *entity)
|
||||
|
||||
dev_dbg(hdmi->dev, "%s(%p)\n", __func__, hdmi);
|
||||
/* PS mode e->a */
|
||||
hdmi_write(hdmi, 0x10, HDMI_SYSTEM_CTRL);
|
||||
hdmi_bit_set(hdmi, 0xFC, 0x10, HDMI_SYSTEM_CTRL);
|
||||
}
|
||||
|
||||
static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = {
|
||||
@ -1110,10 +1222,58 @@ out:
|
||||
dev_dbg(hdmi->dev, "%s(%p): end\n", __func__, hdmi);
|
||||
}
|
||||
|
||||
static void sh_hdmi_htop1_init(struct sh_hdmi *hdmi)
|
||||
{
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_MODE);
|
||||
hdmi_htop1_write(hdmi, 0x0000000b, 0x0010);
|
||||
hdmi_htop1_write(hdmi, 0x00006710, HDMI_HTOP1_HTOP_DCL_FRC_MODE);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y1_2);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB1_2);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR1_2);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_Y2_2);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CB2_2);
|
||||
hdmi_htop1_write(hdmi, 0x01020406, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_1);
|
||||
hdmi_htop1_write(hdmi, 0x07080806, HDMI_HTOP1_HTOP_DCL_FIL_PARA_CR2_2);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y1);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB1);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR1);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_Y2);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CB2);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_HTOP_DCL_COR_PARA_CR2);
|
||||
hdmi_htop1_write(hdmi, 0x00000008, HDMI_HTOP1_CURRENT);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP0_1);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_TISEMP2_C);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PHY_TEST_MODE);
|
||||
hdmi_htop1_write(hdmi, 0x00000081, HDMI_HTOP1_TISIDRV);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_PLLBW);
|
||||
hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
|
||||
hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
|
||||
hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
|
||||
hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
|
||||
hdmi_htop1_write(hdmi, 0x00000016, HDMI_HTOP1_CISRANGE);
|
||||
msleep(100);
|
||||
hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_ENABLE_SELECTOR);
|
||||
msleep(100);
|
||||
hdmi_htop1_write(hdmi, 0x00000003, HDMI_HTOP1_ENABLE_SELECTOR);
|
||||
hdmi_htop1_write(hdmi, 0x00000001, HDMI_HTOP1_MACRO_RESET);
|
||||
hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISEN);
|
||||
hdmi_htop1_write(hdmi, 0x0000000f, HDMI_HTOP1_TISDREN);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_CLK_TO_PHY);
|
||||
hdmi_htop1_write(hdmi, 0x00000000, HDMI_HTOP1_VIDEO_INPUT2);
|
||||
hdmi_htop1_write(hdmi, 0x0000000a, HDMI_HTOP1_CLK_SET);
|
||||
}
|
||||
|
||||
static int __init sh_hdmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mobile_hdmi_info *pdata = pdev->dev.platform_data;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct resource *htop1_res;
|
||||
int irq = platform_get_irq(pdev, 0), ret;
|
||||
struct sh_hdmi *hdmi;
|
||||
long rate;
|
||||
@ -1121,6 +1281,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
|
||||
if (!res || !pdata || irq < 0)
|
||||
return -ENODEV;
|
||||
|
||||
htop1_res = NULL;
|
||||
if (pdata->flags & HDMI_HAS_HTOP1) {
|
||||
htop1_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
if (!htop1_res) {
|
||||
dev_err(&pdev->dev, "htop1 needs register base\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
|
||||
if (!hdmi) {
|
||||
dev_err(&pdev->dev, "Cannot allocate device data\n");
|
||||
@ -1138,6 +1307,15 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
|
||||
goto egetclk;
|
||||
}
|
||||
|
||||
/* select register access functions */
|
||||
if (pdata->flags & HDMI_32BIT_REG) {
|
||||
hdmi->write = __hdmi_write32;
|
||||
hdmi->read = __hdmi_read32;
|
||||
} else {
|
||||
hdmi->write = __hdmi_write8;
|
||||
hdmi->read = __hdmi_read8;
|
||||
}
|
||||
|
||||
/* An arbitrary relaxed pixclock just to get things started: from standard 480p */
|
||||
rate = clk_round_rate(hdmi->hdmi_clk, PICOS2KHZ(37037));
|
||||
if (rate > 0)
|
||||
@ -1176,6 +1354,24 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
/* init interrupt polarity */
|
||||
if (pdata->flags & HDMI_OUTPUT_PUSH_PULL)
|
||||
hdmi_bit_set(hdmi, 0x02, 0x02, HDMI_SYSTEM_CTRL);
|
||||
|
||||
if (pdata->flags & HDMI_OUTPUT_POLARITY_HI)
|
||||
hdmi_bit_set(hdmi, 0x01, 0x01, HDMI_SYSTEM_CTRL);
|
||||
|
||||
/* enable htop1 register if needed */
|
||||
if (htop1_res) {
|
||||
hdmi->htop1 = ioremap(htop1_res->start, resource_size(htop1_res));
|
||||
if (!hdmi->htop1) {
|
||||
dev_err(&pdev->dev, "control register region already claimed\n");
|
||||
ret = -ENOMEM;
|
||||
goto emap_htop1;
|
||||
}
|
||||
sh_hdmi_htop1_init(hdmi);
|
||||
}
|
||||
|
||||
/* Product and revision IDs are 0 in sh-mobile version */
|
||||
dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
|
||||
hdmi_read(hdmi, HDMI_PRODUCT_ID), hdmi_read(hdmi, HDMI_REVISION_ID));
|
||||
@ -1199,6 +1395,9 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
|
||||
ecodec:
|
||||
free_irq(irq, hdmi);
|
||||
ereqirq:
|
||||
if (hdmi->htop1)
|
||||
iounmap(hdmi->htop1);
|
||||
emap_htop1:
|
||||
pm_runtime_put(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
iounmap(hdmi->base);
|
||||
@ -1230,6 +1429,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable(hdmi->hdmi_clk);
|
||||
clk_put(hdmi->hdmi_clk);
|
||||
if (hdmi->htop1)
|
||||
iounmap(hdmi->htop1);
|
||||
iounmap(hdmi->base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
kfree(hdmi);
|
||||
|
@ -105,51 +105,6 @@ static const unsigned short ModeIndex_1920x1440[] = {0x68, 0x69, 0x00, 0x6b};
|
||||
static const unsigned short ModeIndex_300_2048x1536[]= {0x6c, 0x6d, 0x00, 0x00};
|
||||
static const unsigned short ModeIndex_310_2048x1536[]= {0x6c, 0x6d, 0x00, 0x6e};
|
||||
|
||||
static const unsigned short SiS_DRAMType[17][5]={
|
||||
{0x0C,0x0A,0x02,0x40,0x39},
|
||||
{0x0D,0x0A,0x01,0x40,0x48},
|
||||
{0x0C,0x09,0x02,0x20,0x35},
|
||||
{0x0D,0x09,0x01,0x20,0x44},
|
||||
{0x0C,0x08,0x02,0x10,0x31},
|
||||
{0x0D,0x08,0x01,0x10,0x40},
|
||||
{0x0C,0x0A,0x01,0x20,0x34},
|
||||
{0x0C,0x09,0x01,0x08,0x32},
|
||||
{0x0B,0x08,0x02,0x08,0x21},
|
||||
{0x0C,0x08,0x01,0x08,0x30},
|
||||
{0x0A,0x08,0x02,0x04,0x11},
|
||||
{0x0B,0x0A,0x01,0x10,0x28},
|
||||
{0x09,0x08,0x02,0x02,0x01},
|
||||
{0x0B,0x09,0x01,0x08,0x24},
|
||||
{0x0B,0x08,0x01,0x04,0x20},
|
||||
{0x0A,0x08,0x01,0x02,0x10},
|
||||
{0x09,0x08,0x01,0x01,0x00}
|
||||
};
|
||||
|
||||
static const unsigned short SiS_SDRDRAM_TYPE[13][5] =
|
||||
{
|
||||
{ 2,12, 9,64,0x35},
|
||||
{ 1,13, 9,64,0x44},
|
||||
{ 2,12, 8,32,0x31},
|
||||
{ 2,11, 9,32,0x25},
|
||||
{ 1,12, 9,32,0x34},
|
||||
{ 1,13, 8,32,0x40},
|
||||
{ 2,11, 8,16,0x21},
|
||||
{ 1,12, 8,16,0x30},
|
||||
{ 1,11, 9,16,0x24},
|
||||
{ 1,11, 8, 8,0x20},
|
||||
{ 2, 9, 8, 4,0x01},
|
||||
{ 1,10, 8, 4,0x10},
|
||||
{ 1, 9, 8, 2,0x00}
|
||||
};
|
||||
|
||||
static const unsigned short SiS_DDRDRAM_TYPE[4][5] =
|
||||
{
|
||||
{ 2,12, 9,64,0x35},
|
||||
{ 2,12, 8,32,0x31},
|
||||
{ 2,11, 8,16,0x21},
|
||||
{ 2, 9, 8, 4,0x01}
|
||||
};
|
||||
|
||||
static const unsigned char SiS_MDA_DAC[] =
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
|
@ -4222,6 +4222,26 @@ sisfb_post_300_buswidth(struct sis_video_info *ivideo)
|
||||
return 1; /* 32bit */
|
||||
}
|
||||
|
||||
static const unsigned short __devinitconst SiS_DRAMType[17][5] = {
|
||||
{0x0C,0x0A,0x02,0x40,0x39},
|
||||
{0x0D,0x0A,0x01,0x40,0x48},
|
||||
{0x0C,0x09,0x02,0x20,0x35},
|
||||
{0x0D,0x09,0x01,0x20,0x44},
|
||||
{0x0C,0x08,0x02,0x10,0x31},
|
||||
{0x0D,0x08,0x01,0x10,0x40},
|
||||
{0x0C,0x0A,0x01,0x20,0x34},
|
||||
{0x0C,0x09,0x01,0x08,0x32},
|
||||
{0x0B,0x08,0x02,0x08,0x21},
|
||||
{0x0C,0x08,0x01,0x08,0x30},
|
||||
{0x0A,0x08,0x02,0x04,0x11},
|
||||
{0x0B,0x0A,0x01,0x10,0x28},
|
||||
{0x09,0x08,0x02,0x02,0x01},
|
||||
{0x0B,0x09,0x01,0x08,0x24},
|
||||
{0x0B,0x08,0x01,0x04,0x20},
|
||||
{0x0A,0x08,0x01,0x02,0x10},
|
||||
{0x09,0x08,0x01,0x01,0x00}
|
||||
};
|
||||
|
||||
static int __devinit
|
||||
sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth,
|
||||
int PseudoRankCapacity, int PseudoAdrPinCount,
|
||||
@ -4231,27 +4251,8 @@ sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration, int buswidth
|
||||
unsigned short sr14;
|
||||
unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
|
||||
unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
|
||||
static const unsigned short SiS_DRAMType[17][5] = {
|
||||
{0x0C,0x0A,0x02,0x40,0x39},
|
||||
{0x0D,0x0A,0x01,0x40,0x48},
|
||||
{0x0C,0x09,0x02,0x20,0x35},
|
||||
{0x0D,0x09,0x01,0x20,0x44},
|
||||
{0x0C,0x08,0x02,0x10,0x31},
|
||||
{0x0D,0x08,0x01,0x10,0x40},
|
||||
{0x0C,0x0A,0x01,0x20,0x34},
|
||||
{0x0C,0x09,0x01,0x08,0x32},
|
||||
{0x0B,0x08,0x02,0x08,0x21},
|
||||
{0x0C,0x08,0x01,0x08,0x30},
|
||||
{0x0A,0x08,0x02,0x04,0x11},
|
||||
{0x0B,0x0A,0x01,0x10,0x28},
|
||||
{0x09,0x08,0x02,0x02,0x01},
|
||||
{0x0B,0x09,0x01,0x08,0x24},
|
||||
{0x0B,0x08,0x01,0x04,0x20},
|
||||
{0x0A,0x08,0x01,0x02,0x10},
|
||||
{0x09,0x08,0x01,0x01,0x00}
|
||||
};
|
||||
|
||||
for(k = 0; k <= 16; k++) {
|
||||
for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
|
||||
|
||||
RankCapacity = buswidth * SiS_DRAMType[k][3];
|
||||
|
||||
|
@ -1036,6 +1036,6 @@ static void __exit xxxfb_exit(void)
|
||||
*/
|
||||
|
||||
module_init(xxxfb_init);
|
||||
module_exit(xxxfb_remove);
|
||||
module_exit(xxxfb_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -846,7 +846,7 @@ static void ufx_raw_rect(struct ufx_data *dev, u16 *cmd, int x, int y,
|
||||
}
|
||||
}
|
||||
|
||||
int ufx_handle_damage(struct ufx_data *dev, int x, int y,
|
||||
static int ufx_handle_damage(struct ufx_data *dev, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
size_t packed_line_len = ALIGN((width * 2), 4);
|
||||
@ -1083,7 +1083,7 @@ static int ufx_ops_open(struct fb_info *info, int user)
|
||||
|
||||
struct fb_deferred_io *fbdefio;
|
||||
|
||||
fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
|
||||
fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
|
||||
|
||||
if (fbdefio) {
|
||||
fbdefio->delay = UFX_DEFIO_WRITE_DELAY;
|
||||
|
@ -893,7 +893,7 @@ static int dlfb_ops_open(struct fb_info *info, int user)
|
||||
|
||||
struct fb_deferred_io *fbdefio;
|
||||
|
||||
fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
|
||||
fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL);
|
||||
|
||||
if (fbdefio) {
|
||||
fbdefio->delay = DL_DEFIO_WRITE_DELAY;
|
||||
|
@ -1276,17 +1276,12 @@ static int viafb_dfph_proc_open(struct inode *inode, struct file *file)
|
||||
static ssize_t viafb_dfph_proc_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *pos)
|
||||
{
|
||||
char buf[20];
|
||||
u8 reg_val = 0;
|
||||
unsigned long length;
|
||||
if (count < 1)
|
||||
return -EINVAL;
|
||||
length = count > 20 ? 20 : count;
|
||||
if (copy_from_user(&buf[0], buffer, length))
|
||||
return -EFAULT;
|
||||
buf[length - 1] = '\0'; /*Ensure end string */
|
||||
if (kstrtou8(buf, 0, ®_val) < 0)
|
||||
return -EINVAL;
|
||||
int err;
|
||||
u8 reg_val;
|
||||
err = kstrtou8_from_user(buffer, count, 0, ®_val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
viafb_write_reg_mask(CR97, VIACR, reg_val, 0x0f);
|
||||
return count;
|
||||
}
|
||||
@ -1316,17 +1311,12 @@ static int viafb_dfpl_proc_open(struct inode *inode, struct file *file)
|
||||
static ssize_t viafb_dfpl_proc_write(struct file *file,
|
||||
const char __user *buffer, size_t count, loff_t *pos)
|
||||
{
|
||||
char buf[20];
|
||||
u8 reg_val = 0;
|
||||
unsigned long length;
|
||||
if (count < 1)
|
||||
return -EINVAL;
|
||||
length = count > 20 ? 20 : count;
|
||||
if (copy_from_user(&buf[0], buffer, length))
|
||||
return -EFAULT;
|
||||
buf[length - 1] = '\0'; /*Ensure end string */
|
||||
if (kstrtou8(buf, 0, ®_val) < 0)
|
||||
return -EINVAL;
|
||||
int err;
|
||||
u8 reg_val;
|
||||
err = kstrtou8_from_user(buffer, count, 0, ®_val);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
viafb_write_reg_mask(CR99, VIACR, reg_val, 0x0f);
|
||||
return count;
|
||||
}
|
||||
|
@ -611,6 +611,7 @@ struct fb_deferred_io {
|
||||
struct mutex lock; /* mutex that protects the page list */
|
||||
struct list_head pagelist; /* list of touched pages */
|
||||
/* callback */
|
||||
void (*first_io)(struct fb_info *info);
|
||||
void (*deferred_io)(struct fb_info *info, struct list_head *pagelist);
|
||||
};
|
||||
#endif
|
||||
|
106
include/video/auo_k190xfb.h
Normal file
106
include/video/auo_k190xfb.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Definitions for AUO-K190X framebuffer drivers
|
||||
*
|
||||
* Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_VIDEO_AUO_K190XFB_H_
|
||||
#define _LINUX_VIDEO_AUO_K190XFB_H_
|
||||
|
||||
/* Controller standby command needs a param */
|
||||
#define AUOK190X_QUIRK_STANDBYPARAM (1 << 0)
|
||||
|
||||
/* Controller standby is completely broken */
|
||||
#define AUOK190X_QUIRK_STANDBYBROKEN (1 << 1)
|
||||
|
||||
/*
|
||||
* Resolutions for the displays
|
||||
*/
|
||||
#define AUOK190X_RESOLUTION_800_600 0
|
||||
#define AUOK190X_RESOLUTION_1024_768 1
|
||||
|
||||
/*
|
||||
* struct used by auok190x. board specific stuff comes from *board
|
||||
*/
|
||||
struct auok190xfb_par {
|
||||
struct fb_info *info;
|
||||
struct auok190x_board *board;
|
||||
|
||||
struct regulator *regulator;
|
||||
|
||||
struct mutex io_lock;
|
||||
struct delayed_work work;
|
||||
wait_queue_head_t waitq;
|
||||
int resolution;
|
||||
int rotation;
|
||||
int consecutive_threshold;
|
||||
int update_cnt;
|
||||
|
||||
/* panel and controller informations */
|
||||
int epd_type;
|
||||
int panel_size_int;
|
||||
int panel_size_float;
|
||||
int panel_model;
|
||||
int tcon_version;
|
||||
int lut_version;
|
||||
|
||||
/* individual controller callbacks */
|
||||
void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
|
||||
void (*update_all)(struct auok190xfb_par *par);
|
||||
bool (*need_refresh)(struct auok190xfb_par *par);
|
||||
void (*init)(struct auok190xfb_par *par);
|
||||
void (*recover)(struct auok190xfb_par *par);
|
||||
|
||||
int update_mode; /* mode to use for updates */
|
||||
int last_mode; /* update mode last used */
|
||||
int flash;
|
||||
|
||||
/* power management */
|
||||
int autosuspend_delay;
|
||||
bool standby;
|
||||
bool manual_standby;
|
||||
};
|
||||
|
||||
/**
|
||||
* Board specific platform-data
|
||||
* @init: initialize the controller interface
|
||||
* @cleanup: cleanup the controller interface
|
||||
* @wait_for_rdy: wait until the controller is not busy anymore
|
||||
* @set_ctl: change an interface control
|
||||
* @set_hdb: write a value to the data register
|
||||
* @get_hdb: read a value from the data register
|
||||
* @setup_irq: method to setup the irq handling on the busy gpio
|
||||
* @gpio_nsleep: sleep gpio
|
||||
* @gpio_nrst: reset gpio
|
||||
* @gpio_nbusy: busy gpio
|
||||
* @resolution: one of the AUOK190X_RESOLUTION constants
|
||||
* @rotation: rotation of the framebuffer
|
||||
* @quirks: controller quirks to honor
|
||||
* @fps: frames per second for defio
|
||||
*/
|
||||
struct auok190x_board {
|
||||
int (*init)(struct auok190xfb_par *);
|
||||
void (*cleanup)(struct auok190xfb_par *);
|
||||
int (*wait_for_rdy)(struct auok190xfb_par *);
|
||||
|
||||
void (*set_ctl)(struct auok190xfb_par *, unsigned char, u8);
|
||||
void (*set_hdb)(struct auok190xfb_par *, u16);
|
||||
u16 (*get_hdb)(struct auok190xfb_par *);
|
||||
|
||||
int (*setup_irq)(struct fb_info *);
|
||||
|
||||
int gpio_nsleep;
|
||||
int gpio_nrst;
|
||||
int gpio_nbusy;
|
||||
|
||||
int resolution;
|
||||
int rotation;
|
||||
int quirks;
|
||||
int fps;
|
||||
};
|
||||
|
||||
#endif
|
@ -14,7 +14,7 @@
|
||||
|
||||
#define DP_TIMEOUT_LOOP_COUNT 100
|
||||
#define MAX_CR_LOOP 5
|
||||
#define MAX_EQ_LOOP 4
|
||||
#define MAX_EQ_LOOP 5
|
||||
|
||||
enum link_rate_type {
|
||||
LINK_RATE_1_62GBPS = 0x06,
|
||||
|
@ -315,6 +315,7 @@ struct mipi_dsim_lcd_device {
|
||||
int id;
|
||||
int bus_id;
|
||||
int irq;
|
||||
int panel_reverse;
|
||||
|
||||
struct mipi_dsim_device *master;
|
||||
void *platform_data;
|
||||
|
@ -51,6 +51,8 @@
|
||||
|
||||
struct omap_dss_device;
|
||||
struct omap_overlay_manager;
|
||||
struct snd_aes_iec958;
|
||||
struct snd_cea_861_aud_if;
|
||||
|
||||
enum omap_display_type {
|
||||
OMAP_DISPLAY_TYPE_NONE = 0,
|
||||
@ -158,6 +160,13 @@ enum omap_dss_display_state {
|
||||
OMAP_DSS_DISPLAY_SUSPENDED,
|
||||
};
|
||||
|
||||
enum omap_dss_audio_state {
|
||||
OMAP_DSS_AUDIO_DISABLED = 0,
|
||||
OMAP_DSS_AUDIO_ENABLED,
|
||||
OMAP_DSS_AUDIO_CONFIGURED,
|
||||
OMAP_DSS_AUDIO_PLAYING,
|
||||
};
|
||||
|
||||
/* XXX perhaps this should be removed */
|
||||
enum omap_dss_overlay_managers {
|
||||
OMAP_DSS_OVL_MGR_LCD,
|
||||
@ -166,8 +175,9 @@ enum omap_dss_overlay_managers {
|
||||
};
|
||||
|
||||
enum omap_dss_rotation_type {
|
||||
OMAP_DSS_ROT_DMA = 0,
|
||||
OMAP_DSS_ROT_VRFB = 1,
|
||||
OMAP_DSS_ROT_DMA = 1 << 0,
|
||||
OMAP_DSS_ROT_VRFB = 1 << 1,
|
||||
OMAP_DSS_ROT_TILER = 1 << 2,
|
||||
};
|
||||
|
||||
/* clockwise rotation angle */
|
||||
@ -309,6 +319,7 @@ struct omap_dss_board_info {
|
||||
struct omap_dss_device *default_device;
|
||||
int (*dsi_enable_pads)(int dsi_id, unsigned lane_mask);
|
||||
void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
|
||||
int (*set_min_bus_tput)(struct device *dev, unsigned long r);
|
||||
};
|
||||
|
||||
/* Init with the board info */
|
||||
@ -316,11 +327,6 @@ extern int omap_display_init(struct omap_dss_board_info *board_data);
|
||||
/* HDMI mux init*/
|
||||
extern int omap_hdmi_init(enum omap_hdmi_flags flags);
|
||||
|
||||
struct omap_display_platform_data {
|
||||
struct omap_dss_board_info *board_data;
|
||||
/* TODO: Additional members to be added when PM is considered */
|
||||
};
|
||||
|
||||
struct omap_video_timings {
|
||||
/* Unit: pixels */
|
||||
u16 x_res;
|
||||
@ -587,6 +593,8 @@ struct omap_dss_device {
|
||||
|
||||
enum omap_dss_display_state state;
|
||||
|
||||
enum omap_dss_audio_state audio_state;
|
||||
|
||||
/* platform specific */
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
@ -599,6 +607,11 @@ struct omap_dss_hdmi_data
|
||||
int hpd_gpio;
|
||||
};
|
||||
|
||||
struct omap_dss_audio {
|
||||
struct snd_aes_iec958 *iec;
|
||||
struct snd_cea_861_aud_if *cea;
|
||||
};
|
||||
|
||||
struct omap_dss_driver {
|
||||
struct device_driver driver;
|
||||
|
||||
@ -646,6 +659,24 @@ struct omap_dss_driver {
|
||||
|
||||
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
|
||||
bool (*detect)(struct omap_dss_device *dssdev);
|
||||
|
||||
/*
|
||||
* For display drivers that support audio. This encompasses
|
||||
* HDMI and DisplayPort at the moment.
|
||||
*/
|
||||
/*
|
||||
* Note: These functions might sleep. Do not call while
|
||||
* holding a spinlock/readlock.
|
||||
*/
|
||||
int (*audio_enable)(struct omap_dss_device *dssdev);
|
||||
void (*audio_disable)(struct omap_dss_device *dssdev);
|
||||
bool (*audio_supported)(struct omap_dss_device *dssdev);
|
||||
int (*audio_config)(struct omap_dss_device *dssdev,
|
||||
struct omap_dss_audio *audio);
|
||||
/* Note: These functions may not sleep */
|
||||
int (*audio_start)(struct omap_dss_device *dssdev);
|
||||
void (*audio_stop)(struct omap_dss_device *dssdev);
|
||||
|
||||
};
|
||||
|
||||
int omap_dss_register_driver(struct omap_dss_driver *);
|
||||
@ -670,6 +701,8 @@ struct omap_overlay *omap_dss_get_overlay(int num);
|
||||
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres);
|
||||
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
|
||||
void omapdss_default_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
|
||||
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
|
||||
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
|
@ -18,9 +18,11 @@ struct clk;
|
||||
/*
|
||||
* flags format
|
||||
*
|
||||
* 0x0000000A
|
||||
* 0x00000CBA
|
||||
*
|
||||
* A: Audio source select
|
||||
* B: Int output option
|
||||
* C: Chip specific option
|
||||
*/
|
||||
|
||||
/* Audio source select */
|
||||
@ -30,6 +32,14 @@ struct clk;
|
||||
#define HDMI_SND_SRC_DSD (2 << 0)
|
||||
#define HDMI_SND_SRC_HBR (3 << 0)
|
||||
|
||||
/* Int output option */
|
||||
#define HDMI_OUTPUT_PUSH_PULL (1 << 4) /* System control : output mode */
|
||||
#define HDMI_OUTPUT_POLARITY_HI (1 << 5) /* System control : output polarity */
|
||||
|
||||
/* Chip specific option */
|
||||
#define HDMI_32BIT_REG (1 << 8)
|
||||
#define HDMI_HAS_HTOP1 (1 << 9)
|
||||
|
||||
struct sh_mobile_hdmi_info {
|
||||
unsigned int flags;
|
||||
long (*clk_optimize_parent)(unsigned long target, unsigned long *best_freq,
|
||||
|
Loading…
Reference in New Issue
Block a user