blob: 549ad99eda4195990e1b20c1a227ada5593f8401 [file] [log] [blame]
#include <linux/export.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <video/imgpdi_lcd.h>
#include <video/pdpfb.h>
#include <asm/soc-chorus2/pdp.h>
#include <asm/soc-chorus2/c2_irqnums.h>
#include <asm/soc-chorus2/clock.h>
static struct resource pdp_resources[] = {
{
.start = PDP_IRQ_NUM,
/* mapped in display2_device_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_platform_data = {
.bpp = 16,
.lcd_cfg = {
.name = "ATP-dp:display2",
.refresh = 60,
.hsync_len = 16,
.left_margin = 138,
.xres = 640,
.right_margin = 6,
.vsync_len = 3,
.upper_margin = 36,
.yres = 480,
.lower_margin = 6,
/* hsync and vsync are active low */
.sync = 0,
},
.lcd_size_cfg = {
.width = 115, /* 115.2mm */
.height = 86, /* 86.4mm */
},
.sync_cfg = {
.force_vsyncs = 1,
.hsync_dis = 0,
.vsync_dis = 0,
.blank_dis = 0,
.blank_pol = PDP_ACTIVE_LOW,
.clock_pol = PDP_CLOCK_INVERTED,
},
};
static struct platform_device pdp_device = {
.name = "pdpfb",
.id = -1,
.num_resources = ARRAY_SIZE(pdp_resources),
.resource = pdp_resources,
.dev = {
.platform_data = &pdp_platform_data,
},
};
static struct resource pdi_resources[] = {
{
.start = PDI_BASE_ADDR,
.end = PDI_BASE_ADDR + PDI_SIZE,
.flags = IORESOURCE_MEM,
},
};
static int display2_pdi_match_fb(struct imgpdi_lcd_pdata *pdata,
struct fb_info *info)
{
return !strncmp(info->fix.id, "pdp", 16);
}
static struct imgpdi_lcd_pdata pdi_pdata = {
.match_fb = display2_pdi_match_fb,
};
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 *display2_devices[] __initdata = {
&pdi_device,
&pdp_device,
};
/* display2 has a CH7012 on I2C bus, at address 117 */
static int display2_ch7012_probe(struct i2c_adapter *adap)
{
if (i2c_smbus_xfer(adap, 117, 0, 0, 0, I2C_SMBUS_QUICK, NULL) >= 0) {
printk(KERN_INFO "Detected ATP120-dp:display2\n");
pix_clk_set_limits(22660000, /* 22.66MHz */
27690000); /* 27.69MHz */
platform_add_devices(display2_devices,
ARRAY_SIZE(display2_devices));
}
return -EIO;
}
static const struct i2c_device_id display2_ch7012_id[] = {
{ "display2_ch7012", 0 },
{ },
};
static struct i2c_driver display2_ch7012_driver = {
.driver.name = "display2_ch7012",
.attach_adapter = display2_ch7012_probe,
.id_table = display2_ch7012_id,
};
static int __init display2_device_setup(void)
{
int irq;
/* Map the IRQ */
irq = external_irq_map(pdp_resources[0].start);
if (irq < 0) {
pr_err("%s: irq map failed (%d)\n",
__func__, irq);
return irq;
}
pdp_resources[0].start = irq;
pdp_resources[0].end = irq;
i2c_add_driver(&display2_ch7012_driver);
return 0;
}
device_initcall(display2_device_setup);