blob: a031aaf797c3f3950c5e4dfc3edf24d6c98a5d46 [file] [log] [blame]
/*
* pdp.c - contains block specific initialisation routines
*
* Copyright (C) 2010 Imagination Technologies Ltd.
*
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <video/pdpfb.h>
#include <video/imgpdi_lcd.h>
#include <linux/io.h>
#include <asm/soc-tz1090/pdp.h>
#include <asm/soc-tz1090/defs.h>
#include <asm/soc-tz1090/clock.h>
void comet_pdp_set_shared_base(unsigned long pa)
{
writel(pa >> 2, CR_PDP_MEM_BASE_ADDR);
}
static struct resource pdp_resources[] = {
{
.start = PDP_IRQ_NUM,
/* mapped in comet_pdp_setup() */
.flags = IORESOURCE_IRQ,
},
{
.start = PDP_BASE_ADDR,
.end = PDP_BASE_ADDR + PDP_SIZE,
.flags = IORESOURCE_MEM | PDPFB_IORES_PDP,
},
};
static struct pdp_info pdp_pdata = {
.bpp = 16,
#ifdef CONFIG_SOC_COMET_ES1
.linestore_len = 768,
#else
.linestore_len = 1024,
#endif
.vpitch_bilinear_threshold = 3 << PDPFB_PDATA_FIX_SHIFT,
};
static struct platform_device pdp_device = {
.name = "pdpfb",
.id = -1,
.num_resources = ARRAY_SIZE(pdp_resources),
.resource = pdp_resources,
.dev = {
.platform_data = &pdp_pdata,
},
};
static struct resource pdi_resources[] = {
{
.start = PDI_BASE_ADDR,
.end = PDI_BASE_ADDR + PDI_SIZE,
.flags = IORESOURCE_MEM,
},
};
static struct imgpdi_lcd_timings pdi_timings;
static struct imgpdi_lcd_pdata pdi_pdata;
static int comet_pdi_match_fb(struct imgpdi_lcd_pdata *pdata,
struct fb_info *info)
{
return !strncmp(info->fix.id, "pdp", 16);
}
static struct platform_device pdi_device = {
.name = "imgpdi-lcd",
.id = -1,
.num_resources = ARRAY_SIZE(pdi_resources),
.resource = pdi_resources,
.dev = {
.platform_data = &pdi_pdata,
},
};
static struct platform_device *display_devices[] = {
&pdi_device,
&pdp_device,
};
void __init comet_pdp_set_limits(unsigned long min, unsigned long max)
{
pix_clk_set_limits(min, max);
}
int __init comet_pdp_setup(const struct fb_videomode *fbvm,
struct pdp_lcd_size_cfg *plsc, struct imgpdi_lcd_pdata *pdic,
struct pdp_sync_cfg *psc, struct pdp_hwops *hwops)
{
int irq;
/* Make sure we're given the necessary info */
if (!fbvm || !plsc)
return -ENXIO;
/* Map the IRQ */
irq = external_irq_map(pdp_resources[0].start);
if (irq < 0) {
pr_err("%s: unable to map PDP irq %u (%d)\n",
__func__, pdp_resources[0].start, irq);
return irq;
}
pdp_resources[0].start = irq;
pdp_resources[0].end = irq;
memcpy(&pdp_pdata.lcd_cfg, fbvm, sizeof(struct fb_videomode));
memcpy(&pdp_pdata.lcd_size_cfg, plsc, sizeof(struct pdp_lcd_size_cfg));
memcpy(&pdp_pdata.sync_cfg, psc, sizeof(struct pdp_sync_cfg));
memcpy(&pdp_pdata.hwops, hwops, sizeof(struct pdp_hwops));
/* copy PDI platform data if provided */
if (pdic)
memcpy(&pdi_pdata, pdic, sizeof(struct imgpdi_lcd_pdata));
else
memset(&pdi_pdata, 0, sizeof(struct imgpdi_lcd_pdata));
/* if active timings are provided, copy them too */
if (pdi_pdata.active) {
memcpy(&pdi_timings, pdi_pdata.active,
sizeof(struct imgpdi_lcd_timings));
pdi_pdata.active = &pdi_timings;
}
/* use our own fb matcher */
pdi_pdata.match_fb = comet_pdi_match_fb;
return platform_add_devices(display_devices,
ARRAY_SIZE(display_devices));
}