arch/arm/mach-mx28/device.c
};
static struct resource ssp2_resources[] = {
{
.start = SSP2_PHYS_ADDR,
.end = SSP2_PHYS_ADDR + 0x2000 - 1,
.flags = IORESOURCE_MEM,
}, {
.start = MXS_DMA_CHANNEL_AHB_APBH_SSP2,
.end = MXS_DMA_CHANNEL_AHB_APBH_SSP2,
.flags = IORESOURCE_DMA,
}, {
.start = IRQ_SSP2_DMA,
.end = IRQ_SSP2_DMA,
.flags = IORESOURCE_IRQ,
}, {
.start = IRQ_SSP2,
.end = IRQ_SSP2,
.flags = IORESOURCE_IRQ,
},
};
static void __init mx28_init_spi(void)
{
struct platform_device *pdev;
pdev = mxs_get_device("mxs-spi", 0);
if (pdev == NULL || IS_ERR(pdev))
return;
pdev->resource = ssp2_resources;
pdev->num_resources = ARRAY_SIZE(ssp2_resources);
pdev->dev.platform_data = &spi_data;
mxs_add_device(pdev, 3);
}
*************** display driver code ****************************
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/errno.h>
#include <linux/fsl_devices.h>
#include <linux/gpio.h>
#include "mx28_pins.h"
//p
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/notifier.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
#include <mach/device.h>
#include <mach/lcdif.h>
#include <mach/regs-pwm.h>
#include <mach/system.h>
#include <linux/spi/spi.h>
#define DOTCLK_H_ACTIVE 320
#define DOTCLK_H_PULSE_WIDTH 10
#define DOTCLK_HF_PORCH 164
#define DOTCLK_HB_PORCH 89
#define DOTCLK_H_WAIT_CNT (DOTCLK_H_PULSE_WIDTH + DOTCLK_HB_PORCH)
#define DOTCLK_H_PERIOD (DOTCLK_H_WAIT_CNT + DOTCLK_HF_PORCH + DOTCLK_H_ACTIVE)
#define DOTCLK_V_ACTIVE 240
#define DOTCLK_V_PULSE_WIDTH 10
#define DOTCLK_VF_PORCH 10
#define DOTCLK_VB_PORCH 23
#define DOTCLK_V_WAIT_CNT (DOTCLK_V_PULSE_WIDTH + DOTCLK_VB_PORCH)
#define DOTCLK_V_PERIOD (DOTCLK_VF_PORCH + DOTCLK_V_ACTIVE + DOTCLK_V_WAIT_CNT)
static struct clk *lcd_clk;
static int init_panel(struct device *dev, dma_addr_t phys, int memsize,
struct mxs_platform_fb_entry *pentry)
{
int ret = 0;
lcd_clk = clk_get(dev, "dis_lcdif");
if (IS_ERR(lcd_clk)) {
ret = PTR_ERR(lcd_clk);
goto out;
}
ret = clk_enable(lcd_clk);
if (ret) {
clk_put(lcd_clk);
goto out;
}
ret = clk_set_rate(lcd_clk, 1000000 / pentry->cycle_time_ns); /* kHz */
if (ret) {
clk_disable(lcd_clk);
clk_put(lcd_clk);
goto out;
}
/*
* Make sure we do a high-to-low transition to reset the panel.
* First make it low for 100 msec, hi for 10 msec, low for 10 msec,
* then hi.
*/
__raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */
mdelay(100);
__raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */
mdelay(10);
__raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR); /* low */
/* For the Samsung, Reset must be held low at least 30 uSec
* Therefore, we'll hold it low for about 10 mSec just to be sure.
* Then we'll wait 1 mSec afterwards.
*/
mdelay(10);
__raw_writel(BM_LCDIF_CTRL1_RESET, REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET); /* high */
mdelay(1);
setup_dotclk_panel(DOTCLK_V_PULSE_WIDTH, DOTCLK_V_PERIOD,
DOTCLK_V_WAIT_CNT, DOTCLK_V_ACTIVE,
DOTCLK_H_PULSE_WIDTH, DOTCLK_H_PERIOD,
DOTCLK_H_WAIT_CNT, DOTCLK_H_ACTIVE, 0);
ret = mxs_lcdif_dma_init(dev, phys, memsize);
if (ret)
goto out;
// mxs_lcd_set_bl_pdata(pentry->bl_data);
mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_INIT, pentry);
return 0;
out:
return ret;
}
static void release_panel(struct device *dev,
struct mxs_platform_fb_entry *pentry)
{
mxs_lcdif_notify_clients(MXS_LCDIF_PANEL_RELEASE, pentry);
release_dotclk_panel();
mxs_lcdif_dma_release();
clk_disable(lcd_clk);
clk_put(lcd_clk);
}
static int blank_panel(int blank)
{
int ret = 0, count;
switch (blank) {
case FB_BLANK_NORMAL:
case FB_BLANK_VSYNC_SUSPEND:
case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_POWERDOWN:
__raw_writel(BM_LCDIF_CTRL_BYPASS_COUNT,
REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
for (count = 10000; count; count--) {
if (__raw_readl(REGS_LCDIF_BASE + HW_LCDIF_STAT) &
BM_LCDIF_STAT_TXFIFO_EMPTY)
break;
udelay(1);
}
break;
case FB_BLANK_UNBLANK:
__raw_writel(BM_LCDIF_CTRL_BYPASS_COUNT,
REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
break;
default:
ret = -EINVAL;
}
return ret;
}
static struct mxs_platform_fb_entry fb_entry = {
.name = "tm035kdh",
.x_res = 240, //480,
.y_res = 320, //800,
.bpp = 32,
.cycle_time_ns = 35, //35,
.lcd_type = MXS_LCD_PANEL_DOTCLK,
.init_panel = init_panel,
.release_panel = release_panel,
// .blank_panel = blank_panel,
.run_panel = mxs_lcdif_run,
.stop_panel = mxs_lcdif_stop,
.pan_display = mxs_lcdif_pan_display,
};
static const struct {
unsigned char addr;
unsigned char data;
} tftcluster_spi_init_seq[] = {
{0x00,0x07}, {0x01,0x00}, {0x02,0x03}, {0x03,0xCC}, {0x04,0x46}, {0x05,0x0D}, {0x06,0x00}, {0x07,0x00}, {0x08,0x08}, {0x09,0x40}, {0x0A,0x88}, {0x0B,0x88}, {0x0C,0x20}, {0x0D,0x20}, {0x0E,0x10}, {0x0F,0xA4}, {0x10,0x04}, {0x11,0x24}, {0x12,0x24}, {0x1E,0x00}, {0x20,0x00},
};
static int tftcluster_spi_send(struct spi_device *spi, unsigned char reg_addr,
unsigned char reg_data)
{
int ret = 0;
unsigned int cmd = 0, data = 0, data1 = 0;
cmd = 0x0000 | reg_addr; /* register address write */
data1 = 0x0000 | reg_data ; /* register data write */
data = (data1 << 8) | cmd;
// printk("\nAddr: %x Data: %x Write_Data: %x \n",cmd, data1, data);
ret = spi_write(spi, (unsigned char *)&data, 2);
if (ret)
pr_err("error in spi_write %x\n", data);
return ret;
}
static int tftcluster_spi_rcv(struct spi_device *spi, unsigned char reg_addr)
{
int ret = 0;
ret = spi_w8r8(spi, reg_addr);
// ret = spi_read(spi, (unsigned char *)&data, 2);
// spi_write_then_read(spi, (const void *)&data, 1,
// (void *)&ret, 1);
printk("Addr: %x Data: %x \n",reg_addr,ret);
// if (ret)
// pr_err("error in spi_read %x\n", reg_addr);
return ret;
}
static int __devexit lcd_spi_remove(struct spi_device *spi)
{
// lcd_spi = NULL;
return 0;
}
static int spi_init_tftcluster_lcd(struct spi_device *spi)
{
unsigned int i,ret=0;
unsigned char addr=0x00;
/* Initialization Sequence */
/* tftcluster_spi_send(spi, REG, VAL) */
for (i = 0; i <= (ARRAY_SIZE(tftcluster_spi_init_seq) - 1); i++)
tftcluster_spi_send(spi, tftcluster_spi_init_seq[i].addr,
tftcluster_spi_init_seq[i].data);
/* for (i = 0; i <= (ARRAY_SIZE(tftcluster_spi_init_seq) - 1); i++)
{
tftcluster_spi_rcv(spi, (addr+i));
}*/
// udelay(20);
// tftcluster_lcd_auto_power_off(lcd_spi);
return 0;
}
static int __devinit lcd_spi_probe(struct spi_device *spi)
{
printk("\n\n\nlcd_spi probe successfully\n\n\n");
spi->mode = SPI_3WIRE;
// spi->bits_per_word = 16; //32
spi_setup(spi);
spi_init_tftcluster_lcd(spi);
return 0;
}
static struct spi_driver lcd_spi_dev_driver = {
.driver = {
.name = "lcd_spi",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = lcd_spi_probe,
.remove = __devexit_p(lcd_spi_remove),
};
static int __init register_devices(void)
{
struct platform_device *pdev;
pdev = mxs_get_device("mxs-fb", 0);
if (pdev == NULL || IS_ERR(pdev))
{
printk("\n\n register device \n\n");
return -ENODEV;
}
mxs_lcd_register_entry(&fb_entry, pdev->dev.platform_data);
spi_register_driver(&lcd_spi_dev_driver);
return 0;
}
subsys_initcall(register_devices);
****************************************************
i shared the driver code and spi bus stuff in device file.
please check and let me know if there is any issues